Stream API

一秆剪、了解Stream

Java8中有兩大最為重要的改變赊淑。第一個是Lambda表達式;另外一個則是Stream API(java.util.stream.*)仅讽。

Stream是Java8中處理集合的關(guān)鍵抽象概念陶缺,它可以指定你希望對集合進行的操作,可以執(zhí)行非常復(fù)雜的查找洁灵、過濾和映射數(shù)據(jù)等操作饱岸。

使用Stream API對集合數(shù)據(jù)進行操作,就類似于使用sql執(zhí)行的數(shù)據(jù)庫查詢徽千。也可以使用Stream API來并行執(zhí)行操作苫费。簡而言之,Stream API提供了一種高效且易于使用的處理數(shù)據(jù)的方式罐栈。

二黍衙、什么是Stream

流(Stream)到底是什么呢?

是數(shù)據(jù)渠道荠诬,用于操作數(shù)據(jù)源(集合琅翻、數(shù)組等)所生成的元素序列。

“集合講的是數(shù)據(jù)柑贞,流講的是計算方椎!”。

注意:

(1)钧嘶、Stream自己不會存儲元素棠众。

(2)、Stream不會改變源對象有决。相反闸拿,他們會返回一個持有結(jié)果的新Stream。

(3)书幕、Stream操作是延遲執(zhí)行的新荤。這意味著他們會等到需要結(jié)果的時候才執(zhí)行。

三台汇、Stream的操作三個步驟

(1)苛骨、創(chuàng)建Stream

一個數(shù)據(jù)源(如:集合篱瞎、數(shù)組),獲取一個流

(2)痒芝、中間操作

一個中間操作鏈俐筋,對數(shù)據(jù)源的數(shù)據(jù)進行處理

(3)、終止操作(終端操作)

一個終止操作严衬,執(zhí)行中間操作鏈澄者,并產(chǎn)生結(jié)果。

四瞳步、創(chuàng)建Stream

在創(chuàng)建Stream前闷哆,我先來創(chuàng)建一個對象,供下面使用单起。Employee.java

package com.nieshenkuan.pojo;

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    public Employee(String name) {
        this.name = name;
    }
    public Employee(Integer id) {
        this.id = id;
    }
    public Employee(Integer id,Integer age) {
        this.id = id;
        this.age = age;
    }

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String show() {
        return "測試方法引用抱怔!";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(salary);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (age != other.age)
            return false;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
    }

}

創(chuàng)建一個測試類StreamAPI.java,,并創(chuàng)建一個test方法嘀倒。所有的創(chuàng)建Stream的方式都在這個類的test方法中。

@Test
    public void test() {
        
    }
4.1测蘑、可以通過Collection系列集合提供的stream()或parallelStream()

創(chuàng)建代碼:

// 1.1可以通過Collection系列集合提供的stream()或parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
4.2灌危、通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流

創(chuàng)建代碼:

// 1.2通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流
        Employee[] emps = new Employee[10];
        Stream<Employee> stream2 = Arrays.stream(emps);
4.3、通過Stream類中的靜態(tài)方法of()

創(chuàng)建代碼:

// 1.3通過Stream類中的靜態(tài)方法of()
        Stream<String> stream3 = Stream.of("aa", "bb", "cc");
        stream3.forEach(System.out::println);
4.4碳胳、創(chuàng)建無限流
4.4.1勇蝙、迭代

創(chuàng)建代碼:

// 1.4.1、迭代
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        stream4.limit(10)
               .forEach(System.out::println);
4.4.2挨约、生成

創(chuàng)建代碼:

// 1.4.2味混、生成
        Stream.generate(() -> Math.random()).limit(5)
                                         .forEach(System.out::println);

注意:

常用的是第一種跟第二種,這里面獲取的都是串行流(利用Stream)诫惭,還有一種就是并行流翁锡,其獲取方式是parallelStream。

五夕土、中間操作

