Java迭代器– Java中的迭代器
在本文中,我们将讨论有关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枚举和迭代器之间的区别:
Enumeration | Iterator |
---|---|
Introduced in Java 1.0 | Introduced in Java 1.2 |
Legacy Interface | Not 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. |