Szkolenia programowania we Wrocławiu
Kurs Java Podstawy - rozszerzony

Tablice wielowymiarowe

W tej lekcji kursu 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 tablic. 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)

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.

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.

Zadania do samodzielnego wykonania:

1.14 Przy użyciu pętli i tablic przechowujących liczby całkowite zaprezentuj poniższą treść:

tab[0,0] = 0;

tab[0,1] = 1;

tab[0,2] = 2;

tab[1,0] = 3;

tab[1,1] = 4;

tab[1,2] = 5;

Wykorzystuj przy tym własność length.

Rozwiązanie.

<- Poprzednia LekcjaNastępna Lekcja ->

Komentarze

Mateusz

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

nie powinno być w pierwszej linijce:
int[][] tablica = new int[3][];

Slawek

owszem powinno, dzięki.

Mateusz

Masz literówkę: "Jako ciekawostka w języku C# istnieją zarówno tablice jedno i wielowymiarowe, oraz tablice wielowymiarowe JAKIE jak w Javie.", powinno chyba być "TAKIE jak w Javie".

Świetny kurs, dzięki za napisanie, dokładnie czegoś takiego szukałem!

Wojtek

nazwa_tablicy = new typ[ilosc1][ilosc2]; //przypisanie (utworzenie)


Błąd językowy - ilość odnosi się do rzeczy niepoliczalnych (ilość wody, ilość mąki), tutaj mówimy o "liczbie" ("liczba wierszy", nie "ilość wierszy")

Slawek

Dzięki, humanista ze mnie marny ;)

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


int[][] x = new int[5][5];
for(int i=0; i for(int j=0; j x[i][j] = i*5+j;

for(int[] wiersz: x)
for(int element: wiersz)
System.out.println(element);


int wiersz = 0;
int kolumna = 0;
while(wiersz kolumna = 0;
while(kolumna System.out.println(x[wiersz][kolumna]);
kolumna++;
}
wiersz++;
}
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 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 j = 0;
while (j tab[i][j] = licznik++;
j++;
}
i++;
}
for (i = 0; i System.out.print("tab[" + i + "]=");
for (j = 0; 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....

dqbEd1

Cześć.
Tworzę prostą grę - statki, i mam problemy z właśnie tablicą wielowymiarową. Otóż przy próbie przypisania wartości konkretnemu polu

tab[2][3] = 1;

zeruje mi się cała tablica, a potem ustawiana jest wartość 1 dla pola 2; 3.
Ktoś może mi coś doradzić?
:)

dqbEd1

Dla pewności nawet wyświetlam sobie zawartość tablicy przed i po próbie nadania wartości, i działa tak jak opisałem powyżej.

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();
}

thingness

O własności length powinien Pan napisać w poprzedniej lekcji o tablicach jednowymiarowych. :D Pozdrawiam

snt.banzai

Przyznam się szczerze, ze gdyby nie komentarze to nic bym z tej lekcji nie zrozumiał.

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ź :)