2010-04-17 5 views
0

J'ai besoin d'utiliser une structure FIFO dans mon application. Il doit avoir au plus 5 éléments. Je voudrais avoir quelque chose de facile à utiliser (je ne me soucie pas de la simultanéité) qui implémente l'interface de collection.Quelle implémentation de file d'attente utiliser en Java?

J'ai essayé le LinkedList, qui semble provenir de la file d'attente, mais il ne semble pas me permettre de définir sa capacité maximale. Il me semble que je veux juste au maximum 5 éléments mais j'essaie d'en ajouter 20, ça va juste continuer à augmenter en taille pour l'adapter. Je voudrais quelque chose qui travaillerait de la façon suivante:

XQueue<Integer> queue = new XQueue<Integer>(5); //where 5 is the maximum number of elements I want in my queue. 
for (int i = 0; i < 10; ++i) { 
    queue.offer(i); 
} 

for (int i = 0; i < 5; ++i) { 
    System.out.println(queue.poll()); 
} 

Ce serait imprimé:

5 
6 
7 
8 
9 

Merci

+0

Pourquoi faut-il imprimer 5 , 6, ..? pourquoi pas 0,1,2,3,4? l'offre semble suggérer qu'il échouerait quand la capacité maximale est atteinte – mkorpela

+0

Techniquement, je suis réellement intéressé par ce genre de file d'attente, en ignorant généralement les données/tâches (* c'est-à-dire les laisser tomber pour des raisons banales *) ce n'est pas une bonne chose. À part ça, cela ressemble à quelque chose que j'aimerais essayer de coder pour voir si je peux en faire un. – Esko

+1

Il semble que l'intérêt est de garder une trace du top 5 des éléments "récemment utilisés". Puisque vous ne vous souciez que des récents, vous devez vous débarrasser des plus âgés. – rmarimon

Répondre

3

Créer votre propre sous-classe de celui que vous voulez, et passer outre la ajouter la méthode de sorte qu'il

  • vérifie si le nouvel objet s'adaptera et échoue sinon
  • appels super.add()

(et les constructeurs).

Si vous voulez le bloquer lors de l'insertion s'il est plein, c'est différent.

+0

Eh bien, l'idée serait d'utiliser quelque chose qui vient avec le cadre. –

+0

ne va-t-il pas à l'encontre de l'objectif de pouvoir sous-classer? Si le framework n'a pas d'objet, vous pouvez en créer un. –

+0

Eh bien, peut-être que le cadre en est un et que le sous-classement irait à l'encontre de l'objectif d'un cadre aussi riche. –

2

On dirait que ce que vous voulez est une structure FIFO de taille limitée, qui expulse les éléments les plus anciens lorsque de nouveaux sont ajoutés. Je recommande une solution basée sur une implémentation de tableau cyclique, où vous devez suivre l'index de la queue queue et la tête de la file d'attente, et les augmenter (de manière cyclique) selon les besoins.

EDIT: Voici ma mise en œuvre (notez que c'est une collection). Cela fonctionne bien avec votre scénario de test.

public class XQueue <T> extends AbstractQueue<T>{ 
    private T[] arr; 
    private int headPos; 
    private int tailPos; 
    private int size; 

    @SuppressWarnings("unchecked") 
    public XQueue(int n){ 
     arr = (T[]) new Object[n]; 
    } 

    private int nextPos(int pos){ 
     return (pos + 1) % arr.length; 
    } 

    @Override 
    public T peek() { 
     if (size == 0) 
      return null; 
     return arr[headPos]; 
    } 

    public T poll(){ 
     if (size == 0) 
      return null; 
     size--; 
     T res = arr[headPos]; 
     headPos = nextPos(headPos);  
     return res; 
    } 

    @Override 
    public boolean offer(T e) { 
     if (size < arr.length) 
      size++; 
     else 
      if (headPos == tailPos) 
       headPos = nextPos(headPos); 
     arr[tailPos] = e; 
     tailPos = nextPos(tailPos); 
     return true; 
    } 

    @Override 
    public Iterator<T> iterator() { 
     return null; //TODO: Implement 
    } 

    @Override 
    public int size() { 
     return size; 
    } 
} 
2

Je n'ai vu aucune limitation comme celle de l'API. Vous pouvez utiliser ArrayList en modifiant le comportement de la méthode add avec la fonctionnalité de classe anonyme:

new ArrayList<Object>(){ 
    public boolean add(Object o){ /*...*/ } 
} 
1

Peut-être un ArrayBlockingQueue pourrait faire l'affaire. Regardez here. Essayez quelque chose comme ceci:

BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(5); 

for (int i = 0; i < 10; i++) { 
    while (!queue.offer(i)) { 
    queue.poll();   
    } 
} 

for (int i = 0; i < 5; i++) { 
    System.out.println(queue.poll()); 
} 
+0

Le problème est que, une fois qu'il est plein, il ne me permettra pas d'ajouter de nouveaux éléments. Je voudrais qu'il se débarrasse des anciens. –

+0

Voilà à quoi sert le temps. Si l'offre renvoie false, elle ne peut pas ajouter l'élément qui interroge la file d'attente pour supprimer un élément de la tête. La prochaine itération du moment obtient l'offre d'accepter l'élément puisqu'il y a de l'espace disponible du sondage précédent. – rmarimon

1

Vous avez trois choix

1) Subclass an Abstract Collection

2) Limiter la taille à cinq et faire la logique autour du code où vous faites l'insert.

3) Utiliser LinkedListHashMap La méthode removeEldestEntry (Map.Entry) peut être substituée pour imposer une politique de suppression automatique des mappages périmés lorsque de nouveaux mappages sont ajoutés à la carte. (Vous utiliserez alors un Iterator pour obtenir les valeurs - qui seront retournées dans l'ordre d'insertion)

Votre meilleur pari est # 1 - C'est vraiment facile si vous regardez le lien.

0

Si je me souviens bien, j'ai fait exactement ce que vous voulez en utilisant une LinkedList.

Ce que vous devez faire est de vérifier la taille de la liste, si elle est 5 et que vous voulez ajouter des objets, il suffit de supprimer le premier élément et continuer à le faire si la taille est 5.