乐趣区

关于java:Java-Iterator迭代器

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。随着链表大小的减少,拜访效率差距的呈线性增长。

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

退出移动版