2013-05-08 15 views
9

Ich möchte eine Set-Implementierung (HashSet) in Java mit einem Iterable initialisieren. Der Konstruktor von HashSet akzeptiert jedoch keine Iterables, sondern nur Auflistungsobjekte.Initialisieren eines Satzes mit einem Iterable

Gibt es eine Möglichkeit, von Iterable in einen Untertyp von Collections zu konvertieren.

Antwort

6

HashSet Konstruktor verlässt sich auf mehr als was Iterable bietet: es will die size der Kollektion von vorn kennen, um optimal zu sein konstruiere das zugrunde liegende HashMap. Wenn Sie eine echte, strenge Iterable haben, die nicht ihre Größe kennt, dann müssen Sie die Iterable im Voraus erkennen, indem Sie es in eine normale Form von Collection in einer Reihe von offensichtlichen Möglichkeiten.

Wenn Sie auf der anderen Seite ein reicheres Objekt haben, das seine Größe bereits kennt, würde es sich lohnen, eine minimalistische Adapterklasse zu erstellen, die Ihre Iterable in eine Sammlung umwandelt und neben dem Weiterleiten nur size implementiert 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

Gute Erklärung. Ich denke, ich verstehe deinen Standpunkt und deine Intuition. – VaidAbhishek

2

Fügen Sie einfach jedes hinzu.

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

Beachten Sie, dass Sie tun nicht den Konstruktor verwenden new HashSet<Integer>(someIterator), denn das ist nicht vorhanden. Rufen Sie einfach die statische Methode auf.

+3

Ich denke, Sie verwirren 'Iterable' und' Iterator'. –

+0

Ja, du hast Recht. Aber auch iterator() funktioniert nicht. Das Objekt, das ich habe, gibt auch einen Iterator() zurück, aber selbst das ist für den Konstruktor nicht akzeptabel. – VaidAbhishek

+0

Kirk: Du hast recht; Vielen Dank. @Vaid bitte sehe meine Bearbeitung. – wchargin

5

Sicher, es wird in this Antwort angezeigt. Grundsätzlich iterieren die iterable und dessen Inhalt in einer Sammlung kopieren:

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

es wie folgt verwenden, ist das resultierende List Objekt kann als Parameter an den HashSet Konstruktor übergeben werden.

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

EDIT

ich die ganze Zeit geirrt habe. Iterable ist ein Superinterface von Collection, so dass ein einfacher (aber unsicherer) Cast den Trick machen wird, solange der Iterable ein Collection war, um damit zu beginnen.

+0

Downovoter: Vorsicht zu kommentieren? –

+0

Ich vermied es, explizit über Iterable zu iterieren oder selbst einen Iterator zu konsumieren.Ich bin auf der Suche nach einem Mechanismus, der für den Konstruktor des HashSet oder einer Set-Implementierung akzeptabel ist. (Übrigens habe ich nicht abgestimmt). Aber ich würde Sie auf jeden Fall upbooten, wenn Sie mir einen Workaround zeigen könnten. :-) – VaidAbhishek

+1

Das akzeptiert einen Iterator, kein Iterable. – wchargin

32

Sie können Guava verwenden.

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

oder es wie ein Satz statischer Import lesbar zu machen,

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

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

Die Iterable-Schnittstelle ermöglicht die "foreach" Syntax zu arbeiten, so ist der sauberste Weg wahrscheinlich:

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