您将如何根据先前条件更新hashmap中的值?

时间:2018-04-30 05:48:16

标签: java hashmap

关于hashmaps和for循环的基本内容对我来说很难掌握。我想要做的是每次数组列表中的值与键字符串相关联时,基于Keys方法将与键相关联的值添加+1。

因此,如果数组列表中有3个值为正值,则hashmap应该具有将“positive”键更新为3的值。

任何帮助/建议将不胜感激 - 谢谢。

drush entup

4 个答案:

答案 0 :(得分:2)

Map.put(k, v)始终会覆盖您之前的值。您可以使用"传统方法":

if (!map.containsKey("positive"))
    map.put("positive", 0);
map.put("positive", map.get("positive") + 1);

或者更好地使用为这种情况添加的新merge功能:

map.merge("positive", 1, (prev, one) -> prev + one);

但是使用Math.signum()和流收集器可以大大缩短整个逻辑:

Map<Double, Long> collect = inputs.stream()
                                  .collect(Collectors.groupingBy(Math::signum,
                                                                 Collectors.counting()));
System.out.println("positive: " + collect.get(1.0));
System.out.println("negative: " + collect.get(-1.0));
System.out.println("zero: " + collect.get(0.0));

答案 1 :(得分:2)

让我们快速整理,让我们创建一个enum并删除那些你没有在任何地方定义的讨厌的String常量:

public enum Sign {
    POSITIVE,
    ZERO,
    NEGATIVE;

    public static Sign of(double d) {
        if (d > 0) {
            return POSITIVE;
        }
        if (d < 0) {
            return NEGATIVE;
        }
        return ZERO;
    }
}

现在我们可以简单地编写一个方法来增加适当的值:

public void increment(final double d, final Map<Sign, Integer> count) {
    count.merge(Sign.of(d), 1, Integer::sum);
}

快速测试:

final Map<Sign, Integer> count = new EnumMap<>(Sign.class);

increment(0, count);
System.out.println(count);
increment(-1, count);
System.out.println(count);
increment(1, count);
System.out.println(count);
increment(-2, count);
System.out.println(count);
increment(2, count);
System.out.println(count);

输出:

{ZERO=1}
{NEGATIVE=1, ZERO=1}
{POSITIVE=1, NEGATIVE=1, ZERO=1}
{POSITIVE=1, NEGATIVE=2, ZERO=1}
{POSITIVE=2, NEGATIVE=2, ZERO=1}

那么这个神奇的工作原理是什么?来自the documentation for Map.merge

  

如果指定的键尚未与值关联或是   与null关联,将其与给定的非null值相关联。   否则,将相关值替换为给定的结果   重新映射函数,如果结果为null则删除。这种方法可以   在组合键的多个映射值时使用。

所以key作为merge的第一个参数 - 在Sign.of(d)的情况下;这会选择正确的存储桶。如果映射到key的值为null,那么它只是将key的映射放到作为第二个参数传递的value - 在这种情况下{{1} }。否则它会变得更复杂;它采用当前映射到该键的值,并使用作为第三个参数传递的1。这是一个remappingFunction,所以它需要两个BiFunction<V,V,V>类型的参数,V类型并返回一个参数 - 它将两者合并在一起。在这里,我们使用value来获取现有Integer::sum,新value并返回其value

但我们可以更进一步,我们可以使用sum对任意Stream执行此操作:

double[]

注意:我在这里使用了EnumMappublic Map<Sign, Long> count(final double[] d) { return Arrays.stream(d) .mapToObj(Sign::of) .collect(groupingBy(identity(), () -> new EnumMap<>(Sign.class), counting())); } 针对使用Map作为关键进行了优化。

答案 2 :(得分:1)

你可以用流简洁地解决它。您需要一个将值转换为negative / zero / positive键的函数。然后只需通过此键与计数收集器进行分组。它基本上是一个双线:

    List<Double> values = Arrays.asList(-4.56,-4.66,0.0, 6.0, -6.99, 6.97);

    Function<Double, String> toKey = v -> v < 0 ? "negative" : (v == 0 ? "zero" : "positive");

    Map<String, Long> result = values
        .stream()
        .collect(Collectors
            .groupingBy(
                 toKey,
                 Collectors.counting()));

答案 3 :(得分:0)

HashMap的方法<div class="form-group"> {{ form_label(form.amenities, '', {'label_attr': {'class': 'col-md-4 control-label amenities', 'data-location-id': location.id}}) }} <div class="col-md-8"> {{ form_widget(form.amenities, {'attr': {'class': 'form-control'}}) }} {{ form_errors(form.amenities) }} </div> </div> 使用值映射唯一键。如果提供的密钥已经存在于地图中,它将使用新值替换现有值。

您需要定义类似于下面的方法。

put

对于比较值的书写方法,您可以参考https://stackoverflow.com/a/10400718/504133