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

Ken*_*thC 11 java sorting comparator java-8

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

我想设置列表的顺序,

订单应为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));
Run Code Online (Sandbox Code Playgroud)

这是用户类

public class User {
         private String username;
         private Integer status;
     }
Run Code Online (Sandbox Code Playgroud)

它看起来应该是这样的

[
    {
      "username": "A",
      "status": 1
    },
    {
       "username": "D",
       "status": 1
    },
    {
       "username": "C",
       "status": 0
    },
    {
       "username": "F",
       "status": 0
    },
    {
       "username": "B",
       "status": 5
    },
    {
       "username": "E",
       "status": 5
    }
]
Run Code Online (Sandbox Code Playgroud)

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

Mur*_*nik 9

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

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

请注意,虽然这种方法对于少数状态(如您目前所拥有)应该是合理的,但如果存在大量状态并且您每次都需要执行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));
Run Code Online (Sandbox Code Playgroud)


Zhe*_*lov 6

如果您不介意在项目中使用Guava,可以使用Ordering.explicit:

users.sort(Ordering.explicit(1, 0, 5).onResultOf(User::getStatus));
Run Code Online (Sandbox Code Playgroud)

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

users.sort(Ordering
        .explicit(1, 0, 5)
        .onResultOf(User::getStatus)
        .thenComparing(User::getUsername));
Run Code Online (Sandbox Code Playgroud)