Java ConcurrentHashMap
Java ConcurrentHashMap
このチュートリアルでは、例を使用して Java ConcurrentHashMap クラスとその操作について学習します。
ConcurrentHashMap
Java コレクション フレームワークのクラスは、スレッド セーフなマップを提供します。つまり、マップ内のエントリの一貫性に影響を与えることなく、複数のスレッドが一度にマップにアクセスできます。
ConcurrentMap インターフェースを実装します。
ConcurrentHashMap を作成する
並行ハッシュマップを作成するには、java.util.concurrent.ConcurrentHashMap
をインポートする必要があります 最初にパッケージ。パッケージをインポートしたら、Java で同時ハッシュマップを作成する方法を次に示します。
// ConcurrentHashMap with capacity 8 and load factor 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
上記のコードでは、numbers という名前の同時ハッシュマップを作成しました。 .
ここで、
- キー - マップ内の各要素 (値) を関連付けるために使用される一意の識別子
- 値 - マップ内のキーによって関連付けられた要素
new ConcurrentHashMap<>(8, 0.6)
の部分に注目してください .ここで、最初のパラメータは容量です 2 番目のパラメータは loadFactor です .
- 容量 - このマップの容量は 8 です。つまり、8 つのエントリを格納できます。
- 負荷係数 - このマップの負荷率は 0.6 です。これは、ハッシュ テーブルが 60% 埋まるたびに、元のハッシュ テーブルの 2 倍のサイズの新しいハッシュ テーブルにエントリが移動されることを意味します。
デフォルトの容量と負荷率
容量と負荷係数を定義せずに、同時ハッシュマップを作成することは可能です。たとえば、
// ConcurrentHashMap with default capacity and load factor
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
デフォルトでは、
- マップの容量は 16 です
- 負荷係数は 0.75 になります
他のマップから ConcurrentHashMap を作成する
他のマップのすべての要素を含む同時ハッシュマップを作成する方法は次のとおりです。
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
// Creating a hashmap of even numbers
HashMap<String, Integer> evenNumbers = new HashMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("HashMap: " + evenNumbers);
// Creating a concurrent hashmap from other map
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()
- 指定されたマップのすべてのエントリをこのマップに挿入しますputIfAbsent()
- 指定されたキーがマップに存在しない場合、指定されたキー/値のマッピングをマップに挿入します
たとえば、
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
// Creating ConcurrentHashMap of even numbers
ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>();
// Using put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
// Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("ConcurrentHashMap of even numbers: " + evenNumbers);
//Creating ConcurrentHashMap of numbers
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("ConcurrentHashMap of numbers: " + numbers);
}
}
出力
ConcurrentHashMap of even numbers: {Six=6, Four=4, Two=2} ConcurrentHashMap of numbers: {Six=6, One=1, Four=-4, Two=2}
ConcurrentHashMap 要素へのアクセス
<強い>1. entrySet()、keySet()、values() の使用
entrySet()
- マップのすべてのキー/値マッピングのセットを返しますkeySet()
- マップのすべてのキーのセットを返しますvalues()
- マップのすべての値のセットを返します
たとえば、
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);
// Using entrySet()
System.out.println("Key/Value mappings: " + numbers.entrySet());
// Using keySet()
System.out.println("Keys: " + numbers.keySet());
// Using values()
System.out.println("Values: " + numbers.values());
}
}
出力
ConcurrentHashMap: {One=1, Two=2, Three=3} Key/Value mappings: [One=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);
// Using get()
int value1 = numbers.get("Three");
System.out.println("Using get(): " + value1);
// Using getOrDefault()
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("Using getOrDefault(): " + value2);
}
}
出力
ConcurrentHashMap: {One=1, Two=2, Three=3} Using get(): 3 Using 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);
// remove method with single parameter
int value = numbers.remove("Two");
System.out.println("Removed value: " + value);
// remove method with two parameters
boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry {Three=3} removed? " + result);
System.out.println("Updated ConcurrentHashMap: " + numbers);
}
}
出力
ConcurrentHashMap: {One=1, Two=2, Three=3} Removed value: 2 Is the entry {Three=3} removed? True Updated ConcurrentHashMap: {One=1}
ConcurrentHashMap の一括操作
ConcurrentHashMap
クラスは、並行マップに安全に適用できるさまざまな一括操作を提供します。
1. forEach() メソッド
forEach()
メソッドはエントリを繰り返し処理し、指定された関数を実行します。
2 つのパラメーターが含まれます。
- parallelismThreshold - マップ内のいくつの要素操作の後、並列に実行されるかを指定します。
- トランスフォーマー - これにより、データが指定された関数に渡される前にデータが変換されます。
たとえば、
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() without transformer function
numbers.forEach(4, (k, v) -> System.out.println("key: " + k + " value: " + v));
// forEach() with transformer function
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);
// Using search()
String key = numbers.search(4, (k, v) -> {return v == 3 ? k: null;});
System.out.println("Searched value: " + key);
}
}
出力
ConcurrentHashMap: {One=1, Two=2, Three=3} Searched value: Three
search() メソッドのバリエーション
searchEntries()
- 検索機能はキー/値のマッピングに適用されますsearchKeys()
- 検索機能はキーにのみ適用されますsearchValues()
- 検索機能は値にのみ適用されます
3. reduce() メソッド
reduce()
メソッドは、マップ内の各エントリを蓄積 (収集) します。これは、マップのすべての値を追加するなど、共通のタスクを実行するためにすべてのエントリが必要な場合に使用できます。
2 つのパラメーターが含まれます。
- parallelismThreshold - 要素数の後で、マップ内の操作が並列に実行されることを指定します。
- トランスフォーマー - これにより、データが指定された関数に渡される前にデータが変換されます。
たとえば、
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);
// Using search()
int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
System.out.println("Sum of all values: " + sum);
}
}
出力
ConcurrentHashMap: {One=1, Two=2, Three=3} Sum of all values: 6
上記のプログラムでは、ステートメントに注意してください
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
ここで、
- 4 は並列しきい値です
- (k, v) -> v トランス関数です。キー/値のマッピングを値のみに転送します。
- (v1, v2) -> v1+v2 レデューサー関数です。すべての値をまとめて、すべての値を追加します。
reduce() メソッドのバリエーション
reduceEntries()
- 指定されたレデューサー関数を使用してすべてのエントリを収集した結果を返しますreduceKeys()
- 指定されたレデューサー関数を使用してすべてのキーを収集した結果を返しますreduceValues()
- 指定されたレデューサー関数を使用してすべての値を収集した結果を返します
ConcurrentHashMap と HashMap の比較
ConcurrentHashMap
の違いの一部を次に示します。 およびハッシュマップ、
ConcurrentHashMap
スレッドセーフです コレクション。つまり、複数のスレッドが同時にアクセスして変更できます。ConcurrentHashMap
forEach()
のような一括操作のメソッドを提供します 、search()
とreduce()
.
ConcurrentHashMap を使用する理由
ConcurrentHashMap
クラスは、複数のスレッドがそのエントリに同時にアクセスできるようにします。- デフォルトでは、同時ハッシュマップは 16 セグメント に分割されます .これが、16 個のスレッドが同時にマップを同時に変更できる理由です。ただし、一度にマップにアクセスできるスレッドの数に制限はありません。
putIfAbsent()
指定されたキーが既に存在する場合、メソッドはマップ内のエントリをオーバーライドしません。- 独自の同期を提供します。
Java