集合输出 | 带你学《Java语言高级特性》之一百零六

简介: 本节介绍了集合输出的四种形式:Iterator迭代输出、ListIterator双向迭代输出、Enumeration枚举输出、foreach输出。

上一篇:TreeSet子类排序操作 | 带你学《Java语言高级特性》之一百零五
【本节目标】
本节需要掌握集合输出的四种形式:Iterator迭代输出、ListIterator双向迭代输出、Enumeration枚举输出、foreach输出。

集合输出

集合输出实际上从JDK1.8开始就在Iterable接口中提供了一个forEach()方法,但是这种方法输出并不是传统意义上集合输出形式,并且也很难在实际的开发之中出现,对于集合操作而言,一共有四种输出形式:Iterator迭代输出(95%)、ListIterator双向迭代输出(0.1%)、Enumeration枚举输出(4.9%)、foreach输出(与Iterator相当)。

Iterator迭代输出

通过Collection接口的继承关系可以发现,从JDK1.5开始其多继承了一个Iterable父接口,并且在这个接口里面定义有一个iterator()操作方法,通过此方法可以获取Iterator接口对象(在JDK1.5之前,这一方法直接定义在Collection接口之中)。

获取Iterator接口对象:public Iterator<T> iterator​();

在Iterator接口里面定义有如下的方法:

No. 方法名称 类型 描述
01 public boolean hasNext​() 普通 判断是否有数据
02 public E next​() 普通 取出当前数据
03 default void remove​() 普通 删除

在之前使用的java.util.Scanner类就是Iterator接口的子类,所以此时类继承关系如下:

image.png
Iterator接口

范例:使用Iterator输出

import java.util.Set;
import java.util.Iterator;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        Set<String> all = Set.of("Hello", "World", "MLDN");
        Iterator<String> iter = all.iterator();   //实例化Iterator接口对象
        while (iter.hasNext()) {
            String str = iter.next();
            System.out.println(str);   // World Hello MLDN
        }
    }
}

但是对于Iterator接口中的remove()方法的使用需要特别注意一下(如果不是必须不要使用)。实际上在Collection接口中定义有数据的删除操作方法,但是在进行迭代输出的过程中如果你使用了Collection中的remove()方法会导致迭代失败。
范例:采用Collection集合中remove()方法删除

import java.util.Set;
import java.util.Iterator;
import java.util.HashSet;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        Set<String> all = new HashSet<String>();
        all.add("Hello");
        all.add("World");
        all.add("MLDN");
        Iterator<String> iter = all.iterator();   //实例化Iterator接口对象
        while (iter.hasNext()) {
            String str = iter.next();
            if ("World".equals(str)) {
                all.remove("World");  //Collection集合方法
            }else {
                System.out.println(str);   //  Hello   Exception in thread "main" java.util.ConcurrentModificationException
            }
        }
    }
}

此时无法进行数据删除处理操作,那么就只能够利用Iterator接口中的remove()方法删除。

范例:使用Iterator接口删除方法

import java.util.Set;
import java.util.Iterator;
import java.util.HashSet;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        Set<String> all = new HashSet<String>();
        all.add("Hello");
        all.add("World");
        all.add("MLDN");
        Iterator<String> iter = all.iterator();   //实例化Iterator接口对象
        while (iter.hasNext()) {
            String str = iter.next();
            if ("World".equals(str)) {
                iter.remove();  //Collection集合方法
            }else {
                System.out.println(str);   //  Hello   Exception in thread "main" java.util.ConcurrentModificationException
            }
        }
        System.out.println("*** "+ all);  
    }
}
//Hello
//MLDN
//*** [Hello, MLDN]

此时程序执行后没有出现任何的错误,并且可以成功的删除原始集合中的数据。
面试题:
请解释Collection.remove()与Iterator.remove()的区别?
在进行迭代输出的时候,如果使用了Collection.remove()则会造成并发更新的异常,导致程序删除出错,而此时只能够利用Iterator接口中remove()方法实现正常的删除处理。

