Elementarz Java #4 – Tablice
Wstęp
Dzisiaj na tapecie temat dość prosty i krótki. Tak nawiasem pisząc to najkrótszy artykuł z serii #ElementarzJava ale jak pewnie się domyślasz, patrząc na spis treści – to tylko wstęp do kolejnych znacznie ciekawszych zagadnień.
Samo stosowanie i używanie tablic nie jest skomplikowane, powiedziałbym, że jest wręcz trywialne. To chyba jedna z najpopularniejszych kolekcji do przechowywania danych, którą poznajemy na dość wczesnym etapie nauki programowania. Diabeł jednak tkwi w szczegółach i jak to zwykle bywa są pewnie elementy, które nie są takie oczywiste na jakie wyglądają. Takimi zagadnieniami zająłem się właśnie w niniejszym artykule, zapraszam do jego lektury i mam nadzieję, że poszerzy on Twoje horyzonty!
Seria #ElementarzJava składa się z następujących artykułów:
- Podstawy języka Java (kompilacja, zmienne, struktura klasy, pakiety),
- Typy danych w języku Java (deklaracja i inicjalizacja zmiennych, różnica między typami, garbage collection, typy opakowujące),
- Operatory i konstrukcje warunkowe w Java (użycie operatorów, porównywanie obiektów, instrukcje:
if
,if/else
,switch
), - Tablice (charakterystyka tablic, tablice jedno i wielowymiarowe),
- Pętle (tworzenie pętli, instrukcje
break
icontinue
, etykiety), - Metody oraz hermetyzacja (metody statyczne, przeciążanie metod, konstruktory, modyfikatory widoczności, hermetyzacja elementów klasy, parametry),
- Dziedziczenie (implementacja, przysłanianie metod, polimorfizm, rzutowanie),
- Obsługa wyjątków (kategorie wyjątków, łapanie wyjątków, klasy wyjątków),
- API Java (
String
,StringBuilder
, data i czas, kolekcje, wyrażenia lambda).
Jesteś tu pierwszy raz? Polecam rozpocząć lekturę od materiału: Elementarz Java #0 – wprowadzenie.
Czym się charakteryzują tablice?
Zacznijmy od tego, że tablica to obiekt, który przechowuje kolekcję wartości. Może ona mieć typ zarówno prosty (np. int
) jak i obiektowy (np. Integer
). Java jak każdy nowoczesny język programowania umożliwia tworzenie wielowymiarowych tablic. Tablica jednowymiarowa to obiekt, który odnosi się do zbioru wartości skalarnych. Tablice wielowymiarowe odnoszą się do zbioru obiektów, gdzie każdy z nich jest tablicą jednowymiarową. Tworzenie tablicy jest podzielone na trzy kroki: deklaracja, alokacja i inicjalizacja. Deklaracja tablicy składa się z podania jej typu, nazwy zmiennej i jednego lub więcej wystąpień nawiasów kwadratowych ( [ ]
). Tablice mogą posiadać typ interfejsu lub klasy abstrakcyjnej. Oczywiście możemy również stworzyć tablicę typu java.lang.Object
(ponieważ wszystkie klasy w Java rozszerzają klasę Object
).
Wszystkie tablice umożliwiają nam dostęp do pola length
, które określa liczbę elementów w tablicy.
Char[] c = new char[2]; int length = c.length;
Klasa Arrays
poza metodą equals
, którą opisywałem przy okazji porównywania tablic zawiera również metodę asList
, która to konwertuje tablicę do listy. Kolekcja list
z kolei ma zaimplementowaną metodę toArray
, która to konwertuje listę do tablicy.
List<Integer> list = Arrays.asList(10, 4, -1, 5); Integer array[] = list.toArray(new Integer[4]);
Tablica jednowymiarowa
Deklaracja, alokacja i inicjalizacja
Istnieje kilka sposób tworzenia tablic w języku Java. Przenalizujmy poniższe przykłady.
Jedna z najpopularniejszych i najczęściej spotkanych metod tworzenia, alokacji i inicjalizacji pustej tablicy wygląda następująco.
String[] tab = new String[1]; // w momencie alokacji tablicy należy podać jej rozmiar
Powyższy zapis oznacza, że deklarujemy i jednocześnie alokujemy jednowymiarową pustą tablicę typu String. Sama deklaracja tablicy wygląda tak.
String[] tab;
Natomiast jeśli później będziemy chcieli ją alokować oraz jednocześnie inicjalizować no to możemy to zrobić choćby za pomocą słówka kluczowego new
(tablica jest obiektem).
tab = new String[1]; // należy tutaj pamiętać o podaniu rozmiaru tablicy, który musi być zdefiniowany w momencie alokacji
Tablicę w momencie alokacji możemy również zainicjalizować. Popatrzmy jak to się robi.
String[] tab; // deklaracja tablicy tab tab = new String[] {"A", "B", "C"}; //alokacja oraz inicjalizacja
Można to oczywiście zrobić nieco krócej.
String[] tab = {"A", "B", "C"};
Należy jednak pamiętać, że inicjalizacja tablicy poprzez nawiasy klamrowe, dopuszczalna jest jedynie w momencie jej alokacji. Jeśli tablica w momencie alokacji jest równocześnie inicjalizowana to nie podajemy jej rozmiaru.
String tab[]; tab = new []String {"A", "B", "C"}; // to jest niepoprawne – w tym przypadku nawias kwadratowy powinien znajdować się po słowie kluczowym String – new String[]{ "A" };
String tab[]; tab = {"A", "B", "C"}; // to też jest niepoprawne – nie możemy w ten sposób inicjalizować tablicy, jeśli jej równocześnie nie alokujemy
Powyższe dwa przykłady nie zostaną skompilowane poprawnie.
Jakie są dopuszczalne formy tworzenia tablic jednowymiarowych?
Poza przypadkami, które opisałem wyżej, podczas deklaracji oraz alokacji tablicy, specyfikacja Javy dopuszcza następujące formy.
String[] tab0 = new String[2]; String[] tab1 = new String[2]; String []tab2 = new String[2]; String tab3[] = new String[2]; String tab4 [] = { "A" }; // niepoprawny kod String tab5 = new []String; // powinno być new String[]; []String tab6 = new String[]; // nie możemy zaczynać od [] String[2] tab7 = new String[]; // nie możemy definiować rozmiaru tablicy w momencie jej deklaracji String[] tab8 = new String[]; // brak zdefiniowanego rozmiaru tablicy w momencie jej alokacji
W skrócie zasada jest taka, że nawiasy kwadratowe mogą występować po nazwie zmiennej lub jej typie.
Tablica wielowymiarowa
Deklaracja, alokacja i inicjalizacja
Tablice wielowymiarowe tworzy się praktycznie tak samo jak te jednowymiarowe. Jedna ważna uwaga to taka, że podczas alokacji tablicy (jeśli jej równocześnie nie inicjalizujemy) to musimy podać rozmiar przynajmniej pierwszego poziomu tablicy (dla kolejnych wymiarów może to zostać pominięte).
Java.util.Date[] dates[] = new java.util.Date[1][]; String[][][][] tab = new String[1][][][];
Poniższy kod nie zostanie skompilowany poprawnie, ze względu na brak wymiaru pierwszego poziomu tablicy.
int[][] tab = new int[][]; // musimy podać przynajmniej pierwszy rozmiar
Przykład alokacji i inicjalizacji tablicy wielowymiarowej.
String[][] tab = new String[][] { {"1", "3"}, {"2"} };
Oczywiście tablice wielowymiarowe mogą być asymetryczne. Dopuszczalna jest różna liczba kolumn w poszczególnych wierszach.
W przypadku tablic wielowymiarowych nawiasy klamrowe mogą występować zarówno po nazwie zmiennej jak i jej typie – identycznie jak w przypadku tablic jednowymiarowych. Wyjątek jest tu taki, że warunek ten może zachodzić równocześnie. Dopuszczalne są takie zapisy.
int[][] tab1[] = new int[1][][]; int[] tab2[] = new int[1][]; int tab3[][] = new int[1][]; int[][] tab4 = new int[1][]; String tab[][] = new String[][]{ {null}, new String[]{"a","b","c"}, {new String()} }; // ostatnia tablica, która odpowiada za “trzeci” wymiar, będzie potraktowana jako coś nadmiarowego i nie spowoduje błędu kompilacji
Dlaczego utworzenie tablic tab1, tab2 oraz tab3, bez określenia ich rozmiaru jest prawidłowej?
„Poza przypadkami, które opisałem wyżej, podczas deklaracji oraz alokacji tablicy, specyfikacja Javy dopuszcza następujące formy.
String[] tab0 = new String[2];
String[] tab1 = new String[];
String []tab2 = new String[];
String tab3[] = new String[];
String tab4 [] = { „A” };
„
Hej Tomek,
Pomyliłem się w kodzie, ten przykład miał głównie pokazywać w jaki sposób można wstawiać nawiasy „[ ]” przy deklaracji tablic. Oczywiście rozmiar tablicy musi być obowiązkowo uzupełniony w trakcie jej alokacji (o czym piszę w jednym z przykładów wyżej). Kod zaktualizowałem :)
Pozdrawiam,
Łukasz