Cześć! Wcześniej na twoim szkoleniu pracowaliśmy z pojedynczymi obiektami (i typami pierwotnymi). Ale co, jeśli musimy pracować z całą grupą obiektów zamiast tylko jednego? Załóżmy na przykład, że chcemy stworzyć listę urodzin wszystkich pracowników naszej firmy. Powinien zawierać 30 ciągów sformatowanych w następujący sposób: „Sarah Huffman, 25 stycznia” Skorzystamy ze specjalnej struktury danych zwanej tablicą . Jeśli porównamy tablicę z rzeczywistym obiektem, jest ona bardzo podobna do skarbca bankowego ze skrytkami depozytowymi: tablica również składa się z „skrzynek”. Do każdego pudełka możesz włożyć coś (element). Aby uzyskać dostęp do elementu, musisz znać jego numer skrzynki (indeks). W ten sposób tworzona jest tablica:
Każda linia reprezentuje
public class Main {
public static void main(String[] args) {
String [] birthdays = new String[10];
}
}
Tutaj tworzymy tablicę zawierającą 10 elementów. Możesz od razu zauważyć niektóre cechy tablicy:
- Przechowuje elementy dobrze zdefiniowanego typu danych . Jeśli utworzymy tablicę String, nie możemy w niej przechowywać niczego innego. Typ danych jest określany podczas tworzenia tablicy . Tym różni się od skrytki depozytowej (w której klient może przechowywać to, na co ma ochotę).
- Jej rozmiar musi być określony podczas tworzenia tablicy . Nie można jej później wskazać ani zmienić jej rozmiaru po utworzeniu tablicy .
String [] birthdays = new String[10];
String birthdays [] = new String[10];
Jeśli chcesz zapisać coś w tablicy, musisz określić indeks pola, w którym zostanie wpisana wartość. Pola w tablicy są numerowane począwszy od 0. Liczenie od zera jest bardzo powszechną praktyką w programowaniu. Im szybciej się do tego przyzwyczaisz, tym lepiej :) Oznacza to, że jeśli chcesz umieścić jakąś wartość w pierwszym polu , robisz to:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
}
}
Teraz urodziny Jana są przechowywane w pierwszej komórce naszej tablicy urodzin pracowników: Możesz dodać inne wartości w podobny sposób:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
}
}
Zauważ, że dodaliśmy urodziny Rosie do ósmego pudełka (nie zapomniałeś, dlaczego pudełko nr 7 jest ósmym pudełkiem, prawda?) . Widać, że nie wypełniliśmy wszystkich pozostałych komórek. Nie musimy wpisywać wartości do tablicy po kolei. Nie ma takiego wymogu. Oczywiście pisanie elementów w kolejności znacznie ułatwia śledzenie, ile pól jest wolnych, a ile jest zajętych, i zapobiega powstawaniu „dziur” w tablicy. Jeśli chcesz uzyskać zawartość jednej ze skrytek, to (podobnie jak w przypadku skrytki depozytowej) musisz znać jej numer. Oto jak to się robi:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
String rosieBirthday = birthdays[7];
System.out.println(rosieBirthday);
}
}
Dane wyjściowe konsoli: Rosie Mills, 3 stycznia Stworzyliśmy String
zmienną i powiedzieliśmy kompilatorowi: „Znajdź pole o indeksie 7 w tablicy birthdays i przypisz zawartą tam wartość String
zmiennej rosieBirthday ”. I tak właśnie się stało. Podczas pracy z tablicami możemy łatwo znaleźć ich długość za pomocą specjalnej właściwości: length .
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
int birthdaysLength = birthdays.length;
System.out.println(birthdaysLength);
}
}
Dane wyjściowe konsoli: 10 Uwaga: length
Właściwość przechowuje rozmiar tablicy, a nie liczbę zapełnionych pól. Nasza tablica przechowuje tylko 3 wartości, ale podczas jej tworzenia wskazaliśmy jej rozmiar jako 10. I to jest dokładnie wartość, którą length
zwraca pole. Dlaczego miałoby się to przydać? Cóż, załóżmy, że chcesz wyświetlić listę wszystkich urodzin (aby sprawdzić, czy nikt nie został pominięty). Możesz to zrobić w jednej prostej pętli:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[2] = "Jeremiah Leonard, July 12";
birthdays [3] = "Kenny Russo, September 7";
birthdays[4] = "Tommie Barnes, November 9";
birthdays [5] = "Roman Baranov, August 14";
birthdays [6] = "Chanice Andersen, April 1";
birthdays[7] = "Rosie Mills, January 3";
birthdays [8] = "Keenan West, October 19";
birthdays [9] = "Abraham McArthur, May 3";
for (int i = 0; i < birthdays.length; i++) {
System.out.println(birthdays[i]);
}
}
}
W pętli deklarujemy zmienną i
, która jest inicjowana na zero. Przy każdym przejściu pobieramy element o indeksie i z naszej tablicy i wyświetlamy jego wartość. Pętla wykona 10 iteracji, a i wzrośnie od 0 do 9 — a tak się składa, że liczby są indeksami elementów naszej tablicy! W rezultacie wyświetlimy wszystkie wartości od birthdays[0] do birthdays[9] Właściwie istnieje inny sposób na utworzenie tablicy. Na przykład możesz utworzyć tablicę int
s w następujący sposób:
public class Main {
public static void main(String[] args) {
int numbers [] = {7, 12, 8, 4, 33, 79, 1, 16, 2};
}
}
Ta technika nazywa się „inicjowaniem skrótu”. Jest to dość wygodne, ponieważ jednocześnie tworzymy tablicę i wypełniamy ją wartościami. Nie musimy jawnie określać rozmiaru tablicy: przy inicjalizacji skrótu length
pole jest ustawiane automatycznie.
public class Main {
public static void main(String[] args) {
int numbers [] = {7, 12, 8, 4, 33, 79, 1, 16, 2};
System.out.println(numbers.length);
}
}
Dane wyjściowe konsoli: 9 Teraz trochę o tym, jak tablice są przechowywane w pamięci. Powiedzmy, że mamy tablicę trzech Cat
obiektów:
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public static void main(String[] args) {
Cat[] cats = new Cat[3];
cats[0] = new Cat("Thomas");
cats[1] = new Cat("Behemoth");
cats[2] = new Cat("Lionel Messi");
}
}
Musisz tutaj zrozumieć kilka rzeczy:
-
W przypadku prymitywów tablica przechowuje zestaw określonych wartości (np.
int
s). W przypadku obiektów tablica przechowuje zbiór referencji .
Tablicacats
składa się z trzech elementów, z których każdy jest odniesieniem doCat
obiektu. Każde z odwołań wskazuje adres pamięci, w której przechowywany jest odpowiedni obiekt. - Elementy tablicy są ułożone w jednym bloku w pamięci. Ma to na celu umożliwienie szybkiego i sprawnego dostępu do nich.
cats
odwołuje się do bloku pamięci, w którym przechowywane są wszystkie obiekty (elementy tablicy). Cats[0]
odwołuje się do określonego adresu w tym bloku. Ważne jest, aby zrozumieć, że tablica nie tylko przechowuje obiekty: jest sama w sobie obiektem. To prowadzi nas do pytania, czy możemy tworzyć nie tylko tablice ciągów znaków lub liczb, ale także tablice tablic . Odpowiedź brzmi: tak, możemy! Tablica może przechowywać dowolne obiekty, w tym inne tablice. Taka tablica nazywana jest dwuwymiarową . Gdybyśmy mieli go przedstawić wizualnie, byłby bardzo podobny do zwykłego stołu. Załóżmy, że chcemy utworzyć tablicę 3 tablic , z których każda może przechowywać 10 int
s. Wyglądałoby to tak:
int
tablicę. Pierwsza tablica zawiera liczby od 1 do 10, druga tablica — od -1 do -10, a trzecia — zbiór liczb losowych. Każda z tych tablic jest przechowywana w polach naszej dwuwymiarowej tablicy. W kodzie inicjalizacja dwuwymiarowej tablicy wygląda następująco:
public static void main(String[] args) {
Cat[][] cats = new Cat[3][5];
}
Nasze dwuwymiarowe tablice koty przechowują 3 tablice z 5 polami w każdej tablicy. Gdybyśmy chcieli umieścić obiekt w trzecim polu drugiej tablicy, zrobilibyśmy to w następujący sposób:
public static void main(String[] args) {
Cat[][] cats = new Cat[3][5];
cats[1][2] = new Cat("Fluffy");
}
[1]
wskazuje drugą tablicę i [2]
wskazuje trzecie pole tej tablicy. Ponieważ tablica dwuwymiarowa składa się z kilku tablic, w celu iteracji po niej i wyświetlenia wszystkich jej wartości (lub wypełnienia wszystkich jej elementów) potrzebujemy zagnieżdżonej pętli:
for (int i = 0; i < cats.length; i++) {
for (int j = 0; j < cats[i].length; j++) {
System.out.println(cats[i][j]);
}
}
W pętli zewnętrznej (zmienna i
) iterujemy po wszystkich tablicach w naszej dwuwymiarowej tablicy. W pętli wewnętrznej (zmienna j
) przechodzimy przez wszystkie elementy każdej tablicy. W rezultacie koty[0][0] (pierwsza tablica, pierwszy element) zostaną wyświetlone jako pierwsze, a następnie koty[0][1] (pierwsza tablica, drugi element). Po przejrzeniu pierwszej tablicy wyświetlimy koty[1][0] , koty[1][1] , koty[1][2] itd. Nawiasem mówiąc, tablice dwuwymiarowe również obsługują skrótowa inicjalizacja:
int[][] numbers = {{1,2,3}, {4,5,6}, {7,8,9}};
Zwykle zadeklarowalibyśmy dwuwymiarową tablicę numbers
jako int[3][3]
, ale ten skrót pozwala nam natychmiast określić wartości. Dlaczego potrzebujesz tablicy dwuwymiarowej? Cóż, możesz użyć jednego, aby łatwo odtworzyć słynną grę „Battleship”: w „Battleship” strukturę pola gry można łatwo opisać: dwuwymiarową tablicę 10 tablic po 10 elementów każda. Tworzysz dwie takie tablice (jedną dla siebie i jedną dla przeciwnika)
int[][] battleshipBoard1 = new int[10][10];
int[][] battleshipBoard2 = new int[10][10];
użyj pewnych wartości (np. liczb lub symboli), aby wypełnić elementy odpowiadające lokalizacji twoich statków, a następnie po kolei wywołuj współrzędne dla określonych elementów:
- plansza pancernika1[0][2]!
- Chybić! plansza pancernika2[2][4]!
- Uderzyć!
- plansza pancernika2[2][5]!
- Uderzyć!
- pancernikBoard2[2][6]!,
- Zatopiony!
GO TO FULL VERSION