得到Map的值对象字段的总和

时间:2013-11-18 10:07:42

标签: java swing java-ee map

我得到一个Map对象:

Map<String, Shop>> shopData = GET_SHOP_DATA();

Shop类包含两个字段:

public class Shop{
  private String name;
  int salesPerDay

  ...
}

获得所有商店salesPerDay总结有效方式是什么? (我知道我可以遍历Map对象并进行求和),我的意思是没有循环。

我知道我可以通过Collection获得shopData.values()个对象。有没有可能从那里得到总和而没有循环?

3 个答案:

答案 0 :(得分:2)

执行此操作的现代方法称为 map-reduce 它是Java 8的一部分,您只需一行即可完成,但也有框架提供这个。在这里搜索“map reduce”。

W.r.t。 map-reduce你可能会发现这篇文章很有用:Simple Java Map/Reduce framework

Java 8

在Java 8中,解决方案看起来像这样(一行!)

shopData.values().stream().map(s -> s.saledPerDay).sum();

下面

  • shopData.values()生成Shop对象的集合
  • stream()使其成为Shop对象
  • 的流
  • map(s -> s.saledPerDay)使其成为整数流
  • sum()总结一下。

因为你要求“效率”。可以并行执行此操作(使用多核机器的功能),只需

shopData.values().parallelStream().map(s -> s.saledPerDay).sum();

这是快速而简洁的。

Java 6/7

如果你想在Java 6/7中这样做,那么你可以使用一个库。例如,jedi提供了reduce,以下示例实际上或多或少是您需要的: http://jedi.codehaus.org/javadoc/jedi/functional/FunctionalPrimitives.html#reduce%28java.lang.Iterable,%20jedi.functional.Functor2%29

答案 1 :(得分:1)

您可以包装Map并将您的额外功能添加到某些方法中。在这里,我定义了SummingMap,这可能是一个好的开始。我遗漏了许多方法,但他们只需要将调用转发到底层地图。

interface Summable {
  public long getValue();

}

public static class Shop implements Summable {
  private String name;
  private long salesPerDay;

  @Override
  public long getValue() {
    return salesPerDay;
  }

}

public static class SummingMap<K, V extends Summable> implements Map<K, V> {
  private final Map<K, V> map;
  private long sum = 0;

  public SummingMap(Map<K, V> map) {
    this.map = map;
  }

  @Override
  public V put(K key, V value) {
    putting(key, value);
    return map.put(key, value);
  }

  @Override
  public void putAll(Map<? extends K, ? extends V> m) {
    for ( Map.Entry<? extends K, ? extends V> e : m.entrySet() ) {
      putting(e.getKey(), e.getValue());
    }
    map.putAll(m);
  }

  private void putting(K key, V value) {
    if (map.containsKey(key)) {
      sum -= map.get(key).getValue();
    }
    sum += value.getValue();
  }

  @Override
  public V remove(Object key) {
    Object o = map.get(key);
    if (o != null && o instanceof Summable) {
      sum -= ((Summable) o).getValue();
    }
    return map.remove(key);
  }

  // Other methods - just forward the call directly to the held map.

}

正如@Christian正确指出的那样,如果您更改salesPerDay对象中的Store值而不先将其从地图中删除,则此解决方案将无法保持正确的总和。

您可以通过将每个对象包装在代理中来增强此解决方案,但这又不能提供保证总和。

使salesPerDay字段最终确定也可能有所帮助,但是在需要总计时,没有任何东西能够保证正确地添加它们。

答案 2 :(得分:0)

首先,您需要获取地图的键集。然后使用迭代器获取商店的每个对象。然后你总是容易添加。试试这个..

     Set<String> key = shopData.keySet();
     Iterator<String> iterator = key.iterator();
     int total;
     while(iterator.hasNext()){
         Shop shop = shopData.get(iterator.next());
         total+= shop.salesPerDay;
     }
     System.out.println(total);