【问题标题】:Finding an element with the Java For each loop使用 Java For each 循环查找元素
【发布时间】:2016-10-24 12:04:59
【问题描述】:

我想使用 For each 遍历一个 LinkedList 并访问我现在所在的元素之后的元素。如果我使用数组和通常的for(int i = 0; i < ... ; i++),我会寻找元素 i+1。有没有可能在我现在所在的元素之后到达元素?

【问题讨论】:

  • LinkedList 实现了List,它有一个get(index) 方法,你可以使用它。
  • 那会做什么? i++ 已经做到了@YoucefLaidani
  • 你能解释清楚吗:Is there a possibility of reaching the element after the one I am at right now?
  • @Lukäs ,如果我理解正确的话,您采用了 LinkedList 数据结构,并尝试进行随机访问。但你确实关心性能。我认为您选择了错误的数据结构...
  • 使用 (List)Iterator;只需在迭代时将“先前”值保留在局部变量中即可。

标签: java for-loop each


【解决方案1】:

如果您使用自动迭代器 for-each 样式循环,例如:

for (T elem: myList) {
    // ...
}

那么当您查看当前元素而不保存对您上次看到的元素的引用时,没有直接的方法可以访问“下一个”元素。也可以使用indexOf,但是当在列表中找到重复项时,这种方法会变得非常混乱。无论如何,我认为您的问题最好使用对列表进行索引来解决。

如果您要迭代 LinkedList 对象使用基于索引的访问(例如,与迭代器或 for-each 相对),您可以这样做:

for (int i = 0; i < myList.size(); i++) {
    // ...
    if ((i + 1) < myList.size()) {
        T nextElem = myList.get(i+1); // fetch the element at the next index
        // then do whatever you want with "nextElem"
    }
    // ...
}

其中T 指的是您正在使用的LinkedList 的类型,即String,如果您的列表定义类似于LinkedList&lt;String&gt; myList = new LinkedList&lt;&gt;();

【讨论】:

    【解决方案2】:

    是否有可能到达我现在所在的元素之后的元素?

    如果您使用简单的“for each”循环,则不会。列表中的“当前位置”被编码为列表的Iterator。当您使用“for each”时,Iterator 对您的应用程序隐藏。

    相反,您需要执行以下操作:

    List<Element> list = ...
    Element current = null;
    Element next = null;
    Iterator<Element> it = list.iterator();
    while (it.hasNext()) {
        current = next;
        next = it.next();
        if (current == null) {
            continue;
        }
        // process 'current' and use `next` when you need to refer to 
        // the following on element.
    }
    if (next != null) {
        // process 'next' as the last element.
    }
    

    注意事项:

    1. 如果null 是一个有效的列表元素,则使用一个标志来代替。
    2. 对同一个列表使用两个迭代器可能会为您提供更简洁的解决方案。
    3. 您也可以使用for each ... 执行类似的操作,并跟踪变量中的“前一个”元素,就像我在上面所做的那样。请参阅@Jezor 的回答。
    4. 不建议在(大)LinkedList 上使用get(i),因为在一般情况下,get(int)O(N)O(N) 操作。

    【讨论】:

    • “不”有点难,你不觉得吗?大多数可能性是低效的,但仍然“可能”......(忽略重复)
    • 这不会一次遍历列表两个“步骤”吗?例如,每次返回循环顶部时,您会点击元素#0、#2、#4、...等,而不是#0、#1、#2...(不是说这是错了,只是需要考虑的事情。)
    • @ChrisSprague - 再读一遍。每次循环只有一个next() 调用。
    • @StephenC 啊,你是对的。我以为你是在暗示随后在正文中调用next(),但我明白你现在在做什么。而且,您正在考虑 current 在第一遍中为空。我的错。
    【解决方案3】:

    您既不能确定enhanced for loop 中下一个元素的索引,也不能确定它的值。

    您可以保留对前一个元素的引用:

    // List is initialized somewhere in the code.
    List<Element> elements = ...;
    
    Element previousElement = null;
    for (Element element: elements) {
        if (previousElement != null) {
            // ... your code here...
            // previousElement is elements[i]
            // element is elements[i + 1]
        }
    
        previousElement = element;
    } 
    

    在上面的示例中,您可以使用 null object 实例化 previousElement 以避免空检查。

    你真正想要使用的是好的,带有计数器的旧 for 循环:

    List<Element> elements = ...;
    
    for (int i = 0; i < elements.size(); ++i) {
        // elements.get(i) is elements[i]
        // elements.get(i + 1) is elements[i + 1]
        // But be careful, (i + 1) will be out of bounds for the last element!
    }
    

    不要让你的生活变得不必要地复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      相关资源
      最近更新 更多