0

我有一个对象列表,我想聚合该对象的一个​​值,该对象的值由该列表中对象的其他值分组。

我目前正在使用要分组的属性作为哈希键,并且正在遍历该对象:

ArrayList<MyObject> raw = Some Data;
Map<String, MyObject> map = new HashMap<String, MyObject>();

for (MyObject ungrouped : raw) {
  String key = ungrouped.getStringOne().getName() + ungrouped.getStringTwo() + ungrouped.getStringThree();

  if (map.containsKey(key)){
    MyObject holder = map.get(key);
    holder.setNumericProp(holder.getNumericProp() + ungrouped.getNumericProp());
    // map.put(key, holder); //Edited after comments
  }
  else{
    map.put(key, ungrouped);
  }
}
return map.values().toArray(new MyObject[map.values().size()]);

有没有更优雅的方法可以在不使用连接字符串作为键的情况下做到这一点?

如果这是 SQL(我在几个应用层之外),它将是:

SELECT SUM(numericvalue) FROM sometable GROUP BY stringone, stringtwo , stringthree
4

2 回答 2

2

除了我在代码中看到的一些问题之外,一种解决方案是使用(如果你能负担得起的话)GuavaEquivalence(或在你的代码中复制它)。您将实现 anEquivalence<MyObject>并将 aMap<Equivalence.Wrapper<MyObject>, MyObject>用作容器;你会在你的三个字符串成员上做等价。

这将使它不会在这种情况下中断:

// Oops! Same key...
s1 = "foo", s2 = "bar", s3 = "baz"
s1 = "fooba", s2 = "rb", s3 = "az"

此外,您可以使用地图.put()方法的返回值(旧值):

MyObject holder = map.put(key, ungrouped);
if (holder != null)
    holder.setNumericProp(etc);
于 2013-06-13T13:45:28.277 回答
0

如果您看起来优雅地解决了这个问题,您可以使用lambdja 库(在此处下载网站)。例如,您可以使用以下代码对列求和(查看此链接):

double sum = sumFrom(select(sales, 
             having(on(Sale.class).getBuyer().isMale())
             .and( having(on(Sale.class).getSeller().isMale())))).getCost();

您也可以与此分组(查看此链接):

Group<Person> group = group(meAndMyFriends, by(on(Person.class).getAge()));

使用这个库,您可以用几行代码解决您的问题。

于 2013-06-13T13:47:43.470 回答