在中間操作前馆衔,我們先在StreamAPI.java中新創(chuàng)建一個Employee對象的集合,然后每一個中間操作怨绣,我這里都寫了一個測試類角溃。

創(chuàng)建的Employee集合對象如下:

// 2. 中間操作
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66), 
            new Employee(101, "張三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33), 
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(104, "趙六", 8, 7777.77), 
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
            );

下面的中間操作會用到這個集合。

5.1篮撑、篩選與切片
5.1.1开镣、filter——接收 Lambda , 從流中排除某些元素咽扇。

測試代碼:

// (1)邪财、filter——接收 Lambda , 從流中排除某些元素质欲。
    @Test
    public void testFilter() {
        //這里加入了終止操作 树埠,不然中間操作一系列不會執(zhí)行
        //中間操作只有在碰到終止操作才會執(zhí)行
        emps.stream()
        .filter((e)->e.getAge()>18)
        .forEach(System.out::println);//終止操作
        
    }

注意:這里filter主要是過濾一些條件,這里的話就是把年齡小于18歲的Employee對象給過濾掉嘶伟,然后用forEach給遍歷一下怎憋,因為中間操作只有碰到終止操作才會執(zhí)行,不然的話九昧,看不到過濾效果绊袋。以下的操作都大部分都forEach了一下,為方便看到效果铸鹰。filter用的還是很多的癌别。

5.1.2、limit——截斷流蹋笼,使其元素不超過給定數(shù)量展姐。

測試代碼:

// (2)、limit——截斷流剖毯,使其元素不超過給定數(shù)量圾笨。
    @Test
    public void testLimit() {
    emps.stream()
        .filter((e)->e.getAge()>8)
        .limit(4)//跟數(shù)據(jù)庫中的limit有異曲同工之妙
        .forEach(System.out::println);//終止操作

    }

注意:這里我利用了上面的filter跟limit,代碼意思是:過濾掉年齡小于8的逊谋,只要4條數(shù)據(jù)擂达。這種"."式操作很有意思,就是中間操作都可以一直".",直到得到你想要的要求胶滋。

5.1.3板鬓、 skip(n) ——跳過元素,返回一個扔掉了前 n 個元素的流镀钓。若流中元素不足 n 個穗熬,則返回一個空流。與 limit(n) 互補

測試代碼:

// (3)丁溅、skip(n) —— 跳過元素唤蔗,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個窟赏,則返回一個空流垂蜗。與 limit(n) 互補
    @Test
    public void testSkip() {
    emps.stream()
        .filter((e)->e.getAge()>8)
        .skip(2)//這里可以查找filter過濾后的數(shù)據(jù)俩块,前兩個不要,要后面的,與limit相反
        .forEach(System.out::println);//終止操作
    }

注意:這里同樣使用了filter中間操作票唆,也可以不用,代碼意思是:過濾掉年齡小于8歲的employee對象肌稻,然后前兩個對象不要,只要后面的對象掘殴。跟limit意思相反。

5.1.4粟誓、distinct——篩選奏寨,通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素

測試代碼:

// (4)、distinct——篩選鹰服,通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素
    @Test
    public void testDistinct() {
    emps.stream()
        .distinct()//去除重復(fù)的元素病瞳,因為通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素,所以對象要重寫hashCode跟equals方法
        .forEach(System.out::println);//終止操作
    }

注意:distinct悲酷,去除重復(fù)的元素套菜,因為通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素,所以對象要重寫hashCode跟equals方法设易,我在Employee對象中重寫了這兩個方法逗柴。

5.2、映射
5.2.1亡嫌、map-接收Lambda嚎于,將元素轉(zhuǎn)換成其他形式或提取信息。接收一個函數(shù)作為參數(shù)挟冠,該函數(shù)會被應(yīng)用到每個元素上于购,并將其映射成一個新的元素。
5.2.2知染、flatMap-接收一個函數(shù)作為參數(shù)肋僧,將流中的每個值都轉(zhuǎn)換成另一個流,然后把所有流連接成一個流

