Сгруппировать список объектов по атрибуту

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
Попробуйте использовать Comparator и отсортировать по местоположению.
pshemek
1
@Warlord Да, но идти дальше , если мне нужно получить информацию , как, количество Student по местоположению лучше , если бы я мог получить его группироваться
Dilukshan Махендре
@Omoro Пожалуйста, дайте мне подсказку по коду, я не так хорошо знаком с Hashmaps
Дилукшан Махендра

Ответы:

132

Это добавит объект студентов к ключу HashMapс locationIDключом.

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
Вы объявили список объектов Location, а в следующей строке вы добавляете объект Student в предыдущий список, который должен выдать ошибку.
OJVM 06
hashMap.get () возвращает null, когда hashMap.contanisKey () возвращает false. Вы можете сохранить вызов метода containsKey (), если сначала вызовете hashMap.get (), сохраните результат в локальной переменной и проверите, имеет ли эта локальная переменная значение null
Эстев
259

В Java 8:

Map<String, List<Student>> studlistGrouped =
    studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
Виталий Федоренко
источник
Это потому, что в Studentclass stud_locationуказано Friendly. Доступ может получить только Studentкласс и любой класс, определенный в одном пакете . Если вы поставите вместо , это должно сработать. Или вы можете определить функцию получения. Подробнее на cs.princeton.edu/courses/archive/spr96/cs333/java/tutorial/java/…Studentstud_locationpublic String stud_location;String stud_location;
Эранга Хешан
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]
    }
}
Чираг
источник
Этот ответ можно улучшить, придерживаясь того же примера, что и вопрос. Также результат не соответствует желаемому результату, запрошенному в вопросе.
Пим
6

Группировка Java 8 по коллекционеру

Возможно, уже поздно, но я хотел бы поделиться улучшенной идеей по этой проблеме. Это в основном то же самое, что и ответ @Vitalii Fedorenko, но более удобно поиграть.

Вы можете просто использовать Collectors.groupingBy(), передав логику группировки в качестве параметра функции, и вы получите разделенный список с отображением ключевых параметров. Обратите внимание, что using 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);

Возможно, вы захотите также изучить это Руководство по группировке Java 8By 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 с помощью Comparator, компаратор сравнит данные вашего столбца и отсортирует их. В основном, если вы храните отсортированные данные, которые выглядят как сгруппированные, например, если у вас одинаковые повторяющиеся данные столбца, тогда механизм сортировки сортирует их, сохраняя одни и те же данные с одной стороны, а затем ищет другие данные, которые являются несходными данными. Это косвенно рассматривается как группировка одних и тех же данных.

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 (список, объект Comparator для требуемого столбца). Это будет сортироваться на основе вашей реализации компаратора и вы сможете увидеть сгруппированные данные в выводе ниже. Надеюсь это поможет...

    ******** ПЕРЕД ГРУППИРОВКОЙ ВХОДНЫЕ ДАННЫЕ СМОТРИТ ТАК ******
    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]
    ******** ПОСЛЕ ГРУППЫ ПО ИДЕНТИФИКАТОРУ ПРОДУКТА ******
    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
Привет, пожалуйста, не публикуйте один и тот же ответ несколько раз, и, пожалуйста, не публикуйте необработанный код без объяснения того, как он работает и как он решает проблему в вопросе выше.
Mat
Извините, приятель, при вставке кода произошла ошибка, так как он мог повторяться несколько раз. Я отредактировал объяснение того, что опубликовал. Надеюсь, что теперь все в порядке ???
Рави Бели
Мне чего-то не хватает или этот код выполняет сортировку, а не группировку по полю? Я вижу продукты, отсортированные по идентификатору, а затем по цене
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());
        }
    });

Предполагая, что у вас также есть геттер для местоположения в вашем классе Student.

Питер
источник
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()));
ТанвирЧоудхури
источник