จัดกลุ่มรายการวัตถุตามแอตทริบิวต์


102

ฉันต้องการจัดกลุ่มรายการของวัตถุ ( Student) โดยใช้แอตทริบิวต์ ( Location) ของวัตถุนั้น ๆ รหัสเป็นดังนี้:

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

โปรดแนะนำวิธีทำที่สะอาดให้ฉัน


2
แฮชแมปที่มีตำแหน่งเป็นคีย์และรายการนักเรียนเป็นค่า
Omoro

การจัดเรียงตามสถานที่ตั้งจะช่วยแก้ปัญหาของคุณได้หรือมีอย่างอื่นอีกไหม
Warlord

ลองใช้ตัวเปรียบเทียบและจัดเรียงตามสถานที่
pshemek

1
@Warlord ใช่ แต่จะไปไกลกว่านี้ถ้าฉันต้องการข้อมูลเช่นจำนวนนักเรียนตามสถานที่ตั้งจะดีกว่าถ้าฉันสามารถจัดกลุ่มได้
Dilukshan Mahendra

@Omoro ได้โปรดให้เบาะแสด้วยรหัสฉันไม่ค่อยคุ้นเคยกับ Hashmaps
Dilukshan Mahendra

คำตอบ:


132

สิ่งนี้จะเพิ่มวัตถุนักเรียนลงในคีย์HashMapด้วยlocationIDas

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

ซึ่งจะทำให้นักเรียนทุกคนมีรหัสสถานที่เดียวกัน


4
คุณได้ประกาศรายการวัตถุที่ตั้งและในบรรทัดถัดไปคุณจะเพิ่มวัตถุนักเรียนในรายการก่อนหน้าซึ่งควรทำให้เกิดข้อผิดพลาด
OJVM

hashMap.get () คืนค่า null เมื่อ hashMap.contanisKey () ส่งคืนเท็จ คุณสามารถบันทึกการโทรไปยังเมธอด containsKey () ได้หากคุณเรียก hashMap.get () เป็นครั้งแรกเก็บผลลัพธ์ใน var ท้องถิ่นและตรวจสอบว่าตัวแปรท้องถิ่นนี้เป็นโมฆะหรือไม่
Esteve

259

ใน Java 8:

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

นั่นเป็นเพราะในStudentชั้นเรียนstud_locationระบุว่าเป็นมิตร เฉพาะStudentคลาสและคลาสใด ๆ ที่กำหนดไว้ในแพ็คเกจเดียวกันStudentเท่านั้นที่สามารถเข้าถึงstud_locationได้ หากคุณใส่public String stud_location;แทนString stud_location;สิ่งนี้ควรใช้งานได้ หรือคุณสามารถกำหนดฟังก์ชัน getter ข้อมูลเพิ่มเติมในcs.princeton.edu/courses/archive/spr96/cs333/java/tutorial/java/…
Eranga Heshan

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

}

8

ใช้Java 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]
    }
}

คำตอบนี้สามารถปรับปรุงได้โดยยึดติดกับตัวอย่างเดียวกับคำถาม นอกจากนี้ผลลัพธ์ยังไม่ตรงกับผลลัพธ์ที่ต้องการในคำถาม
Pim Hazebroek

6

การจัดกลุ่ม Java 8 โดย Collector

อาจจะสายไปแล้ว แต่ฉันต้องการแบ่งปันแนวคิดที่ได้รับการปรับปรุงสำหรับปัญหานี้ โดยพื้นฐานแล้วนี่คือคำตอบของ @Vitalii Fedorenko แต่เล่นได้คล่องกว่า

คุณสามารถใช้Collectors.groupingBy()โดยส่งลอจิกการจัดกลุ่มเป็นพารามิเตอร์ฟังก์ชันและคุณจะได้รับรายการที่แยกจากการแมปพารามิเตอร์หลัก โปรดทราบว่าการใช้Optionalจะใช้เพื่อหลีกเลี่ยง NPE ที่ไม่ต้องการเมื่อรายการที่ให้มาคือnull

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

ตอนนี้คุณสามารถจัดกลุ่มตามอะไรก็ได้ด้วยสิ่งนี้ สำหรับกรณีการใช้งานที่นี่ในคำถาม

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

