Разница между IntStream.rangeClosed(x,y) и IntStream.range(x,y 1)

#java #java-8 #java-stream

Вопрос:

IntStream.range(x,y) вернет поток из x(включительно) и y(эксклюзивно). IntStream.rangeClosed(x,y) вернет поток из x(включительно) и y(включительно).

Я ожидал rangeClosed(x,y) , что вызову range(x,y-1) или range(x,y) вызову rangeClosed(x,y-1) . Но при взгляде на исходный код для range этого было похоже:

 if (startInclusive >= endExclusive) {
    return empty();
} else {
    return StreamSupport.intStream(
    new Streams.RangeIntSpliterator(startInclusive, endExclusive, false /*not closed*/), false);
}
 

У rangeClosed него также была очень похожая реализация, а не range(x,y 1) . Единственная разница заключалась в том, что третий аргумент to Streams.RangeIntSpliterator true вместо false обозначения того, что диапазон закрыт.

Это логическое значение затем используется для инициализации int last поля в Streams.RangeIntSpliterator классе, и против него упоминается приведенный ниже комментарий:

1, если диапазон закрыт и последний элемент не был пройден в противном случае, 0, если диапазон открыт или является закрытым диапазоном и все элементы были пройдены

Почему необходима такая реализация, а range не просто вызов rangeClosed или наоборот? Есть ли какая-то существенная разница между вызовом rangeClosed(x,y) вместо range(x,y 1) ?

Ответ №1:

Несмотря на то, что в обычном сценарии нет никаких различий, это вызовет проблему, если входные данные для методов будут иметь минимальные/максимальные пределы Integer .

Предполагая, что rangeClosed(x,y) это вызывает range(x,y 1) . Если вы вызываете rangeClosed(0, Integer.MAX_VALUE) , то вместо ожидаемого числа итераций (2147483648) фактическое число итераций будет равно 0, что Integer.MAX_VALUE 1 приведет к переполнению и будет возвращен пустой поток.

Подобное переполнение приведет к тому, что результат будет отличаться в случае, если входные данные будут Integer.MIN_VALUE .

Комментарии:

1. Интервалы открытия и закрытия представлены с помощью (open, close] . Обратите внимание, что Math.addExact(y, 1) это быстро приведет к сбою и должно использоваться в идеале.

2. @AniketSahrawat Извините, но я не могу понять, что вы пытались донести. Похоже ли это на то, что range(x , Math.addExact(y, 1)) приведет к исключению, а не к неправильному результату по сравнению с тем range(x, y 1) , когда y это MAX_VALUE произойдет ?

3. Да, действительно. Попробуйте range(0 , Math.addExact(Integer.MAX_VALUE, 1)) , это приведет к исключению.

4. @AniketSahrawat Да. Но все равно результат этого отличается от вызова rangeClosed(0, Integer.MAX_VALUE) (который работал бы без исключения). Мой вопрос был более склонен к тому, почему один метод не вызывал другой с точки зрения реализации.