简介
本文介绍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

请先 !