【发布时间】:2014-09-24 11:57:57
【问题描述】:
问题:是否有人知道具有以下特征的集合的 Java 实现(我现在没有时间/知识来开发自己的)?
- 快速添加
- 快速随机访问删除
- 快速最小值
- 重复
用例的浓缩(过度简化)版本是:
- 我有一个跟踪“时间”的课程,称之为
TimeClass - 事件以单调递增的时间开始(时间不是唯一的),但可以按任意顺序结束
- 当活动开始时,他们会将开始时间报告给
TimeClass - 活动结束后,他们再次向
TimeClass报告开始时间 -
TimeClass在事件开始时将事件的开始时间添加到集合*(快速添加) -
TimeClass在事件结束时从该集合*中删除事件的开始时间(快速随机访问删除) -
TimeClass能够报告尚未完成的最低开始时间(快速最小值)
* 将 collection 视为:Collection<Time> implements Comparable<Time>
因为我不确定我的系统(TimeClass 所在的系统)的运行时行为是什么,所以我使用这些集合快速对以下场景进行了基准测试:TreeMultiSet (Guava)、@987654331 @(番石榴),ArrayList。
注意,根据使用的集合,最小值以不同的方式实现(记住元素是按递增顺序添加的):TreeMultiSet.firstEntry().getElement()、MinMaxPriorityQueue.peekFirst()、ArrayList.get(0)。
加 1,000,000:
-
TreeMultiSet: 00:00.897 (m:s.ms) -
List: 00:00.068 (m:s.ms) -
MinMaxPriorityQueue: 00:00.658 (m:s.ms)
添加 1,删除 1,重复 1,000,000 次:
-
TreeMultiSet: 00:00.673 (m:s.ms) -
List: 00:00.416 (m:s.ms) -
MinMaxPriorityQueue: 00:00.469 (m:s.ms)
按顺序添加 10,000,按顺序删除所有:
-
TreeMultiSet: 00:00.068 (m:s.ms) -
List: 00:00.031 (m:s.ms) -
MinMaxPriorityQueue: 00:00.048 (m:s.ms)
按顺序添加 10,000 个,按随机顺序删除所有:
-
TreeMultiSet: 00:00.046 (m:s.ms) -
List: 00:00.352 (m:s.ms) -
MinMaxPriorityQueue: 00:00.888 (m:s.ms)
目前的想法:
我倾向于使用TreeMultiSet,因为它具有最稳定的性能并且似乎降级最优雅。 我希望得到更多建议
谢谢
--编辑--
示例伪代码按顺序添加,按随机顺序删除所有:
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;
}
【问题讨论】:
-
“我已经快速对以下场景进行了基准测试”。你是怎么做到的?向我们展示您的基准代码。
-
最小值取决于值本身还是添加顺序?
-
@Tichodroma,两点:(1)我现在添加了一些伪代码(假设传入的 timeClass 实例具有不同的底层实现,使用不同的集合)(2)有一个错误我运行 LinkedList 两次而从未运行 MinMaxPriorityQueue 的代码,我现在重新运行以获取 MinMaxPriorityQueue 编号
-
@udalmik 值本身 Time 实现 Comparable
-
坏消息是,Java 中的基准测试比预期的要困难得多。任何花费几分之一秒的测量结果本质上只是(低质量)随机数,无法用于任何事情,仅与实际使用性能略有相关(在代码预热后等)。见this question。
标签: java data-structures collections guava