Agrupar una lista de objetos por un atributo
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.
En Java 8:
Map<String, List<Student>> studlistGrouped =
studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
Esto agregará el objeto de los estudiantes a la HashMap
clave 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.
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);
}
}
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 Optional
se 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
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]
}
}