ZetCode

Java Collections.copy 方法

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

Collections.copy 方法是 Java 的 java.util.Collections 类中的一个实用方法。它将所有元素从一个列表复制到另一个列表。目标列表的长度必须至少与源列表一样长。

当您需要在列表之间传输元素时,同时保持目标列表的容量时,此方法非常有用。它执行浅拷贝,这意味着复制对象引用,而不是对象本身。

Collections.copy 方法概述

Collections.copy 方法的签名是:public static <T> void copy(List<? super T> dest, List<? extends T> src)。如果目标列表太小,它会抛出 IndexOutOfBoundsException,如果目标列表不可修改,则会抛出 UnsupportedOperationException

该方法保留元素的顺序,并覆盖目标列表中现有的元素。对于大型列表,它比手动复制更有效,因为它在内部使用原生数组复制。

基本复制操作

此示例演示了 Collections.copy 的基本用法。我们创建了两个 ArrayList 并将元素从源复制到目标。目标列表必须有足够的容量来容纳所有元素。

BasicCopyExample.java
package com.zetcode;

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

public class BasicCopyExample {

    public static void main(String[] args) {
        
        // Source list
        List<String> source = new ArrayList<>();
        source.add("Apple");
        source.add("Banana");
        source.add("Cherry");
        
        // Destination list (must have same or larger size)
        List<String> destination = new ArrayList<>();
        destination.add("X");
        destination.add("Y");
        destination.add("Z");
        destination.add("W"); // Extra element
        
        System.out.println("Before copy:");
        System.out.println("Source: " + source);
        System.out.println("Destination: " + destination);
        
        // Perform the copy
        Collections.copy(destination, source);
        
        System.out.println("\nAfter copy:");
        System.out.println("Source: " + source);
        System.out.println("Destination: " + destination);
    }
}

此代码显示了两个列表之间的基本复制操作。目标列表必须至少与源列表一样多的元素。复制后,额外的元素 "W" 仍然保留在目标列表中。

输出结果表明,元素在目标列表中被覆盖,同时保持顺序。源列表在操作后保持不变。

在不同列表类型之间复制

Collections.copy 适用于任何 List 实现。此示例从 ArrayList 复制到 LinkedList。只要支持所需的操作,该方法对不同的列表实现具有灵活性。

DifferentListTypes.java
package com.zetcode;

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

public class DifferentListTypes {

    public static void main(String[] args) {
        
        // ArrayList source
        List<Integer> arraySource = new ArrayList<>();
        arraySource.add(10);
        arraySource.add(20);
        arraySource.add(30);
        
        // LinkedList destination
        List<Integer> linkedDest = new LinkedList<>();
        linkedDest.add(0);
        linkedDest.add(0);
        linkedDest.add(0);
        
        System.out.println("Before copy:");
        System.out.println("Source: " + arraySource);
        System.out.println("Destination: " + linkedDest);
        
        Collections.copy(linkedDest, arraySource);
        
        System.out.println("\nAfter copy:");
        System.out.println("Source: " + arraySource);
        System.out.println("Destination: " + linkedDest);
    }
}

此示例演示了不同 List 实现之间的互操作性。无论使用哪种特定的列表实现,复制操作都以相同的方式工作。

输出结果显示,元素已成功从 ArrayList 复制到 LinkedList。目标列表的实现不会影响复制行为。

处理 IndexOutOfBoundsException

此示例显示了当目标列表对于源列表而言太小时会发生什么情况。在这种情况下,Collections.copy 抛出 IndexOutOfBoundsException。在使用此方法时,适当的错误处理非常重要。

CopyExceptionHandling.java
package com.zetcode;

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

public class CopyExceptionHandling {

    public static void main(String[] args) {
        
        List<String> source = new ArrayList<>();
        source.add("Red");
        source.add("Green");
        source.add("Blue");
        
        List<String> destination = new ArrayList<>();
        destination.add("One");
        destination.add("Two"); // Too small
        
        try {
            System.out.println("Attempting copy...");
            Collections.copy(destination, source);
            System.out.println("Copy succeeded");
        } catch (IndexOutOfBoundsException e) {
            System.out.println("Error: " + e.getMessage());
            System.out.println("Destination list must be at least " + 
                source.size() + " elements long");
        }
    }
}

此代码演示了当目标列表太小时发生的异常。错误消息清楚地表明了问题 - 目标列表的长度必须至少与源列表一样长。

输出结果显示了异常处理的实际效果。在调用 Collections.copy 之前,请务必确保目标列表具有足够的容量。

使用自定义对象复制

Collections.copy 适用于自定义对象,就像它适用于内置类型一样。此示例演示了复制自定义 Person 对象的列表。复制是浅拷贝 - 复制对象引用,而不是对象本身。

CustomObjectsCopy.java
package com.zetcode;

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

class Person {
    String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class CustomObjectsCopy {

    public static void main(String[] args) {
        
        List<Person> source = new ArrayList<>();
        source.add(new Person("Alice", 25));
        source.add(new Person("Bob", 30));
        
        List<Person> destination = new ArrayList<>();
        destination.add(new Person("X", 0));
        destination.add(new Person("Y", 0));
        
        System.out.println("Before copy:");
        System.out.println("Source: " + source);
        System.out.println("Destination: " + destination);
        
        Collections.copy(destination, source);
        
        System.out.println("\nAfter copy:");
        System.out.println("Source: " + source);
        System.out.println("Destination: " + destination);
        
        source.getFirst().name = "Modified";
        System.out.println("\nAfter modification:");
        System.out.println("Source: " + source);
        System.out.println("Destination: " + destination);
    }
}

此示例表明 Collections.copy 执行浅拷贝。目标列表中的 Person 对象与源列表中的对象相同。通过一个列表修改一个对象会影响两个列表。

输出结果表明,虽然列表是分开的,但它们包含对同一对象的引用。在使用可变对象时,这是一个重要的考虑因素。

复制到不可修改的列表

尝试复制到不可修改的列表会导致 UnsupportedOperationException。此示例演示了此行为,并显示了如何正确处理它。

UnmodifiableListCopy.java
package com.zetcode;

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

public class UnmodifiableListCopy {

    public static void main(String[] args) {
        
        List<String> source = new ArrayList<>();
        source.add("Java");
        source.add("Python");
        
        List<String> destination = Collections.unmodifiableList(
            new ArrayList<>(Collections.nCopies(2, "")));
        
        try {
            System.out.println("Attempting to copy to unmodifiable list...");
            Collections.copy(destination, source);
        } catch (UnsupportedOperationException e) {
            System.out.println("Error: " + e.getMessage());
            System.out.println("Cannot copy to an unmodifiable list");
        }
    }
}

此代码尝试复制到不可修改的列表,这会抛出异常。 Collections.unmodifiableList 包装器阻止对列表进行所有修改,包括通过 copy 方法进行的修改。

来源

Java Collections.copy 文档

在本文中,我们深入探讨了 Collections.copy 方法。我们涵盖了基本用法、异常处理以及各种实际示例。理解此方法有助于在 Java 中使用列表操作时。

作者

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

列出所有Java教程