ulaşmak istediğiniz görev gruplama ne oldukça farklıdır. groupingBy
Stream
mertebesinde sitesindeki elemanları ancak Map
ilgili ‘sınıflandırıcı Function
‘in sonuç için uygulanan algoritması dayanmaz. Ne istiyorsun
biri List
öğesine ortak özellik değeri olan komşu öğeleri kat etmektir. Aynı özellik değerine sahip tüm öğelerin kümelenmesini garanti edebildiğiniz sürece, bu özelliğe göre Stream
numaralı ürüne sahip olmanız bile gerekli değildir.
Belki de bir azalma olarak bu görevi formüle etmek mümkündür ama bana çıkan yapı çok karmaşık görünüyor.
Bu özellik için doğrudan destek
Stream
s ekleniyor sürece, bir yineleyici dayalı yaklaşım benim için en pragmatik görünüyor
:
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
katlanmış iyi uygulayarak ortaya konabilir çıkan tembel doğa o sonsuz akışa a katkıda
Folding.foldBy(Stream.iterate(0, i->i+1), i->i>>4)
.filter(e -> e.getKey()>5)
.findFirst().ifPresent(e -> System.out.println(e.getValue()));
Nasıl tembel olursun gruplama ölçütü? Akışta yer alan nesnenin bazı özelliklerini gruplamak için, Akıştaki tüm öğeler üzerinde yineleme yapmanız gerekir. – Eran
"Hatlarını gruplamak" ile ne demek istiyorsun? Stream 'groupBy' yöntemi gibi binning mi demek istiyorsunuz yoksa toplu olarak bir seferde birden çok satır okumayı mı kastediyorsunuz? – dkatzel
Yorumlarınız için teşekkürler, soruya bir UPDATE ekledi. –