2009-06-21 8 views
2

Edit: Meine Liste ist so sortiert, wie es von einem DB kommt Ich habe eine ArrayList, die Objekte der Klasse People hat. Personen haben zwei Eigenschaften: ssn und terminationReason. So sieht meine Liste wie diesewie man Liste in Java manipulieren

ArrayList: 
ssn   TerminatinoReason 
123456789  Reason1 
123456789  Reason2 
123456789  Reason3 
568956899  Reason2 
000000001  Reason3 
000000001  Reason2 

Ich möchte auf diese Liste ändern, so dass es keine Duplikate und Beendigung Gründe sind getrennt durch Kommas.

so oben aufgeführte Liste würde

New ArrayList: 
ssn   TerminatinoReason 
123456789  Reason1, Reason2, Reason3 
568956899  Reason2 
000000001  Reason3, Reason2 

Ich habe zu etwas gehen, wo ich durch die ursprüngliche Liste am Looping und SSN passend, aber es scheint nicht zu funktionieren.

Kann jemand helfen?

Code I wurde mit war:

String ssn = ""; 
    Iterator it = results.iterator(); 
    ArrayList newList = new ArrayList(); 
    People ob; 
    while (it.hasNext()) 
    { 
     ob = (People) it.next(); 
     if (ssn.equalsIgnoreCase("")) 
     { 
      newList.add(ob); 
      ssn = ob.getSSN(); 
     } 
     else if (ssn.equalsIgnoreCase(ob.getSSN())) 
     { 
      //should I get last object from new list and append this termination reason? 
      ob.getTerminationReason() 
     } 
    } 
+1

können Sie den Code anzeigen, in dem Sie die Liste durchlaufen? – rogeriopvl

+0

Ich habe den Code hinzugefügt, in dem ich die Liste durchlaufen habe. –

+0

Sie können die Datenbankabfrage entfernen lassen, so dass Sie sie in Ihrem Java-Code nicht behandeln müssen. Normalerweise ist alles, was Sie in der Datenbank tun, wahrscheinlich sehr viel effizienter. – rich

Antwort

3
List<People> newlst = new ArrayList<People>(); 
People last = null; 
for (People p : listFromDB) { 
    if (last == null || !last.ssn.equals(p.ssn)) { 
     last = new People(); 
     last.ssn = p.ssn; 
     last.terminationReason = ""; 
     newlst.add(last); 
    } 
    if (last.terminationReason.length() > 0) { 
     last.terminationReason += ", "; 
    } 
    last.terminationReason += p.terminationReason; 
} 

Und Sie die aggregierte Liste in newlst erhalten.

Aktualisierung: Wenn Sie MySQL verwenden, können Sie die Funktion GROUP_CONCAT zum Extrahieren von Daten in Ihrem erforderlichen Format verwenden. Ich weiß nicht, ob andere DB-Engines eine ähnliche Funktion haben oder nicht.

Update 2: Die unnötige Sortierung wurde entfernt.

3

Was Sie brauchen könnten, ist ein Hash. HashMap möglicherweise verwendbar.

Überschreiben Sie equals() und hashCode() in Ihrer People-Klasse.

Lassen Sie HashCode die Personen (Person) SSN zurückgeben. Auf diese Weise haben Sie alle People-Objekte mit demselben SSN im selben "Bucket".

Denken Sie daran, dass die Implementierungsklassen der Map-Schnittstelle Schlüssel/Wert-Paare zum Halten Ihrer Objekte verwenden, sodass Sie etwas wie myHashMap.add ("ssn", peopleobject) haben;

1

Zwei mögliche Probleme:

  • Das wird nicht funktionieren, wenn Ihre Liste nicht
  • sortiert Du nichts mit ob.getTerminationReason tun(). Ich denke, du willst es zum vorherigen Objekt hinzufügen.
0

EDIT: Nun, ich sehe, dass Sie Ihre Frage bearbeitet haben.

Wie Ihre Liste sortiert ist, (von ssn Ich nehme an)

Integer currentSSN = null; 
List<People> peoplelist = getSortedList();//gets sorted list from DB. 
/*Uses foreach construct instead of iterators*/ 

for (People person:peopleList){ 

if (currentSSN != null && people.getSSN().equals(currentSSN)){ 
//same person 
system.out.print(person.getReason()+" ");//writes termination reason 

} 
else{//person has changed. New row. 
    currentSSN = person.getSSN(); 
    system.out.println(" ");//new row. 
    system.out.print(person.getSSN()+ " ");//writes row header. 
} 

} 

