Java: эквивалент диапазона Python (int, int)?

99

Есть ли в Java эквивалент range(int, int)метода Python ?

Ник Хайнер
источник
Вы имеете в виду диапазон Python 2.x, который возвращает список, или диапазон Python 3.x, который возвращает итератор (эквивалентный диапазону 2.x xrange)? Первый вариант относительно прост в реализации, как и другие, описанные ниже, но версия с итератором немного сложнее.
Дэйв Кирби,
Для диапазона любых Comparables см. Этот ответ
c0der
Для диапазона со степпингом см. Это
Славомир Ленарт

Ответы:

27

Guava также предоставляет нечто похожее на Python range:

Range.closed(1, 5).asSet(DiscreteDomains.integers());

Вы также можете реализовать довольно простой итератор, чтобы делать то же самое, используя AbstractIterator Guava:

return new AbstractIterator<Integer>() {
  int next = getStart();

  @Override protected Integer computeNext() {
    if (isBeyondEnd(next)) {
      return endOfData();
    }
    Integer result = next;
    next = next + getStep();
    return result;
  }
};
Саймон Стил
источник
6
Мне жаль, что я не видел этого, прежде чем я реализовал свой собственный общий диапазон. Это приятно, но это еще одно напоминание о том, насколько неуклюжая Java может быть сравнена с более функциональными языками.
z7sg Ѫ
14
Range#asSetпохоже, устарело. Теперь вам нужно сделать это:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Chthonic Project
какую библиотеку мне нужно импортировать, чтобы использовать это?
tgabb
Начиная с Java 8, IntStream и LongStream имеют методы range и rangeClosed.
Хосе Мануэль Гомес Альварес
225

Старый вопрос, новый ответ (для Java 8)

    IntStream.range(0, 10).forEach(
        n -> {
            System.out.println(n);
        }
    );

или со ссылками на методы:

IntStream.range(0, 10).forEach(System.out::println);
Jhodges
источник
1
Какой пакет? как мне его импортировать?
Джастин Томас
6
@Justin Это функция языка Java 8.
Tzafrir
16

Начиная с Guava 15.0, Range.asSet () устарел, и его планируется удалить в версии 16. Используйте вместо этого следующее:

ContiguousSet.create(Range.closed(1, 5), DiscreteDomain.integers());
цзеханьчжэн
источник
15

Я работаю над небольшой библиотекой утилит Java под названием Jools , и она содержит класс, Rangeкоторый обеспечивает необходимую вам функциональность (есть загружаемый JAR).
Конструкторы либо Range(int stop), Range(int start, int stop)или Range(int start, int stop, int step)(подобно к для цикла) , и вы можете либо итерацию через него, которые используются ленивые вычисления, или вы можете использовать его toList()метод явно получить список диапазона.

for (int i : new Range(10)) {...} // i = 0,1,2,3,4,5,6,7,8,9

for (int i : new Range(4,10)) {...} // i = 4,5,6,7,8,9

for (int i : new Range(0,10,2)) {...} // i = 0,2,4,6,8

Range range = new Range(0,10,2);
range.toList(); // [0,2,4,6,8]
Амир Рачум
источник
14
public int[] range(int start, int stop)
{
   int[] result = new int[stop-start];

   for(int i=0;i<stop-start;i++)
      result[i] = start+i;

   return result;
}

Простите за любые синтаксические или стилистические ошибки; Обычно я программирую на C #.

KeithS
источник
учитывая, что Вивьен Барусс опередила вас с ответом, почему бы вам не удалить свой, чтобы избежать дублирования. Если, конечно, вы действительно не планируете красиво его воплощать.
aaronasterling,
9
Они похожи; Думаю, мой немного читабельнее. Его использование «длины» вводит в заблуждение, и я не думаю, что он соответствует спецификации Python (он включает верхнюю границу, которая, по словам network-theory.co.uk/docs/pytut/rangeFunction.html , не встречается в Python ). Если вы думаете, что это обман, я считаю, что у вас достаточно репутации, чтобы справиться с этим самостоятельно.
KeithS
10

Вы можете использовать следующий фрагмент кода, чтобы получить диапазон целых чисел:

    Set<Integer> iset = IntStream.rangeClosed(1, 5).boxed().collect
            (Collectors.toSet());
Юлиан
источник
7
public int[] range(int start, int length) {
    int[] range = new int[length - start + 1];
    for (int i = start; i <= length; i++) {
        range[i - start] = i;
    }
    return range;
}

(Длинный ответ, чтобы просто сказать «Нет»)

Вивьен Барусс
источник
Также обратите внимание, что «диапазон» в Python 3 и предпочтительный «xrange» в Python 2 возвращают «живой» объект, который не использует память для каждого содержащегося в нем элемента. Это было бы еще больше для реализации на Java.
jsbueno
3

Java 9 - IntStream::iterate

Начиная с Java 9 вы можете использовать IntStream::iterateи даже можете настроить шаг. Например, если вам нужен intмассив:

public static int[] getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .toArray();
}

или List:

public static List<Integer> getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .boxed()
            .collect(Collectors.toList());
}

А потом используйте это:

int[] range = getInRange(0, 10, 1);
Михалк
источник
2

Изящный класс Groovy Range можно использовать из Java, хотя он, конечно, не так хорош.

Джон
источник
2

Библиотека «Функциональная Java» позволяет программировать таким образом в ограниченной степени, она имеет метод range (), создающий экземпляр fj.data.Array.

Видеть:

Точно так же библиотека «Totally Lazy» предлагает метод отложенного диапазона: http://code.google.com/p/totallylazy/

ткрузе
источник
1

Если вы хотите использовать его, как в цикле Python, Java прекрасно зацикливается с оператором for, который делает эту структуру ненужной для этой цели.

Никки9696
источник
5
Вы также обычно не используете его для цикла в Python. Почти всегда есть более чистый способ итерации.
Daenyth
Ну, диапазон обычно используется в цикле for. Но циклы for часто используются без диапазона.
FogleBird,
1
IntStream.range(0, 10).boxed().collect(Collectors.toUnmodifiableList());
Пьер
источник
1
Было бы полезно, если бы вы объяснили, как этот код решает проблему.
Роберт Колумбия
0

Я знаю, что это старый пост, но если вы ищете решение, которое возвращает поток объектов и не хотите или не можете использовать какие-либо дополнительные зависимости:

Stream.iterate(start, n -> n + 1).limit(stop);

начало - включительно стоп - исключительное

HDubz
источник