【问题标题】:Failure when testing Java HashMap implementation: Works for ~99% of values only测试 Java HashMap 实现时失败:仅适用于 ~99% 的值
【发布时间】:2017-03-14 05:13:53
【问题描述】:

我为 Java 中的简单整数字符串键值编写了一个 HashMap 实现。在尝试对其进行测试时,我编写了一些测试代码,并看到每次有 0-4 个值(在 5000 个样本中),测试都失败了。所以我然后将我的 HashMap 切换到 Java 默认实现,并注意到我的测试没有通过明显正确的实现。所以,在过去的几个小时里,我一直被挂断,试图找出我的测试失败的原因。有什么我想念的吗? (嗯,显然有……)

这是我的代码:

package HashMapOther;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;

public class StudentStore {
    private static SecureRandom random = new SecureRandom();
    static HashMap<Integer, String> map;
    static String[] studentNames;
    static int[] keys;
    static int magicNumber =5000; //still fails no matter size

    public static void main(String[] args){
        long startTime = System.currentTimeMillis();
        start();
        test();
        long endTime = System.currentTimeMillis();
        System.out.println("TIME: " + (endTime - startTime) + " ms");
    }

    public static void start(){
        studentNames = getStudents(); //random strings
        keys = getKeys(); //random integers
        map = new HashMap<Integer, String>(magicNumber, (float) 0.7);
        for(int i=0; i< magicNumber; i++){
            map.put(keys[i],studentNames[i]);
        }
    }

    public static int[] getKeys(){ //random integers
        int[] a = new int[magicNumber];
        for(int k=0; k< magicNumber; k++){
            a[k] = (int) (Math.random()*10000000+1);
        }
        return a;
    }

    public static String[] getStudents(){ //random strings
        String[] temp = new String[magicNumber];
        for(int i=0; i<magicNumber; i++){
            temp[i] = randomString();
        }
        return temp;
    }

    public static String randomString(){ //random string
         return new BigInteger(130, random).toString(32);
    }

    public static void test(){ //test code
        boolean passed = true;
        for(int i=0; i<magicNumber; i++){
            if(!studentNames[i].equals(map.get(keys[i]))){
                System.out.println("FAILURE: "+studentNames[i] + " " + map.get(keys[i]));
                passed = false;
            }
        }
        System.out.println("RESULT: " + passed);
    }
}

这是示例输出:

FAILURE: vq0cpihdsr4vfru6126suufvp4 3dq4shra6dps49psehqjuof4ib
FAILURE: lo2t73n1upqk6cmirdpui29ndt r6accv6ja5pkv723c5g0fe0d1q
RESULT: false
TIME: 94 ms

或者,在另一个运行中:

RESULT: true
TIME: 104 ms

还有一个:

FAILURE: c7848b9rejbtguj2d70llotvpu od7r0fjdphvdli6mgonbictg4d
FAILURE: 4ouk2cj9ipoo4hjrco8vd6p7e kt0u925jdn102cjul96thsfhcm
FAILURE: 2spd0u9lp7531hm09rqu8oncvm scrui9hl7tr0aq85at13oekgf7
RESULT: false
TIME: 99 ms

【问题讨论】:

  • 我注意到,如果我更改 getKeys() 函数以将键设置为唯一的 k 值而不是随机数,它可以解决问题。由于 HashMaps 必须有唯一的键,随机数与前一个数相等的微小机会足以使测试完全失败。我想如果将来有人需要,我会留下这篇文章。
  • 如您所见,重复键的可能性并不小,尽管它可能看起来违反直觉。这被称为birthday problem

标签: java testing hashmap hashtable


【解决方案1】:

您的密钥包含重复项(有时)。您可以通过评估map.put(...) 的返回值来检查这一点。如果地图中不存在密钥,则返回 null。如果映射中已经有一个具有指定键的条目,它将返回该条目的值。

public static void start(){
    studentNames = getStudents(); //random strings
    keys = getKeys(); //random integers
    map = new HashMap<Integer, String>(magicNumber, (float) 0.7);
    for(int i=0; i< magicNumber; i++){
        String previousValue = map.put(keys[i],studentNames[i]);
        if (previousValue != null) {
            System.out.println(keys[i] + " is a duplicate key");
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2020-07-07
    • 1970-01-01
    • 2018-08-28
    • 2022-11-23
    相关资源
    最近更新 更多