web-dev-qa-db-ja.com

nullの追加を許可しない標準のJavaリストの実装はありますか?

私がListを持っていて、nullを追加したくないことを知っているとします。 nullを追加している場合、それは間違いを犯していることを意味します。したがって、そうでなければlist.add(item)を呼び出すたびに、代わりにif (item == null) throw SomeException(); else list.add(item);を呼び出します。これを行う既存のListクラス(Apache Commonsなどにある)はありますか?

同様の質問: Java List? でnull参照を削除するヘルパー)==しかし、すべてのnullを削除するのではなく、追加されないようにしたいそもそも。

26
MatrixFrog

注意してください-ここでいくつかの回答は、リストをラップしてaddaddAllをチェックインすることで問題を解決すると主張していますが、Listを介してlistIteratorに追加することもできません。制限されたリストを正しく取得するのは難しいので、GuavaはConstraints.constrainedListしてください。

しかし、それを見る前に、まずimmutableリストだけが必要かどうかを検討してください。この場合、GuavaのImmutableListはとにかくnullチェックを行います。代わりに、JDKのQueue実装の1つを代わりに使用できる可能性があれば、それもそれで十分です。

(null-hostileコレクションの良いリスト: https://github.com/google/guava/wiki/LivingWithNullHostileCollections

25

Apache Commons Collectionを使用:

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

このリストにnullを追加すると、IllegalArgumentExceptionがスローされます。さらに、好きなList実装でそれをサポートすることができ、必要に応じて、チェックする述語をさらに追加できます。

コレクションについても同様です。

Googleグアバを使用:

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

このリストにnullを追加すると、NullPointerExceptionがスローされます。

16
Fabian Barney

AFAIK、JDKで利用可能な標準実装はありません。ただし、 Collection spec は、コレクションがnullをサポートしていない場合にNullPointerExceptionがスローされることを示しています。次のラッパーを使用して、任意のコレクションに機能を追加できます(ラップされたインスタンスに委任するには、他のコレクションメソッドを実装する必要があります)。

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);
    }
    ...
}
5
Ryan Gross

Listのインスタンスをラップし、null-checked addメソッドを提供するだけでこれを行うことができます。言い換えれば、あなたのクラスはいくつかのメソッドと内部変数を持つだけです。

リストのすべての機能が必要な場合は、Guava(以前はGoogleコレクションでした) ForwardingList を検討してください。

もう1つのアプローチは、Listを拡張することですが、addaddAllの両方をオーバーライドする必要があります。

興味深いことに、guavaには standardAddAll があります。これは、問題の少なくとも一部を解決するaddAllの実装として使用できます。

1
joeslice

この問題は一種の「委任」を叫びますが、ほとんどすべて同じ機能を継承するつもりであるため、サブクラス化を使用する方がはるかに簡単です。

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

これはうまくいくはずです

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

ただし、addAll実装のバグは、以下を使用する必要があることを意味します

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

そしてあなたは得る

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