【问题标题】:Java - How do I refer to the previous and next element during an iteration?Java - 如何在迭代期间引用上一个和下一个元素?
【发布时间】:2012-01-23 19:17:55
【问题描述】:

当我有一个 for 循环时,我使用 i 来引用我的数组、对象等的元素。

喜欢:
当前项目:myArray[i]
下一条:myArray[i+1]
上一条:myArray[i-1]

但目前,我正在使用 foreach 循环 (for (Object elem : col) {)。
如何参考上一项?
(我需要搜索一个“数组”,我正在使用for (Object object : getComponents())

但是当它返回 true 时(所以它会找到我要查找的内容),它应该执行 previousnext 项上的代码。

澄清:我有java.awt.Component元素!

【问题讨论】:

  • (我可以考虑一种解决方法,例如使用临时/一次性整数来“标记”这些项目。比如 tempInt1、tempInt2。我会使用一个额外的标记,如果它返回 true,我会使用这些整数,例如: tempInt2 = mark-1 和 tempInt2 = mark+1。然后只需操作标记的整数。)
  • 但我想必须有一种更清洁的方法来做到这一点。 :D
  • 为什么不去正常的for循环呢?
  • @Bhushan - 缺乏正常教育......我猜? :)
  • foreach 循环是实用的,但非常有限。我经常不得不使用旧的 for 循环。

标签: java loops foreach


【解决方案1】:

foreach 循环不会让您这样做。我的建议是重新使用老式的Iterator。例如

final Iterator itr=getComponents().iterator();
Object previous=itr.next();
Object current=itr.next();
while(itr.hasNext()){
    Object next=itr.next();
    //Do something with previous, current, and next.
    previous=current;
    current=next;
}

【讨论】:

  • 我会在 15 分钟内尝试并报告。谢谢!
  • 在 while 循环之前对 itr.next() 的两次调用不会导致 while 循环从集合中的第三个元素开始吗?
  • @DaveHowes 有 3 个变量:上一个、当前和下一个。
  • @Jack:我有 java.awt.components...,因此迭代器给了我一个错误。 :-/
  • @DaveHowes 循环开始时,previous 是第一个元素,current 是第二个元素,next 成为第三个元素。我可能应该设置一些保护措施,以防列表没有 3 个元素,但我担心这可能会使代码混乱并使其更难理解。
【解决方案2】:

如果数据结构是一个列表,那么你可以直接使用ListIterator。 ListIterator 很特别,因为它同时包含next()previous() 方法

List list = ...;
ListIterator iter = list.listIterator(); //--only objects of type List has this
while(iter.hasNext()){
    next = iter.next();
    if (iter.hasPrevious()) //--note the usage of hasPrevious() method
       prev = iter.previous(); //--note the usage of previous() method
}

【讨论】:

  • 当然,应该注意previous()将迭代器向后移动,这意味着对'next()`和'previous()`的一对调用将导致让迭代器留在原地的净效果。
  • 同样的事情,类似 awt 的对象有问题。我应该将它们转换为列表,还是将值转换为列表,更改值然后返回 *objects?
  • @X-Zero,对,这就是为什么我在代码cmets中明确提到的原因,目的只是为了展示用法:)
  • @Suraj - 你没有提到previous() 移动了迭代器根本(尽管它可能因为next() 而无法推断)。 hasPrevious() 所做的只是防止抛出异常 - 你需要在其中再次调用 next() 才能真正推进循环......
  • 如其他 cmets 中所述,请注意此代码不会推进迭代器,因此不会像 OP 预期的那样工作。最后你需要另一个 next() 以使其正常工作,这最终不是一个特别干净的解决方案。
【解决方案3】:
JButton prev, next, curr;
Component[] arr = getComponents();

for(int i=1;i<arr.length-1;i++) {
    if (yourcondition == true) {
        curr = (JButton) arr[i];
        prev = (JButton) arr[i-1];
        next = (JButton) arr[i+1];
    }
}

【讨论】:

    【解决方案4】:

    数组索引

    如果你有一个类似数组的数据结构(例如一个实际的数组或类似ArrayList的东西),那么引用ii-1i+1会很好性能,所以没有更多的东西。 (尽管必须将 For-Each 循环转换为索引计数 For Loop 并不是很有趣,并且是少数需要注意的地方之一。)

    Sergey 提供的答案是这样的。

    多才多艺的ListIterator

    如果您可以得到ListIterator(这实际上是一个很大的假设),那么 Suraj 提供的答案就足够了。但请注意next()previous() 移动迭代器位置。因此,如果您为每个循环迭代执行以下操作:prev = previous(); current = next(); next = next(); previous(),您最终将在每个循环中执行大约 4 次迭代操作。如果迭代很便宜,这不是什么大问题,幸运的是,提供ListIterator 的数据结构通常就是这种情况。

    通用解决方案

    任何Iterable(或Iterator)的通用解决方案都不应进行随机查找(就像使用数组一样)或对next()的性能做出假设,最多应调用N次,其中N是可用元素的数量。

    这是一个这样的实现:

    final Iterator<E> it = iterable.iterator();
    
    for (E next = (it.hasNext() ? it.next() : null), current = null; next != null;) {
        E previous = current;
        current = next;
        next = it.hasNext() ? it.next() : null;
    
        // Do something using 'current', 'previous' and 'next'.
        // NB: 'previous' and/or 'next' are null when 'current' is
        // the first and/or last element respectively
    }
    

    请注意,此实现有其自身的警告:

    • 如果Iterable 包含null 元素,它将中断。
    • currentnext 都不是有效的最终,因此不能直接在它们中使用尖刻的 Java 8 lambda。

    【讨论】:

      【解决方案5】:

      我这样做是为了在使用增强的 for 循环时访问列表中的上一个和下一个元素。

      这是一个快速的 sn-p:

      import java.util.ArrayList;
      import java.util.List;
      
      class Scratch {
      
        public static void main(String[] args) {
          List<Integer> myInts = new ArrayList<>();
          myInts.add(1);
          myInts.add(2);
          myInts.add(3);
          myInts.add(4);
          myInts.add(5);
      
          Integer next = null;
          Integer previous = null;
      
          for (Integer current: myInts) {
              try {
                      previous = myInts.get(myInts.indexOf(current)-1);
                  } catch (IndexOutOfBoundsException ignored){
                     // ignored
                  }
              try {
                      next = myInts.get(myInts.indexOf(current)+1);
                  } catch (IndexOutOfBoundsException ignored){
                      next = null;
                  }
              System.out.println("previous = " + previous);
              System.out.println("current = " + current);
              System.out.println("next = " + next);
          }
        }
      }
      

      输出:

      previous = null
      current = 1
      next = 2
      previous = 1
      current = 2
      next = 3
      previous = 2
      current = 3
      next = 4
      previous = 3
      current = 4
      next = 5
      previous = 4
      current = 5
      next = null
      

      是的!我知道,代码很难看。但是,它完成了工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-01
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 2017-07-15
        相关资源
        最近更新 更多