Стандартты сұрақ туындайды: тізімді қалай инициализациялау керек? Төмендегі code жұмыс істемейді: Бұл компиляция қатесіне әкеледі: Жергілікті айнымалы атаулар инициализацияланбаған болуы мүмкін . Java спецификациясы барлық жергілікті айнымалыларды (стекте барлар) сәйкес мәндермен инициализациялауды талап етеді. Сіз мұны осылай жасай аласыз: Сөзсіз, тізімді инициализациялау керек. Тізімді бірінші жолда жасауға болады, не ақылдырақ әрекет жасап, getAllNames() әдісіндегідей жалқау инициализацияны қолдануға болады . Бұл жағдайда тізім тек қажет болғанда жасалады - егер бастапқы шарттар орындалмаса, тізім ешқашан үймеде пайда болмайды. Міне, біз негізгі сұраққа келеміз: тізімге қандай өлшемді орнату керек? Ең жақсы нұсқа - оған нақты өлшемді беру. Мысалы: Бұл жағдайда дәл n атау қайтарылуы керек және нәтижесінде n элементтен тұратын топтама жасалады. Алайда n -дің нақты мәні әрқашан белгілі бола бермейді. Тіпті келтірілген мысалда n=1000 және тек 100 атау болса ше? Коллекциялармен жұмыс істеу кезінде ең танымал әдіс әдепкі конструкторды шақыру болып табылады. Егер сіз Java бастапқы codeын қарасаңыз (1.6 нұсқасы) Көріп отырғаныңыздай, әдепкі бойынша 10 элементтен тұратын тізім жасалады . Яғни, біз тізімде 10 элементтен артық сақтауды жоспарламаған кезде әдепкі конструкторды қауіпсіз пайдалана аламыз. 11-ші элементті қосуға әрекеттенсеңіз не болады? Ешқандай жаман ештеңе жоқ... элемент сәтті қосылады. Әдіске қараңыз: массив өлшемін ensureCapacity әдісі басқарады . Көлемі 1,5 есе артады . Жаңа массив жасалады және оған элементтер жылжытылады. Егер өлшемді 10-ға орнатсақ, онда 11-ші элементте:
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); } }
- өлшемі 10 * 3/2 + 1 = 16 болып өзгереді
- келесі өсу = 16 * 3/2 + 1 = 25
- келесі өсу = 25 * 3/2 + 1 = 39 және т.б.
- Жинақты қажет кезде ғана жасаңыз , әйтпесе оны нөлге инициализациялаңыз немесе Collections.EMPTY_LIST пайдаланыңыз .
- Қажетті өлшемді нақты білсеңіз , оны жинақ конструкторында көрсетіңіз.
- Элементтер саны 10 аспайтынына сенімді болсаңыз , әдепкі конструкторды пайдаланыңыз.
- Нөлдік өлшемді жинақты құрумен байланысты тәуекел жаңа массивтерді жасау және деректерді көшіру жиілігі жоғары болуы мүмкін. Нөлдік өлшемді жинақтарды пайдаланудың пайдасы шынымен соншалықты керемет пе, соны мұқият ойластыру керек .
- Әдістің басында жинақты тым үлкен инициализациялаған болсаңыз және оны азайтқыңыз келсе, trimToSize() әдісі бар .
GO TO FULL VERSION