有关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方法 获得一个哈希值,然后 ...
随机推荐
- professional cuda c programming--CUDA库简单介绍
CUDA Libraries简单介绍 上图是CUDA 库的位置.本文简要介绍cuSPARSE.cuBLAS.cuFFT和cuRAND.之后会介绍OpenACC. cuSPARSE线性代数库,主要针 ...
- Gson解析数组和list容器
Gson解析数组和list容器 使用Gson解析首先须要增加架包文件:gson-2.2.4.jar 定义一个类Student: public class Student { String name=& ...
- bootstrap-table自己配置
function initTable(){ var methodNameSearch=$("#methodNameSearch").val(); var requestUrl = ...
- Dynamic Language Runtime (DLR) 初深
本文主要包括两个内容:DLR在.Net中的位置和一次DLR的调用过程. 1. DLR在. Net 中的位置 图1 DLR 包括哪些内容? 1. Expression Tree(表达式树). 2. Dy ...
- ZOJ 3551 Bloodsucker <概率DP>
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3551 题意:开始有N-1个人和一个吸血鬼, 每天有两个生物见面,当人 ...
- python中的类的成员变量以及property函数
1 python类的各种变量 1.1 全局变量 在类外定义的变量. 1.2 类变量 定义在类里面,所有的函数外面的变量.这个变量只有一份,是所有的对象共有的.在类外用“类.”来引用. 1.3 实例变量 ...
- Geoffrey E. Hinton
https://www.cs.toronto.edu/~hinton/ Geoffrey E. Hinton I am an Engineering Fellow at Google where I ...
- 【NOIP 模拟赛】 道路
题目描述在二维坐标平面里有 N 个整数点,信息班某一巨佬要访问这 N 个点.刚开始巨佬在点(0,0)处. 每一步,巨佬可以走到上.下.左.右四个点.即假设巨佬当前所在点的坐标是(x,y),那么它下一步 ...
- [Spring Batch 系列] 第一节 初识 Spring Batch
距离开始使用 Spring Batch 有一段时间了,一直没有时间整理,现在项目即将完结,整理下这段时间学习和使用经历. 官网地址:http://projects.spring.io/spring-b ...
- Linux - Unix环境高级编程(第三版) 源代码编译(即头文件apue.h如何使用问题)【转】
本文转载自:http://blog.csdn.net/hadas_wang/article/details/43203795 1. 下载代码:http://www.apuebook.com/code3 ...