java stream api-将Stream <list <pair <a,b =“” >>>更改为Pair <list <a>,List <b >>

时间:2018-07-13 09:49:11

标签: java java-stream

如何将ARG TARGETOS ENV TARGETOS ${TARGETOS} # do things based on TARGETOS arg # RUN if [ ${TARGETOS} = "windowsservercore-1803" ]; then \ 更改为Stream<List<Pair<A, B>>>? 我是通过以下方式完成的:

1。使用Pair<List<A>, List<B>>收集collect(Collectors.toList())结果

2。列出列表结果并将List<Pair<A, B>>A s添加到两个单独的列表中

3。创建一个新的B

但是我对仍在流中完成此操作感到非常偏执。 需要帮忙。谢谢。

3 个答案:

答案 0 :(得分:2)

要在Stream本身中获得想要的结果,可以使用reduce()

final Pair<List<A>, List<B>> result = stream
    .map(s -> {
      Pair<List<A>, List<B>> p = new Pair<>(new ArrayList<>(), new ArrayList<>());
      p.getKey().add(s.getKey());
      p.getValue().add(s.getValue());
      return p; 
    })
    .reduce((pairA, pairB) -> {
      pairA.getKey().addAll(pairB.getKey());
      pairA.getValue().addAll(pairB.getValue());
      return pairA;
    })
    .get();

但是,更优雅的解决方案是遍历您的Stream并填写两个列表,最后创建Pair,如下所示:

    final Stream<Pair<A, B>> stream = // your stream

    final List<A> listA = new ArrayList<>();
    final List<B> listB = new ArrayList<>();

    stream.forEach(p -> {
        listA.add(p.getKey());
        listB.add(p.getValue());
    });

    final Pair<List<A>, List<B>> result = new Pair<>(listA, listB);

取决于您为什么要将其转换为流内的Pair

编辑:只需注意,使用第一个示例,您将为初始Stream中的每个元素创建很多新的对象实例。这远非最佳解决方案。但是,如果您想在Stream中实现这一目标,我看不到其他选择。

答案 1 :(得分:1)

  
      
  1. 使用collect(Collectors.toList())收集List<Pair<A, B>>结果
  2.   

您可以编写 custom 收集器,使用Collector.of()(在本示例中为 javafx.util.Pair ):

  List<Pair<A, B>> pairs = // list of Pait
  Pair<List<A>,List<B>> pairOfLists = pairs.stream()
            .collect(
                    Collector.of(
                            //init accumulator
                            () -> new Pair<>(
                                     new ArrayList<>(),
                                     new ArrayList<>()
                            ), 
                            //processing each element
                            (pairOfLists, pair) -> {
                                pairOfLists.getKey().add(pair.getKey());
                                pairOfLists.getValue().add(pair.getValue());
                            },
                            //confluence of two accumulators in parallel execution
                            (pairOfLists1, pairOfLists2) ->{
                                pairOfLists1.getKey().addAll(pairOfLists2.getKey());
                                pairOfLists1.getValue()addAll(pairOfLists2.getValue());
                                return pairOfLists1;
                            }
                    )
            );
  

考虑到the three-argument version of Stream.collect()的存在,这使得Collector.of()变得过时,并且对于此类用例而言,合并器更简单。

  Pair<List<A>, List<Integer>> p2 = p.stream()
            .collect(
                    () -> new Pair<>(
                            new ArrayList<>(),
                            new ArrayList<>()
                    ),
                    (pairOfLists, pair) -> {
                        pairOfLists.getKey().add(pair.getKey());
                        pairOfLists.getValue().add(pair.getValue());
                    },
                    (pairOfLists1, pairOfLists2) -> {
                        pairOfLists1.getKey().addAll(pairOfLists2.getKey());
                        pairOfLists1.getValue().addAll(pairOfLists2.getValue());
                    }
            );

答案 2 :(得分:0)

这是最直接的解决方案,但有效,我发现:

Pair<List<T1>, List<T2>> target = new Pair<>(
    pairStream.stream().map(i -> i.getT1()).collect(Collectors.toList()),
    pairStream.stream().map(i -> i.getT2()).collect(Collectors.toList())
);

我假设Pair类具有构造函数public Pair(T1 t1, T2 t2)

我不知道有任何解决方案能够使用单个流返回期望的结果。