2009-11-15 4 views
5

Existe-t-il une classe représentant la concaténation d'une collection avec une autre collection? Cette classe devrait être une collection en elle-même, et devrait déléguer toutes les méthodes aux collections (internes) sous-jacentes - aucune mémoire supplémentaire ne devrait être allouée, ni aucune des collections originales modifiées.Une collection qui représente une concaténation de deux collections en Java

Exemple d'utilisation:

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

Vous voulez dire quelque chose comme ce qu'offre itertools de Python? –

+0

ce n'est pas vraiment clair si vous voulez une classe qui représente une collection et un élément, deux collections ou quoi .. – Jack

+0

Une classe qui représente la concaténation de deux collections. – ripper234

Répondre

0

Je ne sais pas ce que votre demande. Mon interprétation de votre question est que vous cherchez la méthode add sur la collection. Je ne pense pas que ce soit ce que vous demandez.

+0

Je cherche une collection qui encapsule la concaténation de deux collections, _without_ allouer une quantité significative de mémoire ou modifier les collections originales. – ripper234

4

Votre question est très vague. Surtout "avec un autre objet une autre collection" est assez floue.

Vous pouvez au moins ajouter le contenu d'un autre Collection au Collection actuel en utilisant Collection#addAll(). Ici Collection peut être n'importe quoi de ses sous-interfaces/implémentations, par ex. List ou Set.

Exemple:

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

Modifier: Ou voulez-vous réellement créer une nouvelle Collection basé sur un existant Collection puis ajouter un nouvel élément à elle? Dans ce cas, construisez simplement un nouveau Collection avec l'argument Collection existant en tant qu'argument de constructeur. .: par exemple

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

+0

Je préfère toujours les bibliothèques Java natives pour faire les choses avant d'aller dans une bibliothèque tierce. –

2

Je pense que ce que vous demandez est une construction de Java qui vous permet de mettre les collections ensemble sans modifier les collections originales. En d'autres termes, vous avez des collections A et B, de taille N et M respectivement. Après l'appel de concat, vous avez toujours les collections A et B et leurs tailles sont toujours N et M, mais vous avez aussi la collection C qui pointe vers A et B, faisant sa taille N + M. La réponse est non, Java n'a rien d'out-of-the-box qui le fait ... Cependant, vous pouvez écrire un wrapper rapide qui encapsule une série de collections et ajouter ces collections à elle. (Tout ce qu'il ferait est de maintenir des références à chacune des collections) et vous pourriez exposer les méthodes get/insert si nécessaire.

+0

C'est en effet ce que je cherche ... se demandait s'il y a une telle bibliothèque. – ripper234

9

Comme toujours pour tout ce qui concerne les collections, regardez google-collections. Si vous avez Set s, en particulier (pas seulement une collection générale), vous voulez:

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

qui crée une vue non modifiable des deux ensembles. C'est-à-dire, les changements dans foo ou bar seront reflétés dans combined (mais combined.add() etc n'est pas supporté).

Pour le cas plus générique, vous avez Iterables.concat() mais permet simplement vous itérer sur l'élément joint, l'interface Iterable ne comprend pas évidemment contains si vous êtes un peu aspergés là-bas.

Les autres classes d'utilitaires de collections de google-collections (com.google.common.collect.Lists et com.google.common.collect.Collections2) ne contiennent aucune méthode de concaténation. Je ne vois pas pourquoi ils ne pouvaient pas, mais pour le moment ils ne le font pas.

+4

Nous avons constaté que 99% du temps, les utilisateurs avaient juste besoin d'itérer. Donc Iterables.concat(). En interne, nous avons aussi un Lists.concat() mais personne ne l'utilise, et la plupart de ceux qui le font pourraient tout simplement utiliser l'autre de toute façon. –

3

Il n'y a pas, mais l'écrire vous-même devrait être simple

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

} 

Et puis

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

viens d'écrire ce code ici, compiler à vos propres risques! PS, Si vous allez écrire des tests unitaires pour cette classe, envoyez-les moi.