代码之家  ›  专栏  ›  技术社区  ›  cretzel

在Java中获取整数范围内的迭代器的最短路径

  •  20
  • cretzel  · 技术社区  · 17 年前

    在Java的整数范围内获得迭代器的最短路径是什么?换言之,执行以下步骤:

    /** 
    * Returns an Iterator over the integers from first to first+count.
    */
    Iterator<Integer> iterator(Integer first, Integer count);
    

    类似的东西

    (first..first+count).iterator()
    
    7 回复  |  直到 10 年前
        1
  •  5
  •   Bombe    17 年前

    直接执行作业:

    List<Integer> ints = new ArrayList<Integer>();
    for (int i = 0; i < count; i++) {
        ints.add(first + i);
    }
    
        2
  •  65
  •   Saintali    10 年前

    此实现没有内存占用。

    /**
     * @param begin inclusive
     * @param end exclusive
     * @return list of integers from begin to end
     */
    public static List<Integer> range(final int begin, final int end) {
        return new AbstractList<Integer>() {
                @Override
                public Integer get(int index) {
                    return begin + index;
                }
    
                @Override
                public int size() {
                    return end - begin;
                }
            };
    }
    

    编辑:

    在Java 8中,你可以简单地说:

    IntStream.range(begin, end).iterator()                // returns PrimitiveIterator.OfInt
    

    或者如果您需要盒装版本:

    IntStream.range(begin, end).boxed().iterator()        // returns Iterator<Integer>
    
        3
  •  15
  •   Joachim Sauer    17 年前

    未经测试的。把它映射到“min,count”上,留给读者作为练习。

    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();
      }
    }
    
        4
  •  9
  •   Jon Skeet    17 年前

    如果你真的想要最短数量的代码,那么Bombe的答案是好的。然而,它毫无理由地吸走了记忆。如果您希望自己实现它,它将类似于:

    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();
        }
    }
    
        5
  •  7
  •   Lee    14 年前

    使用guava框架的示例。注意,这不会具体化集合(尽管您必须读取continousset实现来验证这一点)。

    import com.google.common.collect.ContiguousSet;
    import com.google.common.collect.DiscreteDomain;
    import com.google.common.collect.DiscreteDomains;
    
    class RangeIterator { 
    
        public Iterator<Integer> range(int start, int length) {
            assert length > 0;
            Range<Integer> dim_range = Ranges.closedOpen(start, start + length);
            DiscreteDomain<Integer> ints = DiscreteDomains.integers();
            ContiguousSet<Integer> dim = dim_range.asSet(ints);
            return dim.iterator();
        }
    }
    
        6
  •  4
  •   btpka3    10 年前

    在Java 8中使用流API的示例:

    int first = 0;
    int count = 10;
    Iterator<Integer> it = IntStream.range(first, first + count).iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
    

    如果没有迭代器,它可以是:

    int first = 0;
    int count = 10;
    IntStream.range(first, first + count).forEach(i -> System.out.println(i));
    
        7
  •  2
  •   Hank Gay    17 年前

    通常认为传球是很好的方式 Collection 而不是朋友 Iterator (见 this FAQ entry )所以我推荐一些

    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() 当你需要通过 迭代器 不管你使用的是什么框架。

    更新:显然,这段代码并不懒惰。如果您负担不起额外的内存存储开销(可能)2^32-1 Integer S,您应该使用不同的解决方案。此外,类型的任何内容都不能保证范围将被排序(即使它是基于实现的)。如果您需要保证排序,可以研究实现 SortedSet 然后用一个 TreeSet ,但建立范围需要更长的时间。老实说,如果你关心细节的正确性,那么寻找一个图书馆可能是值得的。挂毯有一个 internal version 例如。