论坛首页 入门技术论坛

关于Map.entrySet()的疑惑

浏览 12879 次
该帖已经被评为新手帖
作者 正文
   发表时间: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;
	}
}

   发表时间:2006-11-09  
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!
0 请登录后投票
   发表时间:2006-11-09  
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!


但是.我如果直接转换成Object,输出的却是TestObject呢?
0 请登录后投票
   发表时间:2006-11-09  
wuhua 写道
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!


但是.我如果直接转换成Object,输出的却是TestObject呢?

去看HashMap.Entry的实现啊,必然是调用了Value的toString方法咯...
0 请登录后投票
   发表时间:2006-11-09  
Hibernate的 Map重写了java Map呀,所以应该看看Hibernate源码
比较好吧
0 请登录后投票
   发表时间:2006-11-09  
引用
//输出,这里进行类型强制转换,出现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.);  
        }  
这2段不是一样的吗?而且你前面放test的KEY是Integer啊 ,不知道你们说得这么深奥是干什么哦,还望赐教
0 请登录后投票
   发表时间:2006-11-09  
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!

上面没看清楚,我去查查看。
0 请登录后投票
   发表时间: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();
        }




哈哈.我明白了.
0 请登录后投票
   发表时间:2006-11-09  
我感觉你没真的理解哦,value 的toString()
0 请登录后投票
   发表时间:2006-11-09  
引用
我感觉你没真的理解哦,value 的toString()

愿听您详解
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics