国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java8特性③Stream的使用

Barry_Ng / 3354人閱讀

摘要:歸約把一個流中的元素組合起來,使用操作來表達更復雜的查詢,比如計算菜單中的總卡路里或菜單中卡路里最高的菜是哪一個。有沒有交易員是在深圳工作的打印生活在北京的交易員的所有交易額。

篩選和切片

filter 方法

distinct 方法

limit 方法

skip 方法

謂詞篩選

Stream 接口支持 filter 方法,該操作會接受一個謂詞(一個返回 boolean的函數(shù))作為參數(shù),并返回一個包括所有符合謂詞的元素的流。

List dishes = Dish.menu.stream()
      .filter(Dish::isVegetarian)
      .collect(Collectors.toList());
篩選重復的元素

Stream 接口支持 distinct 的方法, 它會返回一個元素各異(根據(jù)流所生成元素的 hashCode和equals方法實現(xiàn))的流。例如,以下代碼會篩選出列表中所有的偶數(shù),并確保沒有 重復。

List numbers = Arrays.asList(1,2,1,3,3,2,4);
numbers.stream().filter(i -> i % 2 == 0)
      .distinct() //去重元素2
      .forEach(System.out::println);
限制元素數(shù)量

Stream 支持limit(n)方法,該方法會返回一個不超過給定長度的流。所需的長度作為參數(shù)傳遞 給limit。如果流是有序的,則最多會返回前n個元素。

List dishLimits = Dish.menu.stream()
        .filter(d -> d.getCalories() > 300)
        .limit(3) //只返回符合要求的前3個元素
        .collect(Collectors.toList());
跳過指定數(shù)量的元素

Stream 支持 skip(n) 方法,返回一個扔掉了前n個元素的流。如果流中元素不足n個,則返回一 個空流。limit(n) 和 skip(n) 是互補的。

List dishSkip = Dish.menu.stream()
        .filter(d -> d.getCalories() > 300)
        .skip(2) //去掉符合要求的集合中的前2個元素后返回
        .collect(Collectors.toList());
dishSkip.forEach(System.out::println);
映射 map 操作

Stream 支持 map 方法,它會接受一個函數(shù)作為參數(shù)。這個函數(shù)會被應用到每個元素上,并將其映 射成一個新的元素

List dishNames = Dish.menu.stream()
      .map(Dish::getName)
      .map(String::length)
      .collect(Collectors.toList());
 
List words = Arrays.asList("Hello", "World");
List wordLens = words.stream()
      .map(String::length) //轉(zhuǎn)為字符串長度的集合
      .collect(Collectors.toList());
flatMap 操作

flatmap 方法讓你把一個流中的每個值都換成另一個流,然后把所有的流連接起來成為一個流。

//使用flatMap找出單詞列表中各不相同的字符
List words = Arrays.asList("Hello", "World");
List wordMap = words.stream()
      .map(word -> word.split(""))
      .flatMap(Arrays::stream)
      .distinct()
      .collect(Collectors.toList());

給定兩個數(shù)字列表,如何返回所有的數(shù)對呢?例如,給定列表[1, 2, 3]和列表[3, 4],應該返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]。

List num1 = Arrays.asList(1, 2, 3);
List num2 = Arrays.asList(4, 5);
List pairs = num1.stream()
        .flatMap(i -> num2.stream().map(j -> new int[]{i, j}))
        .collect(Collectors.toList());
pairs.stream().forEach( i -> {
    Arrays.stream(i).forEach(System.out::println);
查找和匹配 anyMatch

流中是否有一個元素能匹配給定的謂詞。

 if (Dish.menu.stream().anyMatch(Dish::isVegetarian)) {
     System.out.println("Vegetarion");
 }
allMatch

流中是否有所有元素能匹配給定的謂詞。

 if (Dish.menu.stream().allMatch(d -> d.getCalories() < 1000)) {

     System.out.println("都有利于健康");
 }
nonMatch

流中是否有沒有任何元素能匹配給定的謂詞。

 if (Dish.menu.stream().noneMatch(d -> d.getCalories() >= 1000)) {

     System.out.println("都有利于健康");
 }
findAny

findAny 方法將返回當前流中的任意一個元素。

 Optional dish = Dish.menu.stream().filter(Dish::isVegetarian)
         .findAny();
 dish.ifPresent(d -> System.out.println(d.toString()));
findFirst

findAny 方法將返回當前流中的第一個元素。

 List num1 = Arrays.asList(1, 2, 3, 4, 5);
 num1.stream().map(x -> x * x)
         .filter(x -> x % 3 == 0) //平方能被3整除的數(shù)
         .findFirst().ifPresent(x -> System.out.println(x));
      }
Optional

Optional類(java.util.Optional)是一個容器類,代表一個值存在或不存在。Optional里面y有幾種顯式地檢查值是否存在或處理值不存在的情形的方法:

isPresent()將在Optional包含值的時候返回true, 否則返回false。

ifPresent(Consumer block))會在值存在的時候執(zhí)行給定的代碼塊。

T get()會在值存在時返回值,否則拋出一個NoSuchElement異常。

T orElse(T other)會在值存在時返回值,否則返回一個默認值。

歸約(reduce)

把一個流中的元素組合起來,使用 reduce 操作來表達更復雜的查 詢,比如“計算菜單中的總卡路里”或“菜單中卡路里最高的菜是哪一個”。此類查詢需要將流中所有元素反復結(jié)合起來,得到一個值,比如一個Integer。這樣的查詢可以被歸類為歸約操作 (將流歸約成一個值)。

reduce操作是如何作用于一個流的:Lambda反復結(jié)合每個元素,直到流被歸約成一個值。reduce方法接受兩個參數(shù):一個初始值,這里是0;一個 BinaryOperator 來將兩個元素結(jié)合起來產(chǎn)生一個新值, 這里我們用的是 lambda (a, b) -> a + b

元素求和
List numbers = Arrays.asList(3,4,5,1,2);
int sum1 = numbers.stream().reduce(0,(a, b) -> a + b);
System.out.println(sum1);

int sum2 = numbers.stream().reduce(0,Integer::sum);
System.out.println(sum2);
最大值
int max = numbers.stream().reduce(0,Integer::max);
System.out.println(max);
最小值
//reduce不接受初始值,返回一個Optional對象(考慮流中沒有任何元素的情況)
Optional min = numbers.stream().reduce(Integer::min);
min.ifPresent(System.out::println);
數(shù)值流 原始類型流特化

Java 8引入了三個原始類型特化流接口來解決這個問題: IntStream 、 DoubleStream 和 LongStream,分別將流中的元素特化為int、long和double,從而避免了暗含的裝箱成本。每 個接口都帶來了進行常用數(shù)值歸約的新方法,比如對數(shù)值流求和的sum,找到最大元素的max。 此外還有在必要時再把它們轉(zhuǎn)換回對象流的方法。這些特化的原因并不在于流的復雜性,而是裝箱造成的復雜性——即類似int和Integer之間的效率差異。

映射到數(shù)值流:將流轉(zhuǎn)換為特化版本的常用方法是mapToInt、mapToDouble和mapToLong。這些方法和前 面說的map方法的工作方式一樣,只是它們返回的是一個特化流,而不是Stream

int colories = Dish.menu.stream()
        .mapToInt(Dish::getCalories) //返回IntStream
        .sum();

轉(zhuǎn)換回對象流

通過 box 方法可以將數(shù)值流轉(zhuǎn)化為 Stream 非特化流。

IntStream intStream = menu.stream().mapToInt(Dish::getCalories); //將Strean轉(zhuǎn)化為數(shù)值流
Stream stream = intStream.boxed(); //將數(shù)值流轉(zhuǎn)化為Stream

默認值 OptionalInt

Optional 可以用 Integer、String等參考類型來參數(shù)化。對于三種原始流特化,也分別有一個Optional原始類 型特化版本:OptionalInt、OptionalDouble和OptionalLong。

Dish.menu.stream()
        .mapToInt(Dish::getCalories) //返回IntStream
        .max().ifPresent(System.out::println);
數(shù)值范圍
IntStream.rangeClosed(1, 100)
        .filter(x -> x % 10 == 0)
        .forEach(System.out::println);

Java 8引入了兩個可以用于IntStream和LongStream的靜態(tài)方法,幫助生成這種范圍: range和rangeClosed。這兩個方法都是第一個參數(shù)接受起始值,第二個參數(shù)接受結(jié)束值。但 range是不包含結(jié)束值的,而rangeClosed則包含結(jié)束值。

數(shù)值流應用:勾股數(shù)

生成 (5, 12, 13)、(6, 8, 10)和(7, 24, 25) 這樣有效的勾股數(shù)數(shù)組集合。

Stream pythagoreanTriples = IntStream.rangeClosed(1, 100).boxed()
        .flatMap(a -> IntStream.rangeClosed(a,100)
                                .filter(b -> Math.sqrt(a * a + b * b) % 1 == 0).boxed()
                                .map(b -> new int[]{a,b,(int)Math.sqrt(a * a + b * b)})
        );
pythagoreanTriples.forEach(t -> System.out.println(t[0] + ";" + t[1] +";" + t[2]));
構(gòu)建流 值創(chuàng)建流
Stream streams = Stream.of("Java", "Python");
streams.map(String::toUpperCase).forEach(System.out::println);

Stream.concat(Stream.of("Java", "Python"), Stream.of("C++", "Ruby")).forEach(System.out::println);
數(shù)組創(chuàng)建流
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int sum = Arrays.stream(numbers).sum();
文件生成流
String ret = Files.lines(Paths.get("/Users/liuguoquan/Java/java8/src/com/company/data.txt"), Charset.defaultCharset())
        .reduce("", (a, b) -> a + " " + b);
函數(shù)生成流:創(chuàng)建無限流
//迭代
Stream.iterate(0, n -> n + 2)
        .limit(10)
        .forEach(System.out::println);

//生成
Stream.generate(Math::random)
        .limit(5)
        .forEach(System.out::println);

    }
示例實戰(zhàn)

假設你是執(zhí)行交易的交易員。你的經(jīng)理讓你為八個查詢找到答案。你能做到嗎?

(1) 找出2016年發(fā)生的所有交易,并按交易額排序(從低到高)。

(2) 交易員都在哪些不同的城市工作過?

(3) 查找所有來自于北京的交易員,并按姓名排序。

(4) 返回所有交易員的姓名字符串,按字母順序排序。

(5) 有沒有交易員是在深圳工作的?

(6) 打印生活在北京的交易員的所有交易額。

(7) 所有交易中,最高的交易額是多少?

(8) 找到交易額最小的交易。

交易員類

/**
 * 交易人
 * Created by liuguoquan on 2017/4/28.
 */
public class Trader {

    private String name;
    private String city;

    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Trader{" +
                "name="" + name + """ +
                ", city="" + city + """ +
                "}";
    }
}

交易類

/**
 * 交易單
 * Created by liuguoquan on 2017/4/28.
 */
public class Transaction {

    private Trader trader;
    private int year;
    private int value;

    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader() {
        return trader;
    }

    public void setTrader(Trader trader) {
        this.trader = trader;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Transaction{" +
                "trader=" + trader +
                ", year="" + year + """ +
                ", value=" + value +
                "}";
    }
}

計算

public class TransactionProcess {

