返回

万花筒般的 Collectors.toMap():为 Stream 中的数据映射绘制七彩图形

后端

探索 Collectors.toMap() 的奇妙世界:用 Stream 点亮数据映射的七彩画布

引言

在 Java 8 的 Stream API 万花筒中,Collectors.toMap() 方法犹如一位魔术师,挥动法杖,将 Stream 中的数据元素瞬间变幻为 Map 结构。这是一项神奇的转换,就像从帽子中变出兔子,巧夺天工。

Collectors.toMap() 的基本原理

Collectors.toMap() 方法的基本原理很简单,只需两个参数:

  • keyMapper: 魔法师的助手,负责将每个 Stream 元素变为 Map 的钥匙。
  • valueMapper: 魔法师的帮手,负责将每个 Stream 元素变为 Map 的值。

代码示例:

// 用Collectors.toMap()方法变出名字和年龄的Map
Map<String, Integer> ages = people.stream()
    .collect(Collectors.toMap(Person::getName, Person::getAge));

在这个例子中,Stream 包含 Person 对象,Collectors.toMap() 方法挥动它的法杖,将每个 Person 对象的名字变为钥匙,年龄变为值,最终呈现出一幅名字到年龄的 Map 画卷。

Collectors.toMap() 的进阶秘籍

除了基本用法,Collectors.toMap() 还掌握着一些进阶秘籍,让我们探索一下:

指定 Map 的类型:

Collectors.toMap() 可以变出不同类型的 Map,比如 HashMap、TreeMap,由你指定:

// 用 Collectors.toMap() 方法变出 HashMap 名字和年龄的 Map
Map<String, Integer> ages = people.stream()
    .collect(Collectors.toMap(Person::getName, Person::getAge, (oldValue, newValue) -> oldValue, HashMap::new));

处理冲突:

当试图用两个相同的钥匙打开 Map 大门时,Collectors.toMap() 会发出抗议的叫声。但我们可以使用冲突处理策略,让它冷静下来:

// 使用“新的值替换旧的值”策略处理冲突
Map<String, Integer> ages = people.stream()
    .collect(Collectors.toMap(Person::getName, Person::getAge, (oldValue, newValue) -> newValue));

使用 Lambda 表达式:

Lambda 表达式就像魔术师的助手,可以让 Collectors.toMap() 更加灵活:

// 用 Lambda 表达式变出名字和年龄的 Map
Map<String, Integer> ages = people.stream()
    .collect(Collectors.toMap(p -> p.getName(), p -> p.getAge()));

Collectors.toMap() 的魔法场景

Collectors.toMap() 的魔法在现实世界中大显身手,让我们看看它的舞台:

从一个集合变到另一个集合:

Collectors.toMap() 可以挥舞法杖,将数据从一个集合变到另一个集合:

// 将 Person 对象的列表变为名字到 Person 对象的 Map
Map<String, Person> peopleMap = people.stream()
    .collect(Collectors.toMap(Person::getName, Function.identity()));

统计数据:

Collectors.toMap() 可以变出统计数据的魔术:

// 统计数字列表中每个数字出现的次数
Map<Integer, Long> numberCounts = numbers.stream()
    .collect(Collectors.toMap(Function.identity(), v -> 1L, (oldValue, newValue) -> oldValue + newValue));

查找数据:

Collectors.toMap() 可以帮你找到藏宝图上的宝藏:

// 查找名字为 "John" 的 Person 对象
Person person = peopleMap.get("John");

结论

Collectors.toMap() 是 Stream API 魔术师手中的一件利器,它可以将 Stream 中的数据元素变幻为色彩斑斓的 Map 结构。掌握了它的用法,你的代码将变得妙不可言。

常见问题解答

  1. Collectors.toMap() 和 putAll() 有什么区别?

    Collectors.toMap() 将 Stream 元素转换为 Map,而 putAll() 则将一个 Map 的键值对添加到另一个 Map 中。

  2. Collectors.toMap() 可以在并发环境中使用吗?

    不,Collectors.toMap() 不是线程安全的,并发使用可能会导致数据不一致。

  3. 如何自定义 Map 的排序顺序?

    使用 Collectors.toMap(Function.identity(), Function.identity(), (oldValue, newValue) -> oldValue, TreeMap::new) 可以使用 TreeMap 按照键的自然顺序排序。

  4. 如何处理空键或空值?

    Collectors.toMap() 会抛出 NullPointerException,因此在使用前需要检查空值。

  5. Collectors.toMap() 的时间复杂度是多少?

    Collectors.toMap() 的时间复杂度为 O(n),其中 n 是 Stream 中元素的数量。