相关阅读
【小家java】java5新特性(简述十大新特性) 重要一跃
【小家java】java6新特性(简述十大新特性) 鸡肋升级
【小家java】java7新特性(简述八大新特性) 不温不火
【小家java】java8新特性(简述十大新特性) 饱受赞誉
【小家java】java9新特性(简述十大新特性) 褒贬不一
【小家java】java10新特性(简述十大新特性) 小步迭代
【小家java】java11新特性(简述八大新特性) 首个重磅LTS版本
【小家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迭代,内部迭代。
关注A哥
Author | A哥(YourBatman) |
---|---|
个人站点 | www.yourbatman.cn |
yourbatman@qq.com | |
微 信 | fsx641385712 |
活跃平台 | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
公众号 | BAT的乌托邦(ID:BAT-utopia) |
知识星球 | BAT的乌托邦 |
每日文章推荐 | 每日文章推荐 |