0

I am working with a List of Person objects. I am trying to quickly identify and return all Person's with the maximum date.

For example:

Persons:[
{
  id: 1
  submitDate: 2010-01-01
  name : john Smith
},
{
  id: 1
  submitDate: 2011-01-01
  name : john Smith
},
{
  id: 2
  submitDate: 2011-01-02
  name : jason Doe
},
{
  id: 1
  submitDate: 2012-01-01
  name : john Smith
},
{
  id: 1
  submitDate: 2013-01-01
  name : john Smith
},
{
  id: 2
  submitDate: 2013-01-02
  name : jason Doe
}
]

I am looking for a way, in Java, to return the following (Max submitDate value):

Persons: [
{
  id: 1
  submitDate: 2013-01-01
  name : john Smith
},
{
  id: 2
  submitDate: 2013-01-02
  name : jason Doe
}
]

Any thoughts on how to best achieve this?

======================================================================== I've tried:

List<Person> personList = Lists.newArrayList();
getPersonList().stream()
               .map(this.setSource)
               .max(Comparator.comparing(Person::getSubmitDate))
               .map(personList::add);

However it returns a single Person record, Not the max submitDate for each Person

Dan
  • 979
  • 1
  • 8
  • 29
  • For future searching & writing, use the word `distinct` if you mean to eliminate duplicate values. Also, given your example data, I do not see you going for "maximum", I see only eliminating duplicates to make a distinct list. Edit your Question to clarify. Possible duplicate: [Java - Distinct List of Objects](http://stackoverflow.com/q/1019854/642706) – Basil Bourque Dec 01 '16 at 20:26
  • @BasilBourque, if you read above I state "I am trying to quickly identify and return all `Person`'s with the maximum date". I agree I could have originally written my question better explaining I wanted to get the max date for each person (based on id). I did, however, go back and explain myself in my 'edit' – Dan Dec 01 '16 at 20:33
  • I was incorrect in the latter part of my comment above about not performing "maximum". Misread the dates as I looked only at the month-day but not the year. Perhaps you should edit the month-day portions of the example values a bit to avoid others doing the same mistake. – Basil Bourque Dec 01 '16 at 20:38

2 Answers2

0
    List<Person> persons = ...
    List<Person> resultList = new ArrayList<>();
    Map<Integer, List<Person>> personsBySubmitDate =
            persons.stream().collect(Collectors.groupingBy(person -> person.getId());

    for (Map.Entry<Integer, List<Person>> entry : personsBySubmitDate.entrySet()) {
        Person currentPerson = entry.getValue()
                                    .stream()
                                    .max(Comparator.comparing(Person::getSubmitDate))
                                    .orElse(null);
        resultList.add(currentPerson);
    }

It should be O(n).

  • I'll give that a shot. Thanks! – Dan Dec 01 '16 at 18:32
  • there's nothing to collect. 'max()' method returns Optional, that is basically a wrapper for your Person object. You can access it calling a get method. But make sure it's present! – Coderslang Master Dec 01 '16 at 20:09
  • unfortunately using `.max` returns me a single record (the Max of **all** `Person` objects), not the max date for each `Person` – Dan Dec 01 '16 at 20:12
  • Dan, unfortunately I got your question completely wrong twice. I've replaced my original answer with what you're most likely looking for. – Coderslang Master Dec 01 '16 at 20:36
0

@Default71721, your answer works perfectly, however I noticed that longer lists were really bogging down the system (The O(n^2) processing). I decided to re-write the SQL query which proved to give us the speed we needed.

Thank you for all your help!

Dan
  • 979
  • 1
  • 8
  • 29