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

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

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

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

Q&A

3回答

2050閲覧

Java インターフェースについての質問です

anna10

総合スコア24

Java

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

0グッド

0クリップ

投稿2014/12/05 04:33

インターフェースクラスの指定されたメソッドを自作し、自作したメソッドを呼び出す、という問題です。HashMapなどの実装クラスは使用出来ない、という制約付です。


getメソッド、若しくはputメソッドが機能していない?というのが最大の意味不明ポイントです。HashMapをインポートしてみても上記のやり方ではnullが返ったので、普通に、

System.out.println(map.get("リン"));

としてもnullが返ってきてしまいます。Keyの値が表示されなくなっただけでも多少の進歩と言えるのでしょうか。寧ろ退化していると感じています。。。


hashCodeメソッドですが、調べたところ、PCが勝手に設定する数値?というものらしいのです。一応上記のコードで数値の羅列が表示されるのですが、これが合っているのかどうか分かりません。


Listインターフェースに続き、またしてもclearメソッドがその時だけしか機能していないという状況です。全て削除するので、KeyとValueの値も指定して削除しているつもりなのですが。。。

以上3点になりますが、どなたか教えて頂けないでしょうか?
よろしくお願い致します。

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

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

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

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

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

guest

回答3

0

ベストアンサー

質問文に示された コードの設計をベースに
各メソッドの実装と、メインメソッドでの purint 文を変更してみました。
(もっと別の map interface の実装を web で探して 設計方針を比較してみるとよいと思います。)

lang

