JavaRush /בלוג Java /Random-HE /new ArrayList(????) איך ואיפה עדיף לאתחל
Vovan
רָמָה

new ArrayList(????) איך ואיפה עדיף לאתחל

פורסם בקבוצה
כתיבת קוד ללא שימוש במסגרת האוספים תהיה מטורפת. זוהי חתיכת ג'אווה נפלאה עם הרבה פתרונות מסודרים. חשוב מכך, שלא כמו מערכים, אתה לא צריך לדאוג לגבי גדלים. ArrayList יגדל עד שייגמר לו הזיכרון. המפתח לא צריך לדאוג לגבי הגודל הראשוני ושגיאת ArrayIndexOutOfBoundsException . אבל מה אם יש תנאי לנטר את כמות הזיכרון? האם אנו יכולים להשתמש בזיכרון ביעילות כאשר אנו עובדים עם אוספים?
נשאלת שאלה סטנדרטית: כיצד לאתחל רשימה? הקוד שלהלן לא יעבוד: זה יגרום לשגיאת קומפילציה: ייתכן ששמות המשתנים המקומיים לא אוחלו . מפרט 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 וכן הלאה.
במקרה של 100 אלמנטים, ה-JVM יצטרך ליצור מערך חדש מספר פעמים ולהעתיק את האלמנטים לתוכו. בהתחשב בכך, אם יש הנחה לגבי הגודל הנדרש של המערך, עדיף להגדיר את הקיבולת הראשונית קרוב אליו. להלן מספר קווים מנחים לפעולה:
  1. צור אוסף רק כאשר אתה צריך אותו , אחרת אתחול אותו ל-null או השתמש ב-Collections.EMPTY_LIST .
  2. אם אתה יודע את הגודל המדויק הנדרש , ציין אותו בבנאי האוסף.
  3. אם אתה בטוח שמספר האלמנטים לא יעלה על 10 , אל תהסס להשתמש בבנאי ברירת המחדל.
  4. הסיכון הקשור ביצירת אוסף בגודל אפס הוא שתדירות יצירת מערכים חדשים והעתקת נתונים עשויה להיות גבוהה יותר. אתה צריך לחשוב היטב אם היתרון של שימוש בקולקציות בגודל אפס הוא באמת כל כך גדול .
  5. אם אתחוללת אוסף גדול מדי בתחילת השיטה וברצונך לצמצם אותו, יש את המתודה trimToSize() .
כמובן, ההנחיות הללו חלות בעבודה עם אוספים מבוססי מערך, וכל זה לא הגיוני במקרה של רשימה מקושרת. למעשה, סביר להניח שבעיות אלה לא יהיו רוצחות התוכנית, אבל אם יש הזדמנות לעשות קצת יותר טוב, למה לא להשתמש בה. יש לך עוד עצות מועילות? האם מצאת דרכים לגרום לדברים לעבוד טוב יותר? או שכל זה מיותר? מה אתה חושב?
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION