基于流创建地图

简单的情况没有重复的键

Stream<String> characters = Stream.of("A", "B", "C");

Map<Integer, String> map = characters
            .collect(Collectors.toMap(element -> element.hashCode(), element -> element));
// map = {65=A, 66=B, 67=C}

为了使事情更具说明性,我们可以在 Function 接口中使用静态方法 - Function.identity() 。我们可以用 Function.identity() 替换这个 lambda element -> element

可能存在重复键的情况

Collectors.toMapjavadoc 声明:

如果映射的键包含重复项(根据 Object.equals(Object)),则在执行收集操作时会抛出 IllegalStateException。如果映射的键可能有重复,请改用 toMap(Function, Function, BinaryOperator)

Stream<String> characters = Stream.of("A", "B", "B", "C");

Map<Integer, String> map = characters
            .collect(Collectors.toMap(
                element -> element.hashCode(),
                element -> element,
                (existingVal, newVal) -> (existingVal + newVal)));

// map = {65=A, 66=BB, 67=C}

传递给 Collectors.toMap(...)BinaryOperator 生成在碰撞情况下存储的值。它可以:

  • 返回旧值,以便流中的第一个值优先,
  • 返回新值,以便流中的最后一个值优先,或
  • 结合新旧值

按价值分组

当你需要执行等效的数据库级联分组依据操作时,可以使用 Collectors.groupingBy 。为了说明,下面创建了一个地图,其中人们的姓名被映射到姓氏:

List<Person> people = Arrays.asList(
    new Person("Sam", "Rossi"),
    new Person("Sam", "Verdi"),
    new Person("John", "Bianchi"),
    new Person("John", "Rossi"),
    new Person("John", "Verdi")
);

Map<String, List<String>> map = people.stream()
        .collect(
                // function mapping input elements to keys
                Collectors.groupingBy(Person::getName, 
                // function mapping input elements to values,
                // how to store values
                Collectors.mapping(Person::getSurname, Collectors.toList()))
        );

// map = {John=[Bianchi, Rossi, Verdi], Sam=[Rossi, Verdi]}

住在 Ideone 上