我们可以用Java编写自己的迭代器吗?

pho*_*nix 92 java iterator

如果我有一个包含的列表,[alice, bob, abigail, charlie]并且我想编写一个迭代器,以便迭代以'a'开头的元素,我可以编写自己的吗?我怎样才能做到这一点 ?

Mar*_*les 185

最好的可重用选项是实现Iterable接口并覆盖方法iterator().

下面是一个类似ArrayList的实现接口的示例,在该类中重写Iterator()方法.

import java.util.Iterator;

public class SOList<Type> implements Iterable<Type> {

    private Type[] arrayList;
    private int currentSize;

    public SOList(Type[] newArray) {
        this.arrayList = newArray;
        this.currentSize = arrayList.length;
    }

    @Override
    public Iterator<Type> iterator() {
        Iterator<Type> it = new Iterator<Type>() {

            private int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return currentIndex < currentSize && arrayList[currentIndex] != null;
            }

            @Override
            public Type next() {
                return arrayList[currentIndex++];
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
        return it;
    }
}
Run Code Online (Sandbox Code Playgroud)

该类使用Generics实现Iterable接口.考虑到你有数组的元素,你将能够获得一个Iterator的实例,例如,"foreach"循环所使用的实例.

你可以创建一个迭代的匿名实例,而无需创建扩展迭代器,并采取currentSize的价值优势来验证,直到您可以在阵列(假设你创建了10个容量的阵列上浏览,但你只有2元素在0和1).本实例将拥有的地方是它的主人柜台,所有你需要做的就是hasNext(),它验证是否当前值不为空玩了,下一个(),它会回报你CURRENTINDEX的实例.以下是使用此API的示例...

public static void main(String[] args) {
    // create an array of type Integer
    Integer[] numbers = new Integer[]{1, 2, 3, 4, 5};

    // create your list and hold the values.
    SOList<Integer> stackOverflowList = new SOList<Integer>(numbers);

    // Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
    for(Integer num : stackOverflowList) {
        System.out.print(num);
    }

    // creating an array of Strings
    String[] languages = new String[]{"C", "C++", "Java", "Python", "Scala"};

    // create your list and hold the values using the same list implementation.
    SOList<String> languagesList = new SOList<String>(languages);

    System.out.println("");
    // Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
    for(String lang : languagesList) {
        System.out.println(lang);
    }
}
// will print "12345
//C
//C++
//Java
//Python
//Scala
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以使用Iterator实例迭代它:

// navigating the iterator
while (allNumbers.hasNext()) {
    Integer value = allNumbers.next();
    if (allNumbers.hasNext()) {
        System.out.print(value + ", ");
    } else {
        System.out.print(value);
    }
} 
// will print 1, 2, 3, 4, 5
Run Code Online (Sandbox Code Playgroud)

foreach文档位于http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html.您可以在我的个人练习谷歌代码中查看更完整的实现.

现在,了解你需要什么,我认为你需要插上迭代器的过滤器的概念.既然迭代器依赖于下一个值,这将是很难在hasNext(返回true效果),然后使用不以char"a"开头的值过滤next()实现.我认为您需要使用具有给定过滤器的值的过滤列表来使用辅助Interator.

  • `例如`,是一个双关语? (12认同)
  • 其他30个人并不认为这是双关语:) (4认同)
  • 从我们实现的方法中抛出不受支持的操作异常是一个好习惯.我认为从remove()方法抛出不受支持的操作异常是个好主意! (2认同)
  • 对不起@darshan,但这个解决方案是关于"如何编写迭代器"...如果重点是"编写完美编写的代码",那就是那里! (2认同)

T.J*_*der 44

当然.迭代器只是java.util.Iterator接口的一个实现.如果您正在使用现有的可迭代对象(例如,a LinkedList)java.util,则需要对其进行子类化并覆盖其iterator函数以便您返回自己的函数,或者提供在特殊Iterator实例中包装标准迭代器的方法(具有更广泛使用的优点)等.

  • 很好的答案.... + 1但是你没有被迫子类化LinkedList.您可以编写一个CustomIterator,它使用新的CustomIterator(somelist)进行实例化,因为接口不会告诉构造函数. (7认同)

