ZetCode

Java Collections.addAll 方法

上次修改时间:2025 年 4 月 20 日

Collections.addAll 方法是 Java Collections 框架中的一个实用方法。它提供了一种方便的方式,可以在单个操作中将多个元素添加到集合中。此方法是 java.util.Collections 类的一部分。

当您需要一次向集合添加多个元素时,Collections.addAll 尤其有用。它可以接受元素数组或可变数量的参数。此方法是类型安全的,并且适用于所有 Collection 实现。

Collections.addAll 方法概述

addAll 方法签名是:public static <T> boolean addAll(Collection<? super T> c, T... elements)。它将所有指定的元素添加到给定的集合中。元素可以作为数组或单独的参数提供。

如果由于调用导致集合发生更改,该方法将返回 true。如果集合或 elements 参数为 null,则抛出 NullPointerException。该方法针对各种集合类型进行了性能优化。

Collections.addAll 的基本用法

此示例演示了 Collections.addAll 的最基本用法。我们创建一个空的 ArrayList 并使用该方法向其添加多个 String 元素。该示例展示了数组和 varargs 形式。

BasicAddAllExample.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BasicAddAllExample {

    public static void main(String[] args) {
        
        List<String> colors = new ArrayList<>();
        
        // Using varargs
        Collections.addAll(colors, "Red", "Green", "Blue");
        System.out.println("After varargs add: " + colors);
        
        // Using array
        String[] moreColors = {"Yellow", "Purple"};
        Collections.addAll(colors, moreColors);
        System.out.println("After array add: " + colors);
        
        // Check return value
        boolean changed = Collections.addAll(colors, "Red");
        System.out.println("Collection changed? " + changed);
    }
}

此代码创建一个空的 ArrayList,并使用两种形式的 Collections.addAll 添加元素。第一个调用使用 varargs 添加三种颜色。第二个调用从数组中添加另外两种颜色。

输出显示了每次添加后的集合。返回值演示显示,添加重复元素返回 false,因为集合未被修改(对于 Set,则会有所不同)。

向不同的集合类型添加元素

Collections.addAll 适用于所有 Collection 实现。此示例演示了向不同的集合类型(ArrayList、HashSet 和 LinkedList)添加元素。每个集合在处理重复项和排序方面都有不同的行为。

DifferentCollectionTypes.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class DifferentCollectionTypes {

    public static void main(String[] args) {
        
        // ArrayList - maintains insertion order, allows duplicates
        List<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "A", "B", "A", "C");
        System.out.println("ArrayList: " + arrayList);
        
        // HashSet - no order, no duplicates
        Set<String> hashSet = new HashSet<>();
        Collections.addAll(hashSet, "A", "B", "A", "C");
        System.out.println("HashSet: " + hashSet);
        
        // LinkedList - maintains insertion order, allows duplicates
        List<String> linkedList = new LinkedList<>();
        Collections.addAll(linkedList, "A", "B", "A", "C");
        System.out.println("LinkedList: " + linkedList);
    }
}

此示例展示了 Collections.addAll 在不同集合类型中的行为。ArrayList 和 LinkedList 保持插入顺序并允许重复项。HashSet 不保持顺序并消除重复项。

输出清楚地演示了这些差异。将相同的元素添加到不同的集合类型会产生不同的结果,这取决于每个集合的特性。

从数组添加元素

Collections.addAll 的一个常见用例是从数组向集合添加元素。此示例展示了如何有效地将数组内容传输到各种集合类型。该方法会自动处理转换。

ArrayToCollection.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class ArrayToCollection {

    public static void main(String[] args) {
        
        Integer[] numbers = {5, 2, 8, 1, 9, 3, 5};
        
        // Add to ArrayList
        List<Integer> numberList = new ArrayList<>();
        Collections.addAll(numberList, numbers);
        System.out.println("ArrayList: " + numberList);
        
        // Add to TreeSet (sorted, no duplicates)
        Set<Integer> numberSet = new TreeSet<>();
        Collections.addAll(numberSet, numbers);
        System.out.println("TreeSet: " + numberSet);
        
        // Partial array add
        List<Integer> partialList = new ArrayList<>();
        Collections.addAll(partialList, Arrays.copyOfRange(numbers, 2, 5));
        System.out.println("Partial add: " + partialList);
    }
}

此示例演示了将元素从数组添加到不同的集合类型。我们首先将 Integer 数组中的所有元素添加到 ArrayList 中,保留顺序和重复项。然后,我们将相同的元素添加到 TreeSet 中,它会对其进行排序并删除重复项。

最后一部分展示了如何使用 Arrays.copyOfRange 仅添加数组的一部分。当您只需要从数组中添加特定元素时,此技术非常有用。

