2016-10-30 7 views
1

オブジェクト花の特定の花の数を返すFlowerオブジェクト(flower btwというクラスを作成した)の数を数えるメソッドを作成しようとしています。アレイ。"Flower Objects"の配列内での出現回数のカウント

私はキー(花オブジェクトであるキー)に整数(合計量)をマッピングするためにHashMapを使用しています。しかし、配列を出力すると、ヒープ内のキーのメモリアドレスがHashMapテーブル内のキーの位置と一緒になります。

しかし私の意図は、同じ花オブジェクトタイプのその配列の花の量で花(それは主に名前です)を印刷することです。次のように

私のコードは次のとおり

private void displayFlowers(Flower flowerPack[]) { 
     // TODO: Display only the unique flowers along with a count of any 
     // duplicates 
     /* 
     * For example it should say Roses - 7 Daffodils - 3 Violets - 5 
     */ 
     HashMap<Flower, Integer> flowerFrequency = new HashMap<Flower, Integer>(); 
     for (Flower aFlower : flowerPack) { 
      if (flowerFrequency.containsKey(aFlower)) { 
       Integer i = flowerFrequency.get(aFlower); 
       i++; 
      } else { 
       flowerFrequency.put(aFlower, new Integer(1)); 
      } 
     } 
     System.out.println(flowerFrequency); 
} 

出力は次のようである:指示されたように、私ものtoString()とequals()花のクラスにメソッドを追加した

1: Add an item to the pack. 
2: Remove an item from the pack. 
3: Search for a flower. 
4: Display the flowers in the pack. 
0: Exit the flower pack interfact. 
4 
{null=1, [email protected]=1, [email protected]=1, [email protected]=1} 

FlowerクラスのtoString()メソッドとequals()メソッドを次のように追加しました。

public String toString() { 
     return this.color + " " + this.name + " smells like " + this.scentType + " is Thorny " + this.hasThorns; 
} 


@Override 
public boolean equals(Object otherFlower) { 

     if (otherFlower == null) { 
      return false; 
     } 
     if (!Flower.class.isAssignableFrom(otherFlower.getClass())) { 
      return false; 
     } 
     final Flower other = (Flower) otherFlower; 
     if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { 
      return false; 
     } 
     if (!(this.color.equals(other.color))) { 
      return false; 
     } 

     if (!(this.scentType.equals(other.scentType))) { 
       return false; 

     } 

     if (this.hasThorns != other.hasThorns) { 
       return false; 
     } 

     return true; 

} 
+0

@Overrideをあなたのequals ...に置き、コンパイラが**エラー**を表示します。それはequals(Object other)でなければなりません!ちょうど**リンク**に従ってください私は私の答えを入れました! – GhostCat

+0

ありがとう、私が作った編集を保存するのを忘れました、あなたの考えを今共有してください。ありがとう! – Linuxn00b

答えて

1

この問題は、マップとやりとりしているようです。あなたはIntegerのコンストラクタ(オートボックスのために不要)を使ってintをラップしていますが、値をインクリメントしていますが、決して戻しません。

 if (flowerFrequency.containsKey(aFlower)) { 
      Integer i = flowerFrequency.get(aFlower); //uses two lookups 
      i++; //only increments our immediate value, not the object 
     } else { 
      flowerFrequency.put(aFlower, new Integer(1)); //does not need wrapping 
     } 

理想的には、1回と1回だけ検索します。 HashMap戻りnullがキーのマッピングではありませんので、あなたはあなたの利点にそれを使用することができます。Java 8を介して短縮

Integer amount = flowerFrequency.get(aFlower); 
if (amount == null) { 
    amount = 0; 
} 
flowerFrequency.put(aFlower, amount + 1); 

:問題を簡素化するよう

Integer amount = flowerFrequency.getOrDefault(aFlower, 0); //default 0 for no value 
flowerFrequency.put(aFlower, amount + 1); 

、コレクターには素敵なを持っていますこのためのユーティリティ:

Map<Flower, Integer> frequency = Arrays.stream(flowerPack) 
     .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(t -> 1))); 

しかし、あなたはまだ代わりにループを利用することのように、ワンライナーのソリューにもMap#computeがあるかどう

Map<Flower, Integer> frequency = new HashMap<>(); 
for (Flower f : flowerPack) { 
    frequency.compute(f, (key, old) -> old == null ? 1 : old + 1); //increment 
} 
+0

オブジェクトは何らかの理由で同じものとして表示されません(つまり、オブジェクトが同じ値を持つとカウントが完了していないということです)。 .equalsメソッドを再作成して、正しいかどうかを私に知らせてください。 – Linuxn00b

+0

主に '#equals'に依存しないので、'#hashcode 'に依存します。 '#equals'が' true'を返し、2つのオブジェクトが同じでなければならない場合、 '(Object1#hashcode == Object2#hashcode)==(Object1#equals(Object2))'を契約的に実装する必要があります。ハッシュコード – Rogue

0

オブジェクトをコンソール/ログに出力するときにtoString()(java.lang.Objectから来る)をオーバーライドしないと、オブジェクトの16進数表現(Flower @ 6bc7c054など)が出力されます..)。しかし、FlowerクラスのtoString()メソッドをオーバーライドして実際に名前を付けることで、このデフォルトの動作をオーバーライドできます。

public class Flower { 
    private String name; 
    //other flower variables 

    public String toString() { 
     return name; 
    } 
} 

公共のStringのtoString(): オブジェクトの文字列表現を返します。一般に、toStringメソッドは、 がこのオブジェクトを「テキストで表す」文字列を返します。

読みたい文字列を返すようにtoString()を上書きするだけでなく、ここで https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

2

のtoString()APIを参照してください、あなたのコードは、実際のバグが含まれています

if (flowerFrequency.containsKey(aFlower)) { 
    Integer i = flowerFrequency.get(aFlower); 
    i++; 

は動作しません。あなたは、整数オブジェクトは不変です。あなたのコードは、マップからカウンタをフェッチし、そのものをintに変換します(上のコードはコンパイルされますか?)...それを忘れてしまいます!代わりに、あなたがマップに戻って更新値を配置する必要があり、あなたがそのマップに格納された整数の値を変更することはできません。

if (flowerFrequency.containsKey(aFlower)) { 
    Integer currentCounter = flowerFrequency.get(aFlower); 
    flowerFrequency.put(aFlower, currentCounter+1); 

編集:そしてもちろん、それを作るためにMapは実際にあなたの花オブジェクトで動作しますが、equals()/ hashCode()の意味のあるオーバーライドを提供する必要があります(いくつかのガイダンスについてはhereを参照してください)。

+1

['boolean equals(Object o)'](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang)を上書きする必要があります。 .Object-)と['int hashCode()'](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--)を正しくカウントするにはフラワーズ。 – Turing85

+0

ありがとう、良い点。私はそれに応じて私の答えを更新! – GhostCat

+0

編集については上記を参照してください。 – Linuxn00b

関連する問題