protected int sortAndMerge(List eventsToCompare, boolean sort) {
    int numUniqueEvents = 1;
    numEvents = eventsToCompare.size();
    if (sort) {
      Collections.sort(eventsToCompare);
      if (numEvents <= 1) {
        return numUniqueEvents; // nothing to do; edge case (see assertion)
      }

      ComparableEvent ce = (ComparableEvent) eventsToCompare.get(0);
      for (int i = 1; i < numEvents; i++) {
        ComparableEvent ce2 = (ComparableEvent) eventsToCompare.get(i);

        if (ce.compareTo(ce2) == 0) { 
          ce.seen++; // increment the seen count
          eventsToCompare.set(i, null); // kill the duplicate
        }
        else {
          ce = ce2; // a new champion emerges...
          numUniqueEvents++; // increment the # of unique events
        }
      }
    }
    else {
      numUniqueEvents = eventsToCompare.size();
    }
    if (sort) LOG.info("done. Reduced " + numEvents + " events to " + numUniqueEvents + ".");

    contexts = new int[numUniqueEvents][];
    outcomeList = new int[numUniqueEvents];
    numTimesEventsSeen = new int[numUniqueEvents];

    for (int i = 0, j = 0; i < numEvents; i++) {
      ComparableEvent evt = (ComparableEvent) eventsToCompare.get(i);
      if (null == evt) {
        continue; // this was a dupe, skip over it.
      }
      numTimesEventsSeen[j] = evt.seen;
      outcomeList[j] = evt.outcome;
      contexts[j] = evt.predIndexes;
      ++j;
    }
    return numUniqueEvents;
  }