HashMapの初期サイズを設定する方法

1. Alibaba コード仕様の要件

ここに画像の説明を挿入します

2. Alibabaプラグインを使用してスキャンする場合

ここに画像の説明を挿入します
ここに画像の説明を挿入しますここに画像の説明を挿入します
ここに画像の説明を挿入します

3. ソースコード

3.1 初期化でサイズが設定されない場合

Map<Integer, BigDecimal> staffDidiMap = new HashMap<>();
ここに画像の説明を挿入します
ここに画像の説明を挿入します

3.2 サイズを初期化する場合

Map<Integer, BigDecimal> staffDidiMap = new HashMap<>(16);
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します

@Test
	public void caffineTest() {
    
    
		System.out.println(1 << 30);
	}
result: 1073741824

this.threshold = tableSizeFor(initialCapacity);
ここに画像の説明を挿入します

@Test
	public void caffineTest() {
    
    
		int cap = 16;
		int n = cap - 1;
		n |= n >>> 1;
		n |= n >>> 2;
		n |= n >>> 4;
		n |= n >>> 8;
		n |= n >>> 16;
		int result = (n < 0) ? 1 : (n >= 1073741824) ? 1073741824 : n + 1;
		System.out.println(result);
	}
result: 16

//TODOのソースコード部分を改善する必要がある

4. テスト

@SpringBootTest
public class CaffineTest {
    
    

	@Test
	public void caffineTest() throws InterruptedException {
    
    
		test1();
		test2();
		test3();
		test4();
		test5();
	}

	void test1() throws InterruptedException {
    
    
		int aHundredMillion = 10000000;
		Map<Integer, Integer> map = new HashMap<>();
		long s1 = System.currentTimeMillis();
		for (int i = 0; i < aHundredMillion; i++) {
    
    
			map.put(i, i);
		}
		long s2 = System.currentTimeMillis();
		System.out.println("未初始化容量,耗时 : " + (s2 - s1));
		map.clear();
		Thread.sleep(5000);
	}

	void test2() throws InterruptedException {
    
    
		int aHundredMillion = 10000000;
		Map<Integer, Integer> map1 = new HashMap<>(aHundredMillion / 2);
		long s5 = System.currentTimeMillis();
		for (int i = 0; i < aHundredMillion; i++) {
    
    
			map1.put(i, i);
		}
		long s6 = System.currentTimeMillis();
		System.out.println("初始化容量5000000,耗时 : " + (s6 - s5));
		map1.clear();
		Thread.sleep(5000);
	}

	void test3() throws InterruptedException {
    
    
		int aHundredMillion = 10000000;
		Map<Integer, Integer> map2 = new HashMap<>(aHundredMillion);
		long s3 = System.currentTimeMillis();
		for (int i = 0; i < aHundredMillion; i++) {
    
    
			map2.put(i, i);
		}
		long s4 = System.currentTimeMillis();
		System.out.println("初始化容量为10000000,耗时 : " + (s4 - s3));
		map2.clear();
		Thread.sleep(5000);
	}

	void test4() throws InterruptedException {
    
    
		int aHundredMillion = 10000000;
		// 按照阿里巴巴规范   initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认 为 0.75
		int initial = (int) (aHundredMillion / 0.75F + 1F);
		Map<Integer, Integer> map3 = new HashMap<>(initial);
		long s7 = System.currentTimeMillis();
		for (int i = 0; i < aHundredMillion; i++) {
    
    
			map3.put(i, i);
		}
		long s8 = System.currentTimeMillis();
		System.out.println("初始化容量为" + initial + "耗时" + (s8 - s7));
		map3.clear();
		Thread.sleep(5000);
	}

	void test5() throws InterruptedException {
    
    
		int aHundredMillion = 10000000;
		// 初始化16
		Map<Integer, Integer> map4 = new HashMap<>(16);
		long s9 = System.currentTimeMillis();
		for (int i = 0; i < aHundredMillion; i++) {
    
    
			map4.put(i, i);
		}
		long s10 = System.currentTimeMillis();
		System.out.println("初始化容量为" + 16 + "耗时" + (s10 - s9));
		map4.clear();
		Thread.sleep(5000);
	}
}

結果:
ここに画像の説明を挿入します
毎回、1,000 万個のデータがマップに挿入されます。
方法 1: 初期化されず、
時間がかかります 3995。方法 2: 500 万に初期化され、
時間がかかります 2345。方法 3: 1000 万に初期化され
、時間がかかります 261。方法 4: Ali の仕様に従って初期化され、時間がかかります
192。方法 5:初期化 16、時間がかかります 182。


多くのテストを行った結果、最悪のパフォーマンスは初期化されていないものであり、最も効率的で安定したパフォーマンスは Alibaba の仕様に従っており、次にinitialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认 为 0.7516、最後に割り当てられたサイズに従っていると結論付けることができます。

ここに画像の説明を挿入します
ここに画像の説明を挿入しますここに画像の説明を挿入します
ここに画像の説明を挿入します

付録

1. Alibaba は、HashMap の初期化時に容量を指定する必要があることを推奨しているのはなぜですか?

おすすめ

転載: blog.csdn.net/Blue_Pepsi_Cola/article/details/131810014