2013-05-08 13 views
9

ile bir Set başlatılıyor Java bir Set Uygulama (HashSet) bir yinelenen ile başlatmak istiyorum. Ancak, HashSet kurucusu Yineleyicileri kabul etmiyor, ancak yalnızca Koleksiyonlar nesnelerini kabul ediyor.Değiştirilebilir bir

Yinelenebilir olandan bazı alt koleksiyon türlerine dönüştürmenin bir yolu var mı.

cevap

6

HashSet constructor, Iterable'un sunduklarından daha fazlasını sunuyor: Optimize edebilmek için koleksiyonun ön tarafını size bilmek istiyor Altta yatan HashMap'u oluşturun. Eğer boyutu bilmiyorsanız, doğru bir Iterable sert, varsa, o zaman açık bir Collection çeşitli açık yollardan herhangi birine çevirerek Iterable yukarı fark etmelisiniz. Öte yandan, zaten boyutunu bilen bir zengin nesne var, varsa

, o zaman çağrı yönlendirme sadece size ek olarak uygulanması, bir koleksiyona senin Iterable sarar minimalist adaptör sınıfı oluşturmak için ödeyecekleri 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

İyi bir açıklama. Bence senin puanını ve sezgisini aldım. – VaidAbhishek

2

Her birini ekleyin. o bulunmadığı için, değil yapıcısı new HashSet<Integer>(someIterator) kullanırım

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

Not. Sadece statik yöntemi çağırın.

+3

Sanırım "Yinelenen" ve "Yineleyici" yi karıştırıyorsunuz. –

+0

Evet, haklısınız. Ama hatta yineleyici() çalışmıyor. Benim de bir yineleyici() verdiğim nesne, ancak bu yapıcı için kabul edilemez bile. – VaidAbhishek

+0

Kirk: haklısın; Teşekkürler. @ Vaid lütfen düzenleğimi gör. – wchargin

5

Elbette, this cevabında gösterilmiştir. Temelde, iterable içinde yineleme ve koleksiyonunda içeriğini kopyalamak şu şekildedir:

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

kullanın, ortaya çıkan List nesne HashSet yapıcı parametre olarak geçirilebilir.

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

Baştan beri yanılmış ettik

DÜZENLEME. Iterable, Collection'un bir süper arabirimidir, bu nedenle Iterable, başlangıç ​​için Collection olduğu sürece, basit (ancak güvenli olmayan) bir aldatmaca işlemi gerçekleştirecektir.

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

Downovoter: Yorum yapmak ister misiniz? –

+0

Yinelenen veya yineleyici bir yineleyiciyi kendim üzerinde yinelemekten kaçınıyordum.HashSet'in ya da herhangi bir Set Uygulamasının yapıcısı için kabul edilebilir bir mekanizma arıyorum. (BTW: Sana oy vermedim). Ama bana bir geçici çözüm gösterebilirseniz kesinlikle size bildiririm. :-) – VaidAbhishek

+1

Bu yineleyici değil, bir yineleyici kabul eder. – wchargin

32

Sen Guava kullanabilirsiniz.

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

ya da bir cümle statik ithalat gibi okutmak,

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

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

Iterable arayüzü "foreach" sözdizimi çalışmasını sağlar, bu yüzden en temiz yolu muhtemeldir:

public <T> Set<T> toSet(Iterable<T> collection) { 
    HashSet<T> set = new HashSet<T>(); 
    for (T item: collection) 
     set.add(item); 
    return set; 
} 
İlgili konular