Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java: Collect and combine data in a list

In my program I have a List of Plants, each plant has a measurement (String), day (int), camera (int), and replicate number(int). I obtain a List of all plants wanted by using filters:

List<Plant> selectPlants = allPlants.stream().filter(plant -> passesFilters(plant, filters)).collect(Collectors.toList());

What I would like to do now is take all Plants that have the same camera, measurement, and replicate values. And combine them in order of day. So if I have days 1,2,3,5 I would want to find all similar plants and append the values to one plant where the getValues (function).

I added a method to Plant that appends values by just using addAll( new plant values ).

Is there any way of doing this without iterating through the list over and over to find the similar plants, and then sorting each time by day then appending? I'm sorry for the horrible wording of this question.

like image 544
Sam Avatar asked Dec 11 '22 05:12

Sam


1 Answers

While Vakh’s answer is correct, it is unnecessarily complex.

Often, the work of implementing your own key class does not pay off. You can use a List as a key which implies a slight overhead due to boxing primitive values but given the fact that we do operations like hashing here, it will be negligible.

And sorting doesn’t have to be done by using a for loop and, even worse, an anonymous inner class for the Comparator. Why do we have streams and lambdas? You can implement the Comparator using a lambda like (p1,p2) -> p1.getDay()-p2.getDay() or, even better, Comparator.comparing(Plant::getDay).

Further, you can do the entire operation in one step. The sort step will create an ordered stream and the collector will maintain the encounter order, so you can use one stream to sort and group:

Map<List<?>, List<Plant>> groupedPlants =  allPlants.stream()
  .filter(plant -> passesFilters(plant, filters))
  .sorted(Comparator.comparing(Plant::getDay))
  .collect(Collectors.groupingBy(p ->
     Arrays.asList(p.getMeasurement(), p.getCamera(), p.getReplicateNumber())));

That’s all.

like image 144
Holger Avatar answered Dec 28 '22 14:12

Holger