    public static void main(String[] args) {

        Trader liu = new Trader("Lau","Beijing");
        Trader lee = new Trader("Lee","Shanghai");
        Trader zhang = new Trader("Zhang","Guangzhou");
        Trader wang = new Trader("Wang","Beijing");

        List transactions = Arrays.asList(
                new Transaction(liu,2016,300),
                new Transaction(lee,2015,100),
                new Transaction(lee,2016,500),
                new Transaction(zhang,2016,9000),
                new Transaction(wang,2017,1000),
                new Transaction(liu,2016,1500)
        );

        // (1) 找出2016年發(fā)生的所有交易,并按交易額排序(從低到高)。
        transactions.stream().filter(t -> t.getYear() == 2016)
                .sorted(Comparator.comparing(Transaction::getValue))
                .collect(Collectors.toList());

        // (2) 交易員都在哪些不同的城市工作過?
        transactions.stream().map(t -> t.getTrader().getCity())
                .distinct()
                .collect(Collectors.toList());

        // (3) 查找所有來自于北京的交易員,并按姓名排序。
        transactions.stream().map(t -> t.getTrader())
                .filter(t -> t.getCity().equals("Beijing"))
                .distinct()
                .sorted(Comparator.comparing(Trader::getName))
                .collect(Collectors.toList());

        // (4) 返回所有交易員的姓名字符串,按字母順序排序。
        transactions.stream().map(t -> t.getTrader())
                .map(t -> t.getName())
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        // (5) 有沒有交易員是在深圳工作的?
        boolean isExist = transactions.stream().anyMatch(t -> t.getTrader().getCity().equals("Shenzhen"));
        if (isExist) {
            System.out.println("有在深圳工作的");
        } else {
            System.out.println("沒有在深圳工作的");
        }

        // (6) 打印生活在北京的交易員的所有交易額。
        int sum = transactions.stream().filter(t -> t.getTrader().getCity().equals("Beijing"))
                .map(t -> t.getValue())
                .reduce(0,Integer::sum);
        System.out.println(sum);

        // (7) 所有交易中,最高的交易額是多少?
        int max = transactions.stream().map(t -> t.getValue())
                .reduce(0,Integer::max);
        System.out.println(max);

        // (8) 找到交易額最小的交易。
        int min = transactions.stream().map(t -> t.getValue())
                .reduce(0,Integer::min);
        System.out.println(min);
    }
}
小結(jié)

中間操作表

操作 類型 返回類型 目的
filter 中間操作 Stream 過濾元素
distinct 中間操作 Stream 過濾重復的元素
skip 中間操作 Stream 跳過指定數(shù)量的元素
limit 中間操作 Stream 限制元素的數(shù)量
map 中間操作 Stream 流的轉(zhuǎn)化
flatmap 中間操作 Stream 流的扁平化
sorted 中間操作 Stream 元素排序

終端操作表

操作 類型 返回類型 目的
forEach 終端操作 void 消費流中的每個元素,返回void
count 終端操作 long 返回流中元素的個數(shù),返回long
collect 終端操作 R 把流歸約為一個集合
anyMatch 終端操作 boolean 流中是否有符合要求的元素
noneMatch 終端操作 boolean 流中是否沒有任何符合要求的元素
allMatch 終端操作 boolean 流中是否所有元素都是符合要求的
findAny 終端操作 Optional 查找符合要求的元素
findFirst 終端操作 Optional 查找第一個符合要求的元素
reduce 終端操作 Optional 歸約

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69975.html

相關(guān)文章

  • Java8 之 lambda 表達式、方法引用、函數(shù)式接口、默認方式、靜態(tài)方法

    摘要:歐陽思海繼承接口后,又加了新的抽象方法,這個接口就不再是函數(shù)式接口默認方法在接口中添加了一個默認方法。總結(jié)在這篇文章中,我們講了表達式方法引用函數(shù)式接口接口中的靜態(tài)方法接口中的默認方法的使用。 今天我來聊聊 Java8 的一些新的特性,確實 Java8 的新特性的出現(xiàn),給開發(fā)者帶來了非常大的便利,可能剛剛開始的時候會有點不習慣的這種寫法,但是,當你真正的熟悉了之后,你一定會愛上這些新的...

    isLishude 評論0 收藏0
  • Java8-流

    摘要:因此,使用并行流需要考慮以下幾點數(shù)據(jù)量將問題分解之后并行化處理,再將結(jié)果合并會帶來額外的開銷。 目錄 簡介 用法 例子 注意點 一. 簡介 流是Java8引入的一個新特性,提供了對集合元素一系列便捷的操作,可以用很少的代碼實現(xiàn)復雜的功能。流有兩大類,分別是對象流(Stream),基本數(shù)據(jù)流(IntStream、LongStream、DoubleStream)。 二.用法 流的使用通...

    whinc 評論0 收藏0
  • Java8之Consumer、Supplier、Predicate和Function攻略

    摘要:接口有一個方法,可以返回值。在上面的代碼中,就是獲取字符串的長度,然后將每個字符串的長度作為返回值返回。 今天我們還講講Consumer、Supplier、Predicate、Function這幾個接口的用法,在 Java8 的用法當中,這幾個接口雖然沒有明目張膽的使用,但是,卻是潤物細無聲的。為什么這么說呢? 這幾個接口都在 java.util.function 包下的,分別是Con...

    pepperwang 評論0 收藏0
  • 在Android項目中使用Java8

    摘要:現(xiàn)在爸爸終于讓平臺支持了,這篇文章中便來和大家聊聊如何在項目中配置使用。要想在項目中使用的新特性,需要將你的升級到及以上版本,并采用新的編譯。 轉(zhuǎn)載請注明出處:https://zhuanlan.zhihu.com/p/23279894 前言 在過去的文章中我介紹過Java8的一些新特性,包括: Java8新特性第1章(Lambda表達式) Java8新特性第2章(接口默認方法) J...

    junnplus 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<