Regrouper une liste d'objets par un attribut: Java

97

J'ai besoin de grouper une liste d'objets (Student) en utilisant un attribut (Location) de l'objet particulier, le code est comme ci-dessous,

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;

    }
}

Veuillez me suggérer une manière propre de le faire.

Dilukshan Mahendra
la source
2
Un hashmap avec l'emplacement comme clé et la liste des étudiants comme valeur.
Omoro
Le tri par emplacement résoudrait-il votre problème ou y a-t-il autre chose?
Warlord
Essayez d'utiliser Comparator et triez par emplacement.
pshemek
1
@Warlord Oui, mais aller plus loin si j'ai besoin d'informations telles que le nombre d'étudiants par emplacement est meilleur si je pouvais les regrouper
Dilukshan Mahendra
@Omoro S'il vous plaît pouvez-vous me donner un indice par code, je ne suis pas si familier avec les Hashmaps
Dilukshan Mahendra

Réponses:

130

Cela ajoutera l'objet étudiants à la clé HashMapavec locationIDcomme clé.

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

Répétez ce code et ajoutez des étudiants au 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 vous voulez que tous les étudiants aient des détails de localisation particuliers, vous pouvez utiliser ceci:

hashMap.get(locationId);

ce qui vous permettra d'obtenir tous les étudiants avec le même identifiant de lieu.

Dileep
la source
4
Vous avez déclaré une liste d'objets Location et dans la ligne suivante, vous ajoutez un objet Student à la liste précédente qui devrait générer une erreur.
OJVM
hashMap.get () renvoie null lorsque hashMap.contanisKey () renvoie false. Vous pouvez enregistrer l'appel à la méthode containsKey () si vous appelez d'abord hashMap.get (), stockez le résultat dans une variable locale et vérifiez si cette variable locale est nulle
Esteve
248

Dans Java 8:

Map<String, List<Student>> studlistGrouped =
    studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
Vitalii Fedorenko
la source
C'est parce que dans la Studentclasse stud_locationest spécifié comme amical. Seules les Studentclasses et toutes les classes définies dans le même package de Studentpeuvent y accéder stud_location. Si vous mettez public String stud_location;au lieu de String stud_location;, cela devrait fonctionner. Ou vous pouvez définir une fonction getter. Plus d'infos dans 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
la source
8

Utilisation de 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
    }

}

Le résultat sera:

{
    Max={
        Los Angeles=[Student@214c265e], 
        California=[Student@448139f0]
    }, 
    John={
        New York=[Student@7cca494b]
    }, 
    Sam={
        California=[Student@7ba4f24f]
    }
}
Chirag
la source
Cette réponse peut être améliorée en s'en tenant au même exemple que la question. De plus, le résultat ne correspond pas à la sortie souhaitée demandée dans la question.
Pim Hazebroek
5

Regroupement Java 8 par collecteur

Il est probablement tard mais j'aime partager une idée améliorée de ce problème. C'est fondamentalement la même chose que la réponse de @Vitalii Fedorenko, mais c'est plus pratique pour jouer.

Vous pouvez simplement utiliser le Collectors.groupingBy()en passant la logique de regroupement en tant que paramètre de fonction et vous obtiendrez la liste divisée avec le mappage des paramètres clés. Notez que l'utilisation Optionalest utilisée pour éviter le NPE indésirable lorsque la liste fournie estnull

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

Maintenant, vous pouvez groupBy n'importe quoi avec ça. Pour le cas d'utilisation ici dans la question

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

Vous aimeriez peut-être consulter également ce Guide du regroupement Java 8

Shafin Mahmud
la source
4

Vous pouvez utiliser les éléments suivants:

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

//impression

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
la source
4

Implémentez la fonctionnalité SQL GROUP BY en Java à l'aide de Comparator, le comparateur comparera vos données de colonne et les triera. Fondamentalement, si vous conservez des données triées qui ressemblent à des données groupées, par exemple si vous avez les mêmes données de colonne répétées, le mécanisme de tri les trie en gardant les mêmes données d'un côté, puis recherchez d'autres données qui sont des données différentes. Ceci est indirectement considéré comme un GROUPEMENT des mêmes données.

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

La sortie est ici pour que la liste ProductBean ci-dessus soit faite selon les critères GROUP BY, ici si vous voyez les données d'entrée qui sont données la liste de ProductBean à Collections.sort (liste, objet de comparateur pour votre colonne requise) Cela triera en fonction de l'implémentation de votre comparateur et vous pourrez voir les données groupées dans la sortie ci-dessous. J'espère que cela t'aides...

    ******** AVANT DE GROUPER LES DONNÉES D'ENTRÉE SONT DE CETTE FAÇON ******
    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]
    ******** APRÈS LE GROUPE PAR 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]

    ******** APRÈS GROUPE PAR PRIX ******
    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
la source
1
Bonjour, veuillez ne pas publier la même réponse plusieurs fois, et veuillez ne pas publier de code brut sans explication sur son fonctionnement et sur la façon dont il résout le problème dans la question ci-dessus.
Mat
Désolé mon pote, il y a eu une erreur en collant le code, car il pourrait être devenu plusieurs fois. J'ai édité l'explication de ce que j'ai publié. J'espère que ça va bien maintenant ???
Ravi Beli
Il me manque quelque chose ou ce code est en train de trier au lieu de regrouper par champ? Je vois les produits triés par ID, puis par Prix
Bailleur de fonds le
0

Vous pouvez trier comme ceci:

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

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

En supposant que vous ayez également le getter pour l'emplacement sur votre classe Student.

Pieter
la source
3
Pourquoi trier? Le problème est de regrouper les éléments!
Sankalp
0

Vous pouvez faire ceci:

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

les clés seront les emplacements et la liste des valeurs des étudiants. Ainsi, plus tard, vous pouvez obtenir un groupe d'étudiants simplement en utilisant:

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

vous pouvez utiliser 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 })

il imprime:

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

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

Si vous souhaitez ajouter plusieurs objets pour group by, vous pouvez simplement ajouter l'objet dans la compositKeyméthode en séparant par une virgule:

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