[英]Should I use Java 8 Streams Api to combine two Collections?
我有這種情況,似乎Java 8 Streams API會有所幫助,但我不完全確定它是怎么回事。
從兩個集合具有鮮明的元素類型,我想建立第三集合的元素是從兩個集合元素的所有可能的對 。 基本上:
兩種截然不同的元素類型......
public class A {}
public class B {}
As和Bs的“配對”。
public class Pair {
private A a;
private B b;
public Pair(A a, B b){
this a = a;
this b = b;
}
}
使用舊式java.util.Collection
API進行的“ 組合 ”:
public Collection<Pair> combine(Collection<A> as, Collection<B> bs){
Collection<Pair> pairs = new ArrayList();
foreach(A a: as){
foreach(B b: bs){
Pair pair = new Pair(a,b);
pairs.add(pair);
}
}
return pairs;
}
結果對集合中的排序並不重要。 因此,可以創建Pair的每個實例並將其並行添加到結果集合中。 我怎么能實現這個目標?
我能想到的最好的就是使用Streams版本的foreach
:
as.foreach(
a -> {
bs.foreach(
b -> {
Pair pair = new Pair(a,b);
pairs.add(pair);
}
}
);
為簡化起見,這個例子是微不足道的。 類Pair
是將兩個元素處理成第三個元素(即java.util.function.BiFunction
)的示例,將它們添加到Collection
只是可變縮減的一個示例。
有更優雅的方式嗎? 或者更可取的是,在效率方面以更有利可圖的方式? 就像是
BiFunction<A,B,Pair> combinator = Pair::new; //or any other function f(a,b)=c;
Stream<Pair> pairStream =
Streams.unknownElegantMethod(as.stream(), bs.stream(), combinator);
我希望我沒有任何愚蠢的錯別字,但基本上你可以做的是:
List<Pair> list = as
.stream()
.flatMap(a -> bs.stream().map (b -> new Pair(a,b)))
.collect (Collectors.toList());
as
創建一個Stream<A>
。 a
實例 bs
的Stream<B>
b
映射到一對(a,b)
如果您願意使用第三方庫,則可以使用Eclipse Collections Sets.cartesianProduct()
。 這將要求你的a和b都是套裝。 Eclipse Collections具有內置的Pair
類型,因此您無需創建它。
public class A {}
public class B {}
public List<Pair<A, B>> combine(Set<A> as, Set<B> bs)
{
return Sets.cartesianProduct(as, bs).toList();
}
如果A和B的都沒有設置,那么你可以使用一個CollectionAdapter
flatCollect
和collect
,這相當於flatMap
和map
上的Stream
。
public Collection<Pair<A, B>> combine(Collection<A> as, Collection<B> bs)
{
MutableCollection<B> adaptB = CollectionAdapter.adapt(bs);
return CollectionAdapter.adapt(as)
.flatCollect(a -> adaptB.asLazy().collect(b -> Tuples.pair(a, b)));
}
使用Stream
另一個可能選項是為cartesianProduct
定義自己的Collector
。 這比其他Stream
解決方案更復雜,只有在代碼中使用過cartesianProduct
幾次才有用。
List<Pair<A, B>> pairs = as.stream().collect(cartesianProduct(bs));
public static <T1, T2> Collector<T1, ?, List<Pair<T1, T2>>>
cartesianProduct(Collection<T2> other)
{
return Collector.of(
ArrayList::new,
(list, a) -> list.addAll(
other.stream().map(b -> new Pair(a, b))).collect(Collectors.toList())),
(list1, list2) ->
{
list1.addAll(list2);
return list1;
},
Collector.Characteristics.UNORDERED
);
}
注意:我是Eclipse Collections的提交者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.