You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Java的hashCode()方法使杰卡德相似度达标向量获相同哈希值

针对杰卡德相似度阈值的hashCode()重写方案

以下是几种无需依赖minhash或候选对、仅通过向量自身特征生成哈希的实现思路,目标让杰卡德相似度≥0.5的向量大概率进入同一哈希桶:


方法1:基于核心特征子集的哈希映射

思路

杰卡德相似度≥0.5意味着两个向量的交集大小≥差集大小。我们可以提取向量中值为1的特征索引,选取其中固定比例(对应阈值,比如0.5)的核心特征,仅对这些特征计算哈希值。当两个向量有足够多的重叠核心特征时,哈希值碰撞的概率会显著提升。

Java实现

import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

public class BinaryVector {
    private final int[] vector;
    private static final double SIM_THRESHOLD = 0.5;

    public BinaryVector(int[] vector) {
        this.vector = vector.clone();
    }

    @Override
    public int hashCode() {
        List<Integer> oneIndices = new ArrayList<>();
        // 收集所有值为1的维度索引
        for (int i = 0; i < vector.length; i++) {
            if (vector[i] == 1) {
                oneIndices.add(i);
            }
        }

        if (oneIndices.isEmpty()) {
            return 0;
        }

        // 选取核心特征数量:取总1的数量×阈值,至少1个
        int coreCount = Math.max(1, (int) Math.ceil(oneIndices.size() * SIM_THRESHOLD));
        coreCount = Math.min(coreCount, oneIndices.size());

        int hash = 0;
        // 对前coreCount个1的索引做哈希聚合(用31乘积累加,减少碰撞)
        for (int i = 0; i < coreCount; i++) {
            hash = hash * 31 + oneIndices.get(i);
        }

        return hash;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BinaryVector that = (BinaryVector) o;
        return Arrays.equals(vector, that.vector);
    }
}

优缺点

  • ✅ 计算高效,对稀疏向量友好
  • ❌ 依赖1的索引顺序,若向量是无序集合,需先对1的索引排序

方法2:基于维度权重的哈希聚合

思路

给每个维度分配一个固定的随机权重,计算向量中所有1对应的权重总和,然后保留总和的高位部分作为哈希值。杰卡德相似度高的向量,重叠维度多,权重总和的高位更易一致,从而哈希值相同。

Java实现

import java.util.Arrays;

public class BinaryVector {
    private final int[] vector;
    private static final double SIM_THRESHOLD = 0.5;
    // 全局维度权重(与向量维度一致,固定种子保证可复现)
    private static final int[] DIM_WEIGHTS = initWeights(6);

    private static int[] initWeights(int dimension) {
        int[] weights = new int[dimension];
        java.util.Random random = new java.util.Random(42);
        for (int i = 0; i < dimension; i++) {
            weights[i] = random.nextInt();
        }
        return weights;
    }

    public BinaryVector(int[] vector) {
        this.vector = vector.clone();
    }

    @Override
    public int hashCode() {
        long weightSum = 0;
        for (int i = 0; i < vector.length; i++) {
            if (vector[i] == 1) {
                weightSum += DIM_WEIGHTS[i];
            }
        }

        // 根据阈值保留高位:阈值0.5对应保留16位
        int keepBits = (int) Math.ceil(32 * SIM_THRESHOLD);
        keepBits = Math.max(8, Math.min(32, keepBits));
        
        // 提取高位并转为无符号整数
        int hash = (int) (weightSum >> (32 - keepBits));
        hash &= ((1 << keepBits) - 1);
        return hash;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BinaryVector that = (BinaryVector) o;
        return Arrays.equals(vector, that.vector);
    }
}

优缺点

  • ✅ 利用所有特征信息,相似向量的哈希碰撞概率更高
  • ❌ 需要提前初始化全局权重,权重的随机性会影响效果

方法3:基于哈希桶收缩的简化方案

思路

先计算向量的原始哈希值(比如用所有1的索引聚合),然后将哈希值映射到一个更小的范围(通过取模)。阈值越高,哈希桶的数量越少,相似向量进入同一桶的概率就越高。

Java实现

import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

public class BinaryVector {
    private final int[] vector;
    private static final double SIM_THRESHOLD = 0.5;
    // 阈值0.5对应将哈希收缩到2^16个桶
    private static final int BUCKET_COUNT = 1 << 16;

    public BinaryVector(int[] vector) {
        this.vector = vector.clone();
    }

    @Override
    public int hashCode() {
        List<Integer> oneIndices = new ArrayList<>();
        for (int i = 0; i < vector.length; i++) {
            if (vector[i] == 1) {
                oneIndices.add(i);
            }
        }

        // 计算原始哈希
        int originalHash = 0;
        for (int idx : oneIndices) {
            originalHash = originalHash * 31 + idx;
        }

        // 收缩到指定数量的哈希桶
        return Math.abs(originalHash) % BUCKET_COUNT;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BinaryVector that = (BinaryVector) o;
        return Arrays.equals(vector, that.vector);
    }
}

优缺点

  • ✅ 实现最简单,无需额外逻辑
  • ❌ 会引入更多不相似向量的哈希碰撞,需要根据业务平衡桶的数量

注意事项

所有方案都无法做到100%准确(因为相似性的传递性问题,比如A与B、B与C相似但A与C不相似,只能保证A/B同桶或B/C同桶,无法完美区分),但可以通过调整参数(比如核心特征比例、保留位数、桶数量)来优化准确率。

内容的提问来源于stack exchange,提问作者dydy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:00:58