質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

192閲覧

HashTable に関する質問です

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/08/05 07:11

前提・実現したいこと

HashTable の #keys(key を全て取り出したい) と #loadFactor(bucket のサイズの平均値を求めたい)を実装したいのですが、どうすればよいのかさっぱり分かりません。アイデアを頂けないでしょうか?

HashTableEntry

Java

1public class HashTableEntry<K, V> { 2 3 private K key; 4 private V value; 5 private int hash; 6 7 public HashTableEntry(K key, V value) { 8 if (key == null) 9 throw new IllegalArgumentException("key cannot be null"); 10 11 this.key = key; 12 this.value = value; 13 this.hash = key.hashCode(); 14 } 15 16 public K getKey() { 17 return this.key; 18 } 19 20 public V getValue() { 21 return this.value; 22 } 23 24 public int getHashCode() { 25 return this.hash; 26 } 27 28 public String toString() { 29 return "{" + key + ": " + value + " (" + hash + ")}"; 30 } 31 32}

HashTable

Java

1import java.util.List; 2import java.util.LinkedList; 3import java.util.Arrays; 4 5 6public class HashTable<K, V> { 7 8 private Object[] entries; 9 10 private List<HashTableEntry<K, V>> bucket(int i) { 11 return (List<HashTableEntry<K, V>>)entries[i]; 12 } 13 14 public HashTable(int numBuckets) { 15 if (numBuckets < 1) 16 throw new IllegalArgumentException("hash table must have at least one bucket"); 17 this.entries = new Object[numBuckets]; 18 for (int i = 0; i < numBuckets; i++) 19 this.entries[i] = new LinkedList<HashTableEntry<K, V>>(); 20 } 21 22 public void put(K key, V value) { 23 HashTableEntry<K, V> e = new HashTableEntry<K, V>(key, value); 24 int h = e.getHashCode(); 25 int b = Math.abs(h % this.entries.length); 26 bucket(b).add(e); 27 } 28 29 public V get(K key) { 30 int h = key.hashCode(); 31 int b = Math.abs(h % this.entries.length); 32 for (HashTableEntry<K, V> e : bucket(b)) 33 if (key.equals(e.getKey())) 34 return e.getValue(); 35 return null; 36 } 37 38 public List<K> keys() { 39 List<K> klist = new LinkedList<K>(); 40 } 41 42 public double loadFactor() { 43 double sum = 0; 44 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2018/08/05 09:14

今更思ったが、キー重複の処理は?
退会済みユーザー

退会済みユーザー

2018/08/05 23:27

キーの重複を解消できてないということでしょうか?確認してみます、、
guest

回答1

0

ベストアンサー

全要素の列挙

拡張for文でHashTable#entriesを回して、回した要素のLinkedListをループでたどればいいのでは。

loadFactorもループでまわす部分は一緒ですが、LinkedList#size()を使って計算する部分が違います。

◇余談
HashTableEntryKeyはインプレース変更を防止するために、インスタンス変数はfinalで宣言してくださいな。


どうすればすべて取り出せるでしょうか

パフォーマンスを気にしないのであれば以下のように。
2重ループでまわすコードです。(未テストです)

Java

1 public List<K> keys() { 2 List<K> klist = new LinkedList<K>(); 3 for (int i = 0; i < this.entries.length; i++) { 4 List<K> list = (List<K>) entries[i]; 5 for(int j=0;j < list.size();j++) { 6 klist.add(list.get(j)); 7 } 8 } 9 return klist; 10 } 11

以下からはパフォーマンスを気にする人向けのコード。
java.util.List#addAllを使うと、コレクションの要素をShallow Copy(※)できます。
※最初の回答もそうですが、Shallow Copyな点に注意

diff

1 List<K> list = (List<K>) entries[i]; 2- for(int j=0;j < list.size();i++) { 3- klist.add(list.get(j)); 4- } 5+ klist.addAll(list);

次に質問文のコードはLinkedListなので、RandomAccessができません。
内部はArrayListで持つほうがよいでしょう。
◇参考情報
軽い気持ちでLinkedListを使ったら休出する羽目になった話

最後にもっとパフォーマンスを気にするのであれば、entriesとは別にhashcode値のみを管理するint配列(buckets)を宣言してloadFactorに応じてrehashしてくださいな。
あと多分スルーされたと思いますが、キーのインプレース変更も防止してくださいな。
個人的にライブラリのHashMapを使わずにHashTableを再実装される方の義務だと思っているので・・・

◇参考になりそうな物
.netのHashSetクラスのAddIfNotPresentをreferencesourceで見ると
referencesourceのソースコードライセンスはMITです。

License
The files in this repository are licensed with the MIT license unless otherwise specified in the file header.

投稿2018/08/05 08:50

編集2018/08/06 08:40
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/06 00:21 編集

ありがとうございます!以下のようになりました ``` public List<K> keys() { List<K> klist = new LinkedList<K>(); for (int i = 0; i < this.entries.length; i++) { klist = this.entries[i]; } return klist; } ``` ``` public double loadFactor() { double sum = 0; for (int i = 0; i < this.entries.length; i++) { sum += this.entries[i].size(); return sum / this.entries.length; } ```
umyu

2018/08/06 00:43 編集

@egusaさんへ そのkeys()ではfor文で毎回上書きしているので、最後のエントリーの内容しか取れてないです。 this.entries[i]の内容に対してもループするようにしてくださいな。
退会済みユーザー

退会済みユーザー

2018/08/06 03:35

確かに、数字を入れ替えるだけになってました。ありがとうございます!
退会済みユーザー

退会済みユーザー

2018/08/06 04:31 編集

すいません、どうすればすべて取り出せるでしょうか?考えたんですが、分かりませんでした、、 コンパイルエラーが出るところもあり、多少修正しております public List<K> keys() { List<K> klist = new LinkedList<K>(); for (int i = 0; i < this.entries.length; i++) { klist = (List<K>)entries[i]; } return klist; }
退会済みユーザー

退会済みユーザー

2018/08/06 21:02

@umyuさん 本当にありがとうございます!おかげ様でしっかりと理解することができました。 貼って頂いたものも、参考にさせてもらいます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問