

从 Spring PR 中学习代码技巧
source link: https://www.diguage.com/post/learn-code-tips-from-spring-pull-requests/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

从 Spring PR 中学习代码技巧

D瓜哥经常关注 Spring 的 PR 与 Issue。在众多 Contributor 中,除了 Spring 团队成员之外,我对 stsypanov (Сергей Цыпанов) 印象很深刻。这哥们给 Spring 提了非常多的 PR,请看列表 Pull requests · spring-projects/spring-framework,而且这个哥们的 PR 都非常有特点,绝大部分是性能提升方面的 PR,而且还会给出 JMH 的测试结果。不愧是毛熊人,做事细致严谨。
这周心血来潮,把这哥们的 PR 翻一翻,希望可以学习一些编码技巧。简单记录一下,以备以后回顾学习。
提高 Map
的遍历性能
请看: SPR-17074 Replace iteration over Map::keySet with Map::entrySet by stsypanov · Pull Request #1891
摘取一个示例如下:
// --before update------------------------------------------------------
for (String attributeName : attributes.keySet()) {
Object value = attributes.get(attributeName);
// --after update-------------------------------------------------------
for (Map.Entry<String, Object> attributeEntry : attributes.entrySet()) {
String attributeName = attributeEntry.getKey();
Object value = attributeEntry.getValue();
这个改动很小,但是对性能的改善还是比较显著的。翻看自己项目的代码,还是有不少是改动前的写法。
针对这点,D瓜哥也给 Spring 发了一个 PR: Improve performance of iteration in GroovyBeanDefinitionReader by diguage · Pull Request #27100。相信不久就会合并到 main
分支的。
所以,给 Spring 以及其他开源项目提 PR,其实一点也不难。只要,你花心思去研究,肯定有机会的。不过,也反思一点:我这个 PR 有点东施效颦的感觉,有点刷 KPI 的样子。还是应该脚踏实地去好好研究,提更多更有建设性意见的 PR。
ArrayList
初始化
从 PR 中摘录出两个修改片段:
// --before update-------------------------------------------
List<String> result = new ArrayList<>();
result.addAll(Arrays.asList(array1));
// --after update--------------------------------------------
List<String> result = new ArrayList<>(Arrays.asList(array1));
// --before update----------------------------------------
List<String> matchingHeaderNames = new ArrayList<>();
if (headers != null) {
for (String key : headers.keySet()) {
if (PatternMatchUtils.simpleMatch(pattern, key)) {
matchingHeaderNames.add(key);
}
// --after update-----------------------------------------
if (headers == null) {
return Collections.emptyList();
}
List<String> matchingHeaderNames = new ArrayList<>();
for (String key : headers.keySet()) {
if (PatternMatchUtils.simpleMatch(pattern, key)) {
matchingHeaderNames.add(key);
}
new ArrayList<>(Arrays.asList(array1))
与 Collections.emptyList()
都是一些值得关注的代码小技巧。另外,在第二个修改片段中,直接进行空值判断,还可以减少下面代码的括号嵌套层数。
字符串连接
Simplify String concatenation by stsypanov · Pull Request #22466 这个 PR 改动很小,代码也乏善可陈。但是,在这个 PR 的描述中,Contributor 给出了这个 PR 的解释,里面给出的 Reference: StringBuffer and StringBuilder performance with JMH ,详细对比了不同情况下,“字符串连接”的性能情况,读一读还是有不少收获的。这里直接把文章结论引入过来:
-
StringBuilder
is better thanStringBuffer
-
StringBuilder.append(a).append(b)
is better thanStringBuilder.append(a+b)
-
StringBuilder.append(a).append(b)
is better thanStringBuilder.append(a); StringBuilder.append(b);
-
StringBuilder.append()
and+
are only equivalent provided that they are not nested and you don’t need to pre-sizing the builder -
Pre-sizing the
StringBuilder
is like pre-sizing anArrayList
; if you know the approximate size you can reduce the garbage by specifying a capacity up-front
// --before update----------------------
for (int i = 0; i < bytes.length; i++) {
bytes[i] = 'h';
}
// --after update-----------------------
Arrays.fill(bytes, (byte) 'h');
用一行代码代替三行代码,何乐而不为呢?另外,估计很多人不知道 Arrays.fill(array, object);
这个 API。
Comparator
// --before update------------------------------------
Arrays.sort(ctors, (c1, c2) -> {
int c1pl = c1.getParameterCount();
int c2pl = c2.getParameterCount();
return (c1pl < c2pl ? -1 : (c1pl > c2pl ? 1 : 0));
});
// --after update-------------------------------------
Arrays.sort(ctors, (c1, c2) -> {
int c1pl = c1.getParameterCount();
int c2pl = c2.getParameterCount();
return Integer.compare(c1pl, c2pl);
});
Contributor 使用 Integer.compare(int, int)
来简化比较代码。所以,以后比较整数可以使用 Integer.compare(int, int)
。
其实,还可以更进一步:
// --before update----------------------------------------------------------
Arrays.sort(ctors, (c1, c2) -> {
int c1pl = c1.getParameterCount();
int c2pl = c2.getParameterCount();
return Integer.compare(c1pl, c2pl);
});
// --after update-----------------------------------------------------------
Arrays.sort(ctors, Comparator.comparingInt(Constructor::getParameterCount));
// --before update--------------------------------
String[] copy = new String[state.length];
System.arraycopy(state, 0, copy, 0, state.length);
return copy;
// --after update---------------------------------
return state.clone();
复制数组,以前只知 System.arraycopy
可以高效完成任务,以后可以使用 array.clone()
。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK