Tablice wielowymiarowe

Teoria

W tej lekcji poznamy tablice wielowymiarowe, które są naturalnym rozszerzeniem tablic jednowymiarowych. Różnią się przede wszystkim sposobem deklaracji i odwoływania do jej elementów. Za jej pomocą można na przykład w łatwy sposób wyobrazić sobie grę w statki - można przechowywać za pomocą współrzędnych miejsce położenia statków. Tablice wielowymiarowe w języku Java to tak naprawdę tablice które zawierają tablice. Jako ciekawostka w języku C# istnieją zarówno tablice jedno i wielowymiarowe, oraz tablice wielowymiarowe takie jak w Javie (tablice tablic).

Schematyczna deklaracja wygląda tak:

typ[][] nazwa_tablicy; //deklaracja
nazwa_tablicy = new typ[liczba1][liczba2]; //przypisanie (utworzenie)
typ[][] nazwa_tablicy2 = new typ[liczba1][liczba2]; //deklaracja i przypisanie (utworzenie)

Tworzenie tablic wielowymiarowych

Widzimy, że podobnie jak w przypadku tablic jednowymiarowych możemy zarówno zadeklarować i utworzyć tablicę w dwóch różnych miejscach jak i połączyć te operacje ze sobą. Powyżej utworzyliśmy tablicę dwuwymiarową. Struktura taka może przechowywać liczba1*liczba2 elementów. Nic nie stoi na przeszkodzie, aby utworzyć tablice 3 i więcej wymiarowe, ale zazwyczaj nie jest to potrzebne, a na pewno nie jest to praktyczne. Do elementów tablic wielowymiarowych odwołujemy się analogicznie, jak w przypadku jednowymiarowych, możemy sobie wyobrazić, że to podawanie współrzędnych punktów, przykładowo:

int[][] tablica = new int[3][3];
tablica[2][1] = 5;
int zmienna = tablica[2][1];

W ten sposób utworzyliśmy tablicę dwuwymiarową mogącą przechować 9 elementów. Do komórki pod współrzędną (2,1) zapisaliśmy wartość 5, a następnie wykorzystaliśmy ją do zainicjowania zmiennej.

Kurs Java

Tablica niesymetryczna

Ciekawą i często użyteczną funkcjonalnością jest to, że tablica wielowymiarowa nie musi być symetryczna. Przykładowo:

int[][] tablica = new int[3][];
tablica[0] = new int[3];
tablica[1] = new int[2];
tablica[2] = new int[1];

Jeśli byśmy zainicjowali wszystkie jej elementy na przykład w poniższy sposób:

for (int i = 0; i < tablica.length; i++) {
    for (int j = 0; j < tablica[i].length; j++) {
        tablica[i][j] = 0;
    }
}

Użyliśmy tu ważnej własności każdej tablicy, mianowicie length (zauważ, że nie jest to metoda i nie jest zakończona nawiasami() ). Określa ona jej długość, tutaj należy zapamiętać, że zwracana wielkość jest rzeczywista, a nie liczona od 0. W naszym powyższym przykładzie jej wywołania przedstawiają się tak:

  • tablica.length = 3 (bo mamy new tablica[3][x];
  • tablica[0].length = 3
  • tablica[1].length = 2
  • tablica[2].length = 1

Dzięki temu po wydruku danych w podobny sposób:

for (int i = 0; i < tablica.length; i++) {
    for (int j = 0; j < tablica[i].length; j++) {
        System.out.print(tablica[i][j]);
    }
    System.out.println();
}

Uzyskamy wynik postaci:

000
00
0

Własność length posiada każda tablica w Javie, także jednowymiarowa. Przy wypełnianiu, lub wyświetlaniu danych przy użyciu pętli jej używanie jest zdecydowanie wskazana, ponieważ zwiększa to uniwersalność kodu. Przy zmianie wielkości tablicy przy jej tworzeniu nie musimy poprawiać dalszej części kodu, ponieważ jest on elastyczny.

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.

Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.

Krzysiek

Witam ponownie, gdyż znowu mam zaćmienie a chce już ten dział podstaw zakończyć. Czy można tabele wielowymiarową wyświetlić za pomocą pętli for each a jeśli tak to jak? Kiedy wrzucam zapis for(int x: a) to nie kompiluje tego bo czepia się, że "a" to "int[]" a wymagany jest "int". Kiedy użyję zapisu for(int[]x: a) to kompiluje ale na tym kończy się radocha bo po uruchomieniu wyświetlają się jakieś cuda niewidy typu [[I@15e8f2a0[[I@15e8f2a0[[I@15e8f2a0 czyli 3 x [[I@15e8f2a0 :(. A co z wyświetleniem za pomocą pętli while przy wielowymiarówkach, czy jest możliwe? Wystarczą mi konkretne przykłady, nie trzeba tłumaczyć.

Slawek

<pre name="code" class="java"> int[][] x = new int[5][5]; for(int i=0; i<5; i++) for(int j=0; j<5; j++) x[i][j] = i*5+j; for(int[] wiersz: x) for(int element: wiersz) System.out.println(element); </pre> <pre name="code" class="java"> int wiersz = 0; int kolumna = 0; while(wiersz < x.length) { kolumna = 0; while(kolumna < x[wiersz].length) { System.out.println(x[wiersz][kolumna]); kolumna++; } wiersz++; } </pre>

Krzysiek

Dzięki, to wszystko jest proste jak już się wie:) Pętle jak pętle, ale ten zapis mnie rozbroił x[i][j] = i*5+j; To tylko takie proste działanie matematyczne (0*5+0, 0*5+1, 0*5+2, 0*5+3, 0*5+4, 1*5+0, 1*5+1 ...... 4*5+3, 4*5+4) a wieki by mineły zanim sam bym doszedł jak wypełnić tablicę liczbami jedną po drugiej, jeśli w ogóle bym do tego doszedł. Tu nie matma a wyobraźnia i pomysłowość najważniejsza. Do tej pory mi wyświetlało 111222333 i myślałem, że jak poradzę sobie z pętlami to i to się jakoś wyjaśni. Wyprzedziłeś fakty. Dobra teraz powtórka już samych zadań z tego działu i spadam dalej:)

Krzysiek

He He :))) Wypełnienie liczbami w odwrotnej kolejności :):):) int[][] x = new int[5][5]; int d = 5; for(int i=0; i&lt;5; i++){ int e = 0; for(int j=0; j&lt;5; j++){ x[i][j] = d*5-e; e++;} d--;} for(int[] wiersz: x) for(int element: wiersz) System.out.println(element); } }

Krzysiek

Ale w sumie można łatwiej więc po co te kombinacje z mnożeniem i dwoma zmiennymi? Po kolei: int[][] tab = new int[5][5]; int a = 0; for(int i = 0; i &lt; tab.length; i++) for(int j = 0; j &lt; tab[i].length; j++){ tab[i][j] = a++;} i w drugą strone: int[][] tab = new int[5][5]; int a = 25; for(int i = 0; i &lt; tab.length; i++) for(int j = 0; j &lt; tab[i].length; j++){ tab[i][j] = a--;}

HELP

Moze ktoś wytłumaczyć ten "rozbrajający" zapis x[i][j] = i*5+j

lolo

Zapis x[i][j] = i*5+j oznacza tyle, że do tablicy dwuwymiarowej x[][] do komórki o indeksie x[i][j] ( np. zmienna i=5 i j=6 to do komórki o indeksie [5][6]) zostanie wpisany wynik z działania i*5+j (w podanym przezemnie przepadku będzie to wynik z 5*5+6 czyli 31).

HELP

Dzięki nawet nie myślałem, że ktoś odpisze.

Marek

int[][] tablica = new int[3][]; tablica[0] = new int[3]; tablica[1] = new int[2]; tablica[2] = new int[1]; o co chodzi w tym zapisie?

Krzysiek

int[][] tablica = new int[3][]; /* podajesz ilość wierszy, natomiat ilość kolumn pozostawiasz pustą i rozpisujesz każdą koumnę z osobna, gdyż do każdego wiersza chcesz dopisać inną ilość kolumn. Gdybyś napisał odrazu np. int[][] tablica = new int[3][4]; to każdy z 3 wierszy miał by po 4 kolumny, a tak to:/ tablica[0] = new int[3]; // wierszowi pierwszemu przypisujesz 3 kolumny tablica[1] = new int[2]; // wierszowi drugiemu 2 kolumny tablica[2] = new int[1]; // wierszowi trzeciemu 1 kolumnę Sprawdź sobie też to http://www.java2s.com/Book/Java/0020__Language-Basics/Multidimensional_Arrays.htm

Marek

A czy można pozostawić pustą ilość wierszy a ilość kolumn podać np. 3 ? Czyli : int[][] tablica = new int[][3]; ?

Krzysiek

Przeciez kolumna nie moze istniec bez wiersza, bo w czym ja "zawiesisz"? w nicosci? int[][] tablica = new int[][3]; to juz na dzien dobry znaczy int[][] tablica = new int[1][3]; czyli 3 kolumny w jednym wierszu.

Witek

Witam Codzi Ci o tzw. tablice nieregularne, wymagany jest tylko pierwszy rozmiar, natomiast drugi może być pusty np.: „ int tab[][] = new int[3][] ; “ , a pozostałe rozmiary możesz zaalokować odzielnie.

Fiesta

while(licznik&lt;tablica.length){ System.out.print(tablica[i]+&quot; &quot;) licznik++; }tutaj chyba błąd jest, klasa nie jusmpilkoe się bo zmienna [i] jest deklarowana w for-ach i tylko tam istnieje

aaantek

Witam można wydrukować dane z tablicy wielowymiarowej za pomocą pętli for each? jeśli tak to jak to zapisać?

Bogdan

Ciekawą i często użyteczną funkcjonalnością jest to, że tablica wielowymiarowa nie musi być symetryczna. Słowo "symetryczna" jest w tym miejscu całkowicie nieodpowiednie. Proponuję Ciekawą i często użyteczną funkcjonalnością jest to, że tablica dwuwymiarowa nie musi być prostokątna (analogicznie dla wyższych wymiarów).

pavon147

Napotkałem na ciekawy problem. Nie będę wrzucał tutaj kodu, chyba, że będzie to konieczne, ale postaram się opisać po prostu tą sytuację. Tworzę tablicę wielowymiarową typu String. Użytkownik podaje jej wymiary oraz wypełnia ją. I teraz co się dzieje. Po pobraniu rozmiarów tablicy następuje jej wypełnienie za pomocą pętli for, oczywiście user podaje wszystko po kolei i wszystko byłoby ok tylko, że pętla przechodzi przez pierwsze przejście nie czekając na dane od użytkownika. Zachowuje się tak, jakby użytkownik nacisnął ENTER (podczas kolejnych przejść wszystko działa jak należy). Do pobierania danych wykorzystuję funkcję nextLine(); Udało mi się to jednak rozwiązać, wszedłem na stronę Oracle i znalazłem funkcję next(); i po jej zastosowaniu wyżej opisany błąd nie występuje. Chciałem prosić o wytłumaczenie różnicy między nextLine(); a next(); bo po prostu to co jest napisane w krótkim wyjaśnieniu pod tymi funkcjami na stronie Oracle nie pasuje mi do tego, co dzieje się w kodzie, więc chyba czegoś nie rozumiem. Z góry dzięki za odpowiedź ;)

adamglos92

Po pierwsze gratuluję wspaniałego kursu:) Po drugie jako ciekawostkę zamieszczam rozwiązanie bez użycia podwójnej pętli: public class TabWiel{ public static void main (String[] args){ int[][] tablica = new int[2][3]; for (int i=0 ; i&lt;tablica.length*tablica[0].length ; ++i) tablica[i/3][i%3]=i+1; for (int i=0 ; i&lt;tablica.length*tablica[0].length ; ++i) System.out.print(tablica[i/3][i%3]+&quot; &quot;); } }

Marcin

Witam. Może mi ktoś wskazać błąd w tym kodzie ? Meczy się z tym od jakiegoś czasu.... Chodzi o zapełnienie tablicy danymi z użyciem pętli "while". Oto listing: class Main{ public static void main(String args[]){ int[][]tab=new int[4][]; tab[0]=new int[4]; tab[1]=new int[3]; tab[2]=new int[2]; tab[3]=new int[1]; int licznik=1; int i=0; int j=0; while(i&lt;tab.length){ while(j&lt;tab[i].length){ tab[i][j]=licznik++; j++; } i++; } for(i=0;i&lt;tab.length;i++){ System.out.print(&quot;tab[&quot;+i+&quot;]=&quot;); for(j=0;j&lt;tab[i].length;j++){ System.out.print(tab[i][j]+&quot; &quot;); } System.out.println(&quot;&quot;); } } }

Marcin

oooo widzisz :) Dzięki wielkie!

Marcin

P.S. Bład polega na tym ze tylko pierwszy wiersz jest zapełniony liczbami a kolejne juz zamiast dalszymi to same zera....

Marcin Kunert

Zapominasz zerować zmiennej "j" w wewnętrznej pętli. public static void main(String args[]) { int[][] tab = new int[4][]; tab[0] = new int[4]; tab[1] = new int[3]; tab[2] = new int[2]; tab[3] = new int[1]; int licznik = 1; int i = 0; int j = 0; while (i < tab.length) { j = 0; while (j < tab[i].length) { tab[i][j] = licznik++; j++; } i++; } for (i = 0; i < tab.length; i++) { System.out.print("tab[" + i + "]="); for (j = 0; j < tab[i].length; j++) { System.out.print(tab[i][j] + " "); } System.out.println(""); } }

adrian

Mógłby ktoś wytłumaczyć mi krok po kroku co się dzieje w jakimś przykładowym kodzie z tablicami dwuwymiarowymi? Z jednowymiarowymi dałem radę, ale teraz znowu klops. Jakiś przykładowy kod z tablicą dwuwymiarową, i np. pętlą for. Krok po kroku, co się dziej w programie, od początku do końca.

Maciek

Też właśnie stanąłem jakoś na tej lekcji, wcześniejsze przeszedłem bezboleśnie tylko tutaj jakoś nie rozumiem po prostu jak rzeczy działają(polecenia zadania tez w sumie;/) :( Podczepiam się o prośbę o jakieś przykłady dodatkowe) A ogólnie kurs super ! :D Najlepsze do czego dotarłem(a z programowaniem do czynienia wczesniej nie miałem wgl) Pozdrawiam

Piotr

Witam, Posiadam takiego maina i mam problem gdyż wynik sie nie zgadza z zamieszczonym. public class Pro{ public static void main(String[] args){ int[][] tab = new int[3][3]; for(int i=0;i&lt;tab.length;i++){ for(int j=0;j&lt;tab[i].length;j++){ System.out.print(tab[i][j]); } System.out.println(); } } } dostaje: 000 000 000

lolo

Przecież zadeklarowałeś tablicę 3x3 standardowo jest uzupełniana 0 bo nie wpisałeś innych wartości. To co Ci się nie zgadza?

Piotr

powinno być podobno tak: 000 00 0

lolo

Napisałeś: int[][] tab = new int[3][3]; A nie jak w przykładzie u góry: int[][] tablica = new int[3][]; tablica[0] = new int[3]; tablica[1] = new int[2]; tablica[2] = new int[1]; Przyjmijmy, że tablica wielowymiarowa jest to tabliczka czekolady a każdy jeden element [ ] to kostka tejże czekolady. Ty deklarujesz tabliczkę czekolady 3 na 3. Czyli mamy 3 wiersze i w każdym po 3 kolumny: [ ][ ][ ] [ ][ ][ ] [ ][ ][ ] A w przykładzie zdeklarowana jest tabliczka o 3 wierszach kostek (pierwsza linijka int[][] tablica = new int[3][];) [ ] [ ] [ ] I w kolejnych linach deklarowana jest ilość kostek znajdujących się w każdym wierszu naszej tabliczki czekolady W pierwszym wierszu tablica[0] = new int[3]; deklarowane są 3 kostki W drugim wierszu tablica[1] = new int[2]; deklarowane są 2 kostki i w trzecim wierszu tablica[2] = new int[1]; zdeklarowana jest 1 kostka [ ][ ][ ] [ ][ ] [ ]

Janosch

Świetne porównanie, właśnie czegoś takiego mi było trzeba!

D

public class wielowymiarowe { public static void main(String[] args) { // TODO Auto-generated method stub int[][] tablica = new int[3][]; tablica[0] = new int[3]; tablica[1] = new int[2]; tablica[2] = new int[1]; for(int i=0; i&lt;tablica.length; i++){ for(int j=0; j&lt;tablica[i].length; j++){ System.out.println(tablica[i][j]); } System.out.println(); } } } A wynik w konsoli jest taki: 0 0 0 0 0 0 Dlaczego?

G.Jeszka

Bo jest błąd w pętli, w złym miejscu jest wprowadzana new line. for(int i=0; i&lt;tab.length; i++){ for(int j=0; j&lt;tab[i].length; j++){ System.out.print(tab[i][j]); } System.out.println(); }

Damian

mysle ze dla niektorych osob bedzie to niezrozumiale poniewaz nie widza oni 2 kolumna po 3 wiersze, w tym przypadku jedna tablica jest pod druga ,moze zapis tab[0,0] = 0; tab[1,0] = 3; tab[0,1] = 1; tab[1,1] = 4; tab[0,2] = 2; tab[1,2] = 5; cos podpowie;)

Mikołaj

Mam pytanie. Otóż w zadaniu jest aby zrobić pętle wypełniającą tablice w sposób "poziomy", czyli po kolei 012345 od lewej do prawej: tab[0,0] = 0; tab[0,1] = 1; tab[0,2] = 2; tab[1,0] = 3; tab[1,1] = 4; tab[1,2] = 5; Jak w takim razie napisać to, aby wypełniało tablicę w sposób "pionowy, czyli z góry na dół? (Wyglądało by to tak): tab[0,0] = 0; tab[0,1] = 2; tab[0,2] = 4; tab[1,0] = 1; tab[1,1] = 3; tab[1,2] = 5; Proszę o odpowiedź :)