ValueAggregator { public Value<V> weightedMedian(){ if(this.weights == null){ throw new IllegalStateException(); } int size = this.values.size(); if(size == 0){ throw new UndefinedResultException(); } List<Entry> entries = new ArrayList<>(size); for(int i = 0; i < size; i++){ Entry entry = new Entry(this.values.get(i), this.weights.get(i)); entries.add(entry); } Collections.sort(entries); double weightSumThreshold = 0.5d * (this.weights.sum()).doubleValue(); double weightSum = 0d; for(Entry entry : entries){ weightSum += (entry.weight).doubleValue(); if(weightSum >= weightSumThreshold){ return entry.value; } } throw new NotImplementedException(); } protected  ValueAggregator(Vector<V> values); protected  ValueAggregator(Vector<V> values, Vector<V> weights); protected  ValueAggregator(Vector<V> values, Vector<V> weights, Vector<V> weightedValues); void add(Number value); void add(Number value, Number weight); Value<V> average(); Value<V> weightedAverage(); Value<V> sum(); Value<V> weightedSum(); Value<V> median(); Value<V> weightedMedian();  }
@Test public void weightedMedian(){ ValueAggregator<Double> aggregator = new ValueAggregator.WeightedMedian<>(this.valueFactory, 3); try { aggregator.weightedMedian(); fail(); } catch(UndefinedResultException ure){ } aggregator.add(1d, 3d); aggregator.add(5d, 7d); assertEquals(new DoubleValue(5d), aggregator.weightedMedian()); aggregator.add(7d, 11d); assertEquals(new DoubleValue(7d), aggregator.weightedMedian()); }