热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么要使用泛型和迭代器

为什么要使用泛型和迭代器+面试题泛型1)为什么要用泛型?在泛型没有诞生之前,我们经常会遇到这样的问题,如以下代码所示:ArrayListarrayListnewArrayList(

为什么要使用泛型和迭代器 + 面试题

泛型

1)为什么要用泛型?

在泛型没有诞生之前,我们经常会遇到这样的问题,如以下代码所示:

ArrayList arrayList = new ArrayList();
arrayList.add("Java");
arrayList.add(24);
for (int i = 0; i 

看起来好像没有什么大问题,也能正常编译,但真正运行起来就会报错:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

at xxx(xxx.java:12)

类型转换出错,当我们给 ArrayList 放入不同类型的数据,却使用一种类型进行接收的时候,就会出现很多类似的错误,可能更多的时候,是因为开发人员的不小心导致的。那有没有好的办法可以杜绝此类问题的发生呢?这个时候 Java 语言提供了一个很好的解决方案——“泛型”。

2)泛型介绍

泛型:泛型本质上是类型参数化,解决了不确定对象的类型问题。
泛型的使用,请参考以下代码:

ArrayList arrayList = new ArrayList();
arrayList.add("Java");

这个时候如果给 arrayList 添加非 String 类型的元素,编译器就会报错,提醒开发人员插入相同类型的元素。

这样就可以避免开头示例中,类型不一致导致程序运行过程中报错的问题了。

3)泛型的优点

泛型的优点主要体现在以下三个方面。

  • 安全:不用担心程序运行过程中出现类型转换的错误。
  • 避免了类型转换:如果是非泛型,获取到的元素是 Object 类型的,需要强制类型转换。
  • 可读性高:编码阶段就明确的知道集合中元素的类型。

迭代器(Iterator)

1)为什么要用迭代器?

我们回想一下,在迭代器(Iterator)没有出现之前,如果要遍历数组和集合,需要使用方法。

数组遍历,代码如下:

String[] arr = new String[]{"Java", "Java虚拟机", "Java中文社群"};
for (int i = 0; i 

集合遍历,代码如下:

List list = new ArrayList() {{
    add("Java");
    add("Java虚拟机");
    add("Java中文社群");
}};
for (int i = 0; i 

而迭代器的产生,就是为不同类型的容器遍历,提供标准统一的方法。

迭代器遍历,代码如下:

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    Object object = iterator.next();
    // do something
}

总结:使用了迭代器就可以不用关注容器的内部细节,用同样的方式遍历不同类型的容器。

2)迭代器介绍

迭代器是用来遍历容器内所有元素对象的,也是一种常见的设计模式。

迭代器包含以下四个方法。

  • hasNext():boolean —— 容器内是否还有可以访问的元素。
  • next():E —— 返回下一个元素。
  • remove():void —— 删除当前元素。
  • forEachRemaining(Consumer):void —— JDK 8 中添加的,提供一个 lambda 表达式遍历容器元素。

迭代器使用如下:

List list = new ArrayList() {{
    add("Java");
    add("Java虚拟机");
    add("Java中文社群");
}};
Iterator iterator =  list.iterator();
// 遍历
while (iterator.hasNext()){
    String str = (String) iterator.next();
    if (str.equals("Java中文社群")){
        iterator.remove();
    }
}
System.out.println(list);

程序执行结果:

[Java, Java虚拟机]

forEachRemaining 使用如下:

List list = new ArrayList() {{
    add("Java");
    add("Java虚拟机");
    add("Java中文社群");
}};
// forEachRemaining 使用
list.iterator().forEachRemaining(item -> System.out.println(item));

相关面试题

1.为什么迭代器的 next() 返回的是 Object 类型?

答:因为迭代器不需要关注容器的内部细节,所以 next() 返回 Object 类型就可以接收任何类型的对象。

2.HashMap 的遍历方式都有几种?

