2016-06-15 6 views
1

Ich habe eine Liste von IDs, wie diese: 5, 3, 2, 4, 1, dann frage ich Artikel aus der DB mit diesen IDs. Aber sie kommen aus der DB normalerweise sortiert nach ID, ich meine 1, 2, 3, 4, 5. Ich muss sie neu anordnen, um in der gleichen Reihenfolge zu sein, wie sie die IDs auflisten. Wie kann ich das erreichen?Wie ordnen Sie Elemente in der Liste entsprechend einem bestimmten Muster an?

EDIT: Eine Klarstellung, da viele Leute über diese Frage verwirrt scheinen. Eine Liste von IDs verwendet, um die Datenbank abzufragen, zum Beispiel wie folgt aus:

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

Die resultierende Liste von Foo-Objekte nicht in der gleichen Art und Weise wie die Liste der IDs bestellt. Die Frage ist, wie man eine Liste von Foo-Objekten in der gleichen Reihenfolge wie die ursprüngliche Liste von IDs erhält.

+1

lesen Sie Ihre Frage 5 mal noch nicht verstanden, Ihr Problem – SpringLearner

+0

Was meinst du? – ThiepLV

+0

Verwenden Sie kein 'ORDER BY'? Zeig uns, was du versucht hast. – Igoranze

Antwort

2

Ich glaube, Sie haben das Ergebnis der Abfrage im Code neu zu ordnen:

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

Die erste Lösung lässt keine Ergebnisse mit einer ID, die in der Liste der IDs nicht auftritt.

Die zweite Lösung mit dem Komparator platziert alle Ergebnisse mit unbekannten IDs an der Vorderseite der Ergebnisliste.

Ausgang:

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

Hinweis: Gefunden eine ähnliche Frage hier: Sort an (Array)List with a specific order Es hat eine vernünftige Antwort mit einem TreeMap hat.

+1

Sie können mit 'Arrays.asList' keine 'Liste' aus einem 'int []' Array erstellen, aber die manuelle Array-Erstellung ist sowieso veraltet, verwenden Sie einfach' List ids = Arrays.asList (5, 3, 2 , 4, 1); '. By the way, Sie können alle 'null' Elemente mit entweder,' sortedResults.removeAll (Collections.singleton (null)); 'oder' sortedResults.removeIf (Objects :: isNull); ' – Holger

+0

Danke für die Zeiger. Ich habe sie in meine Antwort integriert, –

+1

Die Notwendigkeit der Array-Erstellung gilt auch für den anderen 'asList'-Aufruf:' results = Arrays.asList (new Foo (1), new Foo (8), ... '. Außerdem können Sie drücke die Umwandlung des Arrays in eine Liste ohne 'null' als Stream-Operation aus:' return Arrays.stream (sortedResultsArray) .filter (Objects :: nonNull) .collect (Collectors.toList()); ' – Holger

0

Wenn Sie nur 5, 3, 2, 4, 1 Ihre Liste sortieren möchten, dann können Sie

Collections.sort(List); 

verwenden Wenn Sie eine Liste in Abhängigkeit von anderen Liste sortieren möchten, dann sollten Sie einen Komparator verwenden, zum Beispiel

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

Hinweis: - Dieser Komparator ist nicht sehr effizient, Sie sollten eine Hashmapping verwenden, um die Indizes zu speichern.

+0

Schöne Idee mit dem Komparator. Aber firstList enthält die IDs, oder? Wenn ja, dann vergleichen Sie 'firstList, indexof (left.getId()), firstList, indexOf (right.getId())' –

+0

Ja, aber ich gab nur ein Beispiel, da die Frage nicht sehr klar war. Wie auch immer, ich werde meine Antwort bearbeiten. – Ravikumar

+1

Da es sich um eine Java 8-Frage handelt, können Sie den Vergleicher als 'Comparator.comsparingInt (Element -> firstList.indexOf (item.getId()))' implementieren. Für fünf Elemente gibt es keinen Grund, sich über die Leistung Gedanken zu machen, eine Hashmapp wäre in diesem Fall nicht schneller. – Holger

2

Verwendung von reinem PostgreSQL,

Version> = 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); 

Version> = 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 

Version> = 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 
+0

Dies sollte wahrscheinlich die angenommene Antwort sein –

+0

@AdriaanKoster Es hängt davon ab, wo die Geschäftslogik ist. Wenn die Hauptabfrage beispielsweise automatisch von Java-Code generiert wird, ist die Java-Lösung besser. – Abelisto

+0

Richtig, aber die Frage wurde mit 'Hibernate' und' Postgresql' markiert ... –