计算“花卉对象”数组中出现的次数

时间:2016-10-30 19:50:17

标签: java arrays hashmap

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

我正在使用HashMap将整数(总和)映射到一个键(键是花对象)。但是,当我输出数组时,堆中键的内存地址与HashMap表中键的位置一起。

然而,我的意图是打印花(主要是名称),该数组中的花朵数量与Flower Object类型相同。

我的代码如下:

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, Flower@6bc7c054=1, Flower@42a57993=1, Flower@75b84c92=1}

按照说明,我还将toString()和equals()方法添加到Flower类中,如下所示:

我在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;

}

3 个答案:

答案 0 :(得分:2)

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

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);

编辑:当然,为了使Map真正适用于您的花对象,您必须为equals()/ hashCode()提供有意义的覆盖(有关指导,请参阅here)。

答案 1 :(得分: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);

至于简化问题,Collectors有一个很好的实用工具:

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
}

答案 2 :(得分:0)

如果你没有覆盖toString()(来自java.lang.Object),当你将对象打印到console / log时,它只是打印对象的十六进制表示(如Flower @ 6bc7c054等)。 )。但是,您可以通过覆盖toString类中的Flower()方法来覆盖此默认行为,以实际提供名称。

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

   public String toString() {
      return name;
   } 
}
  

public String toString():返回的字符串表示形式   宾语。通常,toString方法返回一个字符串   “文字表示”这个对象。

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