如何使用流从列表中对TreeMap进行排序

时间:2017-10-12 06:00:06

标签: java collections java-8 java-stream

我有一个课程说Level(它只是一个理解的虚拟课)。 我想要一个基于levelId的排序TreeMap<Level,Set<String>>。 请在下面找到代码

import java.util.*;
import java.util.stream.Collectors;

    public class Level {
        int levelId;

        public Level(int levelId) {
            this.levelId = levelId;
        }

        public static Level getLevel(String name){
            return new Level(name.length());
        }

        public static void main(String[]args){
            Set<String> names=new HashSet<>();
            names.add("Mahesh");
            names.add("Ram");
            names.add("Rita");

            Map<Level, Set<String>> map = names.stream().collect(
                    Collectors.groupingBy(name->Level.getLevel(name),
                    Collectors.mapping(name->name,Collectors.toSet())));

        }
    }

我也试过了Collectors.collectingAndThen()

感谢任何帮助。

提前致谢。

3 个答案:

答案 0 :(得分:4)

您修改后的工作代码如下所示,请参阅@ 4castle评论:

{{1}}

答案 1 :(得分:4)

如果您不想让Level实施Comparable,则需要Comparator。然后,您必须使用此分隔符作为地图工厂向TreeMap收集器传递创建groupingBy的lambda表达式:

public class Level {
    int levelId;

    public Level(int levelId) {
        this.levelId = levelId;
    }

    public static Level getLevel(String name){
        return new Level(name.length());
    }

    public int getLevelId() {
        return levelId;
    }

    public static void main(String[]args){
        Set<String> names=new HashSet<>();
        names.add("Mahesh");
        names.add("Ram");
        names.add("Rita");

        Comparator<Level> c = Comparator.comparingInt(Level::getLevelId);
        Map<Level, Set<String>> map = names.stream()
            .collect(Collectors.groupingBy(
                         Level::getLevel, () -> new TreeMap<>(c), Collectors.toSet()));
    }
}

答案 2 :(得分:1)

在我看来,使用流只能在最简单的情况下提高可读性。如果您有特定要求,例如需要特定Map实施,或者需要使用自定义Comparator,我强烈建议您使用for循环。是的,您可以在Collectors类中搜索适当的方法,但我相信如果您需要稍后再进行一次小更改,则生成的代码更难以遵循并且不太灵活。

在Java 8中,对Map接口进行了许多改进,这意味着在循环中执行此类操作现在比以前更少痛苦。

Map<Level, Set<String>> result = new TreeMap<>(Comparator.comparingInt(level -> level.levelId));
for (String name : names)
    result.computeIfAbsent(getLevel(name), k -> new HashSet<>()).add(name);

在这种情况下,我不确定为什么你想要一张带有Level键的地图。既然您想按ID进行分组,那么密钥是Integer是不是更有意义?

Map<Integer, Set<String>> result = new TreeMap<>();
for (String name : names)
    result.computeIfAbsent(getLevel(name).levelId, k -> new HashSet<>()).add(name);