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 的相关文章

  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