Java 对于每个vs迭代器。哪一个是更好的选择
考虑以下场景Java 对于每个vs迭代器。哪一个是更好的选择,java,foreach,iterator,Java,Foreach,Iterator,考虑以下场景 List<String> list = new ArrayList<>(); 选项二-使用迭代器 Iterator it=list.iterator(); while (it.hasNext()){ System.out.println(it.next()); } 我只想知道如果我对每个使用而不是迭代器,是否有性能优势。现在在Java中使用迭代器也是一种不好的做法吗?简单的答案:否和否 在内部,for each循环创建一个迭代器,对集合进行迭代 显
List<String> list = new ArrayList<>();
选项二-使用迭代器
Iterator it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
我只想知道如果我对每个使用
而不是迭代器
,是否有性能优势。现在在Java中使用迭代器也是一种不好的做法吗?简单的答案:否和否
在内部,for each
循环创建一个迭代器
,对集合进行迭代
显式使用迭代器的优点是,您可以访问迭代器的方法。对于每个都是使用迭代器的语法糖(方法2)
如果需要修改循环中的集合,可能需要使用迭代器。第一种方法将抛出异常
for (String i : list) {
System.out.println(i);
list.remove(i); // throws exception
}
Iterator it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
it.remove(); // valid here
}
每个
的都是高级循环结构。它在内部创建一个迭代器并在集合上进行迭代。对于每个
构造,使用实际迭代器对象而不是对象的唯一可能优势是,您可以使用迭代器的方法(如.remove()
)修改集合。在迭代过程中不使用迭代器的方法修改集合将产生一个差异主要是语法上的差异,除了迭代器可以从它正在迭代的集合中删除项之外。从技术上讲,增强的for循环允许您循环任何可执行的内容,至少包括集合和数组
不要担心性能差异。这种微观优化是一种无关紧要的干扰。如果需要在执行过程中删除项,请使用迭代器。否则,for循环往往会被更多地使用,因为它们更具可读性,即:
for (String s : stringList) { ... }
vs:
for(迭代器iter=stringList.Iterator();iter.hasNext();){
字符串s=iter.next();
...
}
如果您想替换列表中的项目,我会使用for循环进行旧式学习
for (int nIndex=0; nIndex < list.size(); nIndex++) {
Obj obj = (Obj) list.get(nIndex);
// update list item
list.set(nIndex, obj2);
}
for(int-nIndex=0;nIndex
最好的方法是在java 8中
list.forEach(System.out::println);
这里有一些有用的链接
foreach
无论如何都在幕后使用迭代器。它真的只是语法上的糖
考虑以下计划:
import java.util.List;
import java.util.ArrayList;
public class Whatever {
private final List<Integer> list = new ArrayList<>();
public void main() {
for(Integer i : list) {
}
}
}
我们可以看到,foreach
编译成一个程序,该程序:
- 使用
List.iterator()创建迭代器
- If
Iterator.hasNext()
:调用Iterator.next()
并继续循环
至于“为什么这个无用的循环不能从编译后的代码中得到优化?我们可以看到它对列表项没有任何作用”:那么,您可以对iterable进行编码,使.iterator()
产生副作用,或者.hasNext()
产生副作用或有意义的后果
您可以很容易地想象,表示来自数据库的可滚动查询的iterable可能会在.hasNext()
上做一些引人注目的事情(比如联系数据库,或者因为已到达结果集的末尾而关闭光标)
因此,即使我们可以证明在循环体中没有发生任何事情……但在我们迭代时证明没有发生任何有意义的/重要的事情是更昂贵的(难处理的?)。编译器必须在程序中保留此空循环体
我们所能期望的最好结果就是编译器发出警告。有趣的是,javac-Xlint:all Whatever.java
没有警告我们这个空循环体。IntelliJ IDEA确实如此。诚然,我已经将IntelliJ配置为使用Eclipse编译器,但这可能不是原因
这里是一个简单的代码片段,用于检查每个与迭代器的与对的性能,用于遍历在Java版本8上执行的ArrayList
。
long MAX = 2000000;
ArrayList<String> list = new ArrayList<>();
for (long i = 0; i < MAX; i++) {
list.add("" + i);
}
/**
* Checking with for each iteration.
*/
long A = System.currentTimeMillis();
for (String data : list) {
// System.out.println(data);
}
long B = System.currentTimeMillis();
System.out.println(B - A + "ms");
/**
* Checking with Iterator method
*/
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
// System.out.println(iterator.next());
}
long C = System.currentTimeMillis();
System.out.println(C - B + "ms");
/**
* Checking with normal iteration.
*/
for (int i = 0; i < MAX; i++) {
list.get((int) (i % (MAX - i)));
// System.out.println(list.get(i));
}
long D = System.currentTimeMillis();
System.out.println(D - C + "ms");
结果分析:
迭代器
(9ms)
(19ms)
(27ms)
这里,迭代器
的性能最好,For
的性能最低。然而,对于每个
性能而言,都介于两者之间
我认为对于每一次使用,迭代或可能的重复都不能“将”导致ConcurrentModificationExceptionOne混乱如果在内部为每个使用迭代器增强,为什么在迭代时删除元素会受到限制?@shaun,因为您没有访问权限:)当然最好记住,从循环的集合中添加/删除项不是好的做法,出于您突出显示的原因。为什么您认为使用list.foreach()更好?在这样的feaeach()方法中,您不能修改外部变量,必须将其复制为final或将其包装在数组中。但为什么不需要在代码中导入迭代器类?@Dakatine,因为导入是由编译器隐式完成的。
import java.util.List;
import java.util.ArrayList;
public class Whatever {
private final List<Integer> list = new ArrayList<>();
public void main() {
for(Integer i : list) {
}
}
}
public void main();
Code:
0: aload_0
1: getfield #4 // Field list:Ljava/util/List;
4: invokeinterface #5, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
9: astore_1
10: aload_1
11: invokeinterface #6, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
16: ifeq 32
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
25: checkcast #8 // class java/lang/Integer
28: astore_2
29: goto 10
32: return
long MAX = 2000000;
ArrayList<String> list = new ArrayList<>();
for (long i = 0; i < MAX; i++) {
list.add("" + i);
}
/**
* Checking with for each iteration.
*/
long A = System.currentTimeMillis();
for (String data : list) {
// System.out.println(data);
}
long B = System.currentTimeMillis();
System.out.println(B - A + "ms");
/**
* Checking with Iterator method
*/
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
// System.out.println(iterator.next());
}
long C = System.currentTimeMillis();
System.out.println(C - B + "ms");
/**
* Checking with normal iteration.
*/
for (int i = 0; i < MAX; i++) {
list.get((int) (i % (MAX - i)));
// System.out.println(list.get(i));
}
long D = System.currentTimeMillis();
System.out.println(D - C + "ms");
19ms
9ms
27ms