目錄
前言
- 介紹HashMap遍歷的幾種方式
- 介紹HashMap迭代刪除的幾種方式
HashMap遍歷的幾種方式
一、迭代器遍歷
迭代EntrySet
@Test
public void testEntrySet() {
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println(entry.getKey() + " --> " + entry.getValue());
}
}
迭代KeySet
@Test
public void testKeySet() {
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
System.out.println(key + " --> " + map.get(key));
}
}
二、ForEach遍歷
遍歷EntrySet
@Test
public void testForEachEntrySet() {
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " --> " + entry.getValue());
}
}
遍歷KeySet
@Test
public void testForEachKeySet() {
for (String key : map.keySet()) {
System.out.println(key + " --> " + map.get(key));
}
}
三、Lambda遍歷
@Test
public void testLambda() {
map.forEach((key, value) -> {
System.out.println(key + " --> " + value);
});
}
四、StreamAPI遍歷
@Test
public void testStream() {
map.entrySet().stream().forEach(entry -> {
System.out.println(entry.getKey() + " --> " + entry.getValue());
});
}
@Test
public void testParallelStream() {
map.entrySet().parallelStream().forEach(entry -> {
System.out.println(entry.getKey() + " --> " + entry.getValue());
});
}
各種遍歷方式的性能比較
引入jmh性能測試框架
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.23</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
編寫測試
@BenchmarkMode(Mode.Throughput) //測試類型 吞吐量
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) //預熱2輪,每次1秒
@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) //測試5輪,每次3s
@Fork(1) //fork 1個線程
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread) //每個測試線程1個實例
public class HashMapBenchmark {
static Map<String, String> map = new HashMap<String,String>() {
{
put("author", "天喬巴夏");
put("title", "HashMap的各種遍歷方式");
put("url", "www.hyhwky.com");
}
};
public static void main(String[] args) throws RunnerException {
System.out.println(System.getProperties());
Options opt = new OptionsBuilder()
.include(HashMapBenchmark.class.getSimpleName())
.output(System.getProperty("user.dir") + "\\HashMapBenchmark.log")
.build();
new Runner(opt).run();
}
@Benchmark
public void testEntrySet() {
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println(entry.getKey() + " --> " + entry.getValue());
}
}
@Benchmark
public void testKeySet() {
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
System.out.println(key + " --> " + map.get(key));
}
}
@Benchmark
public void testForEachEntrySet() {
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " --> " + entry.getValue());
}
}
@Benchmark
public void testForEachKeySet() {
for (String key : map.keySet()) {
System.out.println(key + " --> " + map.get(key));
}
}
@Benchmark
public void testLambda() {
map.forEach((key, value) -> {
System.out.println(key + " --> " + value);
});
}
@Benchmark
public void testStream(){
map.entrySet().stream().forEach(entry ->{
System.out.println(entry.getKey() + " --> " + entry.getValue());
});
}
@Benchmark
public void testParallelStream(){
map.entrySet().parallelStream().forEach(entry ->{
System.out.println(entry.getKey() + " --> " + entry.getValue());
});
}
}
測試結果如下
Benchmark Mode Cnt Score Error Units
HashMapBenchmark.testEntrySet thrpt 5 6.929 ± 1.042 ops/ms
HashMapBenchmark.testForEachEntrySet thrpt 5 7.025 ± 0.627 ops/ms
HashMapBenchmark.testForEachKeySet thrpt 5 7.024 ± 0.481 ops/ms
HashMapBenchmark.testKeySet thrpt 5 6.769 ± 1.231 ops/ms
HashMapBenchmark.testLambda thrpt 5 7.056 ± 0.300 ops/ms
HashMapBenchmark.testParallelStream thrpt 5 5.784 ± 0.216 ops/ms
HashMapBenchmark.testStream thrpt 5 6.826 ± 0.578 ops/ms
- Score表示平均執行時間,Error表示誤差。
- 測試結果和本機性能有一定關系,只需關注相對結果即可。
- 可以看出除了Parallel的遍歷方法,其他方法在性能上的差別不大。
HashMap迭代刪除的幾種方式
迭代器刪除
@Test
public void testRemoveIterator() {
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next().getKey();
if ("title".equals(key)) {
iterator.remove();
}
}
System.out.println(map);
}
Lambda的removeIf
@Test
public void testRemoveLambda() {
map.keySet().removeIf("title"::equals);
System.out.println(map);
}
StreamAPI的filter
@Test
public void testRemoveStream() {
map.entrySet()
.stream()
.filter(m -> !"title".equals(m.getKey()))
.forEach(entry -> {
System.out.println(entry.getKey() + " --> " + entry.getValue());
});
}
參考文章
- Java中文社群:你一般是怎么遍歷HashMap的?