1. Wprowadzenie
Wyobraź sobie zwykłą tablicę jako długie pudełko po pizzy, w którym wszystkie kawałki leżą w jednym rzędzie — smacznie, ale monotonnie.
A teraz wyobraźmy sobie harmonogram prac albo szachownicę. Tam wszystko jest zorganizowane w wiersze i kolumny — czyli w tabelę. To właśnie klasyczny przypadek dla tablicy dwuwymiarowej.
W prawdziwym życiu tablice dwuwymiarowe spotyka się na każdym kroku:
- Tabele z wynagrodzeniami pracowników (wiersze — pracownicy, kolumny — miesiące).
- Obraz na ekranie (każda „komórka” — kolor piksela, ma dwie współrzędne: X i Y).
- Obliczenia macierzowe i przetwarzanie danych.
- Szachownica lub plansza do kółka i krzyżyka.
Czasem tablicę dwuwymiarową nazywa się macierzą (to określenie z matematyki).
Jest mnóstwo sytuacji, w których jako programista możesz potrzebować tablicy dwuwymiarowej. Implementacja niemal każdej gry planszowej to gotowa tablica dwuwymiarowa: „Szachy”, „Warcaby”, „Kółko i krzyżyk”, „Statki”:

Plansza gry „Szachy” lub „Statki” idealnie odwzorowuje tablice dwuwymiarowe, gdzie jako współrzędnych pól używa się po prostu liczb. Nie „pionek e2 ⟶ e4”, lecz „pionek (4,1) ⟶ (4,3)”. Jako programiście będzie ci tak nawet łatwiej.
2. Składnia deklaracji tablic dwuwymiarowych
Straszne jest tylko do pierwszej deklaracji! Rozłóżmy to krok po kroku.
Reguła ogólna
type[][] arrayName;
Tutaj dwa puste nawiasy kwadratowe [] — to nie błąd kompilatora po nocy z kawą, lecz wskazówka: tablica jest dwuwymiarowa.
Przykłady
int[][] matrix;
double[][] gradesTable;
string[][] chessBoard;
Tworzenie tablicy
Ustalamy wymiary: liczbę wierszy i kolumn.
matrix = new int[3][4]; // 3 wiersze, 4 kolumny
To tabelka 3×4: wyobraź sobie arkusz Excela z 3 wierszami i 4 kolumnami.
Można od razu zadeklarować zmienną i utworzyć tablicę dwuwymiarową:
int[][] matrix = new int[3][4];
Można od razu zainicjalizować wartościami (podobnie jak w przypadku jednowymiarowej):
int[][] example = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Tabela: 3 wiersze, 3 kolumny
Schemat wizualny
┌─────┬─────┬─────┬─────┐
│ 0 │ 1 │ 2 │ 3 │ ← kolumny (Columns)
├─────┼─────┼─────┼─────┤
│ 0,0 │ 0,1 │ 0,2 │ 0,3 │ ← wiersz 0 (Row 0)
├─────┼─────┼─────┼─────┤
│ 1,0 │ 1,1 │ 1,2 │ 1,3 │ ← wiersz 1 (Row 1)
├─────┼─────┼─────┼─────┤
│ 2,0 │ 2,1 │ 2,2 │ 2,3 │ ← wiersz 2 (Row 2)
└─────┴─────┴─────┴─────┘
Każdy element jest określany parą indeksów [row, column].
3. Indeksowanie i dostęp do elementów
W tablicy dwuwymiarowej, aby uzyskać dostęp do elementu, podajemy dwa indeksy:
- Pierwszy — numer wiersza.
- Drugi — numer kolumny.
// W drugim wierszu (indeks 1), trzecia kolumna (indeks 2)
matrix[1][2] = 99;
Jeśli ktoś przywykł do szachów, przypomnę: indeksowanie zaczyna się od zera. Czyli pierwszy element to [0][0].
Zapis i odczyt
int[][] data = new int[5][2];
data[1][1] = 5; // zapis
int value = data[1][1]; // odczyt
Tak będzie to wyglądać w pamięci:

4. Wypełnianie tablicy dwuwymiarowej
Napiszmy kod, który wypełni macierz kolejnymi liczbami od 1 do 12, aby stało się jasne, jak to działa.
int[][] matrix = new int[3][4];
int value = 1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 4; col++)
{
matrix[row][col] = value;
value++;
}
}
Ilustracja:
Po wykonaniu:
┌────┬────┬────┬────┐
│ 1 │ 2 │ 3 │ 4 │
├────┼────┼────┼────┤
│ 5 │ 6 │ 7 │ 8 │
├────┼────┼────┼────┤
│ 9 │ 10 │ 11 │ 12 │
└────┴────┴────┴────┘
5. Budowa tablic dwuwymiarowych
A teraz dowiesz się, jak naprawdę są zbudowane tablice dwuwymiarowe. Gotowy?
Tablice dwuwymiarowe — to w rzeczywistości tablice tablic!
Innymi słowy, jeśli w przypadku zwykłej tablicy „zmienna-tablica przechowuje referencję do kontenera, który przechowuje elementy tablicy”, to w przypadku tablic dwuwymiarowych sytuacja jest nieco bardziej wybuchowa: zmienna—tablica-dwuwymiarowa przechowuje referencję do kontenera, który przechowuje referencje do tablic jednowymiarowych. Lepiej zobaczyć to raz, niż próbować tłumaczyć sto razy:

Po lewej mamy „zmienną—tablicę dwuwymiarową”, która przechowuje referencję do „obiektu—tablicy dwuwymiarowej”. Pośrodku mamy „obiekt tablicy dwuwymiarowej”, w którego komórkach znajdują się referencje do tablic jednowymiarowych — wierszy tablicy dwuwymiarowej. No i po prawej widzisz cztery tablice jednowymiarowe — wiersze naszej tablicy dwuwymiarowej.
Tak w rzeczywistości są zbudowane tablice dwuwymiarowe. Takie podejście daje programiście Java kilka zalet:
Po pierwsze, ponieważ „kontener kontenerów” przechowuje referencje do „tablic-wierszy”, możemy bardzo szybko i prosto zamieniać wiersze miejscami. Aby uzyskać dostęp do „kontenera kontenerów”, wystarczy podać jeden indeks zamiast dwóch. Przykład:
int[][] data = new int[2][5];
int[] row1 = data[0];
int[] row2 = data[1];
Takim kodem można zamienić wiersze miejscami:
// Ważna macierz z danymi
int[][] matrix = {
{1, 2, 3, 4, 5},
{5, 4, 3, 2, 1}
};
int[] tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;
Jeśli odwołujesz się do komórki tablicy dwuwymiarowej, ale po nazwie tablicy podajesz tylko jeden indeks, uzyskasz dostęp do kontenera-kontenerów, w którego komórkach przechowywane są referencje do zwykłych tablic jednowymiarowych.
6. Wypisywanie tablicy dwuwymiarowej na ekran
Do wypisywania tabeli dwuwymiarowej zwykle używa się podwójnej pętli — i to jak rysowanie labiryntu w konsoli. Przykład:
for (int row = 0; row < matrix.length; row++)
{
for (int col = 0; col < matrix[row].length; col++)
{
System.out.print(matrix[row][col] + "\t");
}
System.out.println(); // przejście do nowej linii
}
Przykładowy wynik:
1 2 3 4
5 6 7 8
9 10 11 12
Przy okazji, tutaj nauczyłeś się ładnie „rysować” tabele za pomocą kilku linijek kodu!
GO TO FULL VERSION