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.
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<5; i++){ int e = 0; for(int j=0; j<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 < tab.length; i++) for(int j = 0; j < 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 < tab.length; i++) for(int j = 0; j < 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<tablica.length){ System.out.print(tablica[i]+" ") 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<tablica.length*tablica[0].length ; ++i) tablica[i/3][i%3]=i+1; for (int i=0 ; i<tablica.length*tablica[0].length ; ++i) System.out.print(tablica[i/3][i%3]+" "); } }
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<tab.length){ 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(""); } } }
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<tab.length;i++){ for(int j=0;j<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<tablica.length; i++){ for(int j=0; j<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<tab.length; i++){ for(int j=0; j<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ź :)