protected long mergeNumDistinctValueEstimator(String columnName, List<NumDistinctValueEstimator> estimators,
      long oldNumDVs, long newNumDVs) {
    if (estimators == null || estimators.size() != 2) {
      throw new IllegalArgumentException("NDV estimators list must be set and contain exactly two elements, " +
          "found " + (estimators == null ? "null" :
          estimators.stream().map(NumDistinctValueEstimator::toString).collect(Collectors.joining(", "))));
    }

    NumDistinctValueEstimator oldEst = estimators.get(0);
    NumDistinctValueEstimator newEst = estimators.get(1);
    if (oldEst == null && newEst == null) {
      return mergeNumDVs(oldNumDVs, newNumDVs);
    }

    if (oldEst == null) {
      estimators.set(0, newEst);
      return mergeNumDVs(oldNumDVs, newEst.estimateNumDistinctValues());
    }

    final long ndv;
    if (oldEst.canMerge(newEst)) {
      oldEst.mergeEstimators(newEst);
      ndv = oldEst.estimateNumDistinctValues();
      return ndv;
    } else {
      ndv = mergeNumDVs(oldNumDVs, newNumDVs);
    }
    LOG.debug("Use bitvector to merge column {}'s ndvs of {} and {} to be {}", columnName,
        oldNumDVs, newNumDVs, ndv);
    return ndv;
  }
@Test
  public void testMergeNDVEstimatorsSecondNull() {
    NumDistinctValueEstimator estimator1 =
        NumDistinctValueEstimatorFactory.getNumDistinctValueEstimator(HLL_1.serialize());

    for (ColumnStatsMerger<?> MERGER : MERGERS) {
      List<NumDistinctValueEstimator> estimatorList = Arrays.asList(estimator1, null);
      long computedNDV = MERGER.mergeNumDistinctValueEstimator("", estimatorList, 2, 1);

      assertEquals(Arrays.asList(estimator1, null), estimatorList);
      assertEquals(2, computedNDV);
    }
  }