在这种情况下如何使用迭代器?

时间:2010-09-24 05:47:20

标签: java iterator arraylist

我必须以这种方式迭代一个arraylist。

ArrayList<Integer> li = new ArrayList<Integer>();
li.add(20);
li.add(30);
li.add(40);
li.add(50);
li.add(70);

for (int i = 0; i < li.size() - 1; i++)
    System.out.println(li.get(i) + " " + li.get(i + 1));

输出:

20 30
30 40
40 50
50 70

如何使用迭代器做同样的事情?

4 个答案:

答案 0 :(得分:6)

使用两个迭代器。我测试了这个,它对我有用。

    Iterator<Integer> first = li.listIterator();

    // Will raise IndexOutOfBoundsException if list is empty.
    Iterator<Integer> second = li.listIterator(1);

    while (second.hasNext()) {
        System.out.println(first.next() + " " + second.next());
    }

修改:无需内部if。傻我。

说明:listIterator(index)方法返回一个迭代器,该迭代器从列表中的指定位置开始,其中listIterator()返回从零位开始的迭代器。

first迭代器因此从0开始,second1开始。那么这只是在两者上打印next()的问题。无论列表中的元素数量是奇数还是偶数,这都将起作用。

修改2

我今天的逻辑很弱。感谢@barjak指出有关空列表和不必要的first.hasNext()的案例。

答案 1 :(得分:1)

这有点复杂:

Iterator<Integer> iter = li.iterator();
if (iter.hasNext()) {
    for (int y = iter.next(), x; iter.hasNext(); y = x) {
        x = iter.next();
        System.out.println(y + " " + x);
    }
}

或:

if (iter.hasNext()) {
    for (int x = iter.next(); iter.hasNext();) {
        System.out.println(x + " " + (x = iter.next()));
    }
}

答案 2 :(得分:1)

略微修改Sagar V的解决方案,使其工作。一个迭代器足以实现这一目标。

Iterator iter = li.iterator();
        Integer int1 = null;

        while (iter.hasNext()) {
            if (int1 == null) {
                int1 = (Integer) iter.next();
            }

            System.out.print(int1 + " ");
            if (iter.hasNext()) {
                Integer int2 = (Integer) iter.next();
                System.out.println(int2);
                int1 = int2;
            } else {
                break;
            }
        }
    }

答案 3 :(得分:0)

有许多解决方案,根据您的需要而定。

解决方案1:固定大小视图

迭代列表子集的经典方法是创建原始列表的较窄视图,并迭代整个视图。 subList方法用于创建此类视图。

List<Integer> l = // initialization code

int limitIndex = Math.max(l.size()-1, 0); // needed for empty list
for (int v : l.subList(0, limitIndex)) {
    // your code
}

请注意,我使用了'foreach'循环,这是一种使用迭代器的便捷方法。这完全等同于此代码:

Iterator<Integer> it = l.subList(0, limitIndex).iterator();
while(it.hasNext()) {
    int v = it.next();
    // your code
}

另请注意,subList方法不会创建新列表:它只会在原始列表中创建“视图”。不会复制原始列表的内容,并且可以从subList创建的列表中看到对原始列表所做的所有更改。

解决方案2:自定义Iterator / Iterable

如果你需要的是一个总是从0迭代到n-1的迭代器,你可以定义一个适合特定需求的新Iterable

public class NoLastIterable<T> implements Iterable<T> {

    private final List<T> backend;

    public NoLastIterable(List<T> backend) {
        this.backend = backend;
    }

    public Iterator<T> iterator() {
        return new Iterator<T>() {

            private int nextIndex;

            public boolean hasNext() {
                return nextIndex < backend.size() -1;
            }

            public T next() {
                return backend.get(nextIndex++);
            }

            public void remove() {
                throw new UnsupportedOperationException("not implemented");
            }

        };
    }
}

这个类的用法如下:

for (int v : new NoLastIterable<Integer>(l)) {
    // your code
}

解决方案3

您甚至可以创建List的自定义视图,就像subList一样,但具有更大的灵活性。

public class NoLastList<T> extends AbstractList<T> {

    private final List<T> backend;

    public NoLastList(List<T> backend) {
        this.backend = backend;
    }

    @Override
    public T get(int index) {
        if (index >= size()) {
            throw new IndexOutOfBoundsException();
        }
        return backend.get(index);
    }

    @Override
    public int size() {
        return Math.max(0, backend.size()-1);
    }

}

与其他解决方案的用法相同:

for (int v : new NoLastList<Integer>(l)) {
    // your code
}

在以下情况下可以看到此解决方案的好处:

  1. 创建并初始化原始列表
  2. 创建NoLastList实例(作为原始列表的视图)
  3. 将一些元素添加到原始列表中
  4. 在这种情况下,迭代NoLastList将考虑最近添加的元素。 NoLastList始终表示从0到n-1的元素视图,即使n(大小)发生变化也是如此。