Combinazione di diversi tipi di raccolte in Java

1. Introduzione

In questo rapido tutorial, esploreremo diversi modi per combinare le raccolte in Java.

Esploreremo vari approcci utilizzando Java e framework esterni come Guava, Apache, ecc. Per l'introduzione alle collezioni, dai un'occhiata a questa serie qui.

2. Librerie esterne per lavorare con le raccolte

Insieme agli approcci nativi, utilizzeremo anche librerie esterne. Si prega di aggiungere le seguenti dipendenze nel pom.xml :

 org.apache.commons commons-collections4 4.2   org.apache.commons commons-exec 1.3   com.google.guava guava 26.0-jre 

Le ultime versioni possono essere trovate su Maven Central per Commons, Commons-exec e Guava.

3. Combinazione di array in Java

3.1. Soluzione Java nativa

Java viene fornito con un metodo void arraycopy () integrato che copia un dato array di origine in quello di destinazione.

Possiamo usarlo nel modo seguente:

Object[] combined = new Object[first.length + second.length]; System.arraycopy(first, 0, combined, 0, first.length); System.arraycopy(second, 0, combined, first.length, second.length);

In questo metodo, insieme agli oggetti array, specifichiamo anche la posizione da cui dobbiamo copiare e passiamo anche il parametro length.

Questa è una soluzione Java nativa, quindi non richiede alcuna libreria esterna.

3.2. Utilizzo dell'API Java 8 Stream

Gli stream offrono un modo efficace per iterare su diversi tipi di raccolte. Per iniziare con gli stream, vai al tutorial dell'API Java 8 Stream.

Per combinare array usando uno Stream , possiamo usare questo codice:

Object[] combined = Stream.concat(Arrays.stream(first), Arrays.stream(second)).toArray();

Stream.concat () crea uno stream concatenato in cui gli elementi del primo stream sono seguiti dagli elementi del secondo stream, che viene successivamente convertito in un array utilizzando il metodo toArray () .

Il processo di creazione dello stream è lo stesso per diversi tipi di raccolte. Tuttavia, possiamo raccoglierlo in modi diversi per recuperare da esso diverse strutture di dati.

Rivisiteremo questo metodo nelle sezioni 4.2. e 5.2. per vedere come possiamo usare lo stesso metodo su elenchi e insiemi .

3.3. Utilizzo di ArrayUtils da Apache Commons

La libreria Apache commons ci fornisce il metodo addAll () dal pacchetto ArrayUtils . Possiamo fornire destinazione e matrice di origine come parametri e questo metodo restituirà un array combinato:

Object[] combined = ArrayUtils.addAll(first, second);

Questo metodo è anche discusso in dettaglio nell'articolo Elaborazione di array con Apache Commons Lang 3.

3.4. Utilizzando Guava

Guava ci fornisce il metodo concat () per lo stesso scopo:

Object [] combined = ObjectArrays.concat(first, second, Object.class);

Può essere utilizzato con diversi tipi di dati e accetta due array di origine insieme al valore letterale della classe per restituire l'array combinato.

4. Combinazione di elenco in Java

4.1. Utilizzo del metodo addAll () di Collection Native

L' interfaccia Collection stessa ci fornisce il metodo addAll () , che aggiunge tutti gli elementi nella raccolta specificata all'oggetto chiamante. Questo è anche discusso in dettaglio in questo articolo di Baeldung:

List combined = new ArrayList(); combined.addAll(first); combined.addAll(second);

Poiché questo metodo è fornito nell'interfaccia principale del framework delle collezioni, cioè l' interfaccia della raccolta , può essere applicato a tutte le liste e ai set .

4.2. Utilizzando Java 8

Possiamo utilizzare Stream e Collectors nel modo seguente per combinare gli elenchi :

List combined = Stream.concat(first.stream(), second.stream()).collect(Collectors.toList());

This is the same as what we did in case of Arrays in section 3.2, but instead of converting it to an array, we used collectors to convert it to list. To learn about the Collectors in detail, visit Guide to Java 8’s Collectors.

We can also use flatMaps in this way:

List combined = Stream.of(first, second).flatMap(Collection::stream).collect(Collectors.toList());

First, we're using Stream.of() which returns a sequential stream of two lists – first and second. We'll then pass it to flatMap which will return the contents of a mapped stream after applying the mapping function. This method also discussed in Merging Streams in Java article.

To learn more about the flatMap, head over to this Baeldung article.

4.3. Using ListUtils from Apache Commons

CollectionUtils.union does the union of two collections and returns a collection which contains all the elements:

List combined = ListUtils.union(first, second);

This method is also discussed in A Guide to Apache Commons Collections CollectionUtils. For more info, head over to section 4.9. of this article.

4.4. Using Guava

To merge a List using Guava, we'll use Iterable which consists of the concat() method. After concatenating all the collections, we can quickly get the combined List object as shown in this example:

Iterable combinedIterables = Iterables .unmodifiableIterable(Iterables.concat(first, second)); List combined = Lists.newArrayList(combinedIterables);

5. Combining Set in Java

5.1. Plain Java Solution

As we had already discussed in section 4.1., Collection interface comes with a built-in addAll() method which can be used for copying Lists and Sets as well:

Set combined = new HashSet(); combined.addAll(first); combined.addAll(second);

5.2. Using Java 8 Streams

The same function that we used for List objects can be applied here:

Set combined = Stream .concat(first.stream(), second.stream()) .collect(Collectors.toSet());

The only notable difference here when comparing to list is that instead of using Collectors.toList(), we're using Collectors.toSet() to accumulate all the elements from the supplied two streams into a new Set.

And similar to Lists, when using flatMaps on Sets, it would look like:

Set combined = Stream.of(first, second) .flatMap(Collection::stream) .collect(Collectors.toSet());

5.3. Using Apache Commons

Similar to the ListUtils, we can also work with the SetUtils that does a union of Set elements:

Set combined = SetUtils.union(first, second);

5.4. Using from Guava

The Guava library provides us with straightforward Sets.union() method to combine Sets in Java:

Set combined = Sets.union(first, second);

6. Combining Map in Java

6.1. Plain Java Solution

We can make use of the Map interface which itself provides us with the putAll() method which copies all of the mappings from the supplied argument of Map object to the caller Map object:

Map combined = new HashMap(); combined.putAll(first); combined.putAll(second);

6.2. Using Java 8

Since Java 8, the Map class consists of merge() method which accepts a key, value, and a BiFunction. We can use this with a Java 8 forEach statement to achieve merging functionality:

second.forEach((key, value) -> first.merge(key, value, String::concat));

The third parameter, i.e., remapping function is useful when the same key-value pair is present in both source maps. This function specifies what should be done with those type of values.

We can also use flatMap like this:

Map combined = Stream.of(first, second) .map(Map::entrySet) .flatMap(Collection::stream) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, String::concat));

6.3. Using Apache Commons Exec

Apache Commons Exec provides us with a straightforward merge(Map first, Map second) method:

Map combined = MapUtils.merge(first, second);

6.4. Using Google Guava

Possiamo usare ImmutableMap fornito dalla libreria Guava di Google. Il metodo putAll () associa tutte le chiavi e i valori della mappa data nella mappa costruita:

Map combined = ImmutableMap.builder() .putAll(first) .putAll(second) .build();

7. Conclusione

In questo articolo, abbiamo utilizzato diversi approcci per combinare diversi tipi di raccolte . Abbiamo unito gli array , gli elenchi , i set e le mappe .

Come sempre, gli snippet di codice completi con i relativi unit test possono essere trovati su GitHub.