Java 将线性集合添加到映射,用户希望将对象集合添加到 Map
,其中键为某种对象属性,值为对象本身。使用 Collectors
类定义的 toMap
方法以及 Function
接口定义的 identity
方法。这是一个简短且非常集中的用例,但本节讨论的解决方案可能为实际开发提供很大便利。
Java 将线性集合添加到映射 问题描述
用户希望将对象集合添加到 Map
,其中键为某种对象属性,值为对象本身。
Java 将线性集合添加到映射 解决方案
使用 Collectors
类定义的 toMap
方法以及 Function
接口定义的 identity
方法。
Java 将线性集合添加到映射 具体实例
这是一个简短且非常集中的用例,但本节讨论的解决方案可能为实际开发提供很大便利。
假设存在一个由 Book
实例构成的 List
。Book
是一个简单的 POJO,由 ID、书名、价格参数构成。Book
类的简单形式如例 4-13 所示。
例 4-13
Book
类(描述图书的简单 POJO)
public class Book {
private int id;
private String name;
private double price;
// 其他方法
}
此外,假设存在一个由 Book
实例构成的集合,如例 4-14 所示。
例 4-14 图书集合
List<Book> books = Arrays.asList(
new Book(1, "Modern Java Recipes", 49.99),
new Book(2, "Java 8 in Action", 49.99),
new Book(3, "Java SE8 for the Really Impatient", 39.99),
new Book(4, "Functional Programming in Java", 27.64),
new Book(5, "Making Java Groovy", 45.99)
new Book(6, "Gradle Recipes for Android", 23.76)
);
很多情况下,我们需要的可能是 Map
而非 List
,Map
的键为图书 ID,值为图书本身。借由 Collectors.toMap
方法,很容易就能将图书添加到 Map
,例 4-15 显示了两种不同的方案。
例 4-15 将图书添加到
Map
Map<Integer, Book> bookMap = books.stream()
.collect(Collectors.toMap(Book::getId, b -> b)); ➊
bookMap = books.stream()
.collect(Collectors.toMap(Book::getId, Function.identity())); ➋
❶ lambda 标识:给定一个元素并返回
❷ 静态方法 Function.identity
可以实现同样的目的
toMap
方法传入两个 Function
实例作为参数,根据所提供的对象,两个函数分别生成键和值。在本例中,键由 Book::getId
映射,值为图书本身。
可以看到,第一个 toMap
方法传入两个参数,一个是映射到键的 getId
,另一个是返回参数的显式 lambda 表达式。第二个 toMap
方法通过静态方法 Function.identity
实现相同的目的。
两种静态 identity
方法
静态方法 Function.identity
的签名如下:
static <T> Function<T,T> identity()
它在 Java 标准库中的实现如例 4-16 所示。
例 4-16
Function.identity
方法
static <T> Function<T, T> identity() {
return t -> t;
}
UnaryOperator
接口是 Function
的子接口,但无法重写静态方法。根据 Javadoc 的描述,UnaryOperator
接口也声明了一个称为 identity
的静态方法:
static <T> UnaryOperator<T> identity()
UnaryOperator.identity
方法在 Java 标准库中的实现与 Function.identity
方法基本相同,如例 4-17 所示。
例 4-17
UnaryOperator.identity
方法
static <T> UnaryOperator<T> identity() {
return t -> t;
}
二者的区别仅在于调用方式(不同的接口名)和相应的返回类型有所不同。使用哪种 identity
方法均可,这里将两种方法列出供读者参考。
无论是提供显式的 lambda 表达式抑或使用静态方法,只是编程风格不同而已。两种方案都能很容易地将集合值添加到 Map
,其中键为对象的属性,值为对象本身。