Java8——Stream流的使用(收集操作)(二)

上面的预定义归纳操作内部都是调用的reducing工厂方法,或者说是reducing归纳操作的一些特殊情况,当上面的预定于定义方法不能满足我们的要求,此时我们可以使用reducing...
1.5 自定义

  实际上,上面的预定义归纳操作内部都是调用的reducing工厂方法,或者说是reducing归纳操作的一些特殊情况,当上面的预定于定义方法不能满足我们的要求,此时我们可以使用reducing定义一个自己的归纳操作!

public static < T > Collector<T,?,Optional< T >> reducing(BinaryOperator< T > op)

  op:二元操作器,操作两个元素得到一个新元素。第一次计算时两个参数分别取前两个元素,计算的值将会作为下一次计算的第一个参数,后面的元素作为第二个参数。
  返回一个Collector。没有初始值,返回一个Optional对象,以表明结果可能不存在。

public static < T > Collector<T,?,T> reducing(T identity, BinaryOperator< T > op)

  identity:一个初始值,最终会返回同类型的值。
  op:二元操作器,操作两个元素得到一个新元素。第一次计算时第一个参数取初始值,第二个参数取第一个元素,计算的值将会作为下一次计算的第一个参数,后面的元素作为第二个参数。

public static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator< U > op)

  identity:一个初始值,最终会返回同类型的值。
  mapper: 一个一元函数,操作一个流元素得到一个结果。
  op:二元操作器,操作两个元素得到一个新元素。第一次计算时第一个参数取初始值,第二个参数取第一个元素应用mapper的结果,计算的值将会作为下一次计算的第一个参数,后面元素应用mapper的结果作为第二个参数。

  这样看起来,collect方法和reduce的方法有很多归纳功能都是重合的,但是它们仍然有显著的区别,最重要的就是reduce本身被作为不可变的归纳,每一次操作都应该由两个值生成新的值而不是改变原值,但是collect则作为可变归纳,支持并行的操作!

使用案例:

/**
 * 自定义
 * 看起来和reduce的功能差不多
 */
@Test
public void custom() {

    //自定义求和操作
    System.out.println(Stream.of(1, 2, 3, 4, 7)
            .collect(reducing(0, Integer::sum)));

    //自定义计数操作
    System.out.println(Stream.of(1, 2, 3, 4, 7)
            .collect(reducing(0, x -> 1, Integer::sum)));

    //求最值,初始值10
    System.out.println(Stream.of(1, 2, 3, 4, 7)
            //使用方法引用Integer::max来表示求最值的意图
            .collect(reducing(10, Integer::max)));

    //求最值
    Stream.of(1, 2, 3, 4, 7)
            //使用方法引用Integer::max来表示求最值的意图
            .collect(reducing(Integer::max))
            .ifPresent(System.out::println);

}

2. 集合

  collect最重要的收集操作之一就是将流元素转换为集合,当然Collectos的静态方法中也定义了将流元素输出到集合的收集器!有了这些方法,我们可以方便快捷的实现集合转换!

2.1 收集到Collection

public static < T > Collector<T,?,List< T >> toList()

  返回一个Collector,将所有流元素按顺序收集到一个List中。实际类型是一个ArrayList,不安全!

public static < T > Collector<T,?,Set< T >> toSet()

  返回一个Collector,将所有流元素按顺序收集到一个Set中。实际类型是一个HashSet,不安全!

public static <T,C extends Collection< T >> Collector<T,?,C> toCollection(Supplier< C > collectionFactory)

  collectionFactory:一个生产者,用于指定集合实际类型,只要是Collection体系中的集合!
  返回一个Collector,将所有流元素按顺序收集到一个Collection中。实际类型通过传入的参数自己指定,只要是Collection体系中的集合!

2.2 收集到Map

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  返回一个Collector ,它将元素收集到一个Map ,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型是一个HashMap,不安全!
  注意:如果有重复的key,那么将抛出IllegalStateException异常!

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  mergeFunction:一个二元操作器,处理遇到key冲突的情况!第一个参数是前一个冲突的key的value,第二个参数是后一个冲突的key的value。返回一个结果,作为value。
  返回一个Collector,它将元素收集到一个Map,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型是一个HashMap,不安全!指定冲突解决策略!

