Gruppieren Sie eine Liste von Objekten nach einem Attribut: Java

96

Ich muss eine Liste von Objekten (Student) unter Verwendung eines Attributs (Position) des bestimmten Objekts gruppieren. Der Code ist wie folgt:

public class Grouping {

    /**
     * @param args the command line arguments
     */
    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"));

        //Code to group students by location
        /*  Output should be Like below
            ID : 1726   Name : John Location : New York
            ID : 5223   Name : Michael  Location : New York
            ID : 4321   Name : Max  Location : California
            ID : 7765   Name : Sam  Location : California    

         */

        for (Student student : studlist) {
            System.out.println("ID : "+student.stud_id+"\t"+"Name : "+student.stud_name+"\t"+"Location : "+student.stud_location);
        }


    }
}

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;

    }
}

Bitte schlagen Sie mir einen sauberen Weg vor.

Dilukshan Mahendra
quelle
2
Eine Hashmap mit dem Standort als Schlüssel und der Schülerliste als Wert.
Omoro
Würde das Sortieren nach Ort Ihr Problem lösen oder gibt es noch etwas anderes?
Warlord
Versuchen Sie es mit Comparator und sortieren Sie nach Ort.
Pshemek
1
@ Warlord Ja, aber weiter gehen, wenn ich Informationen wie erhalten möchte: Schüler zählen nach Ort besser, wenn ich sie gruppieren könnte
Dilukshan Mahendra
@Omoro Bitte können Sie mir einen Hinweis per Code geben, ich bin nicht so vertraut mit Hashmaps
Dilukshan Mahendra

Antworten:

130

Dadurch wird das Studenten - Objekt der hinzufügen HashMapmit locationIDals Schlüssel.

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

Durchlaufen Sie diesen Code und fügen Sie die Schüler hinzu zu HashMap:

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

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

Wenn Sie möchten, dass alle Schüler bestimmte Standortdetails haben, können Sie Folgendes verwenden:

hashMap.get(locationId);

Dadurch erhalten Sie alle Schüler mit der gleichen Standort-ID.

Dileep
quelle
4
Sie haben eine Liste von Standortobjekten deklariert und in der nächsten Zeile der vorherigen Liste ein Schülerobjekt hinzugefügt, das einen Fehler auslösen sollte.
ABl.
hashMap.get () gibt null zurück, wenn hashMap.contanisKey () false zurückgibt. Sie können den Aufruf der Methode includesKey () speichern, wenn Sie zuerst hashMap.get () aufrufen, das Ergebnis in einer lokalen Variablen speichern und prüfen, ob diese lokale Variable null ist
Esteve
244

In Java 8:

Map<String, List<Student>> studlistGrouped =
    studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
Vitalii Fedorenko
quelle
Das liegt daran, dass in der StudentKlasse " stud_locationFreundlich" angegeben ist. Nur StudentKlassen und Klassen, die in demselben Paket definiert sind, Studentkönnen darauf zugreifen stud_location. Wenn Sie setzen public String stud_location;statt String stud_location;, sollte diese Arbeit. Oder Sie können eine Getter-Funktion definieren. Weitere Informationen unter 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);
    }

}
Sampath Challa
quelle
8

Verwenden von 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
    }

}

Das Ergebnis wird sein:

{
    Max={
        Los Angeles=[Student@214c265e], 
        California=[Student@448139f0]
    }, 
    John={
        New York=[Student@7cca494b]
    }, 
    Sam={
        California=[Student@7ba4f24f]
    }
}
Chirag
quelle
Diese Antwort kann verbessert werden, indem Sie sich an dasselbe Beispiel wie die Frage halten. Auch stimmt das Ergebnis nicht mit der gewünschten Ausgabe überein, die in der Frage angefordert wird.
Pim Hazebroek
5

Java 8 groupingBy Collector

Wahrscheinlich ist es spät, aber ich möchte eine verbesserte Idee zu diesem Problem teilen. Dies ist im Grunde die gleiche Antwort von @Vitalii Fedorenko, aber handlicher zum Herumspielen.

