专栏首页BAT的乌托邦【小家java】java8新特性之---外部迭代和内部迭代(对比性能差异)

【小家java】java8新特性之---外部迭代和内部迭代(对比性能差异)

每篇一句

到了一定的年龄,不要再去追求一些虚伪虚假的东西了,人的这一生,还得要做自己最想做的事情,听最想听的声音,见最想见的人。

从一个案例开始:遍历一个集合

外部迭代

最传统的方法是用Iterator,当然还以用for i、增强for循环等等。这一类方法叫做外部迭代,意为显式地进行迭代操作,即集合中的元素访问是由一个处于集合外部的东西来控制的,在这里控制着循环的东西就是迭代器。

我们自己定义一个List,叫ContactList:电话本List

public class ContactList extends ArrayList<Integer>{}

里面存他们的编号,现在我们要都输出,可以这么做

for (Iterator<String> contactListIterator = contactList.iterator(); contactListIterator.hasNext(); ) {
    System.out.println(contactListIterator.next());
}
内部迭代

顾名思义,这种方式的遍历将在集合内部进行,我们不会显式地去控制这个循环。无需关心遍历元素的顺序,我们只需要定义对其中每一个元素进行什么样的操作。注意在这种设定下可能无法直接获取到当前元素的下标。 比如JDK8提供的最新的Collection.forEach(…)方法。

forEach方法源码,一看究竟

@Override
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    @SuppressWarnings("unchecked")
    final E[] elementData = (E[]) this.elementData;
    final int size = this.size;
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        action.accept(elementData[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

可以发现其内部依旧是使用了一个for循环遍历本身,只不过对并发做了一些处理而已。可见外部迭代与内部迭代并没有本质上的区别,两者存在形式上的不同。

性能比较

public static void main(String[] args) {
        final long count = 100_00000;
        List<Long> list = new ArrayList<>();
        for (long i = 0; i < count; i++) {
            list.add(i);
        }


        //=========传统方式进行外部迭代=========
        Instant begin = Instant.now();
        for (Long i : list) {
            System.out.print("");
        }
        System.out.println("--------------------------");
        Instant end = Instant.now();
        System.out.println("传统方式进行外部迭代" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());


        //=========java8内部迭代,用lambda处理=========
        begin = Instant.now();
        list.stream().forEach(i -> System.out.print(""));
        System.out.println("--------------------------");
        end = Instant.now();
        System.out.println("内部迭代forEach" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());

        //=========java8进行并行流处理后迭代(备注:并行流输出是没有顺序的 比如不再是1234顺序了)=========
        begin = Instant.now();
        list.parallelStream().forEach(i -> System.out.print(""));
        System.out.println("--------------------------");
        end = Instant.now();
        System.out.println("内部迭代parallelStream" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());
    }

这段代码,有兴趣的各位可以去执行,对比一下效率。

结论

java的内部迭代的推出,使得我们具备了一定的流式处理的能力。特别是当数据量大的时候,一定要使用Stream迭代,内部迭代。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【小家java】Apache Commons-lang3提供的StopWatch执行时间监视器,以及Spring提供的StopWatch分析

    编码过程中我们经常会希望得到一段代码(一个方法)的执行时间,本文将介绍两种时间监视器(秒表)来让你优雅的、灵活的处理这个问题。

    YourBatman
  • 聊聊Java中的位运算:与、或、非、异或、左移、右移、无符号右移【小家Java】

    提及位运算,相信对绝大多数Java程序员是感觉既陌生又熟悉的。陌生是因为你大概率没有去真实的使用过,熟悉是有时在看些开源框架(或者JDK源码)时会时长看到有使用...

    YourBatman
  • 【小家Java】从原理层面理解Java中的类加载器:ClassLoader、双亲委派模型、线程上下文类加载器

    java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 ...

    YourBatman
  • 弄懂这 5 个问题,拿下 Python 迭代器!

    本篇专题写作思路,由几个问题,逐步讨论迭代器存在的价值、使用的方法、以及如何转化为自身武器并真正用到日常Python中。

    龙哥
  • 弄懂这 5 个问题,拿下 Python 迭代器!

    本篇专题写作思路,由几个问题,逐步讨论迭代器存在的价值、使用的方法、以及如何转化为自身武器并真正用到日常Python中。

    double
  • 插入、流和反向迭代器

    用于向容器插入元素,一共有三种,back_inserter,front_insert和inserter;

    Enterprise_
  • 迭代器模式

    迭代器模式Iterator Pattern提供了一种方法顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部实现,这样既可以做到不暴露集合的内部结构,又可...

    WindrunnerMax
  • 爬虫 (二十三) python 迭代器详解 (十四)

    相信如果你慢慢把这篇文章读完,然后加以实践,你会对 python 文件操作会有很大的理解,加油看完哦

    公众号---人生代码
  • 东京玩具箱

    『东京玩具箱』有两部,另一部叫『大东京玩具箱』,连起来是同一个故事。 这大概算是一部『上班族』漫画,就是游离于『青年漫画』和『成人漫画』的边缘的类型。 故事的主...

    沙因Sign
  • 一篇文章教你如何捕获前端错误

    JavaScript代码在用户浏览器中执行时,由于一些边界情况、本地环境的不可控等因素,可能会存在js运行时错误。

    2020labs小助手

扫码关注云+社区

领取腾讯云代金券