【发布时间】:2015-06-25 12:40:09
【问题描述】:
我有什么:
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 会将值作为列表返回,我如何对这些列表进行平面映射?
附加信息: 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)。 -
如果两个名字完全相等(根据 compareTo),那么 Person 将不会被添加到列表中,因为它是一个 Set,但恕我直言,这对于如何对列表进行平面映射的问题并不重要.
-
你用来分组的属性是长度。所以你可以有两个不同的名字(因此在集合中)具有相同的长度......
-
你能给出一个代码示例吗? p.s:即使该列表仅包含一个元素,我也总是得到一个列表。恕我直言,这是否有意义并不重要,因为列表仍然存在。那么我怎样才能 flatMap 呢?
标签: java java-8 java-stream