简介
本文介绍Java中List的使用,包括:创建、遍历。
创建
法1:构造 List 后使用 List.add(繁琐)
List<String> list = new ArrayList<>(); list.add("a"); list.add("b");
法2:Arrays.asList
下边两种方法的区别见:Java工具类-Arrays的用法 – 自学精灵
List<String> list = Arrays.asList("a", "b");
或者
List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
法3:Stream (JDK8)
List<String> list = Stream.of("a", "b").collect(Collectors.toList());
法4:{{}}
List<String> list = new ArrayList<String>() {{ add("a"); add("b"); }};
说明
外层的 {} 定义了一个 ArrayList 的匿名内部类。内层的 {} 的定义了一个实例初始化代码块。 这个代码块在初始化内部类时执行。所以这里相当于定义了一个匿名内部类,并使用 add 添加元素来初始化。
{{}} 双括号语法同样可用于初始化 Map 等其他众多类型。
缺点
- 使用匿名内部类,会有效率上的损失。当然在大多数情况下,这点效率都是可接受的。
- 非静态内部类持有所在外部类的引用,可能造成内存泄漏。见:Java-内存泄露的原因及解决方案(大全) – 自学精灵
法5:google的guava(JDK9)
List<String> list = Lists.newArrayList("one","two","three");
遍历
简介
说明
- 记录的存取方式有两种:一种是数组方式存储,另一种是链表方式。
- 对于数组方式存储的记录可以根据其下标找到对应的记录,而链表方式存储(单链表为例)则必须找到其前一个记录的位置才能够找到本记录。
- 所以:for循环便于访问数组方式存储的记录,比如数组等;而迭代则更适用于链表存储的记录。
法1:for循环
List<Object> list = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { Object value = list.get(i); }
法2:增强for循环
List<Object> list = new ArrayList<>(); for (Object s : list) { Object value = s; }
法3:迭代器(Iterator)
Iterator<Object> iter = list.iterator(); while (iter.hasNext()) { Object value = iter.next(); }
法4:foreach
List<Object> list = new ArrayList<>(); list.forEach(o -> {Object value = o});
实际上,foreach底层也是通过Iterator来遍历,上边的代码反编译之后:
List<Object> list = new ArrayList<>(); for (Iterator iterator = list.iterator(); iterator.hasNext();) { Object value = iterator.next(); }
性能
结论
ArrayList:按性能由高到低排序:forEach > Iterator > 增强for > for
LinkedList:按性能由高到低排序: Iterator > 增强for > forEach> for
ArrayList测试
package org.example.a; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Demo { public static void main(String[] args) { Object obj = new Object(); List<Object> list = new ArrayList<>(); int objCount = 1000; for (int i = 0; i < objCount; i++) { list.add(obj); } int testTimes = 5; for (int i = 0; i < testTimes; i++) { testFor(list); testForEnhanced(list); testForEach(list); testIterator(list); System.out.println(); } } private static void testFor(List<Object> list) { long startTime = 0L; long endTime = 0L; startTime = System.nanoTime(); for (int i = 0; i < list.size(); i++) { Object o = list.get(i); } endTime = System.nanoTime(); System.out.println("for所用时间(ns) :" + (endTime - startTime)); } private static void testForEnhanced(List<Object> list) { long startTime = 0L; long endTime = 0L; startTime = System.nanoTime(); for (Object o : list) { Object value = o; } endTime = System.nanoTime(); System.out.println("增强for所用时间(ns) :" + (endTime - startTime)); } private static void testForEach(List<Object> list) { long startTime = 0L; long endTime = 0L; startTime = System.nanoTime(); list.forEach(o->{Object obj = o;}); endTime = System.nanoTime(); System.out.println("forEach所用时间(ns) :" + (endTime - startTime)); } private static void testIterator(List<Object> list) { long startTime = 0L; long endTime = 0L; startTime = System.nanoTime(); Iterator<Object> iterator = list.iterator(); while (iterator.hasNext()) { Object o = iterator.next(); } endTime = System.nanoTime(); System.out.println("iterator所用时间(ns) :" + (endTime - startTime)); } }
结果
for所用时间(ns) :619500 增强for所用时间(ns) :572300 forEach所用时间(ns) :121775301 iterator所用时间(ns) :34700 for所用时间(ns) :36799 增强for所用时间(ns) :36000 forEach所用时间(ns) :24300 iterator所用时间(ns) :33200 for所用时间(ns) :41401 增强for所用时间(ns) :37800 forEach所用时间(ns) :23799 iterator所用时间(ns) :44100 for所用时间(ns) :34400 增强for所用时间(ns) :345101 forEach所用时间(ns) :24300 iterator所用时间(ns) :31200 for所用时间(ns) :34299 增强for所用时间(ns) :33100 forEach所用时间(ns) :23099 iterator所用时间(ns) :30901
第一次测试:性能由高到低排序: Iterator > 增强for > for > forEach
第二次之后:性能由高到低排序:forEach > Iterator > 增强for > for
原因:
- java8的foreach预热是jvm级别的,需要预热。
- 增强for编译之后是基于Iterator的,所以会比直接用Iterator稍微慢一点点。(写一个增强for循环代码,然后反编译,即可发现它是迭代器方式)
LinkedList测试
将上边测试代码中的ArrayList改为LinkedList,其他不变。
结果:
for所用时间(ns) :1399300 增强for所用时间(ns) :1391200 forEach所用时间(ns) :57331500 iterator所用时间(ns) :44099 for所用时间(ns) :940200 增强for所用时间(ns) :38701 forEach所用时间(ns) :71100 iterator所用时间(ns) :60600 for所用时间(ns) :976100 增强for所用时间(ns) :32301 forEach所用时间(ns) :46000 iterator所用时间(ns) :28700 for所用时间(ns) :358901 增强for所用时间(ns) :37100 forEach所用时间(ns) :42401 iterator所用时间(ns) :29000 for所用时间(ns) :358100 增强for所用时间(ns) :30500 forEach所用时间(ns) :41499 iterator所用时间(ns) :28800
请先
!