2010-11-15 15 views
9

Jestem nowicjuszem z Javą.Java - najlepszy sposób na wdrożenie dynamicznej tablicy rozmiarów obiektów

Muszę zaimplementować tablicę obiektów, które zmieniają rozmiar podczas wykonywania.

Kod, który piszę, będzie również przeniesiony na Androida.

Według twoich doświadczeń, jaka jest najlepsza klasa, aby to zaimplementować?

Dzięki,
Dan

+2

Trudno jest odpowiedzieć bez znajomości wymagań. Spójrz na http://download.oracle.com/javase/tutorial/collections/index.html i sprawdź, który z nich pasuje do rachunku. –

+0

Dlaczego nie używać tych w API, na przykład ArrayList? – dacwe

Odpowiedz

21

Java ma niewystarczającą możliwość szablonu. Tak długo, jak chcesz szereg obiektów, wtedy ArrayList<T> jest dobry. Dla prymitywów to okropne.

Zakładając, że hierarchia obiektów, które chcesz umieścić na liście, ArrayList jest idealna:

ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>(); 

vehicles.add(new Car(...)); 
vehicles.add(new Truck(...)); 

Jestem zakładając w powyższym przykładzie, że pojazd jest klasą bazową, a Car and Truck są podklasami.

Z drugiej strony, jeśli chcesz mieć listę liczb, Java jest wysoce nieefektywna. Każdy obiekt jest odwołaniem (tak naprawdę 4-bajtowym wskaźnikiem) do 12-bajtowego fragmentu pamięci, a także tego, czego faktycznie używasz. Ponieważ ArrayList nie może mieć zastosowania do int, oznacza to, że utworzenie listy numerów oznacza:

  1. Tworzenie listy Integer, wrapper obiektu dla int.
  2. Konwertowanie obiektów przy każdym wyciągnięciu numeru. Odbywa się to automatycznie w dzisiejszych czasach, ale wymaga czasu.
  3. Inicjowanie 5 razy więcej miejsca w razie potrzeby.

Tak więc, jeśli manipulujesz dużymi porcjami prymitywnych danych (int, float, double), możesz być warta napisania własnej wersji ArrayList. Jest to szczególnie ważne, gdy dane są duże, a platforma jest niewielka (jak na przykład poręczny Android).

Porównaj to:

ArrayList<Integer> list = new ArrayList<Integer>(); 
for (int i = 0; i < 1000000; i++) 
    list.add(i): 

do:

public class IntArray { 
private int[] data; 
private int used; 
private void grow() { 
// implement code to make data double in size here... 
} 
public IntArray(int size) { 
    data = new int[size]; 
    used = 0; 
} 

public void add(int i) { 
    if (i >= data.length) grow(); 
    data[used++] = i; 
} 
} 

IntArray list2 = new IntArray(1000000); 
for (int i = 0; i < 1000000; i++) 
    list2.add(i); 

Ostatni raz odwzorować go, optymalne wykorzystanie pierwotnej liście jest ponad 10 razy szybciej niż wprawdzie niewystarczające wykorzystanie ArrayList . Aby być bardziej sprawiedliwym, wstępnie przydziel listę tablicową do odpowiedniego rozmiaru - nadal jest wolniej.

Funkcja LinkedList jest warta zachodu tylko wtedy, gdy wstawiasz ją na początku lub na środku listy. Jeśli twoja lista jest budowana przez dodanie do końca, ArrayList całkowicie zdominuje LinkedList. Tak więc dla typowej listy obiektów, które budujesz w kolejności, ArrayList jest tym, czego szukasz. Dla dużej listy prymitywów, takich jak int lub double, napisz własną listę.

+0

Podczas gdy użycie 'LinkedList' jest najlepsze w porównaniu do' ArrayList', istnieją i 'LinkedList' może w nich znacznie lepiej. Kolejne użycie listy jest jednym z przykładów ... usunięcie z przodu 'ArrayList' jest niezwykle kosztowne w porównaniu do' LinkedList'. Zobacz [to] (http://blog.publicobject.com/2010/07/caliper-confirms-reality-linkedlist-vs.html) i [this] (http://microbenchmarks.appspot.com/run/[email protected] gmail.com/com.publicobject.blog.ListAsQueueBenchmark). – ColinD

+0

@Colin, używanie naiwnie ArrayList zamiast listy LinkedList może naprawdę być złe. Ale jeśli chcesz szybszej kolejki, to założę się, że implementacja okrągłej kolejki z określoną głową/ogonem pokona linkList przez ogromny margines - nawet jeśli możesz sprawić, by rosła, gdy/jeśli zajdzie potrzeba, średnia wielkość będzie po prostu umieszczać obiekty na już istniejącej liście. Tak, wstawianie na początku tablicy ArrayList jest kosztowne. – Dov

2

powinien znać swoją jaźń z collection framework w java Ty. Masz takie rzeczy jak Set, List, Map, SortedSets, etc ... Które mogą być naprawdę pomocne struktury danych.

0

To zależy od tego, do czego go użyjesz.

Jeśli masz tablicę, która zmienia rozmiar często, to polecam stosując ArrayList lub coś innego z collection framework (w zależności od tego, co masz zamiar używać go do).

Jeśli jednak mieć tablicę, która zmienia rozmiar bardzo rzadko, ale jest często czytać, będzie to prawdopodobnie szybciej użyć zwykłej tablicy, a następnie zmienić jego rozmiar, gdy są potrzebne, zamiast

Arrays.copyOf(array, newSize); 

nadzieję, że to pomaga! :)

+0

Podczas gdy prymitywne tablice są czasami najlepsze, nie ma właściwie żadnego powodu, aby używać tablicy obiektów w Javie. "prawdopodobnie byłoby to szybsze" ... przedwczesna optymalizacja. – ColinD

+0

Używanie klasy pierwotnej różni się od pisania za pomocą ustalonych tablic. Zbyt wiele uwagi poświęca się unikaniu "przedwczesnej optymalizacji", a nie tylko wiedzy o tym, co jest skuteczne, i robieniu tego w sposób oczywisty. Łatwo jest napisać dobry kod w większości przypadków jako zły kod. Czasami wymaga to trochę więcej pracy i wtedy możesz myśleć o zrobieniu tego później. – Dov

+0

@Dov: Z pewnością zgadzam się, że jeśli chodzi o robienie czegoś wyraźnie gorszego niż robienie czegoś, co jest poprawne i prawdopodobnie osiągniemy lepsze wyniki przy tym samym wysiłku, to nie jest to przedwczesna optymalizacja, aby zrobić to, co właściwe. Ale tablice są gorsze od List na wiele sposobów, a ich bezpośrednie użycie prawie na pewno spowoduje więcej pracy, aby zrobić proste rzeczy i sprawić, że kod będzie trudniejszy do zrozumienia, i prawdopodobnie nie przejmie żadnej poprawy wydajności, która ma znaczenie dla wszystkich, ale dla tych najmniejszych. -poziom kodu. Dlatego rozważę tę przedwczesną optymalizację. – ColinD

Powiązane problemy