Ich habe eine ArrayList
mit 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?
Ich habe eine ArrayList
mit 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?
Antworten:
Sie sollten eine verwenden Set
. A Set
ist 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 HashSet
Konstruktor identifiziert Duplikate durch Aufrufen der equals () -Methoden der Elemente .
java: no suitable constructor found for HashSet
. Irgendeine Idee, warum dies auftritt?
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
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 HashSet
und darüber zu iterieren:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique
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 TreeSet
anstelle von HashSet
würde direkt sortierte Arraylisten und höher ergeben, Collections.sort
könnte übersprungen werden, ist aber TreeSet
ansonsten weniger effizient. Daher ist es oft besser und selten schlechter, sie zu verwenden, HashSet
selbst wenn eine Sortierung erforderlich ist.
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());
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. Record
Klasse 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.
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.