Подскажите, есть массив, необходимо вывести два элемента, которые в сумме дают 10. Каким будет решение через stream?

int[] arr = {3, 4, 2, 7};
int x = 10;
for (int i = 0; i<arr.length; i++) {
           for(int j = i + 1; j<arr.length; j++){
               if(arr[i] + arr[j] == x){
                   System.out.println(arr[i] + " " + arr[j]);
               }
           }
        }

Ответы (1 шт):

Автор решения: Nowhere Man

Подобно решению с циклами следует сгенерировать целочисленный поток для индекса i, из которого можно будет сгенерировать поток для индекса j и соответственно отфильтровать пары индексов, отвечающих условию, затем применить flatMap и findFirst/findAny для получения результата в виде Optional<int[]>.

int[] arr = {3, 4, 2, 7};
int x = 10;
IntStream.range(0, arr.length - 1)
    .mapToObj(i -> IntStream.range(i + 1, arr.length)
        .filter(j -> arr[i] + arr[j] == x)
        .mapToObj(j -> new int[]{i, j})  // Stream<int[]>
    ) // Stream<Stream<int[]>>
    .flatMap(str -> str) // Stream<int[]>
    .findFirst() // Optional<int[]>
    .ifPresentOrElse(
        ix -> System.out.println(arr[ix[0]] + " + " + arr[ix[1]] + " == " + x), 
        () -> System.out.println("NOT FOUND")
    );
// -> 3 + 7 == 10

Однако оба представленных решения имеют квадратичную сложность,тогда как её можно упростить до O(N), правда без стримов и с использованием мапы, как показано в ответе на похожий вопрос:

public static int[] twoSum(final int target, int ... nums) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0, n = nums.length; i < n; i++) {
        int a = nums[i];
        int b = target - a;
        if (map.containsKey(b)) {
            return new int[]{map.get(b), i};
        }
        map.put(a, i); // запомнить меньший индекс
    }
    
    throw new RuntimeException("the pair is not found");
}
→ Ссылка