简体   繁体   English

转换地图 <Key, List<Value> &gt;到地图 <Key, Value>

[英]Transforming Map<Key, List<Value>> to Map<Key, Value>

What I have: 是)我有的:

    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()));

I need to transform the Map to Map<Integer, Person> I know I need to use flatMap for that purpose but I don't know how. 我需要将Map转换为Map<Integer, Person>我知道我需要为此目的使用flatMap但我不知道如何。

What I have tried so far: Get the value-set and flatmap it. 到目前为止我尝试过的方法:获取值集并将其平面化。

Map <Integer, Person> list2 = list.values()
                                    .stream()
                                    .flatMap(f -> f.stream())
                                    .collect(Collectors.groupingBy(f -> f.name.length()); //doesn't work

Question: As far as I understand Java returns the values as lists when you create Maps via streams, how can I flatMap those lists ? 问:据我所知,当您通过流创建Maps时,Java会将值作为列表返回,我该如何对这些列表进行flatMap?

Additional info: Implementation of compareTo 附加信息: 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;
}

DISCLAIMER: 免责声明:

I know the use-case is a little bit odd since I sort according to length and also use compareTo by comparing the length of the name. 我知道用例有点奇怪,因为我根据长度排序,并通过比较名称的长度使用compareTo。 IMHO this doesn't matter for this question since I will always get a Map<Key, List<Value>> . 恕我直言这个问题无关紧要,因为我总是得到一个Map<Key, List<Value>> The question IS: How do I get Map<Key,Value> 问题是:我如何获得Map<Key,Value>

In fact your requirement does not make sense. 实际上你的要求没有意义。 You want to group by a property, which implies that it's not necessarily a bijective function. 您希望按属性进行分组,这意味着它不一定是双射函数。 Thus the type of the values of the resulting map is a list by default. 因此,默认情况下,结果映射的值的类型是列表。 If you know that the function you apply is bijective, you can supply another downstream collector / or use the toMap collector, having a throwing merger as parameter (the best option IMO). 如果您知道您应用的函数是双射的,则可以提供另一个下游收集器/或使用toMap收集器,将抛出合并作为参数(最佳选项IMO)。

So for example: 例如:

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());}));

outputs in your case: 在你的情况下输出:

{3=(John, Doe, 20), 4=(Bort, Bort, 30), 5=(Max, Power, 26), 7=(Scorpio, McGreat, 56)}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM