Artykuł logo
Pierwszy program w Java
8 listopada 2015
pętle i instrukcje warunkowe
Pętle i instrukcje warunkowe w języku Java
18 listopada 2015
Artykuł - tablice

Dzisiaj dowiesz się czegoś więcej o tablicach w języku Java. Przeczytasz czym są „Magic Numbers” i dlaczego są złe. Poznasz też metody o zmiennej liczbie argumentów. Na koniec czeka na Ciebie zestaw zadań do wykonania wraz z przykładowymi rozwiązaniami.

To jest jeden z artykułów w ramach darmowego kursu programowania w Javie. Proszę zapoznaj się z pozostałymi częściami, mogą one być pomocne w zrozumieniu materiału z tego artykułu.

Czym jest tablica

Tydzień ma siedem dni. Załóżmy, że pierwszy dzień tygodnia to poniedziałek. Wtorek jest drugi, środa jest następna itd. Dni możemy ułożyć w swego rodzaju ponumerowany szereg.

Tablica jednowymiarowa to nic innego jak właśnie taki ponumerowany szereg. W Javie elementy w tablicy numerujemy od 0. Więc w naszym przypadku poniedziałek ma numer 0, wtorek 1 itd. Numer identyfikujący każdy element tablicy to indeks.

Tablice grupują obiekty tego samego typu1. Mogą to być łańcuchy znaków, liczby, wartości logiczne, instancje klas stworzonych przez Ciebie itd.

Tworzenie tablicy

Przekładając nasz przykład z dniami tygodnia na Javę dojdziemy do takiego fragmentu kodu

W pierwszej linijce tworzymy nową tablicę obiektów typu String. Tablica może pomieścić 7 elementów. Poniedziałek ma indeks 0, niedziela ma indeks 6.

Raz przypisany obiekt w tablicy możemy nadpisać.

Teraz pod indeksem 0 znajduje się Monday, pod 1 bez zmian nadal jest wtorek.

Jeśli spróbujesz odwołać się do nieistniejącego elementu w tablicy zostanie rzucony wyjątek java.lang.ArrayIndexOutOfBoundsException. O wyjątkach przeczytasz w jednym z kolejnych artykułów. Aktualnie wystarczy Ci informacja, że wyjątki sygnalizują sytuacje wyjątkowe 🙂 i mogą przerwać działanie programu. Poniższa linijka zakończy program wyjątkiem, odwołujemy się tam do ósmego, nieistniejącego elementu tablicy.

Tablicę można też od razu zainicjalizować wartościami. Oba sposoby inicjalizacji tworzą obiekt tablicy. Zauważ, że w drugim przypadku nie musimy podawać jej długości. Jest ona znana na podstawie przekazanych wartości.

Atrybut length

Tablica to obiekt. Podobnie jak inne obiekty posiada swoje atrybuty i metody. Jedynym publicznie dostępnym atrybutem metody jest length. Atrybut ten przechowuje rozmiar tablicy

Tablice wielowymiarowe

Wyżej napisałem, ze w tablicy możesz trzymać dowolny obiekt. Tablica też jest obiektem 🙂 Więc nic nie stoi na przeszkodzie, żeby w tablicach umieścić inne tablice. Tablica dwuwymiarowa to nic innego jak tabela zawierająca wiersze i kolumny w której możesz przechowywać dane.

Nic nie stoi na przeszkodzie do tworzenia tablic, które mają więcej niż 2 wymiary, jednak w praktyce raczej ich się nie spotyka. Jeśli potrzebna jest tak skomplikowana tablica programiści zazwyczaj przechowują dane w inny sposób używając zbiorów, map czy list 2.

W naszym przykładzie tablicy dwuwymiarowej użyjemy do przechowywania stanu gry kółko krzyżyk

W pierwszy wierszu inicjalizujemy wyłącznie jeden z wymiarów. Musimy tam podać tylko liczbę wierszy, które będzie przechowywała nasza tablica dwuwymiarowa. Kolejne 3 linie kodu to inicjalizacja wierszy tablicy.

Jeśli każdy z wierszy tablicy wielowymiarowej ma dokładnie taki sam rozmiar możemy zainicjalizować ją w jednej linijce. Poniższy przykład ma ten sam efekt jak poprzedni:

