Java 8 - 根据特定顺序自定义排序
Java 8 - customised sort based on specific order
我想根据用户状态对用户列表进行排序,但顺序必须基于我设置的顺序。
我想设置列表的顺序,
顺序应该是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));
这是用户class
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
}
]
我不确定是否可以使用Comparator.comparing,因为这个既不是升序也不是降序。
如果你不介意在你的项目中使用Guava,你可以使用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));
一种方法是按照您想要的顺序保存一个列表,并根据其索引对用户进行排序:
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));
假设 1
、0
和 5
将是 status
的唯一值,AJNeufeld 在 中提出了一个很好的观点;他们说您可以使用方程式将每个值映射到升序。在这种情况下,等式将是 (x - 1)^2
,其中 x
是 status
的值:
users.sort(Comparator.comparingDouble(user -> Math.pow(user.getStatus() - 1, 2)));
如果您在调用上述代码段后打印 user
的内容,您将得到:
[User [username=A, status=1], User [username=D, status=1], User [username=C, status=0], User [username=F, status=0], User [username=B, status=5], User [username=E, status=5]]
你可以尝试一步一步来
//order define here
List<Integer> statusOrder= Arrays.asList(1,0,5,2);
//define sort by status
Comparator<User> byStatus = (u1, u2) -> {
return Integer.compare(statusOrder.indexOf(u1.getStatus()), statusOrder.indexOf(u2.getStatus()));
};
//define sort by name
Comparator<User> byName = Comparator.comparing(User::getUsername);
//actualy sort
users.sort(byStatus.thenComparing(byName));
正如您所提到的,您需要自定义排序,这意味着您需要在 HashMap<Status,Rank>> 中的某处定义排序,或者通过一种简单的方法添加一个属性说 整数排名; 并且您可以根据状态属性的顺序定义排名,例如 users.add(new User("A", 1,0));这里状态 1 按顺序排序,其等级 = 0。然后你可以在等级属性.
上使用Comparator
例如:
public class User {
public String username;
public Integer status;
public Integer rank;
public User(String username, Integer status, Integer rank)
{
this.username = username;
this.status = status;
this.rank = rank;
}
}
比较器class:
class SortByRank implements Comparator<User>
{
// Used for sorting in ascending order of
// rank number
public int compare(User a, User b)
{
return a.rank - b.rank;
}
}
主要 Class :
class Main
{
public static void main (String[] args)
{
List<User> users = new ArrayList();
users.add(new User("A", 1, 0));
users.add(new User("B", 5, 2));
users.add(new User("C", 0, 1));
users.add(new User("D", 1, 0));
users.add(new User("E", 5, 2));
users.add(new User("F", 0, 1));
System.out.println("Unsorted");
for (int i=0; i<users.size(); i++)
System.out.print(users.get(i).username);
Collections.sort(users, new SortByRank());
System.out.println("\nSorted by Rank");
for (int i=0; i<users.size(); i++)
System.out.print(users.get(i).username);
}
}
我想根据用户状态对用户列表进行排序,但顺序必须基于我设置的顺序。
我想设置列表的顺序,
顺序应该是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));
这是用户class
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
}
]
我不确定是否可以使用Comparator.comparing,因为这个既不是升序也不是降序。
如果你不介意在你的项目中使用Guava,你可以使用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));
一种方法是按照您想要的顺序保存一个列表,并根据其索引对用户进行排序:
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));
假设 1
、0
和 5
将是 status
的唯一值,AJNeufeld 在 (x - 1)^2
,其中 x
是 status
的值:
users.sort(Comparator.comparingDouble(user -> Math.pow(user.getStatus() - 1, 2)));
如果您在调用上述代码段后打印 user
的内容,您将得到:
[User [username=A, status=1], User [username=D, status=1], User [username=C, status=0], User [username=F, status=0], User [username=B, status=5], User [username=E, status=5]]
你可以尝试一步一步来
//order define here
List<Integer> statusOrder= Arrays.asList(1,0,5,2);
//define sort by status
Comparator<User> byStatus = (u1, u2) -> {
return Integer.compare(statusOrder.indexOf(u1.getStatus()), statusOrder.indexOf(u2.getStatus()));
};
//define sort by name
Comparator<User> byName = Comparator.comparing(User::getUsername);
//actualy sort
users.sort(byStatus.thenComparing(byName));
正如您所提到的,您需要自定义排序,这意味着您需要在 HashMap<Status,Rank>> 中的某处定义排序,或者通过一种简单的方法添加一个属性说 整数排名; 并且您可以根据状态属性的顺序定义排名,例如 users.add(new User("A", 1,0));这里状态 1 按顺序排序,其等级 = 0。然后你可以在等级属性.
上使用Comparator例如:
public class User {
public String username;
public Integer status;
public Integer rank;
public User(String username, Integer status, Integer rank)
{
this.username = username;
this.status = status;
this.rank = rank;
}
}
比较器class:
class SortByRank implements Comparator<User>
{
// Used for sorting in ascending order of
// rank number
public int compare(User a, User b)
{
return a.rank - b.rank;
}
}
主要 Class :
class Main
{
public static void main (String[] args)
{
List<User> users = new ArrayList();
users.add(new User("A", 1, 0));
users.add(new User("B", 5, 2));
users.add(new User("C", 0, 1));
users.add(new User("D", 1, 0));
users.add(new User("E", 5, 2));
users.add(new User("F", 0, 1));
System.out.println("Unsorted");
for (int i=0; i<users.size(); i++)
System.out.print(users.get(i).username);
Collections.sort(users, new SortByRank());
System.out.println("\nSorted by Rank");
for (int i=0; i<users.size(); i++)
System.out.print(users.get(i).username);
}
}