Множественный цикл переноса кода в Java 8: это лучший способ? - PullRequest
0 голосов
/ 27 октября 2019

У меня есть следующий многократный цикл Java в старом стиле, который я хочу преобразовать в потоки Java 8:

    List<Integer> list1 = Arrays.asList(1,2,3);
    List<Integer> list2 = Arrays.asList(3,5,6);
    List<Integer> list3 = Arrays.asList(3,4,9);
    boolean match = true;

    int list1Size = list1.size();
    int list2Size = list2.size();

    for (int i = 0; i < list1Size; i++ ) {
        for (int j = 0; j < list2Size && i < list1Size; j++) {
            if (list2.get(j).equals(list1.get(i))) {
                if (list3.get(j).equals(list1.get(i))) {
                    System.out.println(list1.get(i));
                }
            }
        }
    }

(вывод: 3)

Лучший способ найтибыло:

    IntStream.range(0, list1Size).forEach(
            ix1 -> {
                    IntStream.range(0, list2.size()).forEach(
                            ix2 -> {
                                if (ix2 < list2.size() && ix1 < list1.size())
                                    if (list2.get(ix2).equals(list1.get(ix1))) {
                                        if (list3.get(ix2).equals(list1.get(ix1))) {
                                            System.out.println(list1.get(ix1));
                                        }
                                    }
                            }
                    );
            }
    );

, что не кажется мне слишком привлекательным ...

Обратите внимание, что я работаю с 3 списками, используя 2 цикла.

Есть лилучший способ?

Спасибо

Ответы [ 3 ]

0 голосов
/ 27 октября 2019

Вы можете сделать:

Set<Integer> set1 = new HashSet<>(list1);

IntStream.range(0, Math.min(list2.size(), list3.size()))
        .filter(i -> Objects.equals(list2.get(i), list3.get(i))) // check where index have the same value
        .mapToObj(list2::get) // get the value (as the values are equal could be also list3)
        .filter(set1::contains) // check if list1 contains the value
        .forEach(System.out::println);

Выход

3

Преобразование list1 в набор (set1) дает вам здоровую скоростьза счет повышения производительности запроса сдерживания (O(n) -> O(1)).

0 голосов
/ 27 октября 2019

Если позиция не важна, и вы используете вместо нее Set, это становится довольно тривиальным:

set1.retainAll(set2);
set1.retainAll(set3);

С потоками вы можете сделать:

set1.stream()
   .filter(set2::contains)
   .filter(set3::contains)
   .collect(Collectors.toList());
0 голосов
/ 27 октября 2019

Поскольку индекс элемента в первом List на самом деле не имеет значения, вы можете Stream по элементам list1 и искать элемент list1, который появляется как в list2, так и в элементах *1003*. list3 с тем же индексом:

Optional<Integer> result = 
    list1.stream()
         .filter(IntStream.range(0,list2.size())
                          .filter(i -> list2.get(i).equals(list3.get(i)))
                          .mapToObj(list2::get)
                          .collect(Collectors.toSet())::contains)
        .findFirst();

Или, если вы просто хотите напечатать первое совпадение:

list1.stream()
     .filter(IntStream.range(0,list2.size())
                      .filter(i -> list2.get(i).equals(list3.get(i)))
                      .mapToObj(list2::get)
                      .collect(Collectors.toSet())::contains)
     .limit(1)
     .forEach(System.out::println);

Конвейер IntStream генерирует Set всехэлементы, которые отображаются в list2 и list3 в одном индексе. filter ищет элементы list1, которые принадлежат этому Set.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...