我所拥有的:

    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

问题:据我了解,当您通过流创建Maps时,Java将这些值作为列表返回,我如何flatMap这些列表?

附加信息: 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)}

07-28 13:03