Twitter: @grzegg
Kategoria: java, Tagi: - - .

Java [15] – Tablice cz. I: tablice jednowymiarowe

Często w programie trzeba zachować wiele związanych ze sobą w jakiś sposób elementów a także przeprowadzać na nich pewne operacje. Mogą to być na przykład serie pomiarów, które chcemy poddać analizie statystycznej, numery telefonów czy lista znalezionych na badanym obszarze gatunków. W takich przypadkach bardzo pomocne są tablice.

Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

Czym są tablice?

Tablice są strukturami pozwalającymi przechowywać wiele elementów tego samego typu. Tablica może więc służyć do zebrania serii liczb, łańcuchów znaków, obiektów czy nawet innych tablic. Mogą mieć jeden, dwa i więcej wymiarów ale w tej lekcji zajmę się tablicami jednowymiarowymi.

Tworzenie tablic

Ponieważ wszystkie elementy w jednej tablicy muszą być tego samego typu, przy deklaracji określamy od razu rodzaj elementów, który będziemy w niej przechowywać. Ogólnie deklaracja tablicy wygląda w ten sposób:

typ[] nazwaTablicy

Na przykład deklaracja tablicy, liczb całkowitych typu int będzie wyglądała tak:


int[] tablicaLiczb;

Deklaracja tablicy przechowującej łańcuchy znaków może z kolei przybrać taką formę:


String[] tablicaGatunkow;

Jak widać deklaracja tablicy jest bardzo podobna do deklaracji zmiennych, różni ją obecność pary nawiasów kwadratowych []. Może zresztą znaleźć się ona po nazwie tablicy zamiast po typie elementów. Deklaracja int liczby[] także jest prawidłowa, choć raczej nie preferowana.

Deklaracja tablicy mówi o rodzaju elementów, które się w niej znajdą ale nie mówi o tym ile elementów może pomieścić. Tą informację przekazujemy przy jej tworzeniu:


tablica = new int[10];

Obie operacje można oczywiście połączyć:

typ[] nazwaTablicy = new typ[liczbaElementów];

Co ważne, kiedy już określimy wielkość tablicy, nie można jej zmieniać. Więc jeśli na przykład utworzymy tablicę dziesięcioelementową nie zmieścimy w niej jedenastego elementu. Można to ograniczenie obejść stosując pewne triki o czym będzie mowa w następnej lekcji albo można użyć list tablicowych, które opiszę jeszcze później.

Nowo utworzoną tablicę można sobie wyobrazić jako półkę z przegródkami w których można umieszczać elementy, przy czym każda z nich ma swój kolej numer. „Przegródki” będziemy nazywać komórkami a numery indeksami.


Zauważ, że:

  • numer pierwszego indeksu = 0
  • numer ostatniego indeksu jest o jeden mniejszy niż liczba elementów w tablicy

Jeśli od razu wiadomo jakie elementy mają znaleźć się w tablicy można od razu połączyć deklarację z inicjalizacją i wypełnieniem tablicy, na przykład tak:


double[] pomiary = {2.1, 4.0, 3.1, 3.0, 2.8, 3.2, 2.7, 3.8, 2.5, 2.9};

W takim przypadku tworzona jest tablica dziesięcioelementowa i od razu zostaje wypełniona podanymi wartościami:


Odwołania do elementów tablicy

Odwołanie się do elementu tablicy wygląda w ten sposób:

tablica[indeks]

Na przykład jeśli chcemy wydrukować zawartość trzeciej komórki można zrobić to tak:


System.out.println("Trzecia: " + pomiary[2]);

Zauważ, że trzecia komórka ma indeks 2, co wynika z tego, że numery indeksu zaczynają się od 0.

Na wartościach umieszczonych w tablicy można wykonywać operacje analogiczne do tych, które wykonuje się na zmiennych, na przykład:

double liczba = pomiary[2];
double sumaDwuPomiarow = pomiary[4] + pomiary[5];
System.out.println("Suma dwu pomiarów: " + sumaDwuPomiarow);
System.out.println("Suma trzech pomiarów: " + (pomiary[1] + pomiary[2]+ pomiary[3]));

itd…

Aby pobrać zawartość komórki o danym indeksie nie trzeba koniecznie używać liczby, można na przykład użyć nazwy zmiennej lub innego wyrażenia zwracającego liczbę typu int:

