将 Map<Key, List<Value>> 转换为 Map<Key, Value>
Transforming Map<Key, List<Value>> to Map<Key, Value>
我有:
SortedSet<Person> ss = new TreeSet<>();
ss.add(new Person("John", "Doe", 20));
ss.add(new Person("Max", "Power", 26));
ss.add(new Person("Bort", "Bort", 30));
ss.add(new Person("Scorpio", "McGreat", 56));
Map<Integer, List<Person>> list = ss.stream().collect(Collectors.groupingBy(p -> p.name.length()));
我需要将 Map 转换为 Map<Integer, Person>
我知道我需要为此目的使用 flatMap,但我不知道如何使用。
到目前为止我已经尝试过:获取值集并将其平面化。
Map <Integer, Person> list2 = list.values()
.stream()
.flatMap(f -> f.stream())
.collect(Collectors.groupingBy(f -> f.name.length()); //doesn't work
问题: 据我了解Java returns 当您通过流创建地图时,值作为列表,我如何平面化这些列表?
附加信息: compareTo
的实现
@Override
public int compareTo(Person o) {
int cmp = this.surname.compareTo(o.surname);
if(cmp == 0){
cmp = this.name.compareTo(o.name);
}
return cmp;
}
免责声明:
我知道这个用例有点奇怪,因为我根据长度排序并通过比较名称的长度来使用 compareTo。恕我直言,这对于这个问题并不重要,因为我总是会得到 Map<Key, List<Value>>
。
问题是:我如何获得 Map<Key,Value>
其实你的要求没有意义。您想要按 属性 分组,这意味着它不一定是双射函数。因此,结果映射的值类型默认为列表。如果您知道您应用的函数是双射的,您可以提供另一个下游收集器/或使用 toMap 收集器,将抛出合并作为参数(IMO 的最佳选择)。
例如:
Map<Integer, Person> list =
ss.stream()
.collect(Collectors.toMap(p -> p.surname.length(),
p -> p,
(p1, p2) -> {throw new IllegalStateException("Duplicate key with length " + p1.surname.length());}));
您的案例输出:
{3=(John, Doe, 20), 4=(Bort, Bort, 30), 5=(Max, Power, 26), 7=(Scorpio, McGreat, 56)}
我有:
SortedSet<Person> ss = new TreeSet<>();
ss.add(new Person("John", "Doe", 20));
ss.add(new Person("Max", "Power", 26));
ss.add(new Person("Bort", "Bort", 30));
ss.add(new Person("Scorpio", "McGreat", 56));
Map<Integer, List<Person>> list = ss.stream().collect(Collectors.groupingBy(p -> p.name.length()));
我需要将 Map 转换为 Map<Integer, Person>
我知道我需要为此目的使用 flatMap,但我不知道如何使用。
到目前为止我已经尝试过:获取值集并将其平面化。
Map <Integer, Person> list2 = list.values()
.stream()
.flatMap(f -> f.stream())
.collect(Collectors.groupingBy(f -> f.name.length()); //doesn't work
问题: 据我了解Java returns 当您通过流创建地图时,值作为列表,我如何平面化这些列表?
附加信息: compareTo
的实现@Override
public int compareTo(Person o) {
int cmp = this.surname.compareTo(o.surname);
if(cmp == 0){
cmp = this.name.compareTo(o.name);
}
return cmp;
}
免责声明:
我知道这个用例有点奇怪,因为我根据长度排序并通过比较名称的长度来使用 compareTo。恕我直言,这对于这个问题并不重要,因为我总是会得到 Map<Key, List<Value>>
。
问题是:我如何获得 Map<Key,Value>
其实你的要求没有意义。您想要按 属性 分组,这意味着它不一定是双射函数。因此,结果映射的值类型默认为列表。如果您知道您应用的函数是双射的,您可以提供另一个下游收集器/或使用 toMap 收集器,将抛出合并作为参数(IMO 的最佳选择)。
例如:
Map<Integer, Person> list =
ss.stream()
.collect(Collectors.toMap(p -> p.surname.length(),
p -> p,
(p1, p2) -> {throw new IllegalStateException("Duplicate key with length " + p1.surname.length());}));
您的案例输出:
{3=(John, Doe, 20), 4=(Bort, Bort, 30), 5=(Max, Power, 26), 7=(Scorpio, McGreat, 56)}