java 根据另一个列表对列表进行排序的番石榴方式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10930443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Guava way of sorting List according to another list?
提问by Cemo
I have List<Integer>
consisting Ids of my Users. And after a database query, I am retrieving List<User>
. I would like to order this list according to first Id list. List<User>
may not include some of the Ids. What is the Guava way for sorting this list?
我有List<Integer>
我的用户的 ID。在数据库查询之后,我正在检索List<User>
. 我想根据第一个 Id 列表对这个列表进行排序。List<User>
可能不包括某些 ID。对这个列表进行排序的 Guava 方式是什么?
回答by Etienne Neveu
The fully "functional" way, using Guava, would combine Ordering#explicit()
with Ordering#onResultOf()
使用 Guava 的完全“功能”方式将Ordering#explicit()
与Ordering#onResultOf()
public class UserService {
@Inject private UserDao userDao;
public List<User> getUsersWithIds(List<Integer> userIds) {
List<User> users = userDao.loadUsersWithIds(userIds);
Ordering<User> orderById = Ordering.explicit(userIds).onResultOf(UserFunctions.getId());
return orderById.immutableSortedCopy(users);
}
}
You could declare an anonymous function inline, but I like to declare my functions as static factory methods in a separate class, for a cleaner code (the verbosity of Java's function declarations is hidden in the utility class):
您可以内联声明一个匿名函数,但我喜欢在单独的类中将我的函数声明为静态工厂方法,以获得更清晰的代码(Java 函数声明的冗长隐藏在实用程序类中):
/**
* Static factory methods to create {@link Function}s for {@link User}s.
*/
public final class UserFunctions {
private UserFunctions() { /* prevents instantiation */ }
/**
* @return a {@link Function} that returns an {@link User}'s id.
*/
public static Function<User, Integer> getId() {
return GetIdFunction.INSTANCE;
}
// enum singleton pattern
private enum GetIdFunction implements Function<User, Integer> {
INSTANCE;
public Integer apply(User user) {
return user.getId();
}
}
}
As mentioned by @Arne in a comment, this can be simplified in Java 8, using a method reference instead of the UserFunctions
class:
正如@Arne 在评论中提到的,这可以在 Java 8 中简化,使用方法引用而不是UserFunctions
类:
public class UserService {
@Inject private UserDao userDao;
public List<User> getUsersWithIds(List<Integer> userIds) {
List<User> users = userDao.loadUsersWithIds(userIds);
Ordering<User> orderById = Ordering.explicit(userIds).onResultOf(User::getId);
return orderById.immutableSortedCopy(immutableSortedCopy(users));
}
}
回答by JB Nizet
I don't think Guava has anything specific to do this. But it's just a matter of writing this comparator:
我不认为 Guava 有任何具体的东西可以做到这一点。但这只是编写这个比较器的问题:
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
int i1 = idList.indexOf(u1.getId());
int i2 = idList.indexOf(u2.getId());
return Ints.compare(i1, i2);
}
}
Now that I think about it, it can also be implemented this way:
现在想想,也可以这样实现:
final Ordering<Integer> idOrdering = Ordering.explicit(idList);
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return idOrdering.compare(u1.getId(), u2.getId());
}
}
which is probably more efficient.
这可能更有效。
回答by missingfaktor
Others have already answered your question using Guava. Here is a Functional Javaanswer.
其他人已经使用 Guava 回答了您的问题。这是一个功能性 Java答案。
Please note that you'll have to use immutable data structures from the library in order to avail of all the goodness.
请注意,您必须使用库中的不可变数据结构才能利用所有优点。
F<User, Integer> indexInIdList = new F<User, Integer>() {
public Integer f(User u) {
return idList.elementIndex(Equal.intEqual, u.getId()).toNull();
}
};
userList.sort(Ord.intOrd.comap(indexInIdList));
回答by Marcello de Sales
Simpler answer using Google Guava
使用谷歌番石榴更简单的答案
class Form {
public Integer index; // for simplicity, no setter/getter included
}
List<Form> forms = ... // list instances, each of each with values for index
// ordering of forms by the ui sort index.
private static final Ordering<Form> sorter = Ordering.natural().onResultOf(new Function<Form, Integer>() {
@Override
public Integer apply(Form form) {
return form.index;
}
});
private List<Form> sortForms(List<Form> forms) {
return sorter.sortedCopy(forms);
}
回答by Jeffrey Bosboom
Here's how to do this with Java 8 lambdas.
以下是如何使用 Java 8 lambda 执行此操作。
List<Integer> ids = ...; List<User> users = ...;
//map ids to their list indices, to avoid repeated indexOf calls
Map<Integer, Integer> rankMap = IntStream.range(0, ids.size()).boxed()
.collect(Collectors.toMap(ids::get, Function.identity()));
//sort on the id's position in the list
users.sort(Comparator.comparing(u -> rankMap.get(u.id())));