我试图按两个属性对一大组对象进行分组。为了证明我的意思,请考虑以下示例。
public class Foo {
private String attributeA;
private String attributeB;
private String anotherAttribute;
}
我想按属性Foo
和attributeA
对attributeB
个对象进行分组。目前我做了以下事情。
List<Foo> foos = getFoos();
Map<Set<String>, List<String>> groupedFoos = Sets.newHashMap();
Set<String> fooGroup;
for(Foo foo : foos) {
fooGroup = Sets.newHashMap(foo.getAttributeA(), foo.getAttributeB());
if (!groupedFoos.containsKey(fooGroup)) {
groupedFoos.put(fooGroup, Lists.newArrayList(foo));
} else {
groupedFoos.get(fooGroup).add(foo);
}
}
如果不使用像Map
这样的Map<Set<String>, List<String>>
,我怎样才能获得相同的结果?在一次迭代中执行此操作非常重要。可以交换属性attributeA
和attributeB
的值。因此,使用Pair
作为Map
的关键字也不是一种选择。
答案 0 :(得分:3)
如果你想摆脱Map
作为关键,你总是可以用比较两种属性的方式编写自己的Key
(无论其顺序如何)。
public class Key {
private String a;
private String b;
private String c;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key foo = (Key) o;
if (a.equals(foo.a) || a.equals(foo.b)) {
return true;
}
return b.equals(foo.b) || b.equals(foo.a);
}
@Override
public int hashCode() {
int result = a.hashCode();
result = 31 * result + b.hashCode();
return result;
}
}
答案 1 :(得分:1)
为您的班级添加关键方法。
public class Foo {
private String attributeA;
private String attributeB;
private String anotherAttribute;
public final String getKey() {
return this.attributeA + "$" + this.attributeB; //use $ or any other delimiter as suggested in the comment
}
}
然后,如果您可以使用Java8,请使用下面的Collectors.groupingBy()
方法
final Map<String, List<Foo>> result = getFoos().stream().collect(Collectors.groupingBy(Foo:getKey));