Java: Round an Integer to an element of a given List

Tags: , ,



Supose i have a List of Integers: ints = {0,10,20,30,40,50} and an input value input = 17

How do i get the closest integer of the list to the given input? For my example it would be 20.

Or to restate the question: how do i round the input to the closest value of the list?

I couldn’t find a function in Java that does something like that

Answer

There is nothing in Java to do this exactly, as it’s not something that’s particularly useful in general.

One approach would be to notice that you are looking for the smallest deviation from input, that is to say, the value where abs(number - input) is closest to 0.

Using this knowledge, we can create a Comparator that compares numbers based on their distance from the input, and pick the smallest number based on this comparator:

List<Integer> ints = List.of(0, 10, 20, 30, 40, 50);
int input = 17;

Comparator<Integer> distanceFromInputComparator = 
        Comparator.comparing(value -> Math.abs(value - input));

System.out.println(ints.stream().min(distanceFromInputComparator).orElseThrow());

This returns 20, as requested.

There are some caveats with this implementation that could be addressed if necessary. It currently throws an exception if the input list is empty. It also picks arbitrarily if there are two closest (e.g. if 14 & 20 are in the list and the input is 17, it’s not specified which would be picked by Stream.min()) since they’re both “equal” according to the comparator.

To address the tiebreaker, you could add a secondary comparison if they’re equidistant. For instance, you could do either of the following:

// Pick the smaller when there's a tie
Comparator<Integer> distanceFromInputComparator = Comparator
        .comparing((Integer value) -> Math.abs(value - input))
        .thenComparing(Comparator.naturalOrder());

// Pick the larger when there's a tie
Comparator<Integer> distanceFromInputComparator = Comparator
        .comparing((Integer value) -> Math.abs(value - input))
        .thenComparing(Comparator.reverseOrder());


Source: stackoverflow