Définir une liste de taille fixe en Java
Est-il possible de définir une liste avec une taille fixe de 100? Sinon, pourquoi n'est-ce pas disponible en Java?
8 answers
Oui,
Commons library fournit un FixedSizeList
qui ne supporte pas le add
, remove
et clear
méthodes (mais la méthode set est autorisée car elle ne modifie pas la taille de List
). En d'autres termes, si vous essayez d'appeler une de ces méthodes, votre liste toujours conserver la même taille.
Pour créer votre liste de tailles fixes, appelez simplement
List<YourType> fixed = FixedSizeList.decorate(Arrays.asList(new YourType[100]));
Vous pouvez utiliser unmodifiableList
si vous souhaitez un inmodifiable vue de la liste des, ouaccès en lecture seule aux listes internes .
List<YourType> unmodifiable = java.util.Collections.unmodifiableList(internalList);
Cela devrait le faire si la mémoire sert:
List<MyType> fixed = Arrays.asList(new MyType[100]);
Soit votre question est inexacte, soit vous avez un modèle mental incorrect de ce qu'est un Java List
.
Une liste Java est une collection d'objets ... les éléments d'une liste. La taille de la liste est le nombre d'éléments de la liste. Si vous souhaitez que cette taille soit corrigée, cela signifie que vous ne pouvez ni ajouter ni supprimer d'éléments, car l'ajout ou la suppression d'éléments violerait votre contrainte "taille fixe".
Le moyen le plus simple d'implémenter une liste "à taille fixe" (si c'est vraiment ce que vous voulez!) est de mettre les éléments dans un tableau, puis Arrays.asList(array)
pour créer le wrapper de liste. Le wrapper vous permettra de faire des opérations comme get
et set
, mais le add
et remove
opérations de lancer des exceptions.
Et si vous voulez créer un wrapper de taille fixe pour une liste existante, vous pouvez utiliser Apache commons FixedSizeList
classe. Mais notez que ce wrapper ne peut pas empêcher quelque chose d'autre de changer la taille de la liste d'origine, et si cela se produit la liste enveloppée reflétera vraisemblablement ces changements. (OMI, le javadoc pour FixedSizeList
est lamentable. Il ne tente pas de documenter le comportement de la classe lorsque la liste encapsulée est modifiée. Vous aurez besoin de lire le code source ... et l'espoir qu'ils ne changent pas le comportement lorsque vous ne faites pas attention.)
D'autre part, si vous voulez vraiment un type de liste avec une limite fixe (ou des limites) sur sa taille, alors vous devrez créer votre propre classe de liste pour l'implémenter. Pour par exemple, vous pouvez créer une classe wrapper qui implémente les vérifications pertinentes dans les différents add
/ addAll
et remove
/ removeAll
/ retainAll
opérations. (Et dans l'itérateur remove
méthodes si elles sont prises en charge.)
Alors pourquoi le framework Java Collections ne les implémente-t-il pas? Voici pourquoi je le pense:
- Les cas d'utilisation qui en ont besoin sont rares.
- Les cas d'utilisation où cela est nécessaire, il existe différentes exigences sur ce qu'il faut faire lorsqu'une opération tente de casser le limites; par exemple, lancer une exception, ignorer l'opération, rejeter un autre élément pour faire de l'espace.
- Une implémentation de liste avec des limites pourrait être problématique pour les méthodes d'aide; par exemple
Collections.sort
.
Oui. Vous pouvez passer un tableau java à Tableaux.asList (Objet []) .
List<String> fixedSizeList = Arrays.asList(new String[100]);
Vous ne pouvez pas insérer de nouvelles chaînes dans fixedSizeList (il a déjà 100 éléments). Vous ne pouvez définir ses valeurs que comme ceci:
fixedSizeList.set(7, "new value");
De cette façon, vous avez une liste de taille fixe. La chose fonctionne comme un tableau et je ne peux pas penser à une bonne raison de l'utiliser. J'aimerais savoir pourquoi vous voulez que votre collection de taille fixe soit une liste au lieu d'utiliser simplement un tableau.
Typiquement, une alternative pour les listes de taille fixe sont les tableaux Java. Les listes par défaut sont autorisées à croître/rétrécir en Java. Toutefois, cela ne signifie pas que vous ne pouvez pas avoir une Liste de taille fixe. Vous devrez faire du travail et créer une implémentation personnalisée.
Vous pouvez étendre une ArrayList avec des implémentations personnalisées des méthodes clear, add et remove.
Par exemple
import java.util.ArrayList;
public class FixedSizeList<T> extends ArrayList<T> {
public FixedSizeList(int capacity) {
super(capacity);
for (int i = 0; i < capacity; i++) {
super.add(null);
}
}
public FixedSizeList(T[] initialElements) {
super(initialElements.length);
for (T loopElement : initialElements) {
super.add(loopElement);
}
}
@Override
public void clear() {
throw new UnsupportedOperationException("Elements may not be cleared from a fixed size List.");
}
@Override
public boolean add(T o) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
}
Créer un tableau de taille 100. Si vous avez besoin de l'interface de liste, appelez Arrays.asList dessus. Il retournera une liste de taille fixe soutenue par le tableau.
Si vous voulez une certaine flexibilité, créez une classe qui surveille la taille de la liste.
Voici un exemple simple. Vous devez remplacer toutes les méthodes qui modifient l'état de la liste.
public class LimitedArrayList<T> extends ArrayList<T>{
private int limit;
public LimitedArrayList(int limit){
this.limit = limit;
}
@Override
public void add(T item){
if (this.size() > limit)
throw new ListTooLargeException();
super.add(item);
}
// ... similarly for other methods that may add new elements ...
Si vous souhaitez utiliser ArrayList ou LinkedList, il semble que la réponse est non. Bien qu'il existe certaines classes en java que vous pouvez leur définir une taille fixe, comme PriorityQueue, ArrayList et LinkedList ne peuvent pas, car il n'y a pas de constructeur pour ces deux pour spécifier la capacité.
Si vous souhaitez vous en tenir à ArrayList/LinkedList, une solution simple consiste à vérifier la taille manuellement à chaque fois.
public void fixedAdd(List<Integer> list, int val, int size) {
list.add(val);
if(list.size() > size) list.remove(0);
}
LinkedList est meilleur que ArrayList dans cette situation. Supposons qu'il y ait beaucoup de valeurs à ajouter mais que la taille de la liste soit assez petite, il y aura beaucoup d'opérations de suppression. La raison en est que le coût de la suppression de ArrayList est O(N), mais seulement O(1) pour LinkedList.