如何在 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);
使其不可修改。 (参见 Immutable vs Unmodifiable collection)
如果您既有可以修改列表的内部方法,又有 public 不允许修改的方法,我建议您这样做
// 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
和它 returns 一个列表,如果你尝试添加、删除或移动元素,它会抛出异常。例如,在 getImmutableList()
末尾使用 return Collections.unmodifiableList(beanList);
而不是 return beanList;
。 main()
会抛出异常。 Collections
class 除了 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 10 开始,List.copyOf(Collection)
可用于 return 给定集合中的不可修改列表。来自 List.copyOf
方法的源代码:
如果给定的集合是不可修改的列表,List.copyOf()
将不会创建副本。
如果给定的集合是可变的和修改的,returned 列表将不会反映此类修改。意思是他们是独立的。
在JDK 8:
List<String> stringList = Arrays.asList("a", "b", "c");
stringList = Collections.unmodifiableList(stringList);
在JDK 9:
List stringList = List.of("a", "b", "c");
如果愿意使用第三方库,Eclipse Collections 允许您从 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,否则仍然可以更改原始列表。
基本上不可修改的 Collection 是一个视图,因此间接地它仍然可以是 'modified' 来自其他一些可修改的引用。此外,由于它只是另一个集合的只读视图,当源集合更改时,不可修改的集合将始终显示最新值。
然而,不可变集合可以被视为另一个集合的只读副本,不能修改。在这种情况下,当源集合发生变化时,不可变集合不会反映变化
List<String> immutableList=Collections.unmodifiableList(
new ArrayList<String>(modifiableList));
使用番石榴:
import java.util.*;
import com.google.common.collect.ImmutableList;
ImmutableList<String> iList = ImmutableList.copyOf(list);
在 java SE 9
之前创建空的不可变列表
在 Java9 之前,我们必须使用 Collections class 的 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 – 使用静态工厂方法of()
创建不可变列表
List<String> immuList = List.of();
Java 9 – 创建非空不可变列表
List<String> immuList = List.of("Atto", "Rick", "Shalini");
我需要将可变列表对象转换为不可变列表。 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);
使其不可修改。 (参见 Immutable vs Unmodifiable collection)
如果您既有可以修改列表的内部方法,又有 public 不允许修改的方法,我建议您这样做
// 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
和它 returns 一个列表,如果你尝试添加、删除或移动元素,它会抛出异常。例如,在 getImmutableList()
末尾使用 return Collections.unmodifiableList(beanList);
而不是 return beanList;
。 main()
会抛出异常。 Collections
class 除了 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 10 开始,List.copyOf(Collection)
可用于 return 给定集合中的不可修改列表。来自 List.copyOf
方法的源代码:
如果给定的集合是不可修改的列表,
List.copyOf()
将不会创建副本。如果给定的集合是可变的和修改的,returned 列表将不会反映此类修改。意思是他们是独立的。
在JDK 8:
List<String> stringList = Arrays.asList("a", "b", "c");
stringList = Collections.unmodifiableList(stringList);
在JDK 9:
List stringList = List.of("a", "b", "c");
如果愿意使用第三方库,Eclipse Collections 允许您从 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,否则仍然可以更改原始列表。
基本上不可修改的 Collection 是一个视图,因此间接地它仍然可以是 'modified' 来自其他一些可修改的引用。此外,由于它只是另一个集合的只读视图,当源集合更改时,不可修改的集合将始终显示最新值。
然而,不可变集合可以被视为另一个集合的只读副本,不能修改。在这种情况下,当源集合发生变化时,不可变集合不会反映变化
List<String> immutableList=Collections.unmodifiableList(
new ArrayList<String>(modifiableList));
使用番石榴:
import java.util.*;
import com.google.common.collect.ImmutableList;
ImmutableList<String> iList = ImmutableList.copyOf(list);
在 java SE 9
之前创建空的不可变列表在 Java9 之前,我们必须使用 Collections class 的 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 – 使用静态工厂方法of()
创建不可变列表List<String> immuList = List.of();
Java 9 – 创建非空不可变列表
List<String> immuList = List.of("Atto", "Rick", "Shalini");