[alice, bob, abigail, charlie]
的列表,并且我想编写一个迭代器,使其遍历以'a'开头的元素,我可以自己编写吗?我该如何做?[alice, bob, abigail, charlie]
的列表,并且我想编写一个迭代器,使其遍历以'a'开头的元素,我可以自己编写吗?我该如何做?最佳的可重复使用选项是实现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;
}
}
这个类使用泛型实现了Iterable接口。如果你有一个数组元素,你就可以得到一个Iterator的实例,这是“foreach”循环所需的实例。
你可以创建一个匿名迭代器实例而不用扩展Iterator,并利用currentSize的值来验证你可以遍历数组到哪里(假设你创建了一个容量为10但只有0和1索引处有2个元素的数组)。该实例将拥有它自己的计数器来记录它所处的位置,你需要做的就是使用hasNext()方法进行判断当前值是否为空,和使用next()方法来返回您当前索引的实例。下面是使用这个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
如果你想的话,你也可以使用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
foreach的文档位于http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html。您可以在我的个人实践Google code中查看更完整的实现。
现在,为了获得所需的效果,我认为您需要在迭代器中插入一个过滤器的概念...由于迭代器依赖于下一个值,因此很难在hasNext()上返回true,然后使用不以字符"a"开头的值来过滤next()实现。我认为您需要使用基于已过滤列表的辅助迭代器,并使用给定过滤器的值。
当然可以。迭代器只是 java.util.Iterator
接口的一种实现。如果你使用一个现有的可迭代对象(比如 LinkedList
)来自于java.util
,你需要继承这个类,并重写它的 iterator
函数,使其返回你自己的迭代器;或者提供一种包装标准迭代器的方法,将其封装在你的特殊 Iterator
实例中(这样做的优点是可以更广泛地使用),等等。
使用Iterable计算阶乘的好例子
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Java 1.8的短代码
new FactorialIterable(5).forEach(System.out::println);
自定义迭代器类
public class FactorialIterable implements Iterable<Integer> {
private final FactorialIterator factorialIterator;
public FactorialIterable(Integer value) {
factorialIterator = new FactorialIterator(value);
}
@Override
public Iterator<Integer> iterator() {
return factorialIterator;
}
@Override
public void forEach(Consumer<? super Integer> action) {
Objects.requireNonNull(action);
Integer last = 0;
for (Integer t : this) {
last = t;
}
action.accept(last);
}
}
自定义迭代器类
public class FactorialIterator implements Iterator<Integer> {
private final Integer mNumber;
private Integer mPosition;
private Integer mFactorial;
public FactorialIterator(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;
}
}
下面是完整的代码,用于编写一个迭代器,使其迭代以字母“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);
}
}
}
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;
}
}
}
您可以实现自己的迭代器。您的迭代器可以构造为包装列表返回的迭代器,或者您可以保持光标并使用列表的get(int index)方法。您只需要在迭代器的next方法和hasNext方法中添加逻辑以考虑您的过滤条件。您还必须决定您的迭代器是否支持删除操作。
以下是该问题的完整答案。
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
}
}
ListIterator
是数组的迭代器,返回以'a'开头的元素。NoSuchElementException
异常。next
应该仍然在常数时间内运行(取决于列表的实现方式)。而且 @Ayoub Omari,在 hasNext
中引入的 while 循环是一个不可避免的计算,必须在某个时候完成以进行过滤位置的移动,因此在 hasNext
方法中完成这个操作与在迭代器外部进行过滤相同。你无论如何都必须编写代码来完成这个操作。 - Lorenzo