web-dev-qa-db-ja.com

Javaで不変リストを作成するには?

可変リストオブジェクトを不変リストに変換する必要があります。 Javaで可能な方法は何ですか?

public void action() {
    List<MutableClass> mutableList = Arrays.asList(new MutableClass("san", "UK", 21), new MutableClass("peter", "US", 34));
    List<MutableClass> immutableList = immutateList(mutableList);
}

public List<MutableClass> immutateList(List<MutableClass> mutableList){
    //some code here to make this beanList immutable
    //ie. objects and size of beanList should not be change.
    //ie. we cant add new object here.
    //ie. we cant remove or change existing one.
}

MutableClass

final class MutableClass {
    final String name;    
    final String address;
    final int age;
    MutableClass(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }
}
28
user4768611

beanListが初期化されると、次のことができます

beanList = Collections.unmodifiableList(beanList);

変更できないようにします。 ( Immutable vs Unmodifiable collection を参照)

リストを変更できる内部メソッドと、変更を許可しないパブリックメソッドの両方がある場合は、実行することをお勧めします

// public facing method where clients should not be able to modify list    
public List<Bean> getImmutableList(int size) {
    return Collections.unmodifiableList(getMutableList(size));
}

// private internal method (to be used from main in your case)
private List<Bean> getMutableList(int size) {
    List<Bean> beanList = new ArrayList<Bean>();
    int i = 0;

    while(i < size) {
        Bean bean = new Bean("name" + i, "address" + i, i + 18);
        beanList.add(bean);
        i++;
    }
    return beanList;
}

(あなたのBeanオブジェクトは既に不変に見えます。)


補足として:Java 8+を使用している場合、getMutableListは次のように表現できます。

return IntStream.range(0,  size)
                .mapToObj(i -> new Bean("name" + i, "address" + i, i + 18))
                .collect(Collectors.toCollection(ArrayList::new));
39
aioobe

Collections.unmodifiableList() を使用します。元のArrayListを渡し、要素を追加、削除、またはシフトしようとすると、例外をスローするリストを返します。たとえば、return Collections.unmodifiableList(beanList);の最後に_return beanList;_の代わりにgetImmutableList()を使用します。 main()は例外をスローします。 Collectionsクラスには、リスト以外のすべての一般的なコレクションタイプのメソッドもあります。

7
Mad Physicist

JDK 8の場合:

List<String> stringList = Arrays.asList("a", "b", "c");
stringList = Collections.unmodifiableList(stringList);

JDK 9の場合:

List stringList = List.of("a", "b", "c");

参照

5
Roushan

From Java 10 on、List.copyOf(Collection)は、指定されたコレクションから変更不可能なリストを返すために使用できます。_List.copyOf_のソースコードから方法:

  • 指定されたコレクションが変更不可能なリストである場合、List.copyOf()はコピーを作成しません。

  • 指定されたコレクションが可変で変更されている場合、返されるリストにはそのような変更は反映されません。意味は依存しています。

5
tonyhoan

以下のソリューションは、APIを使用せずにリストを不変として作成するためのものです。

ArrayListメンバー変数を持つ不変オブジェクト

public final class Demo {

    private final List<String> list = new ArrayList<String>();

    public Demo() {
        list.add("A");
        list.add("B");
    }

    public List<String> getImmutableList() {
        List<String> finalList = new ArrayList<String>();
        list.forEach(s -> finalList.add(s));
        return finalList;
    }

    public static void main(String[] args) {
        Demo obj = new Demo();
        System.out.println(obj.getImmutableList());
        obj.getImmutableList().add("C");
        System.out.println(obj.getImmutableList());
    }
}

したがって、実際のリストは変更されず、常に[A、B]が出力されます

サードパーティのライブラリを使用できる場合、 Eclipse Collection sを使用すると、MutableListからImmutableListに変換し、再び元に戻すことができます。

MutableList<String> mutable = Lists.mutable.with("a", "b", "c");
ImmutableList<String> immutable = mutable.toImmutable();
MutableList<String> mutableAgain = immutable.toList();

これは、プリミティブコレクションでも機能します。

MutableCharList mutable = CharLists.mutable.with('a', 'b', 'c');
ImmutableCharList immutable = mutable.toImmutable();
MutableCharList mutableAgain = immutable.toList();

可変のArrayListとしてListがある場合、以下が機能します。

List<String> mutable = new ArrayList<>(Arrays.asList("a", "b", "c"));
ImmutableList<String> immutable = Lists.immutable.withAll(mutable);
List<String> mutableAgain = immutable.toList();

注:私はEclipse Collectionsのコミッターです。

2
Donald Raab

リストで直接unmodifiableListを使用する代わりに不変にします。そうしないと、元のリストを変更できます。

基本的に変更不可能なコレクションはビューであるため、変更可能な他の参照から間接的に「変更」される可能性があります。また、別のコレクションの読み取り専用ビューとして、ソースコレクションが変更されると、unModifiable Collectionは常に最新の値を表示します。

ただし、不変のコレクションは、別のコレクションの読み取り専用コピーとして扱うことができ、変更できません。この場合、ソースコレクションが変更されると、不変コレクションは変更を反映しません

List<String> immutableList=Collections.unmodifiableList(
                            new ArrayList<String>(modifiableList));

グアバの使用:

import Java.util.*; 
import com.google.common.collect.ImmutableList; 
ImmutableList<String> iList = ImmutableList.copyOf(list); 
1
Saurabh