2016-08-10 13 views

Odpowiedz

6

Oto source code dla ciebie za pierwszym przykładzie

public ArrayList() { 
    this(10); 
} 

Więc nie ma żadnej różnicy. Ponieważ początkowa pojemność jest 10, bez względu na to zdać 10 czy nie, to zostanie zainicjowany o pojemności 10.

Mogę dodać 11th elementem listy2 przez list2.add („coś”)?

Oczywiście, początkowa pojemność nie jest ostateczną pojemnością. Kiedy dodajesz więcej niż 10, rozmiar listy ciągle wzrasta.

Jeśli chcesz mieć stałą Pojemnik użyć Array lub java.util.Collections.unmodifiableList()

Warto przeczytać o tej zmianie w Java 8: In Java 8, why is the default capacity of ArrayList now zero?

w skrócie, zapewniając początkową zdolność przyzwyczajenie naprawdę coś zmienić interms wielkości.

+2

Uwaga: kod źródłowy, z którym się łączysz, pochodzi z JDK 6. Nowsze JDK działają zupełnie inaczej - zobacz np. Moja odpowiedź powyżej. – Mureinik

+0

Co się stanie, jeśli size() zostanie wywołany na obu listach? – v0ld3m0rt

+1

10 elementów ma wartość NULL, więc rozmiar wynosi zero. –

4

Zawsze można dodawać elementy do listy. Jednak tablica, która jest używana przez ArrayList, jest inicjowana z domyślnym rozmiarem 10 lub rozmiarem określonym podczas inicjowania tablicy ArrayList. Oznacza to, że jeśli np. dodaj 11 element, rozmiar tablicy musi zostać zwiększony, co jest wykonywane przez skopiowanie zawartości tablicy do nowej, większej instancji tablicy. To oczywiście wymaga czasu w zależności od wielkości listy/tablicy. Więc jeśli już wiesz, że twoja lista zawiera tysiące elementów, jest szybsza, jeśli już zainicjujesz listę o przybliżonym rozmiarze.

1

Właśnie wybrałeś idealny przykład. Zarówno faktycznie taka sama jak new ArrayList() połączeń this(10);) Ale wewnętrznie byłoby zdefiniować tablicę holdingową z rozmiarem 10. Sposób ArrayList#size z drugiej strony nie tylko zwrócić zmienną size, która zostanie zmieniona tylko po dodawanie i usuwanie elementów. Ta zmienna jest również głównym powodem wyjątków. Więc nie będziesz w stanie tego zrobić.

Jeśli na przykład sprawdzisz kod ArrayList, zauważysz, że metoda ArrayList#add zadzwoni pod numer ArrayList#add pod numer ArrayList#rangeCheck. Czek zakres faktycznie tylko dba o size zmiennej a nie actuall długość tablicy trzyma dane dla List.

W związku z tym you'll nadal nie móc wstawić dane w indeksie 5 na przykład. Wewnętrzna długość tablicy danych w tym miejscu będzie wynosić 10, ale ponieważ nie dodałeś nic do swojej List, zmienna size nadal będzie 0, a otrzymasz prawidłową IndexOutOfBoundsException, kiedy spróbujesz to zrobić.

po prostu spróbuj zadzwonić pod numer list.size() po zainicjowaniu modelu List w dowolnym rozmiarze, a zauważysz, że zwracany rozmiar będzie wynosił 0.

4

ArrayList s w Javie są auto-growalne i zmienią rozmiar, jeśli będą potrzebne w celu dodania dodatkowych elementów. Parametr rozmiaru w konstruktorze jest używany tylko do początkowego rozmiaru wewnętrznej tablicy i jest rodzajem optymalizacji, gdy wiesz dokładnie, do czego masz zamiar użyć tablicy.

Określanie tej pojemności początkowej jest często przedwczesną optymalizacją, ale jeśli naprawdę potrzebujesz ArrayList z 10 elementów, powinieneś ją wyraźnie określić, nie zakładaj, że domyślny rozmiar to 10. Chociaż tak naprawdę było to domyślne zachowanie (do JDK 7, IIRC), nie powinieneś polegać na nim - JDK 8 (sprawdzony z java-1.8.0-openjdk-1.8.0.101-1.b14.fc24.x86_64 Zainstalowałem) domyślnie tworzy pustyArrayList.

2

innych odpowiedzi wyjaśniły naprawdę dobrze, ale tylko do przechowywania rzeczy istotne, w JDK 1.7.0_95:

/** 
* Constructs a new {@code ArrayList} instance with zero initial capacity. 
*/ 
public ArrayList() { 
    array = EmptyArray.OBJECT; 
} 


/** 
* Constructs a new instance of {@code ArrayList} with the specified 
* initial capacity. 
* 
* @param capacity 
*   the initial capacity of this {@code ArrayList}. 
*/ 
public ArrayList(int capacity) { 
    if (capacity < 0) { 
     throw new IllegalArgumentException("capacity < 0: " + capacity); 
    } 
    array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]); 
} 

Jako komentarz wspomina, konstruktor przyjmując żadnych argumentów inicjuje ArrayList z zerowym początkowej pojemności.

A nawet bardziej interesujące tutaj jest zmienna (z komentarzem), który nadaje wiele informacji na własną rękę:

/** 
* The minimum amount by which the capacity of an ArrayList will increase. 
* This tuning parameter controls a time-space tradeoff. This value (12) 
* gives empirically good results and is arguably consistent with the 
* RI's specified default initial capacity of 10: instead of 10, we start 
* with 0 (sans allocation) and jump to 12. 
*/ 
private static final int MIN_CAPACITY_INCREMENT = 12; 
+0

Jest oczywiste, że deweloperzy Java w wersji 1.7 wprowadzili pewne zmiany w tym zachowaniu, ponieważ w niektórych javadoc odnoszą się do starej początkowej pojemności 10. Ale kod mówi nam coś innego. Dobry post. – Aris2World

0

Inicjalizacja ArrayList została zoptymalizowana ponieważ JDK 1.7 aktualizacji 40 i jest tam dobry wyjaśnienie dwóch różnych zachowań pod tym linkiem: java-optimization-empty-arraylist-and-Hashmap-cost-less-memory-jdk-17040-update.

Tak więc przed wersją Java 1.7u40 nie ma różnicy, ale z tej wersji jest dość duża różnica.

Ta różnica dotyczy optymalizacji wyników i nie zmienia umowy z List.add(E e) i ArrayList(int initialCapacity).

Powiązane problemy