Combining Different Types of Collections in Java – 在Java中结合不同类型的集合

最后修改: 2018年 10月 13日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this quick tutorial, we’ll explore different ways of combining collections in Java.

在这个快速教程中,我们将探索在Java中组合集合的不同方法。

We’ll explore various approaches using Java and external frameworks like Guava, Apache, etc. For the introduction to Collections, have a look at this series here.

我们将使用Java和外部框架(如Guava、Apache等)探索各种方法。关于集合的介绍,请看这里的这个系列

2. External Libraries to Work With Collections 

2.外部图书馆与馆藏的合作

Along with native approaches, we’ll also be using external libraries. Please add the following dependencies in the pom.xml:

除了本地方法外,我们还将使用外部库。请在pom.xml中添加以下依赖项。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.2</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-exec</artifactId>
    <version>1.3</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

The latest versions can be found on Maven Central for Commons, Commons-exec and Guava.

最新的版本可以在Maven中心找到:CommonsCommons-execGuava

3. Combining Arrays in Java

3.在Java中组合数组

3.1. Native Java Solution

3.1.当地的Java解决方案

Java comes with a built-in void arraycopy() method which copies a given source array to the destination one.

Java有一个内置的void arraycopy()方法,将一个给定的源数组复制到目标数组。

We can use it in the following manner:

我们可以按以下方式使用它。

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 this method, along with the array objects, we also specify the position from where we need to copy, and we also pass the length parameter.

在这个方法中,与数组对象一起,我们还指定了我们需要复制的位置,并且我们还传递了长度参数。

This is a native Java solution, so it doesn’t require any external libraries.

这是一个本地的Java解决方案,所以它不需要任何外部库。

3.2. Using Java 8 Stream API

3.2.使用Java 8 Stream API

Streams offer an effective way to iterate over several different types of collections. To get started with streams, head over to the Java 8 Stream API Tutorial.

流提供了一种有效的方式来迭代几种不同类型的集合。要开始使用流,请前往Java 8流API教程

To combine arrays using a Stream, we can use this code:

要使用Stream组合数组,我们可以使用这段代码。

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

Stream.concat() creates a concatenated stream in which the elements of the first stream are followed by the elements of the second stream, which is after that converted to an array using toArray() method.

Stream.concat()创建一个串联的流,其中第一个流的元素后面是第二个流的元素,之后用toArray()方法将其转换成一个数组。

The process of creating the stream is the same across different types of collections. However, we can collect it in different ways to retrieve different data structures from it.

在不同类型的集合中,创建流的过程是相同的。然而,我们可以用不同的方式来收集它,以便从中检索出不同的数据结构。

We’ll revisit this method in sections 4.2. and 5.2. to see how we can use the same method on Lists and Sets.

我们将在第4.2节和第5.2节重温这个方法,看看我们如何在ListsSets上使用同样的方法。

3.3. Using ArrayUtils from Apache Commons

3.3.使用来自Apache Commons的ArrayUtils

Apache commons library provides us with the addAll() method from the ArrayUtils package. We can supply destination and source array as parameters, and this method will return a combined array:

Apache commons库为我们提供了addAll()方法,它来自ArrayUtils包。我们可以提供目标数组和源数组作为参数,这个方法将返回一个组合数组。

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

This method is also discussed in details in the Array Processing with Apache Commons Lang 3 article.

Array Processing with Apache Commons Lang 3文章中也详细讨论了这种方法。

3.4. Using Guava

3.4.使用Guava

Guava provides us with the concat() method for the same purpose:

Guava为我们提供了concat()方法来达到同样的目的。

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

It can be used with different data types, and it accepts two source arrays along with the class literal to return the combined array.

它可以用于不同的数据类型,它接受两个源数组和类字,以返回组合数组。

4. Combining List in Java

4.在Java中组合List

4.1. Using Collection Native addAll() Method

4.1.使用Collection Native addAll() 方法

The Collection interface itself provides us with the addAll() method, which adds all of the elements in the specified collection to the caller object. This is also discussed in detail in this Baeldung article:

Collection接口本身为我们提供了addAll()方法,它将指定集合中的所有元素添加到调用者对象中。在这篇Baeldung文章中也有详细的讨论:

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

