שליטה ב-Java Collections

רוב המפתחים משתמשים כברירת מחדל ב-ArrayList או ב-HashSet. זה עובד למשימות פשוטות, אך זה נכשל כשזקוקים למהירות או ליכולת גדילה (scale).

פעם בניתי לוח תוצאות (leaderboard) למשחק באמצעות ArrayList רגיל. מיין אותו בכל פעם שציון השתנה. ממשק המשתמש (UI) קפא כל הזמן. הייתי נלחם בשפה במקום להשתמש בה.

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

  1. EnumSet עבור קבועים מסוג Enum

אם אתם משתמשים ב-HashSet עבור enums, אתם משלמים "מס ביצועים". כל הכנסה (insertion) מבצעת boxing ל-enum לאובייקט. זה מוסיף overhead מיותר.

EnumSet משתמש ב-bit vector. הוא מבצע בדיקות באמצעות הוראת CPU בודדת.

Before: Set<Ability> abilities = new HashSet<>(); abilities.add(Ability.FIRE);

After: EnumSet<Ability> abilities = EnumSet.of(Ability.FIRE);

  1. NavigableSet עבור שאילתות טווח (Range Queries)

מעבר ידני בלולאה על רשימה ממוינת כדי למצוא טווח הוא איטי וחשוף לשגיאות. לעיתים קרובות תמצאו את עצמכם עם באגים מסוג off-by-one.

NavigableSet שומר על הנתונים שלכם ממוינים באופן אוטומטי. הוא מספק חיפושים (lookups) בסיבוכיות של O(log n) עבור תת-קבוצות (subsets).

Before: Collections.sort(scores); List<Integer> topTen = scores.subList(size - 10, size);

After: NavigableSet<Integer> scores = new TreeSet<>(Comparator.reverseOrder()); scores.add(1542); NavigableSet<Integer> topTen = scores.headSet(scores.first(), true).stream().limit(10).collect(Collectors.toCollection(TreeSet::new));

  1. CopyOnWriteArrayList עבור רשימות עם קריאות מרובות (Read-Heavy)

שימוש בבלוקים מסוג synchronized על ArrayList מאט כל קריאה. זה גם גורם ל-ConcurrentModificationException אם תהליכון (thread) אחד כותב בזמן שאחר קורא.

CopyOnWriteArrayList יוצר עותק חדש של המערך בכל פעולת כתיבה. הקוראים צופים ב-snapshot (תמונת מצב) של המערך.

Before: List<String> log = Collections.synchronizedList(new ArrayList<>()); // Iterating here can crash if a writer joins in.

After: CopyOnWriteArrayList<String> log = new CopyOnWriteArrayList<>(); // Iteration is safe and never crashes.

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

מקור: https://dev.to/timevolt/the-java-collections-force-mastering-the-hidden-gems-like-a-jedi-4438