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简单使用】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 发布!

    推荐阅读