Programing

java.util.Set에 get (int index)이없는 이유는 무엇입니까?

lottogame 2020. 4. 16. 08:11
반응형

java.util.Set에 get (int index)이없는 이유는 무엇입니까?


나는 좋은 이유가 있다고 확신하지만 누군가 java.util.Set인터페이스가 부족한 이유 get(int Index)또는 유사한 get()방법을 설명해 주 시겠습니까?

세트가 물건을 넣는 데는 좋은 것 같지만 단일 항목을 검색하는 우아한 방법을 찾을 수 없습니다.

첫 번째 항목을 원한다는 것을 알고 있다면을 사용할 수 set.iterator().next()있지만 그렇지 않으면 특정 인덱스에서 항목을 검색하기 위해 Array로 캐스팅해야합니까?

세트에서 데이터를 검색하는 적절한 방법은 무엇입니까? (반복자를 사용하지 않는 것)

API에서 제외되었다는 사실은 이것을하지 않는 좋은 이유가 있음을 의미합니다. 누군가 나를 기쁘게 할 수 있습니까?

편집 : 여기에 매우 훌륭한 답변과 "더 많은 맥락"이라고 말하는 몇 가지. 특정 시나리오는 dbUnit 테스트였습니다. 여기서 쿼리에서 반환 된 집합에 하나의 항목 만 있다고 주장 할 수 있었고 해당 항목에 액세스하려고했습니다.

그러나 질문은 더 집중되어 있으므로 시나리오 없이도 더 유효합니다.

설정 및 목록의 차이점은 무엇입니까 .

아래 환상적인 답변에 감사드립니다.


세트에는 주문이 없기 때문입니다. 일부 구현은 (특히 java.util.SortedSet인터페이스를 구현하는 ) 구현 이지만 집합의 일반적인 속성은 아닙니다.

이 방법으로 세트를 사용하려는 경우 대신 목록을 사용하는 것이 좋습니다.


실제로 이것은 Object-Relational Mapping을 사용하는 JavaEE 애플리케이션을 작성할 때 반복되는 질문입니다 (예 : 최대 절전 모드). 여기에 답한 모든 사람들로부터 Andreas Petersson은 실제 문제를 이해하고 그에 대한 정답을 제공 한 유일한 사람입니다. Java에는 UniqueList가 없습니다! 또는 OrderedSet 또는 IndexedSet이라고도합니다.

Maxwing 은이 유스 케이스 (주문하고 고유 한 데이터가 필요함)를 언급했으며 SortedSet을 제안했지만 이것이 Marty Pitt가 실제로 필요한 것은 아닙니다.

이 "IndexedSet"은 SortedSet과 같지 않습니다. SortedSet에서 요소는 Comparator (또는 "자연"순서)를 사용하여 정렬됩니다.

그러나 대신 LinkedHashSet (다른 사람들도 제안)에 더 가깝거나 존재하지 않는 "ArrayListSet"에 더 가깝습니다. 요소가 삽입 된 순서와 동일한 순서로 반환되도록하기 때문입니다.

그러나 LinkedHashSet은 인터페이스가 아닌 구현입니다! IndexedSet (또는 ListSet, OrderedSet 또는 UniqueList) 인터페이스가 필요합니다! 이를 통해 프로그래머는 특정 순서를 가지고 중복되지 않은 요소 컬렉션이 필요하다고 지정한 다음 구현 (예 : Hibernate에서 제공하는 구현)으로 인스턴스화 할 수 있습니다.

JDK는 오픈 소스이므로이 인터페이스는 Java 7에 포함될 것입니다.


mmyers 'answer 에서 언급되지 않은 한 점만 추가하면 됩니다.

첫 번째 항목을 원한다는 것을 알고 있다면 set.iterator (). next ()를 사용할 수 있지만 그렇지 않으면 특정 인덱스에서 항목을 검색하기 위해 Array로 캐스팅해야합니까?

세트에서 데이터를 검색하는 적절한 방법은 무엇입니까? (반복자를 사용하지 않는 것)

