首页 > 解决方案 > 按另一个列表对列表进行排序

问题描述

我有一个小问题让我发疯。

我有一个

我必须通过将第一个列表中包含的 id 元素放在顶部,然后按字符串 asc 和第二个字符串 asc 对第二个列表进行排序。

使这项工作最简单的方法是什么?我正在尝试使用 .sort()、比较器等。

一个例子:

@Getter
@Setter
public class ObjectA {
      private Integer id;
      private String code;
      private String name;
}

// comparator:
    static class SortByCode implements Comparator<ObjectA> {
        public int compare(ObjectA a, ObjectA b) {
            String as = a.getCode();
            String bs = b.getCode();

            return as.compareTo(bs);
        }
    }
    static class SortByName implements Comparator<ObjectA> {
        public int compare(ObjectA a, ObjectA b) {
            String as = a.getName();
            String bs = b.getName();

            return as.compareTo(bs);
        }
    }

// then in service:  
List<Integer> idsPreferred = new ArrayList<>();
List<ObjectA> listObj = new ArrayList<>();

idsPreferred = .... add preferred ids;
listObj = .... add objects;  
listObj.sort(new SortByCode()).thenComparing(new SortByName());

有了这个,我按代码和名称排序 - 但我需要按第一个列表添加排序 - 我需要列表中包含 id 的元素排在其他元素之前。

标签: javasortingcomparator

解决方案


我想像这样使用提取键的链式比较:

listObj.sort(Comparator.comparing(o -> !idsPreferred.contains(((ObjectA) o).getId()))
                       .thenComparing(o -> ((ObjectA) o).getId())
                       .thenComparing(o -> ((ObjectA) o).getCode())
                       .thenComparing(o -> ((ObjectA) o).getName()));

或者

listObj.sort(Comparator.comparing(ObjectA::getId,
                                  (id1,id2)-> {if (!((idsPreferred.contains(id1))^idsPreferred.contains(id2)))
                                                  return 0;
                                               else return (idsPreferred.contains(id2))?1:-1;})
                       .thenComparing(ObjectA::getId)
                       .thenComparing(ObjectA::getCode)
                       .thenComparing(ObjectA::getName));

推荐阅读