Java - объединение нескольких коллекций
1. обзор
В этом руководстве мы проиллюстрируем, как объединить несколько коллекций в одну логическую коллекцию.
Мы рассмотрим пять различных подходов: два с использованием Java 8, один с использованием Guava, один с использованием коллекций Apache Commons и один с использованием только стандартного Java 7 SDK.
В следующих примерах рассмотрим следующие коллекции:
Collection collectionA = asList("S", "T");
Collection collectionB = asList("U", "V");
2. Использование API Java 8Stream
ИнтерфейсStream в Java API предоставляет полезные методы, упрощающие обработку коллекций. Давайте посмотрим на два его метода -concat() иflatMap() - которые используются для объединения коллекций.
Как только вы получитеStream, вы можете выполнять с ним агрегированные операции.
2.1. Использование методаconcat() __
Статический методconcat() логически объединяет дваStreams, создавая лениво сцепленныйStream, элементы которого являются элементами первогоStream, за которым следуют все элементы второгоStreamс.
В приведенном ниже примере давайте объединимcollectionA иcollectionB, используя методconcat():
Stream combinedStream = Stream.concat(
collectionA.stream(),
collectionB.stream());
Если вам нужно объединить более двухStreams, вы можете снова вызвать методconcat() из исходного вызова:
Stream combinedStream = Stream.concat(
Stream.concat(collectionA.stream(), collectionB.stream()),
collectionC.stream());
Важно отметить, что Java 8Streamsнельзя использовать повторно, поэтому вы должны учитывать это при назначении их переменным.
2.2. Использование методаflatMap() __
МетодflatMap() возвращаетStream после замены каждого элемента этогоStream содержимым сопоставленногоStream, которое создается путем применения предоставленной функции сопоставления к каждому элементу.
Пример ниже демонстрирует слияние коллекций с использованием методаflatMap(). Первоначально вы получаетеStream, элементами которого являются две коллекции, а затем вы сглаживаетеStream перед тем, как собрать его в объединенный список:
Stream combinedStream = 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, который используется для объединения коллекций:
Iterable combinedIterables = Iterables.unmodifiableIterable(
Iterables.concat(collectionA, collectionA));
ВозвращаемыйIterable может быть преобразован в коллекцию:
Collection collectionCombined = Lists.newArrayList(combinedIterables);
3.2. Maven Dependency
Добавьте следующую зависимость в свой файл Mavenpom.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 в один.
Iterable combinedIterables = IterableUtils.chainedIterable(
collectionA, collectionB);
4.2. Использование методаCollectionUtils.union()
Служебные методы и декораторы для экземпляровCollection предоставляются классомCollectionUtils. Методunion() из этого класса возвращаетCollection, содержащий объединение заданных экземпляровIterable.
Iterable combinedIterables = CollectionUtils.union(
collectionA, collectionB);
В случае методаunion() мощность каждого элемента в возвращаемой коллекции будет равна максимальной мощности этого элемента в двух заданныхIterables. Это означает, что объединенная коллекция состоит только из элементов первой коллекции и элементов второй коллекции, которых не было в первой.
4.3. Maven Dependency
Добавьте следующую зависимость в свой файл Mavenpom.xml, чтобы включить библиотеку коллекций Apache Commons в свой проект:
org.apache.commons
commons-collections4
4.1
Вы можете найти последнюю версию библиотеки Apache Commons в репозиторииMaven Central.
5. Использование Java 7
Если вы все еще используете Java 7 и хотите избегать сторонних библиотек, таких как Guava, вы можете использовать методaddAll() для объединения элементов из нескольких коллекций, или вы можете написать свои собственные служебные методы для объединенияIterables .
5.1. Использование методаaddAll()
Конечно, самым простым решением для объединения коллекций является использование методаaddAll(), как в следующем примереList, однако стоит отметить, что этот метод создает новую коллекцию с дополнительными ссылками на те же объекты, которые в первых двух сборниках:
List listC = new ArrayList<>();
listC.addAll(listA);
listC.addAll(listB);
5.2. Написание собственного методаconcat()
В приведенном ниже примере определяется методconcat(), который принимает дваIterables и возвращает объединенный объектIterable:
public static Iterable 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() можно вызвать, передав две коллекции в качестве аргументов:
Iterable combinedIterables = concat(collectionA, collectionB);
Collection collectionCombined = makeListFromIterable(combinedIterables);
Если вам нужно, чтобыIterable был доступен какList, вы также можете использовать методmakeListFromIterable(), который создаетList с использованием членовIterable:
public static List makeListFromIterable(Iterable iter) {
List list = new ArrayList();
for (E item : iter) {
list.add(item);
}
return list;
}
6. Заключение
В статье обсуждалось несколько различных способов логически объединить две коллекции в Java без создания дополнительных ссылок на объекты, которые они содержат.
Код для этого руководства доступенover on Github.