Java (ArrayList):按姓名对人员列表进行分组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14768550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java (ArrayList) : Grouping a list of persons by name
提问by Paulo
I have a list of persons. The person bean has the following structure :
我有一份人员名单。person bean 具有以下结构:
class Person {
private String name;
private String occupation;
/* Getters and setters*/
/* toString method */
}
This list is tored in an ArrayList<Person>
.
The problem is that when I print its data, I obtain :
这份清单被撕成一个ArrayList<Person>
. 问题是当我打印它的数据时,我得到:
Foo, scientist
Foo, teacher
Bar, student
I'd like to print it like this :
我想这样打印:
Foo, scientist, teacher
Bar, student
So, how can I group the data automatically ?
那么,如何自动对数据进行分组?
Thanks.
谢谢。
采纳答案by Daniel Kaplan
This test case passes for me:
这个测试用例对我来说通过了:
package com.sandbox;
import com.google.common.base.Joiner;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class SandboxTest {
@Test
public void testQuestionInput() {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("Foo", "scientist"));
persons.add(new Person("Foo", "teacher"));
persons.add(new Person("Bar", "student"));
String outputString = getOutputString(persons);
assertEquals("Foo, scientist, teacher\n" +
"Bar, student\n", outputString);
}
private String getOutputString(List<Person> in) {
Multimap<String, String> map = LinkedListMultimap.create();
for (Person person : in) {
map.put(person.name, person.occupation);
}
StringBuilder buf = new StringBuilder();
Joiner joiner = Joiner.on(", ");
for (String key : map.keySet()) {
buf.append(key).append(", ").append(joiner.join(map.get(key))).append("\n");
}
return buf.toString();
}
class Person {
Person(String name, String occupation) {
this.name = name;
this.occupation = occupation;
}
private String name;
private String occupation;
/* Getters and setters*/
/* toString method */
}
}
It takes the list of Persons and passes them into a Multimap. The Multimap comes from the Google guava library.
它获取 Person 列表并将它们传递给 Multimap。 Multimap 来自谷歌番石榴库。
But, you might want to use maurocchi's answer. it's much cleaner than this.
但是,您可能想使用 maurocchi 的答案。它比这干净得多。
回答by maurocchi
If you are looking for a clean library, with emaze-dysfunctionalyou can write
如果您正在寻找一个干净的图书馆,您可以编写emaze-dysfunctional
Groups.groupBy(persons, new Pluck<String, Person>(Person.class, "occupation"))
obtaining a Map<String, List<Person>>
.
获得一个Map<String, List<Person>>
.
回答by fredmanglis
That can be solved in a number of ways. I would probably use Map object, say
这可以通过多种方式解决。我可能会使用 Map 对象,说
Map<String, List<String>> occupationsByName = new LinkedHashMap<String, List<String>>(0);
I would then loop through the list of persons, using the names as keys to the Map object and initialising the List object whenever I find the key does not previously exist in the Map say,
然后我将遍历人员列表,使用名称作为 Map 对象的键,并在我发现 Map 中以前不存在该键时初始化 List 对象,例如,
for ( Iterator<String> persons = personsList.iterator(); persons.hasNext() ) {
String person = persons.next().getName();
if ( occupationsByName.containsKey( person ) ) {
occupationsByName.get( person ).add( person.getOccupation() );
} else {
occupationsByName.put(person, new ArrayList<String>(0) );
occupationsByName.get( person ).add( person.getOccupation() );
}
}
I would then add the occupations to the List under the each key, then end by finally printing out the Map.
然后我将职业添加到每个键下的列表中,然后最后打印出地图。
I have to state that I am making an assumption you know how to use the collection classes, and even if you do not, you can make use of the Java API
我必须声明我假设您知道如何使用集合类,即使您不知道,您也可以使用Java API
回答by posdef
If you have two Person
instances that have the same name but different occupation and you consider them to be the same person then you'll need to tell JVM that if two names are equal then those to people are also equal. THat you do by overriding equals()
如果您有两个Person
名称相同但职业不同的实例,并且您认为它们是同一个人,那么您需要告诉 JVM,如果两个名称相同,那么人们的名称也相同。你通过覆盖来做equals()
Now the second step is to update the list so that once you try to add a Person
which already exist in the list (i.e. there is a person that has the same name) then you add the new occupation onto the old one (e.g. by string concatenation).
现在第二步是更新列表,这样一旦你尝试添加Person
列表中已经存在的一个(即有一个同名的人)然后你将新的职业添加到旧的(例如通过字符串连接) )。
You don't need any libraries for what you want to do, just need to write complete classes. :)
您不需要任何库来完成您想要做的事情,只需要编写完整的类。:)
回答by Milan
If you want to grouping data by name. Then use "Comparator".
如果要按名称对数据进行分组。然后使用“比较器”。
For eg:
例如:
Comparator comparator = new TestComparator();
Collections.sort(listTobeSorted, comparator);
Now, We will have a sorted list in listTobeSorted.So you can print data as your wish.
现在,我们将在 listTobeSorted 中有一个排序列表。因此您可以根据需要打印数据。
//New inner Class
//新建内部类
public class TestComparator implements Comparator<Person > {
@Override
public int compare(Person o1, Person o2) {
//To write logic, Please refer the tutorial for Comparator
}
}
I hope this will help your problem.
我希望这会帮助您解决问题。
回答by Martin Nyolt
From your question I assume Persons from your Lists sharing the same name are in fact the same person. If so, you should really rethink about your data organisation. For instance, you could store, for each person, a list of occupations.
根据您的问题,我假设您列表中同名的人员实际上是同一个人。如果是这样,您真的应该重新考虑您的数据组织。例如,您可以为每个人存储一份职业列表。
class Person {
private String name;
private final List<String> occupations = new ArrayList<String>();
public boolean addOccupation(String occupation) {
return occupations.add(occupation);
}
// getters
}
Grouping persons by name is best done by using a Map instead of a List. You can then write a simple print method as follows:
最好使用 Map 而不是 List 来按姓名对人员进行分组。然后,您可以编写一个简单的打印方法,如下所示:
String personsToString(Map<String, Person> personMap) {
StringBuilder sb = new StringBuilder();
for (Person person: personMap.values())
sb.append(person.getName()).append(", ").append(person.getOccupations()).append("\n");
return sb.toString();
}