Java迭代器– Java中的迭代器

时间:2020-02-23 14:34:29  来源:igfitidea点击:

在本文中,我们将讨论有关Java枚举的一些基础知识,以及有关Java Iterator的深入讨论。
由于不推荐使用Java Enumeration接口,因此不建议在我们的应用程序中使用它。

Java四游标

首先,我想定义什么是Java游标? Java游标是一个迭代器,用于迭代,遍历或者检索Collection或者Stream对象的元素。

Java支持以下四个不同的游标。

  • 枚举
  • 迭代器
  • ListIterator
  • 分流器

每个Java游标都有一些优点和缺点。
在本文中,我们将讨论有关枚举的一些基础知识和有关Iterator的完整详细信息。
我们将在我的后续文章中讨论ListIterator和Spliterator。

Java枚举限制

Java枚举自Java 1.0开始可用,它具有许多局限性,建议不要在新项目中使用。

  • 从Java 1.0和旧版接口开始可用。

  • 它仅对Collection Legacy类有用。

  • 与其他Cursors相比,它具有非常长的方法名称:hasMoreElements()和nextElement()。

  • 在CRUD操作中,它仅支持READ操作。
    不支持CREATE,UPDATE和DELETE操作。

  • 它仅支持正向迭代。
    这就是为什么它也被称为单向光标。

  • 不建议在新的代码库或者项目中使用它。

注意:-Collection API中的CRUD操作是什么?

  • 创建:向Collection对象添加新元素。

  • 阅读:从Collection对象中检索元素。

  • 更新:更新或者设置Collection对象中的现有元素。

  • 删除:从集合对象中删除元素。

为了克服所有这些问题,Java提出了新的Cursors:Java 1.2中的Iterator和ListIterator。
它引入了一种新型的Cursor:Java 1.8中的Spliterator。

在本文中,我们将通过一些合适的示例来讨论Iterator。

Java迭代器

在Java中,Iterator是java.util包中Collection框架中可用的接口。
它是用于迭代对象集合的Java游标。

  • 它用于遍历一个集合对象元素。

  • 从Java 1.2 Collection Framework开始可用。

  • 它适用于所有Collection类。
    因此,它也被称为通用Java游标。

  • 它支持读取和删除操作。

  • 与Enumeration接口相比,Iterator方法名称简单易用。

Java Iterator类图

如下面的类图所示,Java Iterator有四个方法。
我们已经熟悉前四种方法。
Oracle Corp在Java SE 8版本中已向该接口添加了第四种方法。

Java迭代器方法

在本节中,我们将简要讨论Java Iterator方法。
在下一节中,我们将通过一些有用的示例深入探讨这些方法。

  • boolean hasNext():如果迭代具有更多元素,则返回true。

  • E next():返回迭代中的下一个元素。

  • 默认void remove():从基础集合中移除此迭代器返回的最后一个元素。

  • 默认void forEachRemaining(Consumer action):对剩余的每个元素执行给定的操作,直到所有元素都已处理或者该操作引发异常。

Java Iterator基本示例

首先讨论如何从集合中获取Iterator对象。
每个Collection类都具有以下iterator()方法来迭代其元素。

Iterator<E> iterator()

它在给定Collection对象中可用的元素上返回一个迭代器。

示例1:

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class ExternalIteratorDemo 
{
public static void main(String[] args) 
{
	List<String> names = new LinkedList<>();
	names.add("Rams");
	names.add("Posa");
	names.add("Chinni");
	
	//Getting Iterator
	Iterator<String> namesIterator = names.iterator();
		
	//Traversing elements
	while(namesIterator.hasNext()){
		System.out.println(namesIterator.next());			
	}	
	
}
}

示例2:

import java.util.LinkedList;
import java.util.List;

public class InternalIteratorDemo 
{
public static void main(String[] args) 
{
	List<String> names = new LinkedList<>();
	names.add("Rams");
	names.add("Posa");
	names.add("Chinni");
		
	for(String name: names){
		System.out.println(name);			
	}	
	
}
}

如果我们观察上述两个示例,则两个示例都在做相同的事情。
在Example-1中,我们在外部创建了Iterator对象,并一个接一个地检索List对象元素。
在示例2中,我们没有在外部创建Iterator对象。
我们使用增强的for循环来逐一检索List对象元素。

增强的for循环在内部使用Iterator对象,并执行与External Iterator示例相同的操作。
因此,两个示例的输出均相同,如下所示。

输出:

Rams
Posa
Chinni

开发自定义类迭代器

在上一节中,我们讨论了Collection API如何实现iterator()方法以在使用或者不使用Enhanced For Loop的情况下对其元素进行迭代。

