我有一个Class A的对象
class A {
String code;
long timestamp;
long largestTimestamp;
}
我必须为每个对象填充最大的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())));
有没有办法将它们组合成单个流链?
答案 0 :(得分: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());
或者如果您想避免创建新列表,而是像示例中那样修改现有列表,则使用replaceAll
:
list.replaceAll(a -> new A(a.getCode(), a.getTimestamp(),
list.stream()
.filter(b -> a.getCode().equals(b.getCode()))
.mapToLong(A::getTimestamp)
.max().getAsLong()));
但是,我建议避免这种方法:
1),因为它的性能比当前的实现要差,因此此解决方案要求再次遍历list
中的forEach
元素。而您所展示的Map方法只需要一个get
调用,我们都知道在地图中查找的速度有多快。
2)还有更多代码。
是的,您可以将map
中间操作中的代码重构为一种方法,以使其看起来更短,但最终仍然更长。
有时候最好的方法需要两行或更多行,在这种情况下,最好继续使用您的方法。
答案 1 :(得分:3)
您可能只是在寻找(如果为每个对象填充maximumTimestamp字段意味着为整个列表保存相同的largestTimeStamp
):
// find the largest timestamp
long largestTimeStamp = list.stream()
.mapToLong(A::getTimestamp)
.max()
.orElse(Long.MIN_VALUE);
// iterate through the list to set its value
list.forEach(a -> a.setLargestTimestamp(largestTimeStamp));
如果必须在一行代码下执行此操作,则可以使用(已编辑,以与Aomine在注释中阐明的现有代码保持一致):
List<A> output = list.stream()
.map(a -> new A(a.getCode(), a.getTimestamp(),
list.stream().filter(b -> a.getCode().equals(b.getCode()))
.mapToLong(A::getTimestamp).max().orElse(a.getTimestamp())))
.collect(Collectors.toList());
答案 2 :(得分:0)
只是一个不同的想法,但您不能像下面所示那样构造A类
class A {
String code;
long timeStamp;
TimeStampWrapper timeStampWrapper;
}
class TimeStampWrapper {
long maxTimeStamp;
long minTimeStamp;
...
}
使用这种方法,您只需要遍历1个流,而只需一次设置操作即可设置maxTimeStamp,minTimeStamp等。