ജാവ കളക്ഷനുകളിൽ മാസ്റ്റർ ആകാം

മിക്ക ഡെവലപ്പർമാരും ഡിഫോൾട്ട് ആയി ArrayList അല്ലെങ്കിൽ HashSet ആണ് ഉപയോഗിക്കാറുള്ളത്. ലളിതമായ ജോലികൾക്ക് ഇത് മതിയാകും. എന്നാൽ വേഗതയോ വലിയ തോതിലുള്ള ഡാറ്റ കൈകാര്യം ചെയ്യാനോ (scale) ആവശ്യമായി വരുമ്പോൾ ഇത് പരാജയപ്പെടുന്നു.

ഒരിക്കൽ ഞാൻ ഒരു സാധാരണ ArrayList ഉപയോഗിച്ച് ഒരു ഗെയിം ലീഡർബോർഡ് നിർമ്മിച്ചിരുന്നു. ഓരോ തവണ സ്കോർ മാറുമ്പോഴും ഞാൻ അത് സോർട്ട് (sort) ചെയ്യുമായിരുന്നു. ഇത് കാരണം UI നിരന്തരം ഫ്രീസ് ആകുന്നുണ്ടായിരുന്നു. ഞാൻ ഭാഷയെ (language) ഉപയോഗിക്കുന്നതിന് പകരം അതിനോട് പോരാടുകയായിരുന്നു.

തെറ്റായ ടൂളുകൾ ഉപയോഗിക്കുന്നത് നിർത്തുക. വേഗതയേറിയതും വൃത്തിയുള്ളതുമായ കോഡ് എഴുതാൻ ഈ മൂന്ന് സ്പെഷ്യലൈസ്ഡ് കളക്ഷനുകൾ ഉപയോഗിക്കുക.

  1. Enum Constants-നായി EnumSet ഉപയോഗിക്കുക

എനമ്മുകൾക്കായി (enums) നിങ്ങൾ HashSet ഉപയോഗിക്കുകയാണെങ്കിൽ, അത് പെർഫോമൻസിനെ ബാധിക്കും. ഓരോ തവണ ഇൻസേർട്ട് ചെയ്യുമ്പോഴും എനം ഒരു ഒബ്‌ജക്റ്റായി മാറുന്നു (boxing). ഇത് അനാവശ്യമായ അധികഭാരം (overhead) ഉണ്ടാക്കുന്നു.

EnumSet ഒരു ബിറ്റ് വെക്റ്റർ (bit vector) ആണ് ഉപയോഗിക്കുന്നത്. ഇത് ഒരു സിംഗിൾ CPU ഇൻസ്ട്രക്ഷൻ ഉപയോഗിച്ച് പരിശോധനകൾ നടത്തുന്നു.

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

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

  1. Range Queries-നായി NavigableSet ഉപയോഗിക്കുക

ഒരു റേഞ്ച് കണ്ടെത്താനായി സോർട്ട് ചെയ്ത ലിസ്റ്റിലൂടെ മാനുവലായി ലൂപ്പ് ചെയ്യുന്നത് സാവധാനത്തിലുള്ളതും തെറ്റുകൾ സംഭവിക്കാൻ സാധ്യതയുള്ളതുമാണ്. പലപ്പോഴും 'off-by-one' ബഗുകൾ ഇതിലൂടെ ഉണ്ടാകാം.

NavigableSet നിങ്ങളുടെ ഡാറ്റ സ്വയം സോർട്ട് ചെയ്ത് സൂക്ഷിക്കുന്നു. സബ്‌സെറ്റുകൾക്കായി (subsets) ഇത് O(log n) ലുക്കപ്പുകൾ നൽകുന്നു.

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. Read-Heavy ലിസ്റ്റുകൾക്കായി CopyOnWriteArrayList ഉപയോഗിക്കുക

ഒരു ArrayList-ൽ സിൻക്രണൈസ്ഡ് ബ്ലോക്കുകൾ (synchronized blocks) ഉപയോഗിക്കുന്നത് ഓരോ റീഡിനെയും സാവധാനത്തിലാക്കും. കൂടാതെ, ഒരു ത്രെഡ് എഴുതിക്കൊണ്ടിരിക്കുമ്പോൾ മറ്റൊന്ന് വായിക്കാൻ ശ്രമിച്ചാൽ ConcurrentModificationException ഉണ്ടാകാനും ഇത് കാരണമാകും.

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