Collections.unmodifiableList în Java

Returnează o vedere doar-pentru-citire a unei liste: cine o primește nu o poate modifica, dar schimbările originalului se văd.

Sintaxă
static <T> List<T> unmodifiableList(List<? extends T> list)

// la fel: unmodifiableSet, unmodifiableMap, unmodifiableCollection

Ce face Collections.unmodifiableList

Collections.unmodifiableList(lista) învelește lista într-un obiect care permite doar citirea. add, set, remove, clear, sort pe vedere aruncă UnsupportedOperationException.

Este o vedere, nu o copie: dacă lista originală se schimbă, vederea arată schimbarea. Se folosește când o clasă vrea să-și arate lista internă fără să permită altora s-o modifice. Dacă vrei o copie înghețată, care nu se mai schimbă deloc, folosește List.copyOf(lista).

Există variante și pentru alte colecții: unmodifiableSet, unmodifiableMap, unmodifiableCollection.

Parametri

Parametru Descriere
list Lista originală.

Ce returnează

O vedere nemodificabilă a listei.

Exemple

Exemplul 1: Vedere sau copie?

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> original = new ArrayList<>(List.of("Ana", "Radu"));
        List<String> vedere = Collections.unmodifiableList(original);
        List<String> copie = List.copyOf(original);

        original.add("Elena");
        System.out.println("Vedere: " + vedere);
        System.out.println("Copie: " + copie);
        try {
            vedere.add("Mihai");
        } catch (UnsupportedOperationException e) {
            System.out.println("vedere.add: UnsupportedOperationException");
        }
    }
}

Rezultat

Vedere: [Ana, Radu, Elena]
Copie: [Ana, Radu]
vedere.add: UnsupportedOperationException

Exemplul 2: O clasă care își protejează lista

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    static class Cos {
        private final List<String> produse = new ArrayList<>();

        void adauga(String p) {
            produse.add(p);
        }

        List<String> produse() {
            return Collections.unmodifiableList(produse);
        }
    }

    public static void main(String[] args) {
        Cos cos = new Cos();
        cos.adauga("cafea");
        cos.adauga("zahăr");
        List<String> vazute = cos.produse();
        System.out.println(vazute + ", " + vazute.size() + " produse");
        try {
            vazute.clear();
        } catch (UnsupportedOperationException e) {
            System.out.println("Coșul se modifică doar prin adauga()");
        }
    }
}

Rezultat

[cafea, zahăr], 2 produse
Coșul se modifică doar prin adauga()

Greșeli frecvente

  • Crezi că vederea este o copie înghețată. Schimbările listei originale se văd în ea; pentru copie folosește List.copyOf.
  • Crezi că elementele devin și ele nemodificabile. Doar lista este protejată; obiectele din ea se pot modifica în continuare, dacă au metode pentru asta.

Comenzi înrudite

  • List.of: Creează o listă nemodificabilă din valorile date (of) sau dintr-o copie a altei colecții (copyOf).
  • Collections.emptyList: emptyList() returnează o listă goală nemodificabilă; singletonList(x) o listă nemodificabilă cu un singur element.
  • Collections.synchronizedList: Învelește o listă astfel încât fiecare metodă să poată fi apelată în siguranță din mai multe fire de execuție.
  • Set.of: Creează o mulțime nemodificabilă din valorile date (of) sau dintr-o colecție existentă (copyOf). Ordinea nu este garantată.
  • Map.of: Creează un map nemodificabil din perechi date direct (of, ofEntries) sau copiind alt map (copyOf). Ordinea nu este garantată.