List<Integer>
は、私のユーザーのIDで構成されています。データベースクエリの後に、私はList<User>
を取得しています。私は最初のIdリストに従ってこのリストを注文したいと思います。 List<User>
にはIdの一部が含まれていない可能性があります。このリストをソートするためのGuavaの方法は何ですか?Guavaのソート方法別リスト別リスト
答えて
完全に「機能的」な方法、グァバを使用して、あなたは無名関数をインライン宣言することができ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);
}
}
でOrdering#explicit()
を組み合わせたが、私は別のクラスのstaticファクトリメソッドとしての私の関数を宣言したいと思い、クリーンなコード(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();
}
}
}
私は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);
}
}
今、私はそれについて考える、それはまた、この方法を実装することができます。
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());
}
}
おそらくより効率的です。
これは、indexOfメソッドの線形時間要件のために効率的ではありません。ありがとう – Cemo
私の編集した答えを見てください。 –
その他は、すでにグァバを使用して、あなたの質問に答えています。ここにはFunctional Javaの回答があります。
ライブラリの不変なデータ構造を使用して、すべての利点を利用する必要があることに注意してください。 Googleのグアバ
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);
}
ありがとう:)このライブラリも大好きです。 :) – Cemo
脇に:Scalaでは、ソリューションは 'userList.sortBy(idList.indexOf(_。id))'になります。 – missingfaktor
私はjava 8と似たようなものを得ます;) – Premraj
より単純な答えはここでのJava 8ラムダでこれを行う方法です。
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())));
を使用して
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));
OPはnullがある可能性があるので、あなたはIDとしてnullが表示されないようにする必要があると思います –
java 8では、関数全体を取り除き、代わりにメソッド参照を使用することができます。その行は次のようになります(余分な関数はありません)。 orderById = Ordering.explicit(userIds).onResultOf(User :: getId); –
Arne