Java 8系列之Stream的强大工具Collector

Java8之Stream-强大的collect操作 到此对于collect的操作应该就很清晰了,希望通过这些例子能掌握核心,也就是Collector接口中那几个函数的作用,希望对你有帮助. 阅读详情
AI摘要

本文深入探讨Java8中Stream API的Collectors工具类,介绍如何利用Collectors将Stream转换为各种数据结构,如List、Set、Map等,并演示如何进行数值汇总、数据分组等操作。

Stream系列:

概述

前面我们使用过collect(toList()),在流中生成列表。实际开发过程中,List又是我们经常用到的数据结构,但是有时候我们也希望Stream能够转换生成其他的值,比如Map或者set,甚至希望定制生成想要的数据结构。

collect也就是收集器,是Stream一种通用的、从流生成复杂值的结构。只要将它传给collect方法,也就是所谓的转换方法,其就会生成想要的数据结构。这里不得不提下,Collectors这个工具库,在该库中封装了相应的转换方法。当然,Collectors工具库仅仅封装了常用的一些情景,如果有特殊需求,那就要自定义了。

显然,List是能想到的从流中生成的最自然的数据结构, 但是有时人们还希望从流生成其他值, 比如 Map 或 Set, 或者你希望定制一个类将你想要的东西抽象出来。

前面已经讲过,仅凭流上方法的签名,就能判断出这是否是一个及早求值的操作。 reduce操作就是一个很好的例子, 但有时人们希望能做得更多。
这就是收集器,一种通用的、从流生成复杂值的结构。只要将它传给collect 方法,所有的流就都可以使用它了。

<R, A> R collect(Collector<? super T, A, R> collector);

<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);

辅助接口

Supplier

Supplier<T>接口是一个函数接口,该接口声明了一个get方法,主要用来创建返回一个指定数据类型的对象。

  • T:指定的数据类型

    @FunctionalInterface
    public interface Supplier {
    T get();
    }

BiConsumer

BiConsumer<T, U>接口是一个函数接口,该接口声明了accept方法,并无返回值,该函数接口主要用来声明一些预期操作。

同时,该接口定义了一个默认方法andThen,该方法接受一个BiConsumer,并返回一个组合的BiConsumer,其会按照顺序执行操作。如果执行任一操作抛出异常,则将其传递给组合操作的调用者。 如果执行此操作抛出异常,将不执行后操作(after)。

@FunctionalInterface
public interface BiConsumer<T, U> {

    void accept(T t, U u);

    default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
        Objects.requireNonNull(after);

        return (l, r) -> {
            accept(l, r);
            after.accept(l, r);
        };
    }
}

BinaryOperator

BinaryOperator接口继承于BiFunction接口,该接口指定了apply方法执行的参数类型及返回值类型均为T。

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {

    public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

@FunctionalInterface
public interface BiFunction<T, U, R> {


    R apply(T t, U u);

    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

Function

Funtion是一个函数接口,其内定义了一个转换函数,将T转换为R。比如Stream中的map方法便是接受该函数参数,将T转换为R。

@FunctionalInterface
public interface Function<T, R> {

    /**
     * 转换函数,将T转换为R
     */
    R apply(T t);

    /**
     * 返回一个组合函数Function,首先执行before,然后再执行该Function
     *
     * 如果两个函数的求值都抛出异常,它将被中继到组合函数的调用者。
     * 如果before为null,将会抛出NullPointerException
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

     /**
     * 返回一个组合函数Function,首先执行Function,然后再执行after
     *
     * 如果两个函数的求值都抛出异常,它将被中继到组合函数的调用者。
     * 如果after为null,将会抛出NullPointerException
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * 将输入参数返回的函数
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Collector

Collector是Stream的可变减少操作接口,可变减少操作包括:将元素累积到集合中,使用StringBuilder连接字符串;计算元素相关的统计信息,例如sum,min,max或average等。Collectors(类收集器)提供了许多常见的可变减少操作的实现。

Collector<T, A, R>接受三个泛型参数,对可变减少操作的数据类型作相应限制:

  • T:输入元素类型
  • A:缩减操作的可变累积类型(通常隐藏为实现细节)
  • R:可变减少操作的结果类型

Collector接口声明了4个函数,这四个函数一起协调执行以将元素目累积到可变结果容器中,并且可以选择地对结果进行最终的变换.

  • Supplier<A> supplier(): 创建新的结果结
  • BiConsumer<A, T> accumulator(): 将元素添加到结果容器
  • BinaryOperator<A> combiner(): 将两个结果容器合并为一个结果容器
  • Function<A, R> finisher(): 对结果容器作相应的变换

在Collector接口的characteristics方法内,可以对Collector声明相关约束

  • Set<Characteristics> characteristics():

而Characteristics是Collector内的一个枚举类,声明了CONCURRENT、UNORDERED、IDENTITY_FINISH等三个属性,用来约束Collector的属性。

  • CONCURRENT:表示此收集器支持并发,意味着允许在多个线程中,累加器可以调用结果容器
  • UNORDERED:表示收集器并不按照Stream中的元素输入顺序执行
  • IDENTITY_FINISH:表示finisher实现的是识别功能,可忽略。
    注:

    1. 如果一个容器仅声明CONCURRENT属性,而不是UNORDERED属性,那么该容器仅仅支持无序的Stream在多线程中执行。

身份约束和相关性约束

Stream可以顺序执行,或者并发执行,或者顺序并发执行,为了保证Stream可以产生相同的结果,收集器函数必须满足身份约束和相关项约束。

身份约束说,对于任何部分累积的结果,将其与空结果容器组合必须产生等效结果。也就是说,对于作为任何系列的累加器和组合器调用的结果的部分累加结果a,a必须等于combiner.apply(a,supplier.get())。

相关性约束说,分裂计算必须产生等效的结果。也就是说,对于任何输入元素t1和t2,以下计算中的结果r1和r2必须是等效的:

A a1 = supplier.get();
accumulator.accept(a1,t1);
accumulator.accept(a1,t2);
R r1 = finisher.apply(a1); // result without splitting

A a2 = supplier.get();
accumulator.accept(a2,t1);
A a3 = supplier.get();
accumulator.accept(a3,t2);
R r2 = finisher.apply(combiner.apply(a2,a3)); 

创建Collector

自定义Collector

Java 8系列之重构和定制收集器

基于Collector工具库

在Collector工具库中,声明了许多常用的收集器,以供我们快速创建一个收集器。前面我们已经了解到,收集器函数必须满足身份约束和相关项约束。而基于Collector实现简化的库(如Stream.collect(Collector))创建收集器时,必须遵守以下约束:

  1. 第一个参数传递给accumulator()函数,两个参数都传递给combiner()函数,传递给finisher()函数的参数必须是上一次调用supplier(),accumulator()或combiner()函数的结果。
  2. 实现不应该对任何accumulator(),combiner()或finisher()函数的结果做任何事情,除非收集器将返回的结果返回给调用者
  3. 如果结果传递到combiner()或finisher()函数,而且返回对象与传入的不相同,则不会再将对象传递给accumulator()函数调用。
  4. 一旦结果传递到combiner()或finisher()函数,它就不会再次传递到accumulator()函数。
  5. 对于串行收集器,supplier(),accumulator()或combiner()函数返回的任何结果必须是限制串行的。这使得收集器可以并行进行,而收集器不需要执行任何额外的同步。reduce操作实现必须管理Stream的元素被正确区别并分别处理,并且仅在累积完成之后,对累加器中的数据合并。
  6. 对于并发收集器,实现可以自由地(但不是必须)同时实现reduce操作。accumulator()可以在多个线程同时调用,而不是在累积期间保持结果的独立性。仅当收集器具有Collector.Characteristics.UNORDERED特性或者原始数据是无序的时才应用并发还原。

转换成其他集合

对于前面提到了很多Stream的链式操作,但是,我们总是要将Strea生成一个集合,比如:

  • 已有代码是为集合编写的, 因此需要将流转换成集合传入;
  • 在集合上进行一系列链式操作后, 最终希望生成一个值;
  • 写单元测试时, 需要对某个具体的集合做断言。

有些Stream可以转成集合,比如前面提到toList,生成了java.util.List 类的实例。当然了,还有还有toSet和toCollection,分别生成 Set和Collection 类的实例。

toList

示例:

List<Integer> collectList = Stream.of(1, 2, 3, 4)
        .collect(Collectors.toList());
System.out.println("collectList: " + collectList);
// 打印结果
// collectList: [1, 2, 3, 4]

toSet

示例:

Set<Integer> collectSet = Stream.of(1, 2, 3, 4)
        .collect(Collectors.toSet());
System.out.println("collectSet: " + collectSet);
// 打印结果
// collectSet: [1, 2, 3, 4]

toCollection

通常情况下,创建集合时需要调用适当的构造函数指明集合的具体类型:

List<Artist> artists = new ArrayList<>();

但是调用toList或者toSet方法时,不需要指定具体的类型,Stream类库会自动推断并生成合适的类型。当然,有时候我们对转换生成的集合有特定要求,比如,希望生成一个TreeSet,而不是由Stream类库自动指定的一种类型。此时使用toCollection,它接受一个函数作为参数, 来创建集合。

值得我们注意的是,看Collectors的源码,因为其接受的函数参数必须继承于Collection,也就是意味着Collection并不能转换所有的继承类,最明显的就是不能通过toCollection转换成Map

toMap

如果生成一个Map,我们需要调用toMap方法。由于Map中有Key和Value这两个值,故该方法与toSet、toList等的处理方式是不一样的。toMap最少应接受两个参数,一个用来生成key,另外一个用来生成value。toMap方法有三种变形:

  • toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper)

    1. keyMapper: 该Funtion用来生成Key
    2. valueMapper:该Funtion用来生成value

注:若Stream中有重复的值,导致Map中key重复,在运行时会报异常java.lang.IllegalStateException: Duplicate key **

  • toMap(Function

转成值

使用collect可以将Stream转换成值。maxBy和minBy允许用户按照某个特定的顺序生成一个值。

  • averagingDouble:求平均值,Stream的元素类型为double
  • averagingInt:求平均值,Stream的元素类型为int
  • averagingLong:求平均值,Stream的元素类型为long
  • counting:Stream的元素个数
  • maxBy:在指定条件下的,Stream的最大元素
  • minBy:在指定条件下的,Stream的最小元素
  • reducing: reduce操作
  • summarizingDouble:统计Stream的数据(double)状态,其中包括count,min,max,sum和平均。
  • summarizingInt:统计Stream的数据(int)状态,其中包括count,min,max,sum和平均。
  • summarizingLong:统计Stream的数据(long)状态,其中包括count,min,max,sum和平均。
  • summingDouble:求和,Stream的元素类型为double
  • summingInt:求和,Stream的元素类型为int
  • summingLong:求和,Stream的元素类型为long

示例:

Optional<Integer> collectMaxBy = Stream.of(1, 2, 3, 4)
            .collect(Collectors.maxBy(Comparator.comparingInt(o -> o)));
System.out.println("collectMaxBy:" + collectMaxBy.get());
// 打印结果
// collectMaxBy:4

分割数据块

collect的一个常用操作将Stream分解成两个集合。假如一个数字的Stream,我们可能希望将其分割成两个集合,一个是偶数集合,另外一个是奇数集合。我们首先想到的就是过滤操作,通过两次过滤操作,很简单的就完成了我们的需求。

但是这样操作起来有问题。首先,为了执行两次过滤操作,需要有两个流。其次,如果过滤操作复杂,每个流上都要执行这样的操作, 代码也会变得冗余。

这里我们就不得不说Collectors库中的partitioningBy方法,它接受一个流,并将其分成两部分:使用Predicate对象,指定条件并判断一个元素应该属于哪个部分,并根据布尔值返回一个Map到列表。因此对于key为true所对应的List中的元素,满足Predicate对象中指定的条件;同样,key为false所对应的List中的元素,不满足Predicate对象中指定的条件

这里写图片描述

这样,使用partitioningBy,我们就可以将数字的Stream分解成奇数集合和偶数集合了。

 Map<Boolean, List<Integer>> collectParti = Stream.of(1, 2, 3, 4)
            .collect(Collectors.partitioningBy(it -> it % 2 == 0));
System.out.println("collectParti : " + collectParti);
// 打印结果
// collectParti : {false=[1, 3], true=[2, 4]}

数据分组

数据分组是一种更自然的分割数据操作, 与将数据分成true和false两部分不同,可以使用任意值对数据分组。

调用Stream的collect方法,传入一个收集器,groupingBy接受一个分类函数,用来对数据分组,就像partitioningBy一样,接受一个
Predicate对象将数据分成true和false两部分。我们使用的分类器是一个Function对象,和map操作用到的一样。

这里写图片描述

示例:

Map<Boolean, List<Integer>> collectGroup= Stream.of(1, 2, 3, 4)
            .collect(Collectors.groupingBy(it -> it > 3));
System.out.println("collectGroup : " + collectGroup);
// 打印结果
// collectGroup : {false=[1, 2, 3], true=[4]}


注:

看groupingBy和partitioningBy的例子,他们的效果都是一样的,都是将Stream的数据进行了分割处理并返回一个Map。可能举的例子给你带来了误区,实际上他们两个完全是不一样的。

  1. partitioningBy是根据指定条件,将Stream分割,返回的Map为Map

字符串

有时候,我们将Stream的元素(String类型)最后生成一组字符串。比如在Stream.of(“1”, “2”, “3”, “4”)中,将Stream格式化成“1,2,3,4”。

如果不使用Stream,我们可以通过for循环迭代实现。

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);

StringBuilder sb = new StringBuilder();

for (Integer it : list) {
    if (sb.length() > 0) {
        sb.append(",");
    }
    sb.append(it);

}
System.out.println(sb.toString());
// 打印结果
// 1,2,3,4

在Java 1.8中,我们可以使用Stream来实现。这里我们将使用 Collectors.joining 收集Stream中的值,该方法可以方便地将Stream得到一个字符串。joining函数接受三个参数,分别表示允(用以分隔元素)、前缀和后缀。

示例:

String strJoin = Stream.of("1", "2", "3", "4")
        .collect(Collectors.joining(",", "[", "]"));
System.out.println("strJoin: " + strJoin);
// 打印结果
// strJoin: [1,2,3,4]

组合Collector

前面,我们已经了解到Collector的强大,而且非常的使用。如果将他们组合起来,是不是更厉害呢?看前面举过的例子,在数据分组时,我们是得到的分组后的数据列表 collectGroup : {false=[1, 2, 3], true=[4]}。如果我们的要求更高点,我们不需要分组后的列表,只要得到分组后列表的个数就好了。

这时候,很多人下意识的都会想到,便利Map就好了,然后使用list.size(),就可以轻松的得到各个分组的列表个数。

// 分割数据块
Map<Boolean, List<Integer>> collectParti = Stream.of(1, 2, 3, 4)
        .collect(Collectors.partitioningBy(it -> it % 2 == 0));

Map<Boolean, Integer> mapSize = new HashMap<>();
collectParti.entrySet()
        .forEach(entry -> mapSize.put(entry.getKey(), entry.getValue().size()));

System.out.println("mapSize : " + mapSize);
// 打印结果
// mapSize : {false=2, true=2}

在partitioningBy方法中,有这么一个变形:

Map<Boolean, Long> partiCount = Stream.of(1, 2, 3, 4)
        .collect(Collectors.partitioningBy(it -> it.intValue() % 2 == 0,
                Collectors.counting()));
System.out.println("partiCount: " + partiCount);
// 打印结果
// partiCount: {false=2, true=2}

在partitioningBy方法中,我们不仅传递了条件函数,同时传入了第二个收集器,用以收集最终结果的一个子集,这些收集器叫作下游收集器。收集器是生成最终结果的一剂配方,下游收集器则是生成部分结果的配方,主收集器中会用到下游收集器。这种组合使用收集器的方式, 使得它们在 Stream 类库中的作用更加强大。

那些为基本类型特殊定制的函数,如averagingInt、summarizingLong等,事实上和调用特殊Stream上的方法是等价的,加上它们是为了将它们当作下游收集器来使用的。

全网详解(波哥)Java8新特性(Lambda、Stream、LocalDate等)新特性 全网详解(波哥)Java8新特性(Lambda、Stream、LocalDate等)新特性 自学java的同行们应该都要学习java8的新特性,譬如:(Lambda、Stream、LocalDate等)!本人在学习java的时候看的是波哥的视频,确实讲的不错,很详细!系统的讲述了Lambda、Stream、LocalDate等)新特性的使用。在自学的过程中,小生不才,整理了一点波哥的笔记同大家分享,这是全网详解(波哥)Java8新特性(Lambda、Stream、LocalDate等)新特性的全部笔记及代码。后续还会有springmvc、mybatis、mybatis-puls等部分的笔记以及代码,小生会尽快整理出来!最后一个小小的提醒:关注博主不迷路,感谢大家厚爱(手动比心心) 立即下载

相关推荐

Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解

主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下

jdk8 lambda 的坑 stream().collect方法报错空指针异常

jdk8 lambda 的坑 stream().collect方法报错空指针异常

qq690452074的专栏 2157

Java Stream的基本概念以及创建方法

主要介绍了Java Stream的基本概念以及创建方法,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下

java8特性概要以及demo分析

一、Java 8 Lambda 表达式Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。1.1 语法lambda 表达式的语法格式如下:(parameters) -&gt; expression或(parameters) -&gt;{state...

yitian_66的博客 2万+

零样本缺陷检测新体验:用AnomalyGPT大模型快速搭建智能质检系统(附Win10适配指南)

本文详细介绍了如何利用AnomalyGPT大模型在Windows 10系统上快速搭建零样本工业缺陷检测系统。通过实战指南,涵盖从环境部署、模型准备到工程化落地的全过程,包括将模型封装为API服务、接入工业相机以及开发可视化监控看板,为制造业智能质检提供了一套高效、低门槛的本地部署解决方案。

weixin_29094775的博客 310

从零开始的 AI Infra 学习之路

AI Infra(AI 基础设施)是指为上层的 AI 算法应用提供支持的 AI 全栈底层技术,通过合理利用计算机体系结构,可以实现 AI 计算的加速和部署。AI Infra 主要包括以下内容:AI 训练框架 & 推理引擎;AI 编译 & 计算架构;AI 硬件 & 体系结构。参考资料:;。

AI Infra / LLM / 软件开发 3万+

Java 8系列之Stream的详解(转载)

Stream系列: Java 8系列之Stream的基本语法详解 Java 8系列之Stream的强大工具Collector Java 8系列之重构和定制收集器 Java 8系列之Stream中万能的reduce

192

SAP ABAP BADI_FINS_ACDOC_POSTING_EVENTS 深度应用:KO88工单结算的凭证字段定制与财务数据增强

本文深入探讨了SAP ABAP中BADI_FINS_ACDOC_POSTING_EVENTS在KO88工单结算中的应用,详细解析了如何通过BADI实现财务凭证字段的定制与数据增强。文章提供了从结构扩展到BADI方法实现的完整步骤,包括性能优化建议和实际应用中的测试验证流程,帮助开发人员高效解决企业个性化财务需求。

weixin_26869081的博客 389

Java 8系列之Stream的基本语法详解

概述继Java 8系列之Lambda表达式之后,我们来了解Stream。Stream 是用函数式编程方式在集合类上进行复杂操作的工具,其集成了Java 8中的众多新特性之一的聚合操作,开发者可以更容易地使用Lambda表达式,并且更方便地实现对集合的查找、遍历、过滤以及常见计算等。聚合操作为了学习聚合的使用,在这里,先定义一个数据类:public class Student { int no

行云间 7万+

Vast.ai GPU服务器租用与SSH密钥连接实战指南

本文详细介绍了如何在Vast.ai平台租用GPU服务器并通过SSH密钥安全连接的全流程。从注册、选配GPU型号到SSH密钥生成与配置,再到实战中的端口转发和文件传输技巧,帮助用户高效利用云端GPU资源进行深度学习等计算密集型任务。

weixin_29574585的博客 524

044、手持视频抖动严重?OpenCV 光流 + IMU 融合的电子防抖工程方案

本文探讨了基于OpenCV光流和IMU融合的手持视频电子防抖方案。作者从实际工程经验出发,分析了纯光流和纯IMU方案的局限性,指出时间戳对齐和坐标系标定是关键挑战。文章详细介绍了融合滤波器的实现方法,推荐互补滤波替代卡尔曼滤波,并提出了动态调整融合系数的策略。在光流算法优化方面,建议采用网格化FAST特征点和前后向误差检测。最后分享了运动补偿裁剪策略和多线程流水线设计,强调在嵌入式设备上使用NEON指令优化性能。该方案通过精确的时间同步和传感器融合,有效解决了手持拍摄中的高频抖动问题。

ai技术增长的博客 248

Java 8系列之Stream中万能的reduce

reduce 操作可以实现从Stream中生成一个值,其生成的值不是随意的,而是根据指定的计算模型。比如,之前提到count、min和max方 法,因为常用而被纳入标准库中。事实上,这些方法都是reduce操作。reduce方法有三个override的方法: Optional<T> reduce(BinaryOperator<T> accumulator); T reduce(T identity

行云间 8万+

SPICE仿真软件:PSpice_(10).噪声分析

噪声分析是电路设计和优化中的一个重要工具,特别是在低噪声放大器、传感器电路和通信电路中。通过准确设置噪声源和仿真参数,合理选择频率范围,并验证仿真结果,可以有效地评估和优化电路的噪声性能。PSpice提供的噪声分析功能强大且灵活,能够帮助工程师和研究人员在多种应用场景下进行详细的噪声分析。

kkchenjj的博客 1535

java8新特性(四) Collector(收集器)

导航 引例 Collector 什么是Collector Collector工作原理 特征值 自定义Collector Collectors详解 求值 均值:averaging 元素个数:counting 最值:maxBy、minBy 和:summing、summarizing 分组 groupingBy groupingByConcurrent partition...

戏流年的博客 1万+

任务混部最少服务器数量计算问题

这里的并行度指的是该任务运行时会占用的服务器数量。要注意的是,一个服务器在每个时刻可以被任意任务使用,但同一时刻最多只能被一个任务占用,并且任务运行结束后会立即释放服务器(结束时刻不占用)。最后,我们从字典中找出服务器数量的最大值,这个最大值就是完成这批任务混部最少需要的服务器数量。对于每个任务,我们会遍历其对应的时间区间,将该任务的并行度累加到对应时刻的服务器数量上。任务混部的目标是让这批任务由同一批服务器承载运行,你需要计算完成这批任务混部最少需要多少服务器,以此来最大化控制资源成本。

m0_62153576的博客 104

模型实战(16)之StrongSort (OSNET)配合YOLOv5、v7、v8 实现多目标跟踪详解

StrongSort (OSNET)配合YOLOv5、v7、v8 实现多目标跟踪详解

yohnyang的博客 1768

Java 8系列之重构和定制收集器

前面我们已经了解到了Collector类库中各种收集器的强大,可是,它们也只是能满足常用的场景。既然开放了Collector接口,我们当然可以根据自已意愿去定制,实际操作起来还是比较简单的。Collectors.joining源码解析从前面,我们已经了解到一个Collector是由四部分组成的: Supplier<A> supplier(): 创建新的结果结 BiConsumer<A, T> acc

行云间 9367

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java8之强大的Stream API

前言:了解Stream Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。 流(Stream)到底是什么呢

zy512638348的博客 531

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

java8Collector

初识Collector体会Collector的强大 它的实现类为Collectors 聚合

whaleluo的博客 1118

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

怎么在java 8的map中使用stream

文章目录简介基本概念使用Stream获取map的key使用stream获取map的value总结 怎么在java 8的map中使用stream 简介 Map是java中非常常用的一个集合类型,我们通常也需要去遍历Map去获取某些值,java 8引入了Stream的概念,那么我们怎么在Map中使用Stream呢? 基本概念 Map有key,value还有表示key,value整体的Entry。 创建...

程序那些事 1万+

java stream collec,Java stream的collect和Collector

最近在使用Java8的新特性stream,因为LZ也在使用Spark,所以这种流式编程还是蛮顺手的,比以前的循环处理方便很多。stream基本用法网上有很多教程,这里就不在赘述了。这里LZ重点介绍stream的collect方法和其强大的工具类Collector。先看下接口中声名的collect方法: R collect(Collector super T, A, R> collector)...

weixin_42298412的博客 2802

java8 流式操作 stream

https://www.cnblogs.com/owenma/p/12207330.html Java8中Stream详细用法大全 一、概述 Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。 特点:

19li 1671

Java 8 Stream Collectors groupingBy

展示如何使用Java 8 Stream Collectors进行分组,计数,总和和排序List 分组,计数和排序 注:输出结果中的中文均应为英文。 1.1分组List并显示其总数。 Java8Example1.java package com.mkyong.java8; import java.util.Arrays; import java.util.List; import java.util...

Java开发工程师,专注微服务、分布式系统,部署运维,分享实战经验和源码解析。 1217
上一篇: Java 8系列之重构和定制收集器
下一篇: Java 8系列之Stream中万能的reduce
行云间
博客等级 码龄12年 438粉丝 173原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值