Как можно отфильтровать 2 колекции через Stream API, и в конечном итоге создать колекцию Обьектов исходя из данных

Method must return a list of NumberPair objects by the following rules:

the first element of the pair belongs to integerList1; the second element of the pair belongs to integerList2; both elements end with the same digit. Parameter:

integerList1 is a list of positive integers; integerList2 is a list of positive integers.

Proceed to NumberPair class and implement its content, it contains the following fields:

<value_1>, <value_2>.

Example

Input:

integerList1 = [1, 2, 33, 44] integerList2 = [11, 22, 13]

Output:

[ NumberPair(1, 11), NumberPair(2, 22), NumberPair(33, 13) ]

У меня получилось вот так:

List<String > first = integerList1.stream().map(x->x.toString()).collect(Collectors.toList());
    List<String > second = integerList2.stream().map(x->x.toString()).collect(Collectors.toList());


      List<String> list = Stream.concat(first.stream(), second.stream()).collect(Collectors.groupingBy(x->x.charAt(x.length()-1)))
                .entrySet().stream().filter(x->x.getValue().size() > 1).flatMap(x->x.getValue().stream()).collect(Collectors.toList());
       list.stream().mapToInt(x->Integer.parseInt(x)).mapToObj((x,y)->new NumberPair(x,y));

Входные значения я брал из условия.

  1. Для начала я создал 2 листа Стрингов что бы иметь возможноть взять последние элементы для сравнения.
  2. Создал поток из двух этих колекций.
  3. И сгрупировал по последним значениям
  4. Получил 1 поток из значений Map (где 1 элемент - это от 1 колекции и 2 - от 2 колекции) --вывод листа: [1, 11, 2, 22, 33, 13]

Проблемы:

  1. Как лучше можно отфильтровать 2 колекции сразу (ссылаясь на значения друг друга)?
  2. Как создать набор обьект (PairNumber) в условиях потока исходя с данных в потоке?
  3. Если есть какой-то более умный способ решения, буду вам благодарин)

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

Автор решения: Дмитрий

А зачем столько всего? Преобразование в Стринг и назад в Инт - недешевое с точки зрения скорости и ресурсов удовольствие. Может так:

    List<Integer> integerList1 = Arrays.asList(1, 2, 33, 44);
    List<Integer> integerList2 = Arrays.asList(11, 22, 13, 3);

    Map<Integer, List<Integer>> collect = integerList2.stream()
            .collect(Collectors.groupingBy(k -> k % 10));
    List<NumberPair> result = integerList1.stream()
            .filter(i -> collect.get(i % 10) != null)
            .map(i -> new NumberPair(i, collect.get(i % 10).get(0)))
            .collect(Collectors.toList());

Единственная проблема в том, что я не понимаю, как поступить, если несколько чисел заканчиваются на одинаковые цифры? Посему собираю вторую коллекцию в Map, там смотрите сами

→ Ссылка
Автор решения: Nowhere Man

Можно воспользоваться коллектором Collectors.collectingAndThen, в котором сперва следует получить простую мапу с ключом - остатком от деления на 10 Map<Integer, List<Integer>>, и затем преобразовать её значения в нужные объекты. При этом хорошо, чтобы был некий отдельный метод для преобразования списков в NumberPair.

Допустим, класс NumberPair определен как кортеж (record) с конструктором, принимающим список целых чисел:

public record NumberPair(Integer first, Integer second){
    NumberPair(List<Integer> list) {
        this(list.get(0), list.get(1));
    }
}

Тогда можно написать такой метод для произвольного числа списков:

public static List<NumberPair> convert(List<Integer> ... lists) {
    return Stream.of(lists)                     // Stream<List<Integer>>
        .flatMap(List::stream)                  // Stream<Integer>
        .collect(Collectors.collectingAndThen(
            Collectors.groupingBy(i -> i % 10), // Map<Integer, List<Integer>>
            (map) -> map.values()
                .stream()                       // Stream<List<Integer>>
                .filter(lst -> lst.size() == 2)
                .map(NumberPair::new)           // Stream<NumberPair>
                .collect(Collectors.toList())
        ));
}

Тест:

List<Integer> list1 = Arrays.asList(1, 2, 33, 44);
List<Integer> list2 = Arrays.asList(11, 22, 13);

System.out.println(convert(list1, list2));

Результат:

[NumberPair[first=1, second=11], NumberPair[first=2, second=22], NumberPair[first=33, second=13]]
→ Ссылка