Java 将线性集合添加到映射

Java 将线性集合添加到映射,用户希望将对象集合添加到 Map,其中键为某种对象属性,值为对象本身。使用 Collectors 类定义的 toMap 方法以及 Function 接口定义的 identity 方法。这是一个简短且非常集中的用例,但本节讨论的解决方案可能为实际开发提供很大便利。

Java 将线性集合添加到映射 问题描述

用户希望将对象集合添加到 Map,其中键为某种对象属性,值为对象本身。

Java 将线性集合添加到映射 解决方案

使用 Collectors 类定义的 toMap 方法以及 Function 接口定义的 identity 方法。

Java 将线性集合添加到映射 具体实例

这是一个简短且非常集中的用例,但本节讨论的解决方案可能为实际开发提供很大便利。
假设存在一个由 Book 实例构成的 ListBook 是一个简单的 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 而非 ListMap 的键为图书 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,其中键为对象的属性,值为对象本身。

赞(3)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

Java 实例