Vah*_*yan 11

Iterable计算阶乘的好例子

FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
     System.out.println(iterator.next());
}
Run Code Online (Sandbox Code Playgroud)

Java 1.8的简短代码

new FactorialIterable(5).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

自定义Iterable类

public class FactorialIterable implements Iterable<Integer> {

    private final FactorialIteartor factorialIteartor;

    public FactorialIterable(Integer value) {
        factorialIteartor = new FactorialIteartor(value);
    }

    @Override
    public Iterator<Integer> iterator() {
        return factorialIteartor;
    }

    @Override
    public void forEach(Consumer<? super Integer> action) {
        Objects.requireNonNull(action);
        Integer last = 0;
        for (Integer t : this) {
            last = t;
        }
        action.accept(last);
    }

}
Run Code Online (Sandbox Code Playgroud)

自定义迭代器类

public class FactorialIteartor implements Iterator<Integer> {

    private final Integer mNumber;
    private Integer mPosition;
    private Integer mFactorial;


    public FactorialIteartor(Integer number) {
        this.mNumber = number;
        this.mPosition = 1;
        this.mFactorial = 1;
    }

    @Override
    public boolean hasNext() {
        return mPosition <= mNumber;
    }

    @Override
    public Integer next() {
        if (!hasNext())
            return 0;

        mFactorial = mFactorial * mPosition;

        mPosition++;

        return  mFactorial;
    }
}
Run Code Online (Sandbox Code Playgroud)


dit*_*kin 5

您可以实现自己的迭代器。您的迭代器可以构造为包装由 List 返回的 Iterator,或者您可以保留一个游标并使用 List 的 get(int index) 方法。您只需要向迭代器的 next 方法和 hasNext 方法添加逻辑即可考虑您的过滤条件。您还必须决定您的迭代器是否支持删除操作。


elv*_*vis 5

这是编写迭代器的完整代码,以便迭代以'a'开头的元素:

import java.util.Iterator;

public class AppDemo {

    public static void main(String args[]) {

        Bag<String> bag1 = new Bag<>();

        bag1.add("alice");
        bag1.add("bob"); 
        bag1.add("abigail");
        bag1.add("charlie"); 

        for (Iterator<String> it1 = bag1.iterator(); it1.hasNext();) {

            String s = it1.next();
            if (s != null)
                System.out.println(s); 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义迭代器类

import java.util.ArrayList;
import java.util.Iterator;

public class Bag<T> {

    private ArrayList<T> data;

    public Bag() {

        data = new ArrayList<>();
    }

    public void add(T e) {

        data.add(e); 
    }

    public Iterator<T> iterator() {

        return new BagIterator();
    }

    public class BagIterator<T> implements Iterator<T> {

        private int index; 
        private String str;

        public BagIterator() {

            index = 0;
        }

        @Override
        public boolean hasNext() {

             return index < data.size();  
        }

        @Override
        public T next() {

            str = (String) data.get(index); 
            if (str.startsWith("a"))
                return (T) data.get(index++); 
            index++; 
            return null; 
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)


apa*_*ana 5

这是问题的完整答案。

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

class ListIterator implements Iterator<String>{
    List<String> list;
    int pos = 0;

    public ListIterator(List<String> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        while(pos < list.size()){
            if (list.get(pos).startsWith("a"))
                return true;
            pos++;
        }
        return false;

    }

    @Override
    public String next() {
        if (hasNext())
            return list.get(pos++);
        throw new NoSuchElementException();
    }
}

public class IteratorTest {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("alice", "bob", "abigail", "charlie");
        ListIterator itr = new ListIterator(list);

        while(itr.hasNext())
            System.out.println(itr.next()); // prints alice, abigail
    }
}
Run Code Online (Sandbox Code Playgroud)
  • ListIterator是返回以“a”开头的元素的数组的迭代器。
  • 不需要实现 Iterable 接口。但这是一种可能性。
  • 没有必要通用地实现这一点。
  • 它完全满足 hasNext() 和 next() 的约定。即如果 hasNext() 表示仍有元素,则 next() 将返回这些元素。如果 hasNext() 表示不再有元素,它将返回一个有效的NoSuchElementException异常。