또한 SortedSet인터페이스 (가장 일반적인 구현은 TreeSet)에 익숙해 져야 합니다.

SortedSet은 요소의 자연 순서 에 따라 또는 일부를 사용하여 정렬 된 집합 (즉, 요소가 고유 한 요소)입니다 Comparator. first()last()방법을 사용하여 첫 번째 항목과 마지막 항목에 쉽게 액세스 할 수 있습니다 . A SortedSet는 컬렉션을 복제하지 않고 특정 방식으로 주문해야 할 때 가끔 편리합니다.

편집 : 요소가 삽입 순서대로 유지되는 세트가 필요한 경우 (List와 유사)를 살펴보십시오 LinkedHashSet.


이런 종류의 세트는 세트를 사용해야 할 때와 목록을 사용해야 할 때 문제가됩니다. 일반적으로 조언은 다음과 같습니다.

  1. 주문한 데이터가 필요한 경우 목록을 사용하십시오.
  2. 고유 한 데이터가 필요한 경우 세트를 사용하십시오.
  3. 둘 다 필요한 경우 SortedSet (비교자가 정렬 한 데이터의 경우) 또는 OrderedSet / UniqueList (삽입이 정렬 된 데이터의 경우)를 사용하십시오. 불행히도 Java API에는 아직 OrderedSet / UniqueList가 없습니다.

자주 나타나는 네 번째 경우는 둘 다 필요하지 않다는 것입니다. 이 경우 일부 프로그래머는 목록과 함께 있고 일부는 세트와 함께 있습니다. 개인적으로 나는 순서없이 목록으로 목록을 보는 것이 매우 해롭다는 것을 알았습니다. 왜냐하면 그것은 실제로 완전히 다른 짐승이기 때문입니다. 고유성을 설정하거나 평등을 설정하지 않는 한 항상 목록을 선호하십시오.


아무도이 방법으로 정확하게 철자를했는지 확실하지 않지만 다음을 이해해야합니다.

세트에 "첫 번째"요소가 없습니다.

다른 사람들이 말했듯이 세트에는 주문이 없기 때문입니다. 집합은 구체적으로 순서를 포함하지 않는 수학적 개념입니다.

물론, 컴퓨터는 실제로 메모리에 주문되지 않은 것들의 목록을 유지할 수 없습니다. 주문이 필요합니다. 내부적으로는 배열 또는 연결된 목록 또는 무언가입니다. 그러나 당신은 그것이 무엇인지 정말로 알지 못하며, 실제로 첫 번째 요소가 없습니다. "먼저"나오는 요소는 우연히 그런 식으로 나오며 다음 번에는 처음이 아닐 수도 있습니다. 특정 첫 번째 요소를 "보증"하기위한 단계를 밟아도 한 세트의 특정 구현에 대해 올바르게 이해했기 때문에 여전히 우연히 나옵니다. 다른 구현은 당신이 한 일과 같은 방식으로 작동하지 않을 수 있습니다. 그리고 실제로 사용하고있는 구현과 생각하는 것을 모를 수도 있습니다.

사람들은이 모든 것에 부딪칩니다. 그만큼. 시각. RDBMS 시스템으로 이해하지 못합니다. RDBMS 조회는 레코드 세트를 리턴합니다. 이것은 수학과 동일한 유형의 집합입니다.이 경우에만 항목은 레코드 인 정렬되지 않은 항목 모음입니다. ORDER BY 절을 사용하지 않으면 RDBMS 조회 결과의 순서가 전혀 보장되지 않지만 사람들이 항상 가정하고 데이터 또는 코드의 모양이 약간 변경되고 조회 옵티마이 저가 작동 할 때 언젠가는 스스로를 트립합니다. 다른 방식으로 갑자기 결과가 기대 한 순서대로 나오지 않습니다. 이들은 일반적으로 데이터베이스 클래스에서 (또는 설명서 나 자습서를 읽을 때)주의를 기울이지 않았을 때 쿼리 결과에 보장 된 순서가 없다는 데주의를 기울이지 않은 사람들입니다.


일부 데이터 구조가 표준 Java 콜렉션에서 누락되었습니다.

가방 (세트와 같지만 요소를 여러 번 포함 할 수 있음)

UniqueList (순서 목록, 각 요소는 한 번만 포함 할 수 있음)

이 경우 고유 목록이 필요할 것 같습니다.

유연한 데이터 구조가 필요한 경우 Google 컬렉션에 관심이있을 수 있습니다.


사실, Set 컬렉션의 정의에 따라 Set의 요소는 정렬되지 않습니다. 따라서 인덱스로 액세스 할 수 없습니다.

그러나 인덱스를 매개 변수로 제공하는 것이 아니라 찾고있는 객체와 동일한 객체를 사용하여 get (object) 메소드를 사용하지 않는 이유는 무엇입니까? 이런 식으로, 우리는 equal 메소드가 사용하는 속성을 아는 것만으로도 Set 내부의 요소 데이터에 접근 할 수 있습니다.


세트에서 인덱스별로 많은 랜덤 액세스를 수행하려는 경우 해당 요소의 배열보기를 얻을 수 있습니다.

Object[] arrayView = mySet.toArray();
//do whatever you need with arrayView[i]

그러나 두 가지 주요 단점이 있습니다.

  1. 전체 세트에 대한 배열을 작성해야하므로 메모리 효율적이지 않습니다.
  2. 세트가 수정되면보기가 더 이상 사용되지 않습니다.

Set은 고유성을 보장 할뿐 아니라 최적의 액세스 또는 사용 패턴에 대해서는 아무 것도 말하지 않기 때문입니다. 즉, 집합은 목록 또는 맵일 수 있으며 각 검색 특성은 매우 다릅니다.


집합에서 숫자 인덱스를 사용한다고 생각할 수있는 유일한 이유는 반복 때문입니다. 이를 위해

for(A a : set) { 
   visit(a); 
}

인덱스를 통해 액세스 할 수 있는 정렬 된 세트를 실제로 원했던 상황에 부딪 쳤습니다 (인덱스로 정렬되지 않은 세트에 액세스하는 것은 다른 포스터와 일치합니다). 예를 들어 내가 아이들을 정렬하고 중복 된 아이들을 허용하지 않는 나무가 있습니다.

그것들을 표시하기 위해 인덱스를 통한 액세스가 필요했고 세트 속성은 중복을 효율적으로 제거하는 데 편리했습니다.

java.util 또는 Google 컬렉션에서 적합한 컬렉션을 찾지 못하면 직접 구현하는 것이 간단하다는 것을 알았습니다. 기본 아이디어는 인덱스를 통한 액세스가 필요할 때 SortedSet을 랩핑하고 목록을 작성하는 것입니다 (SortedSet이 변경되면 목록을 잊어 버리는 것). 래핑 된 SortedSet을 변경하고 목록에 액세스하는 것이 컬렉션 수명 기간 동안 분리 된 경우에만 효율적으로 작동합니다. 그렇지 않으면 자주 정렬되는 목록처럼 동작합니다 (예 : 너무 느림).

자녀 수가 많을수록 Collections.sort를 통해 정렬 한 목록보다 성능이 크게 향상되었습니다.


인덱스를 통해 2 개의 기본 데이터 구조 만 액세스 할 수 있습니다.

  • O(1)시간이 복잡한 인덱스를 통해 어레이 데이터 구조에 액세스하여 get(int index)작업을 수행 할 수 있습니다.
  • LinkedList 데이터 구조는 색인을 통해 액세스 할 수도 있지만 O(n)시간이 복잡하여 get(int index)조작이 가능합니다.

Java에서는 Array 데이터 구조를 ArrayList사용하여 구현됩니다 .

