Рубрики
Без рубрики

Java – Объединение Нескольких Коллекций

Краткое и практическое руководство по объединению нескольких коллекций в Java

Автор оригинала: baeldung.

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 , элементами которого являются две коллекции, а затем сглаживаете 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

Добавьте следующую зависимость к вашему 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 в один.

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

4.2. Использование метода CollectionUtils.union()

Служебные методы и декораторы для экземпляров Collection предоставляются классом CollectionUtils . Метод union() из этого класса возвращает Коллекцию , содержащую объединение данного Iterable экземпляры.

Iterable combinedIterables = 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 , однако стоит отметить, что этот метод создает новую коллекцию с дополнительными ссылками на те же объекты, которые находятся в первых двух коллекциях:

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

5.2. Написание пользовательского метода concat()

В приведенном ниже примере определяется метод concat () , который принимает два Iterables и возвращает объединенный Iterable объект:

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();
                    }
                };
            }
        };
    }

Метод concat() может быть вызван путем передачи двух коллекций в качестве аргументов:

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

Если вам нужно, чтобы Iterable был доступен как List , вы также можете использовать метод make List From Iterable () , который создает List с использованием членов Iterable :

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

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

В статье обсуждалось несколько различных способов логического объединения двух коллекций в Java без создания дополнительных ссылок на содержащиеся в них объекты.

Код для этого учебника доступен на Github .