1
votes

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

3
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?Andreas
Thanks but that is not the answer to the question.MohantaD
You are correct. It is a comment to the question, which is why it is located in the comment section, not the answer section.Andreas

3 Answers

1
votes

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

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