GVKun编程网logo

java8 collectors

25

对于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

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:

  1. 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.

  2. 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 a Map<TaskType, Task>. One example could be grouping tasks by type and obtaining the first created task.

  3. 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 Collectors 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分组的例子

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 类的静态工厂方法

Java 8 Collectors 类的静态工厂方法

  摘自<<Java 8 实战>>

Collectors 类的静态工厂方法 工厂方法 返回类型 用于 toList List<T>  把流中所有项目收集到一个 List 使用示例: List<Dish> dishes = menuStream.collect(toList()); toSet Set<T> 把流中所有项目收集到一个 Set ,删除重复项 使用示例: Set<Dish> dishes = menuStream.collect(toSet()); toCollection Collection<T> 把流中所有项目收集到给定的供应源创建的集合

使用示例: Collection<Dish> dishes = menuStream.collect(toCollection(),ArrayList::new);

counting Long 计算流中元素的个数 使用示例: long howManyDishes = menuStream.collect(counting()); summingInt Integer 对流中项目的一个整数属性求和

使用示例: int totalCalories = menuStream.collect(summingInt(Dish::getCalories));

averagingInt Double 计算流中项目 Integer 属性的平均值

使用示例: double avgCalories = menuStream.collect(averagingInt(Dish::getCalories));

summarizingInt IntSummaryStatistics

收集关于流中项目 Integer 属性的统计值,例如最大、最小、总和与平均值

使用示例: IntSummaryStatistics menuStatistics = menuStream.collect(summarizingInt(Dish::getCalories));

joining String 连接对流中每个项目调用 toString 方法所生成的字符串

使用示例: String shortMenu = menuStream.map(Dish::getName).collect(joining(","));

maxBy Optional<T>

一个包裹了流中按照给定比较器选出的最大元素的 Optional,或如果流为空则为 Optional.empty()

使用示例: Optional<Dish> fattest = menuStream.collect(maxBy(comparingInt(Dish::getCalories)));

minBy Optional<T>

一个包裹了流中按照给定比较器选出的最小元素的 Optional,或如果流为空则为 Optional.empty()

使用示例: Optional<Dish> lightest = menuStream.collect(minBy(comparingInt(Dish::getCalories)));

reducing 归约操作产生的类型

从一个作为累加器的初始值开始,利用 BinaryOperator 与流中的元素逐个结合,从而将流归约为单个值

使用示例: int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum));

collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果应用转换函数

使用示例: int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size));

groupingBy Map<K, List<T>>

根据项目的一个属性的值对流中的项目作问组,并将属性值作为结果 Map 的键

使用示例: Map<Dish.Type,List<Dish>> dishesByType = menuStream.collect(groupingBy(Dish::getType));

partitioningBy Map<Boolean,List<T>> 根据对流中每个项目应用谓词的结果来对项目进行分区

使用示例: Map<Boolean,List<Dish>> vegetarianDishes = menuStream.collect(partitioningBy(Dish::isVegetarian));

   

Java 8 lambda Collectors.groupingBy with Collector.toList()中的map

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.

解决方法

您需要一个映射收集器来将Event元素映射到EventDto元素:
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 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的相关信息,请在本站寻找。

本文标签: