一文掌握 Java8 Stream 中 Collectors 的 24 个操作

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Java8 应该算是业界主版本了,版本中重要性很高的一个更新是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Stream","attrs":{}}],"attrs":{}},{"type":"text","text":"流处理。关于流处理内容比较多,本文主要是说一下","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Stream","attrs":{}}],"attrs":{}},{"type":"text","text":"中的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Collectors","attrs":{}}],"attrs":{}},{"type":"text","text":"工具类的使用。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Collectors","attrs":{}}],"attrs":{}},{"type":"text","text":"是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.util.stream","attrs":{}}],"attrs":{}},{"type":"text","text":"包下的一个工具类,其中各个方法的返回值可以作为","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.util.stream.Stream#collect","attrs":{}}],"attrs":{}},{"type":"text","text":"的入参,实现对队列的各种操作,包括:分组、聚合等。官方文档给出一些例子:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Implementations of {@link Collector} that implement various useful reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"The following are examples of using the predefined collectors to perform common mutable reduction tasks:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// Accumulate names into a List\nList list = people.stream().map(Person::getName).collect(Collectors.toList());\n\n// Accumulate names into a TreeSet\nSet set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));\n\n// Convert elements to strings and concatenate them, separated by commas\nString joined = things.stream()\n .map(Object::toString)\n .collect(Collectors.joining(\", \"));\n\n// Compute sum of salaries of employee\nint total = employees.stream()\n .collect(Collectors.summingInt(Employee::getSalary)));\n\n// Group employees by department\nMap> byDept = employees.stream()\n .collect(Collectors.groupingBy(Employee::getDepartment));\n\n// Compute sum of salaries by department\nMap totalByDept = employees.stream()\n .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));\n\n// Partition students into passing and failing\nMap> passingFailing = students.stream()\n .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));\n","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"定义示例数据","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先定义待操作对象,一个万能的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"类(用到了 lombok):","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\n@AllArgsConstructor\npublic class Student {\n private String id;\n private String name;\n private LocalDate birthday;\n private int age;\n private double score;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然后定义一组测试数据:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"final List students = Lists.newArrayList();\nstudents.add(new Student(\"1\", \"张三\", LocalDate.of(2009, Month.JANUARY, 1), 12, 12.123));\nstudents.add(new Student(\"2\", \"李四\", LocalDate.of(2010, Month.FEBRUARY, 2), 11, 22.123));\nstudents.add(new Student(\"3\", \"王五\", LocalDate.of(2011, Month.MARCH, 3), 10, 32.123));\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"数据统计","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"元素数量:counting","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个比较简单,就是统计聚合结果的元素数量:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 3\nstudents.stream().collect(Collectors.counting())\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"平均值:averagingDouble、averagingInt、averagingLong","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这几个方法是计算聚合元素的平均值,区别是输入参数需要是对应的类型。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,求学生的分数平均值,因为分数是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"double","attrs":{}}],"attrs":{}},{"type":"text","text":"类型,所以在不转类型的情况下,需要使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"averagingDouble","attrs":{}}],"attrs":{}},{"type":"text","text":":","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 22.123\nstudents.stream().collect(Collectors.averagingDouble(Student::getScore))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果考虑转换精度,也是可以实现:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 22.0\nstudents.stream().collect(Collectors.averagingInt(s -> (int)s.getScore()))\n// 22.0\nstudents.stream().collect(Collectors.averagingLong(s -> (long)s.getScore()))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果是求学生的平均年龄,因为年龄是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"int","attrs":{}}],"attrs":{}},{"type":"text","text":"类型,就可以随意使用任何一个函数了:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 11.0\nstudents.stream().collect(Collectors.averagingInt(Student::getAge))\n// 11.0\nstudents.stream().collect(Collectors.averagingDouble(Student::getAge))\n// 11.0\nstudents.stream().collect(Collectors.averagingLong(Student::getAge))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:这三个方法的返回值都是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Double","attrs":{}}],"attrs":{}},{"type":"text","text":"类型。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"和:summingDouble、summingInt、summingLong","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这三个方法和上面的平均值方法类似,也是需要注意元素的类型,在需要类型转换时,需要强制转换:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 66\nstudents.stream().collect(Collectors.summingInt(s -> (int)s.getScore()))\n// 66.369\nstudents.stream().collect(Collectors.summingDouble(Student::getScore))\n// 66\nstudents.stream().collect(Collectors.summingLong(s -> (long)s.getScore()))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是对于不需要强制转换的类型,可以随意使用任何一个函数:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 33\nstudents.stream().collect(Collectors.summingInt(Student::getAge))\n// 33.0\nstudents.stream().collect(Collectors.summingDouble(Student::getAge))\n// 33\nstudents.stream().collect(Collectors.summingLong(Student::getAge))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:这三个方法返回值和平均值的三个方法不一样,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summingDouble","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Double","attrs":{}}],"attrs":{}},{"type":"text","text":"类型、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summingInt","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Integer","attrs":{}}],"attrs":{}},{"type":"text","text":"类型,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summingLong","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Long","attrs":{}}],"attrs":{}},{"type":"text","text":"类型。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"最大值/最小值元素:maxBy、minBy","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"顾名思义,这两个函数就是求聚合元素中指定比较器中的最大/最小元素。比如,求年龄最大/最小的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"对象:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// Optional[Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)],注意返回类型是Optional\nstudents.stream().collect(Collectors.minBy(Comparator.comparing(Student::getAge)))\n// Optional[Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)],注意返回类型是Optional\nstudents.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getAge)))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从源码可以看出来,这两个方法算是作者给的福利,用于完善数据统计的结果。内部都是封装了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reducing","attrs":{}}],"attrs":{}},{"type":"text","text":"方法和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BinaryOperator","attrs":{}}],"attrs":{}},{"type":"text","text":"工具类,这些下面会讲到。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public static Collector> maxBy(Comparator super T> comparator) {\n return reducing(BinaryOperator.maxBy(comparator));\n}\n\npublic static Collector> minBy(Comparator super T> comparator) {\n return reducing(BinaryOperator.minBy(comparator));\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"统计结果:summarizingDouble、summarizingInt、summarizingLong","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然是数据操作,基本上逃不出计数、求平局、求和、最大、最小这几个,所以作者也是很贴心的实现了一组聚合的数据统计方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这组方法与求和、求平均的方法类似,都需要注意方法类型。比如,按照分数统计的话,需要进行类型转换:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// IntSummaryStatistics{count=3, sum=66, min=12, average=22.000000, max=32}\nstudents.stream().collect(Collectors.summarizingInt(s -> (int) s.getScore()))\n// DoubleSummaryStatistics{count=3, sum=66.369000, min=12.123000, average=22.123000, max=32.123000}\nstudents.stream().collect(Collectors.summarizingDouble(Student::getScore))\n// LongSummaryStatistics{count=3, sum=66, min=12, average=22.000000, max=32}\nstudents.stream().collect(Collectors.summarizingLong(s -> (long) s.getScore()))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果是用年龄统计的话,三个方法通用:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// IntSummaryStatistics{count=3, sum=33, min=10, average=11.000000, max=12}\nstudents.stream().collect(Collectors.summarizingInt(Student::getAge))\n// DoubleSummaryStatistics{count=3, sum=33.000000, min=10.000000, average=11.000000, max=12.000000}\nstudents.stream().collect(Collectors.summarizingDouble(Student::getAge))\n// LongSummaryStatistics{count=3, sum=33, min=10, average=11.000000, max=12}\nstudents.stream().collect(Collectors.summarizingLong(Student::getAge))\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:这三个方法返回值不一样,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summarizingDouble","attrs":{}}],"attrs":{}},{"type":"text","text":"返回","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"DoubleSummaryStatistics","attrs":{}}],"attrs":{}},{"type":"text","text":"类型,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summarizingInt","attrs":{}}],"attrs":{}},{"type":"text","text":"返回","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"IntSummaryStatistics","attrs":{}}],"attrs":{}},{"type":"text","text":"类型,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"summarizingLong","attrs":{}}],"attrs":{}},{"type":"text","text":"返回","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"LongSummaryStatistics","attrs":{}}],"attrs":{}},{"type":"text","text":"类型。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"聚合、分组","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"聚合元素:toList、toSet、toCollection","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这几个函数比较简单,是将聚合之后的元素,重新封装到队列中,然后返回。比如,得到所有","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"的 ID 列表,只需要根据需要的结果类型使用不同的方法即可:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// List: [1, 2, 3]\nfinal List idList = students.stream().map(Student::getId).collect(Collectors.toList());\n// Set: [1, 2, 3]\nfinal Set idSet = students.stream().map(Student::getId).collect(Collectors.toSet());\n// TreeSet: [1, 2, 3]\nfinal Collection idTreeSet = students.stream().map(Student::getId).collect(Collectors.toCollection(TreeSet::new));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toList","attrs":{}}],"attrs":{}},{"type":"text","text":"方法返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"List","attrs":{}}],"attrs":{}},{"type":"text","text":"子类,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toSet","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Set","attrs":{}}],"attrs":{}},{"type":"text","text":"子类,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toCollection","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Collection","attrs":{}}],"attrs":{}},{"type":"text","text":"子类。我们都知道,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Collection","attrs":{}}],"attrs":{}},{"type":"text","text":"的子类包括","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"List","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Set","attrs":{}}],"attrs":{}},{"type":"text","text":"等众多子类,所以","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toCollection","attrs":{}}],"attrs":{}},{"type":"text","text":"更加灵活。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"聚合元素:toMap、toConcurrentMap","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这两个方法的作用是将聚合元素,重新组装为","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Map","attrs":{}}],"attrs":{}},{"type":"text","text":"结构,也就是 k-v 结构。两者用法一样,区别是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Map","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toConcurrentMap","attrs":{}}],"attrs":{}},{"type":"text","text":"返回","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ConcurrentMap","attrs":{}}],"attrs":{}},{"type":"text","text":",也就是说,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toConcurrentMap","attrs":{}}],"attrs":{}},{"type":"text","text":"返回的是线程安全的 Map 结构。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,我们需要聚合","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"的 id:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123), 2=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 3=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)}\nfinal Map map11 = students.stream()\n .collect(Collectors.toMap(Student::getId, Function.identity()));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,如果 id 有重复的,会抛出","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.lang.IllegalStateException: Duplicate key","attrs":{}}],"attrs":{}},{"type":"text","text":"异常,所以,为了保险起见,我们需要借助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"另一个重载方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123), 2=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 3=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)}\nfinal Map map2 = students.stream()\n .collect(Collectors.toMap(Student::getId, Function.identity(), (x, y) -> x));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"有不同的重载方法,可以实现比较复杂的逻辑。比如,我们需要得到根据 id 分组的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"的姓名:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=张三, 2=李四, 3=王五}\nfinal Map map3 = students.stream()\n .collect(Collectors.toMap(Student::getId, Student::getName, (x, y) -> x));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,我们需要得到相同年龄得分最高的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"对象集合:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {10=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123), 11=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 12=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)}\nfinal Map map5 = students.stream()\n .collect(Collectors.toMap(Student::getAge, Function.identity(), BinaryOperator.maxBy(Comparator.comparing(Student::getScore))));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"可玩性很高。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"分组:groupingBy、groupingByConcurrent","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"都是将聚合元素进行分组,区别是,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"结果是 1:1 的 k-v 结构,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"的结果是 1:n 的 k-v 结构。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,我们对","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"的年龄分组:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// List: {10=[Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)], 11=[Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123)], 12=[Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)]}\nfinal Map> map1 = students.stream().collect(Collectors.groupingBy(Student::getAge));\n// Set: {10=[Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)], 11=[Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123)], 12=[Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)]}\nfinal Map> map12 = students.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.toSet()));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"也是分组,是不是也能够实现与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"类似的功能,比如,根据 id 分组的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":":","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123), 2=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 3=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)}\nfinal Map map3 = students.stream()\n .collect(Collectors.groupingBy(Student::getId, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为了对比,把","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"toMap","attrs":{}}],"attrs":{}},{"type":"text","text":"的写法在放这:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123), 2=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 3=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)}\nfinal Map map2 = students.stream()\n .collect(Collectors.toMap(Student::getId, Function.identity(), (x, y) -> x));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果想要得的线程安全的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Map","attrs":{}}],"attrs":{}},{"type":"text","text":",可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingByConcurrent","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"分组:partitioningBy","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"partitioningBy","attrs":{}}],"attrs":{}},{"type":"text","text":"与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"的区别在于,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"partitioningBy","attrs":{}}],"attrs":{}},{"type":"text","text":"借助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Predicate","attrs":{}}],"attrs":{}},{"type":"text","text":"断言,可以将集合元素分为","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"true","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"false","attrs":{}}],"attrs":{}},{"type":"text","text":"两部分。比如,按照年龄是否大于 11 分组:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// List: {false=[Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)], true=[Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)]}\nfinal Map> map6 = students.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 11));\n// Set: {false=[Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123), Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123)], true=[Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123)]}\nfinal Map> map7 = students.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 11, Collectors.toSet()));\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"链接数据:joining","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个方法对","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"String","attrs":{}}],"attrs":{}},{"type":"text","text":"类型的元素进行聚合,拼接成一个字符串返回,作用与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.lang.String#join","attrs":{}}],"attrs":{}},{"type":"text","text":"类似,提供了 3 个不同重载方法,可以实现不同的需要。比如:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// javagosql\nStream.of(\"java\", \"go\", \"sql\").collect(Collectors.joining());\n// java, go, sql\nStream.of(\"java\", \"go\", \"sql\").collect(Collectors.joining(\", \"));\n// 【java, go, sql】\nStream.of(\"java\", \"go\", \"sql\").collect(Collectors.joining(\", \", \"【\", \"】\"));\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"操作链:collectingAndThen","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个方法在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"的例子中出现过,它是先对集合进行一次聚合操作,然后通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Function","attrs":{}}],"attrs":{}},{"type":"text","text":"定义的函数,对聚合后的结果再次处理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"groupingBy","attrs":{}}],"attrs":{}},{"type":"text","text":"中的例子:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// {1=Student(id=1, name=张三, birthday=2009-01-01, age=12, score=12.123), 2=Student(id=2, name=李四, birthday=2010-02-02, age=11, score=22.123), 3=Student(id=3, name=王五, birthday=2011-03-03, age=10, score=32.123)}\nfinal Map map3 = students.stream()\n .collect(Collectors.groupingBy(Student::getId, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"显示将结果聚合成","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"List","attrs":{}}],"attrs":{}},{"type":"text","text":"列表,然后取列表的第 0 个元素返回,通过这种方式,实现 1:1 的 map 结构。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再来一个复杂一些的,找到聚合元素中年龄数据正确的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Student","attrs":{}}],"attrs":{}},{"type":"text","text":"列表:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// [],结果为空,是因为例子中所有人的年龄都是对的\nstudents.stream()\n .collect(\n Collectors.collectingAndThen(Collectors.toList(), (\n list -> list.stream()\n .filter(s -> (LocalDate.now().getYear() - s.getBirthday().getYear()) != s.getAge())\n .collect(Collectors.toList()))\n )\n );\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个例子纯粹是为了使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"collectingAndThen","attrs":{}}],"attrs":{}},{"type":"text","text":"的用法,其实可以简化为:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"students.stream()\n .filter(s -> (LocalDate.now().getYear() - s.getBirthday().getYear()) != s.getAge())\n .collect(Collectors.toList());\n","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"操作后聚合:mapping","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"mapping","attrs":{}}],"attrs":{}},{"type":"text","text":"是先通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Function","attrs":{}}],"attrs":{}},{"type":"text","text":"函数处理数据,然后通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Collector","attrs":{}}],"attrs":{}},{"type":"text","text":"方法聚合元素。比如,获取获取","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"students","attrs":{}}],"attrs":{}},{"type":"text","text":"的姓名列表:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// [张三, 李四, 王五]\nstudents.stream()\n .collect(Collectors.mapping(Student::getName, Collectors.toList()));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这种计算与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.util.stream.Stream#map","attrs":{}}],"attrs":{}},{"type":"text","text":"方式类似:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// [张三, 李四, 王五]\nstudents.stream()\n .map(Student::getName)\n .collect(Collectors.toList());\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从这点上看,还是通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.util.stream.Stream#map","attrs":{}}],"attrs":{}},{"type":"text","text":"更清晰一些。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"聚合后操作:reducing","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"reducing","attrs":{}}],"attrs":{}},{"type":"text","text":"提供了 3 个重载方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"public static Collector> reducing(BinaryOperator op)","attrs":{}}],"attrs":{}},{"type":"text","text":":直接通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BinaryOperator","attrs":{}}],"attrs":{}},{"type":"text","text":"操作,返回值是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Optional","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"public static Collector reducing(T identity, BinaryOperator op)","attrs":{}}],"attrs":{}},{"type":"text","text":":预定默认值,然后通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BinaryOperator","attrs":{}}],"attrs":{}},{"type":"text","text":"操作","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"public static Collector reducing(U identity, Function super T, ? extends U> mapper, BinaryOperator op)","attrs":{}}],"attrs":{}},{"type":"text","text":":预定默认值,通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Function","attrs":{}}],"attrs":{}},{"type":"text","text":"操作元素,然后通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BinaryOperator","attrs":{}}],"attrs":{}},{"type":"text","text":"操作","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,计算所有","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"students","attrs":{}}],"attrs":{}},{"type":"text","text":"的得分总数:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// Optional[66.369],注意返回类型是Optional\nstudents.stream()\n .map(Student::getScore)\n .collect(Collectors.reducing(Double::sum));\n// 66.369\nstudents.stream()\n .map(Student::getScore)\n .collect(Collectors.reducing(0.0, Double::sum));\n// 66.369\nstudents.stream()\n .collect(Collectors.reducing(0.0, Student::getScore, Double::sum));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"mapping","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reducing","attrs":{}}],"attrs":{}},{"type":"text","text":"的操作与","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.util.stream.Stream#reduce","attrs":{}}],"attrs":{}},{"type":"text","text":"方式类似:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// Optional[66.369],注意返回类型是Optional\nstudents.stream().map(Student::getScore).reduce(Double::sum);\n// 66.369\nstudents.stream().map(Student::getScore).reduce(0.0, Double::sum);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上文说到","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"maxBy","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"minBy","attrs":{}}],"attrs":{}},{"type":"text","text":"时,提到这两个函数就是通过","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reducing","attrs":{}}],"attrs":{}},{"type":"text","text":"实现的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对于","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"mapping","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reducing","attrs":{}}],"attrs":{}},{"type":"text","text":",可以参考函数式编程中 map-reduce 的概念。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"文末总结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文主要讲解了 Java8 Stream 中 Collectors 定义的 24 个方法,这种流式计算逻辑,依靠 Fork/Join 框架,性能方面有很大的优势。如果没有掌握这些用法,可能在后续阅读代码时,会很吃力,毕竟,Java8 基本上已经是业界标杆了。","attrs":{}}]},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山,公众号:看山的小屋,10 年老猿,开源贡献者。游于码界,戏享人生。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9e/9e305acd1cca75053c144cb28adc6061.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章