今天在做项目的过程中发现了如下两个问题:

一 使用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)的细节问题的更多相关文章

  1. Go map中一个很重要的特性

    先看一段代码: func main() { m := make(map[int]string) m[1] = "a" m[2] = "b" m[3] = &qu ...

  2. JAVA中遍历Map和Set方法,取出map中所有的key

    Java遍历Set集合 1.迭代器遍历: Set<String> set = new HashSet<String>(); Iterator<String> it ...

  3. 迭代器遍历【List、Set、Map】

    迭代器遍历[List.Set.Map] example package boom.collection; import java.util.ArrayList; import java.util.Ha ...

  4. 获取map中的一个value值以及遍历map获得map里所有key、value的值

    前言: 1.声明一个map: Map map = new HashMap();2.向map中放值,注意:map是key-value的形式存放的.如: map.put(”sa”,”dd”); 3.从ma ...

  5. Java List中迭代器遍历

    在java中,List接口从Collection接口中继承了 iterator()函数,返回值是一个T类型的迭代器(泛型),T是List中元素的类型 public class TestListAndI ...

  6. java 迭代器遍历List Set Map

    Iterator接口: 所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现Iterator接口的对象 Iterator对象称作为迭代器,用以方便的对容器内元素的遍历 ...

  7. 信1705-2 软工作业最大重复词查询思路: (1)将文章(一个字符串存储)按空格进行拆分(split)后,存储到一个字符串(单词)数组中。 (2)定义一个Map,key是字符串类型,保存单词;value是数字类型,保存该单词出现的次数。 (3)遍历(1)中得到的字符串数组,对于每一个单词,考察Map的key中是否出现过该单词,如果没出现过,map中增加一个元素,key为该单词,value为1(

    通过学习学会了文本的访问,了解一点哈希表用途.经过网上查找做成了下面查询文章重复词的JAVA程序. 1 思 思路: (1)将文章(一个字符串存储)按空格进行拆分(split)后,存储到一个字符串(单词 ...

  8. Java 中List 集合索引遍历与迭代器遍历

    package yzhou.iterator; import java.util.ArrayList; import java.util.HashSet; import java.util.Itera ...

  9. Map集合的应用及其遍历方式

    ---> HashMap :底层基于哈希表      存储原理也使用哈希表来存放的:            往HashMap添加了元素 ,首先会调用键的hashCode方法 获得一个哈希值,然后 ...

随机推荐

  1. div和img之间的缝隙问题

    这次做的项目,客户说.banner图的上下之间不要留有空隙,细致一看才发现,上下居然都有空隙.审查元素,发现全部的div,img的padding和margin都是0,对于这个间隙到底是假设产生的真的是 ...

  2. linux 块设备驱动(二)——块设备数据结构

    本文来源于: 1. http://www.cnblogs.com/dyllove98/archive/2013/07/01/3165567.html 块设备相关的数据结构以及接口: 块设备接口则相对复 ...

  3. Web性能测试工具:Siege安装&使用简介

    在Web性能测试工具中,siege是比较热门和常见的,它有安装简单,使用简单,测试报告详细的特点. 并且可以在文本中预定义一系列待测试url模拟,并可设定一定并发量下持续指定时间or测试进行测试. 比 ...

  4. Python标准库:内置函数set([iterable])

    本函数是从迭代对象生成集合.集合能够添加或删除元素. 样例: #set() tset = set([1, 2, 3, 3, 4, 5, 6, 6]) print(tset) tset.add(20) ...

  5. 登录和注册(Js)的写法

    今天在做小组项目的时候发现登录和注册的使用不是很熟,记录下来: <script> //弹出框中的css部分 input { font-family: Arial, sans-serif;} ...

  6. UI 自动化测试工具BackstopJS简介(1)

    BackstopJS源码地址 https://github.com/garris/BackstopJS 我写了一个DEMO放到github上面,https://github.com/shenggen1 ...

  7. linux host=${host:-"localhost"}使用方法

    localhost=${host:-"localhost"} host 变量未设定或者为空,host取"-"后面的值;否则host=$host host=${h ...

  8. beego 导入一个普通的包都会执行init方法,如果是struct就不会执行

    default.go package controllers import ( "beego-test/models" "beego-test/service" ...

  9. ubuntu 12.04安装alsa-lib、alsa-utils【转】

    1. alsa-lib ./configure sudo make install 注意:默认是安装到/usr/这个目录下面,但是我测试多了多次,安装了alsa-lib之后,系统就没有声音了,也没有找 ...

  10. MySQL学习笔记(五)—— 子查询及联结

    子查询: 子查询,即嵌套在其他查询中的查询.例如我们有这样几个表,顾客表,订单表,商品表,我们想知道有哪些客户买了商品A,那么我们就需要先查看哪些订单里包含了商品A,然后根据订单查出是哪些客户. my ...