2011-10-21 9 views
6

Ad esempio, ho set di figure geometriche:Come creare una raccolta da Iterable in java?

Set<Figure> figures; 

Ci sono due tipi di Figura: quadrato e cerchio.

voglio ottenere un insieme di piazze utilizzando collezioni Google:

Iterables.filter(figures,squarePredicate); 

Ma metodo del filtro di ritorno Iterable ... Come si crea Set da Iterable? (senza utilizzare loop su Iterable)

risposta

14

Penso che sia necessario rivedere le vostre esigenze. Hai bisogno di una serie di quadrati. Perché?

Un set ti dà unicità e iterazione, niente di più. Hai unicità nel tuo Iterable, perché la sorgente è un set, e puoi scorrere gli oggetti in un Iterable. Allora, perché dovresti avere bisogno del set?

Ci sono solo due possibili ragioni: o stai lavorando con un'API che ha bisogno di un parametro Set (o Collection), o devi in ​​qualche modo visualizzare le dimensioni del Set.

In questi casi, utilizzare Sets.newHashSet(iterable) per creare un Set (con una mano ovviamente che richiede una iterazione completa, d'altra parte: sarà necessario eseguire un'iterazione completa ad un punto comunque quando si esegue un'iterazione sui valori, quindi perché non farlo ora?). Altrimenti, usa semplicemente l'Iterable e dimenticati di un Set.

+0

Questo codice è ad esempio. Ho un set di oggetti di due tipi. Voglio filtrare un tipo di oggetti con le raccolte di google e quindi ottenere un secondo tipo di oggetti con la sottostringa degli insiemi. –

+0

Piccolo errore: Sets.newHash ** S ** et (iterable) – tashuhka

+0

@tashuhka risolto, grazie –

1

Forse provare CollectionUtils.filter() da utilità di raccolta Apache invece? Puoi usarlo su un Set o usare la collezione risultante nel costruttore Set.

+0

OP ha fatto sorta di stato "utilizzando Google collezioni". –

+0

La domanda riguarda Guava, non Commons/Collections. E il problema è lo stesso: hai bisogno di una completa iterazione per applicare il filtro. –

+0

Credo che stia descrivendo il problema che sta incontrando con la raccolta di google piuttosto che dire che è obbligatorio utilizzarlo. Sto solo suggerendo di andare in un'altra direzione nel caso in cui non sia obbligatorio. Solo un suggerimento. – kgautron

5

Guava Iterables.filter() restituisce deliberatamente una "vista" iterabile. Ci sono due vantaggi di questo approccio:

  • eseguire iterazioni solo sugli elementi quando si ha realmente bisogno di (per esempio, si può catena Iterables.filter() e Iterables.transform() chiama, e iterare solo una volta alla fine).
  • è possibile creare la raccolta appropriata dalla vista, utilizzando qualcosa come ImmutableSet.copyOf(Iterables.filter(..., ...)), Sets.newHashSet(Iterables.filter(..., ...)) o Lists.newArrayList(Iterables.filter(..., ...)). Iterables.filter() ti consente di scegliere l'esatta raccolta necessaria, invece di restituirla arbitrariamente.

Ho anche notato che ti sembra di utilizzare Iterables.filter(Iterable unfiltered, Predicate predicate) con un predicato per filtrare le istanze di un tipo specifico. Potresti anche essere interessato al sovraccarico Iterables.filter(Iterable unfiltered, Class type), che filtra tutte le istanze del tipo specificato e restituisce un Iterable con il tipo generico più specifico. Questo ti permette di evitare lanci scomodi.

+0

grazie! molto informativo –

7

Se si dispone di un Set, è possibile utilizzare Sets.filter anziché Iterables.filter e ottenere un risultato Set. Che Set è una visualizzazione dal vivo, come il risultato di Iterables.filter, ma ha proprietà Set come un veloce metodo contains.

Per creare una copia che contiene solo gli elementi che corrispondono al predicato, è possibile utilizzare ImmutableSet.copyOf o Sets.newHashSet come altri hanno suggerito.

1

È possibile filtrare un set e raccogliere in un altro set con Java 8 flussi:

Set<Number> integers = numbers.stream() 
    .filter(x -> x instanceof Integer) 
    .collect(Collectors.toSet()); 

Il set restituito è una copia, non un live view.

Si noti che a differenza, ad esempio, di Guava FluentIterable.filter, il set risultante è un Set<Integer> perché Java non sa di aver filtrato tutti i non interi. Se hai bisogno di un Set<Integer>, you have to map after filtering.

Set<Integer> integers = numbers.stream() 
    .filter(x -> x instanceof Integer) 
    .map(x -> (Integer)x) 
    .collect(Collectors.toSet()); 

(è possibile combinare il filtro e mappa in un flatMap, ma che sarebbe introdurre un oggetto stream temporanea per intero, e non è più conciso.)

Problemi correlati