基于流创建地图
简单的情况没有重复的键
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.toMap
的 javadoc 声明:
如果映射的键包含重复项(根据
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]}