Retrieve the first items of each group in Java

java collections group by example
java 7 collection group by
java 8 group by multiple fields
group multiple occurrence of array elements ordered by first occurrence
java 8 group by multiple fields and sum
how to get first element of a collection in java
group by in java 7
java collection get element by index

In Java, how to get list down the latest/first item of each group after grouping by field(/s)? e.g From the given list of medical records, how to retrieve the latest record of each patient.


    Sample Data
    ---------------------------------------------------------------------------
    PatientName  |    ReportDate    | ReadingNo |    Measurement
    ---------------------------------------------------------------------------
    X            |    2020-01-02    |    1      |    255
    Y            |    2020-01-02    |    1      |    250
    X            |    2020-01-02    |    2      |    266
    Y            |    2020-01-02    |    2      |    270
    X            |    2020-01-02    |    3      |    298
    Y            |    2020-01-02    |    3      |    259
    X            |    2020-01-02    |    4      |    280
    Y            |    2020-01-02    |    4      |    285
    X            |    2020-01-03    |    1      |    260
    Y            |    2020-01-03    |    1      |    265
    X            |    2020-01-03    |    2      |    280
    Y            |    2020-01-03    |    2      |    260
    X            |    2020-01-03    |    3      |    285
    Y            |    2020-01-03    |    3      |    290
    X            |    2020-01-03    |    4      |    290
    Y            |    2020-01-03    |    4      |    280
    ---------------------------------------------------------------------------

    Expected result
    ---------------------------------------------------------------------------
    PatientName  |    ReportDate    | ReadingNo |    Measurement
    ---------------------------------------------------------------------------
    X            |    2020-01-03    |    4      |    290
    Y            |    2020-01-03    |    4      |    280
    ---------------------------------------------------------------------------

I can do it C# as below. Any one can help to translate it in Java?


    using System.Collections.Generic;
    using System.Linq;

    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("---------------------------------------------------------------------------");
            Console.WriteLine(String.Format("{0}  |\t{1}\t| {2} |\t{3}", "PatientName", "ReportDate", "ReadingNo", "Measurement"));
            Console.WriteLine("---------------------------------------------------------------------------");
            List lst = new List
            {
                new Patient(){Name="X", ReportDate="2020-01-02", ReadingNo=1, Measurement=255 },
                new Patient(){Name="Y", ReportDate="2020-01-02", ReadingNo=1, Measurement=250 },
                new Patient(){Name="X", ReportDate="2020-01-02", ReadingNo=2, Measurement=266 },
                new Patient(){Name="Y", ReportDate="2020-01-02", ReadingNo=2, Measurement=270 },
                new Patient(){Name="X", ReportDate="2020-01-02", ReadingNo=3, Measurement=298 },
                new Patient(){Name="Y", ReportDate="2020-01-02", ReadingNo=3, Measurement=259 },
                new Patient(){Name="X", ReportDate="2020-01-02", ReadingNo=4, Measurement=280 },
                new Patient(){Name="Y", ReportDate="2020-01-02", ReadingNo=4, Measurement=285 },
                new Patient(){Name="X", ReportDate="2020-01-03", ReadingNo=1, Measurement=260 },
                new Patient(){Name="Y", ReportDate="2020-01-03", ReadingNo=1, Measurement=265 },
                new Patient(){Name="X", ReportDate="2020-01-03", ReadingNo=2, Measurement=280 },
                new Patient(){Name="Y", ReportDate="2020-01-03", ReadingNo=2, Measurement=260 },
                new Patient(){Name="X", ReportDate="2020-01-03", ReadingNo=3, Measurement=285 },
                new Patient(){Name="Y", ReportDate="2020-01-03", ReadingNo=3, Measurement=290 },
                new Patient(){Name="X", ReportDate="2020-01-03", ReadingNo=4, Measurement=290 },
                new Patient(){Name="Y", ReportDate="2020-01-03", ReadingNo=4, Measurement=280 }
            };
            lst.ForEach(p=>{
                Console.WriteLine(p.toString());
            });
            Console.WriteLine("---------------------------------------------------------------------------");

            var lstLatest = from p in lst
                  group p by p.Name
                      into g
                      select g.OrderByDescending(p => p.ReportDate).ThenByDescending(p=>p.ReadingNo).ToList();
            foreach(var p in lstLatest)
            {
                Console.WriteLine(p.First().toString());
            }


        }
    }

    public class Patient
    {
        public string Name { get; set;}
        public string ReportDate {get;set;}
        public int ReadingNo {get;set;}
        public int Measurement {get;set;}
        public string toString()
        {
            return String.Format("{0}\t\t\t|\t{1}\t|\t{2}  \t|\t{3}", this.Name, this.ReportDate, this.ReadingNo, this.Measurement);
        }
    }

