Collectors.joining与StringBuilder.append的性能对比:孰优孰劣?
Java字符串拼接:Stream forEach+StringBuilder vs Collectors.joining 性能对比
嘿,这个问题问到点子上了!咱们来好好掰扯下这两种Java字符串拼接方式的性能差异~
先拆解两种实现的底层逻辑
方式一:手动forEach调用StringBuilder
finalWords.stream().forEach(word -> stringBuilder.append(word).append(",")); String finalResult = stringBuilder.toString();
这种方式是你手动控制StringBuilder的拼接逻辑:
- 每次遍历元素时,通过lambda表达式调用
append,这里会有lambda调用的额外开销; - 如果初始化
StringBuilder时没指定合适的容量,大概率会触发多次扩容(每次扩容是翻倍扩容,伴随数组复制操作); - 额外问题:最后会多一个多余的逗号,你还得手动处理(比如
deleteCharAt或者substring),这又多了一步性能损耗。
方式二:Collectors.joining
String finalResult = finalWords.stream().collect(Collectors.joining(","));
Collectors.joining是Java专门为字符串拼接优化的工具,底层同样用StringBuilder,但做了不少细节优化:
- 提前估算容量:它会先遍历所有元素,计算出总字符长度 + 分隔符的总长度,直接初始化一个足够大的
StringBuilder,完全避免扩容带来的数组复制开销; - 无lambda额外开销:内部的拼接逻辑是直接调用
append,没有通过lambda传递的额外调用成本; - 自动处理分隔符:只会在元素之间添加分隔符,最后不会多出多余的逗号,省掉了后续的截断操作。
性能表现总结
毫无疑问,方式二的性能要优于方式一:
- 当元素数量较多时,容量预分配和无lambda开销的优势会被放大,两者的性能差距会很明显;
- 即使元素数量极少,方式二的性能也不会比方式一差,而且代码更简洁、更易维护,不用操心
StringBuilder的初始化和多余分隔符的问题。
简单来说,Collectors.joining就是Java为这种场景量身定做的最优解,既高效又省心~
内容的提问来源于stack exchange,提问作者Sagar
相关产品推荐
相关产品推荐

