Java中ArrayList/Collections方法的代码速度慢
我正在尝试组合一个2D KD树实现。在这一点上,它可以工作,但运行时间会爆炸,超过10万个点。100k需要15秒,1e6需要30分钟。起初,我认为瓶颈是排序以找到中值,但似乎是使用subList和addAll方法。任何改进的建议都会很好 谢谢Java中ArrayList/Collections方法的代码速度慢,java,collections,arraylist,sublist,Java,Collections,Arraylist,Sublist,我正在尝试组合一个2D KD树实现。在这一点上,它可以工作,但运行时间会爆炸,超过10万个点。100k需要15秒,1e6需要30分钟。起初,我认为瓶颈是排序以找到中值,但似乎是使用subList和addAll方法。任何改进的建议都会很好 谢谢 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.R
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
public class KDtree {
//****************************************************
//setting up a data set for input
//****************************************************
public kdLite() {
long startTime = System.currentTimeMillis() / 1000;
//select random values to generate data set
double[][] dataSet = new double[2][100000];
for (int i = 0; i < 100000; i++) {
dataSet[0][i] = (Math.random() * (99));
dataSet[1][i] = (Math.random() * (99));
//System.out.print(dataSet[0][i] + "\t" + dataSet[1][i] + "\n");
}
//System.out.print("\n");
//setup a point class for simple data manipulation and add data to it
ArrayList<Point> preSorted = new ArrayList<Point>();
for (int i = 0; i < dataSet[0].length; i++) {
Point point = new Point(i, dataSet[0][i], dataSet[1][i], 0);
preSorted.add(point);
}
//split and sort the list
ArrayList<Point> outList = splitList(preSorted);
// add the list to the binary tree structure
BinaryST buildKD = new BinaryST();
for (int i = 0; i < outList.size(); i++) {
buildKD.insertNode(outList.get(i));
}
long endTime = System.currentTimeMillis() / 1000;
System.out.println((int) (endTime - startTime) / 60 + " Minutes and " + (endTime - startTime) + " Seconds");
// buildKD.printTree();
//****************************************************
}
//****************************************************
//the brunt of the code. this method takes a list of Point objects
//solves for the axis to split on and cuts the list into 2^i segments
//****************************************************
public ArrayList<Point> splitList(ArrayList<Point> arrToSplit) {
ArrayList<ArrayList<Point>> splitList = new ArrayList<ArrayList<Point>>();
ArrayList<Point> Meds = new ArrayList<Point>();
int axis = 0;
int toSplit = 0;
double maxXdif = 0;
double maxYdif = 0;
//populate first bucket
splitList.add(new ArrayList<Point>());
for (int i = 0; i < arrToSplit.size(); i++) {
splitList.get(0).add(arrToSplit.get(i));
}
for (int slice = 0; slice < arrToSplit.size(); slice++) {
//get first bucket that has more than one value then use it first
for (int i = 0; i < splitList.size(); i++) {
if (splitList.get(i).size() >= 1) {
toSplit = i;
if (splitList.get(i).size() > 1) {
break;
}
}
}
if (splitList.get(toSplit).size() > 1) {
sortByX(splitList.get(toSplit));
maxXdif = Math.abs(splitList.get(toSplit).get(0).x - splitList.get(toSplit).get(splitList.get(toSplit).size() - 1).x);
sortByY(splitList.get(toSplit));
maxYdif = Math.abs(splitList.get(toSplit).get(0).y - splitList.get(toSplit).get(splitList.get(toSplit).size() - 1).y);
//arrange by splitting axis according to largest distance to find splitting axis
if (maxXdif > maxYdif) {
axis = 0;
sortByX(splitList.get(toSplit));
} else {
axis = 1;
sortByY(splitList.get(toSplit));
}
//solve for median point .. arbitrate if no point lies on axis (uneven split)
int Med = (int) Math.floor(splitList.get(toSplit).size() / 2);
//take median point, assign splitting axis
splitList.get(toSplit).get(Med).axis = axis;
Meds.add(splitList.get(toSplit).get(Med));
splitList.get(toSplit).remove(Med);
---- >>>>>> PROBLEM CODE
// relocate all points except median to new list, delete the median value
List<Point> head = splitList.get(toSplit).subList(Med, splitList.get(toSplit).size());
splitList.add(new ArrayList<Point>());
splitList.get(splitList.size() - 1).addAll(head);
head.clear();
splitList.get(toSplit).subList(Med - 1, splitList.get(toSplit).size() - 1).clear();
} else {
//these are the leftover points so ordering is arbitrary
//randomize axis to ensure balance
Random random = new Random();
int randomAxis = random.nextInt(2 - 0);
Meds.add(splitList.get(toSplit).get(0));
splitList.get(toSplit).get(0).axis = randomAxis;
splitList.remove(toSplit);
}
}
return Meds;
}
//****************************************************
//****************************************************
//sorting methods for sorting a list by x or y
//must use comparator to sort by custom object attributes
//****************************************************
private ArrayList<Point> sortByX(ArrayList<Point> xList) {
Collections.sort(xList, new Comparator<Point>() {
public int compare(Point p1, Point p2) {
return Double.compare(p1.getX(), p2.getX());
}
});
return xList;
}
private ArrayList<Point> sortByY(ArrayList<Point> yList) {
Collections.sort(yList, new Comparator<Point>() {
public int compare(Point p1, Point p2) {
return Double.compare(p1.getY(), p2.getY());
}
});
return yList;
}
//****************************************************
}
import java.util.ArrayList;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.List;
导入java.util.Random;
公共类KDtree{
//****************************************************
//为输入设置数据集
//****************************************************
公共kdLite(){
long startTime=System.currentTimeMillis()/1000;
//选择随机值以生成数据集
double[]数据集=新的double[2][100000];
对于(int i=0;i<100000;i++){
数据集[0][i]=(Math.random()*(99));
数据集[1][i]=(Math.random()*(99));
//System.out.print(数据集[0][i]+“\t”+数据集[1][i]+“\n”);
}
//系统输出打印(“\n”);
//为简单的数据操作设置点类并向其添加数据
ArrayList预排序=新建ArrayList();
对于(int i=0;i=1){
toSplit=i;
if(splitList.get(i).size()>1){
打破
}
}
}
if(splitList.get(toSplit.size()>1){
sortByX(splitList.get(toSplit));
maxXdif=Math.abs(splitList.get(toSplit).get(0).x-splitList.get(toSplit).get(splitList.get(toSplit).size()-1.x);
sortByY(splitList.get(toSplit));
maxYdif=Math.abs(splitList.get(toSplit).get(0).y-splitList.get(toSplit).get(splitList.get(toSplit).size()-1.y);
//按最大距离分轴排列,找到分轴
if(maxXdif>maxYdif){
轴=0;
sortByX(splitList.get(toSplit));
}否则{
轴=1;
sortByY(splitList.get(toSplit));
}
//求解中间点。如果轴上没有点(不均匀分割),则进行仲裁
int Med=(int)Math.floor(splitList.get(toSplit.size()/2);
//取中点,指定分割轴
splitList.get(toSplit).get(Med).axis=axis;
Meds.add(splitList.get(toSplit.get(Med));
splitList.get(toSplit).remove(Med);
---->>>>>>>>问题代码
//将除中间值以外的所有点重新定位到新列表,删除中间值
List head=splitList.get(toSplit).subList(Med,splitList.get(toSplit.size());
添加(新的ArrayList());
splitList.get(splitList.size()-1).addAll(head);
头。清除();
splitList.get(toSplit).subList(Med-1,splitList.get(toSplit).size()-1).clear();
}否则{
//这些是剩余点,因此排序是任意的
//随机化轴以确保平衡
随机=新随机();
int randomAxis=random.nextInt(2-0);
药物添加(splitList.get(toSplit.get(0));
splitList.get(toSplit).get(0).axis=randomAxis;
splitList.remove(toSplit);
}
}
退药;
}
//****************************************************
//****************************************************
//按x或y对列表进行排序的排序方法
//必须使用comparator按自定义对象属性排序
//****************************************************
专用ArrayList sortByX(ArrayList XLList){
Collections.sort(xList,newcomparator(){
公共整数比较(点p1,点p2){
返回Double.compare(p1.getX(),p2.getX());
}
});
返回xList;
}
私有ArrayList sortByY(ArrayList-yList){
Collections.sort(yList,newcomparator(){
ArrayList<Point>(int capacity);