In java you should use streams api.

If you need group by you can use this example:

Map<String, Patient> map = 
getValute().stream().collect(
    Collectors.groupingBy(
        Patient::getName,
        Collectors.collectingAndThen(
            Collectors.toList(), 
            values -> values.get(0))));

As example if you want to use FirstOrDefault (only for education):

Animal cheetah = animals.stream()
    .filter((animal) -> animal.getNumber() == cheetahNumber)
    .findFirst()
    .orElse(Animal.DEFAULT);

How to do GROUP BY in Java 8? Collectors , When you got the first item for a new group, you create a list and put line code of Java 8, where you get the stream from the list and used a� We read the ‘:’ used in for-each loop as “in”. So loop reads as “for each element e in elements”, here elements is the collection which stores Element type items. Note :In Java 8 using lambda expressions we can simply replace for-each loop with. elements.forEach (e -> System.out.println(e) ); Using Cursors

Thanks @TemaTre. Your input helped. The working code looks like



    Map map = 
                lst.stream().collect(
                    Collectors.groupingBy(
                        Patient::getName,
                        Collectors.collectingAndThen(
                            Collectors.toList(), 
                            values -> values.stream()
                                .sorted(Comparator.comparing(Patient::getReportDate, Comparator.nullsFirst(Comparator.naturalOrder()))
                                        .thenComparing(Patient::getReadingNo, Comparator.nullsFirst(Comparator.naturalOrder())).reversed())
                                .collect(toList()).get(0)

                            )));

And the complete working code in Java is as below

import java.util.*;
    import java.util.stream.Collectors;
    import static java.util.stream.Collectors.*;
    public class Main{

         public static void main(String []args){
             List<Patient> lst = new ArrayList<>();
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-02");setReadingNo(1);setMeasurement(255);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-02");setReadingNo(1);setMeasurement(250);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-02");setReadingNo(2);setMeasurement(266);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-02");setReadingNo(2);setMeasurement(270);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-02");setReadingNo(3);setMeasurement(298);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-02");setReadingNo(3);setMeasurement(259);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-02");setReadingNo(4);setMeasurement(280);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-02");setReadingNo(4);setMeasurement(285);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-03");setReadingNo(1);setMeasurement(260);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-03");setReadingNo(1);setMeasurement(265);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-03");setReadingNo(2);setMeasurement(280);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-03");setReadingNo(2);setMeasurement(260);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-03");setReadingNo(3);setMeasurement(285);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-03");setReadingNo(3);setMeasurement(290);}});
             lst.add(new Patient(){{setName("X");setReportDate("2020-01-03");setReadingNo(4);setMeasurement(290);}});
             lst.add(new Patient(){{setName("Y");setReportDate("2020-01-03");setReadingNo(4);setMeasurement(280);}});

             for(Patient p: lst){
                 System.out.println(p.toString());
             }
             System.out.println("---------------------------");

             Map<String, Patient> map = 
                lst.stream().collect(
                    Collectors.groupingBy(
                        Patient::getName,
                        Collectors.collectingAndThen(
                            Collectors.toList(), 
                            values -> values.stream()
                                .sorted(Comparator.comparing(Patient::getReportDate, Comparator.nullsFirst(Comparator.naturalOrder()))
                                        .thenComparing(Patient::getReadingNo, Comparator.nullsFirst(Comparator.naturalOrder())).reversed())
                                .collect(toList()).get(0)

                            )));

            for (Map.Entry<String,Patient> entry : map.entrySet()) {
                System.out.println(entry.getValue().toString());
            } 


         }
    }

     class Patient{
        private String Name;
        public String getName(){
            return Name;
        }
        public void setName(String name){
            this.Name=name;
        }

        private String ReportDate;
        public String getReportDate(){
            return ReportDate;
        }
        public void setReportDate(String reportDate){
            this.ReportDate=reportDate;
        }

        private int ReadingNo;
        public int getReadingNo(){
            return ReadingNo;
        }
        public void setReadingNo(int readingNo){
            this.ReadingNo=readingNo;
        }

        private int Measurement;
        public int getMeasurement(){
            return Measurement;
        }
        public void setMeasurement(int measurement){
            this.Measurement=measurement;
        }

        public String toString(){
            return String.format("%s\t%s\t%d\t%d", Name, ReportDate, ReadingNo, Measurement);
        }
    }

