【问题标题】:Sort a map based on value which is an arraylist java 8根据数组列表 java 8 的值对地图进行排序
【发布时间】:2020-09-16 18:44:55
【问题描述】:

我有一个哈希图map<String, List<Student>>

Student {
  String name;
  List<Date> absentDates;
}

键值对如下:

["Class1",<Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
["Class2",<Student3  absentDates = [02/12/2010]>]
["Class3",<Student4  absentDates = null>]

如何使用 java 8 流对这个地图进行排序,如下所示,基于地图值,即 List.get(0).getAbsentDates().get(0),即每个列表中第一个 Student 对象的可为空的缺席日期

预期输出是

["Class2",<Student3  absentDates = [02/12/2010]>]
["Class1",<Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
["Class3",<Student4  absentDates = null>]

【问题讨论】:

  • 您为什么使用null 列表而不是空列表?
  • 你没有问过类似的问题吗? stackoverflow.com/questions/63884675/…
  • 是的@Nikolas 我正在玩一些复杂的需求并在 java-8 中寻找一些最佳解决方案

标签: java java-8 java-stream collectors


【解决方案1】:

我遵循的步骤。

  1. Map 通过 entrySet 流式传输
  2. 转换为类 MapValues{Key,List}。 MapValue 是为保存键和值而创建的自定义包装类
  3. 基于 stundents.get(0).getAbsentDates().get(0) 为 MapValues 实现 Comaparator 并在 comaprator 中处理 null
  4. Collect使用Collectors.toMap保存订单使用LinkedHashMap

总之

Map<String, List<Student>> newmap = map.entrySet()
                                                .stream()
                                                .map(e -> new MapValues(e.getKey(), e.getValue()))
                                                .sorted(new MapValuesComp())
                                                .collect(Collectors.toMap(
                                                 MapValues::getKey, MapValues::getStdns, 
                                                             (e1, e2) -> e1, 
                                                            LinkedHashMap::new));
public class CustomMapSorting {
    public static void main(String[] args) throws ParseException {

        Map<String, List<Student>> map = new HashMap<>();
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        // Class1 Stundent1
        Date s1Date1 = format.parse("02/11/2010");
        Date s1Date2 = format.parse("02/09/2010");

        Date[] s1absentDates = { s1Date1, s1Date2 };
        Student s1 = new Student("Student1", Arrays.asList(s1absentDates));
        // Class1 Stundent2
        Date s2Date1 = format.parse("02/10/2010");

        Date[] s2absentDates = { s2Date1 };
        Student s2 = new Student("Student2", Arrays.asList(s2absentDates));

        // Class2 Stundent3

        Date s3Date1 = format.parse("02/12/2010");

        Date[] s3absentDates = { s3Date1 };
        Student s3 = new Student("Student3", Arrays.asList(s3absentDates));

        // Class3 Stundent4

        Student s4 = new Student("Stundent4", null);

        List<Student> class1SundLst = Arrays.asList(s1, s2);
        map.put("Class1", class1SundLst);
        map.put("Class2", Arrays.asList(s3));
        map.put("Class3", Arrays.asList(s4));

        Map<String, List<Student>> newmap = map.entrySet()
                                                .stream()
                                                .map(e -> new MapValues(e.getKey(), e.getValue()))
                                                .sorted(new MapValuesComp())
                                                .collect(Collectors.toMap(MapValues::getKey, MapValues::getStdns, (e1, e2) -> e1, LinkedHashMap::new));
        //Printing the sorted values
        newmap.entrySet().stream().forEach(e -> System.out.println(e.getKey() + " : " + e.getValue().get(0).absentDates));

    }

}

class MapValues {
    String key;
    List<Student> stdns;

    public MapValues(String key, List<Student> stdns) {
        super();
        this.key = key;
        this.stdns = stdns;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public List<Student> getStdns() {
        return stdns;
    }

    public void setStdns(List<Student> stdns) {
        this.stdns = stdns;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return key;
    }

}

class MapValuesComp implements Comparator<MapValues> {

    public int compare(MapValues o1, MapValues o2) {
        if (o1.stdns.get(0).absentDates == null) {
            return (o2.stdns.get(0).absentDates == null) ? 0 : 1;
        }
        if (o2.stdns.get(0).absentDates == null) {
            return 1;
        }
        return o2.stdns.get(0).absentDates.get(0).compareTo(o1.stdns.get(0).absentDates.get(0));

    }

}

class Student {
    String name;
    List<Date> absentDates;

    public Student(String name, List<Date> absentDates) {
        super();
        this.name = name;
        this.absentDates = absentDates;
    }

    @Override
    public String toString() {
        if (absentDates == null)
            return null;
        SimpleDateFormat format = new SimpleDateFormat("dd/mm/YYYY");
        return format.format(absentDates.get(0));
    }

}

【讨论】:

    【解决方案2】:

    我尝试了使用 @Rono 发布的答案中的 lambdas 的内联解决方案。只是他的解决方案的改进版本。

    Map<String, List<Student>> res = map.entrySet()
            .stream()
            .sorted((o1, o2) -> {
                if (o1.getValue().get(0).absentDates == null) {
                    return (o2.getValue().get(0).absentDates == null) ? 0 : 1;
                }
                if (o2.getValue().get(0).absentDates == null) {
                    return 1;
                }
                return o2.getValue().get(0).absentDates.get(0).compareTo(o1.getValue().get(0).absentDates.get(0));
            }).
            collect(Collectors.toMap(Map.Entry::getKey, 
                    Map.Entry::getValue,(e1, e2) -> e1, 
                    LinkedHashMap::new));
    

    【讨论】:

    • 如果没有泛型,它将是 Map 因此使用泛型
    • 实际上类型推断对我有用(Java 7+),这应该工作
    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2014-12-14
    • 2013-12-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多