2010-06-03 2 views
1

Je reçois une série d'éléments qui sont utilisés dans une de mes structures de données, et j'ai besoin d'un moyen de garder une trace des éléments qui sont conservés.Java: liste d'autofiltrage?

interface Item {} 
class Foo implements Item { ... } 
class Baz implements Item { ... } 

class StateManager 
{ 
    List<Foo> fooList; 
    Map<Integer, Baz> bazMap; 

    public List<Item> getItems(); 
} 

Ce que je veux est que si je fais ce qui suit:

for (int i = 0; i < SOME_LARGE_NUMBER; ++i) 
{ 
    /* randomly do one of the following: 
    * 1) put a new Foo somewhere in the fooList 
    * 2) delete one or more members from the fooList 
    * 3) put a new Baz somewhere in the bazMap 
    * 4) delete one or more members from the bazMap 
    */ 
} 

alors si je fais un appel à StateManager.getItems(), je veux retourner une liste de ces articles Foo et Baz , qui se trouvent dans le fooList et le bazMap, dans l'ordre où ils ont été ajoutés. Les éléments supprimés ou déplacés de fooList et bazMap ne doivent pas figurer dans la liste renvoyée.

Comment pourrais-je l'implémenter? SOME_LARGE_NUMBER est assez grand pour ne pas avoir la mémoire disponible pour conserver tous les objets Foo et Baz, puis les filtrer.


edit: cela me semble difficile, parce que je ne veux vraiment classe Foo ou Baz classe pour avoir une prise de conscience d'un indice d'insertion, et je veux l'approche d'être évolutive afin que je ne suis pas devez avoir StateManager en être conscient non plus.

Je pensais peut-être d'utiliser les décorateurs pour la liste <> et carte <> utilisés dans fooList et bazMap, avec les décorateurs ayant chacun une référence à la liste principale <> retour à getItems(), de sorte que les décorateurs seraient faire silencieusement tout le travail.

Aussi juste pour plus de clarté, disons que les opérations sur fooList et bazMap sont:

fooList.add(foo1); 
bazMap.put(3, baz1); 
fooList.add(foo2);  
fooList.add(foo3); 
bazMap.put(10, baz2); 
bazMap.put(4, baz3); 
fooList.set(1, foo4); 
bazMap.put(7, baz4); 
bazMap.put(3, baz5); 
fooList.add(foo5); 
bazMap.put(7, baz6); 
fooList.set(0, foo6); 
bazMap.put(4, baz7); 
fooList.add(foo1); 

alors la liste renvoyée par getItems devrait être

[foo3, baz2, foo4, baz5, foo5, baz6, foo6, baz7, foo1] 

depuis la fin fooList = [foo6, foo4 , foo3, foo5, foo1] et le bazMap final = {10: baz2, 4: baz7, 3: baz5, 7: baz6}. Les objets foo1, baz1, foo2, baz3 et baz4 ont tous été déplacés (avec foo1 ajouté à la dernière étape)

Répondre

0

Je ne comprends pas d'où vient le filtrage. Si vous supprimez les éléments à l'étape 2 et 4, ne sont-ils pas implicitement filtrés?

Si vous demandez comment combiner les deux collections en une seule liste, c'est plutôt simple.

List<Item> items = new ArrayList<Item>(fooList.size() + bazMap.size()); 
items.addAll(fooList); 
items.addAll(bazMap.values()); 

Vous pourriez peut-être en dire plus sur la partie «dans l'ordre où ils ont été ajoutés». Le fooList pourrait facilement avoir cette propriété, mais l'ordre de bazMap ne va probablement pas avoir cette propriété. Et si vous voulez dire que foo est ajouté, alors baz, puis foo, et vous avez besoin que la collection finale soit dans le même ordre, c'est encore plus compliqué.

+0

Si je fais fooList.set (k, someFoo), il pousse à l'ancien élément dans cette liste. En outre, oui, si les éléments ajoutés dans l'ordre sont [Foo foo1, Baz baz1, Baz baz2, Foo foo2, Foo foo3] alors je dois maintenir cet ordre. –

1

Je ne comprends pas non plus ce que l'on cherche exactement. Si le problème est de maintenir l'ordre d'insertion de Foos et Bars, alors vous pouvez stocker leur index (i dans votre boucle), et les ordonner en fonction de cela, soit en triant une liste ou via un TreeMap ou quelque chose. Une autre option serait d'utiliser un LinkedHashMap (en utilisant à nouveau l'index pour key) qui maintient l'ordre d'insertion.

+0

c'est utile ... même si je ne veux pas inclure l'index dans l'objet lui-même. –

+0

Vous souciez-vous ou non de pouvoir supprimer rapidement des éléments? Si vous savez peut-être que les éléments non supprimés sont peu nombreux, vous pouvez vous en sortir avec une suppression de temps linéaire. Sinon, vous devez stocker quelque chose par lequel vous connaîtrez la position d'un élément (dans la liste des ordres d'insertion) afin de pouvoir le supprimer rapidement, qu'il s'agisse d'un index ou d'une référence à un noeud de liste, etc. –

+1

Hmm, I voir ci-dessous que vous vous souciez d'éviter une suppression de temps linéaire! :) Avez-vous vu la suggestion de LinkedHashMap? Je l'ai ajouté quelques minutes après la réponse initiale. Cela donnerait O (1) des suppressions au lieu de O (logn) d'utiliser un TreeMap. Il stocke bien sûr un état supplémentaire pour le faire - chaque élément a une référence à la liste qui représente l'ordre d'insertion. –

0

Ajoutez les éléments à une liste maîtresse distincte d'éléments et supprimez des éléments de la liste principale et des structures de données spécifiques au type.

à savoir

for (int i = 0; i < SOME_LARGE_NUMBER; ++i) 
{ 
    /* randomly do one of the following: 
    * 1) put a new Foo somewhere in the fooList 
    * 1a) put a new Foo at the end of masterList 
    * 2) delete one or more members from the fooList 
    * 2a) delete the same members from the masterList 
    * 3) put a new Baz somewhere in the bazMap 
    * 3a) put a new Baz at the end of masterList 
    * 4) delete one or more members from the bazMap 
    * 4a) delete the same members from masterList 
    */ 
} 
+0

cela fonctionnerait je suppose, mais supprimer des éléments d'une liste <> est O (n) n'est ce pas? –

+0

non, cela ne fonctionnerait pas, car les étapes (1) et (3) peuvent impliquer de placer un nouvel élément à un endroit où un ancien élément existait, donc l'ancien élément déplacé doit être retiré de la liste principale. –