public V merge(V a, V b) {
        final V aHead = componentOf(a);
        final V bHead = componentOf(b);
        if (aHead.equals(bHead)) return aHead;
        // add the shorter tree underneath the taller tree
        final int aRank = ranks.getOrDefault(aHead, 0);
        final int bRank = ranks.getOrDefault(bHead, 0);
        if (aRank > bRank) {
            parents.put(bHead, aHead);
            return aHead;
        } else if (bRank > aRank) {
            parents.put(aHead, bHead);
            return bHead;
        } else {
            // whoops, the tree got taller
            parents.put(bHead, aHead);
            ranks.put(aHead, aRank + 1);
            return aHead;
        }
    }
public V merge ( V a , V b ) { final V aHead = componentOf ( a ) ; final V bHead = componentOf ( b ) ; if ( aHead . equals ( bHead ) ) return aHead ; final int aRank = ranks . getOrDefault ( aHead , 0 ) ; final int bRank = ranks . getOrDefault ( bHead , 0 ) ; if ( aRank > bRank ) { parents . put ( bHead , aHead ) ; return aHead ; } else if ( bRank > aRank ) { parents . put ( aHead , bHead ) ; return bHead ; } else { parents . put ( bHead , aHead ) ; ranks . put ( aHead , aRank + 1 ) ; return aHead ; } }
Merges the given components and returns the representative of the new component