映射的嵌套流 Java 11
Nested streams to a Map Java 11
假设您有一个接口、几个实现 类 和一个像这样的枚举:
接口:
public interface Employee {
// No two employees will have same favorite hobbies
List<Hobby> favoriteHobbies;
}
实施:
public class Employee1 implements Employee {
@Override
public List<Hobby> favoriteHobbies {
return List.of(Hobbies.swimming, Hobbies.dancing);
}
}
public class Employee2 implements Employee {
@Override
public List<Hobby> favoriteHobbies {
return List.of(Hobbies.running);
}
}
枚举:
public enum Hobby {
swimming,
running,
dancing
}
我有
List<Employee> employees = List.of(Employee1, Employee2);
并且使用 Streams,我想通过 employees
列表进行流式传输,然后再次通过每个 Employee 对象的 favoriteHobbies()
进行流式传输,并创建一个如下所示的 Map<Hobby, Employee>
:
"swimming" -> "Employee1"
"dancing" -> "Employee1"
"running" -> "Employee2"
我会在 Stream
中创建一个 Map.Entry
,然后使用它的键和值收集它
因为 java-16 这可以使用 Stream#mapMulti
Map<Hobby, Employee> map = employees.stream()
.mapMulti((Employee employee, Consumer<AbstractMap.SimpleEntry<Hobby, Employee>> consumer) -> {
employee.favoriteHobbies().forEach(hobby -> {
consumer.accept(new AbstractMap.SimpleEntry<>(hobby, employee));
});
})
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue,
(entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
));
在 java-16 之前,可以使用 Stream#flatMap
和 Collectors#toMap
Map<Hobby, Employee> map = employees.stream()
.flatMap(employee -> employee.favoriteHobbies()
.stream()
.map(hobby -> new AbstractMap.SimpleEntry<>(hobby, employee)))
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue,
(entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
));
产生
因为 Java 9 可以使用 Map.entry
,还应该构造一个 LinkedHashMap
来维护映射条目的插入顺序:
Map<Hobby, Employee> map = employees()
.stream()
.flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a,
LinkedHashMap::new
));
但是,如果输入 employees
列表包含多个不同实现的实例,使用 Stream::flatMap
、Collectors::groupingBy
构建映射 Map<Hobby, List<Employee>>
会更有意义Collectors::mapping
, Collectors::toList
:
List<Employee> employeeList = List.of(
new Employee1("John"), new Employee1("Jack"), new Employee2("Jeff"),
new Employee1("Jake"), new Employee2("Jean")
);
Map<Hobby, List<Employee>> mapList = employees()
.stream()
.flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
.collect(Collectors.groupingBy(
Map.Entry::getKey,
LinkedHashMap::new,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())
));
假设您有一个接口、几个实现 类 和一个像这样的枚举: 接口:
public interface Employee {
// No two employees will have same favorite hobbies
List<Hobby> favoriteHobbies;
}
实施:
public class Employee1 implements Employee {
@Override
public List<Hobby> favoriteHobbies {
return List.of(Hobbies.swimming, Hobbies.dancing);
}
}
public class Employee2 implements Employee {
@Override
public List<Hobby> favoriteHobbies {
return List.of(Hobbies.running);
}
}
枚举:
public enum Hobby {
swimming,
running,
dancing
}
我有
List<Employee> employees = List.of(Employee1, Employee2);
并且使用 Streams,我想通过 employees
列表进行流式传输,然后再次通过每个 Employee 对象的 favoriteHobbies()
进行流式传输,并创建一个如下所示的 Map<Hobby, Employee>
:
"swimming" -> "Employee1"
"dancing" -> "Employee1"
"running" -> "Employee2"
我会在 Stream
中创建一个 Map.Entry
,然后使用它的键和值收集它
因为 java-16 这可以使用 Stream#mapMulti
Map<Hobby, Employee> map = employees.stream()
.mapMulti((Employee employee, Consumer<AbstractMap.SimpleEntry<Hobby, Employee>> consumer) -> {
employee.favoriteHobbies().forEach(hobby -> {
consumer.accept(new AbstractMap.SimpleEntry<>(hobby, employee));
});
})
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue,
(entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
));
在 java-16 之前,可以使用 Stream#flatMap
和 Collectors#toMap
Map<Hobby, Employee> map = employees.stream()
.flatMap(employee -> employee.favoriteHobbies()
.stream()
.map(hobby -> new AbstractMap.SimpleEntry<>(hobby, employee)))
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue,
(entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
));
产生
因为 Java 9 可以使用 Map.entry
,还应该构造一个 LinkedHashMap
来维护映射条目的插入顺序:
Map<Hobby, Employee> map = employees()
.stream()
.flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a,
LinkedHashMap::new
));
但是,如果输入 employees
列表包含多个不同实现的实例,使用 Stream::flatMap
、Collectors::groupingBy
构建映射 Map<Hobby, List<Employee>>
会更有意义Collectors::mapping
, Collectors::toList
:
List<Employee> employeeList = List.of(
new Employee1("John"), new Employee1("Jack"), new Employee2("Jeff"),
new Employee1("Jake"), new Employee2("Jean")
);
Map<Hobby, List<Employee>> mapList = employees()
.stream()
.flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
.collect(Collectors.groupingBy(
Map.Entry::getKey,
LinkedHashMap::new,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())
));