2

ArrayList APIを調べていると、奇妙に見えるものに気づきました。

実際、ここでは、コレクションが引数として渡されたArrayListコンストラクターの実装です。

public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
}

そしてここでHashSetクラスに相当するもの:

public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
}

したがって、ArrayListの1つは、パラメーターのコレクションによって提供される要素のCOPY(Arrays.copyOf)を使用しましたが、HashSetの1つは、addAll()メソッドを使用していることがわかります。

そしてもちろん、addAll()メソッドは要素をコピーせず、HashSetコレクションへの参照を追加するだけです。

この微妙な違いは、それを無視する発信者にとって「危険」だと思います。

同じ参照を持つコレクションを期待する人もいれば、ArrayList APIをよく読む人は、元のコレクションからの要素のコピーを期待するでしょう。

SunがこれらのCollectionsサブクラスに同じ概念を提供しなかったのはなぜですか?

4

3 に答える 3

8

ArrayList 1は、パラメーター内のコレクションによって提供される要素のCOPY(Arrays.copyOf)を使用しましたが、HashSet 1は、addAll()メソッドを使用します。

いいえ、Arrays.copyOf配列をコピーするだけで、この配列が指すオブジェクトはコピーしません。オブジェクトは複製されません。とはいえ、両方のコンストラクターは同じように動作します。元のコレクションと同じオブジェクトへの参照が含まれます。一方のコレクションのオブジェクトを変更すると、もう一方のコレクションも変更されます(同じオブジェクトであるため)。

Arrays.copyOf()また、これは特定の状況でのみ使用されることに注意してください。

于 2012-04-14T20:52:13.277 に答える
3

ArrayListとは両方とも参照HashSetのみをコピーし、それらの参照が参照する実際のオブジェクトはコピーしません。

Javaでは、非プリミティブ型の変数はオブジェクトへの参照です。それらの配列がある場合はArrays.copyOf、参照のみをコピーします。これらの参照が参照するオブジェクトはコピーしません。

于 2012-04-14T20:52:52.120 に答える
1

コレクションには同じ参照があります。A、B、Cの3つのオブジェクトのリストがあり、そのリストをコピーすると、新しいコピーはそれらの同一の3つのオブジェクトも参照します。これらのコンストラクターはどちらも浅く、元のオブジェクトにはまったく触れていません。

public static void main(String args[]) {
    ArrayList l = new ArrayList();
    Object a = new Object();
    Object b = new Object();
    Object c = new Object();
    l.add(a);
    l.add(b);
    l.add(c);

    ArrayList k = new ArrayList(l);
    HashSet h = new HashSet(l);
    System.out.println(a);
    System.out.println(b);
    System.out.println(c);

    System.out.println(l);
    System.out.println(k);
    System.out.println(h);
}

与える:

java.lang.Object@43256ea2
java.lang.Object@4e82701e
java.lang.Object@558ee9d6
[java.lang.Object@43256ea2, java.lang.Object@4e82701e, java.lang.Object@558ee9d6]
[java.lang.Object@43256ea2, java.lang.Object@4e82701e, java.lang.Object@558ee9d6]
[java.lang.Object@4e82701e, java.lang.Object@43256ea2, java.lang.Object@558ee9d6]

すべてのコレクションが同一のオブジェクトを参照していることに気付くでしょう。(HashSetの順序は異なります。)

于 2012-04-14T20:55:49.353 に答える