Java 按多个字段对列表中的对象分组
我有一个像这样的简单物体Java 按多个字段对列表中的对象分组,java,dictionary,grouping,Java,Dictionary,Grouping,我有一个像这样的简单物体 public class Person { private int id; private int age; private String hobby; //getters, setters } Person count/Age/Hobby 2/18/Basket 5/20/football for (Map.Entry<String, List<Person>> entry : personMapGroupped .entry
public class Person {
private int id;
private int age;
private String hobby;
//getters, setters
}
Person count/Age/Hobby
2/18/Basket
5/20/football
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 retrieve the group by hobby here too...
}
我想按属性对人员的列表进行分组
//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);
}
输出应该是这样的
public class Person {
private int id;
private int age;
private String hobby;
//getters, setters
}
Person count/Age/Hobby
2/18/Basket
5/20/football
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 retrieve the group by hobby here too...
}
用图表来加深理解
X轴:爱好重新分区
Y轴:人员分布计数
颜色代表年龄
我设法使用map按一个属性分组,但我不知道如何按多个属性分组
//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);
}
//仅按年龄分组。我也想按爱好分组
personMapGroupped=新建LinkedHashMap();
for(个人:listPerson){
String key=person.getAge();
if(personMapGroupped.get(key)==null){
put(key,newarraylist());
}
personMapGroupped.get(key).add(person);
}
然后像这样检索可分组对象
public class Person {
private int id;
private int age;
private String hobby;
//getters, setters
}
Person count/Age/Hobby
2/18/Basket
5/20/football
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 retrieve the group by hobby here too...
}
for(Map.Entry:personMapGroupped.entrySet()){
String key=entry.getKey();//按年龄分组
String value=entry.getValue();//人数
//我也想在这里通过爱好来找回这个团体。。。
}
如有任何建议,将不胜感激
非常感谢根据不同领域实施人员比较方法。例如,如果要按年龄分组,请将此方法添加到Person
:
public static Comparator<Person> getAgeComparator(){
return new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
};
}
List<Person> people = new ArrayList<>();
people.sort(Person.getAgeComparator());
要同时使用多个比较器进行排序
,首先为每个字段定义一个比较器
(例如,一个用于年龄,一个用于姓名)。然后,您可以使用一个组合键将它们组合在一起。您可以按如下方式使用ComparatorChain
:
ComparatorChain chain = new ComparatorChain();
chain.addComparator(Person.getNameComparator());
chain.addComparator(Person.getAgeComparator());
您可以简单地将属性组合到一个键
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);
}
for(个人:listPerson){
字符串键=person.getAge()+“;”+person.getHobby();
如果(!personMapGrouped.contains(键)){
put(key,newarraylist());
}
personMapGrouped.get(key).add(person);
}
通过使用personMapGrouped.get(“18;Football”).getSize()
我不确定您的要求,但我可能会使用多个地图(Google Guava的Multimap
会让这更容易)和设置,例如:
//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
请注意,我在这里使用了Google Guava,但您可以通过一些额外的手动代码(例如,使用Map
和手动创建值集以及使用Set.retainal()
方法)实现相同的功能。实现可比较的界面,然后对列表排序分组应该如何工作?是否应按单个属性(即每个属性一张地图)、属性组合(即组合地图键)或属性层次(例如先按年龄,然后按爱好)对人员进行分组?@Thomas非常感谢。组合将非常好(例如:PersonCount/Age/Hobby,因为稍后我需要将它们放入for循环中。我编辑了我的答案。不幸的是,您的编辑没有让它更清晰。您是否希望按年龄获得人数,然后按爱好分组,例如“所有18岁的人,所有喜欢打篮球的人”?或者你想让所有人的爱好独立于他们的年龄吗?你需要用Java做这件事有什么原因吗?这是一件你可能会发现使用数据库容易得多的事情。谢谢,我不知道这个Google Guava库,它方便了很多事情。但是我仍然很难在我的案例中使用它。我更新了它带一张代表所需输出的图表。请look@ulquiorra这应该不太难实现。只要根据需要将数据分成单独的子集(即爱好和年龄),并获得这些子集的交点大小作为条形图的数据。毕竟,您仍然需要6个单独的值。