2009-11-15 10 views
5

Esiste una classe che rappresenta la concatenazione di una raccolta con un'altra raccolta? Questa classe dovrebbe essere una raccolta a sé stante e dovrebbe delegare tutti i metodi alle raccolte (interne) sottostanti: nessuna memoria aggiuntiva deve essere allocata, né alcuna delle raccolte originali modificate.Una raccolta che rappresenta una concatenazione di due raccolte in Java

Esempio utilizzo:

Collection<String> foo = ... 
Collection<String> bar = ... 

// this should be O(1) memory and time 
Collection<String> combined = concat(foo, bar); 

if (combined.contains("Zee")) 
    ... 

for (String str : combined) 
    System.out.println(str); 
+0

Intendi qualcosa come quello che fornisce itertools di Python? –

+0

non è molto chiaro se vuoi una classe che rappresenti una collezione e un oggetto, due collezioni o cosa .. – Jack

+0

Una classe che rappresenta la concatenazione di due raccolte. – ripper234

risposta

0

non sono sicuro di che cosa il vostro richiesto. La mia interpretazione della tua domanda è che stai cercando il metodo add sulla Collezione. Non penso che sia quello che stai chiedendo.

+0

Sto cercando una raccolta che racchiuda la concatenazione di due raccolte, senza allocare una quantità significativa di memoria o modificare le raccolte originali. – ripper234

4

La tua domanda è molto vaga. Soprattutto "con un altro elemento un'altra collezione" non è chiaro.

È possibile almeno aggiungere il contenuto di un altro Collection alla corrente Collection utilizzando Collection#addAll(). Qui Collection può essere qualsiasi cosa delle sue sottointerfacce/implementazioni, ad es. List o Set.

Esempio:

List<String> foos = Arrays.asList("foo1", "foo2", "foo3"); 
List<String> bars = Arrays.asList("bar1", "bar2", "bar3"); 
foos.addAll(bars); // Now foos contains everything. 

Edit: O si vuole realmente creare una nuova Collection sulla base di un esistente Collection e quindi aggiungere un nuovo elemento ad esso? In questo caso, basta costruire un nuovo Collection con l'esistente Collection come argomento del costruttore. Es .:

List<String> foos = Arrays.asList("foo1", "foo2", "foo3"); 
List<String> bars = new ArrayList<String>(foos); 
bars.add("bar"); // Now bars contains everything. 
+0

Preferisco sempre le librerie Java native come fare le cose prima di andare a una libreria di terze parti. –

2

Penso che quello che stai chiedendo è un costrutto Java che permette di mettere insieme le collezioni senza modificare le collezioni originali. In altre parole, hai le collezioni A e B, entrambe di dimensione N e M rispettivamente. Dopo la chiamata concat, hai ancora le collezioni A e B e le loro dimensioni sono ancora N e M, tuttavia hai anche la raccolta C che punta a A e B, rendendo le sue dimensioni N + M.

La risposta è no, Java non ha nulla fuori dalla scatola che fa questo ... Tuttavia si potrebbe scrivere un wrapper veloce che avvolge una serie di collezioni e aggiungere quelle collezioni ad esso. (Tutto ciò che farebbe è mantenere i riferimenti a ciascuna delle raccolte) e potresti esporre i metodi get/insert secondo necessità.

+0

Questo è davvero quello che sto cercando ... mi chiedevo se c'è una tale biblioteca. – ripper234

9

Come sempre per qualsiasi materiale di repertorio, vedere google-collections. Se si dispone di Set s, in particolare (non solo una collezione generale), si vuole:

Set<String> combined = Sets.union(foo, bar); 

che crea una visione non modificabile dei due set. Cioè, le modifiche in foo o bar si rifletteranno in combined (ma non è supportato combined.add() ecc.).

Per il caso più generico, è necessario Iterables.concat() ma che semplicemente permette di eseguire iterazioni sulla voce unito, l'interfaccia Iterable, ovviamente, non comprende contains Quindi sei un po 'incasinato lì.

le altre collezioni utilities classi in google-collezioni (com.google.common.collect.Lists e com.google.common.collect.Collections2) non contengono alcun metodo di concatenazione. Non capisco perché non potrebbero, ma al momento non lo fanno.

+4

Abbiamo riscontrato che il 99% delle volte, gli utenti avevano davvero bisogno di iterare. Quindi Iterables.concat(). Internamente abbiamo un Lists.concat(), ma praticamente nessuno lo usa, e la maggior parte di quelli che lo fanno potrebbe aver usato l'altro comunque. –

3

Non c'è, ma scrivere voi stessi dovrebbe essere semplice

package ch.akuhn.util; 

import java.util.Iterator; 
import java.util.NoSuchElementException; 

public class Concat { 

    public static <T> Iterable<T> all(final Iterable<T>... iterables) { 
     return new Iterable<T>() { 
      @Override 
      public Iterator<T> iterator() { 
       return new Iterator<T>() { 
        Iterator<Iterable<T>> more = Arrays.asList(iterables).iterator(); 
        Iterator<T> current = more.hasNext() ? more.next().iterator() : null; 
        @Override 
        public boolean hasNext() { 
         if (current == null) return false; 
         if (current.hasNext()) return true; 
         current = more.hasNext() ? more.next().iterator() : null; 
         return this.hasNext(); 
        } 

        @Override 
        public T next() { 
         if (!hasNext()) throw new NoSuchElementException(); 
         return current.next(); 
        } 

        @Override 
        public void remove() { 
         throw new UnsupportedOperationException(); 
        } 
       }; 
      } 
     }; 
    } 

} 

E poi

for (Object each: Concat.all(collection,whatever,etcetera,...)) { 
    // ... 
} 

appena scritto questo codice qui, compilare a vostro rischio e pericolo!

PS, se vuoi scrivere test di unità per questa classe, mandameli.

Problemi correlati