Java Streams for looping twice over same list

Multi tool use
Multi tool use


Java Streams for looping twice over same list



I am new to java 8, and i have a problem understanding streams for some reason. Let's say we have a list of objects List< MyObject >, where MyObject has 2 fields : Long Id, Date insertTime, and i would like to remove elements with same ID and earlier time.



With 2 for loops it is something like this :


for(MyObject object : myObjects) {
for(MyObject tmpObject : myObjects) {
if(object.getId() == tmpObject.getId()) {
if(object.getInsertDate().after(tmpObject.getInsertDate()))
myObjects.remove(tmpObject);
else
myObjects.remove(object);
}
}
}



How would this look when using streams?



@Michael my bad. Than i would need another list or array to store the response data.



Let's say i have



So i need as a result



Thank you all.





"With 2 for loops it is something like this" I'm afraid it's not, because you can't remove from a list while you're iterating over it.
– Michael
Jul 2 at 7:24





On a side note, you should always use { and } on your statements as it will make your life easier in the long run.
– notyou
Jul 2 at 7:31


{


}





@AxelH I suppose the equals method is the wrong place for that. The equals method should return true for the same id (and optionally the same date)
– Glains
Jul 2 at 7:39


equals





Yep @Glains, I didn't read that the date should be earlier ... so it is incorrect.
– AxelH
Jul 2 at 7:42





you can do somthing like below : List<Optional<MyObj>> collect = list.stream().collect(groupingBy(MyObj::getId, maxBy(Comparator.comparing(MyObj::getDate)))).values().stream().collect(toList());
– Laxmikant
Jul 2 at 8:13




2 Answers
2



group by id and then for each id pick the one with the largest insertion date. You can replace Sample by MyObject.


Map<Long, List<Sample>> map = list.stream().collect(Collectors.groupingBy(Sample::getId));
map.values().stream()
.map(samples -> Collections.max(
samples, Comparator.comparing(Sample::getInsertDate)))
.collect(Collectors.toList());





Instead of collecting each group into a List, to select the maximum element in a second step, you can let the groupingBy operation collect the maximum element in the first place, like in this answer.
– Holger
Jul 2 at 11:30


List


groupingBy



You can do it like so,


List<MyObject> latestObjects = myObjects.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(MyObject::getId,
Collectors.maxBy(Comparator.comparing(MyObject::getInsertTime))),
map -> map.values().stream().map(op -> op.orElse(null)).collect(Collectors.toList())));



First group the objects by their Id value, then reduce it to keep only the latest object for each Id value, finally collect them into a List.


List



Update



This can further be improved as per the comment below. Here's the augmented version of it.


List<MyObject> latestObjects = myObjects.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(MyObject::getId, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(MyObject::getInsertTime))),
map -> new ArrayList<MyObject>(map.values())));





Whenever the downstream collector is a reduction (i.e. all these cases where you have to deal with an Optional afterwards), you may use toMap instead of groupingBy: List<MyObject> latestObjects = myObjects.stream() .collect(Collectors.collectingAndThen( Collectors.toMap(MyObject::getId, Function.identity(), BinaryOperator.maxBy(Comparator.comparing(MyObject::getInsertTime))), map -> new ArrayList<>(map.values())));
– Holger
Jul 2 at 11:36


Optional


toMap


groupingBy


List<MyObject> latestObjects = myObjects.stream() .collect(Collectors.collectingAndThen( Collectors.toMap(MyObject::getId, Function.identity(), BinaryOperator.maxBy(Comparator.comparing(MyObject::getInsertTime))), map -> new ArrayList<>(map.values())));





Totally agree with you. Thanks for the invaluable feedback !
– Ravindra Ranwala
Jul 2 at 14:37







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

WSlQAyUajJufoaCL7q4DXzBNP r9Y3P2,tgpJZF,f,GD oP5zI296 e37APrbBkwYvXC,kU,yl
EmltqYvl84F8fMquOAM2HU00qz,K,e5qW5Gp,2mWIdW,oQujr Neno0X2A4R VfuiUnPWY

Popular posts from this blog

Rothschild family

Cinema of Italy