2016-12-29 66 views
0
import net.openhft.chronicle.map.ChronicleMap; 

import java.io.File; 
import java.io.Serializable; 
import java.util.Map; 
import java.util.concurrent.ConcurrentHashMap; 

public class App { 

    public static void main(String[] args) throws Exception { 

     Map<Point, Point> map1 = new ConcurrentHashMap<>(); 

     ChronicleMap<Point, Point> map2 = ChronicleMap 
       .of(Point.class, Point.class) 
       .name("map") 
       .averageKey(new Point(10, 10)) 
       .averageValue(new Point(10, 10)) 
       .entries(50) 
       .createPersistedTo(new File("c:/temp/map/param.dat")); 

     Point key = new Point(12, 12); 
     key.hashCode(); 

     map1.put(key, key); 
     map2.put(key, key); 

     System.out.println("ConcurrentHashMap.get returned " + map1.get(new Point(12, 12))); 
     System.out.println("ChronicleMap.get returned " + map2.get(new Point(12, 12))); 
    } 
} 

class Point implements Serializable { 
    private int x = 0; 
    private int y = 0; 
    private int _hash = 0; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 


    @Override 
    public String toString() { 
     return super.toString() + " {" + x + "," + y + "}"; 
    } 

    @Override 
    public int hashCode() { 
     _hash = 1; 
     _hash = _hash * 17 + x; 
     _hash = _hash * 31 + y; 
     return _hash; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if(obj instanceof Point) { 
      return (x == ((Point) obj).getX()) && (y == ((Point) obj).getY()); 
     } 
     return false; 
    } 
} 

正如您在上面的示例中看到的,ChronicleMap行为与ConcurrentHashMap(与HashMap相同)有点不同,因为它无法使用hashCode或equals查找关键字。为什么ChronicleMap不使用hashCode或等于查找键?

有人可以指出可以做些什么来解决这个问题吗?

UPDATE; 当被执行时,该程序将返回以下结果:

ConcurrentHashMap.get returned [email protected] {12,12} 
ChronicleMap.get returned null 
+0

*无关:*为什么'_hash'是一个字段(又名实例变量)?它应该只是一个*局部变量*。 – Andreas

+0

*“正如你在上面的例子中看到的,ChronicleMap的行为有点不同”*我必须失明,因为我看不到这一点。 *问题中的哪些地方我们会看到?我们应该在代码的输出中看到吗?如果是这样,编辑问题并显示输出,否则我们看不到它。 – Andreas

+0

我已经更新了执行结果的例子。 – helloWorld998

回答

2

ChronicleMap串行化密钥和开出的字节的64位散列。

使用64位散列,因为该映射针对非常大量的键设计,例如,数十亿,而当你拥有数百万个密钥时,32位散列往往具有很高的冲突率。

它也可以使用更先进的散列策略,如这些https://github.com/OpenHFT/Zero-Allocation-Hashing

注意:使用序列化是这样做的最有效的方式,但从来没有少是适用于本示例。

+2

为了澄清,问题是'_hash'是一个最初为'0'的*字段*,所以对于get()调用它是0,对于put()调用是0 (因为'hashCode()'被调用),因此键不一样。 **解决方案:**删除字段,它不应该在那里,因为它应该只是'hashCode()'方法中的局部变量。 – Andreas

+1

@Andreas如果它是一个缓存的值,它可以被做成'transient',尽管使它成为一个局部变量将是最好的。 –

+2

是的,但这只会解决序列化问题,而不是并发问题。如果不是'_hash'字段,那么这个类是一个不错的行为良好的不可变对象。即使'x'和'y'没有被声明为'final',它们*有效*最终。 – Andreas

相关问题