Java(ArrayList):按名称对人员列表进行分组

时间:2013-02-08 08:32:37

标签: java list

我有一份人员名单。 人bean具有以下结构:

class Person {
    private String name;
    private String occupation;
    /* Getters and setters*/
    /* toString method */
}

此列表位于ArrayList<Person>。 问题是当我打印数据时,我得到:

Foo, scientist
Foo, teacher
Bar, student

我想像这样打印:

Foo, scientist, teacher
Bar, student

那么,我该如何自动分组数据呢?

感谢。

6 个答案:

答案 0 :(得分:2)

如果您正在寻找一个干净的图书馆,可以使用emaze-dysfunctional编写

Groups.groupBy(persons, new Pluck<String, Person>(Person.class, "occupation"))

获得Map<String, List<Person>>

答案 1 :(得分:1)

这可以通过多种方式解决。我可能会使用Map对象,比如说

Map<String, List<String>> occupationsByName = new LinkedHashMap<String, List<String>>(0);

然后我会循环遍历人员列表,使用名称作为Map对象的键并初始化List对象,只要我发现该键以前不存在于Map中,

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() );
    }
}

然后我会将职业添加到每个键下的List中,然后最后打印出Map。

我必须声明我假设您知道如何使用集合类,即使您没有,也可以使用Java API

答案 2 :(得分:0)

如果你有两个Person实例具有相同的名称但职业不同,并且你认为它们是同一个人那么你需要告诉JVM如果两个名字相等,那么那些人也是等于。你可以通过覆盖equals()

来做到这一点

现在第二步是更新列表,以便一旦您尝试添加列表中已存在的Person(即,有一个人具有相同的名称),那么您将新的职业添加到旧的(例如通过字符串连接)。

您不需要任何库来执行您想要的操作,只需要编写完整的类。 :)

答案 3 :(得分:0)

此测试用例传递给我:

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 */
    }

}

它接受人员列表并将其传递到Multimap。 The Multimap comes from the Google guava library.

但是,你可能想要使用maurocchi的答案。它比这更干净。

答案 4 :(得分:0)

如果要按名称对数据进行分组。然后使用“比较器”。

例如:

Comparator comparator = new TestComparator();
Collections.sort(listTobeSorted, comparator);

现在,我们将在listTobeSorted中有一个排序列表。所以你可以按照自己的意愿打印数据。

//新的内部类

public class TestComparator implements Comparator<Person > {

    @Override
    public int compare(Person o1, Person o2) {
       //To write logic, Please refer the tutorial for Comparator
    }
}

我希望这会对您的问题有所帮助。

答案 5 :(得分:0)

根据您的问题,我假设您的名单中的人员名称相同,实际上是同一个人。如果是这样,您应该重新考虑您的数据组织。 例如,您可以为每个人存储职业列表。

class Person {
    private String name;
    private final List<String> occupations = new ArrayList<String>();

    public boolean addOccupation(String occupation) {
        return occupations.add(occupation);
    }
    // getters
}

通过名称对人员进行分组最好使用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();
}