Why does the main function returns unexpected execution result?

131 views Asked by At

I am trying to understand the source code:

public class InstrumentedSet extends HashSet {
    // Keeps the number of attempted element insertions

    private int addCount;

    public InstrumentedHashSet(Collection c) {
        super(c);
    }

    public boolean add(Object o) {
      addCount++;
      return super.add(o);
    }

    public boolean addAll(Collection c) {
      addCount += c.size();
      return super.addAll(c);
    }

    public int getAddCount() {
      return addCount;
    }

    public static void main(String[] args) {
      InstrumentedHashSet s = new InstrumentedHashSet();
      String s1[] = new String[] {"Snap","Crackle","Pop"};
      s.addAll(Arrays.asList(s1));
      System.out.println(s.getAddCount());
      }
    }
}

I can not understand why does the main function return the execution value of 6 instead of the return value of 3.

2

There are 2 answers

0
Tom On BEST ANSWER

Well, besides the fact that you current code doesn't compile it is possible to explain that behavior.

You're calling addAll on your new InstrumentedHashSet (or InstrumentedSet) instance and this method looks like this:

addCount += c.size();
return super.addAll(c);

First you're adding 3 to addCount and since that variable was 0 before, it will then be 3, as well.
Then you're calling addAll of the super class HashSet and the implementation of it looks like this:

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

The most important part is the if statement: if (add(e)). It calls add for each item in the passed Collection and since you've overriden that method with your own implementation:

public boolean add(Object o) {
    addCount++;
    return super.add(o);
}

... that method will be called instead of the parent implementation. And here you're increasing addCount for each added element. So you're now counting each element a second time.
And that is basically the reason why System.out.println(s.getAddCount()); prints the doubled amount of the passed Collection from Arrays.asList(s1).

0
Zereges On

That is because HashSets implementation of addAll method calls add method and due to polymorhphism, InstrumentedSet.add is called.

Remove addCount += c.size(); from InstrumentedSet.addAll implementation and it will work.