有关map中使用iterate迭代器遍历的不保序问题和list remove(object)的细节问题
今天在做项目的过程中发现了如下两个问题:
一 使用map的iterator迭代器对map进行遍历得到的结果是不保序的,也就是每次输出结果都是不一样的。针对这个问题,看以下iterator迭代器的源码。
二list的remove(Object obj) 和 removeAll()方法在删除的时候需要注意的几个地方。
上面两个问题都是比较细小的一些细节问题,但是如果基础知识不牢靠的话,那你在项目中如果使用到但是不知道这些问题,你有可能会遇到灾难性的后果。大家注意以下把。举个简单的例子,按照你的正常的逻辑你可能一直认为就是按照你想要的顺序进行遍历的,但是实际上却不是这样的。当你在项目中的时候,你会发现不知道怎么回事每次都得到不一样的结果,但是程序却没有任何异常。总之像这些比较细节,但是很考验功底的时候,我们不可能任何这种细节的问题都知道,但是每当我们遇到的时候都总结一下记住理解了就可以了。
好了下面针对这两个问题说一下吧。首先是第一个关于map 使用iterator迭代器遍历的时候不保序的问题。先上一个代码大家看看输出结果是什么。
Map<Integer, String> map = new HashMap<Integer, String>();
for(int i = 0;i<50;i++){
map.put(i, i+"");
}
Set<Entry<Integer, String>> iteratorSets = map.entrySet();
Iterator<Entry<Integer, String>> iterators=iteratorSets.iterator();
while (iterators.hasNext()) {
Entry<Integer, String> entry = iterators.next();
System.out.println("key :"+entry.getKey()); }
针对上面的这段代码,我们看看他两次的输出结果分别是:
key :0key :1key :2key :3key :4key :5key :6key :7key :8key :9key :10key :11key :12key :13key :14key :15key :17key :16key :19key :18key :21key :20key :23key :22key :25key :24key :27key :26key :29key :28key :31key :30key :34key :35key :32key :33key :38key :39key :36key :37key :42key :43key :40key :41key :46key :47key :44key :45key :49key :48
和key :0key :1key :2key :3key :4key :5key :6key :7key :8key :9key :10key :11key :12key :13key :14key :15key :17key :16key :19key :18key :21key :20key :23key :22key :25key :24key :27key :26key :29key :28key :31key :30key :34key :35key :32key :33key : 38key :39key :36key :37key :42key :43key :40key :41key :46key :47key :44key :45key :49key :48
从上面的两次的输出结果就可以看出来使用iterators迭代器是不能保证每次输出来的顺序的。当然先说一句,这里如果使用的是for来遍历这个map的话是没有问题的,因为for遍历的时候是从map的第一个元素进行遍历的。
知道了这个现象,那我们看一下map使用iterators进行迭代输出的时候为什么是不保序的,来看以下iterators的源码是怎么写的?
说道这个迭代器其实有研究过jdk中有关集合的源码的话,大家应该知道jdk中的集合有两种类型,一种是基于collection的,一种是基于map的,而基于collection这个集合接口的都是实现了iterator这个迭代器接口的,而这个iterator迭代器接口中只有三个方法,hasnext,next和iterator()返回iterator对象的方法。所以也就是说所有的实现了或者说基于collection接口的都有迭代器的功能。在这个迭代器中是如何对每一个具体的集合进行迭代的在方法中我们可以看到为什么是保序的了。
对于第二个问题。list remove()的删除中的一些细节的实现上需要注意的一些问题。说道这个remove,其实主要是想说一下在什么情况下回执行remove操作。在源代码中我们可以看到,如果是remove(int index)的话是没有问题的,因为是根据索引直接删除的。要说有问题的地方是如果要删除的事个对象的话在什么情况下回删除成功,好了直接说吧,就是在执行remove(object)的时候list默认会根据这个对象的equals()来判断当前要删除的对象是不是在这个集合中。这时候如果要删除的对象没有去显示的重写equals()方法的话,如果这个equals()方法是object默认的话是删除不掉的。我们先看看remove(object)这个源代码是怎么写的:
public boolean remove(Object o) {
if(o == null) {
for(intindex = 0; index < size; index++)
if(elementData[index] == null) {
fastRemove(index);
returntrue;
}
}else{
for(intindex = 0; index < size; index++)
if(o.equals(elementData[index])) {
fastRemove(index);
returntrue;
}
}
returnfalse;
}
在remove的源码中我们看到里面是有的事object的equals()方法来判断的,这个时候我们去看看默认的object中的equals()方法是如何是实现的:
public boolean equals(Object obj) {
return (this == obj);
}
熟悉java对象机制的应该都知道,这里其实是比较的两个对象的在内存中的地址是否相等,而不是比较的内容。所以如果你写如下这样的代码删除是不成功的
public static void main(String args []){
List<Student> students = new ArrayList<Student>();
for(int i = 0;i<10;i++){
Student student = new Student();
student.setName(i+"");
student.setAge(i);
students.add(student);
}
Student stu = new Student();
stu.setName(5+"");
students.remove(stu);
}
如果是这样想删除第五个元素的话是删除失败的,原因很简单,我们在student这个类中没有事重写equals()方法来重新定义判断是否相等的依据。如果我们想根据名称和年龄来判断是否相等可删除的话,需要重写student类的equals()方法。
public boolean equals(Object obj){
if(obj instanceof Student){
Student stu = obj;
if(stu.getName().equals(this.name) && stu.getAge().equals(this.age)){
return true;
}
} else {
return false;
}
}
这样的话相当于自定义了判断相等与否的规则。
上面两个比较细节的知识点,在使用的时候需要大家注意一下。这些虽然很细小确实考验功底的东西啊。好了对于这两个问题就总结到这里,下次再遇到再总结。
有关map中使用iterate迭代器遍历的不保序问题和list remove(object)的细节问题的更多相关文章
- Go map中一个很重要的特性
先看一段代码: func main() { m := make(map[int]string) m[1] = "a" m[2] = "b" m[3] = &qu ...
- JAVA中遍历Map和Set方法,取出map中所有的key
Java遍历Set集合 1.迭代器遍历: Set<String> set = new HashSet<String>(); Iterator<String> it ...
- 迭代器遍历【List、Set、Map】
迭代器遍历[List.Set.Map] example package boom.collection; import java.util.ArrayList; import java.util.Ha ...
- 获取map中的一个value值以及遍历map获得map里所有key、value的值
前言: 1.声明一个map: Map map = new HashMap();2.向map中放值,注意:map是key-value的形式存放的.如: map.put(”sa”,”dd”); 3.从ma ...
- Java List中迭代器遍历
在java中,List接口从Collection接口中继承了 iterator()函数,返回值是一个T类型的迭代器(泛型),T是List中元素的类型 public class TestListAndI ...
- java 迭代器遍历List Set Map
Iterator接口: 所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现Iterator接口的对象 Iterator对象称作为迭代器,用以方便的对容器内元素的遍历 ...
- 信1705-2 软工作业最大重复词查询思路: (1)将文章(一个字符串存储)按空格进行拆分(split)后,存储到一个字符串(单词)数组中。 (2)定义一个Map,key是字符串类型,保存单词;value是数字类型,保存该单词出现的次数。 (3)遍历(1)中得到的字符串数组,对于每一个单词,考察Map的key中是否出现过该单词,如果没出现过,map中增加一个元素,key为该单词,value为1(
通过学习学会了文本的访问,了解一点哈希表用途.经过网上查找做成了下面查询文章重复词的JAVA程序. 1 思 思路: (1)将文章(一个字符串存储)按空格进行拆分(split)后,存储到一个字符串(单词 ...
- Java 中List 集合索引遍历与迭代器遍历
package yzhou.iterator; import java.util.ArrayList; import java.util.HashSet; import java.util.Itera ...
- Map集合的应用及其遍历方式
---> HashMap :底层基于哈希表 存储原理也使用哈希表来存放的: 往HashMap添加了元素 ,首先会调用键的hashCode方法 获得一个哈希值,然后 ...
随机推荐
- Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。
Python3 与 C# 面向对象之-继承与多态 文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...
- 怎样在C语言里实现“面向对象编程”
有人觉得面向对象是C++/Java这样的高级语言的专利,实际不是这样.面向对象作为一种设计方法.是不限制语言的.仅仅能说,用C++/Java这样的语法来实现面向对象会更easy.更自然一些. 在本节中 ...
- 《C程序猿:从校园到职场》出版预告(4):从“散兵游勇”到“正规部队”
看过电视剧<楚汉传奇>的朋友应该对这个场景还有印象:当刘邦第一次去找项羽帮忙的时候.他们一行人看到了项羽军营是怎样练兵的.想到自己练兵的方法,当时就震惊了."刘家军"就 ...
- hdu 2842(矩阵高速幂+递推)
题意:一个中国环的游戏,规则是一个木棒上有n个环.第一个环是能够任意放上或拆下的,剩下的环x假设想放上或拆下必须前一个环x-1是放上的且前x-2个环所有是拆下的,问n个环最少多少次操作能够所有拆掉. ...
- dwr框架中DWRUtil的方法
dwr框架中DWRUtil的方法 2008-10-14 17:57:23| 分类: JAVA | 标签: |举报 |字号大中小 订阅 7. util.js 功能 util.js包含了一些工 ...
- 模式匹配之尺度空间---scale space
转载:http://www.cnblogs.com/cfantaisie/archive/2011/06/14/2080917.html 主要步骤 1).尺度空间的生成: 2).检测尺度 ...
- Creating Tabbed Applications
新建一个空工程,如图 新建类 using System; using UIKit; namespace TabbedApplication { public class TabController : ...
- c# 编程修改 wince 系统时间
[StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public ushort wYear; public ushort ...
- ThreadPoolTaskExecutor
我们在开发过程中经常要用到线程池,线程池应该统一管理起来,而不是随用随建.ThreadPoolTaskExecutor——将线程池交给spring管理 1. ThreadPoolTaskExecuto ...
- 20170301 Excel 分多个sheet 导出
要么上传个EXCEL模板 里面已经有规定好的SHEET页了 要么直接打开个EXCEL 代码里ADDsheet页来做 就是这么点区别 [园工]CD-ABAP-win<allenjj ...