在本节中,我们将讨论如何为用户定义或者自定义类提供类似的功能。
我们应该按照以下说明提供此功能:

  • 定义自定义类。

  • 将此Collection类定义为该Custom类。

  • 此Collection类应使用Custom类作为Type参数实现Iterable接口。

  • 这个Collection类应该提供Iterable接口方法的实现:iterator()。

如果我们对Custom类实施这些说明,则可以使用Enhanced For Loop或者外部Iterator对象来迭代其元素。

让我们开发一个简单的示例来清楚地理解这些说明。

例:

public class Employee {

private int empid;
private String ename;
private String designation;
private double salary;
	
public Employee(int empid,String ename,String designation,double salary){
	this.empid = empid;
	this.ename = ename;
	this.designation = designation;
	this.salary = salary;
}
	
public int getEmpid() {
	return empid;
}
	
public String getEname() {
	return ename;
}

public String getDesignation() {
	return designation;
}
	
public double getSalary() {
	return salary;
}	
	
@Override
public String toString(){
	return empid + "\t" + ename + "\t" + designation + "\t" + salary;	
}
	
}
import java.util.*;

public class Employees implements Iterable{

	private List<Employee> emps = null;
	
	public Employees(){
		emps = new ArrayList<&glt;();
		emps.add(new Employee(1001,"Rams","Lead", 250000L));
		emps.add(new Employee(1002,"Posa","Dev", 150000L));
		emps.add(new Employee(1003,"Chinni","QA", 150000L));
	}
	
	@Override
	public Iterator<Employee> iterator() {
		return emps.iterator();
	}

}
public class EmployeesTester {
	public static void main(String[] args) {
		Employees emps = new Employees();
		for(Employee emp : emps){
			System.out.println(emp);
		}
	}
}

输出:

1001	Rams	Lead	250000.0
1002	Posa	Dev	150000.0
1003	Chinni	QA	150000.0

Java Iterator在内部如何工作?

在本节中,我们将尝试了解Java Iterator及其方法在内部如何工作。
让我们采用以下LinkedList对象来了解此功能。

List<String> names = new LinkedList<>();
names.add("E-1");
names.add("E-2");
names.add("E-3");
.
.
.
names.add("E-n");

现在在List对象上创建一个迭代器对象,如下所示:

Iterator<String> namesIterator = names.iterator();

让我们假设" namesIterator"迭代器如下所示:

这里Iterator的Cursor指向List的第一个元素之前。
现在,我们运行以下代码片段。

namesIterator.hasNext();
namesIterator.next();

当我们运行以上代码片段时,Iterator的Cursor指向List中的第一个元素,如上图所示。
然后运行以下代码片段。

namesIterator.hasNext();
namesIterator.next();

当我们运行以上代码片段时,Iterator的Cursor指向List中的第二个元素,如上图所示。
执行此过程,将Iterator的Cursor移到List的末尾。

阅读完最后一个元素后,如果我们运行下面的代码片段,它将返回" false"值。

namesIterator.hasNext();

当Iterator的Cursor指向List的最后一个元素之后时,hasNext()方法将返回false值。

观察所有这些图之后,我们可以说Java Iterator仅支持正向迭代,如下图所示。
因此也称为单向游标。

Java Iterator的优点

与Enumeration接口相比,Java Iterator具有以下优点或者好处。

  • 我们可以将其用于任何Collection类。

  • 它支持读取和删除操作。

  • 它是Collection API的通用游标。

  • 方法名称简单易用。

Java Iterator的局限性

但是,Java Iterator具有以下限制或者缺点。

  • 在CRUD操作中,它不支持CREATE和UPDATE操作。

  • 它仅支持单向迭代器的正向迭代。

  • 与Spliterator相比,它不支持并行迭代元素,这意味着它仅支持顺序迭代。

  • 与Spliterator相比,它不支持更好的性能来迭代大量数据。

为了克服这些限制,Java又引入了两个游标:ListIterator和Spliterator。
我们将在我的后续文章中讨论这两个游标。

Java枚举和迭代器之间的相似之处

在本节中,我们将讨论两个Java游标之间的相似之处:Java枚举和迭代器

  • 两者都是Java游标。

  • 两者都用于一个Collection对象元素一个一个的迭代。

  • 两者都支持READ或者Retrieval操作。

  • 两者都是单向Java游标,这意味着仅支持正向迭代。

Java枚举和迭代器之间的区别

下表描述了Java枚举和迭代器之间的区别:

EnumerationIterator
Introduced in Java 1.0Introduced in Java 1.2
Legacy InterfaceNot Legacy Interface
It is used to iterate only Legacy Collection classes.We can use it for any Collection class.
It supports only READ operation.It supports both READ and DELETE operations.
It's not Universal Cursor.Its a Universal Cursor.
Lengthy Method names.Simple and easy to use method names.