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, така че трябва да е лесно да се импортира и изпълнява както е.