Wenn Sie den Inhalt der Liste angezeigt werden möchte nicht, dass, könnten Sie es verwenden, um eine Karte zu erstellen und dann verwenden, Wie nachfolgend dargestellt.

Wenn die Liste nicht sortiert

Vielleicht sollten Sie einen anderen Ansatz versuchen, eine Karte. Hier ssn würde der Schlüssel der Karte, Werte könnte eine Liste von Personen

Map<Integer,List<People>> mymap = getMap();//loads a Map from input data. 

for(Integer ssn:mymap.keyset()){ 
dorow(ssn,mymap.get(ssn)); 
} 

public void dorow(Integer ssn, List<People> reasons){ 

system.out.print(ssn+" "); 
for (People people:reasons){ 
system.out.print(people.getTerminationReason()+" "); 
} 

system.out.println("-----");//row separator. 

Last but not least werden, sollten Sie Ihre hashCode() und equals() Methode auf Menschen Klasse außer Kraft setzen.

zum Beispiel

public void int hashcode(){ 

    return 3*this.reason.hascode(); 

} 
+0

in Ihrer Lösung für sortierte Liste zu konvertieren .. wo werde ich das Objekt Person der neuen Liste hinzufügen? Wenn ich es im 'else' hinzufüge, dann muss ich irgendwie das Objekt in 'if' aktualisieren ... –

5

Mir scheint dies wie ein guter Fall eine Multimap zu verwenden, die mehrere Werte für einen einzigen Schlüssel zu speichern erlauben würde.

Die Google Collections verfügt über eine Multimap Implementierung.

Dies kann bedeuten, dass die Person Objekt ssn und terminationReason Felder müssen herausgenommen werden, um ein Schlüssel bzw. Wert sein. (Und diese Felder wird davon ausgegangen werden String sein.)

Grundsätzlich kann man wie folgt verwendet werden:

Multimap<String, String> m = HashMultimap.create(); 

// In reality, the following would probably be iterating over the 
// Person objects returned from the database, and calling the 
// getSSN and getTerminationReasons methods. 

m.put("0000001", "Reason1"); 
m.put("0000001", "Reason2"); 
m.put("0000001", "Reason3"); 
m.put("0000002", "Reason1"); 
m.put("0000002", "Reason2"); 
m.put("0000002", "Reason3"); 

for (String ssn : m.keySet()) 
{ 
    // For each SSN, the termination reasons can be retrieved. 
    Collection<String> termReasonsList = m.get(ssn); 

    // Do something with the list of reasons. 
} 

Falls erforderlich, eine durch Kommata getrennte Liste von einem Collection hergestellt werden:

StringBuilder sb = new StringBuilder(); 

for (String reason : termReasonsList) 
{ 
    sb.append(reason); 
    sb.append(", "); 
} 

sb.delete(sb.length() - 2, sb.length()); 
String commaSepList = sb.toString(); 

Dies könnte wieder auf das Feld terminationReason festgelegt werden.

Eine Alternative, als Jonik in den Kommentaren erwähnt, ist die StringUtils.join Methode von Apache Commons Lang zu verwenden, könnte eine durch Kommata getrennte Liste erstellen verwendet werden.

Es sollte auch beachtet werden, dass die Multimap nicht angibt, ob eine Implementierung doppelte Schlüssel/Wert-Paare zulassen sollte oder nicht, so sollte man sich ansehen, welcher Typ von Multimap zu verwenden.

In diesem Beispiel ist die HashMultimap eine gute Wahl, da doppelte Schlüssel/Wert-Paare nicht zulässig sind. Dies würde automatisch doppelte Gründe für eine bestimmte Person beseitigen.

+0

+1 Genau. Ich wollte gerade meine Multimap-Antwort posten, aber ich werde das jetzt überspringen. :) Obwohl ich StringUtils.join() von Apache Commons Lang für die kommagetrennte Liste verwenden würde. (Und erwähnen Sie, dass vielleicht die objekt-relationale Zuordnung im Allgemeinen neu überdacht werden könnte - ein Objekt in Java, das eine Person darstellt, sollte alle Gründe haben ...) – Jonik

+0

@Jonik, danke für Ihren Zeiger auf StringUtils.join :) I Habe das zur Antwort hinzugefügt. (Ich wusste, dass es einen besseren Weg geben musste, als es mit der Hand zu machen.) Ich stimme auch zu, dass das Person-Objekt selbst mehrere Gründe haben sollte, als mehrere Person-Objekte für eine Person zu haben. – coobird