Java 如何使用streams从列表中对树映射进行排序

Java 如何使用streams从列表中对树映射进行排序,java,collections,java-8,java-stream,Java,Collections,Java 8,Java Stream,我有一个类say级别(它只是一个用于理解的虚拟类)。 我想要一个基于levelId的排序的树映射。 请查找下面的代码 import java.util.*; import java.util.stream.Collectors; public class Level { int levelId; public Level(int levelId) { this.levelId = levelId; }

我有一个类say级别(它只是一个用于理解的虚拟类)。 我想要一个基于levelId的排序的
树映射。
请查找下面的代码

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

        }
    }
import java.util.*;
导入java.util.stream.collector;
公营班级{
int-levelId;
公共级别(int-levelId){
this.levelId=levelId;
}
公共静态级别getLevel(字符串名称){
返回新级别(name.length());
}
公共静态void main(字符串[]args){
Set name=新的HashSet();
名称。添加(“Mahesh”);
名称。添加(“Ram”);
姓名。添加(“丽塔”);
Map Map=names.stream().collect(
收集器.groupingBy(名称->级别.getLevel(名称),
Collectors.mapping(name->name,Collectors.toSet());
}
}
我还尝试了
收集器。collectingAndThen()

感谢您的帮助


提前感谢。

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

public class Level implements Comparable<Level> {
    int levelId;

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

    @Override
    public int compareTo(Level o) {
        return Integer.compare(levelId, o.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(Level::getLevel, TreeMap::new,
                        Collectors.toSet()));
    }
}
公共类级别实现了可比较的{
int-levelId;
公共级别(int-levelId){
this.levelId=levelId;
}
@凌驾
公共内部比较(o级){
返回整数。比较(levelId,o.levelId);
}
公共静态级别getLevel(字符串名称){
返回新级别(name.length());
}
公共静态void main(字符串[]args){
Set name=新的HashSet();
名称。添加(“Mahesh”);
名称。添加(“Ram”);
姓名。添加(“丽塔”);
Map Map=names.stream().collect(
Collectors.groupby(Level::getLevel,TreeMap::new,
Collectors.toSet());
}
}

在我看来,使用流只能在最简单的情况下提高可读性。如果您有特定的需求,例如需要特定的
映射
实现,或者需要使用自定义的
比较器
,我强烈建议您使用for循环。是的,您可以在
收集器
类中搜索合适的方法,但我相信生成的代码更难理解,如果以后需要进行另一个小更改,那么灵活性也会降低

在Java8中,
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);

如果不想让
级别
实现
可比
,则需要一个
比较器
。然后,必须使用此分隔符作为映射工厂,将创建树映射的lambda表达式传递给
groupingBy
收集器:

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()));
    }
}
公共类级别{
int-levelId;
公共级别(int-levelId){
this.levelId=levelId;
}
公共静态级别getLevel(字符串名称){
返回新级别(name.length());
}
public int getLevelId(){
返回levelId;
}
公共静态void main(字符串[]args){
Set name=新的HashSet();
名称。添加(“Mahesh”);
名称。添加(“Ram”);
姓名。添加(“丽塔”);
Comparator c=Comparator.comparingInt(Level::getLevelId);
Map Map=names.stream()
.collect(收集器.groupingBy(
Level::getLevel,()->newtreemap(c),Collectors.toSet();
}
}

使用for循环而不是streams
收集器。groupingBy(Level::getLevel,TreeMap::new,Collectors.toSet())
尝试收集器。groupingBy(Level::getLevel,TreeMap::new,Collectors.mapping(l->l,Collectors.toSet())@Nidhi257用于
TreeMap
根据
levelId
进行排序,您需要使
Level
实现
Comparable
接口。我想,问题的
Level-getLevel(String-name)
方法只是实际操作的占位符。有。顺便说一下,我不认为a的可读性不如循环选项。在某些情况下,循环更好,但我不会说这里已经越过了阈值。
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()));
    }
}