Java中的foreach
是在JDK1.5中增加的内容,使用起来非常方便,是for
的增强版。foreach
的目标对象有两种,分别是数组和实现了Iterable
接口的对象(Set
和Map
等集合)。
foreach
使用和原理
1.1 数组中的使用
public class Test {
public static void main(String[] args)
{
int[] num = {1,2,3};
for (int temp : num)
{
System.out.println(temp);
}
}
}
在数组中,使用foreach实现遍历。对代码进行反编译,其运行逻辑与直接使用for
循环是一样的,详细运行结果如下:
[C:\Users\zhangsz\Downloads\Downloads\just_java\src]$ javap -c Test.class
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: iconst_1
6: iastore
7: dup
8: iconst_1
9: iconst_2
10: iastore
11: dup
12: iconst_2
13: iconst_3
14: iastore
15: astore_1
16: aload_1
17: astore_2
18: aload_2
19: arraylength
20: istore_3
21: iconst_0
22: istore 4
24: iload 4
26: iload_3
27: if_icmpge 50
30: aload_2
31: iload 4
33: iaload
34: istore 5
36: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
39: iload 5
41: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
44: iinc 4, 1
47: goto 24
50: return
}
1.2 对象中的使用
当foreach
的使用目标是对象的时候,对象必须实现Iterable
接口。
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args)
{
List<String> hello = new ArrayList<>();
for (int i = 0;i < 3;i ++)
{
hello.add("hello world");
}
for (String temp : hello)
{
System.out.println(temp);
}
}
}
对代码进行反编译,可以看到在实际遍历的时候,是调用的Iterable
接口中的hasNext
方法和next
方法。所以对于非数组的对象,要想使用foreach
,就必须实现Iterable
接口。
[C:\Users\zhangsz\Downloads\Downloads\just_java\src]$ javap -c Test.class
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: iconst_3
12: if_icmpge 30
15: aload_1
16: ldc #4 // String hello world
18: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
23: pop
24: iinc 2, 1
27: goto 10
30: aload_1
31: invokeinterface #6, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
36: astore_2
37: aload_2
38: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
43: ifeq 66
46: aload_2
47: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
52: checkcast #9 // class java/lang/String
55: astore_3
56: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
59: aload_3
60: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
63: goto 37
66: return
}
2. Java源码中foreach
实现
上文使用foreach
的例子,使用的是ArrayList
。下来看一下其JDK的代码,是如何实现Iterable
接口的。
ArrayList
、List
和Iterator
的关系如下图所示。
在Iterator
接口中,定义了Iterator<T> iterator();
方法,所以在最终的ArrayList
中需要进行实现。实现逻辑如下:
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
// prevent creating a synthetic constructor
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int size = ArrayList.this.size;
int i = cursor;
if (i < size) {
final Object[] es = elementData;
if (i >= es.length)
throw new ConcurrentModificationException();
for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, i));
// update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
代码中,hasNext
方法查看是否后一位还存在元素,next
方法用于获取下一个具体的元素。
import java.util.Iterator;
public class Test1 {
public static void main(String[] args)
{
ForeachTest foreachTest = new ForeachTest();
for (String i : foreachTest)
{
System.out.println(i);
}
}
}
class ForeachTest implements Iterable<String>{
String[] test = {"hello","world","!"};
@Override
public Iterator<String> iterator() {
return new Ite();
}
private class Ite implements Iterator<String>{
int pt = 0;
public Ite(){
}
@Override
public boolean hasNext() {
return pt < test.length;
}
@Override
public String next() {
return test[pt++];
}
}
}
运行结果如下:
点击查看更多内容
3人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