Java Arraylist来映射速度比较

时间:2015-06-17 11:13:10

标签: java arraylist foreach parallel-processing

我正在尝试将ArrayList转换为Treemap,因此我编写了一种基准来比较各种方法:

1)toMap in parallel stream

2)toMap in stream

3)forEach in stream

4)forEach并行流

5)for loop

如果ArrayList的大小很小(比如10,000),那么一切都很好,但是当大小很大时就说一百万,即使在9分钟之后它还在运行'forEach Parallel Stream'方法。我用try catch包围它,但它很干净。

我知道创建新线程会有一些开销,但parallelStream使用threadPool所以它应该是低的,对吗?

public class Set {
private String foo;
private int bar;

public Set(String foo, int bar) {
    this.foo = foo;
    this.bar = bar;
}

public String getFoo() {
    return foo;
}

public void setFoo(String foo) {
    this.foo = foo;
}

public int getBar() {
    return bar;
}

public void setBar(int bar) {
    this.bar = bar;
}

}

主要

public class Test {
TreeMap tr=new TreeMap();

public static void main(String[] args) {
    Test t = new Test();
    t.g();
}

public void g(){
    ArrayList<Set> ar=new ArrayList<>();
    for (int i = 0; i < 1_000_000; i++) {
        ar.add(new Set(UUID.randomUUID().toString(), new Random().nextInt()));
    }
    long start;
    long end;
    System.out.println("Parallel toMap");
    start=System.nanoTime();
    tr.putAll(ar.parallelStream().collect(Collectors.toMap(Set::getFoo, Set::getBar)));
    end=System.nanoTime();
    System.out.println(end-start);

    tr=new TreeMap();
    System.out.println("non-Parallel toMap");
    start=System.nanoTime();
    tr.putAll(ar.stream().collect(Collectors.toMap(Set::getFoo, Set::getBar)));
    end=System.nanoTime();
    System.out.println(end-start);

    tr=new TreeMap();
    System.out.println("non-Parallel forEach");
    start=System.nanoTime();
    ar.stream().forEach(product -> {
            tr.put(product.getFoo(), product.getBar());
        });
    end=System.nanoTime();
    System.out.println(end-start);

    tr=new TreeMap();
    System.out.println("Parallel forEach");
    start=System.nanoTime();
//HANGS SOMEWHERE HERE
    ar.parallelStream().forEach(product -> {
        try {
            tr.put(product.getFoo(), product.getBar());
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
        }

        });
    end=System.nanoTime();
    System.out.println(end-start);

    tr=new TreeMap();
    System.out.println("non-Parallel loop");
    start=System.nanoTime();
    for(Set product:ar)
        tr.put(product.getFoo(), product.getBar());

    end=System.nanoTime();
    System.out.println(end-start);
    }
}

大小为10_000的输出如下

Parallel toMap
130793206
non-Parallel toMap
21729202
non-Parallel forEach
7601349
Parallel forEach
3233395
non-Parallel loop
9744039

'for loop'是预期的最慢

'并行forEach'比预期的'非并行forEach'更快

'parallel toMap'慢于'非平行于map'5X ??什么?英特尔涡轮增压在发挥作用?

回到这一点,为什么当arraylist列表很大时,'并行蒸汽中的'每一个'会失败?

运行i7 2670QM,因此threadPool大小应为8

1 个答案:

答案 0 :(得分:1)

TreeMap不是线程安全的。因此,当从多个线程使用它时,所有的赌注都是关闭的。您可以在HashMap中获得无限循环。据推测,TreeMap在某种程度上表现得非常糟糕。

(基准测试:由于JVM“预热”的方式,你应该为每个测试开始一个新的过程。在一个过程中连续多次运行测试。)