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

HashMap的keyset与value的对应

    博客分类:
  • java
阅读更多

 

在改一个bug的时刻,把原来的老大写个map.values()改成了map.keyset()。前面通过循环得到一个prepared sql,后面再把对象的数据放入到PreparedStatement中。

下班后,感觉不是很对劲。Map怎么确保得values()和keyset()的顺序是一样的呢?

 

原来用map都是先取key然后得到value。由于在map上封装了,不能直接取得entryset,只有keyset和values(),getValue(key)。那values()和keyset()中的元素顺序是否对应呢?

 

首先,写个test,看看顺序是不是一致的:

 

public class HashMapOrder {
	
	public static void main(String[] args) {
		HashMap map = new HashMap();
		
//		map.put(1, "E");
//		map.put(2, "D");
//		map.put(3, "C");
//		map.put(4, "B");
//		map.put(5, "A");

		map.put(12, "E");
		map.put(2, "D");
		map.put(31, "C");
		map.put(4, "B");
		map.put(56, "A");
		
		for(Object key:map.keySet())
			System.out.print(key + ", ");
		
		System.out.println();
		
		for(Object value:map.values())
			System.out.print(value+", ");
		
	}

}
 

 

发现没问题,第一个注释了的代码数据是有序的。输出

1, 2, 3, 4, 5, 

E, D, C, B, A, 

第二个无序数据输出:

2, 4, 56, 12, 31, 

D, B, A, E, C, 

也正常!

 

没问题,查看代码理解如下:

HashMap中存储数据的对象本质是有一个数组!使用Entry[]保存keyvalue对,  然后如果是一样的index会以链表的形式加在entry的next上。

keyset()和value()返回的都是匿名内部类对象,使用iterator迭代器对table的一个迭代!

 

首先,说明entryset()的来龙气脉,后面values()和keyset()都会用到这个方法。

java.util.HashMap.entrySet()

 

    public Set<Map.Entry<K,V>> entrySet() {
        return entrySet0();
    }

    private Set<Map.Entry<K,V>> entrySet0() {
        Set<Map.Entry<K,V>> es = entrySet;
        return es != null ? es : (entrySet = new EntrySet());
    }
    // 内部类,没有static!
    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public Iterator<Map.Entry<K,V>> iterator() {
            return newEntryIterator(); //!!!
        }
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<K,V> e = (Map.Entry<K,V>) o;
            Entry<K,V> 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();
        }
    }
 

java.util.HashMap.getEntry(Object)

 

    final Entry<K,V> getEntry(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
 

 

    Iterator<Map.Entry<K,V>> newEntryIterator()   {
        return new EntryIterator();
    }

    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }

java.util.HashMap.HashIterator.nextEntry()
    。。。。。。
 

再来看keyset()和value()方法,通过iterator迭代entrySet,即获取Entry[]数组中的元素,然后分别取对应的key和value:

java.util.AbstractMap.keySet()

 

    public Set<K> keySet() {
        if (keySet == null) {
            keySet = new AbstractSet<K>() {
                public Iterator<K> iterator() {
                    return new Iterator<K>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public K next() {
                            return i.next().getKey(); //!!!
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
        }
        return keySet;
    }

    public Collection<V> values() {
        if (values == null) {
            values = new AbstractCollection<V>() {
                public Iterator<V> iterator() {
                    return new Iterator<V>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public V next() {
                            return i.next().getValue();//!!!
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object v) {
                    return AbstractMap.this.containsValue(v);
                }
            };
        }
        return values;
    }
 

 

 

分享到:
评论

相关推荐

    如何得到hashmap的索引

    然而,“索引”这一概念通常与数组或列表关联,而在`HashMap`中,我们通过键(Key)来访问其对应的值(Value)。因此,理解如何获取`HashMap`中的“索引”,实际上是指如何有效地遍历`HashMap`以及获取其键值对。 #...

    hashmap使用实例

    6. **遍历HashMap**:有两种方式遍历HashMap,一是通过`entrySet()`获取键值对的迭代器,二是通过`keySet()`获取键的迭代器再获取对应的值。 ```java for (Map.Entry, String&gt; entry : map.entrySet()) { System....

    hashMap具体详解

    9. 其他特性:HashMap还提供了containsKey()、containsValue()、clear()等方法,以及keySet()、values()和entrySet()这三个集合视图,分别用于获取键集合、值集合和键值对集合,方便进行遍历和操作。 总的来说,...

    Java-HashMap.rar_hashmap_java hashmap

    6. **迭代器遍历**:尽管遍历顺序不确定,但`HashMap`提供`keySet()`, `values()`和`entrySet()`方法来遍历键、值和键值对。 下面是一些关于`HashMap`的基本操作: - **插入键值对**:使用`put()`方法插入键值对,...

    浅谈Java中HashMap类的使用.pdf

    HashMap 是 Java 语言中最常用的集合类之一,它实现了 Map 接口,提供了 put、get、keySet 等常用方法来存储和检索数据。本文将详细介绍 HashMap 类的使用,包括其常用方法、特点和应用场景。 一、HashMap 的基本...

    HashMap遍历

    与`keySet()`不同的是,`entrySet()`允许我们同时访问键和值,而无需额外的`get()`操作。这在性能上通常更优,尤其是在频繁访问键值对的场景下。下面是一个使用`entrySet()`遍历`HashMap`的示例: ```java Map, ...

    Java HashMap的三种遍历方法及优缺点含示例

    keySet()方法提供了一个包含所有键的Set集合,通过遍历这个Set集合,我们可以获取到HashMap中的每一个键,然后再通过键去get()对应的值。这种方式比较适合只需要使用键的场景。 **优点**:如果只需要键,这种方法...

    Java 实例 - HashMap遍历源代码-详细教程.zip

    - **迭代器方式**:HashMap提供了`keySet()`、`values()`和`entrySet()`方法,返回相应的Set视图。可以使用迭代器遍历这些集合,分别获取键集、值集和键值对集。 - **foreach循环**:Java 5引入了增强的for循环...

    JAVA中HashMap的用法.docx

    当查找某个键对应的值时,HashMap首先计算键的哈希码,然后在相应的桶中搜索,如果找到多个键值对,就遍历链表直到找到匹配的键。 HashMap的特点: 1. 不保证元素的顺序,插入顺序和迭代顺序可能会不同,因为哈希表...

    Hash Map for geeks_hashmap_Geeks_源码

    - **初始容量与加载因子**:HashMap有初始容量和加载因子两个参数,当元素数量达到容量*加载因子时,HashMap会自动扩容。 - **null键和值**:HashMap允许一个null键和任意数量的null值。 **HashMap的方法:** - `...

    java提高篇(二三)-----HashMap.pdf

    HashMap是基于哈希表实现的,通过哈希函数计算键的存储位置,以此来快速存取对应的值。以下是HashMap的一些关键知识点: 1. **HashMap的定义与实现**: HashMap实现了Map接口,继承自AbstractMap类。Map接口定义了...

    HashMap底层实现原理共6页.pdf.zip

    HashMap提供了两种遍历方式:通过迭代器(Iterator)按照插入顺序遍历,或者通过键集(keySet)、值集(values)或键值对集(entrySet)按照哈希顺序遍历。由于HashMap的无序性,不保证插入顺序与遍历顺序一致。 8....

    java遍历HashMap简单的方法

    HashMap的`keySet()`方法返回所有键的集合,可以通过遍历这个集合来访问每个键,然后使用`get()`方法获取对应的值。这种方式也是比较常见的遍历方法,如下所示: ```java HashMap, String&gt; map = new HashMap(); //...

    java HashMap详解及实例代码

    Java中的HashMap是基于哈希表实现的Map接口的一个实现,它允许将键映射到相应的值。HashMap在Java集合框架中扮演着重要角色,提供快速的查找、插入和删除操作,平均时间复杂度为O(1)。下面将详细介绍HashMap的特点、...

    详解JAVA里面获取map的key和value的方法

    Map的keySet()方法可以获取Map中的所有Key,然后根据Key获取对应的Value。下面是一个简单的示例代码: ```java for (String key : map.keySet()) { String value = map.get(key); System.out.println(key + " " + ...

    Java集合之HashMap用法详解

    * containsValue操作:用于判断HashMap中是否包含指定的值,例如`map.containsValue("Barcelona")`。 * remove操作:用于删除HashMap中指定的键值对,例如`map.remove(5)`。 * clear操作:用于清空HashMap中的所有...

    DoubleAccessMap:可以通过使用值访问KeySet的HashMap

    在标准的HashMap中,查找键对应的值是常见的操作,但查找具有特定值的所有键则不太常见,而DoubleAccessMap就是为了解决这个问题而设计的。 在Java中,HashMap是一个存储键值对的数据结构,其中每个键都是唯一的,...

    使用多种方式实现遍历HashMap的方法

    由于Set接口实现了Iterable接口,我们可以使用for-each循环来遍历KeySet,然后通过map.get(key)获取对应的值。这种方式可以分别获取键和值,但无法同时获取键值对。 2. **方式二:使用Values方法** Values方法返回...

Global site tag (gtag.js) - Google Analytics