CodeGym /课程 /JAVA 25 SELF /集合转换

集合转换

JAVA 25 SELF
第 28 级 , 课程 1
可用

1. 集合元素的转换

在编程中,最常见的操作之一——就是集合转换:我们手里有某种类型的数据集合,需要基于它创建一种新类型的集合。比如,从类型为 User 的对象列表中得到它们的姓名列表(String),或者从数字列表得到它们的平方列表。

在 Java 中最基础、最直观的方式是使用命令式思路,也就是普通的 for 循环(通常为 for-each)。

示例:从字符串列表得到其长度列表

假设我们有一个城市名称的列表:

List<String> cities = List.of("伦敦", "巴黎", "东京", "纽约");

我们的目标是创建一个新列表,其中包含每个名称的长度。最终结果应为:[2, 2, 2, 2]

使用 for 循环的解法:

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

public class CollectionTransform {
    public static void main(String[] args) {
        List<String> cities = List.of("伦敦", "巴黎", "东京", "纽约");
        List<Integer> lengths = new ArrayList<>(); // 创建一个新的空列表用于存放结果

        for (String city : cities) {
            // 对 cities 中的每个元素计算其长度...
            int length = city.length();
            // ...并把这个结果加入到新列表中
            lengths.add(length);
        }

        System.out.println(lengths); // 输出:[2, 2, 2, 2]
    }
}

我们先创建一个新的空集合来存放结果——转换不会修改源集合。遍历源集合时使用 for-each 循环,并在循环体内对每个元素应用所需逻辑(例如 length()),再通过 add 把结果加入新列表。

2. 对象的转换

我们经常会处理更复杂的数据类型。假设有一个 Product 类,需要得到它的名称(或价格)列表。

public class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

现在有了产品列表,我们来获取其名称列表:

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

public class ProductExample {
    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("笔记本电脑", 1200.0),
            new Product("鼠标", 25.5),
            new Product("键盘", 75.0)
        );

        // 为名称创建一个新列表
        List<String> productNames = new ArrayList<>();

        for (Product product : products) {
            // 对每个 Product 对象获取它的名称
            productNames.add(product.getName());
        }

        System.out.println(productNames); // 输出:[笔记本电脑, 鼠标, 键盘]
    }
}

思路不变:遍历源集合,对每个元素调用所需的方法(例如 getName()),并把结果添加到新集合中。

3. 处理嵌套集合

来看一个“列表的列表”的情况:多个部门,每个部门有自己的员工列表。我们的任务是得到一个统一的(“扁平的”)员工总列表。

示例:合并员工列表

List<List<String>> departments = List.of(
    List.of("安娜", "鲍里斯"),
    List.of("维多利亚", "格列布", "德米特里"),
    List.of("叶莲娜")
);

我们希望得到一个统一的列表:[安娜, 鲍里斯, 维多利亚, 格列布, 德米特里, 叶莲娜]

方法 1:使用 addAll()

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

public class NestedCollectionExample {
    public static void main(String[] args) {
        List<List<String>> departments = List.of(
            List.of("安娜", "鲍里斯"),
            List.of("维多利亚", "格列布", "德米特里"),
            List.of("叶莲娜")
        );

        List<String> allEmployees = new ArrayList<>();

        // 遍历每个列表(部门)
        for (List<String> department : departments) {
            // 把当前列表中的所有元素添加到总列表
            allEmployees.addAll(department);
        }

        System.out.println(allEmployees); // [安娜, 鲍里斯, 维多利亚, 格列布, 德米特里, 叶莲娜]
    }
}

方法 2:嵌套循环——效果相同,但“手动”实现:

List<List<String>> departments = List.of(...);
List<String> allEmployees = new ArrayList<>();

for (List<String> department : departments) { // 外层循环:部门
    for (String employee : department) {      // 内层循环:员工
        allEmployees.add(employee);
    }
}

System.out.println(allEmployees);

两种方式在结果上是等价的。addAll() 本质上封装了嵌套循环的逻辑,使代码更简洁。

4. 更复杂的场景与带条件的转换

有时只需要对满足条件的元素执行转换。比如,获取以字符 "纽" 开头的城市名称,并取它们的长度。这里我们把过滤与转换结合起来:if + 方法调用(length())。

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

public class ConditionalTransform {
    public static void main(String[] args) {
        List<String> cities = List.of("伦敦", "巴黎", "东京", "纽约", "纽伦堡");
        List<Integer> lengths = new ArrayList<>();

        for (String city : cities) {
            // 先检查条件
            if (city.startsWith("纽")) {
                // 如果条件满足,再执行转换
                lengths.add(city.length());
            }
        }

        System.out.println(lengths); // 输出:[2, 3]
    }
}

模式是这样的:在循环内部,先用条件(startsWith、比较、范围检查等)过滤元素,然后应用所需的转换,并把结果放入新列表。

5. 常见错误与陷阱

错误 1:在遍历时修改源集合。 常见问题是尝试在 for-each 循环中直接向源集合添加/删除元素。这会导致错误和不可预测的行为。解决方案:始终为结果创建一个新列表,并只向该列表写入。

错误 2:错误的类型转换。 如果你使用“原始类型”的集合(例如通过 Object)并把元素转换成错误的类型,就会得到 ClassCastException。请使用泛型(List<T>),并注意方法签名。

错误 3:资源使用低效。 对于非常大的集合,频繁创建新列表并拷贝元素,可能在内存和时间上都有明显开销。对大多数日常任务来说这可以接受,但在处理海量数据时要考虑复杂度,并在必要时优化方案。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION