Откройте для себя лучший способ подсчета вещей в Java.

Использование карты для подсчета бусин на счетах

Вот простая задача, которую можно решить с помощью Map. Как мы можем посчитать количество бусинок на счетах по цвету? Сначала я определю enum для Color.

Далее я создам HashMap<Color, Integer> и использую метод merge для сложения и вычитания значений для определенных цветов. Я не буду учитывать одну цветную бисеринку (Color.RED). Затем я утверждаю результат запроса Map для подсчета цветов с помощью Map.get.

Я использую одну и ту же операцию merge для сложения и вычитания. Я использую отрицательные значения Integer для вычитания. Я использую ссылку на метод Integer::sum для параметра BiFunction, который принимает метод merge, чтобы определить, как объединять значения. Обратите внимание, что хотя я использую здесь примитивные литеральные значения int, они автоматически упаковываются как объекты Integer в Map., а вызов Integer::sum приведет к большему распаковыванию и упаковке Integer объектов.

В последнем утверждении теста вызов get с экземпляром Color.RED возвращает null. Мне пришлось бы явно установить значение 0, чтобы оно возвращалось как 0 при вызове get. Один из способов решить проблему возврата null с get — использовать вместо него getOrDefault. Это позволит вам вернуть значение по умолчанию в случае, если ключ не существует в файле Map.

Оба метода merge и getOrDefault были добавлены в Java 8 и являются полезными для понимания разработчиками в Map.

Использование примитивной карты вместо карты

В Eclipse Collections есть поддержка примитивных карт. Существует тип ObjectIntMap и соответствующая реализация, которую можно использовать для подсчета бусин. Я буду использовать MutableObjectIntMap, чтобы я мог видоизменять карту и создавать реализацию с помощью фабричного класса ObjectIntMaps.

У MutableObjectIntMap есть метод addToValue, который можно использовать для добавления нового значения на карту или добавления к существующему значению на карте. Метод getIfAbsent можно использовать для поиска значений. Значение 0 является объектом int, а не Integer, и ни один из вызовов addToValue не приводит ни к какой упаковке.

Примечание. Класс Eclipse Collections HashBag использует класс MutableObjectIntMap.

Использование мешка для подсчета бусинок на счетах

Итак, как бы я решил эту проблему, используя MutableBag из Eclipse Collections? MutableBag - это Collection, а не Map. У него есть методы add и remove, которые я могу использовать для добавления отдельных элементов. MutableBag также имеет методы addOccurrences и removeOccurrences, которые позволяют добавлять определенное количество элементов одновременно.

Методы с индивидуальными именами в Bag лучше раскрывают намерения, чем единственный метод с именем merge для этого варианта использования. Обратите внимание, что в случае Color.RED Bag вернет 0 из вызова occurrencesOf. Bag не страдает от проблемы null, которая есть у Map.get. Если значение не существует в Bag, метод occurrencesOf всегда возвращает 0.

Больше информации

Есть еще несколько блогов, которые предоставляют более подробную информацию о типе Bag и поддерживающих методах, таких как countBy в Eclipse Collections. Следующий блог был написан Нихилом Нанивадекаром. В нем описываются многие детали реализации типа Bag в коллекциях Eclipse, которые могут привести к выигрышу как в памяти, так и в производительности.



Я также написал отдельный блог, описывающий метод countBy в коллекциях Eclipse, который возвращает Bag в качестве возвращаемого типа.



Надеюсь, вам понравилось читать этот блог и вы узнали что-то полезное о типах Map и Bag!

Я являюсь руководителем и ответственным за проект OSS Eclipse Collections в Eclipse Foundation. Eclipse Collections открыт для пожертвований. Если вам нравится библиотека, сообщите нам об этом, пометив ее звездочкой на GitHub.

Другие Статьи по Java, которые могут вам понравиться