Сопоставление строк в двух списках в Java 8

#java #java-8 #java-stream

#java #java-8 #java-stream

Вопрос:

Вопрос прост и может быть решен тысячью способов. Но поскольку я изучаю Java 8, я хотел бы сделать это способом Java 8.

У меня есть два списка строк, например:

 List<String> list1 = Arrays.asList("A", "B", "C", "D");
List<String> list2 = Arrays.asList("A", "D", "E");
  

Я хочу взять первый элемент из list1 и проверить, присутствует ли строка в list2 и создать Map<Boolean, String> . Что-то вроде этого:

 Map<Boolean, String> resultMap = list1.stream().collect(partial -> Collectors.partitioningBy(list2.stream().filter(existing -> matchString(partial, existing))));

private static boolean matchString(String partial, String existing) {
    return partial.equals(existing);
}
  

Приведенный выше код содержит ошибку компиляции в matchString(partial, existing) :

Неправильный тип 1-го аргумента. Найдено: «, требуется: ‘java.lang.Строка’

Следует отметить несколько моментов: в моем реальном сценарии это не простой список строк, а более сложный объект, и этот объект не переопределяет метод equals or hashcode .

Я очень хорошо знаю, что это можно сделать разными способами. Но не мог бы кто-нибудь, пожалуйста, сообщить мне, как мы используем Collectors.partitioningBy в этом конкретном сценарии.

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

1. Вы не объяснили, что Map<Boolean, String> представляет. Все, что у нас есть, это фрагмент кода, который не компилируется.

2. Что сказал @shmosel: неясно, что должно представлять сопоставление. Как написано, сопоставление должно содержать не более двух элементов: True, сопоставленное со строковым значением, и False, сопоставленное со строковым значением. Я предполагаю, что сопоставление предназначено для ответа на вопрос, является ли конкретное значение из первого списка членом второго списка, и в этом случае, по крайней мере, сопоставление должно быть введено как Map<Строка, логическое значение> .

Ответ №1:

С помощью Collectors.partitioningBy вы можете получить Map<Boolean, List<String>> . Из partitioningBy документа:

Возвращает коллектор, который разделяет входные элементы в соответствии с Predicate и организует их в Map<Boolean, List<T>> .

В вашем случае:

 Map<Boolean, List<String>> map = list1.stream()
            .collect(Collectors.partitioningBy(list2::contains));
  

В случае более сложного объекта, который не переопределяет equals / hashcode , вы можете выполнить сравнение по некоторому определенному полю. Предполагая, что у вас есть что-то вроде:

 class ComplexObj {
    private String id;
    ...
}

Map<Boolean, List<ComplexObj>> map = list1.stream()
            .collect(Collectors.partitioningBy(obj -> list2.stream()
                    .map(ComplexObj::getId)
                    .anyMatch(id -> id.equals(obj.getId()))));
  

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

1. Спасибо, но `contains’ не будет работать, потому что hashcode и equals не переопределены

2. @RahulDevMishra в вашем вопросе говорится, что у вас есть два списка String . Если у вас действительно есть объекты без надлежащих реализаций hashCode / equals, вы должны включить это в свой вопрос, соответственно. в первую очередь вам не следует говорить о строках.

Ответ №2:

Найдите мою реализацию ниже, используя Collectors.partitioningBy. Я использую метод List.contains() для предиката, и он отлично работает. Пожалуйста, попробуйте поделиться отзывами / предложениями. Спасибо.

 package net.javapedia.streams;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class PartitioningByEx1 {

    public static void main(String[] args) {

        List<String> list1 = Arrays.asList("A", "B", "C", "D");
        List<String> list2 = Arrays.asList("A", "D", "E");

        list1.stream().collect(Collectors.partitioningBy(item -> list2.contains(item)))
                .forEach((key, val) -> System.out.println(key   "-->>"   val));
    }

}
  

Вывод программы:

Вывод