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?
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?
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 HashSetund darüber zu iterieren:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
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.
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.
publicclassRecord{
String employeeName;
String employeeGroup;
Record(String name, String group){
employeeName= name;
employeeGroup = group;
}
public String getEmployeeName(){
return employeeName;
}
public String getEmployeeGroup(){
return employeeGroup;
}
@Overridepublicbooleanequals(Object o){
if(o instanceof Record){
if (((Record) o).employeeGroup.equals(employeeGroup) &&
((Record) o).employeeName.equals(employeeName)){
returntrue;
}
}
returnfalse;
}
@OverridepublicinthashCode(){ //this should return a unique codeint 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.
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.
Antworten:
Sie sollten eine verwenden
Set
. ASet
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 .quelle
java: no suitable constructor found for HashSet
. Irgendeine Idee, warum dies auftritt?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
quelle
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 konvertierenHashSet
und darüber zu iterieren:ArrayList<String> values = ... //Your values HashSet<String> uniqueValues = new HashSet<>(values); for (String value : uniqueValues) { ... //Do something }
quelle
ArrayList values = ... // your values Set uniqueValues = new HashSet(values); //now unique
quelle
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 vonHashSet
würde direkt sortierte Arraylisten und höher ergeben,Collections.sort
könnte übersprungen werden, ist aberTreeSet
ansonsten weniger effizient. Daher ist es oft besser und selten schlechter, sie zu verwenden,HashSet
selbst wenn eine Sortierung erforderlich ist.quelle
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());
quelle
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 TypString
, NO Eigenschaft vom Typint
. Hier wird die ImplementierunghashCode()
schwierig, dahashCode()
eine Rückgabe erforderlich istint
.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 diehashCode()
Methode überschreiben , um sie verwenden zu könnenHashSet
.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.
quelle
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()
undequals(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.quelle
@SuppressWarnings({ "unchecked", "rawtypes" }) public static List getUniqueValues(List input) { return new ArrayList<>(new HashSet<>(input)); }
Vergessen Sie nicht, Ihre Equals-Methode zu implementieren
quelle