2016-10-30 49 views
1

我正在尝试创建一个方法来计算Flower对象的数量(创建一个名为“花btw”的类),该对象返回对象花中特定花朵的数量阵列。计算“花对象”数组中的出现次数

我使用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); 
} 

输出是这样的:

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} 

按照指示,我也加入了toString()和equals()方法,以花卉类如下所示:

我在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(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 
     } 

理想情况下,您将检索一次并放置一次。 HashMap回报null当有该键的映射,所以你可以用它来你的优势:

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

通过Java 8改:

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了一个班轮SOLU重刑:

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

由于某些原因,对象仍然没有显示出来(我的意思是计数没有用对象具有相同的值)。我redid的.equals方法让我知道,如果它看起来是正确的你。 – Linuxn00b

+0

主要是因为它们不依赖于'#equals',它们依赖于'#hashcode'。你需要同时实现和(或者说,以合同方式)'(Object1#hashcode == Object2#hashcode)==(Object1#equals(Object2))',如果'#equals'返回'true',那么这两个对象应该有相同的哈希码 – Rogue

0

如果您不覆盖toString()(来自java.lang.Object),那么当您将对象打印到控制台/日志时,它只会打印对象的十六进制表示形式(如Flower @ 6bc7c054等..)。但是您可以通过覆盖Flower类中的toString()方法来覆盖此默认行为,以实际给出名称。

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

    public String toString() { 
     return name; 
    } 
} 

公共字符串的toString():返回 对象的字符串表示。通常,toString方法返回一个字符串, “文本表示”此对象。

请参考这里 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

2

除了覆盖toString()回到你想要阅读的字符串的toString()API,您的代码包含一个真正的错误:

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

将无法​​工作。你看,Integer对象是不可变的。你的代码从地图中提取计数器,将它变成一个int(上面甚至编译?!)...然后忘掉它!您不能修改您存储在该地图中的整数的价值,相反,你必须把一个更新值回地图:

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

编辑:当然,为了使该地图确实可以和你的花朵对象一起工作,你必须为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