public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction, Supplier< M > mapSupplier)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  mergeFunction:一个二元操作器,处理遇到key冲突的情况!第一个参数是前一个冲突的key的value,第二个参数是后一个冲突的key的value。返回一个结果,作为value。
  mapSupplier:一个生产者,用于指定集合实际类型,只要是Map体系中的集合!
  返回一个Collector,它将元素收集到一个Map,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型通过传入的参数自己指定,只要是Map体系中的集合!指定冲突解决策略!

2.3 收集到ConcurrentMap

public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  返回一个Collector ,它将元素收集到一个ConcurrentMap,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型是一个ConcurrentHashMap,线程安全!
  注意:如果有重复的key,那么将抛出IllegalStateException异常!

public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  mergeFunction:一个二元操作器,处理遇到key冲突的情况!第一个参数是前一个冲突的key的value,第二个参数是后一个冲突的key的value。返回一个结果,作为value。
  返回一个Collector ,它将元素收集到一个ConcurrentMap,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型是一个ConcurrentHashMap,线程安全!指定冲突解决策略!

public static <T,K,U,M extends ConcurrentMap<K,U>> Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction, Supplier< M > mapSupplier)

  keyMapper:map的key的函数,参数就是每一个流元素。
  valueMapper:map的value的函数,参数就是每一个流元素。
  mergeFunction:一个二元操作器,处理遇到key冲突的情况!第一个参数是前一个冲突的key的value,第二个参数是后一个冲突的key的value。返回一个结果,作为value。
  mapSupplier:一个生产者,用于指定集合实际类型,只要是ConcurrentMap体系中的集合!
  返回一个Collector,它将元素收集到一个ConcurrentMap,其键和值是将所提供的映射函数应用于输入元素(流元素)的结果。实际类型通过传入的参数自己指定,只要是ConcurrentMap体系中的集合!指定冲突解决策略!

2.4 使用案例
/**
 * @author lx
 */
public class CollectCollection {


    /**
     * collection
     */
    @Test
    public void collection() {
        //收集全部学生分数ArrayList集合
        List<Integer> scoreArrayList = students.stream().map(Student::getScore).collect(toList());
        //收集全部学生分数HashSet集合
        Set<Integer> scoreHashSet = students.stream().map(Student::getScore).collect(toSet());
        //收集全部学生分数LinkedHashSet集合
        Set<Integer> scoreLinkedHashSet = students.stream().map(Student::getScore).collect(toCollection(LinkedHashSet::new));
        System.out.println(scoreArrayList);
        System.out.println(scoreHashSet);
        System.out.println(scoreHashSet);
    }

    /**
     * map
     */
    @Test
    public void map() {

        //public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
        //注意:如果有重复的key,那么将抛出IllegalStateException异常

        //收集全部学生分数 名字-分数 的HashMap,将会抛出异常
        //Map<String, Integer> nameStoreHashMap = students.stream().collect(toMap(Student::getName, Student::getScore));
        //收集全部学生分数 id-分数 的HashMap,不会抛出异常
        Map<Integer, Integer> idStoreHashMap = students.stream().collect(toMap(Student::getId, Student::getScore));
        System.out.println(idStoreHashMap);

        //public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction)
        //指定key冲突解决策略

        //收集全部学生分数 名字-分数 的HashMap,取前一个冲突的value
        Map<String, Integer> nameStoreHashMap1 = students.stream().collect(toMap(Student::getName, Student::getScore, (x
                , y) -> {
            System.out.println(x);
            System.out.println(y);
            return x;
        }));
        //收集全部学生分数 名字-分数 的HashMap,取后一个冲突的value
        Map<String, Integer> nameStoreHashMap2 = students.stream().collect(toMap(Student::getName, Student::getScore, (x
                , y) -> {
            System.out.println(x);
            System.out.println(y);
            return y;
        }));

        System.out.println(nameStoreHashMap1);
        System.out.println(nameStoreHashMap2);



        //public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction, Supplier< M > mapSupplier)
        //指定key冲突解决策略以及指定Map类型LinkedHashMap
        LinkedHashMap<Integer, String> scoreNameLinkedHashMap = students.stream()
                .collect(toMap(Student::getScore, Student::getName, (x, y) -> y, LinkedHashMap::new));
        //指定key冲突解决策略以及指定Map类型,TreeMap
        TreeMap<Integer, String> scoreNameTreeMap = students.stream()
                .collect(toMap(Student::getScore, Student::getName, (x, y) -> y, TreeMap::new));

        System.out.println(scoreNameLinkedHashMap);
        System.out.println(scoreNameTreeMap);
    }