答:HashMap 的遍历分为以下四种方式。

  • 方式一:entrySet 遍历
  • 方式二:iterator 遍历
  • 方式三:遍历所有的 key 和 value
  • 方式四:通过 key 值遍历

以上方式的代码实现如下:

Map hashMap = new HashMap();
hashMap.put("name", "老王");
hashMap.put("sex", "你猜");
// 方式一:entrySet 遍历
for (Map.Entry item : hashMap.entrySet()) {
  System.out.println(item.getKey() + ":" + item.getValue());
}
// 方式二:iterator 遍历
Iterator> iterator = hashMap.entrySet().iterator();
while (iterator.hasNext()) {
  Map.Entry entry = iterator.next();
  System.out.println(entry.getKey() + ":" + entry.getValue());
}
// 方式三:遍历所有的 key 和 value
for (Object k : hashMap.keySet()) {
  // 循环所有的 key
  System.out.println(k);
}
for (Object v : hashMap.values()) {
  // 循环所有的值
  System.out.println(v);
}
// 方式四:通过 key 值遍历
for (Object k : hashMap.keySet()) {
  System.out.println(k + ":" + hashMap.get(k));
}

3.以下关于泛型说法错误的是?

A:泛型可以修饰类
B:泛型可以修饰方法
C:泛型不可以修饰接口
D:以上说法全错

答:选 C,泛型可以修饰类、方法、接口、变量。
例如:

public interface Iterable\ {
}

4.以下程序执行的结果是什么?

List list = new ArrayList<>();
List list2 = new ArrayList<>();
System.out.println(list.getClass() == list2.getClass());

答:程序的执行结果是 true
题目解析:Java 中泛型在编译时会进行类型擦除,因此 List listList list2 类型擦除后的结果都是 java.util.ArrayLis ,进而 list.getClass() == list2.getClass() 的结果也一定是 true。

5. ListList 有什么区别?

答:List 可以容纳任意类型,只不过 List 被赋值之后,就不允许添加和修改操作了;而 ListList 不同的是它在赋值之后,可以进行添加和修改操作,如下图所示:

6.可以把 List 赋值给 List 吗?

答:不可以,编译器会报错,如下图所示:

List 和 List 的区别是什么?

答: ListList 都能存储任意类型的数据,但 ListList 的唯一区别就是,List 不会触发编译器的类型安全检查,比如把 List 赋值给 List 是没有任何问题的,但赋值给 List 就不行,如下图所示:

List list = new ArrayList<>();
list.add("Java");
list.add("Java虚拟机");
list.add("Java中文社群");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    String str = (String) iterator.next();
    if (str.equals("Java中文社群")) {
        iterator.remove();
    }
}
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
System.out.println("Over");

答:程序打印结果是 Over
题目解析:因为第一个 while 循环之后,iterator.hasNext() 返回值就为 false 了,所以不会进入第二个循环,之后打印最后的 Over。

9.泛型的工作原理是什么?为什么要有类型擦除?

答:泛型是通过类型擦除来实现的,类型擦除指的是编译器在编译时,会擦除了所有类型相关的信息,比如 List 在编译后就会变成 List 类型,这样做的目的就是确保能和 Java 5 之前的版本(二进制类库)进行兼容。

总结

通过本文知道了泛型的优点:安全性、避免类型转换、提高了代码的可读性。泛型的本质是类型参数化,但编译之后会执行类型擦除,这样就可以和 Java 5 之前的二进制类库进行兼容。本文也介绍了迭代器(Iterator)的使用,使用迭代器的好处是不用关注容器的内部细节,用同样的方式遍历不同类型的容器。


欢迎关注我的公众号,回复关键字“Java” ,将会有大礼相送!!! 祝各位面试成功!!!
技术图片
%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png)

为什么要使用泛型和迭代器


推荐阅读
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
author-avatar
何炘柱_549
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有