为什么HashSet解决方案要找慢的独特字符?

时间:2016-10-29 17:31:27

标签: java

我制作了一个O(n ^ 2)和O(n)解决方案来寻找独特的角色,并且很想知道性能差异。我原以为HashSet解决方案会将O(n ^ 2)解决方案从水中吹出来,但它实际上比只做嵌套循环慢。

import java.util.HashSet;

class AllUnique
{
    // O(n^2) solution
    static boolean isUnique(String str)
    {
        int ind = 0;
        boolean unique = true;
        while (ind != str.length())
        {
            int inner_ind = ind + 1;
            while (inner_ind != str.length())
            {
                if (str.charAt(ind) == str.charAt(inner_ind))
                {
                    unique = false;
                }
                inner_ind++;
            }
            ind++;
        }
        return unique;
    }

    // O(n) solution
    static boolean isUnique2(String str)
    {
        HashSet<Character> set = new HashSet<>();
        for (int i = 0; i < str.length(); i++)
        {
            set.add(str.charAt(i));
        }
        return set.size() == str.length();
    }
}

使用一个非常简单的驱动程序来测试毫秒差异: 公共课程{

    public static void main(String[] args) {
        String[] stringArr = new String[10000];
        for (int i = 0; i < 10000; i++)
        {
            stringArr[i] = "wefwefwefwefwefalkjegb";
        }
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++)
        {
            AllUnique.isUnique(stringArr[i]);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Total execution time: " + (endTime-startTime) + "ms");

        long startTime2 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++)
        {
            AllUnique.isUnique2(stringArr[i]);
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("Total execution time: " + (endTime2-startTime2) + "ms");
    }
}

散列Character对象真的需要那么久吗?

通常,嵌套循环解决方案比HashSet解决方案快5-10分钟。

2 个答案:

答案 0 :(得分:1)

在您的基准测试中不公平的一件事是HashSet不与嵌套循环代码在相同的实体上运行。 Java autoboxing将原始char值包装到Character个对象。这会产生额外的成本,例如GC和查找内置缓存中的部分内容。

另一个是基准测试很难做到正确。其中一个很酷的工具是JMH。它在野外有很多例子,例如关于维护者blog

答案 1 :(得分:0)

O(n)比无限数据集上的O(n ^ 2)快。在实践中,n的有限值不一定是真的。你的体型不够大,看不出差异。尝试制作stringArr [i] biger。像1000多长。

如果你想要实用的建议,用

替换set.add(str.charAt(i))
if(set.contains(str.charAt(I)) return false;
set.add(str.charAt(i));