【问题标题】:Sum of List<Integer, Integer> elements in JavaJava 中 List<Integer, Integer> 元素的总和
【发布时间】:2015-03-20 10:15:58
【问题描述】:

我有一个ArrayList,其中包含一些Integer values 作为Pairs。我想对 List 中左侧元素相同的 right 元素求和。

例如,输入的arrayList将包含:

final List<Pair<Integer, Integer>> a = new ArrayList<>();
a.add(new Pair<>(1, 1));
a.add(new Pair<>(2, 1));
a.add(new Pair<>(2, 3));

New ArrayList should contain:

如下图:

(普通左值,左值相同的所有右值之和)

1, 1
2, 4

我编写的代码不返回有效值:

for (int i=0; i< a.size(); i++){


        //need help here
}

编辑:我想要重复的对,所以 HashMap 不起作用。

抱歉修改。

【问题讨论】:

  • 您可以使用HashMap&lt;Integer, Integer&gt; 并对键的值求和。
  • 他可能想要重复的键值对。
  • 我想要重复的键值对,所以 hashmap 不起作用
  • 这个问题没有说明结果中那些重复的键值对。事实上,提供的描述和示例表明结果不应包含重复项。 (“常见的左值,左值相同的所有右值的总和” - 结果中有重复项将不符合该要求)
  • 重复处理还不清楚。如果您的结果包含(3,10)(3,10),那不应该从一开始就合并为(3,20) 吗?

标签: java search arraylist


【解决方案1】:

看起来你需要一些被黑的HashMap,它将对值求和而不是替换它们:

class SummingMap extends HashMap<Integer, Integer> {
    @Override
    public Integer put(Integer key, Integer value) {
        Integer oldResult = get(key);
        return super.put(key, value + (oldResult == null ? 0 : oldResult));
    }
}

如果您希望您的条目按键排序,您应该使用某种SortedMap,例如TreeMap

class SummingMap extends TreeMap<Integer, Integer> {
   ... // the same code as above

【讨论】:

  • @cp101020304 好的,现在?
  • 完美。谢谢你。您将如何根据键和值对其进行排序?
  • @cp101020304 如果键是唯一的(并且它们在任何Map 中),那么您不应该知道按值排序。所以,你所需要的只是SortedMap 的王者,默认情况下它会按键对元素进行排序。我会更新答案以反映这一变化。
【解决方案2】:

您的问题是您只在循环中添加了两个元素,它们适用于 1 但不适用于 2。相反,您应该使用一个映射,其键为第一个数字(在您的情况下为 1 或 2),值为总和。

然后您独立地遍历两个列表,获取左侧数字的当前值,将右侧数字添加到其中并将结果放回地图中。如果还没有值,则假设为 0。

类似这样的:

Map<Integer, Integer> sums = new HashMap<>();

for( Pair<> p : a ) {
  Integer sum = sums.get(p.left);
  if( sum == null ) {
    sums.put( p.left, p.right ); //nothing there yet, so just add the first value
  } else {
    sums.put( p.left, sum + p.right ); //add to the existing sum
  }
}

//do the same for b

最后遍历地图并根据需要构建新的配对列表。

如果您还需要获取原始对,请创建一个容器对象用作包含总和的值以及对该总和有贡献的对的列表。我将把代码留给你作为练习。

【讨论】:

  • @cp101020304 您希望它们出现在结果中吗?如果是这样,您绝对应该扩展您的问题。如果它们只能在输入列表中,那么这是可能的。
【解决方案3】:

使用 org.springframework.util.MultiValueMap:

List<Pair<Integer, Integer>> result = new ArrayList<>();

a.addAll(b); //now there is only one list

//key -> Integer, value -> List<Integer>
MultiValueMap<Integer, Integer> values = new LinkedMultiValueMap<Integer, Integer>();

for (Pair p : a) 
    values.add(p.left, p.right);

for (Integer key : values.keySet()) {
    Integer sum = 0;
    for (Integer right : values.get(key))
        sum += right;
    result.add(new Pair(key, sum));
}

【讨论】:

  • 嗨,MultiValueMap 有替代品吗?
  • 在内部,这个数据结构是Spring开发者实现的Map&lt;T, List&lt;T&gt;&gt;add(key, value) 方法将value 附加到data[key](即一个列表)。您不必关心List 初始化或那些东西。我建议你使用它。
  • @cp101020304 作为替代方案,您可以使用不同风格的 Google Guava 的 Multimap。但除了来自不同的图书馆之外,这个概念是相同的。
【解决方案4】:

这是未经测试的代码,但应该会给你一个想法

HashMap<Integer, Integer> result = new HashMap<Integer, Integer>();
List<Pair<Integer, Integer>> list = new ArrayList<Pair<Integer, Integer>>();

for (Pair p : a)
  if (result.containsValue(p.left)) 
    result.put(p.left, p.right +result.get(p.left)); // add if existing
  else
    result.put(p.left, p.right);                     // assign if not existing 

for (Pair p : b)
  if (result.containsValue(p.left)) 
    result.put(p.left, p.right +result.get(p.left));
  else
    result.put(p.left, p.right);   

p.s.(根据评论):将新对添加到列表中:

for (Pair p : a)
  list.add(new Pair(p.left, result.get(p.left)));

for (Pair p : b)
  list.add(new Pair(p.left, result.get(p.left)));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-14
    • 2014-05-04
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    相关资源
    最近更新 更多