|
锁定老贴子 主题:关于Map.entrySet()的疑惑
该帖已经被评为新手帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2006-11-09
前几天项目用到Map,接着调用Map.entrySet(),结果产生了一些意外的后果.
就是,持久化数据数据的时候出现setter of com.hiber.Hibernate.Test.id 异常. 此异常是提醒,pojo里面未有属性的getter. 因为我在其他方法里面保存过,未曾出现异常,觉得甚是奇怪.后来发现,原来是Map.entrySet()搞的鬼,根据java api. 返回此映射中包含的映射关系的 set 视图。返回的 set 中的每个元素都是一个 Map.Entry。该 set 受映射支持,所以对映射的改变可在此 set 中反映出来,反之亦然。如果修改映射的同时正在对该 set 进行迭代(除了通过迭代器自己的 remove 操作,或者通过在迭代器返回的映射项上执行 setValue 操作外),则迭代结果是不明确的。set 支持通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作实现元素移除,即从映射中移除相应的映射关系。它不支持 add 或 addAll 操作。 为此,我写了一个测试代码.
public class TestMap {
/**
* @param args
*/
public static void main(String[] args) {
Map test = new HashMap();
//测试,put进TestObject
for(int i=0; i<5; i++){
TestObject to = new TestObject();
test.put(new Integer(i), to);
}
//输出,这里进行类型强制转换,出现java.lang.ClassCastException.
for(Iterator it = test.entrySet().iterator(); it.hasNext();){
TestObjectt = (TestObject)it.next();
t.toString();
//System.out.println(t.);
}
//输出,这里直接转换成Object,并且输出的是自己定义的toString()
//且可以正常输出,为此,我不理解.为什么转换的时候保存.
//估计是里面做了些什么手脚.
for(Iterator it = test.entrySet().iterator(); it.hasNext();){
TestObjectt = (TestObject)it.next();
t.toString();
//System.out.println(t.);
}
}
}
class TestObject{
public String toString(){
System.out.println("TestObject");
return null;
}
}
声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现! 包含getKey,getValue等操作!结构类似List! map在rehashing时会重新计算entryset! |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
galaxystar 写道 entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现! 包含getKey,getValue等操作!结构类似List! map在rehashing时会重新计算entryset! 但是.我如果直接转换成Object,输出的却是TestObject呢? |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
wuhua 写道 galaxystar 写道 entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现! 包含getKey,getValue等操作!结构类似List! map在rehashing时会重新计算entryset! 但是.我如果直接转换成Object,输出的却是TestObject呢? 去看HashMap.Entry的实现啊,必然是调用了Value的toString方法咯... |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
Hibernate的 Map重写了java Map呀,所以应该看看Hibernate源码
比较好吧 |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
引用 //输出,这里进行类型强制转换,出现java.lang.ClassCastException.
这2段不是一样的吗?而且你前面放test的KEY是Integer啊 ,不知道你们说得这么深奥是干什么哦,还望赐教
for(Iterator it = test.entrySet().iterator(); it.hasNext();){ TestObjectt = (TestObject)it.next(); t.toString(); //System.out.println(t.); } //输出,这里直接转换成Object,并且输出的是自己定义的toString() //且可以正常输出,为此,我不理解.为什么转换的时候保存. //估计是里面做了些什么手脚. for(Iterator it = test.entrySet().iterator(); it.hasNext();){ TestObjectt = (TestObject)it.next(); t.toString(); //System.out.println(t.); } |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
galaxystar 写道 entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现! 包含getKey,getValue等操作!结构类似List! map在rehashing时会重新计算entryset! 上面没看清楚,我去查查看。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
Readonly 写道 wuhua 写道 galaxystar 写道 entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现! 包含getKey,getValue等操作!结构类似List! map在rehashing时会重新计算entryset! 但是.我如果直接转换成Object,输出的却是TestObject呢? 去看HashMap.Entry的实现啊,必然是调用了Value的toString方法咯... 谢谢高手的提示: 我去看了下源代码,已经搞明白了 按照提示:查看代码的流程是 1.
//获取EntrySet;
public Set entrySet() {
Set es = entrySet;
return (es != null ? es : (entrySet = new EntrySet())); //HashMap内部实现了个EntrySet
}
//下面看看EntrySet的实现
private class EntrySet extends AbstractSet {
//重点看看这段代码
public Iterator iterator() {
return newEntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Entry candidate = getEntry(e.getKey());
return candidate != null && candidate.equals(e);
}
public boolean remove(Object o) {
return removeMapping(o) != null;
}
public int size() {
return size;
}
public void clear() {
HashMap.this.clear();
}
}
得到Iterator实例:EntryIterator.
private class EntryIterator extends HashIterator {
public Object next() {
return nextEntry();
}
}
Entry nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry e = next;
if (e == null)
throw new NoSuchElementException();
Entry n = e.next;
Entry[] t = table;
int i = index;
while (n == null && i > 0)
n = t[--i];
index = i;
next = n;
return current = e;
}
static class Entry implements Map.Entry {
final Object key;
Object value;
final int hash;
Entry next;
/**
* Create new entry.
*/
Entry(int h, Object k, Object v, Entry n) {
value = v;
next = n;
key = k;
hash = h;
}
public Object getKey() {
return unmaskNull(key);
}
public Object getValue() {
return value;
}
public Object setValue(Object newValue) {
Object oldValue = value;
value = newValue;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public int hashCode() {
return (key==NULL_KEY ? 0 : key.hashCode()) ^
(value==null ? 0 : value.hashCode());
}
//最后系统调用的是这里的方法.
public String toString() {
return getKey() + "=" + getValue();
}
哈哈.我明白了. |
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
我感觉你没真的理解哦,value 的toString()
|
|
| 返回顶楼 | |
|
最后更新时间:2006-11-09
引用 我感觉你没真的理解哦,value 的toString() 愿听您详解 |
|
| 返回顶楼 | |










