elasticsearch,hashcode,identifier,Java,Hash,elasticsearch,Hashcode,Identifier" /> elasticsearch,hashcode,identifier,Java,Hash,elasticsearch,Hashcode,Identifier" />

Java对象的唯一id

Java对象的唯一id,java,hash,elasticsearch,hashcode,identifier,Java,Hash,elasticsearch,Hashcode,Identifier,我正在将java对象索引到Elasticsearch中。下面是一个类的结构: public Class Document{ private String name; private double value; private Date date; private Map<String, String> attributes; //getters and setters } 公共类文档{ 私有字符串名称; 私人双重价值; 私人日期; 私有地图属

我正在将java对象索引到Elasticsearch中。下面是一个类的结构:

public Class Document{
    private String name;
    private double value;
    private Date date;
    private Map<String, String> attributes;
    //getters and setters
}
公共类文档{
私有字符串名称;
私人双重价值;
私人日期;
私有地图属性;
//接球手和接球手
}
在为任何对象编制索引之前,我希望计算/派生对象的唯一id,该id应基于这些成员的值。如果我用相同的名称、日期、值和属性值构造另一个对象(即,如果键值对的数量和值相同),那么ID也应该相同

目前,我正在使用
Objects.hash(Object…Objects)
计算hashCode并将该hashCode设置为id。它似乎工作正常。它为具有相同属性值的对象返回相同的整数。但是,考虑到java中int的文档数量和范围,hashcode可能/可能不相同(这将导致重复文档)

有其他解决办法吗?我们可以根据这些值创建字母数字字符串(或其他东西)吗

提前感谢。

除非将对象本身用作键,否则无法完全避免碰撞。。。如果您想这样做,您可以将您的值序列化为一个字节序列,即8个字节的
双字节
8个字节的
日期
(因为内部表示是
长的
,以及任意数量的字节,具体取决于
名称的长度

最明智的做法是使用这些值计算hashCode,然后在发生冲突时逐个比较每个成员以确保相等。这就是java
Hashtable
的工作原理

如果你想继续创建你的“绝对唯一的标识符”

byte[] defoUnique = new byte[24 + name.size()];
byte[] dateBytes = Long.toByteArray(date.getTime());
for (int i = 0 ; i < 8 ; i++) defoUnique[i] = dateBytes[i];
byte[] valueBytes = Long.toByteArray(Double.doubleToLongBits(value));
for (int i = 0 ; i < 8 ; i++) defoUnique[i+8] = valueBytes[i];
byte[] nameBytes = name.getBytes();
for (int i = 0 ; i < nameBytes.length ; i++) defoUnique[i+16] = nameBytes[i];

/* Make byte sequence into alphanumeric string */
String identifierString = Base64.getEncoder().encodeToString(defoUnique);
byte[]defoUnique=新字节[24+name.size()];
byte[]dateBytes=Long.toByteArray(date.getTime());
对于(inti=0;i<8;i++)defoUnique[i]=dateBytes[i];
byte[]valueBytes=Long.toByteArray(Double.doubleToLongBits(value));
对于(int i=0;i<8;i++)defoUnique[i+8]=valueBytes[i];
byte[]nameBytes=name.getBytes();
对于(int i=0;i
您应该重写equals()和hashcode()。(不同时重写两者是常见的错误)

下面是一个例子。其思想是为每个对象创建一个哈希代码,并测试是否相等(无论您是否取回对象)

例如:

    // from http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html
     public class Person {
       String name;
       int age;
       boolean smoker;
       int id;  // this is your bit

       public int hashCode() {
         // you pick a hard-coded, randomly chosen, non-zero, odd number
         // ideally different for each class
         return new HashCodeBuilder(17, 37).
           append(name).
           append(age).
           append(smoker).
           toHashCode();
       }
     }

  public boolean equals(Object obj) {
  // the next 3 ifs are a 'short' circuit'
       if (obj == null) { return false; }
       if (obj == this) { return true; }
       if (obj.getClass() != getClass()) {
         return false;
       }

       // the meat of it
       MyClass rhs = (MyClass) obj;

       boolean sameClass = new EqualsBuilder()
                     .appendSuper(super.equals(obj))
                     .append(field1, rhs.field1)
                     .append(field2, rhs.field2)
                     .append(field3, rhs.field3)
                     .isEquals();

       //  here set/update your id
           if (sameClass){
                 this.id = rhs.id
           }

           return sameClass 
          }

最终得到了这样的结果:

/**
     * Sets the id of document by calculating hash for individual elements
     */
    public void calculateHash(){
        ByteBuffer byteBuffer = ByteBuffer.allocate(16);
        byteBuffer.putInt(Objects.hashCode(name));
        byteBuffer.putInt(Objects.hashCode(date));
        byteBuffer.putInt(Objects.hashCode(value));
        byteBuffer.putInt(Objects.hashCode(attributes));
        super.setId(DigestUtils.sha512Hex(byteBuffer.array())); 
        byteBuffer.clear();
    }
因此,基本上,我计算单个元素的散列,将它们填充到字节数组中,然后计算该元素的SHA-1散列。因此,冲突的可能性非常小。即使一个散列发生冲突,其他散列也不太可能发生冲突(因为它是4个散列的组合)。我认为冲突的可能性是(1/4十亿)^4这对我来说太好了:) 例如,int散列可以有40亿个值,因此,一个值的概率为1/(40亿),而其他位置具有相同数字的概率为1/4b x 1/4b x 1/4b x 1/4b,即(1/4b)^4,如果我没有错的话

不知道这是不是最合适的方式。但这似乎奏效了


谢谢

对象的任何元素都是独一无二的吗?这些对象中的每一个都需要某种类型的id。所有元素都不是唯一的。但是,所有元素的组合都应该是唯一的。你的意思是担心所有哈希代码的大小是否足以容纳大量对象吗?是的。正是我的意思!int:默认情况下,int数据类型是32位带符号2的补码整数,最小值为-2^31,最大值为2^31-1。(20亿美元)。我不知道如何将对象本身用作键。。我想要的是一个数字(或字母数字)id,它对于一个对象来说是“有意义的”唯一的。i、 e.如果存在具有相同值的另一个对象,则id将相同。但是,在插入对象时,我将无法访问存储在ES中的现有数据(对象)。因此,我将生成一个id。如果有另一个对象具有相同的值,我的id将与其id匹配,因此,我的对象将不会被插入。这就是我想要的。谢谢。好的,在这种情况下,您可以使用我提供给您的
字节[]
数组,并使用base64对其进行编码:我不确定修改
equals
中的对象是否是一个好主意。。。