0

我有一份人员名单。person 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

那么,如何自动对数据进行分组呢?

谢谢。

4

6 回答 6

2

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

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

获得一个Map<String, List<Person>>.

于 2013-02-08T08:47:32.433 回答
1

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

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

然后,我将遍历人员列表,使用名称作为 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() );
    }
}

然后我会将职业添加到每个键下的列表中,然后最后打印出地图。

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

于 2013-02-08T09:00:40.930 回答
0

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

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

你不需要任何库来做你想做的事,只需要编写完整的类。:)

于 2013-02-08T08:38:07.663 回答
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 */
    }

}

它获取 Person 列表并将它们传递给 Multimap。 Multimap 来自 Google guava 库。

但是,您可能想使用 maurocchi 的答案。它比这干净得多。

于 2013-02-08T08:49:41.370 回答
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
    }
}

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

于 2013-02-08T08:53:27.513 回答
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();
}
于 2013-02-08T08:58:47.723 回答