Should I use Java 8 Streams Api to combine two Collections?

前端 未结 2 554
清歌不尽
清歌不尽 2021-02-05 13:07

I have this situation where it seems that the Java 8 Streams API would be helpful, but I\'m not fully sure how it could be.

From two Collections with distinct element ty

相关标签:
2条回答
  • 2021-02-05 13:18

    If you're open to using a third-party library, you could use Eclipse Collections Sets.cartesianProduct(). This would require that your a's and b's are both Sets. Eclipse Collections has a Pair type built-in, so you wouldn't need to create it.

    public class A {}
    public class B {}
    
    public List<Pair<A, B>> combine(Set<A> as, Set<B> bs)
    {
        return Sets.cartesianProduct(as, bs).toList();
    }
    

    If your a's and b's are not Sets, then you could use a CollectionAdapter flatCollect and collect, which are equivalent to flatMap and map on 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)));
    }
    

    Another possible option using Stream would be to define your own Collector for cartesianProduct. This is more complex than the other Stream solution, and would only be useful if you used cartesianProduct a few times in your code.

    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
        );
    }
    

    Note: I am a committer for Eclipse Collections.

    0 讨论(0)
  • 2021-02-05 13:34

    I hope I don't have any silly typos, but basically what you can do is :

    List<Pair> list = as
                      .stream()
                      .flatMap(a -> bs.stream().map (b -> new Pair(a,b)))
                      .collect (Collectors.toList());
    
    1. First you create a Stream<A> from as.
    2. For each a instance
      2.1 Create a Stream<B> of bs
      2.2 Map each b to a pair of (a,b)
    3. Flatten all the pairs to a single Stream.
    4. Finally I collected them to a List, though you can choose other collections.
    0 讨论(0)
提交回复
热议问题