1import java.util.Map; 2import java.util.Collection; 3import java.util.Set; 4 5class LocalMap<K, V> implements java.util.Map<K, V> { 6 final int SIZE_UNIT = 2; 7 8 private K[] keys = (K[])(new Object[SIZE_UNIT]); 9 private V[] vals = (V[])(new Object[SIZE_UNIT]); 10 private int count = 0; 11 12 public LocalMap() { 13 count = 0; 14 } 15 16 public void clear() { 17 count = 0; 18 } 19 20 public boolean containsKey(Object key) { 21 for (int i = 0; i < count; i++) { 22 if (keys[i].equals(key)) { 23 return true; 24 } 25 } 26 return false; 27 } 28 29 public boolean containsValue(Object value) { 30 boolean len = false; 31 for (int i = 0; i < count; i++) { 32 if (vals[i].equals(value)){ 33 return true; 34 } 35 } 36 return len; 37 } 38 39 // See http://typea.info/blg/glob/2014/05/java-hashcode-equals.html 40 public int hashCode() { 41 final int prime = 31; 42 int result = 1; 43 result = prime * result + ((keys == null) ? 0 : keys.hashCode()); 44 result = prime * result + ((vals == null) ? 0 : vals.hashCode()); 45 return result; 46 } 47 48 public boolean equals(Object obj) { 49 if (this == obj) { 50 return true; 51 } 52 if (obj == null) { 53 return false; 54 } 55 if (getClass() != obj.getClass()) { 56 return false; 57 } 58 LocalMap<K, V> map2 = (LocalMap<K, V>)obj; 59 if (count != map2.count) { 60 return false; 61 } 62 for (int i = 0; i < count; i++) { 63 K k = keys[i]; 64 if (!get(k).equals(map2.get(k))) { 65 return false; 66 } 67 } 68 return true; 69 } 70 71 public V get(Object key) { 72 for (int i = 0; i < count; i++) { 73 if (keys[i].equals(key)) { 74 return vals[i]; 75 } 76 } 77 return null; 78 } 79 80 public V put(K key, V value) { 81 int pos = -1; 82 for (int i = 0; i < count; i++) { 83 if (keys[i] == key) { 84 pos = i; 85 break; 86 } 87 } 88 if (pos < 0) { 89 if (count == keys.length) { 90 K[] keys_2 = (K[])(new Object[count + SIZE_UNIT]); 91 V[] vals_2 = (V[])(new Object[count + SIZE_UNIT]); 92 for (int i = 0; i < count; i++) { 93 keys_2[i] = keys[i]; 94 vals_2[i] = vals[i]; 95 } 96 keys = keys_2; 97 vals = vals_2; 98 } 99 keys[count] = key; 100 vals[count] = value; 101 count++; 102 } else { 103 vals[pos] = value; 104 } 105 return value; 106 } 107 108 public V remove(Object key) { 109 if (!containsKey(key)) { 110 return null; 111 } 112 V v = get(key); 113 int pos = -1; 114 for (int i = 0; i < count; i++) { 115 if (keys[i].equals(key)) { 116 pos = i; 117 break; 118 } 119 } 120 for (int i = pos; i < count - 1; i++) { 121 keys[i] = keys[i + 1]; 122 vals[i] = vals[i + 1]; 123 } 124 count--; 125 return v; 126 } 127 128 public int size() { 129 return count; 130 } 131 public boolean isEmpty() { 132 return size() > 0; 133 } 134 135 // 実装しないメソッド群 136 public Object clone() { 137 throw new UnsupportedOperationException(); 138 } 139 public Set<Map.Entry<K,V>> entrySet() { 140 throw new UnsupportedOperationException(); 141 } 142 public Set<K> keySet() { 143 throw new UnsupportedOperationException(); 144 } 145 public void putAll(Map<? extends K, ? extends V> m) { 146 } 147 public Collection<V> values() { 148 throw new UnsupportedOperationException(); 149 } 150} 151 152class Main { 153 public static void main(String[] args) { 154 LocalMap<String, String> map = new LocalMap<String, String>(); 155 String[] keys = { 156 "シロウ", // "セイバー" 157 "リン", // "アーチャー" 158 "イリヤ", // "バーサーカー" 159 "サクラ", // "ライダー" 160 "キレイ", // "ランサー" 161 "キャスター", // "アサシン" 162 "ライダー", // "イスカンダル" 163 "ランサー", //" ディルムッド" 164 "ウェイバー", // "ブケファラス" 165 }; 166 map.put("シロウ", "セイバー"); 167 map.put("リン", "アーチャー"); 168 map.put("イリヤ", "バーサーカー"); 169 map.put("サクラ", "ライダー"); 170 map.put("キレイ", "ランサー"); 171 map.put("キャスター", "アサシン"); 172 map.put("ライダー", "イスカンダル"); 173 map.put("ランサー"," ディルムッド"); 174 map.put("ウェイバー", "ブケファラス"); 175 for (int i = 0; i < keys.length; i++) { 176 System.out.println("" + (i + 1) + ":\t[" + keys[i] + ", " + map.get(keys[i]) + "]"); 177 } 178 179 LocalMap<String, String> map2 = new LocalMap<String, String>(); 180 map2.put("クルーゼ", "プロヴィデンス"); 181 System.out.println("map.equals(map2): " + map.equals(map2)); 182 183 System.out.println("map.hashCode(): " + map.hashCode()); 184 map.remove("リン"); 185 System.out.println("after remove(リン)\nマスターが脱落し" + map.size() + "人になりました"); 186 for (int i = 0; i < keys.length; i++) { 187 System.out.println("" + (i + 1) + ":\t[" + keys[i] + ", " + map.get(keys[i]) + "]"); 188 } 189 190 System.out.println("map.containsKey(キレイ): " + map.containsKey("キレイ")); 191 System.out.println("map.containsKey(キリツグ): " + map.containsKey("キリツグ")); 192 193 System.out.println("map.containsValue(セイバー): " + map.containsValue("セイバー")); 194 System.out.println("map.containsValue(ギルガメッシュ): " + map.containsValue("ギルガメッシュ")); 195 196 System.out.println("map.isEmpty(): " + map.isEmpty()); 197 198 map.clear(); 199 System.out.println("after map.clear()\nマスターは" + map.size() + "人になりました。聖杯戦争は終了です"); 200 System.out.println("map.isEmpty(): " + map.isEmpty()); 201 for (int i = 0; i < keys.length; i++) { 202 System.out.println("" + (i + 1) + ":\t[" + keys[i] + ", " + map.get(keys[i]) + "]"); 203 } 204 } 205}

投稿2014/12/03 14:42

katoy

総合スコア22324

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

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

anna10

2014/12/03 21:55

とても助かりました。回答誠にありがとう御座います。
KSwordOfHaste

2014/12/05 09:16

上のコードではequalsをまじめに実装してしているのでhashCodeの実装が不十分になってしまってます。規則によりequalsがtrueならそれら2つのLocalMapはhashCode()が同じ値を返さなければならないのですが、上の実装では異なる値を返すことがあります。
katoy

2014/12/05 13:55

>> hashCodeの実装が不十分 ご指摘のとおりですね。 main() に次のコードを追加してから実行すると、equals() と hashCode() の不一致がわかります。 LocalMap<String, String> mapA = new LocalMap<String, String>(); LocalMap<String, String> mapB = new LocalMap<String, String>(); LocalMap<String, String> mapC = new LocalMap<String, String>(); LocalMap<String, String> mapD = new LocalMap<String, String>(); mapA.put("1", "A"); mapA.put("2", "B"); mapB.put("1", "A"); mapB.put("2", "B"); mapC.put("2", "B"); mapC.put("1", "A"); mapD.put("1", "A"); mapD.put("2", "A"); System.out.println("mapA.equals(mapB): " + mapA.equals(mapB)); System.out.println("mapA.equals(mapC): " + mapA.equals(mapC)); System.out.println("mapA.equals(mapD): " + mapA.equals(mapD)); System.out.println("mapA.hashCode: " + mapA.hashCode()); System.out.println("mapB.hashCode: " + mapB.hashCode()); System.out.println("mapC.hashCode: " + mapC.hashCode()); System.out.println("mapD.hashCode: " + mapD.hashCode()); 実行すると次の出力になります。   mapA.equals(mapB): true   mapA.equals(mapC): true   mapA.equals(mapD): false   mapA.hashCode: 924049720   mapB.hashCode: -1803830863   mapC.hashCode: -1356046837   mapD.hashCode: -1390868029 hashCode() の実装を次のように変更します。 ... import java.util.Arrays; // for Array.sort() .... public int hashCode() { final int prime = 31; int result = 1; K[] keys2 = (K[])(new Object[count]); V[] vals2 = (V[])(new Object[count]); for (int i = 0; i < count; i++) { keys2[i] = keys[i]; } Arrays.sort(keys2); for (int i = 0; i < count; i++) { vals2[i] = get(keys2[i]); } for (int i = 0; i < count; i++) { result = prime * result + ((keys2[i] == null) ? 0 : keys2[i].hashCode()); } for (int i = 0; i < count; i++) { result = prime * result + ((vals2[i] == null) ? 0 : vals2[i].hashCode()); } return result; } 変更後の実行では次の出力になります。   mapA.equals(mapB): true   mapA.equals(mapC): true   mapA.equals(mapD): false   mapA.hashCode: 2433411   mapB.hashCode: 2433411   mapC.hashCode: 2433411   mapD.hashCode: 2433410
guest

0

hashCodeについてのみコメントします。
LocalMapクラスのhashCodeメソッドはLocalMap自体へのput/getの動作には直接関係しません。
hashCodeはequalsと組になってこのクラス(LocalMap)のインスタンスが(ハッシュ法を用いている)他のMapに正しく要素として格納できるかどうかに影響します。つまりいくらLocalMapへのput/getのテストをしてもLocalMapのhashCodeの実装が正しいかどうかの確認をしていることになりません。

通常、Map自体を他のMapの要素としたいということはあまりないと思いますので、equals/hashCodeともにLocalMapに実装する必要はなく、Objectクラスのデフォルト実装で充分です。つまりequalsは==と同じ動作であり、hashCodeは同じインスタンスなら必ず同じ値になり違うインスタンスなら違う値(になる可能性が高い)値になります。
ただし、問題文で実装するMapクラスのequalsの仕様について「同一でないインスタンスであっても内容が同じなら等しいとみなす」等の条件があるならequals/hashCodeをまじめに実装する必要があります。(おそらくそんな意地悪な条件はついてないと思いますが)

投稿2014/12/03 09:05

KSwordOfHaste

総合スコア18394

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

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

0

部分的に回答します。

  • getの実装が意味不明です。keyをstrから検索してrinを返却する処理が必要だと思います。その上で、getをputしたkeyで呼び出せばvalueが取れるはずです。
  • hashCodeはMapのkeyの内部値になるものだと思います。keyに対して一意な数値が作れればいいはずですが、質問の実装はなにかおかしい気がします。(Map自体のhashCodeを使うことはないような気がします。)
  • clearが機能していないと言うのはisEmptyの結果に関することでしょうか? であればclearでnullにしていないのにisEmptyではnullで判定しているからだと思います。

投稿2014/12/03 00:39

TaMaMhyu

総合スコア1356

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問