foreach 按原语或 Java 中的盒装 class 循环

foreach loop by primitive or by boxed class in Java

目前正在看书"Java Generics and Collections",发现了一个有趣的代码:

List<Integer> ints = Arrays.asList(1,2,3);
int s = 0;
for (int n : ints) { s += n; }
assert s == 6;

这里 foreach 循环遍历原语:

for (int n : ints) { ... }

但是,Eclipse IDE 建议我迭代盒装类型:

for (Integer n : ints) { ... }

使用一种或另一种迭代方式有什么好处吗?

Boxing/unboxing 在运行时有成本。

  • 如果您打算在循环体内将 Integer 拆箱一次,就像您所做的那样,这不会有太大的不同。
  • 如果您在循环体中多次拆箱 Integer,最好使用 for(int i : ints)
  • 拆箱一次
  • 如果您打算在循环主体中使用整数,那么使用 int 会导致不必要的 unbox/box 操作。

例如:

List<Integer> subList = new ArrayList<>();

for (Integer i : ints) { //better not to unbox
  if (someCondition(i)) subList.add(i);
}

for (int i : ints) { //better to unbox once
  int a = i;
  int b = 2 * i;
  sum += a + b - i;
}

是的。

    List<Integer> ints = Arrays.asList(1,2,3); //here lists is of type Integer which is boxed type
    int s = 0; //s is primitive type

记住我们只能比较:

1.) 原始类型到原始类型

2.) 盒装为盒装类型

我们可以说

列表整数可以表示为:

    [Integer.valueof(1), Integer.valueof(2), Integer.valueof(3)]

所以,在下面的代码中

    for (int n : ints) // in every loop ints current index value which is an Integer is unboxed and assigned to 'int n'

并且当读取下面的代码时..

     s += n;// int n is added to int s (primitive added to primitive ie; no conversion done here)

2.) 现在第二种方法

    for (Integer n : ints) { ... }// here, since 'n' is also boxed so no conversion takes place

但是,当遇到下一行时

    s += n; // boxed Integer n is unboxed to a primitive and added to primitive 's' (so unboxing/conversion happens in each addition)

所以,这就是两者之间的区别,但是,两种方法的转化次数是相同的。