Java 8流 - 修改组中的所有元素

Oce*_*nic 5 java java-8 java-stream

我有一组A类对象

class A {
    String code;
    long timestamp;
    long largestTimestamp;
}
Run Code Online (Sandbox Code Playgroud)

我必须为每个对象填充maximumTimestamp字段(具有相同代码的对象组中的最大"timestamp"值).我可以通过以下两个步骤完成此操作 -

Map<String, Long> largestTimestampMap = list.stream().collect(Collectors.toMap(A::getCode, A::getTimestamp, Long::max));
list.forEach(a -> a.setLargestTimestamp(largestTimestampMap.get(a.getCode())));
Run Code Online (Sandbox Code Playgroud)

有没有办法将这些组合成一个流链?

Ous*_* D. 4

是的,您可以将它们组合成一个管道,如下所示:

list.stream()
     .map(a -> new A(a.getCode(), a.getTimestamp(),
                list.stream()
                    .filter(b -> a.getCode().equals(b.getCode()))
                    .mapToLong(A::getTimestamp)
                    .max().getAsLong()))           
     .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

或者,如果您想避免创建新列表,而是像示例中那样修改现有列表,则使用replaceAll

list.replaceAll(a -> new A(a.getCode(), a.getTimestamp(),
                        list.stream()
                                .filter(b -> a.getCode().equals(b.getCode()))
                                .mapToLong(A::getTimestamp)
                                .max().getAsLong()));
Run Code Online (Sandbox Code Playgroud)

但是,我建议避免这种方法:

1)因为它的性能比当前的实现更差,所以该解决方案需要再次迭代list其中forEach的元素。而您所展示的地图方法只需要一次get调用,而且我们都知道在地图中查找的速度有多快。

2)有更多的代码。

是的,您可以将中间操作内的代码重构map为一个方法,使其看起来更短,但最终它仍然更长。

有时,最好的方法需要两条或更多条单独的线,在这种情况下,最好继续采用您的方法。