Java实现累加器类,提供Collector

2024-05-17

A Collector具有三种通用类型:

public interface Collector<T, A, R>

With A being 归约操作的可变累积类型(通常隐藏为实现细节).

如果我想创建自定义收集器,我需要创建两个类:

  • 一种用于自定义累积类型
  • 一个用于自定义收集器本身

是否有任何库函数/技巧可以采用累积类型并提供相应的收集器?

简单的例子

这个例子非常简单地说明了这个问题,我知道我可以使用reduce对于这种情况,但这不是我要找的。这里有一个更复杂的例子 https://stackoverflow.com/a/74401856/7424948在这里分享会使问题太长,但这是相同的想法。

假设我想收集流的总和并将其作为String.

我可以实现我的累加器类:

public static class SumCollector {
   Integer value;

    public SumCollector(Integer value) {
        this.value = value;
    }

    public static SumCollector supply() {
        return new SumCollector(0);
    }

    public void accumulate(Integer next) {
       value += next;
    }

    public SumCollector combine(SumCollector other) {
       return new SumCollector(value + other.value);
    }

    public String finish(){
        return Integer.toString(value);
    }
}

然后我可以创建一个Collector从这个班级:

Collector.of(SumCollector::supply, SumCollector::accumulate, SumCollector::combine, SumCollector::finish);

但我觉得奇怪的是,它们都引用了另一个类,我觉得有更直接的方法来做到这一点。

我能做的就是只保留一门课implements Collector<Integer, SumCollector, String>但每个函数都会被重复(supplier()会回来SumCollector::supply, etc).


不需要将函数实现为容器类的方法。

这就是这种总和收集器的典型实现方式

public static Collector<Integer, ?, Integer> sum() {
    return Collector.of(() -> new int[1],
        (a, i) -> a[0] += i,
        (a, b) -> { a[0] += b[0]; return a; },
        a -> a[0],
        Collector.Characteristics.UNORDERED);
}

但是,当然,您也可以将其实现为

public static Collector<Integer, ?, Integer> sum() {
    return Collector.of(AtomicInteger::new,
        AtomicInteger::addAndGet,
        (a, b) -> { a.addAndGet(b.intValue()); return a; },
        AtomicInteger::intValue,
        Collector.Characteristics.UNORDERED, Collector.Characteristics.CONCURRENT);
}

您首先必须为您的收集器找到合适的可变容器类型。如果不存在这样的类型,则必须创建自己的类。这些函数可以实现为对现有方法的方法引用或 lambda 表达式。

对于更复杂的例子,我不知道是否有合适的现有类型来容纳int and a List,但你可能会用盒装的Integer, 像这样

final Map<String, Integer> map = …
List<String> keys = map.entrySet().stream().collect(keysToMaximum());
public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
    return Collector.of(
        () -> new AbstractMap.SimpleEntry<>(new ArrayList<K>(), Integer.MIN_VALUE),
        (current, next) -> {
            int max = current.getValue(), value = next.getValue();
            if(value >= max) {
                if(value > max) {
                    current.setValue(value);
                    current.getKey().clear();
                }
                current.getKey().add(next.getKey());
            }
        }, (a, b) -> {
            int maxA = a.getValue(), maxB = b.getValue();
            if(maxA <= maxB) return b;
            if(maxA == maxB) a.getKey().addAll(b.getKey());
            return a;
        },
        Map.Entry::getKey
    );
}

但是您也可以创建一个新的专用容器类作为临时类型,在特定收集器之外不可见

public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
    return Collector.of(() -> new Object() {
        int max = Integer.MIN_VALUE;
        final List<K> keys = new ArrayList<>();
    }, (current, next) -> {
        int value = next.getValue();
        if(value >= current.max) {
            if(value > current.max) {
                current.max = value;
                current.keys.clear();
            }
            current.keys.add(next.getKey());
        }
    }, (a, b) -> {
        if(a.max <= b.max) return b;
        if(a.max == b.max) a.keys.addAll(b.keys);
        return a;
    },
    a -> a.keys);
}

要点是,您不需要创建一个新的命名类来创建Collector.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java实现累加器类,提供Collector 的相关文章

  • 是否可以在 Spring Batch 中结合分区和并行步骤?

    我只是想知道它在 Spring Batch 中可行吗 Step1Step2 流程 gt 流程1 流程2 流程3 Step3 其中每个flow1 gt 划分为 5 个 GridSizeflow2 gt 划分为 5 个 GridSizeflow
  • Spring控制器是线程安全的吗

    我遇到了这个控制器示例 想知道它是否是线程安全的 我特别想知道 gson 实例变量 import org springframework stereotype Controller import org springframework we
  • 检查双精度值的等于和不等于条件

    我在比较两者时遇到困难double values using and 我创建了 6 个双变量并尝试进行比较If健康 状况 double a b c d e f if a b c d e f My code here in case of t
  • 有没有好的方法来解析用户代理字符串?

    我有一个Java接收模块User Agent来自最终用户浏览器的字符串的行为需要略有不同 具体取决于浏览器类型 浏览器版本甚至操作系统 例如 FireFox 7 0 Win7 Safari 3 2 iOS9 我明白了User Agent由于
  • Java:从元素创建 DOM 元素,而不是文档

    如您所知 在 Java 中创建 Dom 元素的正确方法是执行以下操作 import org w3c dom Document import org w3c dom Element Document d Element e e d creat
  • Android - 除了普通 SSL 证书之外还验证自签名证书

    我有一个通过 SSL 调用 Web 服务的 Android 应用程序 在生产中 我们将拥有由受信任的 CA 签名的普通 SSL 证书 但是 我们需要能够支持自签名证书 由我们自己的 CA 签名 我已经成功实施了接受自签名证书的建议解决方案
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • Java替换特定字符

    这是我在这个网站上的第一个问题 所以我会尽量不要成为一个十足的菜鸟 我目前正在用java 创建刽子手游戏 所以我问你的问题是我们是否被赋予了 幽灵 这个词 并将 Ghost 替换为 hiddenWord ghost length for i
  • 想要开发像 Facebook 这样的网站 - 处理数百万个请求 - 高性能 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想用 Java 开发一个像 Fac
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • 打印包含 JBIG2 图像的 PDF

    请推荐一些库 帮助我打印包含 JBIG2 编码图像的 PDF 文件 PDFRenderer PDFBox别帮我 这些库可以打印简单的 PDF 但不能打印包含 JBIG2 图像的 PDF PDFRenderer尝试修复它 根据 PDFRedn
  • 覆盖 MATLAB 默认静态 javaclasspath 的最佳方法

    MATLAB 配置为在搜索用户可修改的动态路径之前搜索其静态 java 类路径 不幸的是 静态路径包含相当多非常旧的公共库 因此如果您尝试使用新版本 您可能最终会加载错误的实现并出现错误 例如 静态路径包含 google collectio
  • OpenJDK 版本控制

    上下文 我想确保我们系统上安装的 Java 不受 CVE 2022 21449 的影响 java version 给出 openjdk version 11 0 7 2020 04 14 LTS OpenJDK Runtime Enviro
  • 如何在android sdk上使用PowerMock

    我想为我的 android 项目编写一些单元测试和仪器测试 然而 我遇到了一个困扰我一段时间的问题 我需要模拟静态方法并伪造返回值来测试项目 经过一些论坛的调查 唯一的方法是使用PowerMock来模拟静态方法 这是我的 gradle 的一
  • 来自客户端的超时 Web 服务调用

    我正在使用 RestEasy 客户端调用网络服务 一项要求是 如果调用运行时间超过 5 秒 则中止 超时调用 我如何使用 RestEasy 客户端实现这一目标 我只看到服务器端超时 即如果在一定时间内未完成请求 Rest Easy 网络服务
  • 从java中的字符串数组中删除空值

    java中如何从字符串数组中删除空值 String firstArray test1 test2 test4 我需要像这样没有 null 空 值的 firstArray String firstArray test1 test2 test4
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • MongoDB Java 驱动程序:MongoCore 驱动程序与 MongoDB 驱动程序与 MongoDB 异步驱动程序

    MongoDB Java 驱动程序有三种不同的驱动程序选项 核心驱动 MongoDB 驱动程序 MongoDB 异步驱动程序 The 驱动程序描述页面 https docs mongodb org ecosystem drivers jav

随机推荐