測試代碼:

//  map-接收Lambda控淡,將元素轉(zhuǎn)換成其他形式或提取信息嫌吠。接收一個函數(shù)作為參數(shù),該函數(shù)會被應(yīng)用到每個元素上掺炭,并將其映射成一個新的元素辫诅。
    @Test
    public void testMapAndflatMap() {
        List<String> list=Arrays.asList("aaa","bbb","ccc","ddd");
        list.stream()
        .map((str)->str.toUpperCase())//里面是Function
        .forEach(System.out::println);
        
        System.out.println("----------------------------------");
        //這里是只打印名字,map映射涧狮,根據(jù)Employee::getName返回一個name炕矮,映射成新的及結(jié)果name
        emps.stream()
        .map(Employee::getName)
        .forEach(System.out::println);
        
        System.out.println("======================================");
        
        //流中流
        Stream<Stream<Character>> stream = list.stream()
        .map(StreamAPI::filterCharacter);
        //{{a,a,a},{b,b,b}}
        //map是一個個流(這個流中有元素)加入流中
        
        stream.forEach(sm->{
            sm.forEach(System.out::println);
        });
        
        System.out.println("=============引進flatMap=============");
//      只有一個流
        Stream<Character> flatMap = list.stream()
        .flatMap(StreamAPI::filterCharacter);
        //flatMap是將一個個流中的元素加入流中
        //{a,a,a,b,b,b}
        flatMap.forEach(System.out::println);
        
    }
    /**
     * 測試map跟flatMap的區(qū)別
     * 有點跟集合中的add跟addAll方法類似
     * add是將無論是元素還是集合,整體加到其中一個集合中去[1,2,3.[2,3]]
     * addAll是將無論是元素還是集合者冤,都是將元素加到另一個集合中去肤视。[1,2,3,2,3]
     * @param str
     * @return
     */
    public static Stream<Character> filterCharacter(String str){
        List<Character> list=new ArrayList<>();
        for (Character character : str.toCharArray()) {
            list.add(character);
        }
        return list.stream();
    }

注意:map跟flatMap還是有區(qū)別的,map是一個個流(這個流中有元素)加入流中涉枫,flatMap是將一個個流中的元素加入流中邢滑。

5.3、排序
5.3.1愿汰、sorted()---自然排序(Comparable)
5.3.2困后、sorted(Comparator com)----定制排序(Comparator)

測試代碼:

@Test
    public  void  testSorted() {
        List<String> list=Arrays.asList("ccc","aaa","bbb","ddd","eee");
        list.stream()
        .sorted()
        .forEach(System.out::println);
        
        System.out.println("=======定制排序=========");
        
        emps.stream()
        .sorted((x, y) -> {
            if(x.getAge() == y.getAge()){
                return x.getName().compareTo(y.getName());
            }else{
                return Integer.compare(x.getAge(), y.getAge());
            }
        }).forEach(System.out::println);
    }

六乐纸、終止操作

終端操作會從流的流水線生成結(jié)果。其結(jié)果可以是任何不是流的值操灿,例如:List锯仪,Integer,甚至是void趾盐。

在學習終止操作前,我又新建了一個Employee類小腊,如下:Employee2.java

package com.nieshenkuan.pojo;


/**
 * 用來測試終止操作
 * @author NSK
 *
 */
public class Employee2 {

    private int id;
    private String name;
    private int age;
    private double salary;
    private Status status;

    public Employee2() {
    }

    public Employee2(String name) {
        this.name = name;
    }

