Java 合併多個集合
1.概述
在本教程中,我們將說明如何將多個集合連接為一個邏輯集合。
我們將探索五種不同的方法-兩種使用Java 8,一種使用Guava,一種使用Apache Commons Collections,另一種僅使用標準Java 7 SDK。
在下面的示例中,讓我們考慮以下集合:
Collection<String> collectionA = Arrays.asList("S", "T");
Collection<String> collectionB = Arrays.asList("U", "V");
2.使用Java 8 Stream API
Java API中的Stream接口提供了有用的方法,使處理集合變得更加容易。讓我們看看它的兩個方法– concat()和flatMap() –用於合併集合。
一旦獲得Stream ,就可以對其執行聚合操作。
2.1。使用concat()方法
靜態方法的concat()通過創建一個懶惰地級聯流的元素是所有的第一流的元素,接著第二個流中的所有元素在邏輯上組合兩個流。
在下面的示例中,讓我們使用concat()方法組合collectionA和collectionB :
Stream<String> combinedStream = Stream.concat(
collectionA.stream(),
collectionB.stream());
如果需要組合兩個以上的Stream ,則可以從原始調用中再次調用concat()方法:
Stream<String> combinedStream = Stream.concat(
Stream.concat(collectionA.stream(), collectionB.stream()),
collectionC.stream());
重要的是要注意Java 8 Streams不可重用,因此在將它們分配給變量時應考慮到這一點。
2.2。使用flatMap()方法
flatMap()方法將此Stream的每個元素替換為通過將提供的映射函數應用於每個元素而生成的映射Stream的內容後,返回一個Stream 。
下面的示例演示了使用flatMap()方法合併集合。最初,您獲得一個Stream,其元素是兩個集合,然後在將Stream收集到合併列表之前對其進行展平:
Stream<String> combinedStream = Stream.of(collectionA, collectionB)
.flatMap(Collection::stream);
Collection<String> collectionCombined =
combinedStream.collect(Collectors.toList());
3.使用番石榴
Google提供的Guava庫提供了幾種方便的方法來處理集合,並且可以與Java 6或更高版本一起使用。
3.1。使用Iterables.concat()方法
Iterables.concat()方法是用於合併集合的Guava便捷方法之一:
Iterable<String> combinedIterables = Iterables.unmodifiableIterable(
Iterables.concat(collectionA, collectionA));
返回的Iterable可以轉換為一個集合:
Collection<String> collectionCombined = Lists.newArrayList(combinedIterables);
3.2。 Maven依賴
將以下依賴項添加到您的Maven pom.xml文件中,以在您的項目中包括Guava庫:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
您可以在Maven Central存儲庫中找到最新版本的Guava庫。
4.使用Apache Commons集合
Apache Commons Collections是另一個實用程序庫,可幫助您處理各種集合。該庫提供了兩種可用於合併集合的實用程序方法。在本節中,讓我們了解這些方法如何工作。
4.1。使用IterableUtils.chainedIterable()方法
IterableUtils類為Iterable實例提供實用程序方法和裝飾器。它提供了chainedIterable()方法,該方法可用於將多個Iterable組合為一個。
Iterable<String> combinedIterables = IterableUtils.chainedIterable(
collectionA, collectionB);
4.2。使用CollectionUtils.union()方法
對於集合實例的實用工具方法和裝飾是由CollectionUtils類提供。此類的union()方法返回一個Collection,其中包含給定Iterable實例的並集。
Iterable<String> combinedIterables = CollectionUtils.union(
collectionA, collectionB);
對於union()方法,返回集合中每個元素的基數將等於兩個給定Iterables中該元素的基數的最大值。這意味著組合的集合僅由第一個集合中的元素和第二個集合中的第一個元素中不存在的元素組成。
4.3。 Maven依賴
將以下依賴項添加到您的Maven pom.xml文件中,以在項目中包括Apache Commons Collections庫:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
您可以在Maven Central存儲庫中找到最新版本的Apache Commons庫。
5.使用Java 7
如果您仍在使用Java 7,並且希望避免使用第三方庫(例如Guava),則可以使用addAll()方法來組合多個集合中的元素,或者可以編寫自己的實用程序方法來組合Iterables 。
5.1。使用addAll()方法
當然,最簡單的組合集合的解決方案是使用addAll()方法,如下面的List示例所示,但是,值得注意的是,此方法創建了一個新集合,並帶有對前兩個集合中相同對象的附加引用:
List<String> listC = new ArrayList<>();
listC.addAll(listA);
listC.addAll(listB);
5.2。編寫自定義concat()方法
下面的示例定義一個concat()方法,該方法接受兩個Iterables並返回合併的Iterable對象:
public static <E> Iterable<E> concat(
Iterable<? extends E> i1,
Iterable<? extends E> i2) {
return new Iterable<E>() {
public Iterator<E> iterator() {
return new Iterator<E>() {
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<String> combinedIterables = concat(collectionA, collectionB);
Collection<String> collectionCombined = makeListFromIterable(combinedIterables);
如果需要將Iterable用作List ,則還可以使用makeListFromIterable()方法,該方法使用Iterable的成員創建一個List :
public static <E> List<E> makeListFromIterable(Iterable<E> iter) {
List<E> list = new ArrayList<E>();
for (E item : iter) {
list.add(item);
}
return list;
}
六,結論
本文討論了幾種在Java中邏輯組合兩個集合而無需創建對其包含的對象的附加引用的不同方法。
本教程的代碼可以在Github上找到。