Search code examples
javacollectionsguava

Guava way of sorting List according to another list?


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?


Solution

  • The 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 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):

    /**
     * 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:

    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));
        }
    
    }