针对同一个集合,用 stream 操作两次得到两个不同条件筛选出来的集合和map,和一次for循环就搞定搞定的效率对比。
虽然stream写起来链式操作很舒服,但效率在不同数据量下的体现效果是不一样的,以下为我的测试代码:
@Test
public void testStreamAndFor() {
List studentList = new ArrayList<>();
// 初始数据量
int listSize = 100000;
// 测试次数,以便求出平均运行时长
int testTimes = 5;
for (int i = 0; i < listSize; i++) {
Student student = new Student();
student.setId(i + 1);
student.setStudentName("name" + i);
student.setAge(i);
studentList.add(student);
}
BigDecimal streamTotalRunTime = new BigDecimal("0");
BigDecimal forTotalRunTime = new BigDecimal("0");
for (int i = 0; i < testTimes; i++) {
Instant streamStart = Instant.now();
Map idMapOfStream = studentList.stream()
.collect(Collectors.toMap(Student::getId, v -> v));
List studentAgeListOfStream = studentList.stream()
.map(Student::getAge)
.collect(Collectors.toList());
long streamRunTime = Duration.between(streamStart, Instant.now()).toMillis();
System.out.println("第" + (i + 1) + "次:" + "stream 耗时:" + streamRunTime);
Instant forStart = Instant.now();
int size = studentList.size();
Map idMapOfFor = new HashMap<>(size);
List ageListOfFor = new ArrayList<>();
for (Student student : studentList) {
idMapOfFor.put(student.getId(), student);
ageListOfFor.add(student.getAge());
}
long forRunTime = Duration.between(forStart, Instant.now()).toMillis();
System.out.println("第" + (i + 1) + "次:" + "for 耗时:" + forRunTime);
streamTotalRunTime = streamTotalRunTime.add(new BigDecimal(streamRunTime + ""));
forTotalRunTime = forTotalRunTime.add(new BigDecimal(forRunTime + ""));
}
System.out.println("list长度为:" + listSize + ", 总共测试次数:" + testTimes);
System.out.println("stream总运行时间(ms) :" + streamTotalRunTime);
System.out.println("for总运行时间(ms) :" + forTotalRunTime);
BigDecimal streamAverageRunTime = streamTotalRunTime.divide(new BigDecimal(testTimes + ""), 2, BigDecimal.ROUND_HALF_UP);
System.out.println("stream平均每次运行时间(ms) :" + streamAverageRunTime);
BigDecimal forAverageRunTime = forTotalRunTime.divide(new BigDecimal(testTimes + ""), 2, BigDecimal.ROUND_HALF_UP);
System.out.println("for平均每次运行时间(ms) :" + forAverageRunTime);
}
当数据量为10w,测试5次的结果输出:
第1次:stream 耗时:81
第1次:for 耗时:13
第2次:stream 耗时:15
第2次:for 耗时:23
第3次:stream 耗时:7
第3次:for 耗时:11
第4次:stream 耗时:7
第4次:for 耗时:13
第5次:stream 耗时:9
第5次:for 耗时:6
list长度为:100000, 总共测试次数:5
stream总运行时间(ms) :119
for总运行时间(ms) :66
stream平均每次运行时间(ms) :23.80
for平均每次运行时间(ms) :13.20
当数据量为100w,测试5次的输出结果:
第1次:stream 耗时:165
第1次:for 耗时:1296
第2次:stream 耗时:447
第2次:for 耗时:62
第3次:stream 耗时:363
第3次:for 耗时:359
第4次:stream 耗时:61
第4次:for 耗时:350
第5次:stream 耗时:389
第5次:for 耗时:43
list长度为:1000000, 总共测试次数:5
stream总运行时间(ms) :1425
for总运行时间(ms) :2110
stream平均每次运行时间(ms) :285.00
for平均每次运行时间(ms) :422.00
所有运行时长单位均为ms。综上测试结果,当数据量少于百万级别的,一次for循环来筛选数据效率更高,当数据量达到八万级别,还是使用stream来操作更加具有效率。但是小弟还是有点不明白原因是为何,求高人指点一二