int indeks = 4;
System.out.println("Piąty element: " + pomiary[indeks]);
System.out.println("Ósmy element: " + pomiary[(10 + 4)/2]);

Umieszczanie elementów w tablicy

Umieszczanie elementów w tablicy przebiega podobnie jak pobieranie z niej:

String[] planety= new String[7];
planety[0] = "Merkury";
planety[3] = "Mars";
planety[6] = "Uran";
planety[2] = "Ziemia";

Jak widać, nie trzeba od razu wypełniać całej tablicy, nie trzeba też dodawać elementów po kolei. Ale skoro pozostają komórki niewypełnione, to można zadać sobie pytanie co właściwie tam się znajduje. Można to sprawdzić odwołując się do nich:

System.out.println("Druga planeta: " + planety[1]);

Rezultat jest taki:


Druga planeta: null

Przypomnę, że w pierwszej lekcji poświęconej zmiennym napisałem, że String należy typów odnośnikowych, inaczej jest to odwołanie do obiektu. Nie wchodząc w szczegóły oznacza to, że zmienna tego typu przechowuje referencję (odwołanie, odnośnik) do obiektu, czyli informację o miejscu gdzie w pamięci komputera znajduje się dany obiekt. Tablica elementów typu String przechowuje właśnie takie odwołania a wartość null oznacza, że odwołanie nie prowadzi do żadnego obiektu. Można to rozumieć w ten sposób, że null oznacza „nic” (ale nie wartość 0!).

W tablicach przechowujących elementy typu String a także inne typy obiektowe wartością domyślną, umieszczaną „na dzień dobry” w pustej tablicy, lub jej niewypełnionych elementach jest null, ale jakie wartości domyślne znajdują się w tablicach tworzonych dla innych typów danych? Najlepiej to sprawdzić wykonując na przykład taki kod:

Otrzymujemy:


liczbyInt[2] = 0
liczbyDouble[2] = 0.0
wartosciBoolean[2] = false

Zwróć uwagę, że jeśli przy tworzeniu nie podamy wartości, tablica przechowująca liczby jest wypełniana zerami. Warto o tym pamiętać, ponieważ może to być przyczyną błędów rachunkowych, na przykład gdy puste elementy tablicy zostaną potraktowane jako część danych. Podobnie, może dojśc do błędnego działania programu jeśli domyśla wartość false przechowywana w zmiennej typu boolean będzie traktowana jako wartość wprowadzona.

Tablice i pętle

Używając tablic bardzo często przeprowadzamy jakieś operacje na wszystkich elementach po kolei, na przykład wypisując ich wartości, używając ich w obliczeniach itp. W takich przypadkach musimy odwoływać się po kolei do poszczególnych komórek tablicy. Można to oczywiście zrobić robić np. w ten sposób:

double sumaPomiarów = 0;
sumaPomiarów += pomiary[0];
sumaPomiarów += pomiary[1];
sumaPomiarów += pomiary[2];

Ale tego typu operacje aż proszą się, żeby wykorzystać możliwości oferowane przez pętle.
Jeśli chcemy na przykład wydrukować wszystkie elementy w tablicy można to zrobić tak:

Otrzymujemy:


indeks: 0 wartość: 2.1
indeks: 1 wartość: 4.0
indeks: 2 wartość: 3.1
. . .
indeks: 9 wartość: 2.9

Zauważ, że w warunku pętli użyłem wyrażenia i < 10 co wynika z tego, że ostatni element tablicy ma indeks o jeden mniejszy niż liczba elementów.

Odpowiednio manipulując parametrami pętli można uzyskać jej wybrane elementy. Na przykład for (int i = 0; i < 10; i = i + 2) pozwoli uzyskać co drugą wartość.

Liczba 10 użyta w powyższym przykładzie odpowiada długości tablicy. Czasem jednak wielkość tablicy nie jest z góry znana, może zależeć np. od decyzji użytkownika. Miedzy innymi z tego powodu bezpieczniej jest używać w pętlach operujących na tablicach raczej informacji o długości tablicy, pobieranej od niej samej, niż wpisywać na sztywno liczby. Taką wartość można uzyskać w prosty sposób:

tablica.length

Zmodyfikowana pętla, będzie zatem wyglądać tak:

Uwaga na zakres indeksów

Odwołując się do elementów tablicy za pomocą indeksów należy pamiętać aby użyte wartości dla indeksów nie przekroczyły wymiarów tablicy. Na przykład próbując uruchomić taki kod:

