java – Counting the number of occurrences in an array of Flower Objects

java – Counting the number of occurrences in an array of Flower Objects

Besides overriding toString() to return the string you want to read, your code contains a real bug:

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

Will not work. You see, Integer objects are immutable. Your code fetches the counter from the map, turns that thing into an int (does the above even compile?!) … to then forget about it! You cant modify the value of the Integer you stored in that map, instead, you have to put an updated value back into the map:

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

Edit: and of course, in order to make that Map really work with your flower objects, you have to provide meaningful overrides for equals()/hashCode() (see here for some guidance).

The problem seems to be how youre interacting with the map. Youre both wrapping an int via Integers constructor (unnecessary due to autoboxing), and youre incrementing a value but never placing it back.

        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
        }

Ideally, you would retrieve once and place once. HashMap returns null when there is no mapping for the key, so you can use that to your advantage:

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

Shortened via Java 8:

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

As for simplifying the problem, Collectors has a nice utility for this:

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

But if you still like utilizing the loop instead, theres also Map#compute for a one-liner solution:

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

java – Counting the number of occurrences in an array of Flower Objects

If you dont override the toString() (comes from java.lang.Object), when you print the object to console/log, it simply prints the hex representation of the object (like Flower@6bc7c054, etc..). But you can override this default behavior by overriding toString() method in your Flower class to actually the give the name.

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

   public String toString() {
      return name;
   } 
}

public String toString() : Returns a string representation of the
object. In general, the toString method returns a string that
textually represents this object.

Please refer the toString() api here
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

Leave a Reply

Your email address will not be published. Required fields are marked *