Eğer eklerseniz statik ithalatı için Stream.concat ve Stream.of aşağıdaki gibi ilk örnek yazılabilir:
Stream<Foo> stream = concat(stream1, concat(stream2, of(element)));
Genel adlarla statik yöntemlerin içe aktarılması, okunması ve bakımı zorlaşan kodlarla sonuçlanabilir ( ad alanı kirliliği ). Bu nedenle, daha anlamlı adlarla kendi statik yöntemlerinizi oluşturmak daha iyi olabilir . Ancak, gösteri için bu isme sadık kalacağım.
public static <T> Stream<T> concat(Stream<? extends T> lhs, Stream<? extends T> rhs) {
return Stream.concat(lhs, rhs);
}
public static <T> Stream<T> concat(Stream<? extends T> lhs, T rhs) {
return Stream.concat(lhs, Stream.of(rhs));
}
Bu iki statik yöntemle (isteğe bağlı olarak statik içe aktarmalarla birlikte), iki örnek aşağıdaki gibi yazılabilir:
Stream<Foo> stream = concat(stream1, concat(stream2, element));
Stream<Foo> stream = concat(
concat(stream1.filter(x -> x!=0), stream2).filter(x -> x!=1),
element)
.filter(x -> x!=2);
Kod şimdi önemli ölçüde daha kısadır. Ancak, okunabilirliğin iyileşmediğini kabul ediyorum. Başka bir çözüm daha var.
Birçok durumda, Toplayıcılar akışların işlevselliğini genişletmek için kullanılabilir . Alttaki iki Toplayıcı ile, iki örnek aşağıdaki gibi yazılabilir:
Stream<Foo> stream = stream1.collect(concat(stream2)).collect(concat(element));
Stream<Foo> stream = stream1
.filter(x -> x!=0)
.collect(concat(stream2))
.filter(x -> x!=1)
.collect(concat(element))
.filter(x -> x!=2);
İstediğiniz sözdizimi ve yukarıdaki sözdizimi arasındaki tek fark değiştirmek zorunda yani, (...) concat ile toplamak (concat (...)) . İki statik yöntem aşağıdaki gibi uygulanabilir (isteğe bağlı olarak statik içe aktarmalarla birlikte kullanılır):
private static <T,A,R,S> Collector<T,?,S> combine(Collector<T,A,R> collector, Function<? super R, ? extends S> function) {
return Collector.of(
collector.supplier(),
collector.accumulator(),
collector.combiner(),
collector.finisher().andThen(function));
}
public static <T> Collector<T,?,Stream<T>> concat(Stream<? extends T> other) {
return combine(Collectors.toList(),
list -> Stream.concat(list.stream(), other));
}
public static <T> Collector<T,?,Stream<T>> concat(T element) {
return concat(Stream.of(element));
}
Tabii ki bu çözümle birlikte belirtilmesi gereken bir dezavantaj var. toplama , akışın tüm öğelerini tüketen son bir işlemdir. Bunun üzerine, toplayıcı concat zincirde her kullanıldığında bir ara ArrayList oluşturur . Her iki işlemin de programınızın davranışı üzerinde önemli bir etkisi olabilir. Ancak, okunabilirlik performanstan daha önemliyse , yine de çok yararlı bir yaklaşım olabilir.