对于java8collectors感兴趣的读者,本文将会是一篇不错的选择,并为您提供关于Java8-StreamCollectors分组的例子、Java8Collectors类的静态工厂方法、Java
对于java8 collectors感兴趣的读者,本文将会是一篇不错的选择,并为您提供关于Java 8 - Stream Collectors分组的例子、Java 8 Collectors 类的静态工厂方法、Java 8 lambda Collectors.groupingBy with Collector.toList()中的map、Java 8 新特性|java.util.stream.Collectors的有用信息。
本文目录一览:- java8 collectors
- Java 8 - Stream Collectors分组的例子
- Java 8 Collectors 类的静态工厂方法
- Java 8 lambda Collectors.groupingBy with Collector.toList()中的map
- Java 8 新特性|java.util.stream.Collectors
java8 collectors
shekhargulati/java8-the-missing-tutorial
Collectors
On day 2, you learned that the Stream API can help you work with collections in a declarative manner. We looked at collect
, which is a terminal operation that collects the result set of a stream pipeline in a List
. collect
is a reduction operation that reduces a stream to a value. The value could be a Collection, Map, or a value object. You can use collect
to achieve following:
-
Reducing stream to a single value: Result of the stream execution can be reduced to a single value. Single value could be a
Collection
or numeric value like int, double, etc or a custom value object. -
Group elements in a stream: Group all the tasks in a stream by TaskType. This will result in a
Map<TaskType, List<Task>>
with each entry containing a TaskType and its associated Tasks. You can use any other Collection instead of a List as well. If you don''t need all the tasks associated with a TaskType, you can alternatively produce aMap<TaskType, Task>
. One example could be grouping tasks by type and obtaining the first created task. -
Partition elements in a stream: You can partition a stream into two groups -- e.g. due and completed tasks.
Collector in Action
To feel the power of Collector
let us look at the example where we have to group tasks by their type. In Java 8, we can achieve grouping by TaskType by writing code shown below. Please refer to day 2 blog where we talked about the example domain we will use in this series
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) {
return tasks.stream().collect(Collectors.groupingBy(task -> task.getType()));
}
The code shown above uses groupingBy
Collector
defined in the Collectors
utility class. It creates a Map with key as the TaskType
and value as the list containing all the tasks which have same TaskType
. To achieve the same in Java 7, you would have to write the following.
public static void main(String[] args) {
List<Task> tasks = getTasks();
Map<TaskType, List<Task>> allTasksByType = new HashMap<>();
for (Task task : tasks) {
List<Task> existingTasksByType = allTasksByType.get(task.getType());
if (existingTasksByType == null) {
List<Task> tasksByType = new ArrayList<>();
tasksByType.add(task);
allTasksByType.put(task.getType(), tasksByType);
} else {
existingTasksByType.add(task);
}
}
for (Map.Entry<TaskType, List<Task>> entry : allTasksByType.entrySet()) {
System.out.println(String.format("%s =>> %s", entry.getKey(), entry.getValue()));
}
}
Collectors: Common reduction operations
The Collectors
utility class provides a lot of static utility methods for creating collectors for most common use cases like accumulating elements into a Collection, grouping and partitioning elements, or summarizing elements according to various criteria. We will cover the most common Collector
s in this blog.
Reducing to a single value
As discussed above, collectors can be used to collect stream output to a Collection or produce a single value.
Collecting data into a List
Let''s write our first test case -- given a list of Tasks we want to collect all the titles into a List.
import static java.util.stream.Collectors.toList;
public class Example2_ReduceValue {
public List<String> allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toList());
}
}
The toList
collector uses the List''s add
method to add elements into the resulting List. toList
collector uses ArrayList
as the List implementation.
Collecting data into a Set
If we want to make sure only unique titles are returned and we don''t care about order then we can use toSet
collector.
import static java.util.stream.Collectors.toSet;
public Set<String> uniqueTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toSet());
}
The toSet
method uses a HashSet
as the Set implementation to store the result set.
Collecting data into a Map
You can convert a stream to a Map by using the toMap
collector. The toMap
collector takes two mapper functions to extract the key and values for the Map. In the code shown below, Task::getTitle
is Function
that takes a task and produces a key with only title. The task -> task is a lambda expression that just returns itself i.e. task in this case.
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, task -> task));
}
We can improve the code shown above by using the identity
default method in the Function
interface to make code cleaner and better convey developer intent, as shown below.
import static java.util.function.Function.identity;
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity()));
}
The code to create a Map from the stream will throw an exception when duplicate keys are present. You will get an error like the one shown below.
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Task{title=''Read Version Control with Git book'', type=READING}
at java.util.stream.Collectors.lambda$throwingMerger$105(Collectors.java:133)
You can handle duplicates by using another variant of the toMap
function which allows us to specify a merge function. The merge function allows a client to specify how they want to resolve collisions between values associated with the same key. In the code shown below, we just used the newer value, but you can equally write an intelligent algorithm to resolve collisions.
private static Map<String, Task> taskMap_duplicates(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2));
}
You can use any other Map implementation by using the third variant of toMap
method. This requires you to specify Map
Supplier
that will be used to store the result.
public Map<String, Task> collectToMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2, LinkedHashMap::new));
}
Similar to the toMap
collector, there is also toConcurrentMap
collector, which produces a ConcurrentMap
instead of a HashMap
.
Using other collections
The specific collectors like toList
and toSet
do not allow you to specify the underlying List or Set implementation. You can use the toCollection
collector when you want to collect the result to other types of collections, as shown below.
private static LinkedHashSet<Task> collectToLinkedHaskSet(List<Task> tasks) {
return tasks.stream().collect(toCollection(LinkedHashSet::new));
}
Finding Task with longest title
public Task taskWithLongestTitle(List<Task> tasks) {
return tasks.stream().collect(collectingAndThen(maxBy((t1, t2) -> t1.getTitle().length() - t2.getTitle().length()), Optional::get));
}
Count total number of tags
public int totalTagCount(List<Task> tasks) {
return tasks.stream().collect(summingInt(task -> task.getTags().size()));
}
Generate summary of Task titles
public String titleSummary(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(";"));
}
Grouping Collectors
One of the most common use case of Collector is to group elements. Let''s look at various examples to understand how we can perform grouping.
Example 1: Grouping tasks by type
Let''s look at the example shown below, where we want to group all the tasks based on their TaskType
. You can very easily perform this task by using the groupingBy
Collector of the Collectors
utility class. You can make it more succinct by using method references and static imports.
import static java.util.stream.Collectors.groupingBy;
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType));
}
It will produce the output shown below.
{CODING=[Task{title=''Write a mobile application to store my tasks'', type=CODING, createdOn=2015-07-03}], WRITING=[Task{title=''Write a blog on Java 8 Streams'', type=WRITING, createdOn=2015-07-04}], READING=[Task{title=''Read Version Control with Git book'', type=READING, createdOn=2015-07-01}, Task{title=''Read Java 8 Lambdas book'', type=READING, createdOn=2015-07-02}, Task{title=''Read Domain Driven Design book'', type=READING, createdOn=2015-07-05}]}
Example 2: Grouping by tags
private static Map<String, List<Task>> groupingByTag(List<Task> tasks) {
return tasks.stream().
flatMap(task -> task.getTags().stream().map(tag -> new TaskTag(tag, task))).
collect(groupingBy(TaskTag::getTag, mapping(TaskTag::getTask,toList())));
}
private static class TaskTag {
final String tag;
final Task task;
public TaskTag(String tag, Task task) {
this.tag = tag;
this.task = task;
}
public String getTag() {
return tag;
}
public Task getTask() {
return task;
}
}
Example 3: Group task by tag and count
Combining classifiers and Collectors
private static Map<String, Long> tagsAndCount(List<Task> tasks) {
return tasks.stream().
flatMap(task -> task.getTags().stream().map(tag -> new TaskTag(tag, task))).
collect(groupingBy(TaskTag::getTag, counting()));
}
Example 4: Grouping by TaskType and createdOn
private static Map<TaskType, Map<LocalDate, List<Task>>> groupTasksByTypeAndCreationDate(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType, groupingBy(Task::getCreatedOn)));
}
Partitioning
There are times when you want to partition a dataset into two datasets based on a predicate. For example, we can partition tasks into two groups by defining a partitioning function that partitions tasks into two groups -- one with due date before today, and one with the others.
private static Map<Boolean, List<Task>> partitionOldAndFutureTasks(List<Task> tasks) {
return tasks.stream().collect(partitioningBy(task -> task.getDueOn().isAfter(LocalDate.now())));
}
Generating statistics
Another group of collectors that are very helpful are collectors that produce statistics. These work on the primitive datatypes like int
, double
, and long
; and can be used to produce statistics like those shown below.
IntSummaryStatistics summaryStatistics = tasks.stream().map(Task::getTitle).collect(summarizingInt(String::length));
System.out.println(summaryStatistics.getAverage()); //32.4
System.out.println(summaryStatistics.getCount()); //5
System.out.println(summaryStatistics.getMax()); //44
System.out.println(summaryStatistics.getMin()); //24
System.out.println(summaryStatistics.getSum()); //162
There are other variants as well for other primitive types like LongSummaryStatistics
and DoubleSummaryStatistics
You can also combine one IntSummaryStatistics
with another using the combine
operation.
firstSummaryStatistics.combine(secondSummaryStatistics);
System.out.println(firstSummaryStatistics)
Joining all titles
private static String allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(", "));
}
Writing a custom Collector
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
public class MultisetCollector<T> implements Collector<T, Multiset<T>, Multiset<T>> {
@Override
public Supplier<Multiset<T>> supplier() {
return HashMultiset::create;
}
@Override
public BiConsumer<Multiset<T>, T> accumulator() {
return (set, e) -> set.add(e, 1);
}
@Override
public BinaryOperator<Multiset<T>> combiner() {
return (set1, set2) -> {
set1.addAll(set2);
return set1;
};
}
@Override
public Function<Multiset<T>, Multiset<T>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
}
import com.google.common.collect.Multiset;
import java.util.Arrays;
import java.util.List;
public class MultisetCollectorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("shekhar", "rahul", "shekhar");
Multiset<String> set = names.stream().collect(new MultisetCollector<>());
set.forEach(str -> System.out.println(str + ":" + set.count(str)));
}
}
Word Count in Java 8
We will end this section by writing the famous word count example in Java 8 using Streams and Collectors.
public static void wordCount(Path path) throws IOException {
Map<String, Long> wordCount = Files.lines(path)
.parallel()
.flatMap(line -> Arrays.stream(line.trim().split("\\s")))
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
.filter(word -> word.length() > 0)
.map(word -> new SimpleEntry<>(word, 1))
.collect(groupingBy(SimpleEntry::getKey, counting()));
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}
Java 8 - Stream Collectors分组的例子
1.分组依据,计数和排序
1.1按a分组List
并显示它的总数。
package com.mkyong.java8;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Java8Example1 {
public static void main(String[] args) {
//3 apple, 2 banana, others 1
List<String> items =
Arrays.asList("apple", "apple", "banana",
"apple", "orange", "banana", "papaya");
Map<String, Long> result =
items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
)
);
System.out.println(result);
}
}
产量
{
木瓜= 1,橙= 1,香蕉= 2,苹果= 3
}
1.2添加排序。
package com.mkyong.java8;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Java8Example2 {
public static void main(String[] args) {
//3 apple, 2 banana, others 1
List<String> items =
Arrays.asList("apple", "apple", "banana",
"apple", "orange", "banana", "papaya");
Map<String, Long> result =
items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
)
);
Map<String, Long> finalMap = new LinkedHashMap<>();
//Sort a map and add to finalMap
result.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue()
.reversed()).forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
System.out.println(finalMap);
}
}
产量
{
apple = 3,banana = 2,papaya = 1,orange = 1
}
Java 8 Collectors 类的静态工厂方法
Collectors 类的静态工厂方法摘自<<Java 8 实战>>
使用示例: Collection<Dish> dishes = menuStream.collect(toCollection(),ArrayList::new);
使用示例: int totalCalories = menuStream.collect(summingInt(Dish::getCalories));
使用示例: double avgCalories = menuStream.collect(averagingInt(Dish::getCalories));
收集关于流中项目 Integer 属性的统计值,例如最大、最小、总和与平均值
使用示例: IntSummaryStatistics menuStatistics = menuStream.collect(summarizingInt(Dish::getCalories));
使用示例: String shortMenu = menuStream.map(Dish::getName).collect(joining(","));
一个包裹了流中按照给定比较器选出的最大元素的 Optional,或如果流为空则为 Optional.empty()
使用示例: Optional<Dish> fattest = menuStream.collect(maxBy(comparingInt(Dish::getCalories)));
一个包裹了流中按照给定比较器选出的最小元素的 Optional,或如果流为空则为 Optional.empty()
使用示例: Optional<Dish> lightest = menuStream.collect(minBy(comparingInt(Dish::getCalories)));
从一个作为累加器的初始值开始,利用 BinaryOperator 与流中的元素逐个结合,从而将流归约为单个值
使用示例: int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum));
使用示例: int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size));
根据项目的一个属性的值对流中的项目作问组,并将属性值作为结果 Map 的键
使用示例: Map<Dish.Type,List<Dish>> dishesByType = menuStream.collect(groupingBy(Dish::getType));
使用示例: Map<Boolean,List<Dish>> vegetarianDishes = menuStream.collect(partitioningBy(Dish::isVegetarian));
Java 8 lambda Collectors.groupingBy with Collector.toList()中的map
Map<String,List<Event>> map = events.getItems().stream() .collect(Collectors.groupingBy(Event::getStatus,Collectors.toList()));
如何获得Map< String,List< EventDto>>的输出?地图而不是?
可以通过执行将事件转换为EventDto的外部方法来获取EventDto.例如 – this :: convertFromEventToEventDto.
解决方法
Map<String,List<EventDto>> map = events.getItems() .stream() .collect(Collectors.groupingBy(Event::getStatus,Collectors.mapping(this::convertFromEventToEventDto,Collectors.toList())));
Java 8 新特性|java.util.stream.Collectors
Java 8 流的新类 java.util.stream.Collectors 实现了 java.util.stream.Collector 接口,同时又提供了大量的方法对流 (stream) 的元素执行 map and reduce 操作,或者统计操作。
1
Collectors.averagingDouble()
Collectors.averagingDouble()
方法将流中的所有元素视为 double
类型并计算他们的平均值。该方法返回的是同一个 Collectors
实例,因此可以进行链式操作。
Collectors.averagingDouble()
接受一个参数,这个参数是一个 lambda 表达式,用于对所有的元素执行一个 map
操作。
Java 所有集合的 stream().collect()
可以接受一个收集器实例作为其参数并返回该收集器的计算结果
参考下面的代码,collect()
方法会把所有的元素收集起来然后传递给 Collectors.averagingDouble(d->d*2)
收集器,对每个元素执行 *2
操作后计算平均值
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class AveragingDoubleTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
Double result = list.stream().collect(Collectors.averagingDouble(d->d*2));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.AveragingDoubleTest
5.0
Process finished with exit code 0
复制
2
Collectors.averagingInt()
该方法和 Collectors.averagingDouble()
一样,不同的是它把流中的所有元素看成是 int
类型,并返回一个浮点类型的平均值
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class AveragingIntTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
Double result = list.stream().collect(Collectors.averagingInt(v->v*2));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.AveragingIntTest
5.0
Process finished with exit code 0
复制
3
Collectors.averagingLong()
该方法也和 Collectors.averagingDouble()
类似,不同的是它把流中的所有元素看成是 long
类型,并返回一个 double
类型的平均值
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class AveragingLongTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
Double result = list.stream().collect(Collectors.averagingLong(v->v*2));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.AveragingLongTest
5.0
Process finished with exit code 0
复制
4
Collectors.averagingDouble()
Collectors.collectingAndThen()
函数应该最像 map and reduce
了,它可接受两个参数,第一个参数用于 reduce
操作,而第二参数用于 map
操作。
也就是,先把流中的所有元素传递给第二个参数,然后把生成的集合传递给第一个参数来处理。
例如下面的代码,先把 [1,2,3,4]
这个集合传递给 s-> s*s
lambda 表达式,计算得出结果为 [1,4,9,16]
,然后再把 [1,4,9,16]
传递给 v->v*2
表达式,计算得出 [2,8,18,32]
,然后传递给 Collectors.averagingLong()
计算得到结果为 25.0
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CollectingAndThenTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
Double result = list.stream().collect(Collectors.collectingAndThen(Collectors.averagingLong(v->v*2),
s-> s*s));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.CollectingAndThenTest
25.0
Process finished with exit code 0
复制
5
Collectors.counting()
Collectors.counting()
用于统计流中元素的个数。
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CountingTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
long result= list.stream().collect(Collectors.counting());
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.CountingTest
4
Process finished with exit code 0
复制
6
Collectors.joining()
Collectors.joining()
方法用某个指定的拼接字符串把所有元素拼接成一个字符串,并添加可选的前缀和后缀
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class JoiningTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("A","B","C","D");
String result= list.stream().collect(Collectors.joining(",","(",")"));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.JoiningTest
(A,B,C,D)
Process finished with exit code 0
复制
7
Collectors.maxBy () 和 Collectors.minBy ()
Collectors.maxBy()
和 Collectors.minBy()
两个方法分别用于计算流中所有元素的最大值和最小值。
两个方法都可以接受一个比较器作为参数,用于如何计算最大值或最小值
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class MaxByMinByTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(30,10,20,35);
//Get Max
list.stream().collect(Collectors.maxBy(new MaxByMinByTest().new IntegerComp()))
.ifPresent(i->System.out.println(i));
//Get Min
list.stream().collect(Collectors.minBy(new MaxByMinByTest().new IntegerComp()))
.ifPresent(i->System.out.println(i));
}
class IntegerComp implements Comparator<Integer> {
@Override
public int compare(Integer i1, Integer i2) {
if(i1 >=i2 ){
return 1;
}else{
return -1;
}
}
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.MaxByMinByTest
35
10
Process finished with exit code 0
复制
8
Collectors.summingInt()
Collectors.summingInt()
方法将流中的所有元素视为 int
类型,并计算所有元素的总和 (sum)
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class SummingIntTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(30,10,20,35);
int result = list.stream().collect(Collectors.summingInt(i->i));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.SummingIntTest
95
Process finished with exit code 0
复制
9
Collectors.summingLong()
Collectors.summingLong()
将流中的所有元素视为 long
类型,并计算所有元素的总和
package com.sjh.test.java8.collectors;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SummingLongTest {
public static void main(String[] args) {
List<Long> list = new ArrayList<>();
list.add((long)340);
list.add((long)240);
list.add((long)360);
long result = list.stream().collect(Collectors.summingLong(l->l));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.SummingLongTest
940
Process finished with exit code 0
复制
10
Collectors.summingDouble()
Collectors.summingDouble()
将流中的所有元素视为 double
类型,并计算所有元素的总和
package com.sjh.test.java8.collectors;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class SummingDoubleTest {
public static void main(String[] args) {
List<Double> list = Arrays.asList(340.5,234.56,672.76);
Double result = list.stream().collect(Collectors.summingDouble(d->d));
System.out.println(result);
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.SummingDoubleTest
1247.82
Process finished with exit code 0
复制
summingInt ()、summingLong ()、summingDouble () 这三个函数的结果的类型,就是它们如何看待元素的类型。
11
Collectors.toList()
Collectors.toList()
将流中的所有元素导出到一个列表 (List) 中
package com.sjh.test.java8.collectors;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ToListTest {
public static void main(String[] args) {
List<String> list = Stream.of("AA","BB","CC").collect(Collectors.toList());
list.forEach(s->System.out.println(s));
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.ToListTest
AA
BB
CC
Process finished with exit code 0
复制
12
Collectors.toSet()
Collectors.toSet()
把流中的所有元素导出到一个集合 (Set) 中,并排除重复的元素 ( Set 的特性 )
package com.sjh.test.java8.collectors;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ToSetTest {
public static void main(String[] args) {
Set<String> set = Stream.of("AA","AA","BB").collect(Collectors.toSet());
set.forEach(s->System.out.println(s));
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.ToSetTest
AA
BB
Process finished with exit code 0
复制
13
Collectors.toMap()
Collectors.toMap()
将流中的所有元素导出到一个哈希表 (Map) 中。该方法接受两个参数,第一个参数用于生成键 ( key ) ,第二个参数用于生成值 ( value )。两个参数都是 Lambda 表达式。
package com.sjh.test.java8.collectors;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ToMapTest {
public static void main(String[] args) {
Map<String,String> map = Stream.of("AA","BB","CC").collect(Collectors.toMap(k->k, v->v+v));
map.forEach((k,v)->System.out.println("key:"+k +" value:"+v));
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.ToMapTest
key:CC value:CCCC
key:BB value:BBBB
key:AA value:AAAA
Process finished with exit code 0
复制
14
Collectors.mapping()
Collectors.mapping()
一般用于多重 map and reduce
中。Java 文档中描述的原型如下:
mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)
复制
第一个参数用于 map
,第二个参数用于 reduce
package com.sjh.test.java8.collectors;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class MappingTest {
public static void main(String[] args) {
List<Person> list = Person.getList();
Map<Integer, String> nameByAge
= list.stream().collect(Collectors.groupingBy(Person::getAge,
Collectors.mapping(Person::getName, Collectors.joining(","))));
nameByAge.forEach((k,v)->System.out.println("Age:"+k +" Persons: "+v));
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public static List<Person> getList() {
List<Person> list = new ArrayList<>();
list.add(new Person("JayLa", 30));
list.add(new Person("LayMan", 20));
list.add(new Person("Tom", 20));
list.add(new Person("XinYi", 30));
return list;
}
}
复制
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.collectors.MappingTest
Age:20 Persons: LayMan,Tom
Age:30 Persons: JayLa,XinYi
Process finished with exit code 0
复制
end
关于java8 collectors的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Java 8 - Stream Collectors分组的例子、Java 8 Collectors 类的静态工厂方法、Java 8 lambda Collectors.groupingBy with Collector.toList()中的map、Java 8 新特性|java.util.stream.Collectors的相关信息,请在本站寻找。
本文标签: