我有一个CSV文件,其中有将近65000行,分为3个值(经度、纬度和海拔(。我要做的是创建一个数组[][],它是经度乘纬度的。经度和纬度是双精度的,它们不能用于索引,但不知道如何将它们映射到索引。所以我想它会是这样的:
array[0][0] = altitude_value[0];
array[0][1] = altitude_value[1];
·
·
·
array[i][j] = altitude_value[z];
值如下:
-179.75,-89.75,-1965
-179.75,-89.5,-2011
-179.75,-89.25,-2140
-179.75,-89,-2162
我试图实现的是根据经纬度参数获得海拔高度,给出以下方法:
public double getAltitude(double longitude, double latitude) {
return array[array.indexOf(longitude)][array.indexOf(latitude)] = altitude_value;
}
如果你坚持使用2D数组,你可以这样映射你的值:
array[0][0] = longitude[0];
array[0][1] = latitude[0];
array[0][2] = altitude[0];
array[1][0] = longitude[1];
array[1][1] = latitude[1];
array[1][2] = altitude[1];
...
array[n][0] = longitude[n];
array[n][1] = latitude[n];
array[n][2] = altitude[n];
一个更好的解决方案是创建一个Position
类来保存一个经度、纬度和海拔高度。然后您就可以拥有一个Position
实例的1D数组。
编辑后添加:
这里有一个简单的例子。我用你的四条位置线作为输入。
-179.75,-89.75,-1965
-179.75,-89.5,-2011
-179.75,-89.25,-2140
-179.75,-89,-2162
我收到了以下经度-179.75,纬度-89.5的输出。
-2011
我对我创建的1D阵列进行了简单的线性搜索。对于4个值,它足够快。对于6.5万个值,您可以运行我的代码并查看它需要多长时间。正如我所说,如果你按照经度、纬度对数组进行排序,并使用二进制搜索,你将在大约32次测试中得到正确的结果。
这是我使用的完整的可运行代码。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PositionApp {
public static void main(String[] args) {
new PositionApp().run();
}
private Position[] positions;
public void run() {
try {
int count = readCSVFile();
this.positions = new Position[count];
processCSVFile();
int altitude = getAltitude(-179.75, -89.5);
System.out.println(altitude);
} catch (IOException e) {
e.printStackTrace();
}
}
public int readCSVFile() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream("/sample.csv")));
int count = 0;
String line = reader.readLine();
while (line != null) {
count++;
line = reader.readLine();
}
reader.close();
return count;
}
public void processCSVFile() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream("/sample.csv")));
int count = 0;
String line = reader.readLine();
while (line != null) {
String[] parts = line.split(",");
double longitude = Double.valueOf(parts[0]);
double latitude = Double.valueOf(parts[1]);
int altitude = Integer.valueOf(parts[2]);
positions[count++] = new Position(longitude, latitude, altitude);
line = reader.readLine();
}
reader.close();
}
public int getAltitude(double longitude, double latitude) {
for (int index = 0; index < positions.length; index++) {
if ((positions[index].getLongitude() == longitude) &&
(positions[index].getLatitude() == latitude)) {
return positions[index].getAltitude();
}
}
return Integer.MIN_VALUE;
}
public class Position {
private final int altitude;
private final double longitude;
private final double latitude;
public Position(double longitude, double latitude, int altitude) {
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
}
public int getAltitude() {
return altitude;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
}
}
为了简单起见,假设经度和纬度为0-1,增量为0.25(n = 5
增量(。然后你的地图会看起来像这样:
0, 0 -> a0
0, 0.25 -> a1
...
0.25, 0 -> a5
...
然后,您可以使用[longitude * 4][latitude * 4]
为任何经度和纬度值确定的索引[x][y]
来访问海拔高度。
显然,对于您的实际示例,在查询数组时需要将经度和纬度值偏移为零,但这不应该是太多的额外工作。
Java基元数组没有一个"indexOf";方法,例如您提供的getAltitude方法中显示的方法。您需要将其强制转换为List,或者使用java.util.Array等辅助类来获得该功能。
看看如何使用数组索引,您可能会更好地使用另一种数据类型,例如Map of Maps。这些其他数据类型的基本功能在概念上与2D数组相同,但与基元数组相比,允许更多类型的索引数据类型。
使用地图的基本实现:
Map<Double, Map<Double,Double> longitudeMap; //Read your CSV file into this data structure
public double getAltitude(double longitude, double latitude) {
Map<Double> latitudeMap = longitudeMap.get(longitude);
double altitude = latitudeMap.get(latitude);
return altitude;
}
这可以使用链式get简化为更少的行。它还需要一些NULL保护,但应该传达基于Map的解决方案而不是基元数组解决方案的jit。
如果要使用经度和纬度索引的基元数组,那么您基本上是自己手动构建映射(什么值映射到数据数组中的索引(,并且需要将该索引存储在一个单独的对象中,该对象可以是一个数组,但最好是List。您的";indexOf";在getAltitude中,它将进入索引对象,而不是数据数组。