Редактировать # 2:
Хорошо, я испортил свое первое правило - никогда не оптимизировать преждевременно. В худшем случае для этого, вероятно, используется стандартная HashMap с широким диапазоном - так что я просто сделал это. Он по-прежнему работает как секунда, так что забудьте обо всем остальном здесь и просто сделайте это.
И я ВСЕГДА сделаю ДРУГОЕ примечание о скорости тестирования, прежде чем беспокоиться о хитрых реализациях.
(Ниже приведен более старый устаревший пост, который все еще мог бы быть действительным, если бы кто-то имел НАМНОГО больше очков, чем миллион)
HashSet работал бы, но если у ваших целых чисел есть разумный диапазон (скажем, 1-1000), было бы более эффективно создать массив из 1000 целых чисел, и для каждого из ваших миллионов целых чисел увеличить этот элемент массив. (Практически та же идея, что и в HashMap, но оптимизация нескольких неизвестных, для которых Hash должен учесть, должна сделать его в несколько раз быстрее).
Вы также можете создать дерево. Каждый узел в дереве будет содержать (значение, количество), и дерево будет организовано по значению (нижние значения слева, выше справа). Перейдите к вашему узлу, если он не существует - вставьте его - если он есть, просто увеличьте счетчик.
Диапазон и распределение ваших значений будут определять, какое из этих двух значений (или обычный хеш) будет работать лучше. Я думаю, что обычный хэш не будет иметь много «выигрышных» случаев (хотя это должен быть широкий диапазон и «сгруппированные» данные, и даже тогда дерево может победить.
Поскольку это довольно тривиально - я рекомендую вам реализовать более одного решения и тестировать скорости по фактическому набору данных.
Редактировать: RE комментарий
TreeMap будет работать, но все равно добавит слой косвенности (и это так удивительно легко и весело реализовать самостоятельно). Если вы используете стандартную реализацию, вы должны использовать целые числа и постоянно конвертировать в и из int для каждого увеличения. Существует косвенное указатель на Integer и тот факт, что вы храните как минимум в 2 раза больше объектов. Это даже не учитывает никаких накладных расходов на вызовы методов, поскольку они должны быть встроены при любой удаче.
Обычно это будет оптимизация (зло), но когда вы начинаете получать около сотен тысяч узлов, вам иногда приходится обеспечивать эффективность, поэтому встроенный TreeMap будет неэффективным по тем же причинам, что и встроенный -в HashSet будет.