为什么Groovy的Map比Array更好?

时间:2015-04-30 19:54:13

标签: java arrays groovy hashmap

我今天遇到了这个问题,我无法弄清楚为什么groovy数组在变大时不会比Map更好。

在我的例子中,我创建了一个Map(LinkedHashMap)和一个String数组(String [])。然后我从0迭代到10 ^ 7,将i插入Map或Array。我做了10次,以确保异常值不会导致结果混乱。

int max = 10**7
int numTests = 10

long totalTimeMap = 0
long totalTimeArray = 0

numTests.times{
    long start = System.currentTimeMillis()

    Map m = [:]
    max.times {
        m[it] = "${it}"
    }

    long end = System.currentTimeMillis()
    totalTimeMap += (end-start)
}

numTests.times {
    long start = System.currentTimeMillis()

    String[] s = new String[max]
    max.times{
        s[it] = "${it}"
    }

    long end = System.currentTimeMillis()
    totalTimeArray += (end-start)
}

println "Map: ${totalTimeMap}"
println "Array: ${totalTimeArray}"

输出是意料之外的,因为Map具有比Array更好的性能:

Map: 49361
Array: 101123

我在java中做了同样的实验:

public static void main(String[] args) {

        int max = 10000000;
        int numTests = 10;

        long totalTimeMap = 0;
        long totalTimeArray = 0;

        for(int i=0; i<numTests; i++){
            long start = System.currentTimeMillis();

            Map m = new LinkedHashMap();
            for(int j=0; j<max; j++){
                m.put(j, "" + j);
            }

            long end = System.currentTimeMillis();
            totalTimeMap += (end-start);
        }

        for(int i=0; i<numTests; i++){
            long start = System.currentTimeMillis();

            String[] s = new String[max];
            for(int j=0; j<max; j++){
                s[j] = "" + j;
            }

            long end = System.currentTimeMillis();
            totalTimeArray += (end-start);
        }

        System.out.println("Map: " + totalTimeMap);
        System.out.println("Array: " + totalTimeArray);
    }

并且预期输出(阵列比Map快):

Map: 34564
Array: 12822

我的问题是:为什么使用Groovy时Map比Array快?

1 个答案:

答案 0 :(得分:20)

当您在Groovy中将String添加到数组时,您将创建一个模板化的String,然后将其转换回java字符串(在模板完成之后),因为它必须适合{ {1}}

对于String[]版本,您只是存储模板化字符串,因此无需进行评估...

以下基准测试代码:

Map

我们不在Array方法中使用GroovyStrings,给我结果:

@Grab('org.gperfutils:gbench:0.4.3-groovy-2.4')

int max = 10000

new groovyx.gbench.BenchmarkBuilder().run {
    'Array' {
        String[] s = new String[max]
        max.times { int idx ->
            s[idx] = Integer.toString(idx)
        }  
    }
    'List' {
        def s = []
        max.times{
            s << "${it}"
        }  
    }
    'Map' {
        Map m = [:]
        max.times {
            m[it] = "${it}"
        }
    }
}.prettyPrint()