eg:
HashMap<Integer,String> hashMap = new HashMap<>();
hashMap.put(1,"QGS");
System.out.println("QGS"+hashCode());
Toast.makeText(this,hashMap.get(1)+" "+hashCode(),Toast.LENGTH_SHORT).show();
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的,
HashMap的实例有两个参数:"初始容量"和"加载因子",容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度.当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
默认加载因子是 0.75,(static final float DEFAULT_LOAD_FACTOR = 0.75f;)
HashMap是以<key,value>键值对进行存储的
如果HashMap是以键值对进行存储的,那么它使用的数据结构又是什么?
(根据ArrayList和LinkedList)
ArrayList 数组 特性:查找快
LinkedList 链表 特性:增删快(不是单向链表,而是双向链表)
HashMap的数组类型用Node表示(Node<key,value>[])
++size记录数组自己使用的大小
threshold : 键值对的数量*0.75(默认加载因子)
注 : 数组大小size不能大于totalsize
为什么不用链表表示?
当大小过长是,运行速度或效率会变低.Jdk1.8时,如果链表结构长度大于某个值,就将其结构改成红黑树(红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组).
Node节点存在哪里?
利用key值计算Node.在Object类中找hashCode,hashCode返回值为int类型,拿到key.hashCode(存在数组的位置),hash(key)得到具体值.
一个int是几位数:
四个字节,一个字节为8为数,总计32位数.
HashMap的API
void clear()
Object clone()boolean containsKey(Object key)boolean containsValue(Object value)
Set<Entry<K, V>> entrySet()
V get(Object key)boolean isEmpty()
Set<K> keySet()
V put(K key, V value)void putAll(Map<? extends K, ? extends V> map)
V remove(Object key)int size()
Collection<V> values()
HashMap与Map的关系:
HashMap源码解析:
// 默认的初始容量是16,必须是2的幂。
static final int DEFAULT_INITIAL_CAPACITY = 16;
// 最大容量(必须是2的幂且小于2的30次方,传入容量过大将被这个值替换)static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认加载因子static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 存储数据的Entry数组,长度是2的幂。
// HashMap是采用拉链法实现的,每一个Entry本质上是一个单向链表transient Entry[] table;
// HashMap的大小,它是HashMap保存的键值对的数量transient int size;
// HashMap的阈值,用于判断是否需要调整HashMap的容量(threshold = 容量*加载因子)int threshold;
// 加载因子实际大小final float loadFactor;
// HashMap被改变的次数 transient volatile int modCount;
HashMap的构造函数:
1 // 默认构造函数。 2 public HashMap() { 3 // 设置“加载因子” 4 this.loadFactor = DEFAULT_LOAD_FACTOR; 5 // 设置“HashMap阈值”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。 6 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 7 // 创建Entry数组,用来保存数据 8 table = new Entry[DEFAULT_INITIAL_CAPACITY]; 9 init();10 }11 12 // 指定“容量大小”和“加载因子”的构造函数13 public HashMap(int initialCapacity, float loadFactor) {14 if (initialCapacity < 0)15 throw new IllegalArgumentException("Illegal initial capacity: " +16 initialCapacity);17 // HashMap的最大容量只能是MAXIMUM_CAPACITY18 if (initialCapacity > MAXIMUM_CAPACITY)19 initialCapacity = MAXIMUM_CAPACITY;20 if (loadFactor <= 0 || Float.isNaN(loadFactor))21 throw new IllegalArgumentException("Illegal load factor: " +22 loadFactor);23 24 // Find a power of 2 >= initialCapacity25 int capacity = 1;26 while (capacity < initialCapacity)27 capacity <<= 1;28 29 // 设置“加载因子”30 this.loadFactor = loadFactor;31 // 设置“HashMap阈值”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。32 threshold = (int)(capacity * loadFactor);33 // 创建Entry数组,用来保存数据34 table = new Entry[capacity];35 init();36 }37 38 // 指定“容量大小”的构造函数39 public HashMap(int initialCapacity) {40 this(initialCapacity, DEFAULT_LOAD_FACTOR);41 }42 43 // 包含“子Map”的构造函数44 public HashMap(Map<? extends K, ? extends V> m) {45 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,46 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);47 // 将m中的全部元素逐个添加到HashMap中48 putAllForCreate(m);49 }
HashMap的主要对外接口
1. clear()
clear()的作用是清空HaspMap.他是通过将所有的元素设为null来实现.
1 public void clear() {2 modCount++;3 Entry[] tab = table;4 for (int i = 0; i < tab.length; i++)5 tab[i] = null;6 size = 0;7 }
2.containsKey()
containsKey()的作用是判断HashMap是否包含key.
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
3.containsValue()
containsValue()的作用是判断HAshMap是否包含值为"value"的元素
1 public boolean containsValue(Object value) { 2 // 若“value为null”,则调用containsNullValue()查找 3 if (value == null) 4 return containsNullValue(); 5 6 // 若“value不为null”,则查找HashMap中是否有值为value的节点。 7 Entry[] tab = table; 8 for (int i = 0; i < tab.length ; i++) 9 for (Entry e = tab[i] ; e != null ; e = e.next)10 if (value.equals(e.value))11 return true;12 return false;13 }
4. entrySet(),value(),keySet()
1 // 返回“HashMap的Entry集合” 2 public Set<Map.Entry<K,V>> entrySet() { 3 return entrySet0(); 4 } 5 6 // 返回“HashMap的Entry集合”,它实际是返回一个EntrySet对象 7 private Set<Map.Entry<K,V>> entrySet0() { 8 Set<Map.Entry<K,V>> es = entrySet; 9 return es != null ? es : (entrySet = new EntrySet());10 }11 12 // EntrySet对应的集合13 // EntrySet继承于AbstractSet,说明该集合中没有重复的EntrySet。14 private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {15 public Iterator<Map.Entry<K,V>> iterator() {16 return newEntryIterator();17 }18 public boolean contains(Object o) {19 if (!(o instanceof Map.Entry))20 return false;21 Map.Entry<K,V> e = (Map.Entry<K,V>) o;22 Entry<K,V> candidate = getEntry(e.getKey());23 return candidate != null && candidate.equals(e);24 }25 public boolean remove(Object o) {26 return removeMapping(o) != null;27 }28 public int size() {29 return size;30 }31 public void clear() {32 HashMap.this.clear();33 }34 }
5.get()
get()的作用是获取key对应的valuezhi
1 public V get(Object key) { 2 if (key == null) 3 return getForNullKey(); 4 // 获取key的hash值 5 int hash = hash(key.hashCode()); 6 // 在“该hash值对应的链表”上查找“键值等于key”的元素 7 for (Entry<K,V> e = table[indexFor(hash, table.length)]; 8 e != null; 9 e = e.next) {10 Object k;11 if (e.hash == hash && ((k = e.key) == key || key.equals(k)))12 return e.value;13 }14 return null;15 }
6.put()
put()的作用是多外提供接口,让HashMap对象可以通过put()将"key-value"存放到HashMap中
7.putAll()
putAll()的作用是将"m"的全部元素都添加到HashMap中
1 public void putAll(Map<? extends K, ? extends V> m) { 2 // 有效性判断 3 int numKeysToBeAdded = m.size(); 4 if (numKeysToBeAdded == 0) 5 return; 6 7 // 计算容量是否足够, 8 // 若“当前实际容量 < 需要的容量”,则将容量x2。 9 if (numKeysToBeAdded > threshold) {10 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);11 if (targetCapacity > MAXIMUM_CAPACITY)12 targetCapacity = MAXIMUM_CAPACITY;13 int newCapacity = table.length;14 while (newCapacity < targetCapacity)15 newCapacity <<= 1;16 if (newCapacity > table.length)17 resize(newCapacity);18 }19 20 // 通过迭代器,将“m”中的元素逐个添加到HashMap中。21 for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {22 Map.Entry<? extends K, ? extends V> e = i.next();23 put(e.getKey(), e.getValue());24 }25 }
8.remove()
remove()的作用是删除键wei"key"的元素
1 public V remove(Object key) { 2 Entry<K,V> e = removeEntryForKey(key); 3 return (e == null ? null : e.value); 4 } 5 6 7 // 删除“键为key”的元素 8 final Entry<K,V> removeEntryForKey(Object key) { 9 // 获取哈希值。若key为null,则哈希值为0;否则调用hash()进行计算10 int hash = (key == null) ? 0 : hash(key.hashCode());11 int i = indexFor(hash, table.length);12 Entry<K,V> prev = table[i];13 Entry<K,V> e = prev;14 15 // 删除链表中“键为key”的元素16 // 本质是“删除单向链表中的节点”17 while (e != null) {18 Entry<K,V> next = e.next;19 Object k;20 if (e.hash == hash &&21 ((k = e.key) == key || (key != null && key.equals(k)))) {22 modCount++;23 size--;24 if (prev == e)25 table[i] = next;26 else27 prev.next = next;28 e.recordRemoval(this);29 return e;30 }31 prev = e;32 e = next;33 }34 35 return e;36 }
HashMap继承于AbstractMap,实现Map、Cloneable、java.io.Serializable接口.
Cloneable和Serializable都是一个接口
cloneHashMap对象并返回
1 // 克隆一个HashMap,并返回Object对象 2 public Object clone() { 3 HashMap<K,V> result = null; 4 try { 5 result = (HashMap<K,V>)super.clone(); 6 } catch (CloneNotSupportedException e) { 7 // assert false; 8 } 9 result.table = new Entry[table.length];10 result.entrySet = null;11 result.modCount = 0;12 result.size = 0;13 result.init();14 // 调用putAllForCreate()将全部元素添加到HashMap中15 result.putAllForCreate(this);16 17 return result;18 }
Serializable分别实现了串行读取/写入功能
遍历HashMap的键值对
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型Integer integ = null;
Iterator iter = map.entrySet().iterator();while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
// 获取key key = (String)entry.getKey();
// 获取value integ = (Integer)entry.getValue();
}
遍历HashMap的键
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();while (iter.hasNext()) {
// 获取key key = (String)iter.next();
// 根据key,获取value integ = (Integer)map.get(key);
}
遍历HashMap的值
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();while (iter.hasNext()) {
value = (Integer)iter.next();
}
网友评论