2013-05-08 3 views
9

Iterable을 사용하여 Java에서 Set Implementation (HashSet)을 초기화하려고합니다. 그러나 HashSet의 생성자는 반복 가능을 허용하지 않고 컬렉션 유형 객체 만 허용합니다.Iterable을 사용하여 세트 초기화

Iterable에서 Collections의 하위 유형으로 변환하는 방법이 있습니까?

답변

6

HashSet 생성자는 Iterable이 제공하는 것 이상을 의지합니다. 최적으로 수집하기 위해 컬렉션의 size을 알고 싶어합니다. 기초가되는 HashMap을 구성하십시오. 크기가 알지 못하는 진실하고도 까다로운 Iterable을 가지고 있다면 Iterable을 정교한 방법으로 일반 Collection으로 바꾸면됩니다.

반면에 이미 크기를 알고있는 더 풍부한 개체가 있다면 Iterable을 콜렉션으로 랩핑하는 미니멀리스트 어댑터 클래스를 생성하는 데 비용을 지불해야합니다. 호출을 전달하는 것 외에도 size을 구현하는 것입니다. iterator.

public class IterableCollection<T> implements Collection<T> 
{ 
    private final Iterable<T> iterable; 

    public IterableCollection(Iterable<T> it) { this.iterable = it; } 

    @Override public Iterator<T> iterator() { return iterable.iterator(); } 

    @Override public int size() { return ... custom code to determine size ... } 

    @Override .... all others ... { throw new UnsupportedOperationException(); } 
} 
+0

좋은 설명. 나는 네가 요점과 직감을 얻은 것 같아. – VaidAbhishek

2

그냥 하나씩 추가하십시오. 즉 존재하지 않기 때문에 당신이하지 생성자 new HashSet<Integer>(someIterator)를 사용 할

public static <T> Set<T> setFromIterable(Iterable<T> i) { 
    HashSet<T> set = new HashSet<T>(); 
    Iterator<T> it = i.iterator(); 
    while (it.hasNext()) { 
     set.add(it.next()); 
    } 
    return set; 
} 

Iterable<Integer> someIterable = ...; 
Set<Integer> someSet = setFromIterable(someIterable); 

참고. 정적 메서드를 호출하기 만하면됩니다.

+3

'Iterable'과'Iterator'를 혼동스럽게 생각합니다. –

+0

네, 맞습니다. 그러나 iterator()는 작동하지 않습니다. 내가 가지고있는 객체는 Iterator()를 돌려 주지만, 심지어 생성자에게는 받아 들여지지 않습니다. – VaidAbhishek

+0

Kirk : 네 말이 맞아. 감사. @Vaid는 내 편집을 참조하십시오. – wchargin

5

물론, this 답변에 표시됩니다. 기본적으로, 반복 가능한 반복하고 컬렉션의 내용을 복사 다음과 같이

public static <T> List<T> copyIterable(Iterable<T> iterable) { 
    Iterator<T> iter = iterable.iterator(); 
    List<T> copy = new ArrayList<T>(); 
    while (iter.hasNext()) 
     copy.add(iter.next()); 
    return copy; 
} 

그것을 사용하여, 그 결과 List 객체는 HashSet 생성자에 매개 변수로 전달 될 수있다.

Iterable<Integer> list = Arrays.asList(1, 2, 3); 
List<Integer> copy = copyIterable(list); 
Set<Integer> aSet = new HashSet<Integer>(copy); 

내가 모두 함께 착각했습니다

편집 할 수 있습니다. Iterable은 의 수퍼 인터페이스이므로 IterableCollection으로 시작하는 한 단순하지만 위험한 캐스트가 트릭을 수행합니다.

Iterable<Integer> list = Arrays.asList(1, 2, 3); 
Set<Integer> aSet = new HashSet<Integer>((Collection)list); // it works! 
+0

Downovoter : 관심있는 댓글? –

+0

Iterable을 반복적으로 반복하거나 Iterator를 직접 사용하는 것을 피했습니다.HashSet 또는 Set 구현의 생성자가 받아 들일 수 있도록 메커니즘을 찾고 있습니다. (나는 투표하지 않았다.) 그러나 나에게 해결 방법을 보여줄 수 있다면 나는 분명히 당신을 업 그레 이드 할 것이다. :-) – VaidAbhishek

+1

반복자가 아니라 반복자를 받아들입니다. – wchargin

32

Guava을 사용할 수 있습니다.

Set<T> set = Sets.newHashSet(iterable); 

하거나 문장 정적 수입처럼 읽을 수 있도록,

import static com.google.common.collect.Sets.*; 

Set<T> set = newHashSet(iterable); 
0

Iterable 인터페이스는 "foreach는"구문이 작업을 수행 할 수 있습니다, 그래서 가장 깨끗한 방법은 가능성이 높습니다 :

public <T> Set<T> toSet(Iterable<T> collection) { 
    HashSet<T> set = new HashSet<T>(); 
    for (T item: collection) 
     set.add(item); 
    return set; 
} 
관련 문제