    public Employee2(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Employee2(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Employee2(int id, String name, int age, double salary, Status status) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String show() {
        return "測試方法引用救鲤!";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(salary);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee2 other = (Employee2) obj;
        if (age != other.age)
            return false;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Employee2 [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
                + "]";
    }

    public enum Status {
        FREE, BUSY, VOCATION;
    }

}

然后創(chuàng)建了一個測試終止操作的類,TestShutdown.java

public class TestShutdown {
    List<Employee2> emps = Arrays.asList(
            new Employee2(102, "李四", 59, 6666.66, Status.BUSY),
            new Employee2(101, "張三", 18, 9999.99, Status.FREE),
            new Employee2(103, "王五", 28, 3333.33, Status.VOCATION),
            new Employee2(104, "趙六", 8, 7777.77, Status.BUSY),
            new Employee2(104, "趙六", 8, 7777.77, Status.FREE),
            new Employee2(104, "趙六", 8, 7777.77, Status.FREE),
            new Employee2(105, "田七", 38, 5555.55, Status.BUSY)
    );
    }

里面定義了我下面要使用的employee的集合秩冈。

6.1本缠、查找與匹配
6.1.1、allMatch——檢查是否匹配所有元素

測試代碼片段入问,下面有總的代碼:

System.out.println("==========allMatch==============");
        boolean allMatch = emps.stream()
                               .allMatch((e)->e.getStatus().equals(Status.BUSY));
        System.out.println(allMatch);
6.1.2丹锹、anyMatch——檢查是否至少匹配一個元素

測試代碼片段:

System.out.println("==========anyMatch==============");
        boolean anyMatch = emps.stream()
                               .anyMatch((e)->e.getAge()>10);
        System.out.println(anyMatch);
6.1.3、noneMatch——檢查是否沒有匹配的元素

測試代碼片段:

    System.out.println("==========noneMatch==============");
        boolean noneMatch = emps.stream()
                                .noneMatch((e)->e.getStatus().equals(Status.BUSY));
        System.out.println(noneMatch);
6.1.4芬失、findFirst——返回第一個元素

測試代碼片段:

System.out.println("==========findFirst==============");
        Optional<Employee2> findFirst = emps.stream()
                                            .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))//按照工資排序并輸出第一個
                                            .findFirst();       
        System.out.println(findFirst);
6.1.5楣黍、findAny——返回當前流中的任意元素

測試代碼片段:

System.out.println("==========findAny==============");
        Optional<Employee2> findAny = emps.stream()
            .filter((e)->e.getStatus().equals(Status.BUSY))
            .findAny();
        System.out.println(findAny);
6.1.6、count——返回流中元素的總個數(shù)

測試代碼片段:

System.out.println("==========count==============");
        long count = emps.stream()
            .count();
        System.out.println(count);
6.1.7棱烂、max——返回流中最大值

測試代碼片段:

System.out.println("==========max==============");
        Optional<Double> max = emps.stream()
            .map(Employee2::getSalary)
            .max(Double::compare);
        System.out.println(max);
6.1.8租漂、min——返回流中最小值

測試代碼片段:


        System.out.println("==========min==============");
        Optional<Employee2> min = emps.stream()
                                      .min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min);

總的測試代碼:

    //3. 終止操作
    /*查找與匹配
        allMatch——檢查是否匹配所有元素
        anyMatch——檢查是否至少匹配一個元素
        noneMatch——檢查是否沒有匹配的元素
        findFirst——返回第一個元素
        findAny——返回當前流中的任意元素
        count——返回流中元素的總個數(shù)
        max——返回流中最大值
        min——返回流中最小值
     */
    @Test
    public void test() {
//      emps.stream():獲取串行流
//      emps.parallelStream():獲取并行流
        System.out.println("==========allMatch==============");
        boolean allMatch = emps.stream()
                               .allMatch((e)->e.getStatus().equals(Status.BUSY));
        System.out.println(allMatch);
        
        System.out.println("==========anyMatch==============");
        boolean anyMatch = emps.stream()
                               .anyMatch((e)->e.getAge()>10);
        System.out.println(anyMatch);
        
        System.out.println("==========noneMatch==============");
        boolean noneMatch = emps.stream()
                                .noneMatch((e)->e.getStatus().equals(Status.BUSY));
        System.out.println(noneMatch);
        
        
        System.out.println("==========findFirst==============");
        Optional<Employee2> findFirst = emps.stream()
                                            .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))//按照工資排序并輸出第一個
                                            .findFirst();       
        System.out.println(findFirst);
        
        
        System.out.println("==========findAny==============");
        Optional<Employee2> findAny = emps.stream()
            .filter((e)->e.getStatus().equals(Status.BUSY))
            .findAny();
        System.out.println(findAny);
        
        System.out.println("==========count==============");
        long count = emps.stream()
            .count();
        System.out.println(count);
        
        
        System.out.println("==========max==============");
        Optional<Double> max = emps.stream()
            .map(Employee2::getSalary)
            .max(Double::compare);
        System.out.println(max);
        
        System.out.println("==========min==============");
        Optional<Employee2> min = emps.stream()
                                      .min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min);
        
            
    }
6.2、歸約
6.2.1颊糜、reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以將流中元素反復(fù)結(jié)合起來哩治,得到一個值。

測試代碼:

@Test
    public void testReduce() {
        List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream()
            .reduce(0,(x,y)->x+y);
        System.out.println(sum);
        
        Optional<Double> reduce = emps.stream()
            .map(Employee2::getSalary)
            .reduce(Double::sum);
        System.out.println(reduce.get());
        
    }
6.3衬鱼、收集

Collector接口中方法的實現(xiàn)決定了如何對流執(zhí)行收集操作(如收集到List业筏、Set、Map)鸟赫。但是Collectors實用類提供了很多靜態(tài)方法蒜胖,可以方便地創(chuàng)建常見收集器實例,具體方法與實例如下表:

6.3.1惯疙、Collectors.toList()

測試代碼片段:

List<String> collect = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toList());
        collect.forEach(System.out::println);
6.3.2翠勉、Collectors.toSet()

測試代碼片段:


        Set<String> collect2 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toSet());
        collect2.forEach(System.out::println);
6.3.3、Collectors.toCollection(HashSet::new)

測試代碼片段:

HashSet<String> collect3 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toCollection(HashSet::new));
        collect3.forEach(System.out::println);
6.3.4霉颠、Collectors.maxBy()

測試代碼片段:


        
Optional<Double> collect = emps.stream()
            .map(Employee2::getSalary)
            .collect(Collectors.maxBy(Double::compare));
        System.out.println(collect.get());
        
        
        
        Optional<Employee2> collect2 = emps.stream()
            .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(collect2.get());
6.3.5对碌、Collectors.minBy()

測試代碼片段:

Optional<Double> collect4 = emps.stream()
        .map(Employee2::getSalary)
        .collect(Collectors.minBy(Double::compare));
        System.out.println(collect4);
        
        
        Optional<Employee2> collect3 = emps.stream()
        .collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
        System.out.println(collect3.get());
6.3.6、Collectors.summingDouble()

測試代碼片段:

Double collect5 = emps.stream()
        .collect(Collectors.summingDouble(Employee2::getSalary));
    System.out.println(collect5);
6.3.7蒿偎、Collectors.averagingDouble()

測試代碼片段:

Double collect6 = emps.stream()
    .collect(Collectors.averagingDouble((e)->e.getSalary()));
    
    Double collect7 = emps.stream()
    .collect(Collectors.averagingDouble(Employee2::getSalary));
    
    System.out.println("collect6:"+collect6);
    System.out.println("collect7:"+collect7);
6.3.8朽们、Collectors.counting()

測試代碼片段:

//總數(shù)
    Long collect8 = emps.stream()
                       .collect(Collectors.counting());
    System.out.println(collect8);
6.3.9怀读、Collectors.summarizingDouble()

測試代碼片段:

DoubleSummaryStatistics collect9 = emps.stream()
        .collect(Collectors.summarizingDouble(Employee2::getSalary));
    long count = collect9.getCount();
    double average = collect9.getAverage();
    double max = collect9.getMax();
    double min = collect9.getMin();
    double sum = collect9.getSum();
    System.out.println("count:"+count);
    System.out.println("average:"+average);
    System.out.println("max:"+max);
    System.out.println("min:"+min);
    System.out.println("sum:"+sum);
6.3.10、分組Collectors.groupingBy()

測試代碼片段:

//分組
    @Test
    public void testCollect3() {
        Map<Status, List<Employee2>> collect = emps.stream()
        .collect(Collectors.groupingBy((e)->e.getStatus()));
        System.out.println(collect);
        
        
        Map<Status, List<Employee2>> collect2 = emps.stream()
            .collect(Collectors.groupingBy(Employee2::getStatus));
        System.out.println(collect2);
    }
6.3.11骑脱、多級分組Collectors.groupingBy()

測試代碼片段:

//多級分組
    @Test
    public void testCollect4() {
        Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
            .collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
                if(e.getAge() >= 60)
                    return "老年";
                else if(e.getAge() >= 35)
                    return "中年";
                else
                    return "成年";
            })));
        System.out.println(collect);
    }
6.3.12菜枷、分區(qū)Collectors.partitioningBy()

測試代碼片段:

//多級分組
    @Test
    public void testCollect4() {
        Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
            .collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
                if(e.getAge() >= 60)
                    return "老年";
                else if(e.getAge() >= 35)
                    return "中年";
                else
                    return "成年";
            })));
        System.out.println(collect);
    }
6.3.13、組接字符串Collectors.joining()

測試代碼片段:

//組接字符串
    @Test
    public void testCollect6() {
        String collect = emps.stream()
        .map((e)->e.getName())
        .collect(Collectors.joining());
        System.out.println(collect);
        
        String collect3 = emps.stream()
        .map(Employee2::getName)
        .collect(Collectors.joining(","));
        System.out.println(collect3);
        
        
        String collect2 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.joining(",", "prefix", "subfix"));
        System.out.println(collect2);
        
        
    }
    @Test
    public void testCollect7() {
        Optional<Double> collect = emps.stream()
        .map(Employee2::getSalary)
        .collect(Collectors.reducing(Double::sum));
        System.out.println(collect.get());
    }

