Приращение целых чисел на карте

У меня есть HashMap<Token, Integer>, который подсчитывает вхождения Token. Каждый раз, когда Token найден, значение на карте должно быть увеличено.

Map<Token, Integer> occurrences = new HashMap<Token, Integer>();
// ...

public void tokenFound(Token token) {

    Integer numberOfOccurs = occurrences.get(token);
    Integer newNumberOfOccurs = new Integer((numberOfOccurs == null) ? 1 : numberOfOccurs.intValue() + 1);
    occurrences.put(token, newNumberOfOccurs);
}

Есть ли более элегантный способ сделать это?

32 голоса | спросил Kao 15 J000000Tuesday14 2014, 15:44:50

4 ответа


30

У вас есть несколько различных вариантов:

гуавы

В Гуавской библиотеке Google представлена ​​идея Multiset , которая способна подсчитывать вхождения, а также предоставляет несколько других функций.

Java 8

Если вы используете Java 8 (что я настоятельно рекомендую, если у вас есть возможность сделать это), ваш метод tokenFound может быть простым:

occurrences.merge(token, 1, (oldValue, one) -> oldValue + one);

Или это:

occurrences.compute(token, (tokenKey, oldValue) -> oldValue == null ? 1 : oldValue + 1);

Обратите внимание, что с Java 7 вы можете инициализировать карту с помощью «оператора алмаза»:

Map<Token, Integer> occurrences = new HashMap<>();

Без Java 8 нет библиотек

Если вы не можете использовать Java 8 и не хотите добавлять Guava в качестве сторонней библиотеки в свой проект, вы можете сделать небольшую часть, чтобы упростить существующий код:

Integer previousValue = occurrences.get(token);
occurrences.put(token, previousValue == null ? 1 : previousValue + 1);

Более конкретно:

  • Использование конструктора new Integer не требуется, Java автоматически использует бокс для этого. Для значений Integer, близких к нулю, это фактически немного сэкономит вам, потому что Java хранит кешированные целые числа.
  • Вам не нужна переменная newNumberOfOccurs, поскольку она используется только один раз.
ответил Simon Forsberg 15 J000000Tuesday14 2014, 16:03:17
8

Guava Multiset и новые типы коллекции Guava, объясненные .

  • Эффективная Java, 2nd edition , Пункт 47: Знать и использовать библиотеки (автор упоминает только встроенные библиотеки JDK, но я думаю, что рассуждение может быть верным для других библиотек тоже.)
  • ответил palacsint 15 J000000Tuesday14 2014, 15:57:42
    5

    Я чувствую, что ответы на не-библиотеку могут быть улучшены, поэтому вот мой подход к ним.

    Для java 7:

    private final Map<Token, AtomicInteger> occurrences = new HashMap<>();
    
    public void tokenFound(Token token) {
        if (!occurrences.containsKey(token)) {
            occurrences.put(token, new AtomicInteger(1));
            return;
        }
        occurrences.get(token).incrementAndGet();
    }
    

    Вы используете AtomicInteger как тип значения, позволяя легко incrementAndGet() вместо того, чтобы перезаписывать ведро в Map.

    Для Java 8:

    private final Map<Token, LongAdder> occurrences = new HashMap<>();
    
    public void tokenFound(Token token) {
        occurrences.computeIfAbsent(token, (t) -> new LongAdder()).increment();
    }
    

    LongAdder - это тип, специально предназначенный для подсчета (особенно при сильном параллелизме). Добавленный метод computeIfAbsent() на Map и добавление lambdas превращают все это в однострочный.

    Если вы используете java 7, я бы выбрал Guava, но если вы на 8 просто используете классы java.util.

    ответил bowmore 16 J000000Wednesday14 2014, 03:20:27
    1

    Если вы используете Java 8:

    Хотя методы merge и compute в Map работают для этой цели, Map.getOrDefault(Object key, V defaultValue) показывает мне смысл кода более четко.

    Map<Token, Integer> occurrences = new HashMap<Token, Integer>();
    
    // for each token:
    occurrences.put(token, occurrences.getOrDefault(token, 0) + 1);
    
    ответил nybon 3 AMpTue, 03 Apr 2018 05:16:20 +030016Tuesday 2018, 05:16:20

    Похожие вопросы

    Популярные теги

    security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132