繁体   English   中英

如何在java中创建不可变列表?

[英]How to create Immutable List in 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;
    }
}

一旦你的beanList被初始化,你就可以做

beanList = Collections.unmodifiableList(beanList);

使其不可修改。 (请参阅不可变与不可修改集合

如果您同时拥有应该能够修改列表的内部方法和不允许修改的公共方法,我建议您这样做

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

使用Collections.unmodifiableList() 您传入原始ArrayList并返回一个列表,如果您尝试添加、删除或移动元素,该列表将引发异常。 例如,使用return Collections.unmodifiableList(beanList); 而不是return beanList; getImmutableList()的末尾。 main()会抛出异常。 除了List之外, Collections类还具有用于所有其他常见集合类型的方法。

在 JDK 8 中:

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

在 JDK 9 中:

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

参考

从 Java 10 开始, List.copyOf(Collection)可用于从给定集合返回不可修改的列表。 List.copyOf方法的源代码:

  • 如果给定的集合是不可修改的 List,则List.copyOf()将不会创建副本。

  • 如果给定的集合是可变的并被修改,则返回的列表将不会反映此类修改。 意味着他们是独立的。

如果可以使用第三方库, 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 的提交者。

使其不可变,而不是直接在列表上使用 unmodifiableList,否则原始列表仍然可以更改。

基本上 unModifiable Collection 是一个视图,所以间接地它仍然可以从其他一些可修改的引用中“修改”。 也因为它只是另一个集合的只读视图,当源集合更改时, unModifiable 集合将始终显示最新值。

然而,不可变集合可以被视为另一个集合的只读副本并且不能被修改。 在这种情况下,当源集合更改时,不可变集合不会反映更改

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

使用番石榴:

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

下面的解决方案是在不使用任何 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]

在 java SE 9 之前创建空的不可变列表

在 Java 9 之前,我们必须使用 Collections 类的 unmodifiableList() 方法来创建不可变列表。

List<String> noElementList = new ArrayList<String>();
List<String> immuList = Collections.unmodifiableList(noElementList);

在 Java SE 9 之前创建非空的不可变列表

List<String> list = new ArrayList<String>();
list.add("Atto");
list.add("Rick");
list.add("Shalini");
List<String> immuList = Collections.unmodifiableList(list);

Java 9 – 使用()的静态工厂方法创建不可变列表

List<String> immuList = List.of();

Java 9 – 创建非空不可变列表

List<String> immuList = List.of("Atto", "Rick", "Shalini");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM