1. Обзор
В этом уроке мы узнаем, как получить пересечение двух List
s .
Как и многое другое, это стало намного проще благодаря внедрению потоков в Java 8 .
2. Пересечение двух списков строк
Давайте создадим два List
s из String
с некоторым пересечением — оба содержат дублирующиеся элементы:
List<String> list = Arrays.asList("red", "blue", "blue", "green", "red");
List<String> otherList = Arrays.asList("red", "green", "green", "yellow");
А теперь определим пересечение списков с помощью потоковых методов :
Set<String> result = list.stream()
.distinct()
.filter(otherList::contains)
.collect(Collectors.toSet());
Set<String> commonElements = new HashSet(Arrays.asList("red", "green"));
Assert.assertEquals(commonElements, result);
Во-первых, мы удаляем повторяющиеся элементы с разными
. Затем мы используем фильтр
для выбора элементов, которые также содержатся в otherList
.
Наконец, мы преобразуем наш вывод с помощью Collector
. Пересечение должно содержать каждый общий элемент только один раз. Порядок не должен иметь значения, поэтому toSet
— самый простой выбор, но мы также можем использовать toList
или другой метод сбора.
Дополнительные сведения см. в нашем руководстве по коллекторам Java 8 .
3. Пересечение списков пользовательских классов
Что, если наши List
содержат не String
, а экземпляры пользовательского класса, который мы создали? Ну, пока мы следуем соглашениям Java, решение с потоковыми методами будет прекрасно работать для нашего пользовательского класса.
Как метод contains
решает, появляется ли конкретный объект в списке? На основе метода равных .
Таким образом, мы должны переопределить метод equals
и убедиться, что он сравнивает два объекта на основе значений соответствующих свойств.
Например, два прямоугольника равны, если их ширина и высота равны.
Если мы не переопределяем метод equals
, наш класс использует реализацию equals
родительского класса. В конце дня, вернее, в цепочке наследования выполняется метод equals
класса Object .
Тогда два экземпляра равны, только если они ссылаются на один и тот же объект в куче. ``
Для получения дополнительной информации о методе equals
см. нашу статью о контрактах Java equals()
и hashCode()
.
4. Вывод
В этой быстрой статье мы увидели, как использовать потоки для вычисления пересечения двух списков. Есть много других операций, которые раньше были довольно утомительными, но довольно простыми, если мы знаем, как работать с Java Stream API. Взгляните на наши дальнейшие руководства с потоками Java здесь .
Примеры кода доступны на GitHub .