我有一个大型 Java 8 流 ( Stream<MyObject>
),其对象如下所示:
class MyObject {
private String string;
private Date timestamp;
// Getters and setter removed from brevity
}
我知道第 1 天的所有时间戳都将先于第 2 天的时间戳到达,但在每一天中,时间戳都可能乱序。我想对 MyObject
进行排序在 timestamp
中使用 Stream API 每天订购。由于 Stream 很大,我必须尽可能懒惰地执行此操作,即可以保留一天的 MyObject
在内存中,但不能容纳更多的东西。
我怎样才能做到这一点?
2017-04-29 更新:
一个要求是我想在排序后继续在同一个流上工作!我想要这样的东西(伪代码):
Stream<MyObject> sortedStream = myStreamUnsorted().sort(onADailyBasis());
最佳答案
我建议采用以下解决方案:
将流的每个值存储在 TreeMap 中,以便立即对其进行排序。作为键使用对象的时间戳。
Map<Date, MyObject> objectsOfTheDaySorted = new TreeMap<>();
我们需要知道最后必须从 map 中删除哪个对象。它只是一个对象,但存储它的成员必须(有效地)是最终的。所以我选择了一个简单的列表。
List<MyObject> lastObject = new ArrayList<>();
将当前日期设置为整数。
// just an example
int currentDay = 23;
使用谓词来确定 currentDay 和任何路过对象的日期是否不匹配。
Predicate<MyObject> predicate = myObject -> myObject.getTimestamp()
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate()
.getDayOfMonth() != currentDay;
现在流式传输您的流。使用 peek() 两次。首先要将对象放入 map 中。 其次覆盖列表中的对象。 使用 anyMatch() 作为终端操作并提交以前 创建谓词。一旦出现第一个匹配的对象 从第二天开始的标准,anyMatch() 终止流并返回 true。
stream.peek(myObject -> objectsOfTheDaySorted.put(myObject.getTimestamp(), myObject))
.peek(myObject -> lastObject.set(0, myObject))
.anyMatch(predicate);
现在您只需删除已经属于第二天因此不属于您的 map 的最后经过的对象。
objectsOfTheDaySorted.remove(lastObject.get(0).getTimestamp());
完成。您有一个已排序的对象 map ,它们都只属于一天。希望这符合您的期望。请在下面找到一个 block 中的完整代码,以便立即更好地复制它。
Map<Date, MyObject> objectsOfTheDaySorted = new TreeMap<>();
List<MyObject> lastObject = new ArrayList<>();
// just an example
int currentDay = 23;
Predicate<MyObject> predicate = myObject -> myObject.getTimestamp()
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate()
.getDayOfMonth() != currentDay;
stream.peek(myObject -> objectsOfTheDaySorted.put(myObject.getTimestamp(), myObject))
.peek(myObject -> lastObject.set(0, myObject))
.anyMatch(predicate);
objectsOfTheDaySorted.remove(lastObject.get(0).getTimestamp());
关于java - 每天对 Java 8 Stream API 中的实体进行延迟排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43571256/