From the โtoo much time on my handsโ department: here is a little MedianGenerator class:
public final class MedianGenerator{ private MedianGenerator(){ } public static <T> T calculateMedian(final List<T> data, final Comparator<? super T> comparator, final AverageCalculator<T> averageCalculator){ final List<T> copy = new ArrayList<T>(data); Collections.sort(copy, comparator); return doCalculateMedian(data, averageCalculator); } @SuppressWarnings("unchecked") public static <T> T calculateMedian(final List<T> data, final Comparator<? super T> comparator){ return calculateMedian(data, comparator, (AverageCalculator<T>) ALWAYS_FIRST); } @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> T calculateMedian(final List<T> data){ return calculateMedian(data, (AverageCalculator<T>) ALWAYS_FIRST); } public static <T extends Comparable<? super T>> T calculateMedian(final List<T> data, final AverageCalculator<T> averageCalculator){ final List<T> copy = new ArrayList<T>(data); Collections.sort(copy); return doCalculateMedian(copy, averageCalculator); } private static <T> T doCalculateMedian(final List<T> sortedData, final AverageCalculator<T> averageCalculator){ T result; if(sortedData.isEmpty()){ result = null; } else{ final int size = sortedData.size(); if(size % 2 == 0){ result = averageCalculator.getAverage(sortedData.get(size / 2 - 1), sortedData.get(size / 2)); } else{ result = sortedData.get(size / 2 - 1); } } return result; } @SuppressWarnings("unchecked") public static <T> AverageCalculator<T> alwaysFirst(){ return ALWAYS_FIRST; } @SuppressWarnings("rawtypes") public static final AverageCalculator ALWAYS_FIRST = new AverageCalculator(){ @Override public Object getAverage(final Object first, final Object second){ return first; } }; public static interface AverageCalculator<E> { E getAverage(E first, E second); } }
source share