Collectors简单使用

Collectors

Collectors类API

1. public static > Collector toCollection(Supplier collectionFactory);
    
2. public static  Collector> toList();
3. public static  Collector> toSet();
    
4. public static  Collector> toMap(Function keyMapper,
                                    Function valueMapper) ;
5. public static  Collector> toMap(
                                    Function keyMapper,
                                    Function valueMapper,
                                    BinaryOperator mergeFunction);
6. public static > Collector toMap(
                                Function keyMapper,
                                Function valueMapper,
                                BinaryOperator mergeFunction,
                                Supplier mapSupplier);
    
7. public static  Collector>>
    groupingBy(Function classifier) ;
8. public static 
    Collector> groupingBy(Function classifier,
                                          Collector downstream) ;
9. public static >
    Collector groupingBy(Function classifier,
                                  Supplier mapFactory,
                                  Collector downstream);
    
10. public static Collector joining();
11. public static Collector joining(CharSequence delimiter);
12. public static Collector joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix) ;
13. public static 
    Collector mapping(Function mapper,
                               Collector downstream)
@Getter
@Setter
@ToString
@Builder
public class Student {

    private Long id;
    private String name;
    private Integer age;
    private String address;
}

toCollection方法

Collectors类给了toList()toSet()方法,默认的是ArrayListHashSet,所以要想使用其他的类型的集合就可以使用这个方法,例如使用LinkedList

public class CollectorsTest {

    public static void main(String[] args) {
    }
    
    private List list = new ArrayList<>();

    @Before
    public void init(){
        Student student1 = Student.builder().id(1L).name("张三").age(20).address("北京").build();
        Student student2 = Student.builder().id(2L).name("李四").age(21).address("上海").build();
        Student student3 = Student.builder().id(3L).name("王五").age(22).address("广州").build();
        Student student4 = Student.builder().id(4L).name("赵六").age(23).address("重庆").build();
        Student student5 = Student.builder().id(5L).name("钱七").age(24).address("武汉").build();
        list = Stream.of( student4,student5,student1, student2, student3).collect(Collectors.toList());
    }


    @Test
    public void testCollection(){
        System.out.println("list : ");
        System.out.println(JSON.toJSONString(list));
        LinkedList linkedList = list.stream().collect(Collectors.toCollection(LinkedList::new));
        System.out.println("linkedList : ");
        System.out.println(JSON.toJSONString(linkedList));
    }
}
list : 
[{"address":"北京","age":20,"id":1,"name":"张三"},{"address":"上海","age":21,"id":2,"name":"李四"},{"address":"广州","age":22,"id":3,"name":"王五"},{"address":"重庆","age":23,"id":4,"name":"赵六"},{"address":"武汉","age":24,"id":5,"name":"钱七"}]
linkedList : 
[{"address":"北京","age":20,"id":1,"name":"张三"},{"address":"上海","age":21,"id":2,"name":"李四"},{"address":"广州","age":22,"id":3,"name":"王五"},{"address":"重庆","age":23,"id":4,"name":"赵六"},{"address":"武汉","age":24,"id":5,"name":"钱七"}]

toList()方法

这个最常见和常用的方法

List list = Stream.of( student4,student5,student1, student2, student3).collect(Collectors.toList());

toSet()方法

这个也是最常见和常用的方法

Set set = Stream.of(student4, student5, student1, student2, student3).collect(Collectors.toSet());

toMap()方法

toMap()最少接收两个参数

    @Test
    public void testToMap(){
        Map towParamMap = list.stream().collect(Collectors.toMap(Student::getId, Function.identity()));
        System.out.println(JSON.toJSONString(towParamMap));
    }

Collectors.toMap(Student::getId, Function.identity())这个方法碰到重复的key会抛出异常,把张三和李四的id改成一样,再次运行机会抛出异常

    @Before
    public void init(){
        Student student1 = Student.builder().id(1L).name("张三").age(20).address("北京").build();
        Student student2 = Student.builder().id(1L).name("李四").age(21).address("上海").build();
        Student student3 = Student.builder().id(3L).name("王五").age(22).address("广州").build();
        Student student4 = Student.builder().id(4L).name("赵六").age(23).address("重庆").build();
        Student student5 = Student.builder().id(5L).name("钱七").age(24).address("武汉").build();
        list = Stream.of(student1, student2, student3,student4,student5).collect(Collectors.toList());
    }

    @Test
    public void testToMap(){
        Map towParamMap = list.stream().collect(Collectors.toMap(Student::getId, Function.identity()));
        System.out.println(JSON.toJSONString(towParamMap));
    }
java.lang.IllegalStateException: Duplicate key Student(id=1, name=张三, age=20, address=北京)

所以使用这个方法时需要注意,这时可以通过第三个参数来解决重复key的问题

    @Before
    public void init(){
        Student student1 = Student.builder().id(1L).name("张三").age(20).address("北京").build();
        Student student2 = Student.builder().id(1L).name("李四").age(21).address("上海").build();
        Student student3 = Student.builder().id(3L).name("王五").age(22).address("广州").build();
        Student student4 = Student.builder().id(4L).name("赵六").age(23).address("重庆").build();
        Student student5 = Student.builder().id(5L).name("钱七").age(24).address("武汉").build();
        list = Stream.of(student1, student2, student3,student4,student5).collect(Collectors.toList());
    }

    @Test
    public void testToMap(){
        Map threeParamMap = list.stream().collect(Collectors.toMap(Student::getId, Function.identity(), (a,b) -> b));
        System.out.println(JSON.toJSONString(threeParamMap));
    }

结果为

