简体   繁体   English

Java - 优化比较器操作对 POJO 列表进行排序

[英]Java - Optimise Comparator operation to sort a list of POJO

I'm writing a Comparator for one of my DTO.我正在为我的一个 DTO 编写一个Comparator器。

Each DTO object MyDTO contains a Set of Themes .每个 DTO object MyDTO包含一组Themes

class MyDTO {
    Long id;
    Set<Theme> themes;
}

class ThemeDTO {
    Long id;
    String title;
}

We've a given list of themeIDs as input, say Set<Long> inputThemes against which we've to make a comparison and sort list of MyDTOs.我们有一个给定的主题 ID 列表作为输入,比如Set<Long> inputThemes ,我们必须根据它对 MyDTO 的列表进行比较和排序。

Logic for comparison is:比较的逻辑是:

  1. If number of matching themes in myDto1 is more than in myDto2, then, myDto1 will come first.如果 myDto1 中匹配主题的数量多于 myDto2,则 myDto1 将首先出现。 (AND will precede OR). (AND 将在 OR 之前)。
  2. If number of matches are same, objects will be arranged alphabetically as per theme titles.如果匹配的数量相同,对象将按照主题标题按字母顺序排列。

I've written below comparator, but feels like it can be optimised further.我在比较器下面写过,但感觉可以进一步优化。

myDTOList.sort(new Comparator<MyDTO>() {
    @Override
    public int compare(MyDTO o1, MyDTO o2) {

        Set<Long> o1ThemeSet = o1.getThemes().stream().map(ThemeDTO::getId).collect(toSet());
        Set<Long> o2ThemeSet = o2.getThemes().stream().map(ThemeDTO::getId).collect(toSet());

        // Filtering w.r.t to themes coming as input
        Set<Long> inputThemeSet = inputThemes.stream().collect(toSet());
        o1ThemeSet.retainAll(inputThemeSet);
        o2ThemeSet.retainAll(inputThemeSet);

        if (o1ThemeSet.size() == o2ThemeSet.size()) {

            // If 2 MyDTO have same number of theme matches, sorting is done alphabetically.
            return o1.getTitle().toLowerCase().compareTo(o2.getTitle().toLowerCase());

        } else if (o1ThemeSet.size() < o2ThemeSet.size()) {
            return 1;
        } else {
            return -1;
        }
    }
});

Create a map for MyDTO list where store MyDTO#id as key and matched themes as value为 MyDTO 列表创建一个 map,其中将 MyDTO#id 存储为键,将匹配的主题存储为值

Set<Long> inputThemeSet = inputThemes.stream().collect(toSet());
Map<Long, Integer> map = new HashMap<>();
myDTOList.forEach(e -> {
    Integer cnt = (int)e.getThemes().stream().filter(k -> inputThemeSet.contains(k.getId())).count();
    map.put(e.getId(), cnt);
});

Then you can sort, here optimization is for same MyDTO you don't need to do upper operation for every two comparison MyDTO object.然后就可以排序了,这里优化的是同一个MyDTO,不需要对每两个比较MyDTO object做上层操作。 Number of comparison is huge bigger than list size.比较的数量比列表大小大得多。

myDTOList.sort(new Comparator<MyDTO>() {
    @Override
    public int compare(MyDTO o1, MyDTO o2) {
        if (map.get(o1.getId()) == map.get(o2.getId())) {
            return o1.getTitle().toLowerCase().compareTo(o2.getTitle().toLowerCase());
        } 
        return (map.get(o1.getId()) < map.get(o2.getId())) ? 1 : -1;
    }
});

Note: The code is untested hope you get the idea注意:代码未经测试希望你明白

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

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