[java] Java에서 고유 목록을 유지하는 방법은 무엇입니까?

Java에서 고유하거나 구별되는 개체 (중복 없음) 목록을 만드는 방법은 무엇입니까?

지금 HashMap<String, Integer>은 키를 덮어 써서 마지막에 HashMap.getKeySet()고유 한 것을 얻을 수 있기 때문에 이것을 사용 하고 있습니다. 하지만 여기에 가치 부분이 낭비되기 때문에 더 나은 방법이있을 것이라고 확신합니다.



답변

Set 구현을 사용할 수 있습니다 .

JAVADoc의 일부 정보 :

중복 요소없는 컬렉션입니다 . 보다 공식적으로 집합에는 e1.equals (e2)와 같은 요소 e1 및 e2 쌍이없고 최대 하나의 null 요소가 포함됩니다. 이름에서 알 수 있듯이이 인터페이스는 수학적 집합 추상화를 모델링합니다.

참고 : 변경 가능한 개체가 집합 요소로 사용되는 경우에는 각별한주의가 필요합니다. 개체가 집합의 요소 인 동안 같음 비교에 영향을주는 방식으로 개체 값이 변경되면 집합의 동작이 지정되지 않습니다. 이 금지의 특별한 경우는 세트가 자신을 요소로 포함하는 것이 허용되지 않는다는 것입니다 .`

다음은 구현입니다.

  • HashSet

    이 클래스는 해시 함수가 버킷간에 요소를 적절하게 분산한다고 가정하여 기본 작업 (추가, 제거, 포함 및 크기 조정)에 대해 일정한 시간 성능을 제공합니다. 이 세트를 반복하려면 HashSet 인스턴스의 크기 (요소 수)와 지원 HashMap 인스턴스의 “용량”(버킷 수)의 합계에 비례하는 시간이 필요합니다. 따라서 반복 성능이 중요한 경우 초기 용량을 너무 높게 (또는 부하 계수가 너무 낮게) 설정하지 않는 것이 매우 중요합니다.

    반복 할 때 HashSet생성 된 요소의 순서는 정의되지 않습니다.

  • LinkedHashSet

    예측 가능한 반복 순서를 사용하는 Set 인터페이스의 해시 테이블 및 연결 목록 구현. 이 구현은 모든 항목을 통해 실행되는 이중 연결 목록을 유지한다는 점에서 HashSet과 다릅니다. 이 연결 목록은 요소가 집합에 삽입 된 순서 인 반복 순서를 정의합니다 (삽입 순서). 요소가 세트에 다시 삽입되는 경우 게재 순서는 영향을받지 않습니다. (s.contains (e)가 호출 직전에 true를 반환 할 때 s.add (e)가 호출되면 요소 e가 집합 s에 다시 삽입됩니다.)

    따라서 위 코드의 출력은 …

     Set<Integer> linkedHashSet = new LinkedHashSet<>();
     linkedHashSet.add(3);
     linkedHashSet.add(1);
     linkedHashSet.add(2);
    
     for (int i : linkedHashSet) {
         System.out.println(i);
     }

    … 필연적으로

    3
    1
    2
  • TreeSet

    이 구현은 기본 작업 (추가, 제거 및 포함)에 대해 보장 된 log (n) 시간 비용을 제공합니다. 기본적으로 반복에서 반환되는 요소는 ” 자연 순서 ” 로 정렬 되므로 위의 코드는 …

     Set<Integer> treeSet = new TreeSet<>();
     treeSet.add(3);
     treeSet.add(1);
     treeSet.add(2);
    
     for (int i : treeSet) {
         System.out.println(i);
     }

    … 다음을 출력합니다.

    1
    2
    3

    ( 생성자에 Comparator인스턴스를 전달 TreeSet하여 요소를 다른 순서로 정렬 할 수도 있습니다 .)

    Set 인터페이스를 올바르게 구현하려면 집합에 의해 유지되는 순서 (명시 적 비교기가 제공되는지 여부에 관계없이)가 equals와 일치해야합니다. (같음과 일치에 대한 정확한 정의는 Comparable 또는 Comparator를 참조하십시오.) 이것은 Set 인터페이스가 같음 연산의 관점에서 정의되었지만 TreeSet 인스턴스는 compareTo (또는 비교) 메서드를 사용하여 모든 요소 비교를 수행하기 때문입니다. 이 방법에 의해 동일하다고 간주되는 요소는 집합의 관점에서 동일합니다. 집합의 동작은 순서가 같음과 일치하지 않더라도 잘 정의되어 있습니다. Set 인터페이스의 일반 계약을 따르지 않습니다.


답변

나는 다른 사람들이 암시했지만 실제로 명시 적으로 언급하지 않은 원래 포스터에 대해 여기에서 몇 가지를 명확히하고 싶습니다. 고유 목록을 원한다고 말할 때, 이것이 바로 Ordered Set의 정의입니다. Set Interface와 List 인터페이스의 다른 주요 차이점은 List를 사용하여 삽입 인덱스를 지정할 수 있다는 것입니다. 따라서 질문은 목록 인터페이스가 정말로 필요합니까 (예 : 타사 라이브러리와의 호환성 등) 또는 Set 인터페이스를 사용하도록 소프트웨어를 재 설계 할 수 있습니까? 또한 인터페이스로 무엇을하는지 고려해야합니다. 인덱스로 요소를 찾는 것이 중요합니까? 세트에서 얼마나 많은 요소를 기대하십니까? 많은 요소를 갖게 될 경우 주문이 중요합니까?

유일한 제약 조건이있는 List가 정말로 필요한 경우에는 Apache Common Utils 클래스 org.apache.commons.collections.list.SetUniqueList가 있습니다.이 클래스는 List 인터페이스와 고유 제약 조건을 제공합니다. 그러나 이것은 List 인터페이스를 깨뜨립니다. 그러나 색인별로 목록을 검색해야하는 경우이 기능에서 더 나은 성능을 얻을 수 있습니다. Set 인터페이스를 다룰 수 있고 데이터 세트가 더 작은 경우 LinkedHashSet이 좋은 방법 일 수 있습니다. 소프트웨어의 디자인과 의도에 따라 다릅니다.

다시 말하지만, 각 컬렉션에는 특정 장단점이 있습니다. 일부는 빠른 삽입이지만 느린 읽기, 일부는 빠른 읽기이지만 느린 삽입 등입니다. 각 클래스 및 인터페이스의 세부 사항에 대해 완전히 배우려면 콜렉션 문서에 상당한 시간을 투자하는 것이 좋습니다.


답변

사용 new HashSet<String>
예 :

import java.util.HashSet;
import java.util.Set;

public class MainClass {
  public static void main(String args[]) {
    String[] name1 = { "Amy", "Jose", "Jeremy", "Alice", "Patrick" };

    String[] name2 = { "Alan", "Amy", "Jeremy", "Helen", "Alexi" };

    String[] name3 = { "Adel", "Aaron", "Amy", "James", "Alice" };

    Set<String> letter = new HashSet<String>();

    for (int i = 0; i < name1.length; i++)
      letter.add(name1[i]);

    for (int j = 0; j < name2.length; j++)
      letter.add(name2[j]);

    for (int k = 0; k < name3.length; k++)
      letter.add(name3[k]);

    System.out.println(letter.size() + " letters must be sent to: " + letter);

  }
}


답변

를 사용하여 HashSet<String>고유 한 개체 모음을 유지할 수 있습니다. Integer맵 의 값이 중요한 경우 대신 containsKey맵 메서드를 사용 하여 키가 맵에 이미 있는지 테스트 할 수 있습니다.


답변

HashSet<String>(또는) 어떤 Set구현 이든 당신을 위해 일을 할 수 있습니다. Set중복을 허용하지 마십시오.

다음은 HashSet 용 javadoc 입니다.


답변

이것이 얼마나 효율적인지 모르겠지만 간단한 맥락에서 나를 위해 일했습니다.

List<int> uniqueNumbers = new ArrayList<>();

   public void AddNumberToList(int num)
    {
        if(!uniqueNumbers .contains(num)) {
            uniqueNumbers .add(num);
        }
    }


답변

java.util.Set<E>인터페이스 의 구현 클래스 ( 예 : java.util.HashSet<String> 컬렉션 클래스) 중 하나를 사용할 수 있습니다 .

중복 요소가없는 컬렉션입니다. 보다 공식적으로 집합에는 e1.equals (e2)와 같은 요소 e1 및 e2 쌍이없고 최대 하나의 null 요소가 포함됩니다. 이름에서 알 수 있듯이이 인터페이스는 수학적 집합 추상화를 모델링합니다.