Java Stream - 创建已排序重复项的映射

Java Stream - Create a Map of Sorted Duplicates

我有一个对象列表,其中一些对象共享相似的 ID,但其余属性不同。我知道如何通过相似的 ID 对它们进行分组...

...
.stream()
.collect(groupingBy(obj -> obj.id, mapping(obj -> obj, toList())));

但是我想添加一个额外的逻辑层。我希望 Map 中的每个 List 按两个条件排序。

第一个条件,我想使用 contains 检查 obj.specialId 是否存在于单独的 Set 中。如果不是,那很好,但如果是,那么我希望该对象在 Set 中排在第一位。类似于 specialSet.contains(obj.specialId).

第二个条件是我想让它们按日期排序。这些对象有一个名为日期的属性,obj.date.

条件并不是很重要,我最困惑的是如何在 Map 中保留值的顺序。一旦我知道该怎么做,添加我想要的条件应该很容易。

据我了解,您需要从使用 set 切换到使用 list 才能保持元素之间的顺序。然后你需要三段基本代码:

  1. 像这个 lambda 这样的分类器:Thing::getId,这意味着使用 id 对它们进行分组。
  2. 数据结构的供应商表达式,映射是最简单的方法:HashMap::new
  3. 一个收集器,用于处理分组元素,例如 Collectors.collectingAndThen(...)

一个完整的例子:

public class Sandbox {


    public static <T> List<T> doThingWithList( List<T> list) {
        /**
         * Do some fancy things on your grouped elements
         * Such as sorting them
         */
        return list;
    }

    public static void main(String[] args){
        List<Thing> things = new ArrayList<>();
        things.add(new Thing(1,"first", "first ever"));
        things.add(new Thing(2,"second", "almost got first place"));
        things.add(new Thing(2,"second","sharing the second place is better than finishing third"));

        Map<Integer,List<Thing>> result = things.stream()
                .collect(
                        Collectors.groupingBy(Thing::getId, HashMap::new,
                                Collectors.collectingAndThen(Collectors.toList(), Sandbox::doThingWithList))
                );
        System.out.println(result);
    }

}