文章目录
1.创建HashMap对象
HashMap<String, String> map = new HashMap<String, String>();
1.线程不安全的哈希表
2.键值对可以存储null,key不可以重复,value可以重复,重复时覆盖oldVlue
3.取出的数据没有顺序。
2.添加键值对
put方法添加元素时,如果key已经存在,则更新value的值。
存储的key和value都可以为null。
HashMap<String, String> map = new HashMap<String, String>();
map.put("北京", "key存在的oldValue");
map.put("上海", null);
map.put("广州", "oldValue");
map.put(null, "null的oldValue");
map.putIfAbsent(null, "null的newValue");
map.putIfAbsent("杭州", "key不存在的value");
map.putIfAbsent("北京", "key存在的newValue");
map.putIfAbsent("上海", "null值被覆盖");
map.replace("广州", "replaceValue");
map.replace("武汉", "key不存在的value");
replace(key,value);
当key存在时,调用replace方法,会替换value。当key不存在,返回null
@Override
public V replace(K key, V value) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) != null) {
V oldValue = e.value;
e.value = value;
afterNodeAccess(e);
return oldValue;
}
return null;
}
putIfAbsent()当key存在,value有值时不会覆盖value值。
- 首先判断key是否存在,不存在和put的作用一致,更新value。
- 如果存在判断value是否为null,value为null,则更新value值。
- value不为null,则不覆盖,返回原来的value。(null和不存在是两个概念)
put方法源码:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
put方法return的参数中第三个为false。
putIfAbsent源码:
@Override
public V putIfAbsent(K key, V value) {
return putVal(hash(key), key, value, true, true);
}
注意这里return的参数中第三个是true。这个参数的定义有注释说明:
@param onlyIfAbsent if true, don’t change existing value。如果为true,不改变已经存在的value值。
进入到putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict):
/**
* Implements Map.put and related methods
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
//如果传入的参数onlyIfAbsent为true或者oldvalue是null,更新value。
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
3.获取元素
1.get(key)获取HashMap的value
String valueStr=map.get("北京");
2.遍历map.keySet获取HashMap的key
1.ForEach迭代key
for (String key : map.keySet()) {
System.out.println("key= "+ key + ":" + map.get(key));
}
2.Iterator遍历key
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
System.out.println(key + ":" + map.get(key));
}
Console:
null:null的oldValue
上海:null值被覆盖
广州:replaceValue
杭州:key不存在的value
北京:key存在的oldValue
3.遍历map.value获取HashMap的value
1.ForEach迭代value
for (String v : map.values()) {
System.out.println("value= " + v);
}
2.Iterator遍历value
Iterator<String> iterator1 = map.values().iterator();
while (iterator1.hasNext()) {
String value = (String) iterator1.next();
System.out.println("value:" + value);
}
Console:
value= null的oldValue
value= null值被覆盖
value= replaceValue
value= key不存在的value
value= key存在的oldValue
4.遍历Map.entry获取HashMap的key,value
1.ForEach迭代遍历
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
2.Iterator遍历
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, String> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
Console:
null:null的oldValue //key为null,但是是存在的,所以未覆盖
上海:null值被覆盖 //key存在,且value为null,更新oldValue
广州:replaceValue
杭州:key不存在的value //key不存在,更新value
北京:key存在的oldValue //key存在,value不为null,则不更新value
5.通过JDK1.8 Lambda表达式遍历
map.forEach((k, v) -> {
System.out.println("key:" + k + "\tvalue:" + v);
});
Cosole:
key:null value:null的oldValue
key:上海 value:null值被覆盖
key:广州 value:replaceValue
key:杭州 value:key不存在的value
key:北京 value:key存在的oldValue
通过输出可以看到输出的数据与输入的数据顺序不一致,证明hashmap是无序的,实际上hash进行离散,得到的数据就不会按照大小进行排序。有序的map可以使用treeMap等。
4.判断key或value是否存在
// 判断map是否含有key
boolean ifContainKey = map.containsKey("杭州");
System.out.println("ifContainkey:"+ifContainKey);
// 判断map是否含有value
boolean ifContainValue = map.containsValue(null);
System.out.println("ifContainValue:"+ifContainValue);
Console:
ifContainkey:true
ifContainValue:true
5.删除元素
remove(key);存在key返回对应的value,否则返回null
remove(key,value);存在key-value,返回true。否则返回false
String value = map.remove("上海");
System.out.println(value);
String value2 = map.remove("das");
System.out.println(value2);
boolean flag = map.remove("北京", "key存在的oldValue");
System.out.println(flag);
boolean flag2 = map.remove("武汉", "key存在的oldValue");
System.out.println(flag2);
Console:
null值被覆盖
null
true
false