如何在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]