Java-метод проверки, содержатся ли целые числа в списке в другом списке списка целых чисел

#java #list #algorithm #data-structures #java-8

#java #Список #алгоритм #структуры данных #java-8

Вопрос:

* В качестве предисловия я опубликовал аналогичный вопрос, но на этот раз результат, который я хочу, будет другим. Предположим, у нас есть человек по имени Боб, и у него есть список целых чисел, которые он записал:

 bobList = [10, 25, 30, 50]
  

Скажем, есть 3 других списка случайных целых чисел, которые были сгенерированы системой и помещены в 1 основной список:

 list1 = [1, 10, 20, 25, 33, 55]
list2 = [2, 3, 5, 6, 9, 30]
list3 = [25, 30, 50, 100]
List<List<Integer>> masterList = new ArrayList<>()
masterList.add(list1)
masterList.add(list2)
masterList.add(list3)
  

Можно предположить, что 3 списка чисел, сгенерированных системой, расположены в порядке от наименьшего к наибольшему, а список Боба также от наименьшего к наибольшему. Цель состоит в том, чтобы просмотреть список Боба и посмотреть, содержится ли каждое число, записанное Бобом, в каждом списке в главном списке. Я попробовал это с Java 11 с потоками, чтобы попытаться показать, принадлежит ли каждое целое число в списке Боба каждому из 3 списков, пытаясь вывести его следующим образом

 {10=[true, false, false], 25=[true, false, true], 30=[false, true, true] , 50=[false, false, true]}
  

Я думаю, что это будет что-то вроде списка Боба, но с каждым целым числом, которое он записал, является ключом, а значением является список логических значений, где каждый индекс является соответствующим списком, и если его значение true, то это число, которое написал Боб, находится в списке, и наоборот для false. Но проблема в том, что я новичок в программировании, и, на мой взгляд, вся эта структура данных и алгоритмы действительно мешают мне, и я застрял на этом в течение последнего дня. Может ли кто-нибудь опубликовать решение для этого, где результат будет выглядеть так, как описано? Или, если у вас есть лучшие рекомендации для вывода, который имеет более простой вид, я обязательно хочу его улучшить! Спасибо!

Обновление: я совершенно забыл добавить свою попытку, но я поиграл с этим фрагментом:

 List<Map<Boolean, List<Integer>>> test = bobList.stream()
       .map(list -> list.stream()
                        .collect(Collectors.partitioningBy(masterList::contains)))
       .collect(Collectors.toList());

test.forEach(System.out::println);     
  

Вывод выглядит примерно так:

 {false=[1,20,33,55], true=[10,25]}
{false=[2,3,5,6,9], true=[30]}
{false=[100], true=[25,30,50]}
  

Как вы можете видеть, этот способ сравнивает 3 списка в masterList с bobList и выводит его как false и true и разделяет те числа, которые есть в bobList, а какие нет. Тем не менее, я попытался перевернуть его и посмотреть, какие числа в bobList находятся в списках masterList, и вывести его так, как я хотел, но я просто застреваю и обхожусь с разными попытками

Частичное решение, которое у меня было, состояло в том, чтобы перейти от списка boblist к списку 1, используя :

 masterList.stream().map(l -> l.contains(i)).collect(Collectors.toList()))));
  

Но я не уверен, где взять соответствующий ключ для списка.

Обновление: Спасибо Хольгеру, я забыл, что вы можете использовать .collect() дважды

Комментарии:

1. Пожалуйста, добавьте свою текущую попытку, даже если она не работает; это показывает ваши собственные усилия.

2. Просто чтобы дать вам несколько условий поиска: вы ищете пересечение нескольких отсортированных наборов. Я не знаю, разрешено ли вам использовать наборы вместо списков или существуют ли другие ограничения для вашей задачи, но одним из способов было бы использовать что-то вроде [TreeSet ] ( docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util /… ) и его retainAll метод. (Однако в этом решении нет потоков).

3. Что вы пробовали до сих пор?

4. Я добавил свою попытку выше, пожалуйста, помогите мне, спасибо!

Ответ №1:

Попробуйте разбить проблему на этапы и реализовать каждый шаг! (Псевдокод очень помогает) 🙂 Я дам вам небольшую подсказку:

Ваша цель здесь — выполнить итерацию по списку bobList и проверить, содержит ли list1, list2 и list3 (путем итерации по Masterlist) целое число, и распечатать этот результат. Например, вы можете выполнить итерацию с помощью циклов for.

Как вы можете проверить, содержит ли список это целое число? Может ли помочь что-то вроде метода list.contains()?

Что касается вывода, вы можете выводить его как угодно, если он выглядит красиво и соответствует критериям. например, если вы хотите немного пофантазировать со своим выводом:

 10: |true|false|false|
  

Вы можете распечатать логическое значение сразу во время итераций внутри цикла for.

Ответ №2:

Если вы хотите сделать это с потоками, то решение состоит в том, чтобы передавать bobList и собирать поток в виде карты. Значения в map сами по себе могут быть сгенерированы потоковой masterList передачей и отображением в логическое значение, представляющее, находится ли ключ в связанном списке.

Собрать все это вместе:

 Map<Integer,List<Boolean>> result = bobList.stream()
    .collect(Collectors.toMap(
        i -> i,
        i -> masterList.stream().map(l -> l.contains(i)).collect(Collectors.toList()))));
  

По предложению Хольгера: l.contains(i) может быть заменен на Collections.binarySearch(l, i) >= 0 который ускоряет поиск, полагаясь на тот факт, что он предварительно отсортирован. Но если ваши списки не будут длинными или эта карта не будет создаваться много раз, я бы ожидал, что разница будет минимальной.

Вы также упоминаете в комментариях (а не в исходном вопросе), что хотите, чтобы порядок ключей сохранялся. Вы могли бы сделать это, явно используя LinkedHashMap .

Комментарии:

1. Отсутствуют некоторые закрывающие скобки. Кроме того, поскольку в OP указано, что списки гарантированно будут в порядке возрастания, вы можете заменить l -> l.contains(i) на l -> Collections.binarySearch(l, i)>=0 .

2.@IHaveAQuestion нет, чтобы получить результат по порядку, вам нужен a Map , который поддерживает порядок, т. Е. Collectors.toMap(i -> i, i -> masterList.stream().map(l -> l.contains(i)).collect(Collectors.toList()), (a,b) -> { throw new IllegalStateException("duplicate"); }, LinkedHashMap::new)) . binarySearch Использует отсортированную природу исходных списков, чтобы быть быстрее, чем линейный поиск, выполняемый List.contains .