按属性对对象列表进行分组

我需要使用特定对象的属性(Location)对对象列表(Student)进行分组。代码如下:

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

请给我一个干净利落的建议。

302387 次浏览

你可以这样做:

Map<String, List<Student>> map = new HashMap<String, List<Student>>();
List<Student> studlist = new ArrayList<Student>();
studlist.add(new Student("1726", "John", "New York"));
map.put("New York", studlist);

键将是位置和学生的价值观列表。因此,稍后你可以得到一组学生,只需使用:

studlist = map.get("New York");

这将把学生对象添加到以 locationID为键的 HashMap

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

迭代 这段代码并将学生添加到 HashMap:

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


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

如果你希望所有的学生都有特定的位置信息,那么你可以使用这个:

hashMap.get(locationId);

这样所有学生的地址都一样。

你可以这样分类:

    Collections.sort(studlist, new Comparator<Student>() {


@Override
public int compare(Student o1, Student o2) {
return o1.getStud_location().compareTo(o2.getStud_location());
}
});

假设您在 Student 类上也有位置的 getter 函数。

你可使用以下连结:

Map<String, List<Student>> groupedStudents = new HashMap<String, List<Student>>();
for (Student student: studlist) {
String key = student.stud_location;
if (groupedStudents.get(key) == null) {
groupedStudents.put(key, new ArrayList<Student>());
}
groupedStudents.get(key).add(student);
}

//打印

Set<String> groupedStudentsKeySet = groupedCustomer.keySet();
for (String location: groupedStudentsKeySet) {
List<Student> stdnts = groupedStudents.get(location);
for (Student student : stdnts) {
System.out.println("ID : "+student.stud_id+"\t"+"Name : "+student.stud_name+"\t"+"Location : "+student.stud_location);
}
}
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);
}


}

使用比较器在 Java 中实现 SQLGROUPBY 特性,比较器将比较您的列数据,并对其进行排序。基本上,如果你保持排序数据,看起来像分组数据,例如,如果你有相同的重复列数据,然后排序机制排序他们保持相同的数据一边,然后寻找其他数据是不同的数据。这被间接地视为相同数据的 GROUPING。

public class GroupByFeatureInJava {


public static void main(String[] args) {
ProductBean p1 = new ProductBean("P1", 20, new Date());
ProductBean p2 = new ProductBean("P1", 30, new Date());
ProductBean p3 = new ProductBean("P2", 20, new Date());
ProductBean p4 = new ProductBean("P1", 20, new Date());
ProductBean p5 = new ProductBean("P3", 60, new Date());
ProductBean p6 = new ProductBean("P1", 20, new Date());


List<ProductBean> list = new ArrayList<ProductBean>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
list.add(p6);


for (Iterator iterator = list.iterator(); iterator.hasNext();) {
ProductBean bean = (ProductBean) iterator.next();
System.out.println(bean);
}
System.out.println("******** AFTER GROUP BY PRODUCT_ID ******");
Collections.sort(list, new ProductBean().new CompareByProductID());
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
ProductBean bean = (ProductBean) iterator.next();
System.out.println(bean);
}


System.out.println("******** AFTER GROUP BY PRICE ******");
Collections.sort(list, new ProductBean().new CompareByProductPrice());
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
ProductBean bean = (ProductBean) iterator.next();
System.out.println(bean);
}
}
}


class ProductBean {
String productId;
int price;
Date date;


@Override
public String toString() {
return "ProductBean [" + productId + " " + price + " " + date + "]";
}
ProductBean() {
}
ProductBean(String productId, int price, Date date) {
this.productId = productId;
this.price = price;
this.date = date;
}
class CompareByProductID implements Comparator<ProductBean> {
public int compare(ProductBean p1, ProductBean p2) {
if (p1.productId.compareTo(p2.productId) > 0) {
return 1;
}
if (p1.productId.compareTo(p2.productId) < 0) {
return -1;
}
// at this point all a.b,c,d are equal... so return "equal"
return 0;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}


class CompareByProductPrice implements Comparator<ProductBean> {
@Override
public int compare(ProductBean p1, ProductBean p2) {
// this mean the first column is tied in thee two rows
if (p1.price > p2.price) {
return 1;
}
if (p1.price < p2.price) {
return -1;
}
return 0;
}
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}


class CompareByCreateDate implements Comparator<ProductBean> {
@Override
public int compare(ProductBean p1, ProductBean p2) {
if (p1.date.after(p2.date)) {
return 1;
}
if (p1.date.before(p2.date)) {
return -1;
}
return 0;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}
}

上面的 ProductBean 列表是 GROUP BY 条件,如果你看到输入数据列表 ProductBean to Collections.sort (列表,比较器对象,为您所需的列)这将排序基于您的比较器实现,您将能够看到 GROUPED 数据在下面的输出。希望这个能帮上忙。

******** BEFORE GROUPING INPUT DATA LOOKS THIS WAY ******
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 30 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P2 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P3 60 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
******** AFTER GROUP BY PRODUCT_ID ******
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 30 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P2 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P3 60 Mon Nov 17 09:31:01 IST 2014]


******** AFTER GROUP BY PRICE ******
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P2 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 20 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P1 30 Mon Nov 17 09:31:01 IST 2014]
ProductBean [P3 60 Mon Nov 17 09:31:01 IST 2014]


