Nếu bạn thêm nhập khẩu tĩnh cho Stream.concat và Stream.of , ví dụ đầu tiên có thể được viết như sau:
Stream<Foo> stream = concat(stream1, concat(stream2, of(element)));
Nhập phương thức tĩnh với tên chung có thể dẫn đến mã trở nên khó đọc và duy trì ( ô nhiễm không gian tên ). Vì vậy, có thể tốt hơn để tạo các phương thức tĩnh của riêng bạn với các tên có ý nghĩa hơn. Tuy nhiên, để trình diễn tôi sẽ gắn bó với cái tên này.
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));
}
Với hai phương thức tĩnh này (tùy chọn kết hợp với nhập tĩnh), hai ví dụ có thể được viết như sau:
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);
Mã bây giờ ngắn hơn đáng kể. Tuy nhiên, tôi đồng ý rằng khả năng đọc đã không được cải thiện. Vì vậy, tôi có một giải pháp khác.
Trong rất nhiều tình huống, Collector có thể được sử dụng để mở rộng chức năng của các luồng. Với hai Bộ sưu tập ở phía dưới, hai ví dụ có thể được viết như sau:
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);
Sự khác biệt duy nhất giữa cú pháp mong muốn của bạn và cú pháp ở trên là, bạn phải thay thế concat (...) bằng collat (concat (...)) . Hai phương thức tĩnh có thể được thực hiện như sau (tùy chọn được sử dụng kết hợp với nhập tĩnh):
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));
}
Tất nhiên có một nhược điểm với giải pháp này cần được đề cập. thu thập là một hoạt động cuối cùng tiêu thụ tất cả các yếu tố của luồng. Trên hết, concat concat tạo một ArrayList trung gian mỗi khi nó được sử dụng trong chuỗi. Cả hai hoạt động có thể có tác động đáng kể đến hành vi của chương trình của bạn. Tuy nhiên, nếu dễ đọc quan trọng hơn hiệu suất , nó vẫn có thể là một cách tiếp cận rất hữu ích.