我正在寻找为一组二维点计算哈希码的最佳方法(这样我就可以在哈希表中存储多边形).
有一些明显的方法可以做到这一点,例如连接字符串中的所有点坐标及其哈希码,但这将非常慢.
在速度/碰撞频谱的另一端,我还可以例如总结所有坐标,这将导致非常快的代码,但也会产生大量的碰撞.
计算一组点的哈希码的最佳方法是什么?
如果坐标是整数(对比实际坐标),最佳解是不同的吗?
编辑:我正在使用.net,因此哈希码应该是32位长.
Bert Bates和Kathy Sierra的SCJP 6学习指南在第554页(以及其他要求中)指出x.hashCode()!= y.hashCode()要求x.equals(y)== false.
但是Javadoc for Object没有明确提到这样的要求.Quote:
如果两个对象根据equals(Object)方法相等,则在两个对象中的每一个上调用hashCode方法必须产生相同的整数结果.
我应该采用Javadoc所说的物质含义,例如eq - > hc?那么这两个来源之间就不会有冲突.
在查看覆盖的不同选项时hashCode(),我被引导到Objects.hashCode(Object[])Google的guava-libraries(javadoc)中.javadoc表示它委托给Arrays.hashCode(Object[]).在许多不同的对象类型中使用此方法是否安全?这不容易发生哈希冲突,或者这不仅仅是因为容器通常只包含一种类型的对象?
举个简单的例子,考虑以下类,
public class Student {
private final String name;
public Student(String name) {
this.name = name;
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
}
public class Teacher {
private final String name;
public Teacher(String name) {
this.name = name;
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
}
public class HashCodeDriver {
public static void main(String[] args) {
final String name = "moe";
Student s = new Student(name); …Run Code Online (Sandbox Code Playgroud) // The worst possible legal hash function - never use!
@Override public int hashCode() { return 42; }
Run Code Online (Sandbox Code Playgroud)
这是合法的,因为它确保了相等的对象具有相同的哈希码.这很糟糕,因为它确保每个对象都具有相同的哈希码.因此,每个对象都会散列到同一个存储桶,并且散列表会退化为链接列表.应该以线性时间运行的程序改为以二次方运行.
我试图弄清楚如何(引自第47页,第9项,Joshua Bloch的Effective Java).
我看到它的方式如下(考虑以下代码):
Map<String, String> h = new HashMap<String,String>();
h.put("key1", "value1");
h.put("key1", "value2");
Run Code Online (Sandbox Code Playgroud)
什么与第二发生h.put("key1",...)命令如下:1.获取的散列码key1
2.获取到表示上述哈希码3.在该桶桶中,为每个对象,调用equals方法找到相同的对象是否存在.
这有点快,因为首先你找到对象的"组"(桶),然后找到实际的对象.
现在,当哈希码实现42为ALL对象返回相同的整数(如上所述)时,只有一个桶,并且需要在整个hashmap中的每个对象上逐个调用equals方法/哈希表.这与链表一样糟糕,因为如果链表中的对象也是如此,则必须逐个比较(调用equals)每个对象.
有人说,这就是哈希表退化为链表的原因吗?
(我为上述文本的冗长而道歉.我的概念中我不够清楚地说明它更简洁)
为什么每次运行java main时都有不同的hashCode值?查看下面的示例代码.
interface testInt{
public int getValue();
}
enum test implements testInt{
A( 1 ),
B( 2 );
private int value;
private test( int value ) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
Run Code Online (Sandbox Code Playgroud)
每次跑步,
public static void main( String[] args ) {
System.out.println( test.A.hashCode() );
}
Run Code Online (Sandbox Code Playgroud)
控制台上会有不同的打印值.为何不一致?
我正在实现一个可重用的DoubleEqualityComparer(具有自定义容差:"epsilon"构造函数参数),以简化LINQ的使用,使用double序列.例如:
bool myDoubleFound = doubles.Contains(myDouble, new DoubleEqualityComparer(epsilon: 0.01));
Run Code Online (Sandbox Code Playgroud)
实现GetHashCode的正确方法是什么?这是代码:
public class DoubleEqualityComparer : IEqualityComparer<double>, IEqualityComparer<double?>
{
private readonly double epsilon;
public DoubleEqualityComparer(double epsilon)
{
if (epsilon < 0)
{
throw new ArgumentException("epsilon can't be negative", "epsilon");
}
this.epsilon = epsilon;
}
public bool Equals(double x, double y)
{
return System.Math.Abs(x - y) < this.epsilon;
}
public int GetHashCode(double obj)
{
// ?
}
}
Run Code Online (Sandbox Code Playgroud)
PS:我总是可以返回相同的值(例如:GetHashCode(double obj){return 0;})以始终强制调用Equals(double,double)方法(不是很高效,我知道),但我记得这个当比较器与字典一起使用时,解决方案会导致问题...
我正在搞乱一些hashCode + equals + Map的东西,发现了一些东西......很奇怪.
摘录如下:
class Obj {
String n;
Obj(String n) {this.n = n;}
public int hashCode() {return 0;}
public boolean equals(Object o) {return false;} // no instance of this class
// equals any other instance
}
Run Code Online (Sandbox Code Playgroud)
然后我做了这样的事情:
java.util.Map<Obj,String> map = new java.util.HashMap<Obj,String>();
Obj o1 = new Obj("1");
Obj o11 = new Obj("1");
Obj o2 = new Obj("2");
map.put(o1,"val 1");
map.put(o11,"val 2");
map.put(o2,"val 3");
p("size = " + map.size()); // obviously 3
p(map.get(new Obj("1"))); // obviously null
p(map.get(o1)); …Run Code Online (Sandbox Code Playgroud) 在Java中,我们使用了hashCode()和equals()等方法,地图使用这些方法来标识每个对象.C++没有这样的基本方法,默认情况下每个对象都实现.
地图现在如何使用自定义对象作为键值?
编辑:没有重复,因为它特别针对那些特定于Java的接口方法,以前没有用C++做过的人会寻找
我知道这似乎已经讨论过,答案是肯定的,String.hashCode可以为不同的字符串生成相同的值,但是不太可能(Java的hashCode可以为不同的字符串生成相同的值吗?).但它确实发生在我的应用程序中.
以下代码将生成相同的哈希码:-347019262(jave 1.7.25)
String string1 = "/m/06qw_";
String string2="/m/0859_";
System.out.println(string1+","+string1.hashCode());
System.out.println(string2+","+string2.hashCode());
Run Code Online (Sandbox Code Playgroud)
在这种情况下我确实需要哈希码,我想用它来为字符串生成唯一的主键.看来我做得不对.有什么建议吗?
非常感谢!
考虑以下:
Map<Class<?>, Object> myMap = new HashMap<Class<?>, Object>();
Foo fooObject = New Foo();
myMap.put(fooObject.getClass(), fooObject)
Run Code Online (Sandbox Code Playgroud)
请注意,java.lang.Class本身并不实现hashCode()方法,而是隐式地从java.lang.Object继承它.我在JDK 1.8中验证了这一点.
可以java.lang.Class安全地用作钥匙java.util.HashMap吗?将myMap.get(Foo.class)始终返回,我把喜欢的价值观myMap.put(fooObject.getClass(), fooObject)?考虑该软件具有各种类加载器和序列化机制.它仍然会是相同的结果吗?如果不是......会有什么选择?