2011-03-21 16 views
17

estoy tratando de objetos Java grupo por su campo, es decir Person.javapor nombre de campo en Java

public class Person { 
    String name; 
    String surname; 
    .... 
} 

Así que si tengo n objetos Persona, ¿cuál sería la forma más fácil hacer que todas las personas nombren "David" en un mapa como Map<String, List<Person>> map;?

He encontrado esto en Google (pero no compila), que parece ser lo que estoy buscando: http://www.anzaan.com/2010/06/grouping-objects-using-objects-property/

+2

¿Qué dice el error de compilación? – MBU

Respuesta

53

Probablemente hay una biblioteca que puede hacerlo más simple, pero no es demasiado difícil de hacerlo manualmente:

List<Person> allPeople; // your list of all people 
Map<String, List<Person>> map = new HashMap<String, List<Person>>(); 
for (Person person : allPeople) { 
    String key = person.getName(); 
    if (map.get(key) == null) { 
     map.put(key, new ArrayList<Person>()); 
    } 
    map.get(key).add(person); 
} 

List<Person> davids = map.get("David"); 
+3

Eres rápido +1 –

+0

Pero la pregunta era sobre una solución general, donde solo especificas el nombre de una clase, por lo que pasarías a personas: = Lista de Persona, y "nombre" como el nombre del campo, y la función haría el resto. En el siguiente caso, pasa una lista de autos y un nombre de campo "manufactor". En scala, simplemente debe llamar a persons.filter (p => p.name == "David") o agrupar en la lista. –

+4

pobre gente de Java ... nunca sabrá las alegrías de LINQ :) –

4

algo así (no me compilar)

void addPerson(Person p, Map<String, List<Person>> map){ 
    ArrayList<Person> lst = map.get(p.name); 
    if(lst == null){ 
    lst = new ArrayList<Person>(); 
    } 
    lst.add(p); 
    map.put(p.name, lst); 
} 
... 
for(Person p:personsCollection>){ 
    addPerson(p, map); 
} 
-1

en primer lugar se debe añadir objetos de la persona. java en el ArrayList después nos puede volver esos detalles a continuación de manera

addPerson public void() {

ArrayList presonList = new ArrayList();

for (int i = 0; i < = presonList.size(); i ++) {

persona obj = presonList.get (i);

// ahora hacer las cosas de conseguir variable individual aquí

}

}

1

En Scala, esta es una característica de la Lista de clase ya:

class Person (val name: String, val surname: String ="Smith") 
val li = List (new Person ("David"), new Person ("Joe"), new Person ("Sue"), new Person ("David", "Miller")) 
li.groupBy (_.name) 

res87: scala.collection.immutable.Map [Str ing, List [Person]] = Mapa ((David, List (Person @ 1c3f810, Person @ 139ba37)), (Sue, List (Person @ 11471c6)), (Joe, List (Person @ d320e4)))

Como Scala es compatible con bytecode para Java, debería poder llamar a ese método desde Java, si incluye los scala-jar.

11

Google Guava 's Multimapa hace exactamente lo que necesita y mucho más, evitando mucho código repetitivo:

ListMultimap<String, Person> peopleByFirstName = ArrayListMultimap.create(); 
for (Person person : getAllPeople()) { 
    peopleByFirstName.put(person.getName(), person); 
} 

Fuente: http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap

+1

Un hecho realmente útil sería decirle a las personas que llamen 'asMap()' al resultado. 'keys()', 'entries()' y 'values ​​()' no parecen agruparse como cabría esperar. –

26

Usando con la clase y streamsCollectors, usted puede hacer esto:

Map<String, List<Person>> mapByName = 
    allPeople.stream().collect(Collectors.groupingBy(Person::getName)); 

List<Person> allDavids = mapByName.getOrDefault("David", Collections.emptyList()); 

Aquí solía getOrDefault para que obtenga una lista inmutable vacía en lugar de una referencia null si no hay "David" en la lista original, pero puede usar get si prefiere tener un valor null.

Espero que ayude! :)

+0

¿Es posible no usar un captador, pero usar directamente el nombre del campo? –

+1

@ZhangMeng Sí, en este caso usaría lambda 'p -> p.name', suponiendo que puede acceder al campo' name'. –

1

Puede utilizar Multimap y groupBy() de Eclipse Collections

MutableList<Person> allPeople = Lists.mutable.empty(); 
MutableListMultimap<String, Person> multimapByName = allPeople.groupBy(Person::getName); 

Si no puede cambiar el tipo de allPeople de List

List<Person> allPeople = new ArrayList<>(); 
MutableListMultimap<String, Person> multimapByName = 
    ListAdapter.adapt(allPeople).groupBy(Person::getName); 

Nota: Soy un contribuyente a Eclipse Colecciones.

Cuestiones relacionadas