• 迭代器的使用


    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接口的。

  • 相关阅读:
    【36氪收录】观「招商银行」隐私计算布局的思考
    如何用cmake编译
    docker | Ubuntu16.04安装与卸载docker
    通过删除注册表重新获得软件试用期
    k8s | 重启Kubernetes Pod的几种方式
    2021年终总结(一)
    凡是过往、皆为序章20210917PPT分享
    多厂商容器平台开发系统性总结
    VS2022安装.NetFramework4.0目标包的方法
    C# Winform窗体继承过程中,TableLayoutPanel是不支持继承的
  • 原文地址:https://www.cnblogs.com/gxpblogs/p/3067924.html
Copyright © 2020-2023  润新知