1. Обзор
В этом уроке мы проиллюстрируем, как объединить несколько коллекций в одну логическую коллекцию.
Мы рассмотрим пять различных подходов – два с использованием Java 8, один с использованием Guava, один с использованием Apache Commons Collections и один с использованием только стандартного Java 7 SDK.
В следующих примерах рассмотрим следующие коллекции:
CollectioncollectionA = 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() :
StreamcombinedStream = Stream.concat( collectionA.stream(), collectionB.stream());
Если вам нужно объединить более двух потоков , вы можете снова вызвать метод concat() из исходного вызова:
StreamcombinedStream = Stream.concat( Stream.concat(collectionA.stream(), collectionB.stream()), collectionC.stream());
Важно отметить, что Java 8 Streams не являются многоразовыми, поэтому вы должны учитывать это при назначении их переменным.
2.2. Использование метода flatMap()
Метод flatMap() возвращает Поток после замены каждого элемента этого Потока содержимым отображенного Потока , который создается путем применения предоставленной функции отображения к каждому элементу.
В приведенном ниже примере показано слияние коллекций с помощью метода flatMap () . Сначала вы получаете Stream , элементами которого являются две коллекции, а затем сглаживаете Stream перед тем, как собрать его в объединенный список:
StreamcombinedStream = Stream.of(collectionA, collectionB) .flatMap(Collection::stream); Collection collectionCombined = combinedStream.collect(Collectors.toList());
3. Использование Гуавы
Библиотека Guava от Google предоставляет несколько удобных методов работы с коллекциями и может использоваться с Java 6 или более поздней версией.
3.1. Использование метода Iterables.concat()
Метод Iterables.concat() является одним из удобных методов Guava, используемых для объединения коллекций:
IterablecombinedIterables = Iterables.unmodifiableIterable( Iterables.concat(collectionA, collectionA));
Возвращаемый файл Iterable может быть преобразован в коллекцию:
CollectioncollectionCombined = Lists.newArrayList(combinedIterables);
3.2. Зависимость Maven
Добавьте следующую зависимость к вашему Maven pom.xml файл для включения библиотеки Guava в ваш проект:
com.google.guava guava 20.0
Вы можете найти последнюю версию библиотеки Guava в репозитории Maven Central .
4. Использование коллекций Apache Commons
Apache Commons Collections-это еще одна библиотека утилит, помогающих работать с различными коллекциями. Библиотека предоставляет два полезных метода, которые можно использовать для объединения коллекций. В этом разделе давайте разберемся, как работают эти методы.
4.1. Использование метода IterableUtils.chainedIterable()
Класс IterableUtils предоставляет служебные методы и декораторы для экземпляров Iterable . Он предоставляет метод chainedIterable () , который может быть использован для объединения нескольких Iterable s в один.
IterablecombinedIterables = IterableUtils.chainedIterable( collectionA, collectionB);
4.2. Использование метода CollectionUtils.union()
Служебные методы и декораторы для экземпляров Collection предоставляются классом CollectionUtils . Метод union() из этого класса возвращает Коллекцию , содержащую объединение данного Iterable экземпляры.
IterablecombinedIterables = CollectionUtils.union( collectionA, collectionB);
В случае метода union() мощность каждого элемента в возвращаемой коллекции будет равна максимальной мощности этого элемента в двух заданных Итерабли . Это означает, что объединенная коллекция состоит только из элементов в первой коллекции и элементов во второй коллекции, которые не присутствовали в первой.
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()
Конечно, самым простым решением для объединения коллекций является использование метода addAll () , как в следующем примере List , однако стоит отметить, что этот метод создает новую коллекцию с дополнительными ссылками на те же объекты, которые находятся в первых двух коллекциях:
ListlistC = new ArrayList<>(); listC.addAll(listA); listC.addAll(listB);
5.2. Написание пользовательского метода concat()
В приведенном ниже примере определяется метод concat () , который принимает два Iterables и возвращает объединенный Iterable объект:
public staticIterable concat( Iterable extends E> i1, Iterable extends E> i2) { return new Iterable () { public Iterator iterator() { return new Iterator () { Iterator extends E> 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(); } }; } }; }
Метод concat() может быть вызван путем передачи двух коллекций в качестве аргументов:
IterablecombinedIterables = concat(collectionA, collectionB); Collection collectionCombined = makeListFromIterable(combinedIterables);
Если вам нужно, чтобы Iterable был доступен как List , вы также можете использовать метод make List From Iterable () , который создает List с использованием членов Iterable :
public staticList makeListFromIterable(Iterable iter) { List list = new ArrayList (); for (E item : iter) { list.add(item); } return list; }
6. Заключение
В статье обсуждалось несколько различных способов логического объединения двух коллекций в Java без создания дополнительных ссылок на содержащиеся в них объекты.
Код для этого учебника доступен на Github .