Home > Enterprise >  Find the closest object inside a list given two values
Find the closest object inside a list given two values

Time:08-04

I have an object that follows the structure below

class Ray{
   float param1; 
   float param2; 
}

and then I have the following: List<Ray> rays

I have a 2D slider that gives a couple of values {value1, value2}

The problem is that the values inside the slider are continuous and they don't match exactly with the values of the class Ray, thus I cannot just make a filter using stream().

I need to find the Ray that has both fields closest to value1 and value2.

I'm not really expert using streams().

My first idea is to iterate the List and find the nearest value (let's say nearestParam1) to value1, then iterate the list and find the nearest value (nearestParam2) to value2, then filter the list by nearestParam1 and finally filter the list by nearestParam2.

... 
List<Ray> rays;
float nearestParam1;
float value1;
float oldDistance=9999;
for (Ray ray : rays){
 float newDistance = abs( ray.Param1 - value1);
 if(newDistance < oldDistance) {
  oldDistance = newDistance;
  nearestParam1 = ray.Param1;
 }
}

List<Ray> filteredRays = rays.stream().filter(ray -> ray.Param1 == nearestParam1).toList();

and then repeat again for the second field. I don't like this solution, can you find a cleaner and maybe faster solution?

My list has a really huge dimension and inside there are not equals object (1 field could match but not both at the same time)

CodePudding user response:

Rather than comparing each field separately, you can consolidate them into a single value and then find the closest one to your target date using Stream#min.

public LocalDateTime toDateTime(int dayOfTheYear, double timeOfTheDay) {
    LocalDate first = LocalDate.of(2022,1,1);
    return first.atStartOfDay()
            .plusDays(dayOfTheYear)
            .plusHours((int) timeOfTheDay)
            .plusMinutes((long) ((timeOfTheDay - Math.floor(timeOfTheDay)) * 60L));
}

public Optional<Ray> findClosestRay(List<Ray> rays, int DayOfTheYear, float TimeOfTheDay) {
    LocalDateTime target = toDateTime(DayOfTheYear, TimeOfTheDay);

    return rays.stream()
            .min(Comparator.comparing(ray -> Duration.between(target, toDateTime(ray.DayOfTheYear, ray.TimeOfTheDay)).abs()));
}

CodePudding user response:

as MikeFHay pointed out in the main post i didn't specified how to determine the single closest result over all rays combining minimization of param 1 and param 2.

I found a solution that is quite working for my case, what do you think about that?

Comparator<Ray> comparator = Comparator.comparing(ray->abs(ray.param1-value1)   abs(ray.param2-value2) );

Ray bestRay = rays.stream().min(comparator).get();
  • Related