English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 基础教程

Java 流程控制

Java 数组

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Java 例外処理

Java 列表(List)

Java Queue(キュー)

Java Map集合

Java Set集合

Java 输入输出(I/O)

Java Reader/Writer

Java 他のトピック

Java ConcurrentHashMap

このチュートリアルでは、サンプルを使用してJava ConcurrentHashMapクラスとその操作を学びます。

JavaコレクションフレームワークのConcurrentHashMapクラスはスレッドセーフなマップを提供します。つまり、複数のスレッドが一度にこのマップにアクセスし、エントリの一致性に影響を与えずにアクセスできます。

它继承了ConcurrentMapインターフェース

创建一个ConcurrentHashMap

为了创建并发的哈希图,我们必须先导入java.util.concurrent.ConcurrentHashMapパッケージ。インポートした後、Javaで並行ハッシュマップを作成できます。

//ConcurrentHashMap具有容量8和负载因子0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);

在上面的代码中,我们创建了一个名为numbers的并发哈希映射。

ここでは、

  • Key - 用于关联map中每个元素(值)的唯一标识符

  • Value - map中与键相关联的元素

注意语句 new ConcurrentHashMap<>(8, 0.6)。在这里,第一个参数是capacity,第二个参数是loadFactor

  • capacity -该映射的容量为8。意味着,它可以存储8个条目。

  • loadFactor-此map的负载因子为0.6。这意味着,只要我们的哈希表填充了60%,条目就会移到新哈希表中,其大小是原始哈希表的两倍。

默认容量和负载因子

无需定义其容量和负载因子就可以创建并发哈希图。例如,

// 具有默认容量和负载因子的ConcurrentHashMap
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();

デフォルトで、

  • mapの容量は 16

  • 負荷因子は 0. になります。75

他のマッピングからConcurrentHashMapを作成

これは他のマッピングに含まれるすべての要素を持つ並行ハッシュマップを作成する方法です。

import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
    public static void main(String[] args) {
        // 偶数のHashMapを生成
        HashMap<String, Integer> evenNumbers = new HashMap<>();
        evenNumbers.put("Two", 2);
        evenNumbers.put("Four", 4);
        System.out.println("HashMap: " + evenNumbers);
        //他のマッピングから並行hashmapを作成
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
    }
}

出力結果

HashMap: {Four=4, Two=2}
ConcurrentHashMap: {Four=4, Two=2, Three=3}

ConcurrentHashMapのメソッド

ConcurrentHashMapクラスは、マッピングに対してさまざまな操作を実行できるようにするメソッドを提供しています。

要素をConcurrentHashMapに挿入

  • put() - 指定されたキー/値のマッピングをマッピングに挿入

  • putAll() - 指定されたマッピングのすべてのエントリをこのmapに挿入

  • putIfAbsent() - 指定されたキーがマッピングに存在しない場合、指定されたキー/値のマッピングをmapに挿入

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        //偶数のConcurrentHashMapを生成
        ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>();
        // 使用 put()
        evenNumbers.put("Two", 2);
        evenNumbers.put("Four", 4);
        // 使用 putIfAbsent()
        evenNumbers.putIfAbsent("Six", 6);
        System.out.println("偶数のConcurrentHashMap: " + evenNumbers);
        //Creating ConcurrentHashMap of numbers
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        // 使用 putAll()
        numbers.putAll(evenNumbers);
        System.out.println("ConcurrentHashMapの数字为: " + numbers);
    }
}

出力結果

偶数のConcurrentHashMap: {Six=6, Four=4, Two=2}
ConcurrentHashMapの数字为: {Six=6, One=1, Four=-4, Two=2}

访问ConcurrentHashMap元素

1.使用entrySet(),keySet()和values()

  • entrySet() - 返回一组所有键/值映射的集合

  • keySet() - 返回map所有键的集合

  • values() - 返回map所有值的集合

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // 使用 entrySet()
        System.out.println("Key/Value 映射: + numbers.entrySet());
        // 使用 keySet()
        System.out.println("Keys: ") + numbers.keySet());
        // 使用 values()
        System.out.println("Values: ") + numbers.values());
    }
}

出力結果

ConcurrentHashMap: {One=1, Two=2, Three=3}
Key/Value 映射:1, Two=2, Three=3]
Keys: [One, Two, Three]
Values:1, 2, 3]

2.使用get()和getOrDefault()

  • get() - 返回与指定键关联的值。如果找不到键,则返回null。

  • getOrDefault() - 返回与指定键关联的值。如果找不到键,则返回指定的默认值。

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // 使用 get()
        int value1 = numbers.get("Three");
        System.out.println("使用get(): " + value1);
        // 使用 getOrDefault()
        int value2 = numbers.getOrDefault("Five", 5);
        System.out.println("使用getOrDefault(): " + value2);
    }
}

出力結果

ConcurrentHashMap: {One=1, Two=2, Three=3}
使用get(): 3
使用getOrDefault(): 5

