-2

Like with a List you can type:

public Iterable<Integer> findClosestNumbers(int givenValue, Iterable<Integer> numbers, int n){
    Iterable<Integer> closestNumbers;

    int closest = numbers.stream()
            .min(Comparator.comparingInt(i -> Math.abs(i - value)))
            .orElseThrow(() -> new NoSuchElementException("No value present"));


   return closestNumbers;

The 'givenValue' represents the value it should be closest to

The 'numbers' could be an array of numbers {1, 2, 4, 5}

The 'n' specifies how many numbers that should be returned closest to the value

Like value:6 and n=2 then results should return Iterable {4, 5}

How to write this using Iterable as short as possible? I can not change the parameters

Rosso
  • 93
  • 2
  • 9
  • Either create a stream from the iterable (see the linked question), or use a regular loop and a local variable for the current closest value. – Alex Shesterov Oct 30 '20 at 08:17
  • 1
    Note that for signed integers, the distance between two `int` values can be larger than the `int` value space. And once `i - value` has overflown, `abs` can’t cure that. As a corner case, if the distance happens to be `Integer.MIN_VALUE`, the result of `Math.abs` may even be negative. Your approach works fine, as long as the numbers are rather small… – Holger Oct 30 '20 at 11:01

1 Answers1

2

If you need a collection of n closest values, you will need to sort and slice the result:

public Iterable<Integer> findClosestNumbers(int givenValue, 
          Iterable<Integer> numbers, int n) {

    return StreamSupport.stream(numbers.spliterator(), false)
            .sorted(Comparator.comparingInt(i -> Math.abs(i - givenValue)))
            .limit(n)
            .collect(Collectors.toList());
}

This will return n (or fewer) numbers in ascending order of their distance from givenValue.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • Thanks! What if there is 2 numbers equally close to given value and i only want the smalles e.g value=5, n=1, but closest= 4 and 6? – Rosso Oct 30 '20 at 10:00
  • 1
    @RossoTheMan then use `Comparator.comparingInt(i -> Math.abs(i - givenValue)).thenComparing(i -> i)` – ernest_k Oct 30 '20 at 10:04
  • nevemind it already does with your solution! – Rosso Oct 30 '20 at 10:07
  • 1
    The code in the answer would return the first one in the iterable when the distance from `givenValue` is the same. You'd have to add that `thenComparing` if you want the smaller of two values at the same distance of it (try `findClosestNumbers(4, Arrays.asList(1, 5, 3, 0, 2, 6), 1)` with both versions, you'll see). – ernest_k Oct 30 '20 at 10:11