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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:07:37  来源:igfitidea点击:

Guava way of sorting List according to another list?

javacollectionsguava

提问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 UserFunctionsclass:

正如@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())));