Question: does anybody know of a Java implementation (I have too little time/knowledge to develop my own right now) of a collection with the following characteristics?
- fast add
- fast random-access remove
- fast minimum value
- duplicates
Condensed (oversimplified) version of use case is:
- I have a class that keeps track of 'time', call it
TimeClass
- Events start at monotonically increasing times (times are not unique), but can finish in any order
- When events start they report their start time to
TimeClass
- When events finish they again report their start time to
TimeClass
TimeClass
adds an event's start time to a collection* when the event starts (fast add)TimeClass
removes an event's start time from that collection* when the event finishes (fast random-access remove)TimeClass
is capable of reporting the lowest not-yet-finished start time (fast minimum value)
* think of collection as: Collection<Time> implements Comparable<Time>
Because I'm not sure what the runtime behavior of my system (the system in which TimeClass
lives) will be, I've quickly benchmarked the following scenarios using these collections: TreeMultiSet
(Guava), MinMaxPriorityQueue
(Guava), ArrayList
.
Note, depending on the collection used, min value is achieved in different ways (remember elements are added in increasing order): TreeMultiSet.firstEntry().getElement()
, MinMaxPriorityQueue.peekFirst()
, ArrayList.get(0)
.
ADD 1,000,000:
TreeMultiSet
: 00:00.897 (m:s.ms)List
: 00:00.068 (m:s.ms)MinMaxPriorityQueue
: 00:00.658 (m:s.ms)
ADD 1, REMOVE 1, REPEAT 1,000,000 TIMES:
TreeMultiSet
: 00:00.673 (m:s.ms)List
: 00:00.416 (m:s.ms)MinMaxPriorityQueue
: 00:00.469 (m:s.ms)
ADD 10,000 IN SEQUENTIAL ORDER, REMOVE ALL IN SEQUENTIAL ORDER:
TreeMultiSet
: 00:00.068 (m:s.ms)List
: 00:00.031 (m:s.ms)MinMaxPriorityQueue
: 00:00.048 (m:s.ms)
ADD 10,000 IN SEQUENTIAL ORDER, REMOVE ALL IN RANDOM ORDER:
TreeMultiSet
: 00:00.046 (m:s.ms)List
: 00:00.352 (m:s.ms)MinMaxPriorityQueue
: 00:00.888 (m:s.ms)
Current thoughts:
I'm leaning towards using TreeMultiSet
as it has the most stable performance and seems to degrade most gracefully. I WOULD LOVE MORE SUGGESTIONS
Thanks
--EDIT--
Example pseudo code of ADD ALL IN SEQUENTIAL ORDER, REMOVE ALL IN RANDOM ORDER:
benchmark(){
int benchmarkSize = 1000000;
int benchmarkRepetitions = 100;
Duration totalDuration = Duration.fromMilli(0);
TimeClass timeClass = new TimeClassImplementation();
for (int i = 0; i < benchmarkRepetitions; i++)
totalDuration += benchmarkRun(timeClass,benchmarkSize);
System.out.println(totalDuration);
}
Duration benchmarkRun(TimeClass timeClass, int count){
List<Time> times = createMonotonicallyIncreasingTimes(count)
// monotonically increasing times to add from
List<Time> timesToAddFrom = copy(times)
// random times to remove from
List<Time> timesToRemoveFrom = shuffleUniformly(copy(times))
Time startTime = now()
// add all times
for(Time time: timesToAddFrom) {
Time min = timeClass.addTimeAndGetMinimumValue(time);
// don't use min value
}
// remove all times
for(Time time: timesToRemoveFrom) {
Time min = timeClass.removeTimeAndGetMinimumValue(time);
// don't use min value
}
Time finishTime = now()
return finishTime - startTime;
}