如何根据给定的模式重新排列列表中的项目?

时间:2016-06-15 09:02:50

标签: java hibernate postgresql java-8 spring-data

我有id列表,如下所示:5, 3, 2, 4, 1,然后我用DB查询DB中的项目。但它们来自DB通常按id排序,我的意思是1, 2, 3, 4, 5。我需要将它们重新排列为与它们列出的顺序相同。我怎样才能实现这一目标?

编辑:澄清,因为很多人似乎对这个问题感到困惑。 ID列表用于查询数据库,例如:

SELECT * FROM Foo WHERE id in (5, 3, 2, 4, 1)

生成的Foo对象列表的排序方式与ID列表的排序方式不同。问题是如何获得与初始ID列表具有相同顺序的Foo对象列表。

3 个答案:

答案 0 :(得分:2)

我认为您必须在代码中重新排序查询结果:

public static void main(String[] args) {

    List<Integer> ids = Arrays.asList(5, 3, 2, 4, 1, 6);
    List<Foo> results = Arrays.asList(new Foo(1), new Foo(8), new Foo(2), new Foo(4), new Foo(5), new Foo(7));

    System.out.println("sortResults1: " + sortResults1(ids, results));
    System.out.println("sortResults2: " + sortResults2(ids, results));
}

private static List<Foo> sortResults1(List<Integer> ids, List<Foo> results) {
    Foo[] sortedResultsArray = new Foo[ids.size()];
    for (Foo result : results) {
        // look up the required position of this result's id 
        int pos = ids.indexOf(result.getId());
        if (pos >= 0) {
            sortedResultsArray[pos] = result;
        }
    }
    List<Foo> sortedResults = new ArrayList<>(Arrays.asList(sortedResultsArray));
    sortedResults.removeAll(Collections.singleton(null));
    return sortedResults;
}

private static List<Foo> sortResults2(List<Integer> ids, List<Foo> results) {
    Collections.sort(results, Comparator.comparingInt(item -> ids.indexOf(item.getId())));
    return results;
}

第一种解决方案省略了ID不在ID列表中出现的任何结果。

使用比较器的第二个解决方案将任何带有未知ID的结果放在结果列表的前面。

输出:

sortResults1: [Foo 5, Foo 2, Foo 4, Foo 1]
sortResults2[Foo 8, Foo 7, Foo 5, Foo 2, Foo 4, Foo 1]

注意:在此处找到了类似的问题:Sort an (Array)List with a specific order 它对TreeMap有一个合理的答案。

答案 1 :(得分:2)

使用纯PostgreSQL,

版本&gt; = 9.5:

select * from foo where id = any(array[5,3,2,4,1])
order by array_position(array[5,3,2,4,1], id);

版本&gt; = 9.4:

with lst(i,n) as (select * from unnest(array[5,3,2,4,1]) with ordinality)
select foo.* from foo join lst on (foo.id = lst.i)
order by lst.n

版本&gt; = 8.4:

with lst(i,n) as (select *, row_number() over () from unnest(array[5,3,2,4,1]))
select foo.* from foo join lst on (foo.id = lst.i)
order by lst.n

答案 2 :(得分:0)

如果您只想对列表5, 3, 2, 4, 1进行排序,则可以使用

Collections.sort(List);

如果要根据其他列表对列表进行排序,则应使用比较器,例如

Collections.sort(secondList, new Comparator<Item>() {
public int compare(Item left, Item right) {
    return Integer.compare(firstList.indexOf(left.getId(), firstList.indexOf(right.getId());
}
});

注意: - 这个比较器效率不高,你应该使用hashmap来存储索引。