Mam ArrayListkilka rekordów, a jedna kolumna zawiera nazwy gazów, takie jak CO2 CH4 SO2 itp. Teraz chcę pobrać różne nazwy gazów (unikalne) tylko bez powtarzania z ArrayList. Jak można to zrobić?
Zaktualizuję tagi. To jest pytanie dotyczące języka Java i wydaje mi się, że nie ma ono związku z jsf i primefaces ...
Mathias Schwarz,
Odpowiedzi:
136
Powinieneś użyć Set. A Setto kolekcja, która nie zawiera duplikatów.
Jeśli masz, Listktóry zawiera duplikaty, możesz uzyskać unikalne wpisy w ten sposób:
List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());
UWAGA : Ten HashSetkonstruktor identyfikuje duplikaty, wywołując metody equals () elementów .
oznacza to, że 2 rekordy są uważane za równe (w sensie HashSet), jeśli ich nazwy są równe.
njzk2
@ njzk2 - Pomyślałem, że będzie to dość oczywiste, ale myślę, że mogę edytować, aby wyraźnie to wskazać ...
jahroy
Otrzymuję komunikat o błędzie podczas próby wykonania powyższy kod: java: no suitable constructor found for HashSet. Masz jakiś pomysł, dlaczego tak się dzieje?
Metoda odrębna to operacja pośrednia, która filtruje strumień i pozwala tylko odrębnym wartościom (domyślnie przy użyciu metody Object :: equals) przejść do następnej operacji.
Poniżej napisałem przykład dla twojego przypadku,
// 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
Mam nadzieję, że dobrze rozumiem twoje pytanie: zakładając, że wartości są typu String, najskuteczniejszym sposobem jest prawdopodobnie zamiana na a HashSeti iteracja po nim:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
Otrzymuję teraz unikalne elementy z listy, ale jest ona sortowana samodzielnie. Ale potrzebuję, aby dane nie były posortowane. Jak to zrobić?
SD:
6
Oto prosty sposób bez uciekania się do niestandardowych komparatorów lub podobnych rzeczy:
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);
Uwaga: użycie TreeSetzamiast tego HashSetdałoby bezpośrednio posortowaną listę arraylist i wyższe, Collections.sortktóre można pominąć, ale TreeSetpoza tym jest mniej wydajne, więc często lepiej, a rzadko gorzej, używać HashSetnawet wtedy, gdy potrzebne jest sortowanie.
Kiedy robiłem to samo zapytanie, miałem trudności z dostosowaniem rozwiązań do mojego przypadku, chociaż wszystkie poprzednie odpowiedzi mają dobry wgląd.
Oto rozwiązanie, gdy trzeba uzyskać listę unikalnych obiektów, a nie ciągów. Powiedzmy, że mamy listę obiektów Record. Recordklasa ma tylko właściwości typu String, BRAK właściwości typu int. Tutaj implementacja hashCode()staje się trudna, ponieważ hashCode()trzeba zwrócić plik int.
Poniżej znajduje się przykładowa Recordklasa.
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;
}
Jak zasugerowali wcześniej inni, klasa musi przesłonić zarówno metodę, jak equals()i hashCode()metodę, aby móc jej używać HashSet.
Powiedzmy, że lista rekordów to allRecord( List<Record> allRecord).
Set<Record> distinctRecords = new HashSet<>();
for(Record rc: allRecord){
distinctRecords.add(rc);
}
Spowoduje to tylko dodanie odrębnych rekordów do skrótu, odrębnych rekordów.
Jeśli masz tablicę jakiegoś obiektu (fasoli), możesz to zrobić:
List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
jak powiedział Mathias Schwarz powyżej, ale musisz dostarczyć swojemu aBean metodami hashCode()i equals(Object obj)można to łatwo zrobić w Eclipse przez dedykowane menu ' Generate hashCode() and equals()' (będąc w klasie bean). Set oceni nadpisane metody w celu rozróżnienia równych obiektów.
Odpowiedzi:
Powinieneś użyć
Set
. ASet
to kolekcja, która nie zawiera duplikatów.Jeśli masz,
List
który zawiera duplikaty, możesz uzyskać unikalne wpisy w ten sposób:List<String> gasList = // create list with duplicates... Set<String> uniqueGas = new HashSet<String>(gasList); System.out.println("Unique gas count: " + uniqueGas.size());
UWAGA : Ten
HashSet
konstruktor identyfikuje duplikaty, wywołując metody equals () elementów .źródło
java: no suitable constructor found for HashSet
. Masz jakiś pomysł, dlaczego tak się dzieje?LinkedHashSet
stackoverflow.com/a/8712770/32453Możesz użyć Java 8 Stream API .
Metoda odrębna to operacja pośrednia, która filtruje strumień i pozwala tylko odrębnym wartościom (domyślnie przy użyciu metody Object :: equals) przejść do następnej operacji.
Poniżej napisałem przykład dla twojego przypadku,
// 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
źródło
Mam nadzieję, że dobrze rozumiem twoje pytanie: zakładając, że wartości są typu
String
, najskuteczniejszym sposobem jest prawdopodobnie zamiana na aHashSet
i iteracja po nim:ArrayList<String> values = ... //Your values HashSet<String> uniqueValues = new HashSet<>(values); for (String value : uniqueValues) { ... //Do something }
źródło
ArrayList values = ... // your values Set uniqueValues = new HashSet(values); //now unique
źródło
Oto prosty sposób bez uciekania się do niestandardowych komparatorów lub podobnych rzeczy:
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);
Uwaga: użycie
TreeSet
zamiast tegoHashSet
dałoby bezpośrednio posortowaną listę arraylist i wyższe,Collections.sort
które można pominąć, aleTreeSet
poza tym jest mniej wydajne, więc często lepiej, a rzadko gorzej, używaćHashSet
nawet wtedy, gdy potrzebne jest sortowanie.źródło
możesz użyć tego do stworzenia listy Unikalnej
ArrayList<String> listWithDuplicateValues = new ArrayList<>(); list.add("first"); list.add("first"); list.add("second"); ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());
źródło
Kiedy robiłem to samo zapytanie, miałem trudności z dostosowaniem rozwiązań do mojego przypadku, chociaż wszystkie poprzednie odpowiedzi mają dobry wgląd.
Oto rozwiązanie, gdy trzeba uzyskać listę unikalnych obiektów, a nie ciągów. Powiedzmy, że mamy listę obiektów Record.
Record
klasa ma tylko właściwości typuString
, BRAK właściwości typuint
. Tutaj implementacjahashCode()
staje się trudna, ponieważhashCode()
trzeba zwrócić plikint
.Poniżej znajduje się przykładowa
Record
klasa.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; }
Jak zasugerowali wcześniej inni, klasa musi przesłonić zarówno metodę, jak
equals()
ihashCode()
metodę, aby móc jej używaćHashSet
.Powiedzmy, że lista rekordów to
allRecord
(List<Record> allRecord
).Set<Record> distinctRecords = new HashSet<>(); for(Record rc: allRecord){ distinctRecords.add(rc); }
Spowoduje to tylko dodanie odrębnych rekordów do skrótu, odrębnych rekordów.
Mam nadzieję że to pomoże.
źródło
public static List getUniqueValues(List input) { return new ArrayList<>(new LinkedHashSet<>(incoming)); }
nie zapomnij najpierw zaimplementować metody equals
źródło
Jeśli masz tablicę jakiegoś obiektu (fasoli), możesz to zrobić:
List<aBean> gasList = createDuplicateGasBeans(); Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
jak powiedział Mathias Schwarz powyżej, ale musisz dostarczyć swojemu aBean metodami
hashCode()
iequals(Object obj)
można to łatwo zrobić w Eclipse przez dedykowane menu 'Generate hashCode() and equals()
' (będąc w klasie bean). Set oceni nadpisane metody w celu rozróżnienia równych obiektów.źródło