העתק רשימה לרשימה אחרת ב- Java

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

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

להקדמה לשימוש ב- אוספיםאנא עיין במאמר זה כאן.

2. קונסטרוקטור

דרך פשוטה להעתיק רשימה הוא באמצעות הבנאי שלוקח אוסף כטיעון שלו:

עותק רשימה = ArrayList חדש (רשימה);

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

מסיבה זו, שימוש בבנאי הוא טוב להעתקת אובייקטים בלתי ניתנים לשינוי:

עותק רשימה = ArrayList חדש (רשימה);

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

An מספר שלם כך ניתן לשתף הפניה על ידי מספר רשימות וחוטים ואין שום סיכוי שאף אחד יכול לשנות את ערכה.

3. רשימהConcurrentAccessException

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

כדי לפתור בעיה זו עלינו:

  • השתמש בתכנית המיועדת לאיסוף גישה במקביל
  • נעל את האוסף כראוי כדי לחזור עליו
  • מצא דרך להימנע מצורך להעתיק את האוסף המקורי

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

למידע נוסף, עיין במאמר זה.

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

4. הוסף הכל

גישה נוספת להעתקת אלמנטים היא שימוש ב- הוסף הכל שיטה:

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

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

5. Collections.copy

ה אוספים מחלקה מורכבת אך ורק משיטות סטטיות הפועלות או מחזירות אוספים.

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

זה ישמור על האינדקס של כל אלמנט שהועתק ברשימת היעד כמו המקור:

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

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

במקרה שגודל רשימת היעד גדול מהמקור:

מקור רשימה = Arrays.asList (1, 2, 3); רשימת dest = Arrays.asList (5, 6, 7, 8, 9, 10); Collections.copy (יעד, מקור);

רק שלושת הפריטים הראשונים הוחלפו בזמן ששאר האלמנטים ברשימה שמורים.

6. שימוש ב- Java 8

גרסה זו של Java פותחת את האפשרויות שלנו על ידי הוספת כלים חדשים. זה שנחקור בדוגמאות הבאות הוא זרם:

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

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

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

אפשר לסנן לפי אורך ה- חוּט או על ידי השוואת תכונה של האובייקטים שלנו:

רשימת העתק = list.stream () .filter (s -> s.length ()> 10) .collect (Collectors.toList ());
רשימת פרחים = list.stream () .filter (f -> f.getPetals ()> 6) .collect (Collectors.toList ());

סביר להניח שאנחנו רוצים לעבוד בצורה בטוחה:

רשימת פרחים = Optional.ofNullable (list) .map (List :: stream) .orElseGet (Stream :: ריק) .collect (Collectors.toList ());

ודלג על אלמנט גם בדרך זו:

רשימת פרחים = Optional.ofNullable (list) .map (List :: stream) .orElseGet (Stream :: ריק) .skip (1) .collect (Collectors.toList ());

7. שימוש ב- Java 10

לבסוף, אחת מגרסאות הג'אווה האחרונות מאפשרת לנו ליצור מהפך רשימה המכיל את יסודות הנתון אוסף:

עותק רשימה = List.copyOf (רשימה);
התנאים היחידים הם שאסור שהאוסף הנתון יהיה ריק, והוא לא יכול להכיל רכיבי null.

8. מסקנה

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