![](/img/trans.png)
[英]Combine multiple `Collectors::groupBy` functions with Java Streams
[英]Combine multiple streams of events
假設我有N個數據事件流,我想將它們組合為一個,使用一些for排序(例如時間戳 )。 假設EventStream
定義為:
class EventStream{
Event peek();
Event next();
}
現在,我想獲取N個事件流,並將它們包裝在一個流中,這將強制執行排序。 但是,我不想簡單地遍歷所有流並將它們添加到priorityQueue
-我不希望內存中有所有事件,因為我很快就會用完堆空間。 我想要一種動態方法,其中每個next()
之后的合並流確定next()
一個事件應該是什么。 我每次可以掃描N個流,找出下一個值是什么,但是有沒有更好的方法?
您可以通過只偷看它們的頭部,並僅在需要時才這樣做,來避免對所有內容進行高速緩存並進行過多的查找。 我建議您編寫與MergedEventStream
似的MergedEventStream
:
public class MergedEventStream implements EventStream {
private ArrayList<EventStream> merged = new ArrayList<EventStream>();
private int nextIndex = -1;
public MergedEventStream(Collection<EventStream> toMerge) {
merged.addAll(toMerge);
findNext();
}
public Event peek() {
if (nextIndex == -1 && findNext() == false) {
throw new NoSuchElementException();
} else {
Event e = merged.get(nextIndex).peek();
return e;
}
}
public Event peek() {
if (nextIndex == -1 && findNext() == false) {
throw new NoSuchElementException();
} else {
Event e = merged.get(nextIndex).next();
findNext();
return e;
}
}
/**
* iterates over merged, and for each stream with an available event,
* adds it to a sorted TreeMap<Event, Integer> (sorting by any event field; integer
* is stream index in arrayList)
* if set is not empty, returns 'true', and sets nextIndex to the stream index
* otherwise, returns 'false', and sets nextIndex to -1
*/
private boolean findNext() {
// ...
}
}
通過將TreeMap保留為實例屬性並僅刷新從中提取的流,可以稍微提高效率。
使用MinHeap存儲每個事件流中的一個事件。
在next()
上,從堆中彈出頂部事件(具有最舊時間的值)。
然后從檢索該事件的同一EventStream中推送一個事件。
因此,MinHeap中的每個EventStream只會有一個Event。
您將需要將對EventStream的引用與事件一起存儲在MinHeap中。
此next()
實現將使用O(log n),其中“ n”是EventStreams的數量。
注意:預計EventStream已對事件進行了排序。 Next()始終返回最早的事件。
您的方法很好。 除非N大,否則應該可以。
如果N確實很大,則可以將每個流的第一個事件存儲在一個排序的集合中,並與它來自的流相關聯,並且每次從該排序的集合中刪除一個項目時,都將在它的流中添加下一個事件來自。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.