Java - Combiner plusieurs collections

Java - Combiner plusieurs collections

1. Vue d'ensemble

Dans ce didacticiel, nous allons illustrer comment concaténer plusieurs collections dans une collection logique.

Nous allons explorer cinq approches différentes: deux utilisant Java 8, une utilisant Guava, une utilisant Apache Commons Collections et une utilisant uniquement le SDK Java 7 standard.

Dans les exemples qui suivent, considérons les collections suivantes:

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

2. Utilisation de l'API Java 8Stream

L'interfaceStream de l'API Java fournit des méthodes utiles qui facilitent le traitement des collections. Jetons un coup d'œil à deux de ses méthodes -concat() etflatMap() - qui sont utilisées pour combiner des collections.

Une fois que vous avez obtenu unStream, vous pouvez y effectuer des opérations d'agrégation.

2.1. Utilisation de la méthodeconcat() __

La méthode statiqueconcat() combine logiquement deuxStreams en créant unStream paresseusement concaténé dont les éléments sont tous les éléments du premierStream suivis de tous les éléments du secondStream.

Dans l'exemple ci-dessous, combinonscollectionA etcollectionB à l'aide de la méthodeconcat():

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

Si vous devez combiner plus de deuxStreams, vous pouvez appeler à nouveau la méthodeconcat() depuis l'invocation d'origine:

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

Il est important de noter que Java 8Streams ne sont pas réutilisables, vous devez donc en tenir compte lors de leur affectation à des variables.

2.2. Utilisation de la méthodeflatMap() __

La méthodeflatMap() renvoie unStream après avoir remplacé chaque élément de ceStream par le contenu d'unStream mappé qui est produit en appliquant la fonction de mappage fournie à chaque élément.

L'exemple ci-dessous illustre la fusion de collections à l'aide de la méthodeflatMap(). Au départ, vous obtenez unStream dont les éléments sont les deux collections, puis vous aplatissez lesStream avant de le rassembler dans une liste fusionnée:

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

3. Utilisation de goyave

La bibliothèque Guava de Google propose plusieurs méthodes pratiques d'utilisation des collections et peut être utilisée avec Java 6 ou une version ultérieure.

3.1. Utilisation de la méthodeIterables.concat()

La méthodeIterables.concat() est l'une des méthodes pratiques de Guava utilisées pour fusionner des collections:

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

LesIterable renvoyés peuvent être convertis en collection:

Collection collectionCombined = Lists.newArrayList(combinedIterables);

3.2. Dépendance Maven

Ajoutez la dépendance suivante à votre fichier Mavenpom.xml pour inclure la bibliothèque Guava dans votre projet:


    com.google.guava
    guava
    20.0

Vous pouvez trouver la dernière version de la bibliothèque Guava dans le référentielMaven Central.

4. Utilisation des collections Apache Commons

Apache Commons Collections est une autre bibliothèque d'utilitaires qui aide à travailler avec les différentes collections. La bibliothèque fournit deux méthodes utilitaires pouvant être utilisées pour combiner des collections. Dans cette section, laissez-nous comprendre le fonctionnement de ces méthodes.

4.1. Utilisation de la méthodeIterableUtils.chainedIterable()

La classeIterableUtils fournit des méthodes utilitaires et des décorateurs pour les instancesIterable. Il fournit la méthodechainedIterable(), qui peut être utilisée pour combiner plusieursIterables en un seul.

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

4.2. Utilisation de la méthodeCollectionUtils.union()

Les méthodes utilitaires et les décorateurs pour les instancesCollection sont fournis par la classeCollectionUtils. La méthodeunion() de cette classe renvoie unCollection contenant l'union des instancesIterable données.

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

Dans le cas de la méthodeunion(), la cardinalité de chaque élément de la collection retournée sera égale au maximum de la cardinalité de cet élément dans les deuxIterables donnés. Cela signifie que la collection combinée ne comprend que les éléments de la première collection et les éléments de la seconde collection qui n'étaient pas présents dans la première.

4.3. Dépendance Maven

Ajoutez la dépendance suivante à votre fichier Mavenpom.xml pour inclure la bibliothèque Apache Commons Collections dans votre projet:


    org.apache.commons
    commons-collections4
    4.1

Vous pouvez trouver la dernière version de la bibliothèque Apache Commons dans le référentielMaven Central.

5. Utiliser Java 7

Si vous utilisez toujours Java 7 et souhaitez éviter les bibliothèques tierces telles que Guava, vous pouvez utiliser la méthodeaddAll() pour combiner des éléments de plusieurs collections, ou vous pouvez écrire vos propres méthodes utilitaires pour combinerIterables .

5.1. Utilisation de la méthodeaddAll()

Bien sûr, la solution la plus simple pour combiner des collections consiste à utiliser la méthodeaddAll(), comme dans l'exempleList suivant, mais il convient de noter que cette méthode crée une nouvelle collection avec des références supplémentaires aux mêmes objets qui sont dans les deux premières collections:

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

5.2. Ecriture d'une méthodeconcat() personnalisée

L'exemple ci-dessous définit une méthodeconcat() qui accepte deuxIterables et renvoie un objetIterable fusionné:

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

La méthodeconcat() peut être invoquée en passant les deux collections comme arguments:

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

Si vous avez besoin que lesIterable soient disponibles en tant queList, vous pouvez également utiliser la méthodemakeListFromIterable() qui crée unList en utilisant les membres desIterable:

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

6. Conclusion

L'article présentait différentes manières de combiner logiquement deux collections en Java sans créer de références supplémentaires aux objets qu'elles contiennent.

Le code de ce tutoriel est disponibleover on Github.