Guava way to sort a list by another list?

I have a List<Integer> consisting of the identifiers of my users. And after querying the database, I retrieve the List<User> . I would like to order this list according to the first list of identifiers. List<User> may not include some identifiers. What is the guava way to sort this list?

+7
source share
5 answers

A fully "functional" way, using Guava, would combine Ordering#explicit() with 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 can declare an anonymous inline function, but I like to declare my functions as static factory methods in a separate class, for cleaner code (verbosity of Java function declarations is hidden in the utility class):

 /** * 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} 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(); } } } 
+12
source

I do not think that Guwa has anything specific for this. But this is just a matter of writing this comparator:

 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 as follows:

 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.

+9
source

Others have already answered your question using Guava. Here is Functional Java answer.

Please note that you will need to use immutable data structures from the library to take full advantage.

 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)); 
+2
source

Simple 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); } 
0
source

Here's how to do it with Java 8 lambdas.

 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 position in the list users.sort(Comparator.comparing(u -> rankMap.get(u.id()))); 
0
source

All Articles