001 /*--------------------------------------------------------------------------+ 002 $Id: MedianAggregator.java 29788 2010-08-19 08:46:02Z juergens $ 003 | | 004 | Copyright 2005-2010 Technische Universitaet Muenchen | 005 | | 006 | Licensed under the Apache License, Version 2.0 (the "License"); | 007 | you may not use this file except in compliance with the License. | 008 | You may obtain a copy of the License at | 009 | | 010 | http://www.apache.org/licenses/LICENSE-2.0 | 011 | | 012 | Unless required by applicable law or agreed to in writing, software | 013 | distributed under the License is distributed on an "AS IS" BASIS, | 014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 015 | See the License for the specific language governing permissions and | 016 | limitations under the License. | 017 +--------------------------------------------------------------------------*/ 018 package edu.tum.cs.commons.math; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Collections; 023 024 /** 025 * Median aggregator. Note that for an even number of elements this aggregator 026 * returns the mean value of both middle elements. 027 * 028 * @author deissenb 029 * @author $Author: juergens $ 030 * @version $Rev: 29788 $ 031 * @levd.rating GREEN Hash: 263069760E186DA03CC4463A773263DD 032 */ 033 public class MedianAggregator implements IAggregator { 034 035 /** 036 * Aggregates by finding the median. 037 * 038 * @return {@link Double#NaN} for empty input collection 039 */ 040 @Override 041 public double aggregate(Collection<? extends Number> values) { 042 if (values.isEmpty()) { 043 return Double.NaN; 044 } 045 046 ArrayList<Double> doubleValues = new ArrayList<Double>(); 047 048 for (Number value : values) { 049 doubleValues.add(value.doubleValue()); 050 } 051 052 Collections.sort(doubleValues); 053 054 // odd number of elements 055 if (doubleValues.size() % 2 == 1) { 056 int medianIndex = (int) Math.ceil(doubleValues.size() / 2); 057 return doubleValues.get(medianIndex); 058 } 059 060 // even number of elements 061 int lowerMedianIndex = doubleValues.size() / 2 - 1; 062 double lowerMedian = doubleValues.get(lowerMedianIndex); 063 double upperMedian = doubleValues.get(lowerMedianIndex + 1); 064 065 return (lowerMedian + upperMedian) / 2; 066 } 067 068 /** Returns {@link Double#NaN}. */ 069 @Override 070 public double getNeutralElement() { 071 return Double.NaN; 072 } 073 }