技术开发 频道

Java迭代器的使用

  【IT168 技术文档】1.迭代器Iterator

  迭代器是一个对象,它的工作是遍历并选择序列中的对象。客户端程序员不关心序列底层的结构。此外,迭代器通常被称为“轻量级”对象:创建它的代价小。因此,经常可以见到对迭代器有些奇怪的限制。

  Java 的Iterator 就是迭代器受限制的例子,它只能用来:

  1)使用方法 iterator()要求容器返回一个 Iterator。第一次调用Iterator 的next()方法时,它返回序列的第一个元素。

  2)使用next()获得序列中的下一个元素。

  3)使用hasNext()检查序列中是否还有元素。

  4)使用remove()将上一次返回的元素从迭代器中移除。

  import java.util.ArrayList;   import java.util.Iterator;   import java.util.List;   class Cat {   private int id;   public int getId() {   return id;   }   public void setId(int id) {   this.id = id;   }   Cat(int i) {   id = i;   }   }   public class Cats {   public static void main(String[] args) {   List cats = new ArrayList();   for (int i = 0; i < 7; i++)   cats.add(new Cat(i));   System.out.println("before remove:"+cats.size());   Iterator e = cats.iterator();   while (e.hasNext()) {   //e.remove();//java.lang.IllegalStateException   System.out.println("Cat id:" + ((Cat) e.next()).getId());   e.remove();   }   System.out.println("after remove:"+cats.size());   }   }

  结果:

  before remove:7

  Cat id:0

  Cat id:1

  Cat id:2

  Cat id:3

  Cat id:4

  Cat id:5

  Cat id:6

  after remove:0

  这里必须注意remove()方法的使用,在调用该方法之前必须先调用next()方法。

  2.迭代器ListIterator

  该迭代器只能用于各种List类的访问。ListIterator可以双向移动。

  import java.util.ArrayList;   import java.util.Arrays;   import java.util.List;   import java.util.ListIterator;   public class ListIteration {   public static void main(String[] args) {   List stringList = new ArrayList(Arrays.asList("a", "b", "c",   "d", "e"));   ListIterator it = stringList.listIterator();   while (it.hasNext())   System.out.print(it.next() + "," + it.nextIndex() + ","   + it.previousIndex() + ";");   System.out.println();   //回溯   while(it.hasPrevious())   System.out.print(it.previous()+" ");   System.out.println();   System.out.println(stringList);   it=stringList.listIterator(2);   while(it.hasNext()){   it.next();   it.set("z");   }   System.out.println(stringList);   }   }

  结果:

  a,1,0;b,2,1;c,3,2;d,4,3;e,5,4;

  e d c b a

  [a, b, c, d, e]

  [a, b, z, z, z]

  ①next()得到下一个元素;previous()得到前一个元素。

  ②nextIndex()得到下一个元素的索引号;previousIndex()得到前一个元素的索引号。

  ③hasNext()判断是否还有后继元素;hasPrevious()判断是否还有前驱元素。

  ④listIterator()得到该集合的迭代器;listIterator(n)得到一个子迭代器,从原集合中第n+1个元素起(注意考虑第一个元素索引号为0)至集合末尾的所有元素组成一个子迭代器。

  ⑤set(“newElement”)将当前元素替换为newElement。这个方法的调用类似remove()方法,需要先调用next()方法。

  3.Iterable接口与Foreach

  Iterable接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此如果创建了任何实现Iterable接口的类,都可以将它用于foreach语句中。

  import java.util.Iterator;   public class IterableClass implements Iterable {   protected String[] words = ("And that is how "   + "we know the Earth to be banana-shaped.").split(" ");   public Iterator iterator() {   return new Iterator() {   private int index = 0;   public boolean hasNext() {   return index < words.length;   }   public String next() {   return words[index++];   }   public void remove() {}   };   }   public static void main(String[] args){   for(String s:new IterableClass())   System.out.print(s+",");   }   }

  结果:

  And,that,is,how,we,know,the,Earth,to,be,banana-shaped.,

  这个例子中,IterableClass类实现了Iterable接口,该接口只有一个方法:

  Iterator iterator();

  使用内部类实现这个Iterator接口,该接口有三个方法:

  boolean hasNext();

  E next();

  void remove();

  但是,如果尝试把数组当作一个Iterable参数传递会导致失败。这说明不存在任何从数组到Iterable的自动转换。

  import java.util.Arrays;   public class ArrayIsNotIterable {   static void test(Iterable ib){   for(T t:ib)   System.out.print(t+" ");   }   public static void main(String[] args){   test(Arrays.asList(1,2,3));   String[] strs={"A","B","C"};   //test(strs);ERROR   test(Arrays.asList(strs));   }   }

  4.实现特定功能的Foreach

  前面已经讨论了,foreach语法是通过Iterable接口实现移动的,所以如果需要改变foreach语句的逻辑功能,其实质就是覆盖底层Iterable中Iterator接口中三个方法的逻辑实现。下面,我们实现反向的Foreach“效果”。

  import java.util.ArrayList;   import java.util.Arrays;   import java.util.Collection;   import java.util.Iterator;   @SuppressWarnings("serial")   class ReversibleArrayList extends ArrayList {   public ReversibleArrayList(Collection c) {   super(c);   }   public Iterable reversed() {   return new Iterable() {   public Iterator iterator() {   return new Iterator() {   int current = size() - 1;   public boolean hasNext() {   return current > -1;   }   public T next() {   return get(current--);   }   public void remove() {   }   };   }   };   }   }   public class AdapterMethodIdiom {   public static void main(String[] args) {   ReversibleArrayList ral = new ReversibleArrayList(   Arrays.asList("To be or not to be".split(" ")));   for (String s : ral)   System.out.print(s + " ");   System.out.println();   for (String s : ral.reversed())   System.out.print(s + " ");   }   }

  结果:

  To be or not to be

  be to not or be To

  在这个例子中,ReversibleArrayList类又实现了一个Iterable接口,名为reversed(),将其底层Iterator接口中的三个方法的逻辑实现为反向的遍历,就达到了反向Foreach的效果。从这个示例中,我们还可以注意到:

  ReversibleArrayList ral = new ReversibleArrayList(…);   for (String s : ral)   //此处的ral其实是Iterable接口的引用,因为ReversibleArrayList类是实现Iterable接口的。
0
相关文章