Uzyskaj unikalne wartości od arraylist w java

83

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ć?

SDas
źródło
4
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 .

jahroy
źródło
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?
lordlabakdas
Jeśli chcesz zachować oryginalne zamówienie z listy, zobacz LinkedHashSet stackoverflow.com/a/8712770/32453
rogerdpack
68

Moż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
George Siggouroglou
źródło
12

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
}
Mathias Schwarz
źródło
6
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique
xagyg
źródło
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.

hyde
źródło
3

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());
Nitin9791
źródło
2

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.

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()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.

Mam nadzieję że to pomoże.

Natasza
źródło
2
    public static List getUniqueValues(List input) {
      return new ArrayList<>(new LinkedHashSet<>(incoming));
    }

nie zapomnij najpierw zaimplementować metody equals

Santoferr
źródło
1

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.

Salvatore D'alessandro
źródło