删除ConcurrentHashMap元素

  • remove(key) - 返回并从映射中删除与指定键关联的条目

  • remove(key, value) - 仅当指定键映射到指定值并返回布尔值时,才从映射中删除条目

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        //单参数删除方法
        int value = numbers.remove("Two");
        System.out.println("被删除的值: " + value);
        // 具有两个参数的删除方法
        boolean result = numbers.remove("Three", 3);
        System.out.println("エントリ {Three=3} 削除されました? " + result);
        System.out.println("更新後のConcurrentHashMap: " + numbers);
    }
}

出力結果

ConcurrentHashMap: {One=1, Two=2, Three=3}
削除された値: 2
エントリ {Three=3} 削除されました? True
更新後のConcurrentHashMap: {One=1}

ConcurrentHashMapのバッチ操作メソッド

ConcurrentHashMapクラスは、並行に安全に適用できる異なるバッチ操作メソッドを提供します。

1. forEach()メソッド

forEach()メソッドは、私たちのエントリを巡回し、指定された関数を実行します。

これは2つのパラメータを含んでいます。

  • parallelismThreshold -これは、マップで並行実行される要素の数を指定します。

  • transformer -これは、データが指定された関数に渡される前にデータを変換します。

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        //forEach()には渡された関数が含まれていません
        numbers.forEach(4, (k, v) -> System.out.println("key: " + k + " value: " + v));
        // forEach()に指定された関数を渡します
        System.out.print("Values are ");
        numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
    }
}

出力結果

ConcurrentHashMap: {One = 1, Two = 2, Three = 3}
key: One value: 1
key: Two value: 2
key: Three value: 3
Values are 1, 2, 3,

上記のプログラムでは、並行閾値を使用しました。4これは、マップに何個の要素があるかによって、4エントリが存在する場合、この操作は並行して実行されます。

forEach()メソッドのバリエーション

  • forEachEntry() - 指定された関数を実行するための各エントリ

  • forEachKey() - 指定された関数を実行するための各キー

  • forEachValue() - 指定された関数を実行するための各値

2. search()メソッド

search()メソッドは指定された関数に基づいてマップを検索し、一致するエントリを返します。

ここでは、指定された関数が何を検索するかを決定します。

それには、オプションのパラメータparallelThresholdがあります。並行実行の閾値は、マッピングにどれだけの要素があるかを指定します。

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // search()を使用して
        String key = numbers.search(4, (k, v) -> {return v == 3 ? k: null;});
        System.out.println("検索された値: " + key);
    }
}

出力結果

ConcurrentHashMap: {One=1, Two=2, Three=3}
検索される値: Three

search()メソッドのバリエーション

  • searchEntries() - 検索関数はキーに適用されます/値マッピング

  • searchKeys() - 検索関数はキーにのみ適用されます

  • searchValues() - 検索関数は値にのみ適用されます

3. reduce()メソッド

reduce()メソッドはマッピングの各エントリーを蓄積(集約)します。このメソッドは、すべてのエントリーが必要な場合(例えば、マッピングのすべての値を足す場合)に使用されます。

これは2つのパラメータを含んでいます。

  • parallelismThreshold -これは要素がどれだけ多くになるかによって、mapの操作が並行で実行されるかを指定します。

  • transformer - これはデータが指定された関数に渡される前にデータを変換する前にデータを変換します。

例えば、

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // search()を使用して
        int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
        System.out.println("すべての値の合計: " + sum);
    }
}

出力結果

ConcurrentHashMap: {One=1, Two=2, Three=3}
すべての値の合計: 6

上記のプログラムでは、以下の文に注意してください

numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);

ここでは、

  • 4 は並行処理の閾値です

  • (k, v) -> vは変換関数です。キー/値マッピングは値にのみ変換されます。

  • (v1, v2) -> v1+v2 サイズ計算関数です。すべての値を収集し、すべての値を足します。

reduce()メソッドのバリエーション

  • reduceEntries() - 指定のreducer関数を使用してすべてのエントリーを収集した結果を返します

  • reduceKeys() - 指定のreducer関数を使用してすべてのキーを収集した結果を返します

  • reduceValues() - 指定されたリデューサー関数を使用してすべての値を収集する結果を返すようにします。

ConcurrentHashMapとHashMapの違い

以下は、ConcurrentHashMapとHashMap間の違いがあります。

  • ConcurrentHashMapはスレッドセーフコレクションです。つまり、複数のスレッドが同時にアクセスおよび変更できます。

  • ConcurrentHashMapはforEach()、search()、reduce()などのバッチ操作に使用されるメソッドを提供します。

なぜConcurrentHashMapを選んだのでしょうか?

  • ConcurrentHashMap クラスは、複数のスレッドが並行して変更操作を行うことを許可します。

  • デフォルトでは、並行ハッシュマップは以下のように分割されます。16セクションこれが、以下の理由で許可されています。16個のスレッドが同時にマッピングを変更する理由です。しかし、一度に任意の数のスレッドがアクセスできます。

  • 指定されたキーが既に存在する場合、putIfAbsent()メソッドはマッピング内のエントリーを上書きしません。