使用 Collections.addAll 组合集合

Collections.addAll 可用于组合多个集合。此示例展示了如何将来自不同集合的元素合并到一个集合中。我们演示了相同类型和混合类型的集合。

CombineCollections.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class CombineCollections {

    public static void main(String[] args) {
        
        List<String> fruits = new ArrayList<>();
        Collections.addAll(fruits, "Apple", "Banana", "Cherry");
        
        Set<String> vegetables = new LinkedHashSet<>();
        Collections.addAll(vegetables, "Carrot", "Broccoli", "Spinach");
        
        // Combine into new List
        List<String> produce = new ArrayList<>();
        Collections.addAll(produce, fruits.toArray(new String[0]));
        Collections.addAll(produce, vegetables.toArray(new String[0]));
        System.out.println("Combined produce: " + produce);
        
        // Add array and collection together
        String[] moreFruits = {"Orange", "Mango"};
        Collections.addAll(produce, moreFruits);
        Collections.addAll(produce, vegetables.toArray(new String[0]));
        System.out.println("After more additions: " + produce);
    }
}

此示例演示了使用 Collections.addAll 组合来自不同集合的元素。我们首先为水果和蔬菜创建单独的集合。然后,我们通过首先将每个集合转换为数组,将它们组合到一个新的 List 中。

第二部分显示了将数组和另一个集合添加到现有集合。输出显示了元素如何组合,同时保持插入顺序(对于 List)并允许重复项。

性能注意事项

此示例比较了 Collections.addAll 与添加多个元素的替代方法的性能。我们测量了使用不同方法将元素添加到各种集合类型所花费的时间。

AddAllPerformance.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class AddAllPerformance {

    public static void main(String[] args) {
        final int SIZE = 1000000;
        Integer[] data = new Integer[SIZE];
        Arrays.setAll(data, i -> i);
        
        timeArrayList(data);
        timeHashSet(data);
    }
    
    private static void timeArrayList(Integer[] data) {
        // Method 1: Collections.addAll
        List<Integer> list1 = new ArrayList<>();
        long start = System.nanoTime();
        Collections.addAll(list1, data);
        long end = System.nanoTime();
        System.out.printf("ArrayList Collections.addAll: %d ms%n", 
            (end - start) / 1000000);
        
        // Method 2: addAll from another collection
        List<Integer> list2 = new ArrayList<>();
        start = System.nanoTime();
        list2.addAll(Arrays.asList(data));
        end = System.nanoTime();
        System.out.printf("ArrayList addAll from List: %d ms%n", 
            (end - start) / 1000000);
    }
    
    private static void timeHashSet(Integer[] data) {
        // Method 1: Collections.addAll
        Set<Integer> set1 = new HashSet<>();
        long start = System.nanoTime();
        Collections.addAll(set1, data);
        long end = System.nanoTime();
        System.out.printf("HashSet Collections.addAll: %d ms%n", 
            (end - start) / 1000000);
        
        // Method 2: Constructor with collection
        start = System.nanoTime();
        Set<Integer> set2 = new HashSet<>(Arrays.asList(data));
        end = System.nanoTime();
        System.out.printf("HashSet constructor: %d ms%n", 
            (end - start) / 1000000);
    }
}

此性能测试比较了将元素添加到集合的不同方法。对于 ArrayList,Collections.addAll 与来自另一个集合的 addAll 进行比较。对于 HashSet,我们与接受集合的构造函数进行比较。

结果将因系统而异,但通常表明 Collections.addAll 经过高度优化。对于 ArrayList,它通常比其他方法更快。对于 HashSet,构造函数可能更快,因为它能够优化容量。

将 Collections.addAll 用于自定义对象

Collections.addAll 可与自定义对象无缝协作。此示例演示了将自定义类的实例添加到不同的集合类型。我们将使用一个简单的 Person 类,其中包含 name 和 age 字段。

CustomObjectsExample.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class CustomObjectsExample {

    public static void main(String[] args) {
        
        List<Person> people = new ArrayList<>();
        
        // Add multiple Person objects
        Collections.addAll(people,
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        );
        
        System.out.println("People list:");
        people.forEach(System.out::println);
        
        // Add from array
        Person[] morePeople = {
            new Person("David", 40),
            new Person("Eve", 28)
        };
        Collections.addAll(people, morePeople);
        
        System.out.println("\nAfter adding more people:");
        people.forEach(System.out::println);
    }
    
    static class Person {
        private String name;
        private int age;
        
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        
        @Override
        public String toString() {
            return name + " (" + age + ")";
        }
        
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }
        
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }
}

此示例展示了 Collections.addAll 与自定义 Person 对象的配合使用。我们首先使用 varargs 添加几个 Person 实例,然后从数组中添加更多实例。Person 类包括适当的 equalshashCode 实现。

