Ответ
1. Использование примитивных типов вместо обёрток (Boxed Types)
int,long,doubleвместоInteger,Long,Double.- Почему: Избегаем накладных расходов на объект в куче и автоупаковку/распаковку.
- Пример: Для больших коллекций используйте
Trove,Eclipse Collectionsили массивы примитивов.
2. Осознанное использование строк (String Pool)
- Литералы (
String s = "text") используют пул строк. - Метод
intern()помещает строку в пул, но может привести к утечке памяти, если используется бездумно. - Лучшая практика: Используйте
StringBuilderдля конкатенации в циклах.
3. Выбор правильных структур данных
ArrayListобычно эффективнееLinkedListпо памяти (не хранит отдельные узлы с двумя ссылками).- Для enum-значений используйте
EnumSetиEnumMap. - Устанавливайте начальную вместимость (
initialCapacity) коллекций, чтобы избежать лишних ресайзов.
4. Паттерн "Приспособленец" (Flyweight)
- Разделение общего, неизменяемого состояния между множеством объектов.
- Пример: Кэширование экземпляров часто используемых неизменяемых классов (например,
BigDecimal).
5. Своевременная очистка ссылок
- Обнуляйте ссылки на большие объекты, когда они больше не нужны (
largeList = null). - Используйте WeakReference для кэшей, которые можно очистить при нехватке памяти.
- Избегайте утечек памяти в слушателях событий (event listeners) — не забывайте отписываться.
6. Ленивая инициализация (Lazy Initialization)
- Создавайте ресурсоёмкие объекты только при первом обращении.
7. Потоковая обработка данных (Stream API)
- Обрабатывайте данные потоково, не загружая весь набор в память.
// Экономит память при работе с большими файлами Files.lines(path) .filter(line -> line.contains("error")) .forEach(System.out::println);