A standard question arises: how to initialize a list? The code below will not work: It will result in a compilation error: The local variable names may not have been initialized . The Java specification requires that all local variables (those that exist on the stack) be initialized with appropriate values. This is how you can do it: Without a doubt, the list must be initialized. You can either create the list on the first line, or you can do something smarter and use lazy initialization like we did in the getAllNames() method . In this case, the list will only be created when necessary - if the initial conditions are not met, the list will never appear on the heap. Here we come to the main question: what size should we set for the list? The best option is to give him the exact size. For example: In this case, exactly n names must be returned, and as a consequence, a collection of n elements is created. However, the exact value of n is not always known. Even in the example given, what if n=1000 and there were only 100 names available? When working with collections, the most popular method is to call the default constructor. If you look at the Java source code (version 1.6) As you can see, by default a list of 10 elements is created . That is, we can safely use the default constructor when we do not plan to store more than 10 elements in the list. What happens if you try to add the 11th element? Well, nothing bad... the element will be added successfully. Look at the method: The size of the array is controlled by the ensureCapacity method . The size increases by 1.5 times . A new array is created and the elements are moved into it. If we set the size to 10, then on the 11th element:
public List
getAllNames() { List
names; if (/*необходимые условия выполнены*/) { names = new ArrayList
(); /*заполнение списка*/ } return names; }
List
names = null; List
names = new ArrayList
(); List
names = new ArrayList
(0); List
names = new ArrayList
(size);
public List
getTopNames (int n) { List
names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList
(n); /*заполнение списка*/ } return names; }
names = new ArrayList
();
/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; }
public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
- size changes to 10 * 3 / 2 + 1 = 16
- next increase = 16 * 3 / 2 + 1 = 25
- next increase = 25 * 3 / 2 + 1 = 39 and so on.
- Create a collection only when you need it , otherwise initialize it to null or use Collections.EMPTY_LIST .
- If you know the exact size required , specify it in the collection constructor.
- If you are sure that the number of elements will not exceed 10 , feel free to use the default constructor.
- The risk associated with creating a zero-size collection is that the frequency of creating new arrays and copying data may be higher. You need to think very carefully about whether the benefit of using zero-size collections is really that great .
- If you initialized a collection too large at the beginning of the method and want to reduce it, there is the trimToSize() method .
GO TO FULL VERSION