Sie können das einfach verwenden, Collectors.groupingBy()indem Sie die Gruppierungslogik als Funktionsparameter übergeben, und Sie erhalten die geteilte Liste mit der Schlüsselparameterzuordnung. Beachten Sie, dass die Verwendung Optionalverwendet wird, um unerwünschte NPE zu vermeiden, wenn die bereitgestellte Liste vorhanden istnull

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

Jetzt können Sie alles damit gruppieren . Für den Anwendungsfall hier in der Frage

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

Vielleicht möchten Sie sich auch dieses Handbuch zu Java 8 groupingBy Collector ansehen

Shafin Mahmud
quelle
4

Sie können Folgendes verwenden:

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

//drucken

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);
    }
}
Azizi
quelle
4

Implementieren Sie die SQL GROUP BY-Funktion in Java mithilfe von Comparator. Der Comparator vergleicht Ihre Spaltendaten und sortiert sie. Wenn Sie sortierte Daten behalten, die als gruppierte Daten aussehen, z. B. wenn Sie dieselben wiederholten Spaltendaten haben, sortieren Sie sie nach dem Sortiermechanismus, indem Sie dieselben Daten auf einer Seite behalten, und suchen Sie dann nach anderen Daten, bei denen es sich um unterschiedliche Daten handelt. Dies wird indirekt als Gruppierung derselben Daten angesehen.

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

Die Ausgabe erfolgt hier für die oben genannte ProductBean-Liste. Die GROUP BY-Kriterien werden hier angezeigt. Wenn Sie die Eingabedaten sehen, die eine Liste der ProductBean an Collections.sort (Liste, Objekt des Komparators für Ihre erforderliche Spalte) erhalten, wird dies basierend auf Ihrer Komparatorimplementierung sortiert und Sie können die GROUPED-Daten in der folgenden Ausgabe sehen. Hoffe das hilft...

    ******** VOR DER GRUPPIERUNG DER EINGABEDATEN SCHAUT DIESER WEG ******
    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]
    ******** NACH DER GRUPPE NACH 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]

    ******** NACH PREISGRUPPE ******
    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]

Ravi Beli
quelle
1
Hallo, bitte poste nicht dieselbe Antwort mehrmals und poste keinen Rohcode ohne eine Erklärung darüber, wie es funktioniert und wie es das Problem in der obigen Frage löst.
Mat
Entschuldigung, Kumpel, beim Einfügen des Codes ist ein Fehler aufgetreten, da er möglicherweise mehrmals aufgetreten ist. Ich habe die Erklärung für das, was ich gepostet habe, bearbeitet. Hoffe das sieht jetzt gut aus ???
Ravi Beli
Mir fehlt etwas oder dieser Code wird sortiert, anstatt nach einem Feld zu gruppieren? Ich sehe Produkte sortiert nach ID, dann nach Preis
Funder
0

Sie können so sortieren:

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

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

Angenommen, Sie haben auch den Getter für den Standort in Ihrer Schülerklasse.

Pieter
quelle
3
Warum sortieren? Das Problem ist, die Elemente zu gruppieren!
Sankalp
0

Sie könnten dies tun:

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

Die Schlüssel sind Orte und die Werteliste der Schüler. So können Sie später eine Gruppe von Studenten erhalten, indem Sie einfach Folgendes verwenden:

studlist = map.get("New York");
Omoro
quelle
0

Sie können guava's verwendenMultimaps

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

es drucken:

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

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

Wenn Sie mehrere Objekte für die Gruppe hinzufügen möchten, können Sie das Objekt einfach in compositKeyeiner durch Komma getrennten Methode hinzufügen :

Function<Student, List<Object>> compositKey = std ->
                Arrays.asList(std.stud_location(),std.stud_name());
        studentList.stream().collect(Collectors.groupingBy(compositKey, Collectors.toList()));
TanvirChowdhury
quelle
0
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
}
Soudipta Dutta
quelle