繁体   English   中英

以优雅的方式从java ArrayList聚合值

[英]Aggregating value from java ArrayList in an elegant way

我有一个对象列表,我想要聚合此对象的一个​​值,这些值按此列表中对象的其他值分组。

我正在使用我想要分组的属性作为哈希键,我正在遍历对象,所以:

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

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

这样就不会在这种情况下破坏:

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

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

MyObject holder = map.put(key, ungrouped);
if (holder != null)
    holder.setNumericProp(etc);

如果您正在优雅地解决这个问题,您可以使用lambdja库( 在此下载网站 )。 例如,您可以使用以下代码对列进行SUM化( 查看此链接 ):

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()));

使用这些库,您可以在几行中解决您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM