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

1. Общ преглед

В този бърз урок ще разгледаме как да изчислим пресечната точка между два Integer масива 'a' и 'b' .

Ще се съсредоточим и върху това как да обработваме дублиращи се записи.

За внедряването ще използваме потоци.

2. Членски предикат за масив

Пресичането на два множества по дефиниция е множество с всички стойности от едно, които също са част от второто множество.

Следователно се нуждаем от функция или по-скоро предикат, за да решим членството във втория масив. Тъй като List предоставя такъв метод извън кутията, ние ще го трансформираме в List :

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

3. Изграждане на кръстовището

За да изградим получения масив, ще разгледаме последователно елементите на първия набор и ще проверим дали те също се съдържат във втория масив.След това ще създадем нов масив въз основа на това.

The Stream API ни дава необходимите методи. Първо ще създадем поток , след това ще филтрираме с членството - предикат и накрая ще създадем нов масив:

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

4. Дублирани записи

Тъй като масивите в Java не са изпълнение на Set , ние сме изправени пред проблема с дублиращи се записи във входа и след това в резултата. Забележете, че броят на повторенията в резултата зависи от случаите в първия параметър.

Но за набори елементите не трябва да се появяват няколко пъти. Можем да архивираме това, като използваме метода distinct () :

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

Така че дължината на пресичането вече не зависи от реда на параметрите.

Пресичането на масив със себе си обаче може да не е масивът отново, тъй като премахваме двойни записи.

5. Мултимножество пресичане

По-общо понятие, което позволява множество равни записи, са мултимножествата. За тях пресичането тогава се дефинира от минималния брой входове. Така че нашето членство - предикатът трябва да поддържа резултат колко често добавяме елемент към резултата.

За това може да се използва методът remove () , който връща членството и консумира елементите. Така че след като се консумират всички равни елементи в 'b' , към резултата не се добавят повече равни елементи:

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

Тъй като API на Arrays връща само неизменяем списък, трябва да генерираме посветен изменяем.

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

В тази статия видяхме как да използваме методите contains и remove за реализиране на пресичане на два масива в Java.

Цялото внедряване, кодови фрагменти и тестове могат да бъдат намерени в нашето хранилище на GitHub - това е проект, базиран на Maven, така че трябва да е лесно да се импортира и изпълнява както е.