I want to efficiently calculate two means of values of a HashMap
each time a new key/value pair is inserted.
Suppose we currently have this HashMap<Double, Double>
:
3 4
5 6
8 8
1 3
6 8 <- Latest insertion
The latest insertion was the key 6
with value 8
.
The first mean to calculate consists of all values which keys are smaller than the inserted one, which is 6
.
These are the values 4,6,3
of the keys 3,5,1
, so the mean is (4+6+3)/3=4.3...
The second mean is the "opposite", so the mean of all values for all keys greater than 6
.
The key 8
with value 1
gives this mean as 8/1=8
.
Now, a new key/pair gets inserted:
3 4
5 6
6 8
8 8
1 3
4 9 <- Latest insertion
So again, we need to calculate the mean for all values with keys smaller than 4
.
These are the values 4,3
for the keys 3,1
, so the "smaller mean" is now (4+3)/2=3.5
The "greater mean" is now (6+8+8)/3=7.3...
for the key/value pairs 5/6,6/8,8/8
.
A naive implementation might be something like this:
public class CalculateMapMean {
private double smallerMean = 0.0;
private double greaterMean = 0.0;
private HashMap<Double, Double> someMap = new HashMap<Double, Double>();
public void calculateMeans(double latestInsertedKey) {
double sumGreater = 0;
double sumSmaller = 0;
double sumGreaterCount = 0;
double sumSmallerCount = 0;
for (Map.Entry<Double, Double> entry : someMap.entrySet()) {
double key = entry.getKey();
double value = entry.getValue();
if (key > latestInsertedKey) {
sumGreater += value;
++sumGreaterCount;
}
else if (key < latestInsertedKey) {
sumSmaller += value;
++sumSmallerCount;
}
}
if (sumGreaterCount != 0) {
greaterMean = sumGreater / sumGreaterCount;
}
else {
greaterMean = 0.0;
}
if (sumSmallerCount != 0) {
smallerMean = sumSmaller / sumSmallerCount;
}
else {
smallerMean = 0.0;
}
}
}
The question is if the calculations of the means can be dramatically improved with a TreeMap
or another datastrure such that one does not to have iterate over all keys on every insertion.
Is there an elegant way of reusing former calculations?