2009-04-07 5 views
6

Jeśli masz instancję Collection, powiedzieć coś w stylu:Co przekazać do metody instancji tablic do metody aArray (T [] a)?

Collection<String> addresses = new ArrayList<String>(); 

które miały być następnie wypełniona pęczek wartości, która jest „najlepszy” sposób, jeśli w ogóle, aby korzystanie z metoda toArray() bez konieczności rzutowania typu?

Czy istnieje różnica semantyczna między pierwszymi dwoma? Czy trzeci jest najbardziej wydajny? Czy czwarty jest mniej wydajny niż trzeci?

Odpowiedz

7

Według a findbugs report, jest to najbardziej efektywny:

String[] addressesArray = addresses.toArray(new String[addresses.size()]); 

Wierzę, że;)

+2

Jest to niepoprawne, zgodnie z artykułem @AlekseyShipilev http://shipilev.net/blog/2016/arrays-wisdom-ancients/ –

0

Jest to udokumentowane w javadoc interfejsu List:

Jeżeli lista mieści się w określonej tablicy z pomieszczenia do części (czyli macierz zawiera wiele elementów, niż na liście), przy czym element macierzy natychmiast po zakończeniu listy jest ustawiona na null. (Jest to przydatne w określaniu długości listy tylko wtedy, gdy rozmówca wie, że lista nie zawiera żadnych elementów null.)

+0

Ma to sens, jeśli rozmiar tablicy ArrayList wynosi 5, a przechodzisz do Array() nowej tablicy String o rozmiarze 10, to zostanie ona zmieniona, ale nadal nie wiem, która z nich jest bardziej lub mniej prawidłowa/wydajna . –

+0

Nie zmienia rozmiaru tablicy, po prostu ustawia element poza końcem listy na wartość null. –

0

Robisz skutecznie to samo z dwoma pierwszymi wypowiedziami.

Trzeci jest najbardziej wydajny, ponieważ jeśli twoje elementy nie zmieszczą się w tablicy, zostanie utworzona nowa tablica.

3

Jeśli zdecydujesz się nie wierzyć innym lub po prostu chcesz sprawdzić samemu, możesz przejrzeć source for java.util.ArrayList (opublikowanie źródła prawdopodobnie narusza niektóre licencje, cieszę się, że po prostu linkuję do niego). Otrzymasz także kopię całego kodu źródłowego po pobraniu Sun's JDK).

Po zapoznaniu się z kodu źródłowego <T> T[] toArray(T[] a); oczywiste jest, że:

String[] addressesArray = addresses.toArray(new String[addresses.size()]); 

jest najszybszym sposobem, aby to zrobić.

Oczywiście nie zawsze można poświęcić czas na przeczytanie i zrozumienie kodu źródłowego, a czasami najlepsza opcja nie zawsze jest oczywista, ale w przypadku prostszych metod może być bardzo pouczające, aby przeczytać źródło.

5

Za moje pieniądze

String[] addressesArray = addresses.toArray(new String[0]); 

jest najprostszy, najmniej podatne na błędy i dlatego "najlepszy". Ma także tę zaletę, że ten sam kod działa dla kolekcji współbieżnych/synchronizowanych. Musiałbyś znaleźć się w naprawdę niskim poziomie, mocno używanym kodzie dla niewielkiej różnicy w wydajności, aby zrobić jakąkolwiek różnicę.

Często pojawia się pusta tablica przypisana do static final, aby uniknąć przypisania przy każdym wykonaniu. Najwyraźniej okazuje się, że wydajność może spaść z powodu tej "optymalizacji" (alokacja jest naprawdę bardzo szybka).

Aktualizacja: Okazało się, że jest to szybsze niż użycie tablicy o rozmiarze.http://shipilev.net/blog/2016/arrays-wisdom-ancients/tl; dr: Odbicie jest trywialnego rodzaju, nie obejmującego powolnego wyszukiwania metod, a zerowanie tablicy można pominąć, jeśli można stwierdzić, że wszystkie elementy zostaną zapisane (lub tablica stanie się nieosiągalna).

+2

+1 za zauważenie problemu z współbieżnością. Napotkałem ten problem w moim kodzie: http://github.com/orfjackal/dimdwarf/blob/0d1a0897821a4e0e557a1390a7252a8580d2ec95/dimdwarf-core/src/main/java/net/orfjackal/dimdwarf/scheduler/TaskThreadPool.java#L111 -116 –

+0

Zazwyczaj używam podejścia "addresses.toArray (new String [addresses.size()])". –

+1

Jest to zarówno prostsze, jak i szybsze! http://shipilev.net/blog/2016/arrays-wisdom-ancients/ –

1

To jest ciekawe głównie teoretyczne, ale jeśli lista jest pusta często można ponownie użyć tablicę o zerowej długości:

private static final String[] EMPTY_STRING_ARRAY = {}; 
... 
String[] addressesArray = addresses.toArray(EMPTY_STRING_ARRAY); 

Ponieważ tablice zerowej długości są niezmienne (w przeciwieństwie do tablic niezerowej długości), są one w porządku do przechowywania i ponownego użycia.

+0

Zobacz odpowiedź Toma Hawtina. –

Powiązane problemy