Как создать неизменяемый список в 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;
    }
}

6 ответов


после того, как ваш 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() выдаст исключение. The Collections класс имеет методы для всех других типов коллекций, кроме списка.


С Java 10 on,List.copyOf(Collection) может использоваться для возврата неизменяемого списка из данной коллекции. Из исходного кода List.copyOf способ:

  • Если данная коллекция является неизменяемым списком,List.copyOf() не будет создавать копию.

  • Если данная коллекция изменчива и изменена, возвращаемый список не будет отражать такие изменения. То есть они зависимы.


ниже решение для создания списка как неизменяемого без использования какого-либо 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) {
    // TODO Auto-generated method stub
    Demo obj = new Demo();
    System.out.println(obj.getImmutableList());
    obj.getImmutableList().add("C");
    System.out.println(obj.getImmutableList());
}

}

таким образом, фактический список не изменится, всегда вывод будет [A, B]


в JDK 8:

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

в JDK 9:

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

ссылка


если открыты для использования сторонней библиотеки,Коллекция Eclipses позволяет конвертировать из MutableList to 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.