1.一段BUG引出迭代器
因为公司的代码蕴含业务逻辑局部,为了不便大家了解,写了一段简化的代码。这段代码是对列表List中的元素进行遍历,并且将满足肯定规定的元素(比方不能被3整除的数字)移除。刚开始这段代码是用for循环进行的,运行后会发现,有些元素明明不是3的倍数,却还是存在于链表之中。

            //筹备数据    LinkedList<Integer> list1 = new LinkedList<Integer>();    LinkedList<Integer> list2 = new LinkedList<Integer>();    for(int i=0;i<30;i++)    {        list1.add(i);        list2.add(i);    }    //for办法移除    System.out.println("For Remove");    for(int i =0;i<list1.size();i++)    {        Integer num = list1.get(i);        if(num%3 != 0)            list1.remove(i);    }    for(Integer num : list1)        System.out.print(num + " ");    System.out.println();

程序的运行后果如下:

For Remove
0 2 3 5 6 8 9 11 12 14 15 17 18 20 21 23 24 26 27 29
对此,上面这段代码进行了改良,采纳迭代器依此拜访各元素。

//迭代器Iterator办法移除

    System.out.println("Iterator Remove");    Iterator<Integer> iter = list2.iterator();    while(iter.hasNext())    {        Integer num = iter.next();        if(num%3 != 0) {            iter.remove();        }    }    for(Integer num : list2)        System.out.print(num + " ");    System.out.println();

运行后果如下:

Iterator Remove
0 3 6 9 12 15 18 21 24 27
能够看的这次程序能够失常的运行了,不会漏掉remove()操作后的一些元素。

这个例子给咱们的启发有两条:

在for循环外面能够拜访元素列表,但最好不要对元素列表进行移除操作;
如果想要在遍历过程中移除不适合的元素,最好应用迭代器;
2.迭代器的相干介绍
迭代器是java定义的一个接口,在java.util.Iterator包下。该接口有四大办法,便于实现了该接口的汇合类进行拜访操作。

public interface Iterator<E>
{
E next();
boolean hasNextO;
void remove0;
default void forEachRemaining(Consumer<? super E> action);
}
在很多的汇合中曾经存在了拜访的办法,如get(),为什么还须要迭代器Iterator这种接口的存在呢?这是因为,在LinkedList汇合中,迭代器的拜访效率是要高于get办法的,测试代码如下:

public static void ForMethod(List<Integer> list)

{    long start = System.currentTimeMillis();    for(int i=0;i<list.size();i++)    {        Integer num = list.get(i);    }    long t = System.currentTimeMillis() - start;    System.out.println("ForMethod:" + t + " ms ");}public static void IteratorMethod(List<Integer> list){    long start = System.currentTimeMillis();    Iterator<Integer> iter = list.iterator();    while(iter.hasNext())    {        Integer num = iter.next();    }    long t = System.currentTimeMillis() - start;    System.out.println("IteratorMethod"+ t + " ms ");}

这里将产生一个大小为100000的链表,对两种办法进行测试,测试代码如下:

    LinkedList<Integer> list = new LinkedList<Integer>();    for(int i=0;i<100000;i++)    {        list.add(i);    }    ForMethod(list);    IteratorMethod(list);

程序的运行后果发现两者的差距是十分的大的,简直是近千倍的比率。

ForMethod:4327 ms
IteratorMethod 5 ms
这是因为链表中的get办法每次都是从头部查找,直到找到第i个元素为止。而Iterator办法更像以前学数据结构的时候,对链表进行依此遍历。也就是说,对于大小为n的链表,采纳get办法的工夫复杂度是 n(n+1)/2,而采纳迭代器的工夫复杂度是n。随着链表大小的减少,拜访效率差距的呈线性增长。

谢谢大家可能耐着性子读到这里,心愿对大家有帮忙,如果喜爱的话请双击一下屏幕!笔心啦!