Java中 forEach() 和 Iterator 与 增强for循环 的那些事儿

forEach & Iterator & 增强for 循环

  • List.forEach()
    • 示例
    • forEach()的底层实现
    • 小结
  • Iterator
    • 迭代器简介
    • Iterator应用
  • 增强for 循环
    • 简介
    • 使用格式
    • 注意事项

List.forEach()

示例

 // create some Persons objects
Persons p1 = new Persons("B", 10);
Persons p2 = new Persons("D", 20);
Persons p3 = new Persons("A", 18);

// before sort
List<Persons> list = Arrays.asList(p2, p1, p3);
System.out.println("Before Sort:");
list.forEach(Persons -> System.out.println("Persons name"+Persons.name));

forEach()的底层实现

public interface Iterable<T> {
     
 
    Iterator<T> iterator();
 
    default void forEach(Consumer<? super T> action) {
     
        Objects.requireNonNull(action);
        for (T t : this) {
     
            action.accept(t);
        }
    }
 
    default Spliterator<T> spliterator() {
     
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }

从源码中可以看到:forEach() 方法是Iterable接口中的一个方法。
Java容器中,所有的Collection子类(List、Set)会实现Iteratable接口以实现foreach功能。
forEach()方法里面有个Consumer类型,它是Java8新增的一个消费型函数式接口,其中的accept(T t)方法代表了接受一个输入参数并且无返回的操作。

小结

foreach相对于for循环,代码减少了,但是foreach依赖IEnumerable(IEnumerable是一个接口,它定义一个方法GetEnumerator,它返回一个IEnumerator接口,这允许只读访问一个集合,然后实现IEnumerable的集合可以与for-each语句一起使用)。
在运行的时候效率低于for循环。当然了,在处理不确定循环次数的循环,或者循环次数需要计算的情况下,使用foreach比较方便。而且foreach的代码经过编译系统的代码优化后,和for循环的循环类似。
可以说,foreach语句是for语句的特殊简化版本,在遍历数组、集合方面,foreach为开发人员提供了极大的方便。在复杂的循环设计时,还是应该使用for循环更加的灵活。

  • 如果只是遍历集合或者数组,用foreach好些,快些。
  • 如果对集合中的值进行修改,确定循环次数就要用for循环了。

Iterator

迭代器简介

迭代器(Iterator)是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

Java中的Iterator功能比较简单,并且只能单向移动:

(1)使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
Java中 forEach() 和 Iterator 与 增强for循环 的那些事儿_第1张图片

Iterator应用

import java.util.*;

public class IteratorTest {
     
	public static void main(String[] args) {
     
		//创建一个集合。使用多态
		Collection<String> list=new ArrayList<String>();
		//往集合里添加内容
		list.add("姚明");
		list.add("易建联");
		list.add("科比");
		
		// 使用集合中的方法iterator()获取 迭代器的实现类对象,使用Iterator接口接收,多态写法
		Iterator<String> abc=list.iterator(); // new 实现类名称()
		while(abc.hasNext()){
      // Iterator接口的方法判断有没有下一个元素
			System.out.println(abc.next());//取出集合的下一个元素
		}
		// 增强for循环for(数组或集合的数据类型 变量名 : 集合或数组的名称){}
		for(String a:list){
     
			System.out.print(a+",");
		}
		System.out.println();
		System.out.println("=============");
	
		// 增强for循环for(数组或集合的数据类型 变量名 : 集合或数组的名称){}
		int array[]={
     1,2,5,1,6,23,1,0};
		for(int i: array){
     
			System.out.print(i+",");
		}
	}
}

增强for 循环

简介

  • 增强for循环的作用
    简化迭代器的书写格式。(注意:增强for循环的底层还是使用了迭代器遍历。)
  • 增强for循环的适用范围
    如果是实现了Iterable接口的对象或者是数组对象都可以使用增强for循环。
  • 增强for循环的缺点
    增强for循环iterator遍历的效果是一样的,也就说增强for循环的内部也就是调用iteratoer实现的,但是增强for循环有些缺点:例如不能在增强循环里动态的删除集合内容不能获取下标等。

使用格式

集合框架中的三种迭代方式

  • 普通for循环

  • 迭代器

for(Iterator<String> a = list.iterator(); a.hasNext();){
     
	System.out.println(a.next());  // 取出集合的下一个元素
}
//使用迭代器遍历Set的集合. 
Iterator<String> it  = set.iterator(); 
while(it.hasNext()){
      
    String temp = it.next();   // 取出元素
    System.out.println("元素:"+ temp); 
} 
  • 增强for 循环
    底层是迭代器
for(数组或集合的数据类型 变量名 : 集合或数组的名称){
     
	// 数据类型 变量名:声明一个变量用来接收遍历目标遍历后的元素
	...
}

注意事项

1,增强for循环底层也是使用了迭代器获取的,只不过获取迭代器由jvm完成,不需要我们获取迭代器而已,所以在使用增强for循环变量元素的过程中不准使用集合对象对集合的元素个数进行修改。
2,迭代器遍历元素与增强for循环变量元素的区别:使用迭代器遍历集合的元素时可以删除集合的元素,而增强for循环变量集合的元素时,不能调用迭代器的remove方法删除元素。
3,普通for循环与增强for循环的区别:普通for循环可以没有遍历的目标,而增强for循环一定要有遍历的目标。

删除时

  • 普通for循环,可以删除,注意让索引做自减运算
  • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常。
  • 增强for循环 不能删除,否则Throws ConcurrentModificationException

Map集合没有实现Iterable接口,所以map集合不能直接使用增强for循环,如果需要使用增强for循环需要借助于Collection的集合。

参考下一篇文章 手撕HashMap

借鉴学习大佬的博客
Address1
Address2
感谢!

参考大佬文章,及官方API,向优秀的人致敬!
加油!!!

你可能感兴趣的:(Java,java)