web-dev-qa-db-fra.com

Existe-t-il une implémentation Java List standard qui ne permet pas l'ajout de null?

Disons que j’ai une List et que je sais que je ne veux jamais y ajouter null. Si j'ajoute null à cela, cela signifie que je commets une erreur. Donc, chaque fois que j'appellerais autrement list.add(item) j'appellerais plutôt if (item == null) throw SomeException(); else list.add(item);. Existe-t-il une classe List (peut-être dans Apache Commons ou quelque chose d’autre) qui le fait pour moi?

Question similaire: Aide à supprimer les références null dans une liste Java? mais je ne veux pas supprimer toutes les NULL, je veux m'assurer qu'elles ne seront jamais ajoutées en premier lieu.

20
MatrixFrog

Faites attention - plusieurs réponses prétendent résoudre votre problème en enveloppant une liste et en enregistrant add et addAll, mais elles oublient que vous pouvez également ajouter une List via sa listIterator. Il est difficile d'avoir une liste restreinte correcte, c'est pourquoi Guava a Constraints.constrainedList pour le faire pour vous.

Mais avant de regarder cela, demandez-vous d’abord si vous avez seulement besoin d’une liste immuable /, auquel cas la variable ImmutableList de Guava effectuera cette vérification nulle pour vous. Et si vous pouvez utiliser l'une des implémentations Queue du JDK à la place, vous le ferez aussi.

(Bonne liste des collections null-hostiles: https://github.com/google/guava/wiki/LivingWithNullHostileCollections )

24
Kevin Bourrillion

Utilisez Apache Commons Collection:

ListUtils.predicatedList(new ArrayList(), PredicateUtils.notNullPredicate());

Ajouter null à cette liste jette IllegalArgumentException. En outre, vous pouvez l’ajouter à l’implémentation de la liste de votre choix et, si nécessaire, ajouter plus de prédicats à vérifier.

Même chose pour les collections en général.

Utilisez Google Guava:

Constraints.constrainedList(new ArrayList(), Constraints.notNull())

Ajouter null à cette liste jette NullPointerException.

16
Fabian Barney

Autant que je sache, il n’ya pas d’implémentation standard disponible dans le JDK. Cependant, la spécification Collection indique que NullPointerException doit être levé lorsqu'une collection ne prend pas en charge les valeurs NULL. vous pouvez utiliser le wrapper suivant pour ajouter la fonctionnalité à n'importe quelle collection (vous devrez implémenter les autres méthodes de la collection pour les déléguer à l'instance encapsulée): 

class NonNullCollection<T> implements Collection<T> {

    private Collection<T> wrapped;
    public NonNullCollection(Collection<T> wrapped) {
        this.wrapped = wrapped;
    }
    @Override
    public void add(T item) {
        if (item == null) throw new NullPointerException("The collection does not support null values");
        else wrapped.add(item);
    }
    @Override
    public void addAll(Collection<T> items) {
        if (items.contains(null)) throw new NullPointerException("The collection does not support null values");
        else wrapped.addAll(item);
    }
    ...
}
4
Ryan Gross

Vous pouvez le faire en encapsulant simplement une instance d'une liste et en fournissant la méthode add à vérification nulle. En d’autres termes, votre classe n’aurait que deux méthodes et une variable interne. 

Si vous avez besoin de toutes les fonctionnalités d’une liste, vous pouvez envisager l’utilisation de Guava (anciennement Google Collections) ForwardingList .

Une autre approche consiste simplement à étendre la liste, mais il faut éviter de remplacer add et addAll.

Fait intéressant, la goyave a un standardAddAll , qui peut être utilisé comme implémentation de addAll, ce qui résout au moins une partie du problème.

1
joeslice

Bien que ce problème appelle en quelque sorte "délégué", il est beaucoup plus facile de sous-classer car vous avez l'intention d'hériter de la même fonctionnalité.

class MyList extends List {

  //Probably need to define the default constructor for the compiler

  public add(Object  item) {
    if (item == null) throw SomeException();
    else super.add(item);
  }    

  public addAll(Collection c) {
    if (c.contains(null)) throw SomeException();
    else super.addAll(c);
  }
}
1
Jeremy

Cela devrait marcher

List<String> list = Collections.checkedList(new ArrayList<String>(), String.class);
try {
    list.add(null);
    throw new AssertionError("Expected a NPE");
} catch (NullPointerException expected) {
    System.out.println("list.add(null); threw "+expected);
}
try {
    List<String> list2 = Arrays.asList("", null);
    list.addAll(list2);
    throw new AssertionError("Expected a NPE");
} catch (NullPointerException expected) {
    System.out.println("list.addAll(\"\", null); threw " + expected);
}

cependant, un bogue dans l'implémentation addAll signifie que vous devez utiliser le code suivant.

List<String> list = Collections.checkedList(
   Collections.checkedList(new ArrayList<String>(), String.class), String.class);

et vous obtenez

list.add(null); threw Java.lang.NullPointerException
list.addAll("", null); threw Java.lang.NullPointerException
0
Peter Lawrey