{1:{"address":"上海","age":21,"id":1,"name":"李四"},3:{"address":"广州","age":22,"id":3,"name":"王五"},4:{"address":"重庆","age":23,"id":4,"name":"赵六"},5:{"address":"武汉","age":24,"id":5,"name":"钱七"}}

可以看到李四覆盖了张三,所以实际中使用时也要注意数据选择.注意一下这个函数(a,b) -> b也可以重新自己定义一个合并的函数BinaryOperator mergeFunction来处理重复数据

还有四个参数的方法可以不使用默认的HashMap而使用其他的容器,例如TreeMap

Map fourParamMap = list.stream().collect(Collectors.toMap(Student::getId, student -> student.getName(), (a,b) -> b, TreeMap::new));
System.out.println(JSON.toJSONString(fourParamMap));

结果

{1:"李四",3:"王五",4:"赵六",5:"钱七"}

groupingBy()方法

Collectors类 groupingBy 方法

  1. 一个参数的方法

    一个参数的方法,还是调用的两个参数的重载方法,第二个参数默认调用 toList() 方法

    public static  Collector>>
        groupingBy(Function classifier) {
            return groupingBy(classifier, toList());
        }

    示例:

    public class GroupingByTest {
    
        public static void main(String[] args) {
            List students = new ArrayList<>();
            Student student = new Student();
            student.setId(1L);
            student.setName("小明");
            students.add(student);
            Student student2 = new Student();
            student2.setId(2L);
            student2.setName("小红");
            students.add(student2);
            Map> collect = students.stream().collect(Collectors.groupingBy(s -> {
                return s.getId();
            }));
            System.out.println(JSON.toJSONString(collect));
        }
    }

    结果

    {1:[{"id":1,"name":"小明"}],2:[{"id":2,"name":"小红"}]}

    groupingBy 方法参数Function classifier

    @FunctionalInterface
    public interface Function {
        R apply(T t);
    }

Function是函数式接口,接收一个参数T,返回一个结果R,示例中可以表示为下面这样的,先创建一个Function接口,再将接口当作参数传进去.

   Function groupingByFun = s -> {return s.getId()};
           Map> collect = students.stream().collect(Collectors.groupingBy(groupingByFun
           ));

优化s -> {return s.getId()} 可以简化写法

Function groupingByFun = s -> {return s.getId()};
// 可以简化成
Function groupingByFun = s ->  s.getId();
// 再一次简化
Function groupingByFun = Student::getId;
  1. 两个参数的方法

    public static 
        Collector> groupingBy(Function classifier,
                                              Collector downstream) {
            return groupingBy(classifier, HashMap::new, downstream);
        }

    示例

    Map countMap = students.stream().collect(Collectors.groupingBy(Student::getId, Collectors.counting()));
            System.out.println(JSON.toJSONString(countMap));
    
    // {1:1,2:1}
  1. 三个参数的方法

    public static >
        Collector groupingBy(Function classifier,
                                      Supplier mapFactory,
                                      Collector downstream) {
        
    }

    示例

    TreeMap> treeMapSet = students.stream().collect(Collectors.groupingBy(Student::getId, TreeMap::new, Collectors.toSet()));
    
    System.out.println(JSON.toJSONString(treeMapSet));
    // {1:[{"id":1,"name":"小明"}],2:[{"id":2,"name":"小红"}]}

joining()方法

总共默认了三个拼接方法

    @Test
    public void testJoin(){
        String join = Stream.of("hello", "world", "hello", "java").collect(Collectors.joining());
        System.out.println(join);
        String join1 = Stream.of("hello", "world", "hello", "java").collect(Collectors.joining(","));
        System.out.println(join1);
        String join2 = Stream.of("hello", "world", "hello", "java").collect(Collectors.joining(",","",""));
        System.out.println(join2);
    }
// helloworldhellojava
//hello,world,hello,java
//hello,world,hello,java

从内部实现来看,还是有不一样,不带参数的方法,内部使用StringBuilder实现

public static Collector joining() {
        return new CollectorImpl(
                StringBuilder::new, StringBuilder::append,
                (r1, r2) -> { r1.append(r2); return r1; },
                StringBuilder::toString, CH_NOID);
    }

带参数的方法使用StringJoiner实现

public static Collector joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix) {
        return new CollectorImpl<>(
                () -> new StringJoiner(delimiter, prefix, suffix),
                StringJoiner::add, StringJoiner::merge,
                StringJoiner::toString, CH_NOID);
    }

mapping()方法

mapping简单用法,mapping最简单的用法可以和map方法一样收集某一个字段的值,大部分情况可以和groupingBy,配合使用,例如分组之后只想取某一个字段的值,就可以使用Collectors.mapping配合

    private List list = new ArrayList<>();

    @Before
    public void init(){
        Student student1 = Student.builder().id(1L).name("张三").age(20).address("北京").build();
        Student student2 = Student.builder().id(1L).name("李四").age(21).address("上海").build();
        Student student3 = Student.builder().id(3L).name("王五").age(22).address("广州").build();
        Student student4 = Student.builder().id(4L).name("赵六").age(23).address("重庆").build();
        Student student5 = Student.builder().id(5L).name("钱七").age(24).address("武汉").build();
        list = Stream.of(student1, student2, student3,student4,student5).collect(Collectors.toList());
    }

    @Test
    public void testMapping(){
        // 收集单个字段
         List mappingList = list.stream().collect(Collectors.mapping(Student::getId, Collectors.toList()));
        System.out.println(JSON.toJSONString(mappingList));
        // 和groupingBy配合使用
        Map> mapping = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.mapping(Student::getName, Collectors.toList())));
        System.out.println(JSON.toJSONString(mapping));
    }
本文由博客一文多发平台 OpenWrite 发布!

你可能感兴趣的:(java后端)