java8学习笔记(二): list与map遍历效率浅析

1,891 阅读4分钟

引言

在工作中大部分时间都会涉及到对list的遍历,java8为我们提供的的stream方便我们对集合的操作。我在工作中使用流式操作也非常多,使用越发熟练变多,不禁让我对list与map遍历效率产生疑问,究竟哪种效率更高呢?现在就让我们一探究竟吧。

前期准备

测试类如下:

@Data
@Builder
@ToString
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Person {
    Integer age;
    String name;
    String skin;
}

比对效率

思路非常简单,使用list与map对同一个集合分别进行遍历,在集合元素不同个数是,通过遍历时间即可辨别效率。话不多说,上代码~

public class PerformanceTest {

    public static void main(String[] args) {
        List<Person> list = new ArrayList<>(2<<6);
        for (int i = 0; i < 100000; i++) {
            list.add(Person.builder().age(i).name("name" + i).skin("yellow" + i).build());
        }
        long firstTime = Instant.now().toEpochMilli();
        list.parallelStream().forEach(x -> {
        });
        long secondTime = Instant.now().toEpochMilli();
        System.out.println("list遍历耗时为:" + (secondTime - firstTime));
        Map<Integer, Person> map = list.parallelStream().collect(Collectors.toConcurrentMap(Person::getAge, Function.identity()));
        System.out.println("list转为map耗时为:" + (Instant.now().toEpochMilli() - secondTime));
        map.forEach((k,v) -> {
        });
        long thirdTime = Instant.now().toEpochMilli();
        System.out.println("map遍历循环耗时为:" + (thirdTime - secondTime));
    }

}

上述程序分别测试了集合个数为:50,100, 200, 300, 400,1000,10000, 100000时的效率,测试结果为多次测试汇总。

size = 50 : list遍历耗时为:99,list转为map耗时为:12,map遍历循环耗时为:13
size = 100 : list遍历耗时为:53,list转为map耗时为:5,map遍历循环耗时为:5
size = 200 : list遍历耗时为:158,list转为map耗时为:7,map遍历循环耗时为:7
size = 300 : list遍历耗时为:123,list转为map耗时为:9,map遍历循环耗时为:9
size = 400 : list遍历耗时为:121,list转为map耗时为:6,map遍历循环耗时为:7
size = 1000 : list遍历耗时为:113,list转为map耗时为:7,map遍历循环耗时为:9
size = 10000 : list遍历耗时为:117,list转为map耗时为:22,map遍历循环耗时为:28
size = 20000 : list遍历耗时为:127,list转为map耗时为:17,map遍历循环耗时为:22
size = 30000 : list遍历耗时为:155,list转为map耗时为:20,map遍历循环耗时为:25
size = 40000 : list遍历耗时为:147,list转为map耗时为:32,map遍历循环耗时为:38
size = 50000 : list遍历耗时为:139,list转为map耗时为:32,map遍历循环耗时为:38
size = 60000 : list遍历耗时为:110,list转为map耗时为:35,map遍历循环耗时为:46
size = 70000 : list遍历耗时为:103,list转为map耗时为:38,map遍历循环耗时为:48
size = 80000 : list遍历耗时为:92,list转为map耗时为:29,map遍历循环耗时为:39
size = 90000 : list遍历耗时为:79,list转为map耗时为:54,map遍历循环耗时为:66
size = 100000 : list遍历耗时为:68,list转为map耗时为:96,map遍历循环耗时为:122
size = 1000000 : list遍历耗时为:552,list转为map耗时为:1356,map遍历循环耗时为:1589
size = 10000000 : list遍历耗时为:120,list转为map耗时为:6054,map遍历循环耗时为:6264

通过上述结果,我们可以简单总结如下:在数据量低于1000000时,当数据量为40000时,list的遍历速度达到顶峰,之后逐步减少,而map的遍历速度却一直在增长。当数据量高于1000000时,list转换为map的速度及map遍历的速度都显著增加。

但是为啥性能会变化,这个还要后续在研究!今天做个简单总结 ...

总结

因此,在处理数据体量不是很大时,建议先将list转换为map,再使用map的流式表达式遍历,可提升效率,并且java8的流式表达式提供多种操作方式。了解stream常用使用方式 click me