Самый короткий способ получить Итератор по диапазону Целых чисел в Java

«Когда может GHC получить экземпляр functor, а когда он не может быть?»

Когда у нас есть преднамеренные структуры круговых данных. Система типов не позволяет нам выразить наше намерение принудительной округлости. Таким образом, ghc может получить экземпляр , подобный , к тому, что мы хотим, но не то же самое.


Структуры круговых данных, вероятно, являются только случай, когда Functor должен быть реализован по-другому. Но опять же, у него будет такая же семантика.

data HalfEdge a = HalfEdge { label :: a , companion :: HalfEdge a }

instance Functor HalfEdge where
    fmap f (HalfEdge a (HalfEdge b _)) = fix $ HalfEdge (f a) . HalfEdge (f b)

EDIT:

HalfEdges - это структуры (известные в компьютерной графике, 3D-сетки ...), которые представляют неориентированные края в графе, где вы можете иметь ссылку на любой конец. Обычно они хранят больше ссылок на соседние HalfEdges, Nodes и Faces.

newEdge :: a -> a -> HalfEdge a
newEdge a b = fix $ HalfEdge a . HalfEdge b

Семантически, нет fix $ HalfEdge 0 . HalfEdge 1 . HalfEdge 2, потому что ребра всегда состоят из ровно двух половинных ребер.


РЕДАКТИРОВАТЬ 2:

В сообществе haskell цитата «Связывание узла» известна такой структурой данных. Речь идет о структурах данных, которые семантически бесконечны, потому что они цикличны. Они потребляют только ограниченную память. Пример: данный ones = 1:ones, мы будем иметь эти семантически эквивалентные реализации twos:

twos = fmap (+1) ones
twos = fix ((+1)(head ones) :)

Если мы пересекаем (первые n элементов) twos и все еще имеем ссылку на начало в этом списке эти реализации отличаются скоростью (оценивайте 1 + 1 каждый раз только один раз) и потребление памяти (O (n) против O (1)).

22
задан cretzel 16 December 2008 в 11:16
поделиться

4 ответа

Простая реализация Вашей домашней работы:

List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
    ints.add(first + i);
}
4
ответ дан Bombe 29 November 2019 в 00:37
поделиться

Непротестированный. При отображении этого на "минуту количество" оставляют как осуществление для читателя.

public class IntRangeIterator implements Iterator<Integer> {
  private int nextValue;
  private final int max;
  public IntRangeIterator(int min, int max) {
    if (min > max) {
      throw new IllegalArgumentException("min must be <= max");
    }
    this.nextValue = min;
    this.max = max;
  }

  public boolean hasNext() {
    return nextValue <= max;
  }

  public Integer next() {
    if (!hasNext()) {
      throw new NoSuchElementException();
    }
    return Integer.valueOf(nextValue++);
  }

  public void remove() {
    throw new UnsupportedOperationException();
  }
}
15
ответ дан Joachim Sauer 29 November 2019 в 00:37
поделиться

Если Вы на самом деле хотите самый короткий объем кода, то ответ Мороженого прекрасен. Однако это сосет память ни на каком серьезном основании. Если бы Вы хотите реализовать его сами, это было бы что-то как:

import java.util.*;

public class IntegerRange implements Iterator<Integer>
{
    private final int start;
    private final int count;

    private int position = -1;

    public IntegerRange(int start, int count)
    {
        this.start = start;
        this.count = count;
    }

    public boolean hasNext()
    {
        return position+1 < count;
    }

    public Integer next()
    {
        if (position+1 >= count)
        {
            throw new NoSuchElementException();
        }
        position++;
        return start + position;
    }

    public void remove()
    {
        throw new UnsupportedOperationException();
    }
}
9
ответ дан Jon Skeet 29 November 2019 в 00:37
поделиться

Это обычно полагало, что хороший стиль раздает Collection и друзья вместо Iterator (см. эта запись FAQ ), таким образом, я рекомендовал бы что-то как [1 110]

public final class IntegerRange implements Set<Integer> {
        final LinkedHashSet<Integer> backingList;
        public IntegerRange(final int start, final int count) {
                backingList = new LinkedHashSet(count, 1.0f);
                for (int i=0; i < count; i++) {
                        backingList.set(i, start + i);
                }       
        }       
        /** Insert a bunch of delegation methods here */
}

и затем просто использовал бы .iterator(), когда необходимо передать Iterator любой платформе, Вы используете.

ОБНОВЛЕНИЕ: Очевидно, этот код не ленив. Если Вы не можете позволить себе дополнительную память наверху хранения (потенциально) 2^32-1 Integer с, необходимо использовать различное решение. Кроме того, ничто о типе не гарантирует, что диапазон будет отсортирован (даже при том, что это, на основе реализации). Если необходимо гарантировать сортировку, Вы могли бы изучить реализацию SortedSet и поддержка ее с TreeSet, но займет больше времени создать диапазон. Честно, если Вы - то, который коснулся разбиранием в деталях, это могло бы стоить Вашего усилия искать библиотеку. Гобелен имеет внутренняя версия , например.

2
ответ дан Hank Gay 29 November 2019 в 00:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: