如何从Java IntStream中的nested.forEach收集结果

如何从Java IntStream中的nested.forEach收集结果,java,arrays,loops,java-stream,Java,Arrays,Loops,Java Stream,我在玩游戏,试图用Java流解决这个“两个和”的问题,而不是使用命令式方法: Given nums = [2, 7, 11, 15], target = 18, Because nums[1] + nums[2] = 7 + 11 = 18, return [1, 2]. 这是我的部分工作代码。有人能帮忙解决吗?我就是不知道如何将它收集起来,作为原始int数组返回: class Solution { public int[] twoSum(int[] input, int targe

我在玩游戏,试图用Java流解决这个“两个和”的问题,而不是使用命令式方法:

Given nums = [2, 7, 11, 15], target = 18,
Because nums[1] + nums[2] = 7 + 11 = 18,
return [1, 2].
这是我的部分工作代码。有人能帮忙解决吗?我就是不知道如何将它收集起来,作为原始int数组返回:

class Solution { 
    public int[] twoSum(int[] input, int target) {
        IntStream.range(0,  input.length)
           .forEach(i -> {
               IntStream.range(0,  input.length)
                   .filter(j -> i != j && input[i] + input[j] == target)
                   .peek(t -> System.out.println(input[t]))
                   .findFirst();
               }
            );
        return null;
    }
}
这是上面的输出(来自peek):


正如我在评论中所说,流并不总是一个完美的解决方案。但是关于你的任务,看起来你需要一个成对的流。不幸的是,Java没有元组(比如Scala),这就是为什么我建议创建一个简单的
类的原因

class Pair {
    int i, j;
    public Pair(int i, int j) {
        this.i = i;
        this.j = j;
    }
}
然后,使用一组对进行操作

 IntStream.range(0,  input.length)
                .boxed()
                .flatMap(i -> IntStream.range(0,  input.length).boxed()
                                .map(j -> new Pair(i,j))
                )
                        .filter(p -> p.i != p.j)
                        .filter(p -> input[p.i] + input[p.j] == target)
                        .collect(toList());

对于通过索引驱动列表或数组的
循环,模拟嵌套的
的常见方法是使用
IntStream
flatMap

int[] input = {12, 7, 11, 15, 6, 2};
int target = 18;

List<List<Integer>> result = IntStream.range(0, input.length)
    .boxed()
    .flatMap(i -> IntStream.range(i + 1, input.length)
        .filter(j -> input[i] + input[j] == target)
        .mapToObj(j -> Arrays.asList(i, j)))
    .collect(Collectors.toList());

System.out.println(result); // [[0, 4], [1, 2]]
int[]input={12,7,11,15,6,2};
int目标=18;
列表结果=IntStream.range(0,input.length)
.boxed()
.flatMap(i->IntStream.range(i+1,input.length)
.filter(j->input[i]+input[j]==目标)
.mapToObj(j->Arrays.asList(i,j)))
.collect(Collectors.toList());
System.out.println(结果);//[[0, 4], [1, 2]]
请注意,您不需要使用
类来维护从内部流到外部流的状态,因为您可以对内部流应用所需的过滤器


此外,内部
IntStream
不需要在
0
上启动,因为您不希望结果中同时包含
[i,j]
[j,i]
(只需要其中一个)。因此,用
i+1
启动内部
IntStream
就足够了。

该问题应以时间复杂度O(n)来解决:

Map indexMap=IntStream.range(0,a.length).boxed().collect(Collectors.groupingBy(i->a[i]);
IntStream.range(0,a.length)
.boxed()
.filter(i->indexMap.containsKey(目标-a[i]))
.flatMap(i->indexMap.get(target-a[i]).stream().filter(j->iPair.of(i,j)))
.forEach(System.out::println);

循环和流方法是不同的。解决方案需要保留一些全局变量,但流通常使用无状态方法转换数据。可能流不是完成此任务的完美方法。谢谢。我能够让它与
import javafx.util.Pair一起工作。结果列表中有“重复的反向对”。只需过滤掉重复的内容。
int[] input = {12, 7, 11, 15, 6, 2};
int target = 18;

List<List<Integer>> result = IntStream.range(0, input.length)
    .boxed()
    .flatMap(i -> IntStream.range(i + 1, input.length)
        .filter(j -> input[i] + input[j] == target)
        .mapToObj(j -> Arrays.asList(i, j)))
    .collect(Collectors.toList());

System.out.println(result); // [[0, 4], [1, 2]]
Map<Integer, List<Integer>> indexMap = IntStream.range(0, a.length).boxed().collect(Collectors.groupingBy(i -> a[i]));

IntStream.range(0, a.length)
    .boxed()
    .filter(i -> indexMap.containsKey(target - a[i]))
    .flatMap(i -> indexMap.get(target - a[i]).stream().filter(j -> i < j).map(j -> Pair.of(i, j)))
    .forEach(System.out::println);