Czy istnieje niezmienna alternatywa dla pierwotnych tablic w Javie? Tworzenie prymitywnej tablicy w final
rzeczywistości nie uniemożliwia zrobienia czegoś takiego
final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;
Chcę, aby elementy tablicy były niezmienne.
int[]
inew int[]
czy DUŻO łatwiej jest pisać niżList<Integer>
inew ArrayList<Integer>
? XDOdpowiedzi:
Nie z prymitywnymi tablicami. Będziesz musiał użyć listy lub innej struktury danych:
źródło
Arrays.asList
jest nie niezmienne. docs.oracle.com/javase/7/docs/api/java/util/… "Zwraca listę o stałym rozmiarze wspieraną przez określoną tablicę. (Zmiany w zwróconej liście" zapisuj "do tablicy.)"Arrays.asList()
rzeczywiście wydaje się niemodyfikowalny w tym sensie, że nie możeszadd
lubremove
elementy zwróconejava.util.Arrays.ArrayList
( nie mylić zjava.util.ArrayList
) - te operacje po prostu nie są zaimplementowane. Może @mauhiz próbuje to powiedzieć? Ale oczywiście można modyfikować istniejące elementy za pomocąList<> aslist = Arrays.asList(...); aslist.set(index, element)
, więc najava.util.Arrays.ArrayList
pewno nie jest to niemożliwe , QED Dodano komentarz tylko po to, aby podkreślić różnicę między wynikiemasList
a normalnymArrayList
Moja rada jest taka, aby nie używać tablica czy
unmodifiableList
jednak używać Guava „s ImmutableList , która istnieje do tego celu.źródło
Collections.unmodifiableList
wystarczy, aby lista była niezmienna?Jak zauważyli inni, w Javie nie można mieć niezmiennych tablic.
Jeśli absolutnie potrzebujesz metody zwracającej tablicę, która nie wpływa na oryginalną tablicę, musisz sklonować tablicę za każdym razem:
Oczywiście jest to dość kosztowne (ponieważ utworzysz pełną kopię za każdym razem, gdy wywołasz getter), ale jeśli nie możesz zmienić interfejsu (aby użyć
List
na przykład) i nie możesz ryzykować, że klient zmieni twoje wewnętrzne, to może to być konieczne.Ta technika nazywa się robieniem kopii obronnej.
źródło
clone()
czyArrays.copy()
tutaj?Istnieje jeden sposób na utworzenie niezmiennej tablicy w Javie:
Tablice z elementami 0 (oczywiście) nie mogą być mutowane.
Może się to przydać, jeśli używasz
List.toArray
metody do konwersji aList
na tablicę. Ponieważ nawet pusta tablica zajmuje trochę pamięci, możesz zapisać tę alokację pamięci, tworząc stałą pustą tablicę i zawsze przekazując ją dotoArray
metody. Że metoda będzie przydzielić nową tablicę jeśli tablica zdać nie ma wystarczająco dużo miejsca, ale jeśli to robi (lista jest pusta), zwróci macierz, którą przeszedł, co pozwala na ponowne użycie tej tablicy każdej chwili zadzwonićtoArray
na zasadzie pustyList
.źródło
Jeszcze jedna odpowiedź
źródło
Jak Java 9 można użyć
List.of(...)
, Javadoc .Ta metoda zwraca niezmienną
List
i jest bardzo wydajna.źródło
Jeśli potrzebujesz (ze względu na wydajność lub w celu zaoszczędzenia pamięci) natywnego „int” zamiast „java.lang.Integer”, prawdopodobnie będziesz musiał napisać własną klasę opakowującą. W sieci są różne implementacje IntArray, ale żadna (znalazłem) nie była niezmienna: Koders IntArray , Lucene IntArray . Prawdopodobnie są inni.
źródło
Od Guava 22, z pakietu
com.google.common.primitives
można użyć trzech nowych klas, które mają mniejszy ślad pamięci w porównaniu doImmutableList
.Mają też budowniczego. Przykład:
lub, jeśli rozmiar jest znany w czasie kompilacji:
To kolejny sposób na uzyskanie niezmiennego widoku tablicy dla prymitywów języka Java.
źródło
Nie, to niemożliwe. Można jednak zrobić coś takiego:
Wymaga to użycia opakowań i jest listą, a nie tablicą, ale jest najbliższą, jaką otrzymasz.
źródło
valueOf()
, autobox się tym zajmie. RównieżArrays.asList(0, 2, 3, 4)
byłoby znacznie bardziej zwięzły.valueOf()
jest wykorzystanie wewnętrznej pamięci podręcznej obiektu Integer w celu zmniejszenia zużycia / recyklingu pamięci.int
naInteger
chociaż; po prostu trzeba uważać na odwrót.W niektórych sytuacjach lżejsze będzie użycie tej statycznej metody z biblioteki Google Guava:
List<Integer> Ints.asList(int... backingArray)
Przykłady:
List<Integer> x1 = Ints.asList(0, 1, 2, 3)
List<Integer> x1 = Ints.asList(new int[] { 0, 1, 2, 3})
źródło
Jeśli chcesz uniknąć zarówno zmienności, jak i boksu, nie ma wyjścia z pudełka. Ale możesz stworzyć klasę, która zawiera wewnątrz pierwotną tablicę i zapewnia dostęp tylko do odczytu do elementów za pośrednictwem metod.
źródło
Metoda of (E ... elements) w Javie9 może służyć do tworzenia niezmiennej listy przy użyciu tylko linii:
Powyższa metoda zwraca niezmienną listę zawierającą dowolną liczbę elementów. Dodanie dowolnej liczby całkowitej do tej listy spowodowałoby
java.lang.UnsupportedOperationException
wyjątek. Ta metoda akceptuje również pojedynczą tablicę jako argument.źródło
Chociaż prawdą jest, że to
Collections.unmodifiableList()
działa, czasami możesz mieć dużą bibliotekę z już zdefiniowanymi metodami zwracania tablic (npString[]
.). Aby zapobiec ich uszkodzeniu, możesz faktycznie zdefiniować tablice pomocnicze, które będą przechowywać wartości:Testować:
Nie jest to doskonałe, ale przynajmniej masz „pseudo niezmienne tablice” (z punktu widzenia klasy) i to nie zepsuje powiązanego kodu.
źródło
No cóż ... tablice są przydatne do przekazywania jako stałe (jeśli były) jako parametry wariantów.
źródło
int[]
, wywołujący może założyć, że może robić, co chce z tą tablicą bez wpływu na wewnętrzne funkcje API.