8

私がコーディングしているプロジェクトでは、関数からスレッド セーフで不変のビューを返す必要があります。しかし、私はこれについて確信が持てません。リストのビューを返すだけなのでsynchronizedListunmodifiableList

Collections.synchronizedList(Collections.unmodifiableList(this.data));

トリックを行うでしょう。

これが正しいかどうか誰か教えてもらえますか? そうでない場合、これが失敗する可能性がある状況はありますか?

ご意見ありがとうございます。

4

6 に答える 6

13

これがJDKの本当のギャップだと思います。幸いなことに、Java Collections デザイナーのJoshua Blochが率いる Google のチームが、真に不変のコレクションを含むライブラリを作成しました。

特にImmutableListは、探している実装です。これは、Guava の ImmutableCollections の機能のいくつかの簡単なスケッチです

于 2011-07-12T01:48:52.913 に答える
5

変更不可で十分だと思います。マルチスレッドアクセスで問題が発生するのは、それに書き込むことができないためです。読み取り専用なので、同期の追加手順は必要ないように思えます。

このような質問がある場合は、ソース コードを確認することをお勧めします。を返すように見えますUnmodifiableList:

/**
 * @serial include
 */
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                  implements List<E> {
    static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;

UnmodifiableList(List<? extends E> list) {
    super(list);
    this.list = list;
}

public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode()       {return list.hashCode();}

public E get(int index) {return list.get(index);}
public E set(int index, E element) {
    throw new UnsupportedOperationException();
    }
public void add(int index, E element) {
    throw new UnsupportedOperationException();
    }
public E remove(int index) {
    throw new UnsupportedOperationException();
    }
public int indexOf(Object o)            {return list.indexOf(o);}
public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
    throw new UnsupportedOperationException();
    }
public ListIterator<E> listIterator()   {return listIterator(0);}

public ListIterator<E> listIterator(final int index) {
    return new ListIterator<E>() {
    ListIterator<? extends E> i = list.listIterator(index);

    public boolean hasNext()     {return i.hasNext();}
    public E next()          {return i.next();}
    public boolean hasPrevious() {return i.hasPrevious();}
    public E previous()      {return i.previous();}
    public int nextIndex()       {return i.nextIndex();}
    public int previousIndex()   {return i.previousIndex();}

    public void remove() {
        throw new UnsupportedOperationException();
            }
    public void set(E e) {
        throw new UnsupportedOperationException();
            }
    public void add(E e) {
        throw new UnsupportedOperationException();
            }
    };
}
于 2011-07-12T01:47:42.367 に答える
5
Collections.unmodifiableList(this.data) 

ビューを返すため、上記のステートメントで十分です。このビューを変更しようとすると、UnsupportedOperationExceptionスローされます。以下はCollections#unmodifiableListドキュメントの抜粋です。

指定されたリストの変更不可能なビューを返します。この方法により、モジュールはユーザーに内部リストへの「読み取り専用」アクセスを提供できます。返されたリストに対するクエリ操作は、指定されたリストを「読み取り」、直接または反復子を介して返されたリストを変更しようとすると、UnsupportedOperationException が発生します。

……

Java 8 java.util.Collections javadoc

于 2016-03-02T08:07:33.867 に答える
0

これらのビューは、真にスレッドセーフなコレクションを返しません。誰かがバッキング コレクションまたはコレクション内の要素を変更する可能性は常にあります。

これを解決するには、不変のコレクションと不変の要素を使用する必要があります。その結果、スレッドセーフが発生します。

Clojure には、そのような不変 (または永続的な)コレクションが含まれています。

簡単に言えば、新しい要素を追加または削除すると、新しいコレクションが返されます。これは一般に Trie 型のデータ構造を巧みに使用することで、古いコレクションの大部分を再利用します。

これらだけでは、そのままの Java で使用するには適していません。

Pure4jは、これら (および Clojure が提唱する不変/値ベースのスタイル) を Java 言語に移植する試みです。それはあなたが求めているものかもしれません。

免責事項: 私は Pure4J の開発者です

于 2015-11-06T14:06:09.660 に答える