נשאלת שאלה סטנדרטית: כיצד לאתחל רשימה? הקוד שלהלן לא יעבוד: זה יגרום לשגיאת קומפילציה: ייתכן ששמות המשתנים המקומיים לא אוחלו . מפרט Java דורש שאתחול כל המשתנים המקומיים (אלה שקיימים בערימה) עם ערכים מתאימים. כך תוכלו לעשות זאת: ללא ספק יש לאתחל את הרשימה. אתה יכול ליצור את הרשימה בשורה הראשונה, או שאתה יכול לעשות משהו חכם יותר ולהשתמש באתחול עצלן כמו שעשינו בשיטת getAllNames() . במקרה זה, הרשימה תיווצר רק בעת הצורך - אם התנאים ההתחלתיים לא מתקיימים, הרשימה לעולם לא תופיע בערימה. כאן הגענו לשאלה המרכזית: איזה מידה עלינו להגדיר לרשימה? האפשרות הטובה ביותר היא לתת לו את הגודל המדויק. לדוגמה: במקרה זה, יש להחזיר n שמות בדיוק, וכתוצאה מכך נוצר אוסף של n אלמנטים. עם זאת, הערך המדויק של n לא תמיד ידוע. אפילו בדוגמה שניתנה, מה אם n=1000 והיו רק 100 שמות זמינים? כאשר עובדים עם אוספים, השיטה הפופולרית ביותר היא לקרוא לבנאי ברירת המחדל. אם אתה מסתכל על קוד המקור של Java (גרסה 1.6) כפי שאתה יכול לראות, כברירת מחדל נוצרת רשימה של 10 אלמנטים . כלומר, אנו יכולים להשתמש בבטחה בבנאי ברירת המחדל כאשר איננו מתכננים לאחסן יותר מ-10 אלמנטים ברשימה. מה יקרה אם תנסה להוסיף את האלמנט ה-11? ובכן, שום דבר רע... האלמנט יתווסף בהצלחה. תסתכל על השיטה: גודל המערך נשלט על ידי שיטת sureCapacity . הגודל גדל פי 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 וכן הלאה.
- צור אוסף רק כאשר אתה צריך אותו , אחרת אתחול אותו ל-null או השתמש ב-Collections.EMPTY_LIST .
- אם אתה יודע את הגודל המדויק הנדרש , ציין אותו בבנאי האוסף.
- אם אתה בטוח שמספר האלמנטים לא יעלה על 10 , אל תהסס להשתמש בבנאי ברירת המחדל.
- הסיכון הקשור ביצירת אוסף בגודל אפס הוא שתדירות יצירת מערכים חדשים והעתקת נתונים עשויה להיות גבוהה יותר. אתה צריך לחשוב היטב אם היתרון של שימוש בקולקציות בגודל אפס הוא באמת כל כך גדול .
- אם אתחוללת אוסף גדול מדי בתחילת השיטה וברצונך לצמצם אותו, יש את המתודה trimToSize() .
GO TO FULL VERSION