你想要實現的任務與分組完全不同。 groupingBy
不依賴於Stream
元素的順序,而是依據Map
的算法應用於分類器Function
的結果。
你想要的是將具有共同屬性值的相鄰項目摺疊成一個List
項目。甚至沒有必要通過該屬性對Stream
進行排序,只要您能保證所有具有相同屬性值的項目都被聚類。
也許有可能把這個任務作爲一個減少,但對我來說,最終的結構看起來太複雜了。
所以,除非此功能直接支持被添加到Stream
S,迭代器爲基礎的方法看起來最務實的對我說:
class Folding<T,G> implements Spliterator<Map.Entry<G,List<T>>> {
static <T,G> Stream<Map.Entry<G,List<T>>> foldBy(
Stream<? extends T> s, Function<? super T, ? extends G> f) {
return StreamSupport.stream(new Folding<>(s.spliterator(), f), false);
}
private final Spliterator<? extends T> source;
private final Function<? super T, ? extends G> pf;
private final Consumer<T> c=this::addItem;
private List<T> pending, result;
private G pendingGroup, resultGroup;
Folding(Spliterator<? extends T> s, Function<? super T, ? extends G> f) {
source=s;
pf=f;
}
private void addItem(T item) {
G group=pf.apply(item);
if(pending==null) pending=new ArrayList<>();
else if(!pending.isEmpty()) {
if(!Objects.equals(group, pendingGroup)) {
if(pending.size()==1)
result=Collections.singletonList(pending.remove(0));
else {
result=pending;
pending=new ArrayList<>();
}
resultGroup=pendingGroup;
}
}
pendingGroup=group;
pending.add(item);
}
public boolean tryAdvance(Consumer<? super Map.Entry<G, List<T>>> action) {
while(source.tryAdvance(c)) {
if(result!=null) {
action.accept(entry(resultGroup, result));
result=null;
return true;
}
}
if(pending!=null) {
action.accept(entry(pendingGroup, pending));
pending=null;
return true;
}
return false;
}
private Map.Entry<G,List<T>> entry(G g, List<T> l) {
return new AbstractMap.SimpleImmutableEntry<>(g, l);
}
public int characteristics() { return 0; }
public long estimateSize() { return Long.MAX_VALUE; }
public Spliterator<Map.Entry<G, List<T>>> trySplit() { return null; }
}
所得到的摺疊Stream
可以最好的應用表現出的懶性質它無限流:
Folding.foldBy(Stream.iterate(0, i->i+1), i->i>>4)
.filter(e -> e.getKey()>5)
.findFirst().ifPresent(e -> System.out.println(e.getValue()));
哪有你做得很懶通過...分組?爲了對流中包含的對象的某些屬性進行分組,您必須遍歷流中的所有元素。 – Eran 2014-09-03 20:27:31
你是什麼意思的「分組線」?你的意思是像Stream'groupBy'方法裝倉,還是你的意思是批量讀取多行? – dkatzel 2014-09-03 20:29:27
感謝您的意見,增加了一個更新的問題。 – 2014-09-03 21:13:12