Пересечение между двумя целочисленными массивами

Пересечение между двумя целочисленными массивами

1. обзор

В этом кратком руководстве мы рассмотрим, как использоватьcompute the intersection between two Integer arrays ‘a' и‘b'.

Мы также сосредоточимся на том, как обрабатывать повторяющиеся записи.

Для реализации мы будем использоватьStreams.

2. Предикат членства для массива

Пересечение двух наборов по определению является набором со всеми значениями из одного, которые также являются частью второго набора.

Поэтому нам нуженFunction или, скорее,Predicate, чтобы определить членство во втором массиве. ПосколькуList предоставляет такой метод из коробки, мы преобразуем его вList:

Predicate isContainedInB = Arrays.asList(b)::contains;

3. Строительство перекрестка

Чтобы создать результирующий массив, мы последовательно рассмотрим элементы первого набора и проверим, содержатся ли они также во втором массиве.  Затем мы создадим новый массив на основе этого.

Stream API предоставляет нам необходимые методы. First, we’ll create a Stream, then filter with the membership-Predicate and finally we’ll create a new array:

public static Integer[] intersectionSimple(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(Arrays.asList(b)::contains)
      .toArray(Integer[]::new);
}

4. Повторяющиеся записи

Поскольку массивы в Java не являются реализациейSet, мы сталкиваемся с проблемой дублирования записей во входных данных, а затем и в результате. Обратите внимание, что количество вхождений в результате зависит от вхождений в первом параметре.

Но для наборов элементы не должны встречаться несколько раз. We can archive this by using the distinct() method:с

public static Integer[] intersectionSet(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(Arrays.asList(b)::contain)
      .distinct()
      .toArray(Integer[]::new);
}

Таким образом, длина пересечения больше не зависит от порядка параметров.

Однако пересечение массива с самим собой не может снова быть массивом, так как мы удаляем двойные записи.

5. Multiset Intersection

Более общим понятием, которое допускает множественные равные записи, являются мультимножества. Для них пересечение определяется минимальным количеством входных вхождений. Таким образом, наше членство -Predicate должно отслеживать, как часто мы добавляем элемент к результату.

Для этого можно использовать методremove(), который возвращает членство и потребляет элементы. Таким образом, после того, как все равные элементы в‘b' потреблены, к результату больше не добавляются равные элементы:

public static Integer[] intersectionSet(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(new LinkedList<>(Arrays.asList(b))::remove)
      .toArray(Integer[]::new);
}

ПосколькуArrays API возвращает только неизменяемыйList,, мы должны создать специальный изменяемый.

6. Заключение

В этой статье мы увидели, как использовать методыcontains иremove  для реализации пересечения двух массивов в Java.

Всю реализацию, фрагменты кода и тесты можно найти в нашемGithub repository - это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.