了解已排序和未排序的 ArrayList<Object> 的 HashCode
Understanding HashCode of sorted & unsorted ArrayList<Object>
我正在做一个小项目,遇到了一个问题(?)我真的无法解释。这是我的代码:
====主要内容=====
Beacon b1 = new Beacon("192.168.0.12", 72.0);
Beacon b4 = new Beacon("192.168.0.13", 72.0);
Beacon b2 = new Beacon("192.168.0.24", 84.0);
Beacon b3 = new Beacon("192.168.0.5", 64.0);
ArrayList<Beacon> alBeacons = new ArrayList();
alBeacons.add(b4);
alBeacons.add(b2);
alBeacons.add(b1);
alBeacons.add(b3);
Room room = new Room("Testroom", alBeacons);
====信标====
public class Beacon {
String sIP;
private int ID = 0;
private Double RSSi;
public Beacon(String sIP, double RSSi){
this.sIP = sIP;
this.RSSi = RSSi;
setID();
}
private void setID(){
String sTemp[] = sIP.split("\.");
this.ID = Integer.parseInt(sTemp[sTemp.length-1]);
}
public String getsID(){
return String.valueOf(ID);
}
public int getID(){
return ID;
}
}
====房间====
public Room(String sName, ArrayList<Beacon> alBeacons){
System.out.println("Unsorted: " + alBeacons.hashCode());
for(Beacon b: alBeacons){
System.out.println(b.getID());
}
alBeacons.sort(new Comparator<Beacon>() {
@Override
public int compare(Beacon o1, Beacon o2) {
return o1.getID() - o2.getID();
}
});
System.out.println("Sorted: " + alBeacons.hashCode());
for(Beacon b: alBeacons){
System.out.println(b.getID());
}
}
现在我遇到的问题是,在未排序状态下,无论信标如何插入 ArrayList,我总是得到相同的 HashCode(),1498918675。一旦我对它们进行排序,我就会得到一个不同的 HashCode,这是有道理的。但现在的问题是,根据 ArrayList 最初的排序方式,我在排序后得到了不同的 HashCode。这是 .sort() 固有的,还是我对实数排序的修复破坏了它?
编辑:以下是一些输出示例:
Unsorted: 1498918675
13
24
12
5
Sorted: 341854239
5
12
13
24
Unsorted: 1498918675
24
5
12
13
Sorted: 638040239
5
12
13
24
Unsorted: 1498918675
12
5
24
13
Sorted: 1060992495
5
12
13
24
根据内容和顺序计算的列表哈希码。
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
一个List
的hashCode必须(接口内的合约)是:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
因此,元素的排序对于确定哈希码很重要:为已排序或未排序的列表获取不同的哈希码是正常的。
但是你说 'depending on how the ArrayList was sorted in the first place, I get a different HashCode after sorting it' :所以基本上你说:
- 案例一:
你从 [b, a, c] 开始,它被排序为 [a, b, c] 你得到 hashCode X
- 案例2:
你从 [c, b, a] 开始,它被排序为 [a, b, c] 你得到 hashCode Y
如果 Beacon
class 的 hashcode
方法依赖于 Beacon
的字段,则不应发生这种情况。您还没有覆盖 hashCode
因此它是 "typically implemented by converting the internal address of the object into an int" 的基本实现(来自 javadoc)。
要解决您的问题,您应该在 Beacon
中定义自己的 hashCode
:
public int hashCode() {
final int prime = 31;
int res = (sIP != null) ? sIP.hashCode() : 1;
res = res * prime + ID;
return res * prime + Double.hashCode(RSSi);
}
我正在做一个小项目,遇到了一个问题(?)我真的无法解释。这是我的代码:
====主要内容=====
Beacon b1 = new Beacon("192.168.0.12", 72.0);
Beacon b4 = new Beacon("192.168.0.13", 72.0);
Beacon b2 = new Beacon("192.168.0.24", 84.0);
Beacon b3 = new Beacon("192.168.0.5", 64.0);
ArrayList<Beacon> alBeacons = new ArrayList();
alBeacons.add(b4);
alBeacons.add(b2);
alBeacons.add(b1);
alBeacons.add(b3);
Room room = new Room("Testroom", alBeacons);
====信标====
public class Beacon {
String sIP;
private int ID = 0;
private Double RSSi;
public Beacon(String sIP, double RSSi){
this.sIP = sIP;
this.RSSi = RSSi;
setID();
}
private void setID(){
String sTemp[] = sIP.split("\.");
this.ID = Integer.parseInt(sTemp[sTemp.length-1]);
}
public String getsID(){
return String.valueOf(ID);
}
public int getID(){
return ID;
}
}
====房间====
public Room(String sName, ArrayList<Beacon> alBeacons){
System.out.println("Unsorted: " + alBeacons.hashCode());
for(Beacon b: alBeacons){
System.out.println(b.getID());
}
alBeacons.sort(new Comparator<Beacon>() {
@Override
public int compare(Beacon o1, Beacon o2) {
return o1.getID() - o2.getID();
}
});
System.out.println("Sorted: " + alBeacons.hashCode());
for(Beacon b: alBeacons){
System.out.println(b.getID());
}
}
现在我遇到的问题是,在未排序状态下,无论信标如何插入 ArrayList,我总是得到相同的 HashCode(),1498918675。一旦我对它们进行排序,我就会得到一个不同的 HashCode,这是有道理的。但现在的问题是,根据 ArrayList 最初的排序方式,我在排序后得到了不同的 HashCode。这是 .sort() 固有的,还是我对实数排序的修复破坏了它?
编辑:以下是一些输出示例:
Unsorted: 1498918675
13
24
12
5
Sorted: 341854239
5
12
13
24
Unsorted: 1498918675
24
5
12
13
Sorted: 638040239
5
12
13
24
Unsorted: 1498918675
12
5
24
13
Sorted: 1060992495
5
12
13
24
根据内容和顺序计算的列表哈希码。
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
一个List
的hashCode必须(接口内的合约)是:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
因此,元素的排序对于确定哈希码很重要:为已排序或未排序的列表获取不同的哈希码是正常的。
但是你说 'depending on how the ArrayList was sorted in the first place, I get a different HashCode after sorting it' :所以基本上你说:
- 案例一: 你从 [b, a, c] 开始,它被排序为 [a, b, c] 你得到 hashCode X
- 案例2: 你从 [c, b, a] 开始,它被排序为 [a, b, c] 你得到 hashCode Y
如果 Beacon
class 的 hashcode
方法依赖于 Beacon
的字段,则不应发生这种情况。您还没有覆盖 hashCode
因此它是 "typically implemented by converting the internal address of the object into an int" 的基本实现(来自 javadoc)。
要解决您的问题,您应该在 Beacon
中定义自己的 hashCode
:
public int hashCode() {
final int prime = 31;
int res = (sIP != null) ? sIP.hashCode() : 1;
res = res * prime + ID;
return res * prime + Double.hashCode(RSSi);
}