Is this really necessary vs. using ArrayList<IntPair>?

We created IntList because storing int in an ArrayList requires allocating an Integer wrapper object for each element.  But now that you are using IntPair which is a full blown object that advantage is gone.