Otrzymamy komunikat o błędzie.


Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

Program próbował się odwołać do piątego elementu w tablicy, a były w niej tylko cztery komórki.

Zadanie

Utwórz tablicę, wypełnij wartościami od 0–99 a następnie napisz kod który wypisze zawartość tablicy, po 10 liczb w rzędzie, tak, aby liczby jednocyfrowe zostały wypisane jako dwucyfrowe (np. zamiast 9 zostało wypisane 09):


00, 01, 02, 03, 04, 05, 06, 07, 08, 09,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,

Pętla foreach

Teraz przyszedł czas na poznanie ostatniego z typów pętli czyli pętli foreach. Jej struktura wygląda tak:


for(deklaracja zmiennej : tablica) {

}

Jak widać nazwa jest trochę myląca, ponieważ zamiast foreach widnieje powyżej for. Ale nazwa jest taka (jak sądzę) po pierwsze dla tego, żeby odróżnić ją od „klasycznej” pętli for a po drugie podkreśla jej zastosowanie: operowanie na każdym elemencie tablicy. Jest to bowiem pętla stworzona do obsługi tablic (i innych podobnych obiektów). Zadeklarowana zmienna musi być tego samego typu co elementy przechowywane przez tablicę. Podczas każdej iteracji (pojedynczego wykonania pętli) pobierana jest kolejna wartość z tablicy, która zostaje przypisana zadeklarowanej zmiennej. Nie trzeba się troszczyć o długość tablicy, Java sama „wie” kiedy skończyć. Przy użyciu pętli foreach wypisanie wszystkich wartości z tablicy może wyglądać tak:

Zaletą tej pętli jest niewątpliwie jej prostota do wad należy to, że nie ma tu wbudowanego „licznika”, który informowałby o tym w którym miejscu tablicy pętla się aktualnie znajduje, ale nie zawsze jest to potrzebne. Ponadto w razie konieczności można taki „licznik” dopisać:

Zadanie

Napisz program, który będzie znajdował największą wartość z podanych przez użytkownika pomiarów (dodatnie liczby typu double) a następnie poda ich sumę i średnią arytmetyczną. Wcześniej użytkownik deklaruje ile liczb będzie chciał wpisać.

Poniżej znajdują się wskazówki, zanim z nich skorzystasz, spróbuj poradzić sobie samodzielnie

<

p class="uwaga"> Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

6 komentarzy Java [15] – Tablice cz. I: tablice jednowymiarowe

  • Piter

    jak zrobić lsowoy tekst che aby wyloswało mi jedną rzecz z posród 50 tylko nie cyfry a tekst dodaż że chcę zrobć to w netbeans

    • Grzegorz

      Tu na przykładzie sześciu String-ów:


      import java.util.Random;

      public class Losowanie {

      public static void main(String[] args) {
      // Tworzenie i wypełnianie tablicy
      String[] tablica ={"Ala", "Aga", "Ula", "Ola", "Ela", "Iza"};
      // Tworzenie obiektu typu Random - służy do generowania liczb pseudolosowych
      Random losowacz = new Random();
      // Losowanie liczby z zakresu (0-5)
      int wylosowanyIndeks = losowacz.nextInt(6);
      // Uzyskanie String-a z tablicy z komórki o wylosowanym indeksie
      String wylosowana = tablica[wylosowanyIndeks];
      // Wydruk wyniku
      System.out.println("Wylosowano: " + wylosowana);
      }
      }

      Albo krócej (ciało metody 'main()`, już bez komentarzy):


      String[] tablica ={"Ala", "Aga", "Ula", "Ola", "Ela", "Iza"};
      Random losowacz = new Random();
      System.out.println("Wylosowano: " + tablica[losowacz.nextInt(6)]);

      O losowaniu liczb napisałem tutaj.

  • Michal

    Jak zrobic to drugie zad we wspomnianej jednej petli?

  • Mateusz

    „System.out.println(„Suma trzech pomiarów: ” + pomiary[1] + pomiary[2]+ pomiary[3]);”
    Tutaj brakuje nawiasu umożliwiającego zsumowanie części tablicy.

    Przy okazji dlaczego po zsumowaniu pomiary[0] + pomiary[3] + pomiary[7] wynika zamiast 8.9 wychodzi 8.8999999999?

Leave a Reply