Agrupar una lista de objetos por un atributo

Resuelto Dilukshan Mahendra asked hace 10 años • 13 respuestas

Necesito agrupar una lista de objetos ( Student) usando un atributo ( Location) del objeto en particular. El código es como el siguiente:

public class Grouping {
    public static void main(String[] args) {

        List<Student> studlist = new ArrayList<Student>();
        studlist.add(new Student("1726", "John", "New York"));
        studlist.add(new Student("4321", "Max", "California"));
        studlist.add(new Student("2234", "Andrew", "Los Angeles"));
        studlist.add(new Student("5223", "Michael", "New York"));
        studlist.add(new Student("7765", "Sam", "California"));
        studlist.add(new Student("3442", "Mark", "New York"));

    }
}

class Student {
    String stud_id;
    String stud_name;
    String stud_location;

    Student(String sid, String sname, String slocation) {
        this.stud_id = sid;
        this.stud_name = sname;
        this.stud_location = slocation;
    }
}

Por favor sugiérame una forma limpia de hacerlo.

Dilukshan Mahendra avatar Feb 10 '14 20:02 Dilukshan Mahendra
Aceptado

En Java 8:

Map<String, List<Student>> studlistGrouped =
    studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
Vitalii Fedorenko avatar May 12 '2015 21:05 Vitalii Fedorenko

Esto agregará el objeto de los estudiantes a la HashMapclave locationID.

HashMap<Integer, List<Student>> hashMap = new HashMap<Integer, List<Student>>();

Repita este código y agregue estudiantes a HashMap:

if (!hashMap.containsKey(locationId)) {
    List<Student> list = new ArrayList<Student>();
    list.add(student);

    hashMap.put(locationId, list);
} else {
    hashMap.get(locationId).add(student);
}

Si desea que todos los estudiantes tengan detalles de ubicación particulares, puede usar esto:

hashMap.get(locationId);

lo que le permitirá obtener todos los estudiantes con la misma identificación de ubicación.

Dileep avatar Feb 10 '2014 13:02 Dileep
Map<String, List<Student>> map = new HashMap<String, List<Student>>();

for (Student student : studlist) {
    String key  = student.stud_location;
    if(map.containsKey(key)){
        List<Student> list = map.get(key);
        list.add(student);

    }else{
        List<Student> list = new ArrayList<Student>();
        list.add(student);
        map.put(key, list);
    }

}
sampath challa avatar Feb 10 '2014 13:02 sampath challa

Agrupación de Java 8 por recopilador

Probablemente sea tarde pero me gustaría compartir una idea mejorada para este problema. Esto es básicamente lo mismo que la respuesta de @Vitalii Fedorenko, pero es más útil para jugar.

Puede usar simplemente Collectors.groupingBy()pasando la lógica de agrupación como parámetro de función y obtendrá la lista dividida con la asignación de parámetros clave. Tenga en cuenta que el uso Optionalse utiliza para evitar NPE no deseados cuando la lista proporcionada esnull

public static <E, K> Map<K, List<E>> groupBy(List<E> list, Function<E, K> keyFunction) {
    return Optional.ofNullable(list)
            .orElseGet(ArrayList::new)
            .stream()
            .collect(Collectors.groupingBy(keyFunction));
}

Ahora puedes agrupar por cualquier cosa con esto. Para el caso de uso aquí en la pregunta

Map<String, List<Student>> map = groupBy(studlist, Student::getLocation);

Quizás también le gustaría consultar esta Guía para agrupar Java 8 por recopilador

Shafin Mahmud avatar Dec 03 '2019 12:12 Shafin Mahmud

Usando Java 8

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class Student {

    private String stud_id;
    private String stud_name;
    private String stud_location;

    public String getStud_id() {
        return stud_id;
    }

    public String getStud_name() {
        return stud_name;
    }

    public String getStud_location() {
        return stud_location;
    }



    Student(String sid, String sname, String slocation) {

        this.stud_id = sid;
        this.stud_name = sname;
        this.stud_location = slocation;

    }
}

class Temp
{
    public static void main(String args[])
    {

        Stream<Student> studs = 
        Stream.of(new Student("1726", "John", "New York"),
                new Student("4321", "Max", "California"),
                new Student("2234", "Max", "Los Angeles"),
                new Student("7765", "Sam", "California"));
        Map<String, Map<Object, List<Student>>> map= studs.collect(Collectors.groupingBy(Student::getStud_name,Collectors.groupingBy(Student::getStud_location)));
                System.out.println(map);//print by name and then location
    }

}

El resultado será:

{
    Max={
        Los Angeles=[Student@214c265e], 
        California=[Student@448139f0]
    }, 
    John={
        New York=[Student@7cca494b]
    }, 
    Sam={
        California=[Student@7ba4f24f]
    }
}
Chirag avatar Apr 15 '2016 06:04 Chirag