Since this method is provided in the most parent interface of Collections framework, i.e., Collection interface, it can be applied across all Lists and Sets.

由于这个方法是在集合框架的最父级接口中提供的,即Collection接口,它可以应用于所有的Lists和Sets。

4.2. Using Java 8

4.2.使用Java 8

We can use Stream and Collectors in the following way to combine Lists:

我们可以通过以下方式使用StreamCollectors来组合Lists

List<Object> 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.

这与我们在第3.2节中对Arrays所做的相同,但我们不是将其转换为数组,而是使用收集器将其转换为列表。要详细了解收集器,请访问Java 8的收集器指南

We can also use flatMaps in this way:

我们也可以通过这种方式使用flatMaps

List<Object> 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.

首先,我们使用Stream.of(),它返回两个列表的顺序流 – 第一第二。然后我们将它传递给flatMap,它将在应用映射函数后返回映射的流的内容。这个方法也在在Java中合并流文章中讨论。

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

要了解有关flatMap的更多信息,请前往这篇Baeldung文章

4.3. Using ListUtils from Apache Commons

4.3.使用来自Apache Commons的ListUtils

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

CollectionUtils.union 做两个集合的联合,并返回一个包含所有元素的集合。

List<Object> 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.

这个方法也在A Guide to Apache Commons Collections CollectionUtils中讨论。欲了解更多信息,请前往本文的第4.9节。

4.4. Using Guava

4.4.使用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:

使用Guava合并一个List,我们将使用Iterable,它由concat()方法组成。在连接所有集合后,我们可以快速得到合并后的List对象,如本例所示。

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

5. Combining Set in Java

5.在Java中组合Set

5.1. Plain Java Solution

5.1.纯粹的Java解决方案

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:

正如我们在第4.1节中已经讨论过的,集合接口带有一个内置的addAll() 方法,该方法也可以用于复制列表集合

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

5.2. Using Java 8 Streams

5.2.使用Java 8 Streams

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

我们用于List objects的相同功能可以应用在这里。

Set<Object> 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.

与列表相比,这里唯一值得注意的区别是,我们没有使用Collectors.toList(),而是使用Collectors.toSet()来将提供的两个流中的所有元素累积到一个新Set

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

Lists类似,当在Sets上使用flatMaps时,它看起来像。

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

5.3. Using Apache Commons

5.3.使用Apache Commons

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

类似于ListUtils,我们也可以使用SetUtils来做Set元素的联合。

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

5.4. Using from Guava

5.4.从Guava中使用

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

Guava库为我们提供了直接的Sets.union()方法来结合Java中的Sets

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

6. Combining Map in Java

6.在Java中组合Map

6.1. Plain Java Solution

6.1.纯粹的Java解决方案

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接口,它本身为我们提供了putAll()方法,该方法将Map对象提供的参数中的所有映射复制到调用者Map对象。

Map<Object, Object> combined = new HashMap<>();
combined.putAll(first);
combined.putAll(second);

6.2. Using Java 8

6.2.使用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:

自Java 8以来,Map类包括merge()方法,该方法接受键、值和BiFunction我们可以将其与Java 8 forEach语句一起使用来实现合并的功能。

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:

我们也可以像这样使用flatMap

Map<String, String> 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

6.3.使用Apache Commons Exec

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

Apache Commons Exec为我们提供了一个直接的merge(Map<K,V> first, Map<K,V> second)/a>方法。

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

6.4. Using Google Guava

6.4.使用Google Guava

We can use ImmutableMap provided by Google’s Guava library. It’s putAll() method associates all of the given map’s keys and values into the built map:

我们可以使用Google的Guava库所提供的ImmutableMap。它的putAll()方法将所有给定的地图的键和值关联到内置的地图中。

Map<String, String> combined = ImmutableMap.<String, String>builder()
  .putAll(first)
  .putAll(second)
  .build();

7. Conclusion

7.结论

In this article, we went through different approaches to combining different type of Collections. We merged the arraysListsSets, and Maps.

在这篇文章中,我们经历了不同的方法来合并不同类型的Collections。我们合并了arrays, Lists, Sets, 和Maps

As always, the complete code snippets with their proper unit tests can be found over on GitHub.

一如既往,完整的代码片段及其适当的单元测试可以在GitHub上找到