我有一个像这样的简单对象
public class Person{
private int id;
private int age;
private String hobby;
//getters, setters
}
我想按属性
对Person
列表进行分组
输出应该是这样的
Person count/Age/Hobby
2/18/Basket
5/20/football
使用图表了解更多
X轴:爱好重新分配 Y轴:人员分布计数
颜色代表年龄
我设法使用地图按一个属性分组,但我无法计算如何按多个属性进行分组
//group only by age . I want to group by hobby too
personMapGroupped = new LinkedHashMap<String, List<Person>>();
for (Person person : listPerson) {
String key = person.getAge();
if (personMapGroupped.get(key) == null) {
personMapGroupped.put(key, new ArrayList<Person>());
}
personMapGroupped.get(key).add(person);
}
然后我像这样检索可分组对象
for (Map.Entry<String, List<Person>> entry : personMapGroupped .entrySet()) {
String key = entry.getKey();// group by age
String value = entry.getValue(); // person count
// i want to retieve the group by hobby here too...
}
任何建议都将不胜感激。 非常感谢你
答案 0 :(得分:2)
实施根据不同领域比较人的方法。例如,如果您想按年龄分组,请将此方法添加到Person
:
public static Comparator<Person> getAgeComparator(){
return new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
};
}
然后,您只需致电:Arrays.sort(people,Person.getAgeComparator())
或使用以下代码对Collection
进行排序:
List<Person> people = new ArrayList<>();
people.sort(Person.getAgeComparator());
要同时使用多个Comparator
进行排序,首先要为每个字段定义Comparator
(例如,一个用于年龄,一个用于名称)。然后,您可以使用ComparatorChain
将它们组合在一起。您可以使用ComparatorChain
,如下所示:
ComparatorChain chain = new ComparatorChain();
chain.addComparator(Person.getNameComparator());
chain.addComparator(Person.getAgeComparator());
答案 1 :(得分:2)
您可以简单地将属性组合到一个键。
for (Person person : listPerson) {
String key = person.getAge() + ";" + person.getHobby();
if (!personMapGrouped.contains(key)) {
personMapGrouped.put(key, new ArrayList<Person>());
}
personMapGrouped.get(key).add(person);
}
使用personMapGrouped.get("18;Football").getSize()
可以轻松确定条目数。
答案 2 :(得分:2)
我不确定您的要求,但我可能会使用多个地图(Google Guava&#39; Multimap
会使bww更容易)并设置,例如像这样的东西:
//I'm using a HashMultimap since order of persons doesn't seem to be relevant and I want to prevent duplicates
Multimap<Integer, Person> personsByAge = HashMultimap.create();
//I'm using the hobby name here for simplicity, it's probably better to use some enum or Hobby object
Multimap<String, Person> personsByHobby = HashMultimap.create();
//fill the maps here by looping over the persons and adding them (no need to create the value sets manually
由于我使用值集Person
需要equals()
和hashCode()
的合理实施,这可能会使用id
字段。这也有助于查询。
构建子集非常简单:
Set<Person> age18 = personsByAge.get(18);
Set<Person> basketballers = personsByHobby.get( "basketball" );
//making use of Guava again
Set<Person> basketballersAged18 = Sets.intersection( age18, basketballers );
请注意,我在此处使用了Google Guava,但您可以通过一些额外的手动代码实现相同的功能(例如,使用Map<String, Set<Person>>
并手动创建值集以及使用Set.retainAll()
方法)。