【发布时间】:2019-02-25 01:54:48
【问题描述】:
我有以下两种调用收集操作的形式,都返回相同的结果,但我仍然不能完全依赖方法引用并且需要一个 lambda。
<R> R collect(Supplier<R> supplier,
BiConsumer<R,? super T> accumulator,
BiConsumer<R,R> combiner)
为此考虑以下由 100 个随机数组成的流
List<Double> dataList = new Random().doubles().limit(100).boxed()
.collect(Collectors.toList());
1) 以下示例使用纯 lambdas
Map<Boolean, Integer> partition = dataList.stream()
.collect(() -> new ConcurrentHashMap<Boolean, Integer>(),
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, (map, map2) ->
{
map2.putAll(map);
});
2) 以下尝试使用方法引用,但第二个参数仍然需要 lambda
Map<Boolean, Integer> partition2 = dataList.stream()
.collect(ConcurrentHashMap<Boolean, Integer>::new,
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, Map::putAll);
如何在 java 8 中重写 collect 方法的第二个参数,以在本示例中使用方法引用而不是 lambda?
System.out.println(partition.toString());
System.out.println(partition2.toString());
{false=55, true=45}
{false=55, true=45}
【问题讨论】:
-
为什么是
map2.putAll(map)?应该是map.putAll(map2)。看看Java 9 docs。此外,您不能对第二个参数使用方法引用,因为您有条件运算符(顺便说一句,这是不必要的,x < 0.5就足够了)和初始1作为放入地图的值是给定键没有条目。 -
感谢您的建议,我已经测试过并且使用 map.putAll(map2) 效果很好。那么除了合并操作之外,有没有办法在 x
-
使用 lambda 有什么问题?当参数的数量和类型不匹配时,您不能使用方法引用。在这种情况下,
merge需要 3 个参数:键、初始值和合并二元运算符,而累加器是一个BiConsumer,它接收映射和流的一个元素并且不返回任何内容。如果您创建一个接收映射和流元素的void方法,则可以将其用作方法引用。但我认为这毫无意义,lambda更具表现力,IMO -
putAll不是适合您的操作的正确合并函数,因为它只是覆盖现有映射而不是合并值。此外x < 0.5 ? Boolean.TRUE : Boolean.FALSE已过时。只需使用x < 0.5。也不需要ConcurrentMap。并且整个操作可以这么简单地执行:Map<Boolean, Long> partition2 = dataList.stream() .collect(Collectors.partitioningBy(x -> x < 0.5, Collectors.counting())); -
感谢 Holger 的回复,这比我尝试的所有方法都更加简洁易懂。我会接受它作为有效答案。
标签: dictionary merge java-8 collectors