【问题标题】:What are the chances for collision in sum of 2 hash codes?2个哈希码的总和发生冲突的可能性是多少?
【发布时间】:2017-08-24 10:39:45
【问题描述】:

如果在 Java 中添加 2 个其他哈希码生成一个新的哈希码,碰撞的概率是多少

例如:

Integer reportHashCode = reportFields.hashCode() + reportId.hashCode();

假设 Java 的哈希码是 32 位,我们可以忽略哈希码本身的正常冲突。

【问题讨论】:

  • 这种情况下哈希码是xored 是有原因的...
  • 我应该做异或而不是加法吗?
  • 我认为你的意思是“溢出”而不是“碰撞”
  • 哦!完全没想过..是啊..溢出的概率很大..对吧?
  • @StenalPJolly 使用xor 的另一个原因。但即使它溢出,哈希映射/集合中使用的哈希码也不关心溢出。 int 的溢出仍然是 int。

标签: java hash hashcode


【解决方案1】:

我会在这里XOR 而不是加法,因为 xor 有 50-50% 的分布 10

【讨论】:

【解决方案2】:

我们找出来怎么样?下面的程序将为您模拟这一点。请注意,总和的两个加数是随机生成的,因此两者都具有近似完整整数范围的概率。实际上,您求和的两个哈希码在整个整数空间中可能没有平坦的分布。可以调整程序来模拟它。

package hashcode;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;

public class HashCode {
    // Number of test cases
    private static final int TEST_CASES = 10_000_000;
    public static void main(String[] args) {
        // Random number generator
        Random rand = new Random();
        // Map from integers (result hash codes) to a list of addend pairs that formed those hash codes
        Map<Integer, Set<Pair>> hashCodesToComposites = new HashMap<>();
        // Number of collissions
        int collisions = 0;
        // Running simulations
        for (int i = 0; i < TEST_CASES; ++i) {
            if (TEST_CASES / 4 == i) {
                System.out.println("25 %");
            }
            if (TEST_CASES / 2 == i) {
                System.out.println("50 %");
            }
            if ((TEST_CASES * 3) / 4 == i) {
                System.out.println("75 %");
            }
            // Generating addends as random integers
            int first = rand.nextInt();
            int second = rand.nextInt();
            // The pair; its hash code is the sum of the above
            Pair pair = new Pair(first, second);
            // Did it occur before?
            if (hashCodesToComposites.containsKey(pair.hashCode())) {
                // Getting the set of addend pairs that created this hash code
                Set<Pair> composites = hashCodesToComposites.get(pair.hashCode());
                // Checking if by any chance the two random numbers happened to be the same (almost negligible)
                if (!composites.contains(pair)) {
                    // Actual collision from different numbers
                    collisions++;
                    // Adding to the set of composites
                    composites.add(pair);
                } // Same numbers; doesn't count as collision
            } else {
                // First occurrence of this hash code
                Set<Pair> composites = new HashSet<>();
                composites.add(pair);
                hashCodesToComposites.put(pair.hashCode(), composites);
            }
        }
        // Results
        System.out.println("Test cases: " + TEST_CASES);
        System.out.println("Collisions: " + collisions);
        System.out.println("Probability: " + ((double) collisions / (double) TEST_CASES));
    }
    private static class Pair {
        final int first;
        final int second;
        final int hashCode;
        Pair(int first, int second) {
            this.first = first;
            this.second = second;
            hashCode = first + second;
        }
        @Override
        public int hashCode() {
            return hashCode;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            final Pair other = (Pair) obj;
            return (this.first == other.first && this.second == other.second) || (this.first == other.second && this.second == other.first);
        }
    }
}

结果通常在 0.00115 左右。这意味着大约有 0.115% 的碰撞几率。我已经运行了下面的代码来找出随机整数之间发生冲突的几率。

package hashcode;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class HashCode2 {
    // Number of test cases
    private static final int TEST_CASES = 10_000_000;
    public static void main(String[] args) {
        // Random number generator
        Random rand = new Random();
        Set<Integer> hashCodes = new HashSet<>();
        // Number of collissions
        int collisions = 0;
        // Running simulations
        for (int i = 0; i < TEST_CASES; ++i) {
            if (TEST_CASES / 4 == i) {
                System.out.println("25 %");
            }
            if (TEST_CASES / 2 == i) {
                System.out.println("50 %");
            }
            if ((TEST_CASES * 3) / 4 == i) {
                System.out.println("75 %");
            }
            int next = rand.nextInt();
            if (hashCodes.contains(next)) {
                collisions++;
            } else {
                hashCodes.add(next);
            }
        }
        // Results
        System.out.println("Test cases: " + TEST_CASES);
        System.out.println("Collisions: " + collisions);
        System.out.println("Probability: " + ((double) collisions / (double) TEST_CASES));
    }
}

概率其实差不多。它仅略低,但仍四舍五入至 0.115 %。最后,我再次尝试了第一个程序,但在 Pair 的 hashCode 方法中使用了 xor 而不是 sum。结果?几乎是同样的事情。

因此,如果两个哈希码相加/异或的两个哈希码具有良好的分布,那么最终,对于两个哈希码和一个异或的和,您可以期望与随机整数非常接近的冲突率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多