`
wuhua
  • 浏览: 2112249 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

关于Map.entrySet()的疑惑

阅读更多
前几天项目用到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;
	}
}

分享到:
评论
11 楼 我不知道 2007-06-26  
这段代码的输出隐蔽性很强啊。呵呵
追究根源才是真理。
10 楼 jianfeng008cn 2006-11-11  
Readonly 写道
wuhua 写道
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!


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

去看HashMap.Entry的实现啊,必然是调用了Value的toString方法咯...

上面人家已经说了呀,
你放进去的是TestObject 为什么转成Object后就该是Object 的 toString() 呀,输出是TestObject的 不是很正常?你看了map的源代码就说知道了,可这里面的关系和这个错误关系不大吧,我感觉你的理解就好象把一个对象转成接口来调用的时候方法都变空了。
9 楼 wuhua 2006-11-09  
引用
我感觉你没真的理解哦,value 的toString()

愿听您详解
8 楼 jianfeng008cn 2006-11-09  
我感觉你没真的理解哦,value 的toString()
7 楼 wuhua 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();
        }




哈哈.我明白了.
6 楼 jianfeng008cn 2006-11-09  
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!

上面没看清楚,我去查查看。
5 楼 jianfeng008cn 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啊 ,不知道你们说得这么深奥是干什么哦,还望赐教
4 楼 ASDF1982 2006-11-09  
Hibernate的 Map重写了java Map呀,所以应该看看Hibernate源码
比较好吧
3 楼 Readonly 2006-11-09  
wuhua 写道
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!


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

去看HashMap.Entry的实现啊,必然是调用了Value的toString方法咯...
2 楼 wuhua 2006-11-09  
galaxystar 写道
entrySet迭代出来的是Map.Entry对象,当然会出现ClassCastException!
Entry对象里是map结构的一种内部实现!
包含getKey,getValue等操作!结构类似List!
map在rehashing时会重新计算entryset!


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

相关推荐

    另一种遍历Map的方式

    今天,我们来讨论一种遍历Map的方式,即使用Map.Entry和Map.entrySet()。 Map.Entry是什么? ---------------- Map.Entry是一个接口,表示一个映射项,里面有Key和Value。它有两个方法:getKey()和getValue(),...

    java遍历大容量map的正确方法.pdf

    Iterator&lt;Map.Entry, String&gt;&gt; it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry, String&gt; entry = it.next(); System.out.println("key= " + entry.getKey() + " and value= " + entry....

    Map集合的四种遍历方式 .txt

    Iterator&lt;Map.Entry, String&gt;&gt; iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry, String&gt; entry = iterator.next(); System.out.println("key=" + entry.getKey() + " and value=...

    java循环Map java迭代Map

    Map a = new HashMap(); //方法一 Iterator it = a.entrySet().iterator(); while (it.hasNext()) { ...for(Map.Entry entry:a.entrySet()){ System.out.println(entry.getKey()+"="+entry.getValue()); }

    Java Map 遍历比较齐全的解析.docx

    总结,Java中遍历`Map`主要有四种方式,其中通过`Map.entrySet()`进行遍历通常被认为效率较高,尤其在`Map`容量较大的情况下。而在Java 8之后,我们可以利用Lambda表达式简化遍历操作。获取`Map`的长度直接调用`size...

    map遍历的四种方法

    Iterator&lt;Map.Entry, String&gt;&gt; it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry, String&gt; entry = it.next(); System.out.println("key=" + entry.getKey() + " and value=" + entry....

    java中Map集合的常用遍历方法及HashMap的应用实例

    1、遍历Map.entrySet():它的每一个元素都是Map.Entry对象,这个对象中, 放着的就是Map中的某一对key-value; 2、遍历Map.keySet():它是Map中key值的集合,我们可以通过遍历这个集合来 读取Map中的元素; 3、...

    JavaMap.rar_arraylist map_collection_java map_javamap_地图 java

    `, `Set&lt;Map.Entry, Integer&gt;&gt; entries = map.entrySet();` ArrayList是List接口的一个具体实现,它基于动态数组。ArrayList的特点是可以快速访问任意位置的元素,但插入和删除元素的效率相对较低,因为需要移动...

    map集合遍历的五种方法

    for (Map.Entry, Integer&gt; entry : map.entrySet()) { System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()); } ``` 这种方法能够保证遍历顺序与插入顺序一致,但不适用于...

    java集合遍历的几种方式总结及详细比较

    Java中提供了多种Map遍历方式,包括通过获取所有的key、通过Map.entrySet使用iterator遍历、通过Map.entrySet遍历等。 1. 通过获取所有的key遍历 ``` Set&lt;Integer&gt; set = map.keySet(); for (Integer in : map....

    Map,HashMap,TreeMap的使用

    import java.util.Map; import java.util.TreeMap; public class MapAppTest { public static void main(String[] args) { noOrder(); hasOrder(); likedHashMap(); } public static void noOrder() { ...

    android控件监听管理工具

    for(Map.Entry,Object&gt; entry:data.entrySet()){ View v = (View) entry.getKey(); v.setOnClickListener(null); } } private void registerLisntener(){ for(Map.Entry,Object&gt; entry:data.entrySet...

    金陵科技学院软件院大二上Java高级1212Map.docx

    以上就是关于Java中Map的使用,特别是HashMap和TreeMap的基本操作。理解这些概念和方法对于处理键值对的数据结构至关重要。通过实践这些示例,你可以更熟练地在Java项目中运用Map接口及其实现类。

    Java Map.Entry的使用方法解析

    for(Entry, Object&gt; entry : map.entrySet()){ System.out.println(entry.getKey()+"::::"+entry.getValue()); } } ``` 在上面的代码中,我们首先创建了一个HashMap对象,并将其初始化为一个空的Map集合。然后,...

    JAVA遍历Map所有元素.doc

    通过调用`Map.entrySet()`方法,我们可以获取到Map中所有键值对的`Set`集合。然后,我们可以迭代这个集合,每次迭代得到一个`Map.Entry`对象,该对象代表了一个键值对。以下是如何使用这种方式遍历Map: ```java ...

    map排序.txt

    List&lt;Map.Entry, V&gt;&gt; list = new ArrayList(map.entrySet()); Collections.sort(list, new Comparator&lt;Map.Entry, V&gt;&gt;() { @Override public int compare(Map.Entry, V&gt; o1, Map.Entry, V&gt; o2) { int compare =...

    java遍历Map对象的说有数据

    Iterator&lt;Map.Entry, V&gt;&gt; iterator = map.entrySet().iterator(); ``` 2. **创建迭代器**: ```java while (iterator.hasNext()) { Map.Entry, V&gt; entry = iterator.next(); // 处理键值对 } ``` 3. **...

    Java Map 按值排序

    我们可以使用map的entrySet()方法获取所有键值对,然后通过sorted()方法进行排序,最后用collect()方法将结果转换回Map: ```java Map, Integer&gt; map = new HashMap(); // 添加元素... Map, Integer&gt; sortedByValue...

    map转化为list

    在上述代码中,`map.entrySet()`返回一个包含Map所有键值对的迭代器,将其添加到ArrayList中即可得到一个包含Map.Entry对象的List。如果需要分别获取键和值,可以遍历Map并分别将键和值添加到两个独立的List中。 ...

    Java中如何遍历Map对象的4种方法_.docx

    for (Map.Entry, Integer&gt; entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } ``` 当遍历空 Map 时,需注意避免 `NullPointerException`,所以...

Global site tag (gtag.js) - Google Analytics