測試代碼片段:

    /**
     * collect——將流轉(zhuǎn)換為其他形式叁丧。接收一個 Collector接口的實現(xiàn)啤誊,用于給Stream中元素做匯總的方法
     */
    @Test
    public void testCollect() {
        
        List<String> collect = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toList());
        collect.forEach(System.out::println);
        
        
        Set<String> collect2 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toSet());
        collect2.forEach(System.out::println);
        
        HashSet<String> collect3 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.toCollection(HashSet::new));
        collect3.forEach(System.out::println);
    }
    
    @Test
    public void testCollect2() {
        Optional<Double> collect = emps.stream()
            .map(Employee2::getSalary)
            .collect(Collectors.maxBy(Double::compare));
        System.out.println(collect.get());
        
        
        
        Optional<Employee2> collect2 = emps.stream()
            .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(collect2.get());
        
        
        Optional<Double> collect4 = emps.stream()
        .map(Employee2::getSalary)
        .collect(Collectors.minBy(Double::compare));
        System.out.println(collect4);
        
        
        Optional<Employee2> collect3 = emps.stream()
        .collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
        System.out.println(collect3.get());
        
        
    System.out.println("=========================================");
    
    Double collect5 = emps.stream()
        .collect(Collectors.summingDouble(Employee2::getSalary));
    System.out.println(collect5);
    
    
    Double collect6 = emps.stream()
    .collect(Collectors.averagingDouble((e)->e.getSalary()));
    Double collect7 = emps.stream()
    .collect(Collectors.averagingDouble(Employee2::getSalary));
    
    System.out.println("collect6:"+collect6);
    System.out.println("collect7:"+collect7);
    
    
    //總數(shù)
    Long collect8 = emps.stream()
    .collect(Collectors.counting());
    System.out.println(collect8);
    
    
    
    DoubleSummaryStatistics collect9 = emps.stream()
        .collect(Collectors.summarizingDouble(Employee2::getSalary));
    long count = collect9.getCount();
    double average = collect9.getAverage();
    double max = collect9.getMax();
    double min = collect9.getMin();
    double sum = collect9.getSum();
    System.out.println("count:"+count);
    System.out.println("average:"+average);
    System.out.println("max:"+max);
    System.out.println("min:"+min);
    System.out.println("sum:"+sum);
    }
    
    //分組
    @Test
    public void testCollect3() {
        Map<Status, List<Employee2>> collect = emps.stream()
        .collect(Collectors.groupingBy((e)->e.getStatus()));
        System.out.println(collect);
        
        
        Map<Status, List<Employee2>> collect2 = emps.stream()
            .collect(Collectors.groupingBy(Employee2::getStatus));
        System.out.println(collect2);
    }
    //多級分組
    @Test
    public void testCollect4() {
        Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
            .collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
                if(e.getAge() >= 60)
                    return "老年";
                else if(e.getAge() >= 35)
                    return "中年";
                else
                    return "成年";
            })));
        System.out.println(collect);
    }
    //分區(qū)
    @Test
    public void testCollect5() {
        Map<Boolean, List<Employee2>> collect = emps.stream()
        .collect(Collectors.partitioningBy((e)->e.getSalary()>5000));
        System.out.println(collect);
    }
    //組接字符串
    @Test
    public void testCollect6() {
        String collect = emps.stream()
        .map((e)->e.getName())
        .collect(Collectors.joining());
        System.out.println(collect);
        
        String collect3 = emps.stream()
        .map(Employee2::getName)
        .collect(Collectors.joining(","));
        System.out.println(collect3);
        
        
        String collect2 = emps.stream()
            .map(Employee2::getName)
            .collect(Collectors.joining(",", "prefix", "subfix"));
        System.out.println(collect2);
        
        
    }
    @Test
    public void testCollect7() {
        Optional<Double> collect = emps.stream()
        .map(Employee2::getSalary)
        .collect(Collectors.reducing(Double::sum));
        System.out.println(collect.get());
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拥娄,隨后出現(xiàn)的幾起案子蚊锹,更是在濱河造成了極大的恐慌,老刑警劉巖稚瘾,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牡昆,死亡現(xiàn)場離奇詭異,居然都是意外死亡摊欠,警方通過查閱死者的電腦和手機丢烘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來些椒,“玉大人播瞳,你說我怎么就攤上這事√粒” “怎么了狐史?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長说墨。 經(jīng)常有香客問我骏全,道長,這世上最難降的妖魔是什么尼斧? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任姜贡,我火速辦了婚禮,結(jié)果婚禮上棺棵,老公的妹妹穿的比我還像新娘楼咳。我一直安慰自己,他們只是感情好烛恤,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布母怜。 她就那樣靜靜地躺著,像睡著了一般缚柏。 火紅的嫁衣襯著肌膚如雪苹熏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音轨域,去河邊找鬼袱耽。 笑死,一個胖子當著我的面吹牛干发,可吹牛的內(nèi)容都是我干的朱巨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枉长,長吁一口氣:“原來是場噩夢啊……” “哼冀续!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起必峰,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤沥阳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后自点,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡脉让,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年桂敛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溅潜。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡术唬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滚澜,到底是詐尸還是另有隱情粗仓,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布设捐,位于F島的核電站借浊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萝招。R本人自食惡果不足惜蚂斤,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望槐沼。 院中可真熱鬧曙蒸,春花似錦、人聲如沸岗钩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兼吓。三九已至臂港,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背趋艘。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工疲恢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓷胧。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓显拳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搓萧。 傳聞我的和親對象是個殘疾皇子杂数,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容