Holen Sie sich eindeutige Werte von Arraylist in Java


81

Ich habe eine ArrayListmit einer Reihe von Datensätzen und eine Spalte enthält Gasnamen wie CO2 CH4 SO2 usw. Jetzt möchte ich verschiedene Gasnamen (eindeutig) nur ohne Wiederholung von der abrufen ArrayList. Wie geht das?


4
Ich werde die Tags aktualisieren. Dies ist eine Java-Frage und ich glaube, sie hat nichts mit jsf und primefaces zu tun ...
Mathias Schwarz

Antworten:


133

Sie sollten eine verwenden Set. A Setist eine Sammlung , die keine Duplikate enthält.

Wenn Sie eine haben List, die Duplikate enthält, können Sie die eindeutigen Einträge wie folgt erhalten:

List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());

ANMERKUNG : Dieser HashSetKonstruktor identifiziert Duplikate durch Aufrufen der equals () -Methoden der Elemente .


Dies bedeutet, dass 2 Datensätze als gleich (im Sinne von HashSet) betrachtet werden, wenn ihre Namen gleich sind.
NJZK2

@ njzk2 - Ich dachte, das wäre ziemlich offensichtlich, aber ich denke, ich kann bearbeiten, um explizit darauf hinzuweisen ...
Jahroy

Beim Versuch, den obigen Code zu implementieren, wird eine Fehlermeldung angezeigt : java: no suitable constructor found for HashSet. Irgendeine Idee, warum dies auftritt?
Lordlabakdas

66

Sie können die Java 8 Stream-API verwenden .

Die Methode different ist eine Zwischenoperation , die den Stream filtert und nur verschiedene Werte (standardmäßig mit der Object :: equals-Methode) an die nächste Operation übergeben lässt.
Ich habe unten ein Beispiel für Ihren Fall geschrieben:

// Create the list with duplicates.
List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2");

// Create a list with the distinct elements using stream.
List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList());

// Display them to terminal using stream::collect with a build in Collector.
String collectAll = listAll.stream().collect(Collectors.joining(", "));
System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc..
String collectDistinct = listDistinct.stream().collect(Collectors.joining(", "));
System.out.println(collectDistinct); //=> CO2, CH4, SO2

11

Ich hoffe, ich verstehe Ihre Frage richtig: Unter der Annahme, dass die Werte vom Typ sind String, besteht der effizienteste Weg wahrscheinlich darin, in a zu konvertieren HashSetund darüber zu iterieren:

ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
   ... //Do something
}

6
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique

Ich erhalte jetzt die eindeutigen Elemente aus der Liste, aber sie werden von selbst sortiert. Aber ich brauche die Daten, um nicht in sortierter Reihenfolge zu sein. Wie kann das gemacht werden?
SDas

6

Hier ist ein einfacher Weg, ohne auf benutzerdefinierte Komparatoren oder ähnliches zurückzugreifen:

Set<String> gasNames = new HashSet<String>();
List<YourRecord> records = ...;

for(YourRecord record : records) {
  gasNames.add(record.getGasName());
}

// now gasNames is a set of unique gas names, which you could operate on:
List<String> sortedGasses = new ArrayList<String>(gasNames);
Collections.sort(sortedGasses);

Hinweis: Die Verwendung von TreeSetanstelle von HashSetwürde direkt sortierte Arraylisten und höher ergeben, Collections.sortkönnte übersprungen werden, ist aber TreeSetansonsten weniger effizient. Daher ist es oft besser und selten schlechter, sie zu verwenden, HashSetselbst wenn eine Sortierung erforderlich ist.


3

Sie können dies verwenden, um eine Liste eindeutig zu machen

ArrayList<String> listWithDuplicateValues = new ArrayList<>();
list.add("first");
list.add("first");
list.add("second");

ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());

2

Wenn ich dieselbe Abfrage durchführte, fiel es mir schwer, die Lösungen an meinen Fall anzupassen, obwohl alle vorherigen Antworten gute Einblicke haben.

Hier ist eine Lösung, wenn eine Liste eindeutiger Objekte, NICHT Zeichenfolgen, erfasst werden muss. Angenommen, man hat eine Liste von Record-Objekten. RecordKlasse hat nur Eigenschaften vom Typ String, NO Eigenschaft vom Typ int. Hier wird die Implementierung hashCode()schwierig, da hashCode()eine Rückgabe erforderlich ist int.

Das Folgende ist eine Beispielklasse Record.

public class Record{

    String employeeName;
    String employeeGroup;

    Record(String name, String group){  
        employeeName= name;
        employeeGroup = group;    
    }
    public String getEmployeeName(){
        return employeeName;
    }
    public String getEmployeeGroup(){
        return employeeGroup;
    }

  @Override
    public boolean equals(Object o){
         if(o instanceof Record){
            if (((Record) o).employeeGroup.equals(employeeGroup) &&
                  ((Record) o).employeeName.equals(employeeName)){
                return true;
            }
         }
         return false;
    }

    @Override
    public int hashCode() { //this should return a unique code
        int hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 )
        //again, the multiplier could be anything like 59,79,89, any prime
        hash = 89 * hash + Objects.hashCode(this.employeeGroup); 
        return hash;
    }

Wie bereits von anderen vorgeschlagen, muss die Klasse sowohl die equals()als auch die hashCode()Methode überschreiben , um sie verwenden zu können HashSet.

Angenommen, die Liste der Datensätze lautet allRecord( List<Record> allRecord).

Set<Record> distinctRecords = new HashSet<>();

for(Record rc: allRecord){
    distinctRecords.add(rc);
}

Dadurch werden nur die unterschiedlichen Datensätze zum Hashset "differentRecords" hinzugefügt.

Hoffe das hilft.


1

Wenn Sie ein Array eines Objekts (Bean) haben, können Sie dies tun:

List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);

wie oben Mathias Schwarz gesagt, aber Sie müssen Ihrer aBean die Methoden zur Verfügung stellen, hashCode()und equals(Object obj)das kann in Eclipse einfach über ein spezielles Menü ' Generate hashCode() and equals()' (während Sie in der Bean-Klasse sind) durchgeführt werden. Set wertet die überschriebenen Methoden aus, um gleich Objekte zu unterscheiden.


1
  @SuppressWarnings({ "unchecked", "rawtypes" })
    public static List getUniqueValues(List input) {
    return new ArrayList<>(new HashSet<>(input));
    }

Vergessen Sie nicht, Ihre Equals-Methode zu implementieren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.