【问题标题】:java/guava - start and stop at certain index of iterable/iteratorjava/guava - 在可迭代/迭代器的某个索引处开始和停止
【发布时间】:2015-01-03 10:57:13
【问题描述】:

我正在寻找一种优雅的方式(可能使用 Guava)来包装 Iterable/Iterator,以便新的 Iterable/Iterator

  • 从某个索引开始,并且
  • 停在某个索引处。

Guava 似乎具有限制输入的功能(http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Iterables.html#limit(java.lang.Iterable,%20int),但不是从给定索引开始。我需要两者的组合。

你会怎么做?

【问题讨论】:

    标签: java iterator guava iterable


    【解决方案1】:

    您可以为此使用skip

    返回跳过第一个 numberToSkip 元素的 iterable 视图。

    例如,以下将为您提供一个跳过前两个元素的 Iterable,然后将其限制为接下来的五个:

    List<Integer> list = [0, ..., 10];
    Iterable<Integer> iterable = Iterables.limit(Iterables.skip(list, 2), 5); //[2, 3, 4, 5, 6]
    

    请注意,参数不被视为索引,而是被视为要跳过(或限制)的元素的数量。但是,如果您知道要跳过多少个元素,则很容易计算结束索引。

     import static com.google.common.collect.Iterables.limit;
     import static com.google.common.collect.Iterables.skip;
    
     ...
    
     static <T> Iterable<T> bounded(Iterable<T> iterable, int startIndex, int lastIndex) {
         return limit(skip(iterable, startIndex+1), lastIndex-startIndex);
     }
    
     bounded(list, 2, 5)//[3, 4, 5]
    

    只有在底层数据结构使用索引(例如ArrayList)对其元素进行排序时,后者才有意义。

    但它也可能是HashSet,并且在HashSet 中的给定索引处开始和停止是没有意义的,因为它是无序的(即不要指望limit(skip(mySet, 2), 5) 会为您提供元素3, 4, 5回)


    使用,您可以使用新的 Stream API,它也有那些跳过和限制方法。

    static <T> Iterable<T> bounded(Iterable<T> iterable, int startIndex, int lastIndex) {
          return StreamSupport.stream(iterable.spliterator(), false)
                              .skip(startIndex+1)
                              .limit(lastIndex-startIndex)
                              .collect(Collectors.toList());
    }
    

    【讨论】:

    • 谢谢!我真的忽略了跳过功能。我会试试看。
    【解决方案2】:

    确实没有一种有效的方法来做到这一点,因为迭代器是如此通用。没有什么可以告诉您底层数据结构将有任何方式跳转到中间以找到给定的索引。想想一个链表:你可以索引 k 的唯一方法是遍历链表。

    您需要围绕您的Iterator 创建一个包装器,并将接口方法委托给底层Iterator,但是为hasNext()next() 方法添加一些额外的逻辑,如果是remove()您需要移除支持。第一次调用其中一个时,它需要遍历底层列表以找到起始索引,并设置一个私有标志来指示它已经这样做了;如果有足够的元素到达起始索引,则它可以分别返回 true 或元素。

    在正确的地方停下来更容易(也更有效):保留一个私人的int 来跟踪您当前所在的索引,当您到达结束索引时,让hasNext() 返回false,和next() 抛出NoSuchElementException

    如果您希望能够随时删除元素,那应该很容易:您可以委托给底层remove(),但首先检查(如上)您还没有达到结束索引。

    【讨论】:

      猜你喜欢
      • 2019-05-25
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-24
      • 2011-09-11
      • 2016-02-06
      • 2015-04-30
      相关资源
      最近更新 更多