    /**
     * ConcurrentMap
     */
    @Test
    public void concurrentMap() {

        //public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
        //注意:如果有重复的key,那么将抛出IllegalStateException异常

        //收集全部学生分数 名字-分数 的HashMap,将会抛出异常
        //ConcurrentMap<String, Integer> collect = students.stream().collect(toConcurrentMap(Student::getName,Student::getScore));

        //收集全部学生分数 id-分数 的ConcurrentHashMap,不会抛出异常
        ConcurrentMap<Integer, Integer> idStoreHashMap = students.stream().collect(toConcurrentMap(Student::getId, Student::getScore));

        System.out.println(idStoreHashMap);


        //public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction)
        //指定key冲突解决策略

        //收集全部学生分数 名字-分数 的ConcurrentHashMap,取前一个冲突的value
        ConcurrentMap<String, Integer> nameStoreHashMap1 = students.stream().collect(toConcurrentMap(Student::getName, Student::getScore, (x
                , y) -> {
            System.out.println(x);
            System.out.println(y);
            return x;
        }));
        //收集全部学生分数 名字-分数 的HashMap,取后一个冲突的value
        ConcurrentMap<String, Integer> nameStoreHashMap2 = students.stream().collect(toConcurrentMap(Student::getName, Student::getScore, (x
                , y) -> {
            System.out.println(x);
            System.out.println(y);
            return y;
        }));

        System.out.println(nameStoreHashMap1);
        System.out.println(nameStoreHashMap2);



        //public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator< U > mergeFunction, Supplier< M > mapSupplier)
        //指定key冲突解决策略以及指定Map类型ConcurrentHashMap
        ConcurrentMap<Integer, String> scoreNameConcurrentHashMap = students.stream()
                .collect(toConcurrentMap(Student::getScore, Student::getName, (x, y) -> y, ConcurrentHashMap::new));
        //指定key冲突解决策略以及指定Map类型,ConcurrentSkipListMap
        ConcurrentMap<Integer, String> scoreNameConcurrentSkipListMap = students.stream()
                .collect(toConcurrentMap(Student::getScore, Student::getName, (x, y) -> y, ConcurrentSkipListMap::new));

        System.out.println(scoreNameConcurrentHashMap);
        System.out.println(scoreNameConcurrentSkipListMap);
    }


    List<Student> students = new ArrayList<>();

    @Before
    public void before() {
        students.add(new Student(1, 55, "小花"));
        students.add(new Student(2, 100, "小华"));
        students.add(new Student(3, 85, "晓华"));
        students.add(new Student(4, 70, "肖华"));
        students.add(new Student(5, 70, "小小"));
        students.add(new Student(6, 66, "小小"));
        students.add(new Student(7, 60, "小夏"));
    
全文链接:Java8——Stream流的使用(收集操作)
  • 发表于 2020-09-16 16:39
  • 阅读 ( 24 )

0 条评论

请先 登录 后评论
NX小编
NX小编

995 篇文章

作家榜 »

  1. NX小编 995 文章
  2. 58沈剑 309 文章
  3. 奈学教育 131 文章
  4. 李希沅 | 奈学教育 28 文章
  5. 江帅帅 | 奈学教育 27 文章
  6. 林淮川 | 奈学教育 12 文章
  7. 科技热点 10 文章
  8. 邱鹏超 2 文章