23

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

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

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

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

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

編集:明確にするために、Collections.emptyList()を使用したいのですが、上記のadd()のチェックは本当に醜いです...それを行うためのより良い方法があるのか​​、それとも他の方法があるのか​​疑問に思いました。これを処理するの。

4

9 に答える 9

22

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

これは本当に悪い考えであり、== nullチェックやその他のコーナーケースの処理でコードが散らかってしまいます(そしておそらくとにかくnullポインター例外になってしまいます)!

今、私はそれらのヌルチェックを使用してそれらを排除することができないかどうか疑問に思いましたCollections.emptyList()

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

if (list.equals(Collections.<Object>emptyList()))

しかし、それでもNullPointerExceptionがスローされるlist == nullので、それでもあなたが求めているものではありません。

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

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

于 2011-07-01T10:42:37.537 に答える
19

提案された答えは完全に正しいですが、ちょっとしたヒントです。Java8では、新しいオプションクラスを使用して、より機能的なアプローチでリストインスタンスが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;
}

コメントのヒントに続いて、空のArrayListの新しいインスタンスが作成されないようにするために、に置き換えることをおnew ArrayList<>()勧めしますCollections.emptyList()

public static List<String> addElement(List<String> list, String toAdd) {
   List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
   newList.add(toAdd);
   return newList;
}
于 2016-08-30T06:53:48.183 に答える
7

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

List<Object> list = CollectionUtils.emptyIfNull(list);
于 2019-12-17T14:03:58.110 に答える
5

これが私のコードのいくつかのヘルパーメソッドに使用するものです。リストを反復処理する前に通常配置しなければならない大量の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型にしましたが、これを使用法に最も適したものに変更することは明らかです。

于 2012-10-29T20:28:19.110 に答える
2

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++) {
     ;
}
于 2011-07-01T10:45:27.543 に答える
2

@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の優れた機能に最も近いものでもあります。

例えば:

// no need to indent everything inside a null check of myObjects
for (MyObj myObj : Optional.ofNullable(myObjects).orElse(Collections.emptyList())){
    // do stuff with myObj
}
于 2019-02-26T15:51:09.040 に答える
0

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

それ以外の場合はチェックしてくださいlist.isEmpty()

于 2011-07-01T10:43:32.280 に答える
0

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

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

}

于 2011-07-01T10:45:31.857 に答える
0

この規則に従うのが最も簡単だと思います。

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

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

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

于 2012-09-14T14:42:47.527 に答える