ticTacToeBoard[0] odwołuje się do pierwszego wiersza w tablicy. ticTacToeBoard[0][0] odwołuje się do pierwszej komórki w pierwszym wierszu. W ten sposób każde pole na naszej planszy ma unikalny indeks składający się z dwóch liczb:

00 01 02
10 11 12
20 21 22

Podobnie jak w przypadku tablicy jednowymiarowej i tu możemy przypisywać wartości. Poniżej przykładowy przebieg gry.

Spróbuj narysować sobie na kartce powyższy przebieg gry. Kto ma szanse na wygraną? 🙂

Magiczne liczby

Przykład z planszą do gry świetnie nadaje się do wytłumaczenia czym właściwie są magiczne liczby (ang. magic numbers). W kodzie programu bardzo często występują liczby. Liczby te w rzeczywistości mają jakieś znaczenie. W naszym przykładzie 1 to nie zwykła jedynka a wartość oznaczająca kółko. Dobrą praktyką jest przypisanie takich „magicznych wartości” do zmiennych/stałych 3 i używanie ich w kodzie. Na dłuższą metę kod używający nazwanych zmiennych w miejscu „magic numbers” jest bardziej czytelny i łatwiejszy w utrzymaniu.

Poza czytelnością zyskujemy kolejną rzecz. Nie łamiemy zasady DRY (ang. Dont Repeat Yourself)4.

Metody o zmiennej liczbie argumentów

Znasz już metodę main, domyślnie przyjmuje ona tablicę łańcuchów znaków. Równie dobrze metodę tą możemy zapisać jako

Inny przykład metody z wieloma argumentami to metoda sumująca wszystkie przekazane liczby:

Magiczny wielokropek to nic innego jak uproszczenie składni (ang. syntactic sugar). Nasza metoda z przykładu może przyjąć dowolną liczbę argumentów. W szczególności może też nie przyjąć żadnego.

Metody mogą przyjmować wiele argumentów. Jednak argument z wielokropkiem może być tylko jeden i musi występować jako ostatni.

Jak wspomniałem wielokropek to nic innego jak uproszczenie składni. W rzeczywistości metody są tożsame

Zadania

  1. Napisz metodę pobierającą dwuelementową tablicę liczb i zwracający ich sumę.
  2. Napisz program pobierający trójelementową tablicę liczb i zwracający największą liczbę.
  3. Jak przechowałbyś stan sudoku? Napisz program, który stworzy instancje tablicy służących do przechowywania sudoku i uzupełnij ją przykładową planszą.
  4. Jak przechowałbyś stan gry w szachy? Napisz program, który stworzy instancje tablic służące do przechowywania stanu gry w szachy. Potrafiłbyś zachować w nim ostatni stan partii Kasparowa z Deegtp Blue?

Zachęcam Cię, do samodzielnego rozwiązania zadań, jeśli jednak miałbyś jakikolwiek problem możesz rzucić okiem na przykładowe rozwiązania. Pamiętaj, że rozwiązując zadania samodzielnie nauczysz się najwięcej.

Podsumowanie

Bardzo się cieszę, że przeczytałeś artykuł aż do końca. Jeśli masz jakiekolwiek uwagi proszę podziel się nimi w komentarzach. Byłbym także bardzo wdzięczny gdybyś przekazał swoim znajomym informację o blogu – jak zawsze zależy mi na dotarciu do jak największej grupy ludzi, którzy chcą uczyć się programować.

Jak zwykle informacje o artykule prezentuję na stronie na facebooku, polub ją a będziesz otrzymywał informacje o nowych artykułach.

[FM_form id=”3″]

  1. Znów uproszczenie, jak poznamy dziedziczenie dowiesz się trochę więcej na ten temat.
  2. Są to 3 podstawowe typy kolekcji w języku Java. Przeczytasz o nich w jednym z kolejnych artykułów.
  3. O stałych przeczytasz w innym artykule
  4. W uproszczeniu zasada mówi o nie powtarzaniu tego samego kodu wielokrotnie, przeczytasz o tym w jednym z kolejnych artykułów. Poprę to lepszym przykładem niż ten w tym artykule.
  • lukasz

    To co w książkach jest napisane jak encyklopedia tu jest napisane zwięźle i praktycznie

    • Marcin Pietraszek

      Bardzo miło mi to słyszeć 😉 Jak zwykle, jeśli jest jeszcze temat, o którym chciałbyś przeczytać proszę daj znać.

  • lu

    Czy z metody przyjmującej dwa arg można zwrócić dwa argumenty?

    • Marcin Pietraszek

      A próbowałeś taką metodę napisać? Co na to kompilator? Dla przypomnienia materiału zachęcam do przeczytania artykułu o metodach.

      • luk

        Zadanie 1 – niby proste a jednak nie moge dojść dlaczego nie zwraca tego co chce czyli prawidlowej sumy:

        • Marcin Pietraszek

          Nie dam Ci odpowiedzi na tacy. Przyjrzyj się ostatnim linijką metody main.

  • Luk

    Racja. Trzeba zastosować metode zwracajaca tablicę

  • luk

    Eh wszystko jasne:

  • Łukasz

    Cześć. Poprawilbyś mój kod po swojemu tak aby to profesjonalnie wyglądało? I czy może jest inna metoda to rozwiązać np krótsza.

    • Marcin Pietraszek

      Programiści mają to do siebie, że zawsze wykorzystają 110% czasu, który mają na wykonanie zadania. Kod zawsze można zmienić, o refaktoryzacji jeszcze napiszę 😉

      Co do edycji kodu – możesz to zrobić sam otaczając kod znacznikami <pre>kod tutaj</pre>

      • Szymon

        Nie można tego zrobić po prostu tak. Po co tworzyć osobną klasę to dodania liczb z tabeli

        • Marcin Pietraszek

          Oczywiście, że można :). W przypadku takich „ćwiczeń dla początkujących” robienie osobnych klas często nie jest potrzebne. Robi się je raczej do „przećwiczenia” pewnych konstrukcji.

  • mg

    pytanie mam takie: czy przy deklaracji tablicy int dwuwymiarowej trzeba to robić tak jak jest zrobione w przykładzie:

    czy nie można tego zrobić w jednej linii:

    dlaczego rozmiary poszczególnych wierszy (kolumn) są deklarowane kolejnymi wpisami choć wszystkie są takie same?
    no bo gdyby wartość drugiego wymiaru była różna dla każdej wartości ticTacToeBoard[n] to jasne. ale skoro są takie same to jaki jest cel tych trzech dodatkowych linii?

    • Marcin Pietraszek

      Słuszna uwaga, oczywiście można to zrobić w jednej linii. Celowo zrobiłem to w ten sposób, ponieważ tablice wielowymiarowe na początku dla mnie nie były „oczywiste”, a pokazanie tego w prosty sposób – to zwykła tablica z zagnieżdżonymi tablicami trochę mi to uprościło. Taki też cel był tutaj, niemniej jednak uzupełnię artykuł o dodatkowy akapit 🙂

  • mg

    fajne są te ćwiczenia na końcu. bo bez ćwiczenia samego programowania to naprawde można czytać i czytać teorię i przykłady i wiele to nie daje.

    • Marcin Pietraszek

      Cieszę się, że Ci się podobają. Za za każdym razem staram się dodać przykładowe zadania do rozwiązania. Dopiero zrobienie czegoś samemu pozwala przekonać się czy rzeczywiście wiemy coś na dany temat 🙂

  • Ahlen

    Nie mogę w zadaniu 1 poradzić sobie z wyświetleniem wyniku jako jednej liczby.
    https://gist.github.com/ahlens/4ce149fc5328d2b058ab1e1b8ba15888
    A po przejrzeniu komentarzy widzę, że inaczej zinterpretowałem zadanie, myśląc, że pobieranie danych to wpisanie przez użytkownika. Niemniej jednak miło jeżeli udzielisz komentarza 🙂

    • Nie dam Ci odpowiedzi, postaram się Cię na nią nakierować. Dlaczego aktualnie wyświetlasz kilka liczb?

      Rozmiar tablicy można ustawić używając zmiennej. Wartość tej zmiennej możesz pobrać od użytkownika.

      • Ahlen

        Znowu rozwiązanie banalne. System out print powinienem umieścić za pętlą… W ten sposób otrzymałem jeden wynik czyli sumę wszystkich liczb. W pętli powtarzało mi sumowanie operacji.