Reputation: 97
I have list of records as below. I want to fetch the latest record based on date and set its name as 'H'. In the same way I want to set 'L' as name for all remaining records.
List<Student> studentList = new ArrayList<>();
try {
studentList.add(new Student("A", new SimpleDateFormat("dd-MM-yyyy").parse("01-01-1990")));
studentList.add(new Student("B", new SimpleDateFormat("dd-MM-yyyy").parse("01-01-2010")));
studentList.add(new Student("C", new SimpleDateFormat("dd-MM-yyyy").parse("01-01-2011")));
studentList.add(new Student("D", new SimpleDateFormat("dd-MM-yyyy").parse("01-01-2012")));
studentList.add(new Student("E", new SimpleDateFormat("dd-MM-yyyy").parse("01-01-2018")));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Student student = Collections.max(studentList, Comparator.comparing(s -> s.getDate()));
I've tried as above but here I can set name only for latest record but I'm unable to set name for all other remaining records.
Any help would be appreciated.
Upvotes: 2
Views: 4959
Reputation: 200
Just iterate over your list and set the name as you need:
Student student = Collections.max(studentList, Comparator.comparing(Student::getDate));
studentList.forEach(s -> s.name = s.equals(student) ? "H" : "L");
Upvotes: 0
Reputation: 718826
Single-threaded version:
// Find the latest student in the list
Student latest = Collections.max(studentList,
Comparator.comparing(s -> s.getDate()));
// Iterate the list, setting each student's name depending on whether it
// is the latest or not.
studentList.forEach(s -> {s.setName(s == latest ? "H" : "L");});
The above code makes two passes through the list. There are other ways to do the second step; e.g.
studentList.forEach(s -> {s.setName("L");});
latest.setName("H");
The max
call will throw NoSuchElementException
if the collection is empty. You could either treat that as an error (i.e. let the exception propagate), or test for an empty list before you start.
A one pass solution is possible using streams:
Optional<Student> latest = studentList.stream()
.peek(s -> {s.setName("L")})
.max(Comparator.comparing(s -> s.getDate());
latest.ifPresent(s -> {s.setName("H")});
We set every student's name to "L"
and find the latest in one pass.
Then we reset the latest student's name to "H"
.
This version also works for an empty list. (Indeed, we would need to work hard to make it not work. Optional
is helpful in some contexts.)
If the list was long enough, might be worth using parallel()
.
Upvotes: 5
Reputation: 40058
If you have only date please use LocalDate
and DateTimeFormatter
from java-8
studentList.add(new Student("A", LocalDate.parse("01-01-1990", DateTimeFormatter.ofPattern("dd-MM-yyyy")));
So the Student
class will be
public class Student {
private String name;
private date LocalDate;
//getters and setters
}
Now use Collections.max
Since LocalDate
implements Comparable
Student student = Collections.max(studentList, Comparator.comparing(s -> s.getDate()));
To Set H
and L
1st aaproach
The approach i would suggest here is first set name = L
for every student using forEach
studentList.forEcah(stu->stu.setName("L"));
Now just get the max student using comparator and set name = H
Student student = Collections.max(studentList, Comparator.comparing(s -> s.getDate()));
student.setName("H");
2nd approach
You can sort the List
first
studentList.sort(Comparator.comparing(s -> s.getDate()).reversed());
And then Set name = H
for first record and L
for rest of them
IntStream.range(0,studentList.size())
.forEach(i->{
if(i==0) {
studentList.get(i).setName("H");
}
else {
studentList.get(i).setName("L");
}
});
Upvotes: 2