Java의 arraylist에서 고유 값 가져 오기


83

나는 ArrayList많은 레코드를 가지고 있고 하나의 열에는 CO2 CH4 SO2 등의 가스 이름이 포함되어 있습니다 ArrayList. 이제. 어떻게 할 수 있습니까?


4
태그를 업데이트하겠습니다. ... 이것은 자바 질문이고, 나는 그것이 JSF와 primefaces 관련이없는 생각
마티아스 슈왈츠

답변:


136

당신은을 사용한다 Set. A Set는 중복 항목이없는 모음 입니다.

당신이있는 경우 List중복을 포함 것을,이 같은 고유 항목을 얻을 수 있습니다 :

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

참고 :이 HashSet생성자는 요소의 equals () 메서드 를 호출하여 중복을 식별 합니다.


이는 이름이 같으면 2 개의 레코드가 (HashSet의 의미에서) 같은 것으로 간주된다는 것을 의미합니다.
njzk2

@ njzk2 - 나는 꽤 명백 할 것이다, 그러나 나는 ... 나는 명시 적으로 지적하고 편집 할 수 있습니다 생각 생각
jahroy

위의 코드를 구현하는 동안 오류가 발생 java: no suitable constructor found for HashSet합니다.. 왜 이런 일이 발생하는지 아십니까?
lordlabakdas

목록에서 원래 주문을 유지하려면 LinkedHashSet stackoverflow.com/a/8712770/32453
rogerdpack

68

Java 8 Stream API를 사용할 수 있습니다 .

고유 한 메서드 는 스트림을 필터링하고 고유 한 값 (기본적으로 Object :: equals 메서드 사용) 만 다음 연산에 전달할 수 있는 중간 연산 입니다.
귀하의 경우에 대한 예를 아래에 썼습니다.

// 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

12

귀하의 질문을 올바르게 이해하기를 바랍니다. 값이 유형이라고 가정 String하면 가장 효율적인 방법은 a로 변환 HashSet하고 반복하는 것입니다.

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

이제 목록에서 고유 한 요소를 가져 오지만 자체적으로 정렬되고 있지만 데이터가 정렬 된 순서가 아니어야합니다. 어떻게 할 수 있습니까?
SDas

6

사용자 지정 비교기 또는 이와 같은 것에 의존하지 않는 간단한 방법은 다음과 같습니다.

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);

참고 : TreeSet대신 사용하면 HashSet직접 정렬 된 배열 목록이 제공되며 위의 내용 Collections.sort은 건너 뛸 수 있지만 TreeSet그렇지 않으면 효율성이 떨어 지므로 HashSet정렬이 필요할 때도 사용하는 것이 더 좋고 드물게 나쁩니다 .


3

목록을 고유하게 만드는 데 사용할 수 있습니다.

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

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

2

동일한 쿼리를 수행 할 때 이전의 모든 답변이 좋은 통찰력을 가지고 있지만 내 사례에 대한 솔루션을 조정하는 데 어려움을 겪었습니다.

다음은 문자열이 아닌 고유 한 객체의 목록을 획득해야하는 경우의 해결책입니다. 하나는 Record 객체의 목록을 가지고 있다고 가정 해 봅시다. Record클래스에는 유형의 속성 만 있고 유형의 String속성은 없습니다 int. 여기에 구현이 hashCode()어려운 될 hashCode()필요가를 반환 int.

다음은 샘플 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;
    }

앞서 다른 사람들이 제안한 것처럼 클래스는를 사용할 수 있도록 equals()hashCode()메서드를 모두 재정의해야 합니다 HashSet.

이제 레코드 목록이 allRecord( List<Record> allRecord) 라고 가정 해 보겠습니다 .

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

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

이것은 Hashset, distinctRecords에 고유 한 레코드 만 추가합니다.

도움이 되었기를 바랍니다.


2
    public static List getUniqueValues(List input) {
      return new ArrayList<>(new LinkedHashSet<>(incoming));
    }

먼저 equals 메소드를 구현하는 것을 잊지 마십시오


1

어떤 종류의 객체 (빈) 배열이있는 경우 다음을 수행 할 수 있습니다.

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

위에서 Mathias Schwarz가 말했듯이, 당신은 당신의 aBean에 메소드를 제공해야 hashCode()하고, equals(Object obj)그것은 전용 메뉴 ' Generate hashCode() and equals()'(Bean Class에있는 동안)에 의해 Eclipse에서 쉽게 할 수 있습니다 . Set는 객체가 같음을 구별하기 위해 재정의 된 메서드를 평가합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.