Group multiple occurrence of array elements ordered by first , The inner loop checks if this is first occurrence, if yes, then the inner loop prints it and all other A simple method to group all occurrences of individual elements ……….a) Get its count and print the element 'count' times. Java program to group multiple occurrences of individual array elements */. As with the ArrayList class, you can use the get method to retrieve an item in Java based on its index. If you pass it an invalid index number, the get method throws the unchecked IndexOutOfBoundsException. You can also use an enhanced for loop to retrieve all the items in the linked list.

import static java.util.Comparator.comparing;
import static java.util.Comparator.reverseOrder;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.groupingBy;



    Map<String, List<Patient>> map = lst.stream()
        .collect(groupingBy(Patient::getName, toList()));

    for (List<Patient> group : map.values()) {

        Patient first = group.stream()
            .sorted(comparing(Patient::getReportDate).thenComparing(Patient::getReadingNo, reverseOrder()))
            .findFirst()
            .orElseThrow();

        System.out.println(first);
    }

Retrieving Elements from Collection in Java (For-each, Iterator , So loop reads as “for each element e in elements”, here elements is the collection which stores Element type items. Note :In Java 8 using lambda� Prerequisite : Collection in Java Following are the 4 ways to retrieve any elements from a collection object: For-each For each loop is meant for traversing items in a collection. // Iterating over collection 'c' using for-each for (Element e: c) System.out.println(e); We read the ‘:’ used in for-each loop as “in”.

SQLite Group By, This tutorial shows you how to use SQLite GROUP BY clause to group a set The GROUP BY clause a selected group of rows into summary rows by values of one or more columns. album's titles and uses the GROUP BY clause with the COUNT function to get SQLite PHP � SQLite Node.js � SQLite Java � SQLite Python� This snippet will find the first element in arraylist using java 8. The Java 8 Streams APIprovides Streams.findFirst which will return the wrapper Optionalobject describing the first element of the stream. If the arraylist is empty, an empty Optional will be returned.

Capturing groups, It allows to get a part of the match as a separate item in the result array. If we put a quantifier The first group is returned as result[1] . Here it� When you got the first item for a new group, you create a list and put that item on the list, but when the group already exists in Map then you just retrieve it and store your element into it. The code is not difficult to write but it takes 5 to 6 lines to do that and you have to do null check everywhere to avoid NullPointerException.

Part 2: Processing Data with Java SE 8 Streams, In the first part of this series, you saw that streams let you process collections with The function is used to extract a comparable key from the element of a stream. Grouping. A common database query is to group data using a property. A Group node contains an ObservableList of children that are rendered in order whenever this node is rendered. A Group will take on the collective bounds of its children and is not directly resizable. Any transform, effect, or state applied to a Group will be applied to all children of that group. Such transforms and effects will NOT be

Comments
  • What have you tried? Do you know Java at all and how to use streams, or are you just hoping we'll refactor the code for you? Did you try searching for how to group data in Java using streams?
  • Thanks but that is not the answer to the question.
  • You are correct. It is a comment to the question, which is why it is located in the comment section, not the answer section.
  • How to sort by the ReadingDate and ReadingNo before collecting the first item?
  • You can sort it firstly. And then after grouping, groups will sorts too
  • Creating 16 classes, just to initialize 16 instances, is a very bad idea. Do not use the double-brace hack. Efficiency of Java "Double Brace Initialization"? --- Recommend adding a 4-arg constructor instead. If you don't want that, then add a static helper method to the Main class, so you can simply do List<Patient> lst = Arrays.asList(newPatient("X", "2020-01-02", 1, 255), newPatient("Y", "2020-01-02", 1, 250), ...);