黑马程序员技术交流社区
标题: 迭代器的问题 [打印本页]
作者: 殷婷婷 时间: 2013-10-8 21:04
标题: 迭代器的问题
本帖最后由 殷婷婷 于 2013-10-10 10:59 编辑
main函数中
ArrayList al = new ArrayList();
al.add(“----1”);
al.add(“----2”);
Iterator it = al.iterator();
while(it.hasNext())
{
Objectobj = it.next();
if(obj.equals(“----1”))
it.remove();//我不明白的是此时----1已经被删掉了,obj此时怎么还会指向----1并输出呢?迭代器到底是怎么个原理?
System.out.println(obj);
}
结果是:
----1
----2
作者: 落木萧萧 时间: 2013-10-8 23:24
尝试着回答一下,可能是这样的,iterator里有个计数器,当你remove的时候这个计数器不会马上减一,因为程序迭代器要保证迭代过程中集合的完整性,所以再次执行next方法时,才会把那个计数器减一,也可以理解成“真正的”remove.所以输出的时候还是那个list。刚才说了,迭代的时候要保证完整性,所以绝对不能在remove后再remove或者add.爪机无力,纯手打,没
作者: 落木萧萧 时间: 2013-10-8 23:25
没法组织语言,抱歉
作者: a283398689 时间: 2013-10-9 08:33
我来回答一下,~ 亲 , 你删的是容器里面的吧,~ 但是你删除之前 已经把这个对象NEW出来给呢OBJ
OBJ 和容器是没有联系的 明白呢吗 不懂在问
作者: 殷婷婷 时间: 2013-10-9 10:22
你好,请问能说再详细点吗?为什么Obj和容器是没有关系的?迭代器到底是什么啊?
作者: yting_xmei1129 时间: 2013-10-9 10:57
迭代器(Iterator)
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
迭代器应用:
list l = new ArrayList();
l.add("aa");
l.add("bb");
l.add("cc");
for (Iterator iter = l.iterator(); iter.hasNext();) {
String str = (String)iter.next();
System.out.println(str);
}
/*迭代器用于while循环
Iterator iter = l.iterator();
while(iter.hasNext()){
String str = (String) iter.next();
System.out.println(str);
}
*/
作者: 殷婷婷 时间: 2013-10-9 13:29
你的答案我在百度上看过了。However,Thanks.
作者: 张慧 时间: 2013-10-9 13:59
这里的迭代器,你可以先看下ArrayList的源码,在ArrayList里有个私有成员:
private transient Object[] elementData;
这个是用来存集合中对象的。
ArrayList继承了AbstractList,在AbstractList里有个内部类 private class Itr implements Iterator<E> ;
这个就是迭代器。
it.remove();//我不明白的是此时----1已经被删掉了,obj此时怎么还会指向----1并输出呢?迭代器到底是怎么个原理?
其实在调用迭代器在调用自己的remove()方法的内部是调用了AbstractList的remove(int index)方法。至于这个index的值是怎么获得的,看源码后就知道,值是lastRet,这个是Itr (迭代器)中用来保存最后一个位置的下标。因为ArrayList继承了AbstractList,所以,在这里就要看一下ArrayList源码中的remove(index)方法,原代码:- E oldValue = (E) elementData[index];
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- return oldValue;
- }
复制代码 可以看出,他是将elementData中index位置之后的对象都向前移动,最后在让最后一个对象指向null.
即使是这样,但感觉被删除的对象,是没有立刻从对内存中释放的,他会再保留一段时间。
Objectobj = it.next();这里是将一个obj引用指向了那个地址。
当 System.out.println(obj)时,即使你感觉删除了那个对象,其实在内存中仍然存在,一段时间内,会有GC(垃圾回收机制)去检查,如果无用就会真正从内存中删除。
(其实就是引用去指向其他地址了,单这不代表那个地址就不存在了)
作者: kmter 时间: 2013-10-9 23:02
本帖最后由 kmter 于 2013-10-9 23:04 编辑
Object obj = it.next();
这里是将对象的引用即对象在内存中的首地址传递给了obj
it.remove();
这句话只是将当前的迭代元素的引用从集合中删除了,注意,删除的只是对象的引用,并非对象本身
System.out.println(obj);
由于obj任然指向内存中"----1”这个字符串,GC是不会将其回收的,故会出现你那样的疑问。
张慧已经分析了remove的源代码,希望可以帮到你理解这个问题。
作者: IT_JM 时间: 2013-10-9 23:28
容器里面存储的是这些对象的哈希值,也就是地址,remove()只是删除了存在集合容器中的地址,但是这个对象还在内存中,没有被删除呢,而且你又把这个对象给了Object,相当于父类指向子类对象了,不就是多态嘛。
再给你打个比喻:你有一个很多东西,突然有一天有一个东西你不喜欢了或者不想要了,你把它送给了别人(当然是能用的,不是坏的,哈哈~),是不是别人拿着这个东西也能用啊。你这个送的过程就相当于那个remove()
作者: 殷婷婷 时间: 2013-10-10 10:56
谢谢,懂了哦:handshake
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |