אינדקס JavaOutOfBoundsException "המקור אינו מתאים ליעדים"

1. סקירה כללית

בג'אווה, יצירת עותק של a רשימה יכול לפעמים לייצר IndexOutOfBoundsException: "המקור אינו מתאים ליעוד". במדריך קצר זה, אנו נסתכל מדוע אנו מקבלים שגיאה זו בעת השימוש ב- Collections.copy שיטה ואיך ניתן לפתור אותה. נבחן גם חלופות ל- Collections.copy כדי ליצור עותק של הרשימה.

2. שכפול הבעיה

נתחיל בשיטה ליצירת עותק של a רשימה משתמש ב Collections.copy שיטה:

רשימת סטטי copyList (מקור רשימה) {יעד יעד = ArrayList חדש (source.size ()); Collections.copy (יעד, מקור); יעד חזרה; }

הנה ה copyList השיטה יוצרת רשימה חדשה עם קיבולת התחלתית השווה לגודל רשימת המקורות. ואז הוא מנסה להעתיק את האלמנטים של רשימת המקורות לרשימת היעד:

מקור רשימה = Arrays.asList (1, 2, 3, 4, 5); עותק רשימה = copyList (מקור);

עם זאת, ברגע שאנחנו מתקשרים אל copyList בשיטה, זה יוצא חריג java.lang.IndexOutOfBoundsException: המקור אינו מתאים ליעוד.

3. הסיבה ל יוצא מן הכלל

בואו ננסה להבין מה השתבש. על פי התיעוד עבור Collections.copy שיטה:

רשימת היעד חייבת להיות ארוכה לפחות כמו רשימת המקורות. אם הוא ארוך יותר, האלמנטים הנותרים ברשימת היעד אינם מושפעים.

בדוגמה שלנו, יצרנו חדש רשימה באמצעות קונסטרוקטור בעל קיבולת התחלתית השווה לגודל רשימת המקורות. זה פשוט מקצה מספיק זיכרון ולא ממש מגדיר אלמנטים. גודל הרשימה החדשה נשאר אפס מכיוון שהקיבולת והגודל הם מאפיינים שונים של ה- רשימה.

לכן, כאשר Collections.copy השיטה מנסה להעתיק את רשימת המקורות לרשימת היעד, היא זורקת java.lang.IndexOutOfBoundsException.

4. פתרונות

4.1. Collections.copy

בואו נסתכל על דוגמא לעבודה להעתקה של רשימה לאחר רשימה, משתמש ב Collections.copy שיטה:

יעד יעד = Arrays.asList (1, 2, 3, 4, 5); מקור רשימה = Arrays.asList (11, 22, 33); Collections.copy (יעד, מקור);

במקרה זה אנו מעתיקים את כל שלושת האלמנטים של רשימת המקורות לרשימת היעד. ה Arrays.asList השיטה מאותתת את הרשימה באלמנטים ולא רק בגודל, ולכן אנו יכולים להעתיק את רשימת המקורות לרשימת היעד בהצלחה.

אם רק נחליף את הטיעונים של Collections.copy שיטה, זה יזרוק java.lang.IndexOutOfBoundsException מכיוון שגודל רשימת המקורות קטן מגודל רשימת היעד.

לאחר פעולת העתקה זו, רשימת היעד נראית כך:

[11, 22, 33, 4, 5]

ביחד איתי Collections.copy בשיטה, ישנן דרכים אחרות בג'אווה ליצור עותק של רשימה. בואו נסתכל על כמה מהם.

4.2. רשימת מערך בַּנַאִי

הגישה הפשוטה ביותר להעתיק א רשימה משתמש בבנאי שלוקח א אוסף פָּרָמֶטֶר:

מקור רשימה = Arrays.asList (11, 22, 33); יעד רשימה = ArrayList חדש (מקור);

כאן אנו מעבירים את רשימת המקורות לבונה של רשימת היעד, היוצרת עותק רדוד של רשימת המקורות.

רשימת היעד תהיה רק ​​עוד התייחסות לאותו אובייקט שמפנה אליו רשימת המקורות. לכן, כל שינוי שנעשה על ידי כל התייחסות ישפיע על אותו אובייקט.

לכן, שימוש בבנאי הוא אפשרות טובה להעתקת אובייקטים בלתי ניתנים לשינוי כמו שלמים ו מיתרים.

4.3. הוסף הכל

דרך פשוטה נוספת היא להשתמש ב- הוסף הכל שיטה של רשימה:

יעד רשימה = ArrayList חדש (); destination.addAll (מקור);

התוסף All השיטה תעתיק את כל האלמנטים של רשימת המקורות לרשימת היעד.

יש לציין כמה נקודות לגבי גישה זו:

  1. זה יוצר עותק רדוד של רשימת המקורות.
  2. אלמנטים של רשימת המקורות מצורפים לרשימת היעד.

4.4. ג'אווה 8 זרמים

Java 8 הציגה את ה- API של Stream, שהוא כלי נהדר לעבודה עם Java אוספים.

משתמש ב זרם() שיטה, אנו יוצרים עותק של הרשימה באמצעות Stream API:

רשימה עותק = source.stream () .collect (Collectors.toList ());

4.5. ג'אווה 10

העתקה א רשימה פשוט אפילו יותר ב- Java 10. השימוש ב- העתק של() השיטה מאפשרת לנו ליצור רשימה בלתי ניתנת לשינוי המכילה את מרכיבי הנתון אוסף:

יעד רשימה = List.copyOf (sourceList);

אם אנו רוצים ללכת בגישה זו, עלינו לוודא את הקלט רשימה לא ריק ושהוא לא מכיל ריק אלמנטים.

5. מסקנה

במאמר זה בדקנו כיצד ומדוע Collections.copy שיטה זורקת IndexOutOfBoundException "המקור אינו מתועד ביעד". יחד עם זה, בדקנו גם דרכים שונות להעתקה של רשימה לאחר רשימה.

ניתן למצוא את הדוגמאות שלפני Java-10 ואת דוגמאות Java 10 ב- GitHub.