I'm trying to group a large list of objects by two of their attributes. To demonstrate what I mean, consider the following example.
public class Foo {
private String attributeA;
private String attributeB;
private String anotherAttribute;
}
I want to group a large list of Foo
objects by the attributes attributeA
and attributeB
. Currently I do the following.
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);
}
}
How can I achieve the same result without using a Map
like Map<Set<String>, List<String>>
? It is important to do this in one iteration. The values of the attributes attributeA
and attributeB
can be swapped. So using Pair
as the key of the Map
is also not an option.
If you want to get rid of Map
as key, you can always write your own Key
in a way that will compare both attributes (regardless of their order).
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;
}
}
Add a key method to your class.
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
}
}
Then if you can use Java8, use Collectors.groupingBy()
method like below
final Map<String, List<Foo>> result = getFoos().stream().collect(Collectors.groupingBy(Foo:getKey));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.