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

我需要将可变列表对象转换为不可变列表,在java中可能的方式是什么。

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

使它不可修改。 (参见Immutable vs Unmodifiable collection )

如果你有两个应该能够修改列表的内部方法,以及那些不允许修改的公共方法,我建议你这样做

 // public facing method where clients should not be able to modify list public List getImmutableList(int size) { return Collections.unmodifiableList(getMutableList(size)); } // private internal method (to be used from main in your case) private List getMutableList(int size) { List beanList = new ArrayList(); 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并返回一个列表,如果您尝试添加,删除或移动元素,则会抛出exception。 例如,使用return Collections.unmodifiableList(beanList); 而不是return beanList;getImmutableList()的末尾。 main()将抛出exception。 Collections类还具有除列表之外的所有其他常见集合类型的方法。

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

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

  • 如果给定集合是可变的并且已修改,则返回的列表将不会反映此类修改。 意思是他们依赖。

在JDK 8中:

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

在JDK 9中:

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

参考

如果对使用第三方库开放, Eclipse Collection允许您从MutableList转换为ImmutableList并再次返回。

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

这也适用于原始集合。

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

如果您有一个ArrayList作为可变List ,则以下内容将起作用。

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

注意:我是Eclipse Collections的提交者。

下面的解决方案是使列表成为不可变的,而不使用任何API。

具有ArrayList成员变量的不可变对象

 public final class Demo { private final List list = new ArrayList(); public Demo() { list.add("A"); list.add("B"); } public List getImmutableList() { List finalList = new ArrayList(); 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]