java - 在 Java 8 流中使用每个元素类型的特定消费者

标签 java java-8 java-stream

我有一个 Java 8 数字流:

Stream<Number> numbers = ...;

我想迭代流并根据每个元素的类型调用特定的使用者。 IE。对于 Integer我想调用 Consumer<Integer> 的元素, 对于 Long一个Consumer<Long>等等

forEach()方法,但这需要一个 Consumer<? super Number> ,要求该实现(通常是 Lambda 表达式)对确切类型本身进行 instanceof-switch。

就 API 而言,我基本上是在寻找这样的东西:

numbers.forEach( callbacks -> {
    callbacks.on( Integer.class, i -> { /* handle Integer */ } );
    callbacks.on( Long.class, l -> { /* handle Long */ } )
} );

是否有任何现有的 API 允许我以类似于此的方式为每个流元素子类型注册一个特定的消费者?

最佳答案

您确定不想只运行两次流吗?它将更具可读性。

但是如果你愿意,你可以像这样定义一个类型检查消费者:

public static<T> Consumer<Object> acceptType(Class<T> clazz, Consumer<? super T> cons) {
    return t -> {
        if (clazz.isInstance(t)) {
            cons.accept(clazz.cast(t));
        }
    };
}

然后您可以使用 andThen 组合多个消费者:

Consumer<Object> combined = acceptType(Integer.class, i -> ...)
                   .andThen(acceptType(Long.class, lng -> ...))

如果要隐藏andThen,可以定义

static<T> Consumer<T> doAll(Consumer<T>... consumers) {
    return Arrays.stream(consumers)
            .reduce(Consumer::andThen)
            .orElse(t -> {});
}

然后就变成了

nums.forEach(doAll(
            acceptType(Integer.class, i -> ...),
            acceptType(Long.class, lng -> ..),
            ...
));

关于java - 在 Java 8 流中使用每个元素类型的特定消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36180074/

相关文章:

java - 如何在 Java 中取消转义 HTML 字符实体?

Java8 流和类型转换

java - 将列表的字符串列表转换为整数列表

java - 如何重构 for 循环与服务调用流?

java - 使用 mahout 出现 NoClassDefFoundError

java - 通过 JProfiler 查找内存泄漏

java - 填写 list <?扩展 Foo>

java Stream map和mapToObj的区别

java - 如何从数组创建并行流?

java - Eclipse/Java 代码完成不起作用