Java Collections: Скрытые инструменты, которые вы упускаете
Большинство разработчиков используют Java collections одинаково изо дня в день. Они используют ArrayList и HashSet. Но вы можете упускать инструменты, которые сделают ваш код быстрее и безопаснее.
Вот три конкретных инструмента для улучшения вашего кода.
- Arrays.asList — это не настоящий List
Когда вы используете Arrays.asList(array), вы получаете список фиксированного размера. Он напрямую связан с вашим исходным массивом.
- Если вы измените массив, список тоже изменится.
- Если вы попытаетесь добавить или удалить элементы, ваш код завершится с ошибкой.
Чтобы исправить это, оберните его в новый ArrayList:
List<String> list = new ArrayList<>(Arrays.asList(array));
Это создает настоящий, независимый список, который можно изменять.
- Используйте EnumSet для повышения производительности
Вы храните перечисления (enums) в HashSet? Это создает ненужные накладные расходы. HashSet использует хеш-таблицы и заголовки объектов.
Вместо этого используйте EnumSet. Внутри он использует битовый вектор. Он работает чрезвычайно быстро и практически не потребляет памяти. Он идеально подходит для систем на основе флагов, таких как способности игрока или настройки.
- Он обеспечивает типобезопасность.
- Он намного быстрее, чем
HashSet. - Он берет на себя выполнение побитовых операций.
- Используйте ConcurrentHashMap.computeIfAbsent для кэшей
При создании кэша вы часто пишете сложный код, чтобы предотвратить одновременное вычисление одного и того же значения несколькими потоками. Это называется double-checked locking. Такой код трудно читать, и в нем легко допустить ошибку.
Вместо этого используйте одну строку:
cache.computeIfAbsent(key, this::expensiveCalculation);
Этот метод является атомарным. Он гарантирует, что вычисление выполнится только один раз, даже если множество потоков одновременно запрашивают один и тот же ключ. Это уменьшает количество багов и делает ваши намерения понятными.
Почему эти инструменты важны:
- Предсказуемая производительность: вы избегаете скрытых затрат памяти.
- Меньше багов: вы перестаете бороться с состоянием гонки (race conditions) в многопоточном коде.
- Более чистый код: другие разработчики сразу поймут вашу логику.
Хватит бороться с фреймворком. Начните использовать его, чтобы писать более лаконичный и безопасный код.