在 Java 8中:

Map<String, List<Student>> studlistGrouped =
studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));

使用 爪哇8

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


class Student {


String stud_id;
String stud_name;
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
}


}

结果将是:

{
Max={
Los Angeles=[Student@214c265e],
California=[Student@448139f0]
},
John={
New York=[Student@7cca494b]
},
Sam={
California=[Student@7ba4f24f]
}
}

你可以使用 guavaMultimaps

@Canonical
class Persion {
String name
Integer age
}
List<Persion> list = [
new Persion("qianzi", 100),
new Persion("qianzi", 99),
new Persion("zhijia", 99)
]
println Multimaps.index(list, { Persion p -> return p.name })

它打印:

【钱子: [ com.ctcf.message. Persion (线子,100) ,com.ctcf.message. Persion (线子,88)] ,知家: [ com.ctcf.message. Persion (线家,99)]

Function<Student, List<Object>> compositKey = std ->
Arrays.asList(std.stud_location());
studentList.stream().collect(Collectors.groupingBy(compositKey, Collectors.toList()));

如果你想为 group 添加多个对象,你可以简单地在 compositKey方法中添加对象,用逗号分隔:

Function<Student, List<Object>> compositKey = std ->
Arrays.asList(std.stud_location(),std.stud_name());
studentList.stream().collect(Collectors.groupingBy(compositKey, Collectors.toList()));
public class Test9 {


static class Student {


String stud_id;
String stud_name;
String stud_location;


public Student(String stud_id, String stud_name, String stud_location) {
super();
this.stud_id = stud_id;
this.stud_name = stud_name;
this.stud_location = stud_location;
}


public String getStud_id() {
return stud_id;
}


public void setStud_id(String stud_id) {
this.stud_id = stud_id;
}


public String getStud_name() {
return stud_name;
}


public void setStud_name(String stud_name) {
this.stud_name = stud_name;
}


public String getStud_location() {
return stud_location;
}


public void setStud_location(String stud_location) {
this.stud_location = stud_location;
}


@Override
public String toString() {
return " [stud_id=" + stud_id + ", stud_name=" + stud_name + "]";
}


}


public static void main(String[] args) {


List<Student> list = new ArrayList<Student>();
list.add(new Student("1726", "John Easton", "Lancaster"));
list.add(new Student("4321", "Max Carrados", "London"));
list.add(new Student("2234", "Andrew Lewis", "Lancaster"));
list.add(new Student("5223", "Michael Benson", "Leeds"));
list.add(new Student("5225", "Sanath Jayasuriya", "Leeds"));
list.add(new Student("7765", "Samuael Vatican", "California"));
list.add(new Student("3442", "Mark Farley", "Ladykirk"));
list.add(new Student("3443", "Alex Stuart", "Ladykirk"));
list.add(new Student("4321", "Michael Stuart", "California"));


Map<String, List<Student>> map1  =


list
.stream()


.sorted(Comparator.comparing(Student::getStud_id)
.thenComparing(Student::getStud_name)
.thenComparing(Student::getStud_location)
)


.collect(Collectors.groupingBy(


ch -> ch.stud_location


));


System.out.println(map1);


/*
Output :


{Ladykirk=[ [stud_id=3442, stud_name=Mark Farley],
[stud_id=3443, stud_name=Alex Stuart]],


Leeds=[ [stud_id=5223, stud_name=Michael Benson],
[stud_id=5225, stud_name=Sanath Jayasuriya]],




London=[ [stud_id=4321, stud_name=Max Carrados]],




Lancaster=[ [stud_id=1726, stud_name=John Easton],


[stud_id=2234, stud_name=Andrew Lewis]],




California=[ [stud_id=4321, stud_name=Michael Stuart],
[stud_id=7765, stud_name=Samuael Vatican]]}
*/




}// main
}

Java8 groupingBy Collector

也许现在已经很晚了,但是我想和大家分享一个关于这个问题的更好的想法。这和@Vitalii Fedorenko 的回答基本相同,但是更容易操作。

只需将分组逻辑作为函数参数传递,就可以使用 Collectors.groupingBy(),并且将获得带有键参数映射的拆分列表。注意,当提供的列表为 null时,使用 Optional可以避免不需要的 NPE

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

现在你可以用这个 GroupBy任何东西

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

也许你想看看这也 Java8 groupingBy Collector 指南

  @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeyValuePair<?, ?> that = (KeyValuePair<?, ?>) o;
return Objects.equals(key, that.key) && Objects.equals(value, that.value);
}


@Override
public int hashCode() {
return Objects.hash(key, value);
}