Create/Sort 列表<X> 值的排序与列表<Y> 中的相同

Create/Sort List<X> with values ordered the same as in List<Y>

我有一个对象列表 A,用于检索另一个对象列表 B。但是第二个列表是随机排序的。两种对象类型都有 id 属性 的共同点。

我现在在做什么:

List<A> input = ...;
List<B> output = new ArrayList<>();
for(A a : input) {
    output.add(getOutputObjectById(a.getId()));
}

问题是,getOutputObjectById 相当昂贵。还有另一种方法 getOutputObjectsByIds 需要 Collection 个 id 和 returns List<B>但是元素的顺序可以不同。虽然我需要一种方法来确保两个列表最后的排序相同。

我首先想到使用 LinkedHashMap 并执行如下操作:

List<A> input = ...;
List<B> output = new ArrayList<>();
LinkedHashMap<String, Object> intermediate = new LinkedHashMap<String, Object>();
for(A a : input) {
    intermediate.put(a.getId(), a);
}
for(B b : getOutputObjectsByIds(intermediate.keySet())) {
    intermediate.put(b.getId(), b);
}
for(Object o : intermediate.values()) {
    output.add((B) o);
}

这么多代码,在多个集合中复制对象等等

我真的希望,有一个更短、更优雅的方法来做到这一点。

你有什么想法吗?

看起来你标记了这个 java-8 所以我将提供流的使用:

List<A> input = ...;
HashMap<IdClass, B> bsById = new HashMap<>();
for(B b : getOutputObjectsByIds(input.stream().map(A::getId).collect(Collectors.toList()))){
    bsById.put(b.getId(), b);
}
return input.stream().map((A a)->bsById.get(a.getId())).collect(Collectors.toList());

这使用中间 HashMap,以避免对 input 的每个成员的列表进行并行扫描的 O(n^2) 情况。

基于 hexafraction 的工作,我创建了一个非常相似的解决方案,它不会创建新的 List,而是对给定的 List:

进行排序
/*
 * converts a Collection<T> to Map<ID, T>
 * ID is specified by the keyFunction
 */
public static <T, ID> Map<ID, T> collectionToMap(Collection<T> collection, Function<T, ID> keyFunction) {
    return collection.stream().collect(Collectors.toMap(keyFunction, Function.identity()));
}

/*
 * sorts List<T> to have the same ordering as List<O>
 * two functions have to be provided, that are used to get the List's ID
 */
public static <T, O, ID> void sortListByObjects(List<T> list, Function<T, ID> listIdFunction, List<O> objects, Function<O, ID> objectIdFunction) {
    Map<ID, T> map = collectionToMap(list, listIdFunction);
    for(int i = 0; i < objects.size(); i++) {
        list.set(i, map.get(objectIdFunction.apply(objects.get(i))));
    }
}

/*
 * abstraction of the method above, which sorts List<T> by a List of IDs
 */
public static <T, ID> void sortListByIds(List<T> list, Function<T, ID> listIdFunction, List<ID> ids) {
    sortListByObjects(list, listIdFunction, ids, Function.identity());
}

使用起来非常简单:

List<String> ids = Arrays.asList("4", "1", "9");
List<Foo> unsortedList = Arrays.asList(new Foo("1"), new Foo("9"), new Foo("4"));
sortListByIds(unsortedList, foo -> foo.getId(), ids);

或者:

List<Foo> unsortedList = Arrays.asList(new Foo("1"), new Foo("9"), new Foo("4"));
List<Bar> sortedList = Arrays.asList(new Bar("4"), new Bar("1"), new Bar("4"));
sortListByObjects(unsortedList, foo -> foo.getId(), sortedList, bar -> bar.getId());