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

时间:2021-12-07 15:06:49

If I have a list containing [alice, bob, abigail, charlie] and I want to write an iterator such that it iterates over elements that begin with 'a', can I write my own ? How can I do that ?

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

5 个解决方案

#1


36  

Sure. An iterator is just an implementation of the java.util.Iterator interface. If you're using an existing iterable object (say, a LinkedList) from java.util, you'll need to either subclass it and override its iterator function so that you return your own, or provide a means of wrapping a standard iterator in your special Iterator instance (which has the advantage of being more broadly used), etc.

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

#2


161  

The best reusable option is to implement the interface Iterable and override the method iterator().

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

Here's an example of a an ArrayList like class implementing the interface, in which you override the method 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;
    }
}

This class implements the Iterable interface using Generics. Considering you have elements to the array, you will be able to get an instance of an Iterator, which is the needed instance used by the "foreach" loop, for instance.

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

You can just create an anonymous instance of the iterator without creating extending Iterator and take advantage of the value of currentSize to verify up to where you can navigate over the array (let's say you created an array with capacity of 10, but you have only 2 elements at 0 and 1). The instance will have its owner counter of where it is and all you need to do is to play with hasNext(), which verifies if the current value is not null, and the next(), which will return the instance of your currentIndex. Below is an example of using this API...

您可以创建迭代器的匿名实例,而无需创建扩展Iterator并利用currentSize的值来验证您可以在数组上导航的位置(假设您创建了一个容量为10的数组,但您只有2个元素在0和1)。该实例将拥有其所在的所有者计数器,您需要做的就是使用hasNext()来验证当前值是否为null,以及next(),它将返回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> *List = 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 : *List) {
        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

If you want, you can iterate over it as well using the Iterator instance:

如果需要,您可以使用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

The foreach documentation is located at http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html. You can take a look at a more complete implementation at my personal practice google code.

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

Now, to get the effects of what you need I think you need to plug a concept of a filter in the Iterator... Since the iterator depends on the next values, it would be hard to return true on hasNext(), and then filter the next() implementation with a value that does not start with a char "a" for instance. I think you need to play around with a secondary Interator based on a filtered list with the values with the given filter.

现在,为了获得你需要的效果,我认为你需要在Iterator中插入一个过滤器的概念......由于迭代器依赖于下一个值,因此很难在hasNext()上返回true,然后使用不以char“a”开头的值过滤next()实现。我认为您需要使用具有给定过滤器的值的过滤列表来使用辅助Interator。

#3


7  

Good example for Iterable to compute factorial

Iterable计算阶乘的好例子

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

shortly code for Java 1.8

Java 1.8的简短代码

new FactorialIterable(5).forEach(System.out::println);

custom Iterable class

自定义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);
    }

}

custom Iterator class

自定义迭代器类

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;
    }
}

#4


3  

You can implement your own Iterator. Your iterator could be constructed to wrap the Iterator returned by the List, or you could keep a cursor and use the List's get(int index) method. You just have to add logic to your Iterator's next method AND the hasNext method to take into account your filtering criteria. You will also have to decide if your iterator will support the remove operation.

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

#5


3  

This is the complete code to write an iterator such that it iterates over elements that begin with 'a':

这是编写迭代器的完整代码,以便迭代以'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); 
        }
    }
}

Custom Iterator class

自定义迭代器类

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; 
        }
    } 
}

#1


36  

Sure. An iterator is just an implementation of the java.util.Iterator interface. If you're using an existing iterable object (say, a LinkedList) from java.util, you'll need to either subclass it and override its iterator function so that you return your own, or provide a means of wrapping a standard iterator in your special Iterator instance (which has the advantage of being more broadly used), etc.

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

#2


161  

The best reusable option is to implement the interface Iterable and override the method iterator().

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

Here's an example of a an ArrayList like class implementing the interface, in which you override the method 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;
    }
}

This class implements the Iterable interface using Generics. Considering you have elements to the array, you will be able to get an instance of an Iterator, which is the needed instance used by the "foreach" loop, for instance.

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

You can just create an anonymous instance of the iterator without creating extending Iterator and take advantage of the value of currentSize to verify up to where you can navigate over the array (let's say you created an array with capacity of 10, but you have only 2 elements at 0 and 1). The instance will have its owner counter of where it is and all you need to do is to play with hasNext(), which verifies if the current value is not null, and the next(), which will return the instance of your currentIndex. Below is an example of using this API...

您可以创建迭代器的匿名实例,而无需创建扩展Iterator并利用currentSize的值来验证您可以在数组上导航的位置(假设您创建了一个容量为10的数组,但您只有2个元素在0和1)。该实例将拥有其所在的所有者计数器,您需要做的就是使用hasNext()来验证当前值是否为null,以及next(),它将返回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> *List = 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 : *List) {
        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

If you want, you can iterate over it as well using the Iterator instance:

如果需要,您可以使用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

The foreach documentation is located at http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html. You can take a look at a more complete implementation at my personal practice google code.

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

Now, to get the effects of what you need I think you need to plug a concept of a filter in the Iterator... Since the iterator depends on the next values, it would be hard to return true on hasNext(), and then filter the next() implementation with a value that does not start with a char "a" for instance. I think you need to play around with a secondary Interator based on a filtered list with the values with the given filter.

现在,为了获得你需要的效果,我认为你需要在Iterator中插入一个过滤器的概念......由于迭代器依赖于下一个值,因此很难在hasNext()上返回true,然后使用不以char“a”开头的值过滤next()实现。我认为您需要使用具有给定过滤器的值的过滤列表来使用辅助Interator。

#3


7  

Good example for Iterable to compute factorial

Iterable计算阶乘的好例子

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

shortly code for Java 1.8

Java 1.8的简短代码

new FactorialIterable(5).forEach(System.out::println);

custom Iterable class

自定义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);
    }

}

custom Iterator class

自定义迭代器类

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;
    }
}

#4


3  

You can implement your own Iterator. Your iterator could be constructed to wrap the Iterator returned by the List, or you could keep a cursor and use the List's get(int index) method. You just have to add logic to your Iterator's next method AND the hasNext method to take into account your filtering criteria. You will also have to decide if your iterator will support the remove operation.

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

#5


3  

This is the complete code to write an iterator such that it iterates over elements that begin with 'a':

这是编写迭代器的完整代码,以便迭代以'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); 
        }
    }
}

Custom Iterator class

自定义迭代器类

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; 
        }
    } 
}