Skip to content

Instantly share code, notes, and snippets.

@mohno007
Last active January 25, 2019 05:55
Show Gist options
  • Select an option

  • Save mohno007/1b9d8b0dbfb35c3bdf7a03e954ed0857 to your computer and use it in GitHub Desktop.

Select an option

Save mohno007/1b9d8b0dbfb35c3bdf7a03e954ed0857 to your computer and use it in GitHub Desktop.
HashMap `javac hashmap.java && java -enableassertions hashmap`
import java.lang.SuppressWarnings;
import java.util.Optional;
import java.util.Objects;
class hashmap {
static class HashMap<K, V> {
private class Entry {
public final K key;
public V value;
public Entry next = null;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
private Object[] bucket;
private int length;
public HashMap(int length) {
assert(length > 0): "`length` must be grater than 0";
this.bucket = new Object[length];
this.length = length;
}
// キーに紐づく値を追加する
void put(K key, V value) {
Objects.requireNonNull(key, "`key` must not be null");
var hashCode = Math.abs(key.hashCode());
var newEntry = new Entry(key, value);
// ハッシュ値を元に、配列を索引する
@SuppressWarnings("unchecked")
var foundEntry = (Entry)this.bucket[hashCode % this.length];
// エントリがなければ、最初のエントリなので、そのまま代入する
if (foundEntry == null) {
this.bucket[hashCode % this.length] = newEntry;
return;
// エントリがある場合は Entry#next をたどっていって、
// * Entry#nextがnullなら: Entry#nextに新しいEntryをくっつける
// * Entry#key が一致するなら: 値を上書き
} else {
for (; foundEntry.next != null && !foundEntry.key.equals(key); foundEntry = foundEntry.next) {}
if (foundEntry.key.equals(key)) {
foundEntry.value = value;
} else {
foundEntry.next = newEntry;
}
}
}
// キーに紐づく値を取ってくる
Optional<V> find(K key) {
Objects.requireNonNull(key, "`key` must not be null");
var hashCode = Math.abs(key.hashCode());
@SuppressWarnings("unchecked")
var foundEntry = (Entry)this.bucket[hashCode % this.length];
if (foundEntry == null) {
return Optional.empty();
}
for (; !foundEntry.key.equals(key) && foundEntry != null; foundEntry = foundEntry.next) {}
return Optional
.ofNullable(foundEntry)
.map(entry -> entry.value);
}
}
public static void main(String args[]) {
var map = new HashMap<String, Integer>(10);
// 名前と年齢をセットしてみる
map.put("Yamada", 34);
// 見つかるはず
assert(map.find("Yamada").isPresent());
// 年齢は一致するはず
assert(map.find("Yamada").get().equals(34));
// 入れてないキーに対応する値はあるはずがない
assert(! map.find("Suzuki").isPresent());
// 他の名前と年齢もセットしてみる
map.put("Watanabe", 20);
assert(map.find("Watanabe").isPresent());
assert(map.find("Watanabe").get().equals(20));
// Suzukiさんを追加したら、あるはず。
map.put("Suzuki", 50);
assert(map.find("Suzuki").isPresent());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment