Java実装の簡単なHashMap
9344 ワード
Hashテーブルの作成方法
K(キー)-V(値)のようなキー値ペアをHashテーブルに挿入するには、2つのステップが必要です.は、ハッシュ関数を使用してKを小さな整数(そのハッシュコードと呼ばれる)に変換する. ハッシュコードは、インデックス(hashCode%arrSize)を検索するために使用され、最初にインデックスにおけるチェーンテーブル全体(単一チェーン)を検索して、既存のKを検索する. が見つかった場合、その値が更新され、そうでない場合、K-Vペアがリスト内の新しいノードとして格納されます.
複雑さと負荷係数最初のステップは、Kおよびハッシュ関数に依存して時間がかかる.
たとえば、キーが文字列「abcd」である場合、そのハッシュ関数は文字列の長さに依存する可能性があります.しかし,非常に大きなn値では,マッピング中のエントリ数に比べて鍵の長さはほとんど無視できるため,ハッシュ計算は一定時間,すなわちO(1)で起こると考えられる.は、第2のステップについて、インデックスに存在するK−Vペアのリストを巡回する必要がある.このため、最悪の場合、すべてのn個のエントリが同じインデックスにある可能性があります.したがって,時間的複雑さはO(n)となる.しかし,ハッシュ関数で生成された結合が配列中に均一に分布するように十分な研究が行われているので,これはほとんど起こらない.
したがって、平均すると、n個のエントリがあり、bが配列のサイズである場合、各インデックスにはn/b個のエントリがある.この値n/bを負荷因子と呼び,hashテーブル上の負荷状況を表す.負荷係数(Load Factor)は低く維持する必要があるため、1つのインデックスにおけるエントリ数が少ないため、複雑度はほぼ一定、すなわちO(1)である.
Rehashing
名前の通り、rehashingは再びハッシュすることを意味します.基本的には、負荷係数が所定値を超える(負荷係数のデフォルト値が0.75)まで増加すると、複雑さが増加する.従って、この問題を克服するために、配列のサイズが増加(倍増)し、すべての値が再びハッシュされ、低負荷因子と低複雑度を維持するために、新しい2倍サイズの配列に格納される.
なぜ?
再ハッシュは、キー値ペアがマッピングに挿入されるたびに負荷係数が増加するため、時間的複雑さも上述したように増加することを意味する.これはO(1)に要する時間的複雑さを提供できない可能性がある.
したがって,負荷因子と時間的複雑さを低減するためにBucket Arrayのサイズを大きくするために再ハッシュを行う必要がある.
どうやって?
Rehashingは次のように行えます. hashテーブルに新しいエントリを追加するたびに、負荷係数を確認します. 事前定義値より大きい場合(指定されていない場合、デフォルト値は0.75)、再ハッシュされます. Rehashingでは、以前のサイズよりも2倍の新しい配列を作成し、新しいBucket Arrayにします. は、その後、古いBucket Arrayの各要素を巡回し、各要素に対してinsert()関数を呼び出して、新しいより大きなbucket配列に挿入します.
Javaプログラムインスタンス
運転出力
テキストリンク
K(キー)-V(値)のようなキー値ペアをHashテーブルに挿入するには、2つのステップが必要です.
複雑さと負荷係数
たとえば、キーが文字列「abcd」である場合、そのハッシュ関数は文字列の長さに依存する可能性があります.しかし,非常に大きなn値では,マッピング中のエントリ数に比べて鍵の長さはほとんど無視できるため,ハッシュ計算は一定時間,すなわちO(1)で起こると考えられる.
したがって、平均すると、n個のエントリがあり、bが配列のサイズである場合、各インデックスにはn/b個のエントリがある.この値n/bを負荷因子と呼び,hashテーブル上の負荷状況を表す.
Rehashing
名前の通り、rehashingは再びハッシュすることを意味します.基本的には、負荷係数が所定値を超える(負荷係数のデフォルト値が0.75)まで増加すると、複雑さが増加する.従って、この問題を克服するために、配列のサイズが増加(倍増)し、すべての値が再びハッシュされ、低負荷因子と低複雑度を維持するために、新しい2倍サイズの配列に格納される.
なぜ?
再ハッシュは、キー値ペアがマッピングに挿入されるたびに負荷係数が増加するため、時間的複雑さも上述したように増加することを意味する.これはO(1)に要する時間的複雑さを提供できない可能性がある.
したがって,負荷因子と時間的複雑さを低減するためにBucket Arrayのサイズを大きくするために再ハッシュを行う必要がある.
どうやって?
Rehashingは次のように行えます.
Javaプログラムインスタンス
// Java program to implement Rehashing
import java.util.ArrayList;
class Map {
class MapNode {
K key;
V value;
MapNode next;
public MapNode(K key, V value)
{
this.key = key;
this.value = value;
next = null;
}
}
// The bucket array where
// the nodes containing K-V pairs are stored
ArrayList > buckets;
// No. of pairs stored - n
int size;
// Size of the bucketArray - b
int numBuckets;
// Default loadFactor
final double DEFAULT_LOAD_FACTOR = 0.75;
public Map()
{
numBuckets = 5;
buckets = new ArrayList<>(numBuckets);
for (int i = 0; i < numBuckets; i++) {
// Initialising to null
buckets.add(null);
}
System.out.println("HashMap created");
System.out.println("Number of pairs in the Map: " + size);
System.out.println("Size of Map: " + numBuckets);
System.out.println("Default Load Factor : " + DEFAULT_LOAD_FACTOR + "
");
}
private int getBucketInd(K key)
{
// Using the inbuilt function from the object class
int hashCode = key.hashCode();
// array index = hashCode%numBuckets
return (hashCode % numBuckets);
}
public void insert(K key, V value)
{
// Getting the index at which it needs to be inserted
int bucketInd = getBucketInd(key);
// The first node at that index
MapNode head = buckets.get(bucketInd);
// First, loop through all the nodes present at that index
// to check if the key already exists
while (head != null) {
// If already present the value is updated
if (head.key.equals(key)) {
head.value = value;
return;
}
head = head.next;
}
// new node with the K and V
MapNode newElementNode = new MapNode(key, value);
// The head node at the index
head = buckets.get(bucketInd);
// the new node is inserted
// by making it the head
// and it's next is the previous head
newElementNode.next = head;
buckets.set(bucketInd, newElementNode);
System.out.println("Pair(" + key + ", " + value + ") inserted successfully.
");
// Incrementing size
// as new K-V pair is added to the map
size++;
// Load factor calculated
double loadFactor = (1.0 * size) / numBuckets;
System.out.println("Current Load factor = " + loadFactor);
// If the load factor is > 0.75, rehashing is done
if (loadFactor > DEFAULT_LOAD_FACTOR) {
System.out.println(loadFactor + " is greater than " + DEFAULT_LOAD_FACTOR);
System.out.println("Therefore Rehashing will be done.
");
// Rehash
rehash();
System.out.println("New Size of Map: " + numBuckets + "
");
}
System.out.println("Number of pairs in the Map: " + size);
System.out.println("Size of Map: " + numBuckets + "
");
}
private void rehash()
{
System.out.println("
***Rehashing Started***
");
// The present bucket list is made temp
ArrayList > temp = buckets;
// New bucketList of double the old size is created
buckets = new ArrayList >(2 * numBuckets);
for (int i = 0; i < 2 * numBuckets; i++) {
// Initialised to null
buckets.add(null);
}
// Now size is made zero
// and we loop through all the nodes in the original bucket list(temp)
// and insert it into the new list
size = 0;
numBuckets *= 2;
for (int i = 0; i < temp.size(); i++) {
// head of the chain at that index
MapNode head = temp.get(i);
while (head != null) {
K key = head.key;
V val = head.value;
// calling the insert function for each node in temp
// as the new list is now the bucketArray
insert(key, val);
head = head.next;
}
}
System.out.println("
***Rehashing Ended***
");
}
public void printMap()
{
// The present bucket list is made temp
ArrayList > temp = buckets;
System.out.println("Current HashMap:");
// loop through all the nodes and print them
for (int i = 0; i < temp.size(); i++) {
// head of the chain at that index
MapNode head = temp.get(i);
while (head != null) {
System.out.println("key = " + head.key + ", val = " + head.value);
head = head.next;
}
}
System.out.println();
}
}
public class GFG {
public static void main(String[] args)
{
// Creating the Map
Map map = new Map();
// Inserting elements
map.insert(1, "Geeks");
map.printMap();
map.insert(2, "forGeeks");
map.printMap();
map.insert(3, "A");
map.printMap();
map.insert(4, "Computer");
map.printMap();
map.insert(5, "Portal");
map.printMap();
}
}
運転出力
HashMap created
Number of pairs in the Map: 0
Size of Map: 5
Default Load Factor : 0.75
Pair(1, Geeks) inserted successfully.
Current Load factor = 0.2
Number of pairs in the Map: 1
Size of Map: 5
Current HashMap:
key = 1, val = Geeks
Pair(2, forGeeks) inserted successfully.
Current Load factor = 0.4
Number of pairs in the Map: 2
Size of Map: 5
Current HashMap:
key = 1, val = Geeks
key = 2, val = forGeeks
Pair(3, A) inserted successfully.
Current Load factor = 0.6
Number of pairs in the Map: 3
Size of Map: 5
Current HashMap:
key = 1, val = Geeks
key = 2, val = forGeeks
key = 3, val = A
Pair(4, Computer) inserted successfully.
Current Load factor = 0.8
0.8 is greater than 0.75
Therefore Rehashing will be done.
***Rehashing Started***
Pair(1, Geeks) inserted successfully.
Current Load factor = 0.1
Number of pairs in the Map: 1
Size of Map: 10
Pair(2, forGeeks) inserted successfully.
Current Load factor = 0.2
Number of pairs in the Map: 2
Size of Map: 10
Pair(3, A) inserted successfully.
Current Load factor = 0.3
Number of pairs in the Map: 3
Size of Map: 10
Pair(4, Computer) inserted successfully.
Current Load factor = 0.4
Number of pairs in the Map: 4
Size of Map: 10
***Rehashing Ended***
New Size of Map: 10
Number of pairs in the Map: 4
Size of Map: 10
Current HashMap:
key = 1, val = Geeks
key = 2, val = forGeeks
key = 3, val = A
key = 4, val = Computer
Pair(5, Portal) inserted successfully.
Current Load factor = 0.5
Number of pairs in the Map: 5
Size of Map: 10
Current HashMap:
key = 1, val = Geeks
key = 2, val = forGeeks
key = 3, val = A
key = 4, val = Computer
key = 5, val = Portal
テキストリンク