我正在尝试基于六个不同的值来实现唯一的hashCode。我的班级具有以下属性:
private int id_place;
private String algorithm;
private Date mission_date;
private int mission_hour;
private int x;
private int y;
我正在按以下方式计算hashCode:
id_place * (7 * algorithm.hashCode()) + (31 * mission_date.hashCode()) + (23 * mission_hour + 89089) + (x * 19 + 67067) + (y * 11 + 97097);
如何将其转换为唯一的hashCode?我不确定这是独一无二的...
答案 0 :(得分:3)
它不必唯一,也可以唯一。 if (callType == OUTGOING_CALL_END || callType == INCOMING_CALL_END) {
Cursor cursorCallLogs = getRecentCallLogs(context.getContentResolver());
if (cursorCallLogs != null) {
cursorCallLogs.moveToLast();
do {
try {
String callNumber = cursorCallLogs.getString(cursorCallLogs.getColumnIndex("number"));
callNumber = utilS.getPhoneNumber(callNumber);
utilS.log("Phone NUmber", callNumber);
duration = (cursorCallLogs.getInt(cursorCallLogs.getColumnIndex("duration")) * 1000);
utilS.log("durationCall", "" + duration);
} catch (Exception e) {
e.printStackTrace();
}
}
while (cursorCallLogs.moveToPrevious());
}
}
public static Cursor getRecentCallLogs(ContentResolver cr) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
return null;
} else {
return cr.query(CallLog.Calls.CONTENT_URI, null, null, null, android.provider.CallLog.Calls.DATE + " DESC limit 1");
}
}
返回一个hashCode()
(32位),这意味着如果您只有一个int
属性,而没有其他属性,则它可能是唯一的。
int
类可以(并且确实)具有唯一的Integer
,但是很少有其他类。
由于您具有多个属性,其中一些是hashCode()
,所以作为这些属性的函数的int
不能是唯一的。
您应该争取一个hashCode()
函数,该函数可以为您的属性的不同组合提供各种不同的值,但是它不能唯一。
答案 1 :(得分:1)
两个不同对象的HashCode不必唯一。根据{{3}}-
因此,您不必创建每次都返回不同哈希码的hashCode()函数。
答案 2 :(得分:1)
Unique is not a hard requirement, but the more unique the hash code is, the better.
Note first that the hash code in general is used for a HashMap, as index into a 'bucket.' Hence optimally it should be unique modulo the bucket size, the number of slots in the bucket. However this may vary, when the map grows.
But okay, towards an optimal hash code:
You can explore existing or generate plausible test data. One then can mathematically optimize your hash code function by their coincidental coefficients (7, 13, 23). This is linear optimisation, but one can also do it by simple trial-and-error: counting the clashes for varying (A, B, C).
//int[] coeffients = ...;
int[][] coefficientsCandidates = new int[NUM_OF_CANDIDATES][NUM_OF_COEFFS];
...
int[] collisionCounts = new int[NUM_OF_CANDIDATES];
for (Data data : allTestData) {
... update collisionCounts for every candidate
}
... take the candidate with smallest collision count
... or sort by collisionCounts and pick other candidates to try out
In general such evaluation code is not needed for a working hash code, but especially it might detect bad hash codes, were there is some pseudo-randomness going wrong. For instance if a factor is way too large for the range (weekday * 1000), so value holes appear.
But also one has to say in all honesty, that all this effort probably really is not needed.
答案 3 :(得分:0)
在Eclipse中,有一个函数可以为您生成方法public int hashCode()
。我使用了您提供的类属性,结果如下:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((algorithm == null) ? 0 : algorithm.hashCode());
result = prime * result + id_place;
result = prime * result + ((mission_date == null) ? 0 : mission_date.hashCode());
result = prime * result + mission_hour;
result = prime * result + x;
result = prime * result + y;
return result;
}
它看起来很像您的计算。但是,正如安迪·特纳(Andy Turner)在对问题的评论中指出的,而伊兰在回答中指出的那样,如果对象的每个实例的数量超过了可能的不同哈希码的最大数量,则无法简单地为其创建唯一的哈希码。
答案 4 :(得分:0)
由于您有多个字段,请使用:
public int hashCode() {
return Objects.hash(id_place, algorithm, mission_date, mission_hour, x, y);
}
如果objA.equals(objB)为true,则objA和objB必须返回相同的哈希码。 如果objA.equals(objB)为false,则objA和objB可能返回相同的哈希码,如果在这种情况下您的哈希算法碰巧返回了不同的hashCode,则出于性能方面的考虑。
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClassA classA = (ClassA) o;
return id_place == classA.id_place &&
mission_hour == classA.mission_hour &&
x == classA.x &&
y == classA.y &&
Objects.equals(algorithm, classA.algorithm) &&
Objects.equals(mission_date, classA.mission_date);
}