상태 설정 데이터 구조는 일반적으로 통해 구현 될 수있다 해시 / HashMap의 또는 BalancedTree의 빠른 요소가 존재하고 존재하지 않는 요소를 추가할지 여부를 검출하기위한 데이터 구조, 보통 잘 구현 집합 달성 O(1)시간 복잡도 contains동작. Java HashSet에서 가장 일반적으로 사용되는 Set 구현은 HashMapAPI 를 호출하여 구현되며 , 연결된 목록 ( ArrayLinkedList 의 조합) 과 별도의 체인을HashMap 사용하여 구현됩니다 .

이후 집합은 다른 데이터 구조를 통해 구현 될 수 있고, 더 없다 get(int index)그것을위한 방법.


Set 인터페이스 에 get 인덱스 유형 호출이 없거나 first () 또는 last ()와 같은 훨씬 더 기본적인 것이없는 이유는 모호한 작업이므로 잠재적으로 위험한 작업이기 때문입니다. 메서드가 Set을 반환하고 first () 메서드를 호출하면 일반 Set이 순서를 보장하지 않는 경우 예상되는 결과는 무엇입니까? 결과 객체는 메소드를 호출 할 때마다 매우 다양 할 수 있으며 변경하는 라이브러리가 구현을 변경하고 모든 코드가 중단 될 때까지 잘못된 보안 감각으로 당신을 유혹하지 않을 수도 있습니다. 특별한 이유가 없습니다.

여기에 나열된 해결 방법에 대한 제안이 좋습니다. 인덱스 액세스가 필요한 경우 목록을 사용하십시오. a) 순서에 대한 보장이 없으며 b) 후속 호출이나 다른 기본 구현에서 순서가 변경되지 않을 것이라는 보장이 없으므로 일반적인 Set과 함께 반복자 또는 toArray를 사용할 때는주의하십시오. 그 사이에 무언가가 필요한 경우 SortedSet 또는 LinkedHashSet이 원하는 것입니다.

// Set 인터페이스에 get-random-element가 있었으면 좋겠습니다.


java.util.Set정렬되지 않은 항목의 모음입니다. Set에 인덱스가없고 값만 추측 할 수 있기 때문에 Set에 get (int index)이 있으면 의미가 없습니다.

정말로 이것을 원한다면 Set에서 임의의 요소를 얻도록 메소드를 코딩하십시오.


넌 할 수있어 new ArrayList<T>(set).get(index)


세트를 정렬하지 않아도되는 경우 인덱스 트리 맵 프로젝트를 살펴 보는 것이 좋습니다 .

향상된 TreeSet / TreeMap 은 요소 색인을 가져 오거나 색인을 통해 요소에 대한 액세스를 제공합니다. 그리고 구현은 RB 트리에서 노드 가중치 업데이트를 기반으로합니다. 따라서 목록으로 반복하거나 백업하지 마십시오.


인덱스를 통해 액세스 할 수있는 대체 옵션으로이 코드를 사용해보십시오.

import java.io.*;
import java.util.*;
class GFG {
public static void main (String[] args) {
    HashSet <Integer> mySet=new HashSet<Integer>();
    mySet.add(100);
    mySet.add(100);
    int n = mySet.size();
    Integer arr[] = new Integer[n];
    arr = mySet.toArray(arr);
    System.out.println(arr[0]);
    }
}

100이 인쇄됩니다.


세트의 요소를 얻으려면 다음 중 하나를 사용합니다.

public T getElement(Set<T> set, T element) {
T result = null;
if (set instanceof TreeSet<?>) {
    T floor = ((TreeSet<T>) set).floor(element);
    if (floor != null && floor.equals(element))
    result = floor;
} else {
    boolean found = false;
    for (Iterator<T> it = set.iterator(); !found && it.hasNext();) {
    if (true) {
        T current = it.next();
        if (current.equals(element)) {
        result = current;
        found = true;
        }
    }
    }
}
return result;
}

참고 URL : https://stackoverflow.com/questions/769731/why-doesnt-java-util-set-have-getint-index

반응형