Java 8 - 基于特定顺序的自定义排序

2022-09-04 01:15:47

我想根据用户列表的状态对用户列表进行排序,但顺序必须基于我设置的顺序。

我想设置列表的顺序,

顺序应为 1, 0 , 5。我们还应该记住对用户名进行排序。

List<User> users = new ArrayList();
         users.add(new User("A", 1));
         users.add(new User("B", 5));
         users.add(new User("C", 0));
         users.add(new User("D", 1));
         users.add(new User("E", 5));
         users.add(new User("F", 0));

下面是用户类

public class User {
         private String username;
         private Integer status;
     }

它应该看起来像这样

[
    {
      "username": "A",
      "status": 1
    },
    {
       "username": "D",
       "status": 1
    },
    {
       "username": "C",
       "status": 0
    },
    {
       "username": "F",
       "status": 0
    },
    {
       "username": "B",
       "status": 5
    },
    {
       "username": "E",
       "status": 5
    }
]

我不确定是否可以使用Compolarator.comparing,因为这个既不是升序也不是降序。


答案 1

一种方法是保存一个具有所需顺序的列表,并根据其索引对用户进行排序:

final List<Integer> order = Arrays.asList(1, 0, 5);
users.sort(
    Comparator.comparing((User u) -> order.indexOf(u.getStatus()))
              .thenComparing(User::getUsername));

请注意,虽然这种方法对于少量状态(就像您当前拥有的那样)应该是合理的,但如果存在大量状态并且每次都需要执行O(n)搜索,则可能会减慢排序速度。一种性能更好的方法(尽管可以说不是那么时尚),是使用地图:

final Map<Integer, Integer> order = new HashMap<>();
order.put(1, 0);
order.put(0, 1);
order.put(5 ,2);
users.sort(Comparator.comparing((User u) -> order.get(u.getStatus()))
                     .thenComparing(User::getUsername));

答案 2

如果您不介意在项目中使用番石榴,则可以使用:Ordering.explicit

users.sort(Ordering.explicit(1, 0, 5).onResultOf(User::getStatus));

如果您还想按名称排序,请添加:thenComparing

users.sort(Ordering
        .explicit(1, 0, 5)
        .onResultOf(User::getStatus)
        .thenComparing(User::getUsername));

推荐