本文主要梳理 Java 集合框架常见的遍历/迭代方式,如下:
1、List 的遍历方式
List 的遍历主要有以下几种方式:
其中 2、3、5 本质上可以说是一样的使用 Iterator 迭代器。而 ListIterator 则是 Iterator 的一个变种(双向迭代, 可以进行 add、remove、set、定位当前索引),使用如下:
public static voidmain(String[] args) {
List strList = new ArrayList<>();/// List strList = new LinkedList<>();
strList.add("1st");
strList.add("2nd");
strList.add("3rd");
strList.add("4th");//1、 索引下标 for 循环//注意:对于链表形式的实现,每次都是 O(N),总的是(O(N*N)),效率较低
System.out.println("for 循环");for (int i = 0, length = strList.size(); i < length; i++) {
System.out.println(strList.get(i));
}//2、 增强的 for 循环,内部是迭代器实现// https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2
System.out.println("增强的 for 循环");for(String str : strList) {
System.out.println(str);
}//3.1、 Iterator 迭代器 while 形式
System.out.println("Iterator 迭代器 while 形式");
Iterator itr =strList.iterator();while(itr.hasNext()) {
String string=itr.next();
System.out.println(string);
}//3.2、 Iterator 迭代器 for 形式
System.out.println("Iterator 迭代器 for 形式");for (Iterator iterator =strList.iterator(); iterator.hasNext();) {
String string=iterator.next();
System.out.println(string);
}//4、 ListIterator 双向迭代器, Iterator 的子类型, List 集合特有的方式//ListIterator 双向, 还可以进行 add、remove、set、定位当前索引//ArrayList 和 LinkedList 各自的内部类实现
ListIterator listItr =strList.listIterator();
System.out.println("ListIterator 反向迭代1");//这里并没有上一个,所以没有
while(listItr.hasPrevious()) {
String string=listItr.previous();
System.out.println(string);
}
System.out.println("ListIterator 正向迭代");while(listItr.hasNext()) {
String string=listItr.next();
System.out.println(string);
}
System.out.println("ListIterator 反向迭代2");while(listItr.hasPrevious()) {
String string=listItr.previous();
System.out.println(string);
}//5、 Java 8 Lambda 迭代方式//本质上还是增强的 for 循环(内部是迭代器实现),将对应的操作封装到 Consumer 里面
System.out.println("Java 8 Lambda 迭代方式");
strList.forEach(str->System.out.println(str));
System.out.println("=-=");
strList.forEach(System.out::println);
strList.forEach(str->{
System.out.println("---");
System.out.println(str);
});//比较完整的写法,其实就是自定义 Consumer 接口的实现类,重写 accept 方法
strList.forEach(new Consumer() {
@Overridepublic voidaccept(String str) {
System.out.println("-=-");
System.out.println(str);
};
});//6、 Java 8 Stream 迭代方式
System.out.println("Java 8 Stream 迭代方式");
strList.stream().forEach(System.out::println);
System.out.println("-~-");
strList.stream().forEach(str->System.out.println(str));
strList.stream().forEach(str->{
System.out.println("===");
System.out.println(str);
});//也可以使用自定义 Consumer 接口的实现类的方式
}
注:因 LinkedList 内部为双向链表实现,通过 LinkedList.get(index) 获取元素每次都是 O(N) ,效率相对较低,建议使用 Iterator 的方式(增强的 for 循环或者直接使用 Iterator)。
2、Set 的遍历方式
对比 List 可知,Set 没有 get(index) 的方式,也没有 ListIterator 双向迭代器 ,其他的都是类似的,Set 的遍历主要有以下几种方式:
使用代码如下:
public static voidmain(String[] args) {
Set strSet = new HashSet<>();//Set strSet = new LinkedHashSet<>();//Set strSet = new TreeSet<>();
strSet.add("1st");
strSet.add("2nd");
strSet.add("3rd");
strSet.add("4th");//1、 增强的 for 循环
System.out.println("增强的 for 循环");for(String str : strSet) {
System.out.println(str);
}//2.1、 Iterator 迭代器 while 形式
System.out.println("Iterator 迭代器 while 形式");
Iterator itr =strSet.iterator();while(itr.hasNext()) {
String string=itr.next();
System.out.println(string);
}//2.2、 Iterator 迭代器 for 形式
System.out.println("Iterator 迭代器 for 形式");for (Iterator iterator =strSet.iterator(); iterator.hasNext();) {
String string=iterator.next();
System.out.println(string);
}//3、 Java 8 Lambda 迭代方式//本质上还是增强的 for 循环(内部是迭代器实现),将对应的操作封装到 Consumer 里面
System.out.println("Java 8 Lambda 迭代方式");
strSet.forEach(str->System.out.println(str));//4、 Java 8 Stream 迭代方式
System.out.println("Java 8 Stream 迭代方式");
strSet.stream().forEach(System.out::println);
System.out.println("-~-");
strSet.stream().forEach(str->System.out.println(str));
}
另外还有一些方式是先转成 Array 再遍历。。。
3、Map 的遍历方式
Map 比较特殊,它是 k-v 对,遍历也会相对不一样。这里总结几种遍历方式:
1、Map.Entry + foreach 的迭代方式
2、Map.Entry + Iterator 的迭代方式
3、keySet + foreach 的迭代方式
4、keySet + Iterator 的迭代方式
使用如下:
public static voidmain(String[] args) {
Map strMap = new HashMap<>();//Map strMap = new LinkedHashMap<>();//Map strMap = new TreeMap<>();
strMap.put("1", "1st");
strMap.put("2", "2nd");
strMap.put("3", "3rd");
strMap.put("4", "4th");//1、 Map.Entry + foreach 的迭代方式
System.out.println("Map.Entry + foreach 迭代方式");for (Map.Entryentry : strMap.entrySet()) {
System.out.println(entry.getKey()+ "=" +entry.getValue());
}//2.1、 Map.Entry + Iterator 的 while 迭代方式
System.out.println("Map.Entry + Iterator 的 while 迭代方式");
Iterator> mapItr =strMap.entrySet().iterator();while(mapItr.hasNext()) {
Map.Entry entry =mapItr.next();
System.out.println(entry.getKey()+ "=" +entry.getValue());
}//2.2、 Map.Entry + Iterator 的 for 迭代方式
System.out.println("Map.Entry + Iterator 的 for 迭代方式");for (Iterator> mapItrs =strMap.entrySet().iterator(); mapItrs.hasNext();) {
Map.Entry entry =mapItrs.next();
System.out.println(entry.getKey()+ "=" +entry.getValue());
}//3、 keySet + foreach 的迭代方式
System.out.println("keySet + foreach 的迭代方式");
Set keySet =strMap.keySet();for(String key : keySet) {
System.out.println(key+ "=" +strMap.get(key));
}//4、 keySet + Iterator 的迭代方式
System.out.println("keySet + Iterator 的迭代方式");
Iterator strItr =strMap.keySet().iterator();while(strItr.hasNext()) {
String key=strItr.next();
System.out.println(key+ "=" +strMap.get(key));
}//以下这些都可以通过自定义 Consumer 接口的实现类来处理//5、 Iterable.forEach + Lambda (Java 8 Lambda 迭代方式)
System.out.println("Iterable.forEach + Lambda (Java 8 Lambda 迭代方式)");
strMap.forEach((k, v)-> System.out.println(k + "=" +v));//6、 Stream.forEach ( Java 8 Stream 迭代方式)
System.out.println("Stream.forEach ( Java 8 Stream 迭代方式)");
strMap.entrySet().forEach((entry)-> System.out.println(entry.getKey() + "=" +entry.getValue()));
}
4、总结
总的来说,基本上就是 : 索引 + 增强的 foreach + Iterator + Iterable.forEach + Stream.forEach