Większość zadań w mojej szkole na początkowych zajęciach z programowania wymagała ode mnie używania tablic. Pracuję teraz na pełny etat i nigdy nie użyłem tablicy dla żadnego projektu, nad którym pracowałem. Nawet w istniejących projektach nigdzie nie widziałem zastosowania tablic. Moim zdaniem Lista jest łatwiejsza w użyciu i jest standardem. Dlaczego profesorowie mówią uczniom, aby używali tablic w swoich zadaniach? Czy to po to, aby uczniowie rozumieli podstawy?
Ponieważ większość uniwersytetów uczy języka Java, pytanie to dotyczy języka Java.
java
programming-languages
programming-practices
Wycie Hagrid
źródło
źródło
Odpowiedzi:
Ponieważ tablice uczą takich pojęć, jak indeksowanie i granice, dwa fundamentalnie ważne pojęcia w programowaniu komputerowym.
Listy nie są „standardem”. Istnieje wiele różnych miejsc problemowych, do których idealnie pasują tablice.
źródło
Prawdopodobnie chcieli zacząć od struktury danych, która najdokładniej odzwierciedla sposób działania komputera, więc znasz podstawy, zanim zaczną wprowadzać abstrakcje wyższego poziomu, takie jak Listy, które ułatwiają pracę. W przeciwnym razie nie byłbyś w stanie zrozumieć, dlaczego określona struktura lub algorytm działa wolno / szybko dla niektórych operacji, a nie dla innych; gdyby pamięć komputera faktycznie została utworzona z połączonych list, świat byłby zupełnie innym miejscem.
Z tego samego powodu, moja pierwsza klasa programowania w college'u była w C, a reszta zajęć była w C ++, Java i innych językach. Nie chodzi o to, że C jest w jakiś sposób lepszy lub łatwiejszy, to o to, że C (i Array) niczego przed tobą nie ukrywa.
źródło
Powyższe odpowiedzi są świetne, ale mam na myśli inną.
main()
Metoda Java oznacza, że uczniowie spotykają się z podstawowymi tablicami bardzo wcześnie, często już pierwszego dnia zajęć. Czemu?To pierwsza rzecz, z którą będziesz musiał się zmierzyć, aby napisać Hello World i nie tylko. (Widziałem, że niektóre kursy używają na początku nauczania IDE, takich jak BlueJ, które pozwalają na wskazywanie i klikanie w celu uruchomienia dowolnych metod, ale odłożymy je na bok ...) Chociaż może być wskazane, aby przeforsować niektóre z nich te słowa kluczowe przez jakiś czas, wcześniej czy później większość nauczycieli będzie chciała je wyjaśnić. Rzeczywiście, klasycznym pytaniem testowym dla początkujących jest poproszenie uczniów o podanie znaczenia każdego słowa kluczowego w podstawowym programie Hello World. A co znajdujemy jako część naszej głównej sygnatury metody? Tablica (Przyczyna tego jest częściowo historyczna. ArrayList nie istniał w Javie 1.0). Tablice są częścią tego podstawowego zestawu wiedzy. Lista nie jest.
To powiedziawszy, nie jest niczym niezwykłym, że klasy wprowadzają ArrayList nieco później w kursie, szczególnie po omówieniu obiektów i ich użycia. Nawet program nauczania informatyki AP dla Java zawiera ArrayList (wiem, że kiedyś to robił, a Google wydaje się wskazywać, że nadal tak robi), chociaż ignoruje fakt, że ArrayList implementuje List i resztę Frameworkm kolekcjonowania.
Wreszcie, z mojego doświadczenia wynika, że uniwersyteckie programy CS używają Javy jako środka do eksploracji CS i koncepcji programistycznych, zamiast uczyć studentów, jak zostać dobrymi programistami Java. Niektóre programy mogą bardziej koncentrować się na rezygnacji z profesjonalnych programistów, podczas gdy inne koncentrują się bardziej na teorii, ale w obu przypadkach jest wiele do nauczenia się, jak używać Javy w prawdziwej pracy zawodowej, której nie uczy się w większości programów nauczania na studiach. Obejmuje to zarówno wzorce projektowe i techniki, takie jak w Effective Java , jak i frameworki, takie jak Spring, Hibernate lub JUnit, a nawet bardziej popularne rzeczy, takie jak JSP lub JDBC. Mając na uwadze tę filozofię, podkreślanie tablic w stosunku do częściej używanych ArrayList ma nieco więcej sensu.
źródło
Jednym z powodów, dla których klasy programowania pierwszego roku używają tablic, jest spuścizna: tak właśnie profesorowie nauczyli się tego, zanim zaczęliśmy używać standardowych bibliotek z dynamicznymi listami wypalonymi. Używanie prymitywnych typów danych ma również bardziej ogólne zastosowanie: tablice istnieją na prawie każdym komputerze język pod słońcem (i może być zaimplementowany w kilku instrukcjach montażu). Kiedy uczyłem się programowania, jednym z zadań było wdrożenie listy połączonej.
O wiele łatwiej jest zacząć od podstawowych zasad, a następnie powiedzieć „To jest podstawowa struktura. Ten język (lub jego biblioteki) zapewnia tę strukturę danych wysokiego poziomu, która robi wszystko, ale daje ci x, y i z” niż to znaczy „Więc to te struktury danych wysokiego poziomu, oto co jest pod maską”. Uczenie się, jak korzystać z LinkedList vs. ArrayList (lub HashSet vs. TreeSet) jest zwykle drugim lub trzecim rokiem kursu algorytmów. Listy i mapy mają te same interfejsy i dają te same wyniki, ale mogą mieć radykalnie różne zachowania w aplikacji dowolnej wielkości. Po wyjściu z programowania 101 nie ma gwarancji, że programowanie 102 będzie używać tego samego języka. Jeśli zaczniesz od koncepcji tablicy, możesz po prostu powiedzieć „
Innym powodem, dla którego preferuje się „tablicę” nad „listą” w kursie wprowadzającym jest to, że tablice są zasadniczo łatwe do zrozumienia: tablica 20
bytes
zajmuje 20 bajtów (plus kilka, aby wskazać koniec tablicy lub długość, w zależności od implementacji ).„Lista” jest zupełnie innym kotłem rybnym i może być zaimplementowana na wiele różnych sposobów (ArrayList, LinkedList i pewnie kilka, o których zapomniałem), z zasadniczo różnymi cechami wydajności. Bez zrozumienia wnętrzności co różne zajęcia Lista robią, nie można mieć znaczący dyskusję kiedy należy użyć
List foo = new ArrayList()
kontraList foo = new LinkedList()
. Jeśli spróbujesz zmusić ucznia do użycia implementacji listy, ktoś zapyta, dlaczego używasz ArrayList zamiast jednej z innych implementacji. A „ArrayList” zawiera słowo „Array” i jest przez nie poparte, więc tak naprawdę nie jest to ogromny skok logiczny z „tablicy” do „ArrayList”.Wbrew powszechnemu przekonaniu, istnieją sytuacje, w których sensowne jest używanie tablic nad listami, szczególnie gdy mamy do czynienia z listą wielkości statycznej. Oto kilka:
foo[n]
dereferencje i niektóre zakulisowe operacje arytmetyczne na wskaźnikach, podczas gdyfoo.get(n)
trzeba je wyrejestrować, wykonać wywołanie metody, zrobić drugie dereferencje, a następnie może zrobić arytmetykę wskaźnika (jeśli używasz ArrayList; LinkedLists potencjalnie potrzebuje iteracji po każdym elemencie listy).int[] foo = new int[]{1, 2, 3, 4, 5}
porównaniu z sugestiami zawartymi w kolejnym pytaniu StackOverflowźródło
perm
jest toint[256]
permutacja, można ją łatwo odwrócić za pomocą tablicy:int[] inv = new int[256]; for (int i=0; i<256; i++) inv[perm[i]]=i;
nie sądzę, aby cokolwiek, co można napisać za pomocą,ArrayList<>
byłoby tak czyste.ArrayList
mógł łatwo otrzymać konstruktor, który tworzy domyślnie inicjowaną listę o określonym rozmiarze.get
iset
nie daj się inlined.get
iset
może być wbudowany , coś takiegomyList.set(23,myList.get(23)+1)
nie będzie tak wydajne jakmyArray[23]+=1
. Co więcej, nawet dla typów, które nie wymagałyby boksu, byłbym bardzo zaskoczony, gdyby każdy JITter mógł cokolwiek równoważnego dofor (i=0; i<1000; i++) myList2.set(i+2000,myList2.get(i+3000));
czegoś, co jest blisko gdziekolwiek blisko.System.arrayCopy(myArray1,3000,myArray2,2000,1000);
Nie ma powodu, aby dynamiczny typ tablicy frameworka nie oferował szybkiego działania w zakresie kopiowania, ale Java nie.Java umożliwia przechowywanie zmiennych dowolnego typu w tablicach. Natomiast
ArrayList
pozwala tylko na przechowywanie referencji. Nie można zatem pożytecznie dyskutowaćArrayList
bez uprzedniego omówienia , w jaki sposób auto-boxowanie przekształci prymitywy w typy referencyjne, i jak auto-rozpakowanie czasami przekształci typy referencyjne w prymitywy:Gdyby kod używał
int[3]
raczej niż anArrayList
, nie byłoby niespodzianek. Wszystkie trzy elementy byłybyi
do siebie równe . UżywającArrayList
jednak, mimo że wszystkie trzy elementy listy zawsze będą się porównywać równei
, a pierwszy i trzeci zawsze będą porównywać się równe, pierwsze dwa elementy będą sobie równe tylko, gdyi
wynosi 1, 10 lub 100, ale (w większości implementacji) nie wtedy, gdyi
wynosi 1000 lub 10000.źródło
Integer
Klasa zagnieżdżona o nazwie klasa,IntegerCache
która przechowuje wstępnie zainicjowaneInteger
obiekty dla zakresu wartości, które zwykle rozciągają się na -128..127; boksowanie wartości spoza tego zakresu będzie wymagało utworzenia nowego obiektu, ale boksowanie wartości w zbuforowanym zakresie zwróci po prostu odwołanie do jednego z wstępnie zainicjowanych obiektów przechowywanych wIntegerCache.cache
. Każdy dobry programista Java musi być świadomy, żeInteger
zmienne dwóch typów enkapsulujące tę samą wartość mogą, ale nie muszą się równać, ale zbyt wczesne wprowadzenie tego pomysłu może spowodować, że studenci uciekną z przerażenia.==
. Biorąc pod uwagę możliwość, że automatyczne rozpakowywanie może rzucić, byłbym skłonny całkowicie to zabronić, ale jego zachowanie==
jest szczególnie okropne.==
Operator zachowuje się też źle w takich przypadkach16777217==16777216f
[Raporty true], a konwersje niejawne dlalong v=Math.Round(123456789), w=Math.Round(123456789012345)
są w stanie być nieoczekiwany [można się domyślać, co te wyrażenia przyniesie?]IntegerCache
, z pewnością są chwile, kiedy może to pomóc w wydajności, ale często może powodować, że kod, który jest po prostu zły, nie działa. W pewnym sensie chciałbym, aby istniał tryb, w którym boks quasi-losowo zwraca obiekty z dwóch liczb całkowitych pamięci podręcznej i quasi-losowo zamienia elementy pamięci podręcznej na nowe, tak aby kod polegający na zachowaniu boksu wartości -128..127 byłby bardzo mało prawdopodobne, aby odniosło sukces bardzo długo.Myślę, że sensowne jest nauczenie, jak najpierw korzystać z tablic, ponieważ
ArrayList
wewnętrznie korzysta z tablicy.ArrayList
Klasa ma zmienną składową o nazwieelementData
, która jestObject
tablicą.Z
ArrayList
kodu źródłowego JDK :Kiedy dodajesz, aktualizujesz, pobierasz lub usuwasz elementy z
ArrayList
, używa tej wewnętrznej tablicy do wykonywania tych operacji. Jak zauważył już użytkownik Ixrec -ArrayList
to tylko abstrakcja wyższego poziomu, z którą zwykle łatwiej jest pracować.źródło
Java
- Zadawało pytanie, dlaczego uczyć tablic, kiedy zwykle można ich używaćArrayList
. Java nie ma wskaźników. Dobrze czy źle, uważam, że C / C ++ jest lepszym językiem dla początkujących niż Java. Wiele tematów programowania można lepiej zrozumieć dzięki znajomości C / C ++.Zakładając, że lista jest rzeczywiście łatwiejsza do pracy, jak mówisz - to naprawdę nie ma znaczenia. Uczenie się dotyczy bardziej „podstawowego do złożonego” niż „łatwego do trudnego”. Gdyby podstawy nie były ważne, informatyka nie byłaby dziedziną akademicką. Możesz po prostu nauczyć się, jak klikać razem aplikacje przy użyciu istniejących platform / bibliotek z samouczków online. (Oczywiście, ktoś musi napisać te biblioteki ... i ktoś musi
ArrayList
przede wszystkim zaimplementować ...)źródło
ArrayList
można lepiej korzystać, używając osobnej tablicy i licznika „liveItems”, z wyjątkiem tego, że nie ma wygodnego sposobu pracy z tablicą i liczenia razem, z wyjątkiem ich agregacji.Jest tak, ponieważ najważniejszą rzeczą w edukacji akademickiej jest nauczenie cię używania właściwej terminologii do opisywania swoich działań.
Lista jest czymś innym niż tablica. i Nie możesz używać
java.util.List
w Javie, ponieważ jest to interfejs. Zazwyczaj używasz tego,java.util.ArrayList
który jest implementacją listy, nie jest listą, ale jest opakowaniem obiektu wokół dynamicznej tablicy. Mówisz więc, że używasz „Listy”, ale używasz tablicy.Bardzo rozsądnym jest ominąć chaos terminologiczny i po prostu użyć tablic, aby nauczyć uczniów, czym jest tablica. Jeśli używasz tablic w Javie, przynajmniej używasz tablic.
Szczerze mówiąc, jest to również argument, dlaczego nauczanie programowania w Javie nie jest dobrym pomysłem. Trudno jest poprawnie nauczyć się podstawowych pojęć programowania.
źródło
Dosłownie nigdy nie widziałeś ani nie używałeś żadnych tablic? Używamy ich cały czas, oprócz list. Zwykle nie używamy Javy, ale używamy wielu innych języków, które wykazują oczywiste podobieństwa.
Pomiędzy tablicami i listami jeden jest lżejszy, a dodatkowo bardziej konkretny, podczas gdy drugi ma większą funkcjonalność. Zasadniczo w programowaniu, gdy istnieją dwa podobne typy, które są zasadniczo podzielone wzdłuż tych linii, powinieneś wybrać lekką, chyba że naprawdę potrzebujesz bardziej wymyślnego. Oprócz zmniejszenia narzutu, pomaga to utrzymać porządek i stan programu, a zwłaszcza jego kodu . Jeśli coś pójdzie nie tak podczas testowania, masz mniej miejsc do patrzenia; a co ważniejsze, w przypadku tablic vs. list, ludzie mają lepsze pojęcie o ograniczonym zakresie tego, do czego faktycznie go używasz i próbują z tym zrobić.
I tak, z akademickiego punktu widzenia istnieje dodatkowy powód, aby uczyć studentów podstaw. Jednak idzie to nieco głębiej. Tablice i listy są dobrym przykładem typów nieporęcznych, często budowanych na wierzchu, a często po prostu owijających, leżące u podstaw wystąpienia mniejszych typów. Nawet jeśli Listy nie mają podstawowych tablic, zachowują się na zewnątrz tak, jak mają. Częścią uczenia kogoś, czym jest lista, byłoby nauczenie jej, czym jest tablica.
Widziałem, jak to wymyka się spod kontroli w języku takim jak C ++, w którym tablice w zasadzie nie mogą być bardziej rozbierane niż są w rzeczywistości, ale w językach wyższego poziomu prawie same są listami. Jeśli idealnie pasują do twoich potrzeb w danej sytuacji, dlaczego miałbyś chcieć użyć czegoś innego?
źródło
T[]
będzie gotowy, zaraz po przejściu przez bramę, do przyjmowania przedmiotów w dowolnej kolejności, natomiastArrayList<T>
wymaga dodania przedmiotów w kolejności, zanim będą mogły zostać zmodyfikowane. AT[]
może skopiować dowolny zakres przedmiotów do podobnego rozmiaru innego innegoT[]
stosunkowo szybko, podczas gdyArrayList<T>
wymagałoby to odczytania pojedynczych elementów z jednej listy i przechowywania ich na drugiej - znacznie wolniej i mniej wygodnie.