ListIterator双向迭代输出

使用Iterator进行的迭代输出操作有一个特点:只允许由前向后输出,而如果现在需要进行双向迭代处理,那么就必须依靠Iterator的子接口:ListIterator接口来实现了。需要注意的是,如果想要获取ListIterator接口对象,Collection中并没有定义相关的处理方法,但是List子接口有,也就是说这个输出的接口是专门为List集合准备的。

image.png
ListIterator接口

ListIterator接口中定义有如下的操作方法:

判断是否有前一个元素:public boolean hasPrevious()
获取当前元素:public E previous()

范例:实现双向迭代

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        List<String> all = new ArrayList<String>();
        all.add("Hello");
        all.add("World");
        all.add("MLDN");
        ListIterator<String> iter = all.listIterator();
        System.out.print("由前向后输出:");
        while (iter.hasNext()) {
            System.out.print(iter.next() + "、");
        }
        System.out.print("\n由后向前输出:");   //由前向后输出:Hello、World、MLDN、
        while (iter.hasPrevious()) {
            System.out.print(iter.previous() + "、");  //由后向前输出:MLDN、World、Hello、
        }      
    }
}

如果想实现由后向前的遍历,那么首先要实现的是由前向后实现遍历处理。

Enumeration输出

Enumeration是在JDK1.0的时候就使用的输出接口,这个输出接口主要是为了Vector类提供服务的,一直到后续的JDK的发展,Enumeration依然只为Vector一个类服务,所以要想获取Enumeration接口对象,那么必须依靠Vector类提供的方法:

获取Enumeration:public Enumeration<E> elements()
在Enumeration接口中定义有两个操作方法:
判断是否有下一个元素:public boolean hasMoreElements()
获取当前元素:public E nextElement()

image.png
Enumeration

范例:使用Enumeration实现输出

import java.util.Enumeration;
import java.util.Vector;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        Vector<String> all = new Vector<String>();
        all.add("Hello");
        all.add("World");
        all.add("MLDN");
        Enumeration<String> enu = all.elements();
        while (enu.hasMoreElements()) {
            String str = enu.nextElement();
            System.out.print(str +"、");    //Hello、World、MLDN、
        }
    }
}

由于该接口出现的时间比较长了,所以在一些比较早的开发过程中,也有部分的方法只支持Enumeration输出操作,但随着类方法的不断完善,大部分的操作都能直接利用Iterator实现了。

foreach输出

除了使用迭代接口实现输出之外,从JDK1.5开始加强型for循环也可以实现集合的输出了。这种输出的形式与数组的输出操作形式类似。
范例:使用foreach输出

import java.util.ArrayList;
import java.util.List;
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        List<String> all = new ArrayList<String>();
        all.add("Hello");
        all.add("World");
        all.add("MLDN");
        for (String str : all){
            System.out.print(str+"、");   //Hello、World、MLDN、
        }     
    }
}

这种输出最初出现时很多人并不建议使用,因为标准的集合操作还是以Iterator为主,但是毕竟JDK1.5都已经推出十多年了,很多语法也开始被大部分人所习惯。

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:Map接口 | 带你学《Java语言高级特性》之一百零七
更多Java面向对象编程文章查看此处

相关文章
|
9天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
19 2
|
11天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
25 4
|
9天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
14天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
14天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
14天前
|
Java 开发者
|
26天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
53 5
|
26天前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
50 3
|
26天前
|
存储 安全 Java
Java Map新玩法:深入探讨HashMap和TreeMap的高级特性
【10月更文挑战第19天】Java Map新玩法:深入探讨HashMap和TreeMap的高级特性,包括初始容量与加载因子的优化、高效的遍历方法、线程安全性处理以及TreeMap的自然排序、自定义排序、范围查询等功能,助你提升代码性能与灵活性。
24 2
|
27天前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
52 3