英文:
How to get second biggest distance from a Hashmap?
问题
我正试图在Java中的哈希映射中获取最大和第二大的距离。
基本上,从一个包含(x,y)值的哈希映射中,我计划选择一个点,将其设置为固定点,并计算与所有其他点相关的距离。在计算了所有可能的距离之后,我将固定点更改为哈希映射中的下一个元素。通过这个过程,我旨在在哈希映射中按距离获取最大和第二大的值。
HashMap<Integer, Integer> corners = getPotentialCorners(image);
HashMap<Integer, Integer> extremeCorners = new HashMap<>();
int Blue = new Color(0, 0, 255).getRGB();
int currentNumberX;
int currentNumberY;
int pivotVarX;
int pivotVarY;
double distance;
double Highest = 0;
double Highest2 = 1;
int xHighest = 0;
int yHighest = 0;
int xHighest2 = 0;
int yHighest2 = 0;
for (int i : corners.keySet()) {
currentNumberX = (i);
currentNumberY = corners.get(currentNumberX);
for (int j : corners.keySet()) {
pivotVarX = j;
pivotVarY = corners.get(pivotVarX);
distance = Math.abs(Math.sqrt(Math.pow((pivotVarX - currentNumberX), 2) + Math.pow((pivotVarY - currentNumberY), 2)));
if (pivotVarX != currentNumberX) {
if ((Highest > Highest2)) {
xHighest = currentNumberX;
yHighest = currentNumberY;
Highest2 = distance;
}
if (distance > Highest2) {
Highest2 = distance;
xHighest2 = currentNumberX;
yHighest2 = currentNumberY;
}
}
}
}
通过这段代码,我进行了调试,我总是得到一个正确的点,而另一个点总是(0,0)。我知道问题在于获取第二高点(Highest2、XHighest2、YHighest2)的过程,但我不知道如何修复它。
英文:
I am trying to get the biggest and second biggest distance in a Hashmap in Java.
Basically, from a hashmap populated with (x,y) values, I plan to pick a point, set it as a fixed point and calculate distance with this point in relation to all the other points. After all possible distances are calculated, I change the fixed point to the next element in the HashMap. With this process, I aim to get the biggest and second biggest value in a hashmap distance-wise.
HashMap<Integer, Integer> corners = getPotentialCorners(image);
HashMap<Integer, Integer> extremeCorners = new HashMap<>();
int Blue = new Color(0, 0, 255).getRGB();
int currentNumberX;
int currentNumberY;
int pivotVarX;
int pivotVarY;
double distance;
double Highest = 0;
double Highest2 = 1;
int xHighest = 0;
int yHighest = 0;
int xHighest2 = 0;
int yHighest2 = 0;
for (int i : corners.keySet()) {
currentNumberX = (i);
currentNumberY = corners.get(currentNumberX);
for (int j : corners.keySet()) {
pivotVarX = j;
pivotVarY = corners.get(pivotVarX);
distance = Math.abs(Math.sqrt(Math.pow((pivotVarX - currentNumberX), 2) + Math.pow((pivotVarY - currentNumberY), 2)));
if (pivotVarX != currentNumberX) {
if ((Highest > Highest2)) {
xHighest = currentNumberX;
yHighest = currentNumberY;
Highest2 = distance;
}
if (distance > Highest2) {
Highest2 = distance;
xHighest2 = currentNumberX;
yHighest2 = currentNumberY;
}
}
}
}
With this code, I debugged it, and I always get one correct point, and another point is ALWAYS (0,0). I know the issue lies with my process of getting the second highest point (Highest2, XHighest2,YHighest2), but I do not know how to fix it.
答案1
得分: 1
正如其他人指出的那样,与其使用HashMap,最好使用List<Point>
,你可以轻松地进行迭代:
for (Point p: myList) {
...
}
或者如果你需要更多地控制要迭代的元素,你可以使用整数计数器:
for (int j = i+1; j < corners.size(); j++) {
Point p = corners.get(j);
...
}
而不是必须使用keySet()
和get()
,以及在相同的 bin 上具有相同 x 值映射时出现的所有问题。
另外,还有一些微小的速度改进可以实现:
- 无需使用缓慢的
Math.sqrt()
函数(或Math.abs()
,因为平方根始终为正数),因为你只是在比较较大/较小的距离。你可以直接比较平方距离。 - 最新的Java编译器知道如何优化
Math.pow(int, 2)
,但为了确保你不会得到函数调用的开销,你可以通过编写:(p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.x-q.y)
来帮助编译器。
将current
和pivot
重命名为p
和q
以减少代码长度,你的代码将会是这样的:
List<Point> corners = getPotentialCorners(image);
Double highest = null;
Double highest2 = null;
Point highestP = null, highestQ = null;
Point highestP2 = null, highestQ2 = null;
for (int i = 0; i < corners.size()-1; i++) {
Point p = corners.get(i);
for (int j = i+1; j < corners.size(); j++) {
Point q = corners.get(j);
double distanceSq = (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
if (highest == null || distanceSq >= highest) {
// shift highest to second highest
highest2 = highest;
highestP2 = highestP;
highestQ2 = highestQ;
highest = distanceSq;
highestP = p;
highestQ = q;
} else if (highest2 == null || distanceSq > highest2) {
highest2 = distanceSq;
highestP2 = p;
highestQ2 = q;
}
}
}
英文:
As others pointed out, instead of a HashMap, it is better to use List<Point>
which you can easily iterate as:
for (Point p: myList) {
...
}
or if you need more control on which elements to iterate over you can use an integer counter:
for (int j = i+1; j < corners.size(); j++) {
Point p = corners.get(j);
...
}
instead of having to use keySet()
and get()
and all the problems with identical x-values mapping on the same bin.
Also, there are some trivial speed improvements possible:
- No need to use the slow
Math.sqrt()
function (orMath.abs()
as square root is always positive) since you are only comparing larger/smaller distances. You can just compare the squared distances. - The latest Java compiler knows how to optimize
Math.pow(int, 2)
, but to make sure you don't get the overhead of a function call, you can help the compiler by writing:(p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.x-q.y)
Renaming current
and pivot
to p
and q
for conciseness, your code would look like:
List<Point> corners = getPotentialCorners(image);
Double highest = null;
Double highest2 = null;
Point highestP = null, highestQ = null;
Point highestP2 = null, highestQ2 = null;
for (int i = 0; i < corners.size()-1; i++) {
Point p = corners.get(i);
for (int j = i+1; j < corners.size(); j++) {
Point q = corners.get(j);
double distanceSq = (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
if (highest == null || distanceSq >= highest) {
// shift highest to second highest
highest2 = highest;
highestP2 = highestP;
highestQ2 = highestQ;
highest = distanceSq;
highestP = p;
highestQ = q;
} else if (highest2 == null || distanceSq > highest2) {
highest2 = distanceSq;
highestP2 = p;
highestQ2 = q;
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论