1. keySet()、values() 、entrySet()
- 获取 keys、values 、entrySet集合,keySet、values 是AbstractMap的变量,entrySet是hashMap 的变量,HashMap继承了AbstractMap,所以HashMap三个变量都能使用
- 源码很简单,变量为null,则new 对应的类型,否则直接返回
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
}
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
2. key、value、entrySet 的迭代器Iterator与分解迭代器Spliterator
- 可以回看01篇,有这几个类的源码解析,本章演示为主
import java.util.*;
import java.util.Map.Entry;
public class HashMapTest03 {
public static void main(String[] args) {
HashMap<String, Integer> hashMap = new HashMap<>();
for(int i = 1; i <= 10; i++) {
hashMap.put("我是" + i, i);
}
System.out.println("now hashMap: " + hashMap);
Set<String> keySet = hashMap.keySet();
System.out.println("hashMap.keySet(): " + keySet);
Iterator<String> keyIterator = keySet.iterator();
if(keyIterator.hasNext()) System.out.println("keyIterator.next(): " + keyIterator.next());
Spliterator<String> keySpliterator = keySet.spliterator();
keySpliterator.tryAdvance((e) -> System.out.println("keySpliterator.tryAdvance(): " + e));
Spliterator<String> keySpliterator01 = keySpliterator.trySplit();
System.out.println("keySpliterator.estimateSize(): " + keySpliterator.estimateSize());
System.out.println("keySpliterator01.estimateSize(): " + keySpliterator01.estimateSize());
Spliterator<String> keySpliterator02 = keySpliterator.trySplit();
Spliterator<String> keySpliterator03 = keySpliterator01.trySplit();
System.out.println("keySpliterator.estimateSize(): " + keySpliterator.estimateSize());
System.out.println("keySpliterator01.estimateSize(): " + keySpliterator01.estimateSize());
System.out.println("keySpliterator02.estimateSize(): " + keySpliterator02.estimateSize());
System.out.println("keySpliterator03.estimateSize(): " + keySpliterator03.estimateSize());
System.out.println("============== 我是一条警戒线 ============");
System.out.println("===== keySpliterator中的元素 ===== : ");
keySpliterator.forEachRemaining(e -> System.out.print(e + "\t"));
System.out.println();
System.out.println("===== keySpliterator01中的元素 ===== : ");
keySpliterator01.forEachRemaining(e -> System.out.print(e + "\t"));
System.out.println();
System.out.println("===== keySpliterator02中的元素 =====");
keySpliterator02.forEachRemaining(e -> System.out.print(e + "\t"));
System.out.println();
System.out.println("===== keySpliterator03中的元素 ===== : ");
Spliterator<String> keySpliterator04 = keySpliterator03.trySplit();
System.out.println("keySpliterator04.estimateSize(): " + keySpliterator04.estimateSize());
System.out.println("========= 元素太少,继续分割为 null ==========");
Spliterator<String> keySpliterator05 = keySpliterator04.trySplit();
System.out.println("keySpliterator05(): " + keySpliterator05);
System.out.println("========================");
Collection<Integer> values = hashMap.values();
System.out.println("hashMap.values(): " + values);
Iterator<Integer> valuesIterator = values.iterator();
System.out.println("valuesIterator: ");
valuesIterator.forEachRemaining((e) -> System.out.print(e + "\t"));
System.out.println();
Spliterator<Integer> valuesSpliterator = values.spliterator();
System.out.println("valuesSpliterator: ");
valuesSpliterator.forEachRemaining((e) -> System.out.print(e + "\t"));
System.out.println();
System.out.println("========================");
Set<Entry<String, Integer>> entrySet = hashMap.entrySet();
System.out.println("hashMap.entrySet(): " + entrySet);
Iterator<Entry<String, Integer>> entryIterator = entrySet.iterator();
System.out.println("entryIterator: ");
entryIterator.forEachRemaining(e -> System.out.print(e.getKey() + "=" + e.getValue() + "\t"));
System.out.println();
Spliterator<Entry<String, Integer>> entrySpliterator = entrySet.spliterator();
System.out.println("entrySpliterator: ");
entrySpliterator.forEachRemaining(e -> System.out.print(e.getKey() + " = " + e.getValue() + "\t"));
}
}
now hashMap: {我是6=6, 我是7=7, 我是8=8, 我是9=9, 我是2=2, 我是3=3, 我是4=4, 我是5=5, 我是10=10, 我是1=1}
hashMap.keySet(): [我是6, 我是7, 我是8, 我是9, 我是2, 我是3, 我是4, 我是5, 我是10, 我是1]
keyIterator.next(): 我是6
keySpliterator.tryAdvance(): 我是6
keySpliterator.estimateSize(): 5
keySpliterator01.estimateSize(): 5
keySpliterator.estimateSize(): 2
keySpliterator01.estimateSize(): 2
keySpliterator02.estimateSize(): 2
keySpliterator03.estimateSize(): 2
============== 我是一条警戒线 ============
===== keySpliterator中的元素 ===== :
我是10 我是1
===== keySpliterator01中的元素 ===== :
我是9 我是2 我是3
===== keySpliterator02中的元素 =====
我是4 我是5
===== keySpliterator03中的元素 ===== :
keySpliterator04.estimateSize(): 1
========= 元素太少,继续分割为 null ==========
keySpliterator05(): null
========================
hashMap.values(): [6, 7, 8, 9, 2, 3, 4, 5, 10, 1]
valuesIterator:
6 7 8 9 2 3 4 5 10 1
valuesSpliterator:
6 7 8 9 2 3 4 5 10 1
========================
hashMap.entrySet(): [我是6=6, 我是7=7, 我是8=8, 我是9=9, 我是2=2, 我是3=3, 我是4=4, 我是5=5, 我是10=10, 我是1=1]
entryIterator:
我是6=6 我是7=7 我是8=8 我是9=9 我是2=2 我是3=3 我是4=4 我是5=5 我是10=10 我是1=1
entrySpliterator:
我是6 = 6 我是7 = 7 我是8 = 8 我是9 = 9 我是2 = 2 我是3 = 3 我是4 = 4 我是5 = 5 我是10 = 10 我是1 = 1
Process finished with exit code 0
3. forEach
- 遍历HashMap的每一个元素,执行 action 动作
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key, e.value);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
import java.util.HashMap;
public class HashMapTest04 {
public static void main(String[] args) throws InterruptedException {
HashMap<String, Integer> hashMap = new HashMap<>();
for(int i = 1; i <= 10; i++) {
hashMap.put("我是" + i, i);
}
System.out.println("now hashmap: " + "\t");
hashMap.forEach((k, v) -> {
System.out.print(k + " = " + v + "\t");
});
System.out.println();
new Thread(() -> {
try {
Thread.sleep(300);
hashMap.put("我是11", 11);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
System.out.println("now hashmap: " + "\t");
try{
hashMap.forEach((k, v) -> {
try {
Thread.sleep(100);
System.out.print(k + " = " + v + "\t");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
} catch (Exception e) {
System.out.println();
e.printStackTrace();
}
System.out.println("======== 华丽分割线 =======");
Thread.sleep(1000);
System.out.println("now hashmap: " + "\t");
try{
hashMap.forEach((key, value) -> {
System.out.print(key + " = " + value + "\t");
hashMap.remove(key);
});
} catch (Exception e) {
System.out.println();
e.printStackTrace();
}
Thread.sleep(1000);
System.out.println("now hashmap: " + hashMap);
}
}
- 对 HashMap 的操作会导致 ConcurrentModificationException 报错,但是在源码也可以看到,是 action 全部执行完才报错。所以若需要在遍历时改变其结构,建议使用 iterator。