Java 为什么实证结果与TreeSet';最后一种方法是什么?
我们正在对Java数据结构进行一些实证测试,得到了一些我们无法正确解释的结果 例如,当我们测试TreeSet的最后一个方法时,时间要求应该是恒定的,当TreeSet的大小超过30000后,我们会在运行时间上得到一个提升。我们运行最后一种方法,将树集合中的元素数量增加1000倍,然后取结果的中值 有关守则如下:Java 为什么实证结果与TreeSet';最后一种方法是什么?,java,algorithm,benchmarking,Java,Algorithm,Benchmarking,我们正在对Java数据结构进行一些实证测试,得到了一些我们无法正确解释的结果 例如,当我们测试TreeSet的最后一个方法时,时间要求应该是恒定的,当TreeSet的大小超过30000后,我们会在运行时间上得到一个提升。我们运行最后一种方法,将树集合中的元素数量增加1000倍,然后取结果的中值 有关守则如下: import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.ma
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Collections;
import jxl.write.WriteException;
public class TestRunner {
public void test(Testable testeCase, String outputFileName, Integer... initArgs){
ExcelWriter excel = null;
try {
excel = new ExcelWriter(outputFileName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
int measurementsPoints = 35;
//calculate median to every dataset size
for(int j = 0; j < measurementsPoints; j++){
int testCount = 1000;
long startTime;
long endTime;
//double sum = 0;
ArrayList<Integer> results = new ArrayList<Integer>();
for (int i = 0; i < testCount; i++) {
//initialize tested data structure
testeCase.initTestRun(initArgs);
startTime = threadMxBean.getCurrentThreadCpuTime();
// run tested method
testeCase.runTestMethod();
endTime = threadMxBean.getCurrentThreadCpuTime();
results.add((int)(endTime - startTime));
}
Collections.sort(results);
excel.addNumber(j, 5, new Double(initArgs[0]));
excel.addNumber(j, 6, new Double(results.get(testCount / 2)));
//increase the size of the data structure 10, 15, 20, 30, 40, 60, 80...
if(j % 2 == 0){
initArgs[0] = (int)(initArgs[0] * 1.5);
}
else{
initArgs[0] = (int)(initArgs[0] / 3 * 4);
}
}
try {
excel.write();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
import java.util.TreeSet;
public class TreeSetLastTest implements Testable {
private TreeSet<Integer> values;
@Override
public void initTestRun(Integer... integers) {
Integer initialCapacity = integers[0];
values = new TreeSet<Integer>();
for(int i = Integer.MIN_VALUE; i < Integer.MIN_VALUE + initialCapacity; i++){
values.add(i);
}
}
@Override
public void runTestMethod() {
values.last();
}
}
import java.io.IOException;
导入java.lang.management.ManagementFactory;
导入java.lang.management.ThreadMXBean;
导入java.util.ArrayList;
导入java.util.Collections;
导入jxl.write.WriteException;
公共类测试运行程序{
公共无效测试(可测试的testeCase、字符串outputFileName、整数…initArgs){
ExcelWriter excel=null;
试一试{
excel=新的ExcelWriter(outputFileName);
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
ThreadMXBean ThreadMXBean=ManagementFactory.getThreadMXBean();
int测量点=35;
//计算每个数据集大小的中值
对于(int j=0;j
当树状集合中的元素数量在10-30000个元素之间时,测量的中值为3000纳秒。当树状集合的大小增加到120000个元素时,测量的中值为13000纳秒,然后在元素数量增加超过100万个时保持不变。那么,是什么原因导致增加,或者时间单位太小了,以至于差异在现实中毫无意义。谢谢你的帮助。我想这是值得回答的 您认为
TreeSet
具有O(1)last()
的假设是错误的。首先,文档中没有说明这类内容,事实上java中的TreeSet
是使用一个红黑树的实现TreeMap
实现的
红黑树类似于AVL树,因为它可以保证O(logn)
进行查找,也就是说,确保树不会退化为链表。基本上,您的last()
查找具有O(logn)
复杂性,因此随着它变大,复杂性会变差
可能是因为缓存,甚至可能是分页效果,您无法直接在基准测试中看到O(logn)
这与LinkedList和Array类似——理论上,链表有很多功能,实际上,链表是现代CPU上最糟糕的数据结构之一。毕竟常数因素很重要,内存访问模式是很大的常数因素。我想这是值得回答的 您认为
TreeSet
具有O(1)last()
的假设是错误的。首先,文档中没有说明这类内容,事实上java中的TreeSet
是使用一个红黑树的实现TreeMap
实现的
红黑树类似于AVL树,因为它可以保证O(logn)
进行查找,也就是说,确保树不会退化为链表。基本上,您的last()
查找具有O(logn)
复杂性,因此随着它变大,复杂性会变差
可能是因为缓存,甚至可能是分页效果,您无法直接在基准测试中看到O(logn)
这与LinkedList和Array类似——理论上,链表有很多功能,实际上,链表是现代CPU上最糟糕的数据结构之一。毕竟常数因子很重要,内存访问模式是很大的常数因子。你的计算机有什么内存?交换内存会出现吗发挥作用?Java的内存管理开始使用不同的策略了吗?所有这些都可以解释。它没有回答您的问题,但您应该阅读。您从何处得到树集中的
最后一个应该是常量的想法?快速查看源代码表明该假设是错误的。树集在内部使用树映射,它本身是一个红黑树实现。因此我们有O(logn)
作为get。内存做什么