HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Generic Median Heap using PriorityQueues

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
priorityqueuesgenericheapusingmedian

Problem

I've implemented a generic data structure to keep track of the median in a streaming list of numbers. I was hoping to gather the community's feedback on code style and taste.

```
package ad.collections;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.util.*;

/**
* Created by adhulipa on 10/28/16.
*/
public class MedianHeap implements Queue {

private enum QueueSize { BIGGER, SMALLER };

private PriorityQueue lowers;
private PriorityQueue uppers;

public MedianHeap() {
super();
lowers = new PriorityQueue(Collections.reverseOrder());
uppers = new PriorityQueue();
}

@Override
public boolean offer(Number number) {
boolean offered;
if ( !lowers.isEmpty() && isLessThan(number, lowers.peek())) {
// Cast number to actual type E
offered = lowers.offer( (E) number);
} else if ( !uppers.isEmpty() && isGreaterThan(number, uppers.peek())) {
offered = uppers.offer( (E) number);
} else {
// Otherwise, add new number to smaller of the two queues
Queue smallerQueue = selectQueue(QueueSize.SMALLER);
offered = smallerQueue.offer(number);
}

rebalance();
return offered;
}

@Override
public Double peek() {
return this.median(false);
}

@Override
public int size() {
return lowers.size() + uppers.size();
}

@Override
public boolean isEmpty() {
return lowers.isEmpty() && uppers.isEmpty();
}

@Override
public Double poll() {
Double median = this.median(true);
rebalance();
return median;
}

private void rebalance() {
while ( Math.abs(lowers.size() - uppers.size()) > 1 ) {
Queue bigger = selectQueue(QueueSize.BIGGER);
Queue smaller = selectQueue(QueueSize.SMALLER);
smaller.offer(bigger.poll());
}
}

private Doubl

Solution

A few of my personal pet hates:

  • You should avoid boxed Doubles as much as possible. If you are looking for a double that you can set to null, you should consider using the OptionalDouble instead.



  • You are violating the contract of the Queue interface. Notably the poll method, which is really only supposed to remove one number from the queue (yours can remove two in some circumstances), and can return an item that was never put in the queue in the first place.



  • The number of NotImplementedExceptions you are throwing around tells me that the Queue interface is not the right one to implement for this purpose. (Frankly, that type of exception should not exist, as it only encourages bad practice.)

Context

StackExchange Code Review Q#145578, answer score: 2

Revisions (0)

No revisions yet.