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

相关阅读

【小家java】java8新特性(简述十大新特性)
【小家java】java8新特性之—Base64加密和解密原理
【小家java】java8新特性之—反射获取方法参数名
【小家java】java8新特性之—全新的日期、时间API(完全实现了JSR 310规范)
【小家java】java8新特性之—Optional的使用,避免空指针,代替三目运算符
【小家java】java8新特性之—lambda表达式的的原理
【小家java】java8新特性之—函数式接口(Supplier、Consumer、Predicate、Function、UnaryOperator,通往高阶设计的好工具)
【小家java】java8新特性之—方法引用
【小家java】java8新特性之—Stream API 详解 (Map-reduce、Collectors收集器、并行流)
【小家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迭代,内部迭代。

猜你喜欢

转载自blog.csdn.net/f641385712/article/details/81514334
今日推荐