如何使用流来查找两个列表或数组乘法中的元素对

Ank*_*ngh 20 java matrix-multiplication java-8 java-stream

我有两个数字列表,我想找到所有可能的数字对.例如,给定列表[1,2,3]和[3,4],结果应该是[(1,3),(1,4),(2,3),(2,4),(3) ,3),(3,4)].

我知道我可以使用for循环来做到这一点,但有没有更简洁的方法来使用Java 8流?

我试过以下但是我错过了一些东西,因为我得到了List<Stream<int[]>>而不是List<int[]>.

public static void main(String[] args) {
    List<Integer> list1 = Arrays.asList(1, 2, 3);
    List<Integer> list2 = Arrays.asList(3, 4);
    List<int[]> pairs = list1.stream().map(i -> list2.stream().map(j -> new int[] { i, j }))
            .collect(Collectors.toList());
    pairs.forEach(i -> {
            System.out.println("{" + i[0]+ "," + i[1]+ "}");
    });
}
Run Code Online (Sandbox Code Playgroud)

小智 15

使用flatMap()方法代替map(),它将流组合成一个.参考:map()和flatMap()以及flatMap()示例之间的区别

  • 在这里提供这些信息,而不是隐藏在链接后面 (5认同)
  • @BoristheSpider:是的. (2认同)

JB *_*zet 14

你只需要更换你的第一个map()flatMap().


Don*_*aab 14

这是一个使用IntStream两个int数组作为源而不是使用的解决方案List<Integer>.我想看看是否有可能解决这个问题而不用拳击int作为一个Integer.

int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<IntIntPair> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
        IntStream.of(two).mapToObj(j -> PrimitiveTuples.pair(i, j)).forEach(list::add));
System.out.println(list);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法使用flatMap,IntStream因为它返回一个IntStream.没有flatMapToObj目前IntStream,这是此处将需要的东西.所以我用了forEach.

IntIntPairPrimitiveTuples班我从使用Eclipse的集合,因为他们把它简单到只输出列表作为字符串.您可以int[]像在解决方案中一样使用它.代码如下所示.

List<int[]> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
        IntStream.of(two).mapToObj(j -> new int[]{i, j}).forEach(list::add));
Run Code Online (Sandbox Code Playgroud)

在Eclipse Collections的8.1版本中(将于3月中旬发布),现在flatCollect库中的所有原始容器都有一个方法可用于解决此问题.这基本上做了一个flatMapToObj方法IntStream应该做的事情.

IntList a = IntLists.mutable.with(1, 2, 3);
IntList b = IntLists.mutable.with(3, 4);
List<IntIntPair> result =
        a.flatCollect(
                i -> b.collect(j -> PrimitiveTuples.pair(i, j)),
                Lists.mutable.empty());
System.out.println(result);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
Run Code Online (Sandbox Code Playgroud)

更新:

正如Boris the Spider的评论所指出的那样,forEach解决方案不会是线程安全的,如果IntStream是的话会破坏parallel.以下解决方案应该以串行或并行方式工作.我很高兴,这是指出,因为我还没有想过做一个mapToObjIntStream再接着一个flatMap.

int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<int[]> list = IntStream.of(one).parallel()
        .mapToObj(i -> IntStream.of(two).mapToObj(j -> new int[]{i, j}))
        .flatMap(e -> e)
        .collect(Collectors.toList());
list.stream().map(e -> "{" + e[0] + "," + e[1] + "}").forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

注意:我是Eclipse Collections的提交者.

  • @BoristheSpider非常好.我添加了一个应该以串行或并行方式工作的更新.谢谢你指出这一点. (2认同)