บางทีคุณอาจต้องการดูสิ่งนี้ด้วยGuide to Java 8 groupingBy Collector


4

คุณสามารถใช้สิ่งต่อไปนี้:

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

4

ใช้คุณลักษณะ SQL GROUP BY ใน Java โดยใช้ตัวเปรียบเทียบตัวเปรียบเทียบจะเปรียบเทียบข้อมูลคอลัมน์ของคุณและเรียงลำดับ โดยทั่วไปหากคุณเก็บข้อมูลที่จัดเรียงซึ่งมีลักษณะเป็นข้อมูลที่จัดกลุ่มไว้เช่นหากคุณมีข้อมูลคอลัมน์ที่ซ้ำกันกลไกการเรียงลำดับจะจัดเรียงข้อมูลโดยเก็บข้อมูลเดียวกันไว้ด้านหนึ่งจากนั้นมองหาข้อมูลอื่นที่เป็นข้อมูลที่แตกต่างกัน สิ่งนี้ถูกมองโดยอ้อมว่าเป็นการจัดกลุ่มข้อมูลเดียวกัน

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 ไปยัง Collections.sort (รายการวัตถุของตัวเปรียบเทียบสำหรับคอลัมน์ที่คุณต้องการ) สิ่งนี้จะจัดเรียงตามการใช้งานตัวเปรียบเทียบของคุณ และคุณจะสามารถดูข้อมูล GROUPED ในเอาต์พุตด้านล่าง หวังว่านี่จะช่วยได้ ...

    ******** ก่อนที่จะจัดกลุ่มข้อมูลอินพุตให้มองหาวิธีนี้ ******
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 30 จ. พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P2 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P3 60 จ. 17 พ.ย. 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ******** หลังจาก GROUP ตาม PRODUCT_ID ******
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 30 จ. พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P2 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P3 60 จ. 17 พ.ย. 09:31:01 IST 2014]

    ******** หลังจากกลุ่มตามราคา ******
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P2 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 20 จันทร์ พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P1 30 จ. พ.ย. 17 09:31:01 IST 2014]
    ProductBean [P3 60 จ. 17 พ.ย. 09:31:01 IST 2014]


1
สวัสดีโปรดอย่าโพสต์คำตอบเดียวกันหลายครั้งและโปรดอย่าโพสต์โค้ดดิบโดยไม่มีคำอธิบายเกี่ยวกับวิธีการทำงานและวิธีแก้ปัญหาในคำถามข้างต้น
จ้า

ขออภัยเพื่อนมีข้อผิดพลาดในการวางรหัสเนื่องจากอาจมีหลายครั้ง ฉันได้แก้ไขคำอธิบายสำหรับสิ่งที่ฉันโพสต์แล้ว หวังว่าคงสบายดีนะ ???
Ravi Beli

ฉันขาดอะไรไปหรือรหัสนี้กำลังเรียงลำดับแทนที่จะจัดกลุ่มตามเขตข้อมูล? ฉันเห็นสินค้าเรียงตาม ID แล้วเรียงตามราคา
funder7

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

0

คุณสามารถเรียงลำดับดังนี้:

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

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

สมมติว่าคุณมีจุดเริ่มต้นสำหรับตำแหน่งในชั้นเรียนของคุณ


4
ทำไมต้องเรียง? ปัญหาคือการจัดกลุ่มองค์ประกอบ!
Sankalp

0

คุณสามารถทำได้:

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

0

คุณสามารถใช้guava'sMultimaps

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

มันพิมพ์:

[qianzi: [com.ctcf.message.Persion (qianzi, 100), com.ctcf.message.Persion (qianzi, 88)], zhijia: [com.ctcf.message.Persion (zhijia, 99)]]


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

หากคุณต้องการเพิ่มหลายวัตถุสำหรับกลุ่มคุณสามารถเพิ่มวัตถุในcompositKeyวิธีการโดยคั่นด้วยลูกน้ำ:

Function<Student, List<Object>> compositKey = std ->
                Arrays.asList(std.stud_location(),std.stud_name());
        studentList.stream().collect(Collectors.groupingBy(compositKey, Collectors.toList()));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.