web-dev-qa-db-ja.com

nullチェックの代わりにCollections.emptyList()?

何度もインスタンス化される可能性があるクラスでめったに使用されないコレクションがある場合、不要なオブジェクトの作成を保存するために、次の「イディオム」に頼ることがあります。

_List<Object> list = null;

void add(Object object) {
    if (list == null)
        list = new ArrayList<Object>();

    list.add(object);
}

// somewhere else
if (list != null)
    for (Object object : list)
         ;
_

今、私はCollections.emptyList()を使用してこれらのnullチェックを排除できないかと思っていましたが、add()のifチェックを次のように変更する必要があります。

_if (list == Collections.<Object>emptyList())
    list = new ArrayList<Object>();
_

毎回新しい空のコレクションを割り当てる以外に、これを処理するより良い方法はありますか?

編集:明確にするために、ICollections.emptyList()を使用したいが、上記のadd( )は本当に醜いです...それを行うためのより良い方法、またはこれを処理する他の完全な方法があるかどうか私は思っていました。

18

不要なオブジェクトの作成を保存するため

_== null_チェックとその他のコーナーケースの処理でコードを散らかす(そして、とにかくnullポインター例外が発生する)ので、これは本当に悪いアイデアです!

さて、Collections.emptyList()を使用してこれらのnullチェックを排除できないのかと思っていました。

いいえ、そうでもありません。 emptyList()は空のリストを返します。あなたできるする

_if (list.equals(Collections.<Object>emptyList()))
_

しかし、それでも_list == null_の場合はNullPointerExceptionがスローされるので、それでも目的を達成することはできません。

私の推奨事項:リストを常に_new ArrayList<Object>_に初期化するか、たとえば、メソッドから空のリストを返したい場合は、代わりにCollections.emptyList()を使用します。 (これにより、毎回同じインスタンスが返されるため、不要なオブジェクトの作成もありません。)

次に、.isEmpty()を使用して、コレクションが空かどうかを確認します。

18
aioobe

提案された答えは絶対に正しい、ほんの小さなヒント-Java 8では、新しい オプションクラス を使用して、リストインスタンスがnullである場合に対処できます。機能的アプローチ。

たとえば、次のようなもの:

public static List<String> addElement(List<String> list, String toAdd) {
       List<String> newList = Optional.ofNullable(list).orElse(new ArrayList<>());
       newList.add(toAdd);
       return newList;
}
10
Johnny

これは、いくつかのコードでヘルパーメソッドに使用するものです。リストを反復する前に通常配置しなければならないnullチェックの量を減らすのに本当にうまく機能します。不変ではないリストが必要な場合は、Collections.emptyListの代わりに新しいリストオブジェクトを返すことができます。

/**
 * Helper method to return an empty list if provided one is null.
 *
 * @param list the list
 * @return the provided list or an empty one if it was null
 */
private static <T> List<T> emptyIfNull(List<T> list) {
    if (list == null) {
        return Collections.emptyList();
    }
    return list;
}

次に、ヘルパーメソッドを次のように使用します。

for (Object object : emptyIfNull(existingList)) { ... }

リストオブジェクトがnullの場合、ヘルパーメソッドは静的な空のリストを返し、ループの内容はスキップされます。これは、リストの反復をラップするnullチェックを作成する必要がないようにするための良い方法です。

例として、リストの内部をObject型にしていますが、これを明らかに使用方法に最も適したものに変更します。

2
Aaron

emptyList()は、毎回オブジェクトを割り当てません。

毎回リストを作成できるように、リストを含むオブジェクトの作成を減らします。

あなたにできることは

private List<Object> list = Collections.emptyList();

private List<Object> listForWrite() {
    return list.isEmpty() ? list = new ArrayList<Object>() : list;
}


void add(Object object) {
    listForWrite().add(object);
}


// avoid creating an Iterator every time.
for (int i = 0, size = list.size(); i < size; i++) {
     ;
}
2
Peter Lawrey

@Stasが推奨するオプションの使用のバリエーションですが、質問で最初に要求されたisEmpty不変コレクションも使用します。

public static List<String> addElement(List<String> list, String toAdd) {
   List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
   newList.add(toAdd);
   return newList;
}

この方法は、コレクションがnullの場合に空の配列を使用するJavascriptのNice機能に最も近いものです。

例えば:

// no need to indent everything inside a null check of myObjects
for (MyObj myObj : Optional.ofNullable(myObjects).orElse(Collections.emptyList())){
    // do stuff with myObj
}
1
Adam Wise

私はこの慣習に従うのが最も簡単だと思います:

  1. 私のメソッドのポイントがコレクションを返すことである場合、メソッドは決してnullを返しません。ヌルがあいまいです。代わりに、Guavaを使用している場合はCollection.emptyXXX()またはImmutableXXX.of()を返します。

  2. 内部リストをメンバーとして保持しているオブジェクトがある場合は、コンストラクターでインスタンス化します。問題が発生した場合、遅延コード私の意見でははデバッグが困難になる傾向があるため、大幅な向上が証明できない限り、遅延インスタンス化を行わないようにします。

不変または変更不可能な空のコレクションが、オブジェクトの外部のコントラクトの一部であることが本当にわかります。コレクションを内部で使用している場合、正当な理由(同時実行性、一貫性、オブジェクトの不変性)がある場合にのみ、不変コレクションの使用を確認できます。

0
Nick Campion

package org.Apache.commons.collections4;にはemptyIfNullメソッドがあります。指定されたリストがnullの場合、空のリストを返します。

List<Object> list = CollectionUtils.emptyIfNull(list);
0
jastka4

反復にのみリストを使用する場合は、for (Object object : list)を使用するだけでかまいません。これは、空のリストに対しては何もしない、つまり単一の反復ではありません。

それ以外の場合は、list.isEmpty()を確認してください。

0
Thomas

次のような静的メソッドでユーティリティクラスを作成できます。

public class ListUtil {

/**
 * Checks if {@link List} is null or empty.
 *
 * @param <E> the generic type
 * @param list the list
 * @return true, if is null or empty
 */
public static <E> boolean isNullOrEmpty(List<E> list) {
    return list == null || list.size() == 0;
}

/**
 * Checks if {@link List} is not null and empty.
 *
 * @param <E> the generic type
 * @param list the list
 * @return true, if is not null and empty
 */
public static <E> boolean isNotNullAndEmpty(List<E> list) {
    return list != null && list.size() != 0;
}

}

0
Tapas Bose