Java - Комбинирайте няколко колекции

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

В този урок ще илюстрираме как да обединим множество колекции в една логическа колекция.

Ще проучим пет различни подхода - два с Java 8, един с помощта на Guava, един с Apache Commons Collections и един, използващ само стандартния Java 7 SDK.

В примерите, които следват, нека разгледаме следните колекции:

Collection collectionA = Arrays.asList("S", "T"); Collection collectionB = Arrays.asList("U", "V");

2. Използване на Java 8 Stream API

Интерфейсът Stream в Java API предоставя полезни методи, които улесняват обработката на колекции. Нека да разгледаме два от методите му - concat () и flatMap () - които се използват за комбиниране на колекции.

След като получите поток , можете да извършвате обобщени операции върху него.

2.1. Използване на Concat () Метод

Статичният метод concat () обединява два потока логически, като създава лениво свързан поток, чиито елементи са всички елементи на първия поток, последван от всички елементи на втория поток .

В примера по-долу нека комбинираме collectionA и collectionB, използвайки метода concat () :

Stream combinedStream = Stream.concat( collectionA.stream(), collectionB.stream());

Ако трябва да комбинирате повече от два потока , можете да извикате метода concat () отново от първоначалното извикване:

Stream combinedStream = Stream.concat( Stream.concat(collectionA.stream(), collectionB.stream()), collectionC.stream());

Важно е да се отбележи, че Java 8 Streams не могат да се използват повторно, така че трябва да вземете това предвид, когато ги присвоявате на променливи.

2.2. Използване на flatMap () Метод

Методът flatMap () връща поток, след като замества всеки елемент от този поток със съдържанието на картографиран поток, който се създава чрез прилагане на предоставената функция за картографиране към всеки елемент.

Примерът по-долу демонстрира обединяване на колекции с помощта на метода flatMap () . Първоначално получавате поток, чиито елементи са двете колекции, и след това изравнявате потока, преди да го съберете в обединен списък:

Stream combinedStream = Stream.of(collectionA, collectionB) .flatMap(Collection::stream); Collection collectionCombined = combinedStream.collect(Collectors.toList());

3. Използване на Гуава

Библиотеката на Гуава от Google предоставя няколко удобни метода за работа с колекции и може да се използва с Java 6 или по-нова версия.

3.1. Използване на Iterables.concat () метод

Методът Iterables.concat () е един от удобните методи на Guava, който се използва за обединяване на колекции:

Iterable combinedIterables = Iterables.unmodifiableIterable( Iterables.concat(collectionA, collectionA));

В Iterable , че се връща може да бъде превърнат в колекция:

Collection collectionCombined = Lists.newArrayList(combinedIterables);

3.2. Зависимост на Maven

Добавете следната зависимост към вашия файл Maven pom.xml, за да включите библиотеката Guava във вашия проект:

 com.google.guava guava 20.0 

Можете да намерите най-новата версия на библиотеката Гуава в централното хранилище на Maven.

4. Използване на колекции Apache Commons

Apache Commons Collections е поредната библиотека от помощни програми, които помагат в работата с различните колекции. Библиотеката предоставя два полезни метода, които могат да се използват за комбиниране на колекции. В този раздел нека разберем как работят тези методи.

4.1. Използване на IterableUtils.chainedIterable () метод

Класът IterableUtils предоставя помощни методи и декоратори за екземпляри на Iterable . Той осигурява метода chainedIterable () , който може да се използва за комбиниране на множество Iterable s в един.

Iterable combinedIterables = IterableUtils.chainedIterable( collectionA, collectionB);

4.2. Използване на CollectionUtils.union () Метод

Помощните методи и декоратори за екземпляри на Collection се предоставят от класа CollectionUtils . Методът union () от този клас връща Колекция, съдържаща обединението на дадените Итерируеми екземпляри.

Iterable combinedIterables = CollectionUtils.union( collectionA, collectionB);

В случая на метод union () , мощността на всеки елемент във върнатата колекция ще бъде равна на максимума на мощността на този елемент в двете дадени Iterables . Това означава, че комбинираната колекция се състои само от елементите в първата колекция и елементите от втората колекция, които не са присъствали в първата.

4.3. Зависимост на Maven

Добавете следната зависимост към вашия файл Maven pom.xml, за да включите библиотеката Apache Commons Collections във вашия проект:

 org.apache.commons commons-collections4 4.1 

Можете да намерите най-новата версия на библиотеката Apache Commons в хранилището на Maven Central.

5. Използване на Java 7

Ако все още използвате Java 7 и искате да избегнете библиотеки на трети страни като Guava, можете да използвате метода addAll () , за да комбинирате елементи от множество колекции, или можете да напишете свои собствени полезни методи, за да комбинирате Iterables .

5.1. Използване на addAll () Метод

Of course the simplest solution for combining collections is using the addAll() method, as in the following List example, however it is worth noting that this method creates a new collection with additional references to the same objects that are in the first two collections:

List listC = new ArrayList(); listC.addAll(listA); listC.addAll(listB);

5.2. Writing a Custom concat() Method

The below example defines a concat() method that accepts two Iterables and returns a merged Iterable object:

public static  Iterable concat( Iterable i1, Iterable i2) { return new Iterable() { public Iterator iterator() { return new Iterator() { Iterator listIterator = i1.iterator(); Boolean checkedHasNext; E nextValue; private boolean startTheSecond; void theNext() { if (listIterator.hasNext()) { checkedHasNext = true; nextValue = listIterator.next(); } else if (startTheSecond) checkedHasNext = false; else { startTheSecond = true; listIterator = i2.iterator(); theNext(); } } public boolean hasNext() { if (checkedHasNext == null) theNext(); return checkedHasNext; } public E next() { if (!hasNext()) throw new NoSuchElementException(); checkedHasNext = null; return nextValue; } public void remove() { listIterator.remove(); } }; } }; }

The concat() method can be invoked by passing the two collections as its arguments:

Iterable combinedIterables = concat(collectionA, collectionB); Collection collectionCombined = makeListFromIterable(combinedIterables);

Ако се нуждаете от Iterable, за да бъде достъпен като Списък , можете също да използвате метода makeListFromIterable () , който създава Списък с помощта на членовете на Iterable :

public static  List makeListFromIterable(Iterable iter) { List list = new ArrayList(); for (E item : iter) { list.add(item); } return list; }

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

Статията обсъжда няколко различни начина за логично комбиниране на две колекции в Java, без да се създават допълнителни препратки към обектите, които те съдържат.

Кодът за този урок е достъпен в Github.