Stream (四)之Collectors集合类常用方法

Stream (四)之Collectors集合类常用方法

package com.zy.stream.collect;

import com.zy.stream.model.Apple;
import com.zy.stream.model.Person;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream流中关于Collectors集合类中的相关方法,详解
 **/

public class StreamCollectTest {

 //实体类 
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
     class Apple {

        private String color;
        private Integer weight;


    }
  
    @Data
    @Builder(toBuilder = true)
    @AllArgsConstructor
    @NoArgsConstructor
     class Person {

        private String firstName, lastName, job, gender;
        private int salary,age;

    }


    List<Person> listPerson1= new ArrayList<Person>() {
        {
            add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
            add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
            add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25));
            add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
            add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25));
            add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 870));
            add(new Person("testMaude", null, "Java programmer", "female", 2057, 870));
            add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
            add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99));
            add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
            add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14));
            add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
        }
    };
    List<Person> listPerson2= new ArrayList<Person>() {
        {
            add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
            add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
            add(new Person("testFloyd", "Donny", "Java programmer", "male", 3322, 25));
            add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
            add(new Person("testVere", "Hervey", "Java programmer", "male", 2272, 25));
            add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
            add(new Person("testShawn", "Randall", "Java programmer", "male", 3120, 99));
            add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
            add(new Person("testPalmer", "Dene", "Java programmer", "male", 3375, 14));
            add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
        }
    };


    @Test
    public void testAll(){

        List<Integer> collect = listPerson1.stream().map(Person::getSalary).collect(Collectors.toList());


        //交集 (list1 + list2)
        System.out.println("test=======交集[firstName中不含有test] ========>:");
        listPerson1.stream()
                    .filter(listPerson2::contains)
                    .collect(Collectors.toList())
                    .forEach(System.out::println);

        //差集 取差集是注意以那个集合为主
        System.out.println("test=======listPerson2差集[firstName中含有test] ========>:");
        listPerson2.stream()
                    .filter(e-> !listPerson1.contains(e))
                    .collect(Collectors.toList())
                    .forEach(System.out::println);

        //并集
        System.out.println("test=======并集[两个集合的所有元素] ========>:");
        List<Person> collect1 = listPerson1.parallelStream().collect(Collectors.toList());
        collect1.addAll(listPerson2.parallelStream().collect(Collectors.toList()));
        collect1.stream().forEach(System.out::println);
        System.out.println("test=======并集[两个集合的所有元素] 去重========>:");
        collect1.stream().distinct().forEach(System.out::println);


        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple1",30);
        map.put("Apple2",20);
        map.put("Apple3",10);
        map.put("Apple6",51);
        map.put("Apple4",99);

        System.out.println("test=======Map集合转 List[注意数据类型]按照key值排序========>:");
        //Map集合转 List
        map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey()))
                .map(e -> new Apple(e.getKey(), e.getValue())).collect(Collectors.toList())
                .forEach(System.out::println);

        System.out.println("test=======Map集合转 List[注意数据类型]按照value值排序========>:");
        map.entrySet()
                .stream()
                .sorted(Comparator.comparing(Map.Entry::getValue)).map(e -> new Apple(e.getKey(), e.getValue()))
                .collect(Collectors.toList())
                .forEach(System.out::println);

        System.out.println("test=======Map集合转 List[注意数据类型]按照key值排序Entry.comparingByKey()========>:");
        map.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .map(e -> new Apple(e.getKey(), e.getValue()))
            .collect(Collectors.toList())
            .forEach(System.out::println);


        //toList()方法
        List<Integer> collectList = Stream.of(1, 2, 3, 4)
                .collect(Collectors.toList());
        System.out.println("test=======Collectors.toList()========》: " + collectList);



        HashMap<String, Object> objMap = new HashMap<>();
        //List转map集合    Collectors.toMap方法的第三个参数为键值重复处理策略,如果不传入第三个参数,当有相同的键时,会抛出一个IlleageStateException。
        System.out.println("test=======List元素对象转map集合[方式一]========>:");
        /*  toMap()参数一:key值,参数二:value值 参数三:当两个key值相同时,决定保留前一个value值还是后一个value值
             key为null    可以为null
            字典查询和数据转换 toMap时,如果value为null,会报空指针异常,需要校验
         */
        listPerson1.stream()
                .collect(Collectors.toMap(p -> p.getFirstName(), p -> Optional.ofNullable(p.getLastName()).orElse("value为null加非空检验"), (k1, k2) -> k1))
                .forEach(
                        (key, value) -> {
                        //map集合forEach()循环时传两个参数,key,value值,
                        System.out.println("key: " + key + "    value: " + value);
                }
        );

        /*下面这种形式,通过方法的引用也可以去取重复的key,保证不抛出异常,但是只能保证出现的第一个key的数据(Map::putAll)
            key为null    可以为null
            value为null,不会报空指针异常
         */
        System.out.println("test=======List元素对象转map集合[方式二]========>:");
        listPerson1.stream()
                    .collect(HashMap::new,(maps,p)->maps.put(p.getFirstName(),p.getLastName()),Map::putAll)
                    .forEach(
                        (key, value) -> {
                            //map集合forEach()循环时传两个参数,key,value值,
                            //如果value为null 打印:key: testMaude    value: null
                            System.out.println("++key: " + key + "    ++value: " + value);
                    }
        );
        System.out.println("test=======List元素对象转map集合[方式三]========>:");
        Stream<Apple> appleStream = Stream.of(new Apple("白色", 18),
                                            new Apple("红色", 180),
                                            new Apple("绿色", 187),
                                            new Apple("银色", 19));

        Map<String , Apple> appleMap = appleStream.collect(Collectors.toMap(Apple::getColor, i -> i));
        appleMap.forEach(
                (key, value) -> {
                    System.out.println("appleKey: " + key + "    appleValue: " + value);
                }
        );

        System.out.println("test========假设要得到按年龄分组的Map<Integer,List>:=======>:");
        Map<Integer, List<Person>> ageMap = listPerson1.stream().collect(Collectors.toMap(Person::getAge, Collections::singletonList, (a, b) -> {
            List<Person> resultList = new ArrayList<>(a);
            resultList.addAll(b);
            return resultList;
        }));
        ageMap.forEach(
                (key, value) -> {
                    System.out.println("ageKey: " + key + "   personValue: " + value);
                }
        );

        //List<String> 转String
        System.out.println("test========List<String> 转String使用Collectors.joining():=======>:");
        String str = Arrays.asList("voidcc.com", "voidmvn.com", "voidtool.com").stream().collect(Collectors.joining(","));
        System.out.println(str);

        //排序
        System.out.println("test=======排序sorted()========>:");
        //按照自然顺序进行排序 如果要自定义排序sorted 传入自定义的 Comparator
        listPerson1.stream().map(Person::getAge).sorted((x,y)->x.compareTo(y)).forEach(System.out::println);


        //比较
        System.out.println("test=======比较sorted()========>:");
        Comparator<Person> comparator = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());

        Person p1 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20);
        Person p2 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20);

        comparator.compare(p1, p2);             // > 0
        comparator.reversed().compare(p1, p2);  // < 0


        //分组
        System.out.println("test=======按照薪资分组Collectors.groupingBy()=====返回map===>:");
        listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary)).forEach(
                (key, value) -> {System.out.println("key: " + key + "    value: " + value);}
        );
        /*
         * groupingBy 分组后操作
                //Collectors中还提供了一些对分组后的元素进行downStream处理的方法:
                //counting方法返回所收集元素的总数;
                //summing方法会对元素求和;
                //maxBy和minBy会接受一个比较器,求最大值,最小值;
                //mapping函数会应用到downstream结果上,并需要和其他函数配合使用;
         */

        Map<Integer, Long> count = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.counting()));
        count.forEach((key, value) -> {System.out.println("counting方法返回所收集元素的总数:--->key: " + key + "    value: " + value);});

        Map<Integer, Integer> ageCount = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.summingInt(Person::getAge)));
        ageCount.forEach((key, value) -> {System.out.println("summing方法会对元素求和:--->key: " + key + "    value: " + value);});

        Map<Integer, Optional<Person>> ageMax =  listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.maxBy(Comparator.comparing(Person::getAge))));
        ageMax.forEach((key, value) -> {System.out.println("maxBy和minBy会接受一个比较器,求最大值,最小值:--->key: " + key + "    value: " + value);});

        Map<Integer, List<String>> nameMap =  listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.mapping(Person::getFirstName,Collectors.toList())));
        nameMap.forEach((key, value) -> {System.out.println("mapping函数会应用到downstream结果上,并需要和其他函数配合使用: " + key + "    value: " + value);});

        /*
         *1.    Collectors partitioningBy
         *      Collectors中还提供了partitioningBy方法,接受一个Predicate函数,该函数返回boolean值,用于将内容分为两组。
         *
         *2.    Collectors joining
         *      Collectors.joining 收集Stream中的值,该方法可以方便地将Stream得到一个字符串。joining函数接受三个参数,分别表示允(用以分隔元素)、前缀和后缀
         *
         *  Collectors分别提供了求平均值averaging、总数couting、最小值minBy、最大值maxBy、求和suming等操作。
         *  但是假如你希望将流中结果聚合为一个总和、平均值、最大值、最小值,
         *  那么Collectors.summarizing(Int/Long/Double)就是为你准备的,
         *  它可以一次行获取前面的所有结果,其返回值为(Int/Long/Double)SummaryStatistics。
         *
         *
         * 使用collect可以将Stream转换成值。maxBy和minBy允许用户按照某个特定的顺序生成一个值。
                averagingDouble:求平均值,Stream的元素类型为double
                averagingInt:求平均值,Stream的元素类型为int
                averagingLong:求平均值,Stream的元素类型为long
                counting:Stream的元素个数
                maxBy:在指定条件下的,Stream的最大元素
                minBy:在指定条件下的,Stream的最小元素
                reducing: reduce操作
                summarizingDouble:统计Stream的数据(double)状态,其中包括count,min,max,sum和平均。
                summarizingInt:统计Stream的数据(int)状态,其中包括count,min,max,sum和平均。
                summarizingLong:统计Stream的数据(long)状态,其中包括count,min,max,sum和平均。
                summingDouble:求和,Stream的元素类型为double
                summingInt:求和,Stream的元素类型为int
                summingLong:求和,Stream的元素类型为long
         *
         */


    }
}
原文地址:https://www.cnblogs.com/MrYuChen-Blog/p/14074488.html