输出表明,自定义对象可以像内置类型一样轻松地添加到集合中。这使得 Collections.addAll 对于遵循 Java 集合要求的任何对象类型都非常通用。

边缘情况和异常处理

此示例探讨了 Collections.addAll 的边缘情况和异常处理。我们演示了空集合、空元素和不兼容类型会发生什么情况。适当的错误处理对于健壮的代码至关重要。

EdgeCasesExample.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class EdgeCasesExample {

    public static void main(String[] args) {
        
        // 1. Null collection
        try {
            Collections.addAll(null, "A", "B", "C");
        } catch (NullPointerException e) {
            System.out.println("Caught NullPointerException for null collection: " + e.getMessage());
        }
        
        // 2. Null elements array
        List<String> list = new ArrayList<>();
        try {
            Collections.addAll(list, (String[]) null);
        } catch (NullPointerException e) {
            System.out.println("Caught NullPointerException for null elements: " + e.getMessage());
        }
        
        // 3. Null elements in varargs
        try {
            Collections.addAll(list, "A", null, "C");
        } catch (NullPointerException e) {
            System.out.println("Caught NullPointerException for null element: " + e.getMessage());
        }
        
        // 4. Incompatible types
        List<Integer> numbers = new ArrayList<>();
        try {
            Collections.addAll(numbers, "String");
        } catch (ClassCastException e) {
            System.out.println("Caught ClassCastException for incompatible type: " + e.getMessage());
        }
        
        // 5. Unmodifiable collection
        List<String> unmodifiableList = Collections.unmodifiableList(new ArrayList<>());
        try {
            Collections.addAll(unmodifiableList, "A", "B");
        } catch (UnsupportedOperationException e) {
            System.out.println("Caught UnsupportedOperationException for unmodifiable collection: " + e.getMessage());
        }
        
        // Successful case
        Collections.addAll(list, "X", "Y", "Z");
        System.out.println("Successfully added elements: " + list);
    }
}

此示例演示了 Collections.addAll 的各种边缘情况。我们测试:1. 传递空集合,这会抛出 NullPointerException。2. 传递空元素数组,这也会抛出 NullPointerException。3. 在 varargs 中包含空元素,如果集合不允许空值,则会抛出 NullPointerException。4. 尝试添加不兼容的类型,这可能会在运行时抛出 ClassCastException。5. 尝试添加到不可修改的集合,这将抛出 UnsupportedOperationException

输出显示了针对每种情况捕获的异常以及成功的添加,以演示正确用法。在使用 Collections.addAll 时,适当的异常处理可确保代码的健壮性。

实际用例

此示例演示了 Collections.addAll 在数据处理服务中的实际应用,该服务收集和管理用户偏好。该服务使用该方法有效地将多个偏好添加到集合中。

PreferenceService.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PreferenceService {

    private final List<String> userPreferences = new ArrayList<>();
    
    public void addPreferences(String... preferences) {
        Collections.addAll(userPreferences, preferences);
    }
    
    public void addPreferencesFromArray(String[] preferences) {
        Collections.addAll(userPreferences, preferences);
    }
    
    public List<String> getPreferences() {
        return Collections.unmodifiableList(userPreferences);
    }
    
    public static void main(String[] args) {
        PreferenceService service = new PreferenceService();
        
        // Add preferences using varargs
        service.addPreferences("Dark Mode", "Email Notifications", "Auto Save");
        System.out.println("Preferences after varargs: " + service.getPreferences());
        
        // Add preferences from array
        String[] morePrefs = {"High Contrast", "Two-Factor Auth"};
        service.addPreferencesFromArray(morePrefs);
        System.out.println("Preferences after array: " + service.getPreferences());
        
        // Demonstrate unmodifiable return
        try {
            service.getPreferences().add("Invalid");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify preferences directly: " + e.getMessage());
        }
    }
}

此示例展示了一个 PreferenceService,它使用 Collections.addAll 添加用户偏好。该服务提供了通过 varargs 或数组添加偏好的方法,并返回偏好的不可修改视图,以防止外部修改。

输出显示了每次添加后的偏好,并演示了客户端无法直接修改返回的集合。这种模式在 API 中很常见,在 API 中您需要内部管理集合,同时为客户端提供安全访问。

来源

Java Collections.addAll 文档

在本教程中,我们深入探讨了 Collections.addAll。我们涵盖了基本用法、不同的集合类型、数组转换、组合集合、性能、自定义对象、边缘情况和实际应用。此方法对于有效地将多个元素添加到集合中很有价值。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的程序员,在该领域拥有多年的经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识,并帮助他人掌握编程概念。

列出所有Java教程