java 使用 next() 调用 ArrayList 的下一次迭代

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16244205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 22:22:22  来源:igfitidea点击:

Using next() to call next iteration of ArrayList

javaarraylistnext

提问by ivanthemeh

Having a little bit of trouble with the iterator next(). Can't seem to get it to work properly. I've been working on this code for a while so I was thinking another set of eyes would help.

迭代器 next() 有点麻烦。似乎无法让它正常工作。我已经在这段代码上工作了一段时间,所以我认为另一组眼睛会有所帮助。

This is my deck class with creates a list of Card objects, I'm trying to make a method to grab the next Card in the list starting with the first one:

这是我的甲板类,它创建了一个 Card 对象列表,我正在尝试创建一种方法来从第一个开始获取列表中的下一张卡片:

package blackHyman;

import blackHyman.Card.Rank;
import blackHyman.Card.Suit;
import java.util.*;

public class Deck {

public ArrayList<Card> cards = new ArrayList<>();
int i;
Card next;

public Deck() {
    initializeDeck();

}

public void printDeck() {
    for (Card c: cards)
        System.out.println(c);
}

private void initializeDeck() {
    for (Suit suit : Suit.values()) {
        for (Rank rank : Rank.values()) {
            cards.add(new Card(rank, suit));
        }
    }
}

public Card getNextCard() {
    if (cards.listIterator().hasNext() != true) {
        getNextCard();
    }
    else {
        next = cards.listIterator().next();
    }
      return next; 
}
}

This is my main class where I call the getNextCard() and what I'm thinking it should do is print the first and then the next Card in the list but what it's doing is printing the first Card twice.

这是我调用 getNextCard() 的主类,我认为它应该打印列表中的第一张卡片,然后打印下一张卡片,但它所做的是打印第一张卡片两次。

package blackHyman;

import java.util.*;

public class BlackHyman {

public static void main(String[] args) {
    Deck deck = new Deck();
    System.out.println(deck.getNextCard());
    System.out.println(deck.getNextCard());
    }

}

Thanks in advance for any help!

在此先感谢您的帮助!

回答by mdierker

In your getNextCard()method, you're creating an iterator every time it's called. Iterators always start at index 0 (although there is a listIterator(index)method), but you shouldn't need it.

在您的getNextCard()方法中,每次调用时都会创建一个迭代器。迭代器总是从索引 0 开始(虽然有一个listIterator(index)方法),但你不应该需要它。

Option 1:Keep track of the iterator, and use the same iterator each time. However, this has an important shortcoming not pointed out by anyone else yet. From the Javadoc:

选项 1:跟踪迭代器,并且每次都使用相同的迭代器。但是,这有一个重要的缺点,其他人还没有指出。来自 Javadoc:

The iterators returned by this class's iteratorand listIteratormethods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

此类iteratorlistIterator方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法外,迭代器将抛出一个ConcurrentModificationException.

Translation: If you modify the list in any way outside of the iterator (say, by adding a card to the end of the list), then your iterator breaks. This leads us to option 2:

翻译:如果您在迭代器之外以任何方式修改列表(例如,通过在列表末尾添加一张卡片),那么您的迭代器就会中断。这导致我们选择选项 2:

Option 2:Keep a counter of the index you returned last, and simply return that each time. Something like:

选项 2:保留您上次返回的索引的计数器,并且每次都简单地返回该计数器。就像是:

public class Deck {

public ArrayList<Card> cards = new ArrayList<>();
Card next;
int currentCardIndex = -1;

/* The initialization stuff you have above */

public Card getNextCard() {

    currentCardIndex++;

    // If we're at the end, go back to the beginning
    if (currentCardIndex >= cards.size()) {
        currentCardIndex = 0;
    }

    return (next = cards.get(currentCardIndex));
}

And finally Option 3: (not advised): If you really wanted to, you could catch the ConcurrentModificationExceptionand generate a new iterator at that point, but there's not really a reason to unless you need some iterator-specific feature. (The get()call is just as fast as an interator - both are constant time).

最后选项 3:(不建议):如果你真的想要,你可以ConcurrentModificationException在那个时候捕获并生成一个新的迭代器,但没有真正的理由,除非你需要一些特定于迭代器的功能。(get()调用与 interator 一样快 - 两者都是恒定时间)。

回答by Duncan Jones

You need to save the iterator returned by cards.listIterator().

您需要保存由 返回的迭代器cards.listIterator()

Your code creates a new one each time, meaning you always get the first element.

你的代码每次都会创建一个新的,这意味着你总是得到第一个元素。

回答by Laf

You always get the first card because you are creating a new iterator each time you call the getNextCard ()method. The line

您总是得到第一张卡片,因为每次调用该getNextCard ()方法时您都在创建一个新的迭代器。线

next = cards.listIterator().next();

will always create a new iterator. What you want to do would look like (assuming you want to create a new ListIteratorinstance each time you have reached the last card of the deck):

将始终创建一个新的迭代器。你想要做的看起来是这样的(假设你ListIterator每次到达牌组的最后一张牌时都想创建一个新实例):

private ListIterator<Card> myIterator = null;

public Card getNextCard() {
    if (myIterator == null || !myIterator.hasNext ()) {
        myIterator = cards.listIterator ();
    }

    return myIterator.next(); 
}