提升Java性能的9个技巧☕️🚀🚶♂️
1. 在构造函数中实例化
2. AddAll 比 Add 更快。
3.EntrySet用于地图KeySet
4. 使用单个元素SingletonList代替。array
5. 使用 ` .`EnumSet代替HashSet`.`EnumSet会快得多。
6. 不要随意初始化对象。尽量做到最大限度的重用。
7. 使用String.isEmpty()方法检查是否为String空。
8. 如果您使用的是仅包含单个字符的字符串,请将其替换为Character
9.尽可能使用StringBuilder 。
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
任何傻瓜都能写出计算机能理解的代码。优秀的程序员写出的代码,人类也能理解。——马丁·福勒
但对于任何开发者来说,编写高性能代码的渴望始终存在。让我们来看看如何让 Java 代码运行得更快。
注意:JVM 会自动高效地优化代码,因此对于一般使用场景,您无需进行额外优化。但如果您想最大限度地发挥 JVM 的性能,请继续阅读。
所有测试均在 Macbook Pro 2017 笔记本电脑上使用 OpenJDK 12.0.1 进行。
1. 在构造函数中实例化
如果你的集合只初始化一次,最好constructor直接在集合中初始化值,而不是实例化集合并使用addAll.
// Slower 🚶♂️
Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("one", "two", "three"));
// Faster 🚀
Set<String> set = new HashSet<>(Arrays.asList("one", "two", "three"));
让我们使用JMH 基准测试来验证这一点。
结果单位为
operations/second(op/s)。数值越大,性能越高。
@State(Scope.Thread)
public static class MyState {
@Setup(Level.Trial)
public void doSetup() {
var arr = new Integer[100000];
for (var i = 0; i < 100000; i++) {
arr[i] = i;
}
list = Arrays.asList(arr);
}
public List list;
}
// Faster 🚀 > ~148,344 op/s
@Benchmark
public HashSet usingConstructor() {
var set = new HashSet<>(list);
return set;
}
// Slower 🚶♂️ > ~112,061 op/s
@Benchmark
public HashSet usingAddAll() {
var set = new HashSet<>();
set.addAll(list);
return set;
}
该
construtor版本比上一版本每秒运算次数多约 36000 次addAll。
2. AddAll 比 Add 更快。
同样,addAll与相比,它能提供更高的每秒操作数add。因此,下次向数组中添加元素时,请确保将它们堆叠起来并使用添加addAll。
// Slower 🚶♂️ ~116116op/s
@Benchmark
public ArrayList<Integer> usingAdd() {
var a = new int[1000];
for (var i = 0; i < 1000; i++) {
a[i] = i;
}
var arr = new ArrayList<Integer>();
for (var i = 0; i < 1000; i++) {
arr.add(a[i]);
}
return arr;
}
// Faster 🚀 ~299130 op/s
@Benchmark
public ArrayList<Integer> usingAddAll() {
var a = new Integer[1000];
for (var i = 0; i < 1000; i++) {
a[i] = i;
}
var arr = new ArrayList<Integer>();
arr.addAll(Arrays.asList(a));
return arr;
}
这个版本的addAll速度几乎是另一个版本的两倍add。
3.EntrySet用于地图KeySet
你是否经常遍历地图?如果是,请entrySet使用keySet.
// Slower 🚶♂️ ~37000 op/s
@Benchmark
public HashMap<Integer, Integer> keySetIteration(Blackhole blackhole) {
var someMap = new HashMap<Integer, Integer>();
for (var i = 0; i < 1000; i++) {
someMap.put(i, i);
}
var sum = 0;
for(Integer i: someMap.keySet()) {
sum += i;
sum += someMap.get(i);
}
blackhole.consume(sum);
return someMap;
}
// Faster 🚀 ~45000 op/s
@Benchmark
public HashMap<Integer, Integer> entrySetIteration(Blackhole blackhole) {
var someMap = new HashMap<Integer, Integer>();
for (var i = 0; i < 1000; i++) {
someMap.put(i, i);
}
var sum = 0;
for(Map.Entry<Integer, Integer> e: someMap.entrySet()) {
sum += e.getKey();
sum += e.getValue();
}
blackhole.consume(sum);
return someMap;
}
它每秒entrySet可以执行的9000操作次数比它的变体更多。keySet
4. 使用单个元素SingletonList代替。array
// Faster 🚀
var list = Collections.singletonList("S");
// Slower 🚶♂️
var list = new ArrayList(Arrays.asList("S"));
5. 使用 ` .`EnumSet代替HashSet`.`EnumSet会快得多。
// Faster 🚀
public enum Color {
RED, YELLOW, GREEN
}
var colors = EnumSet.allOf(Color.class);
// Slower 🚶♂️
var colors = new HashSet<>(Arrays.asList(Color.values()));
有关 EnumSet 的更多信息,请点击此处。
6. 不要随意初始化对象。尽量做到最大限度的重用。
// Faster 🚀
var i = 0 ;
i += addSomeNumber();
i -= minusSomeNumber();
return i;
// Slower 🚶♂️
var i = 0 ;
var j = addSomeNumber();
var k = minusSomeNumber();
var l = i + j - k;
return l;
7. 使用String.isEmpty()方法检查是否为String空。
字符串类型是 a byte[],isEmpty它只检查字符串的长度Array。因此速度快得多。
public boolean isEmpty() {
return value.length == 0;
}
8. 如果您使用的是仅包含单个字符的字符串,请将其替换为Character
// Faster 🚀
var r = 'R' ;
var g = 'G' ;
var b = 'B' ;
// Slower 🚶♂️
var r = "R" ;
var g = "G" ;
var b = "B" ;
9.尽可能使用StringBuilder 。
// Faster 🚀
StringBuilder str = new StringBuilder();
str.append("A");
str.append("B");
str.append("C");
str.append("D");
str.append("E");
....
// Slower 🚶♂️
var str = "";
str += "A";
str += "B";
str += "C";
str += "D";
str += "E";
....
但是,当只需要进行单个字符串连接时,使用 `StringBuilder` 会更快
+。
如果您有任何关于性能方面的实用技巧/发现任何问题,请在评论区留言。
你可以在推特上关注我。
如果你喜欢这篇文章,请点赞或留言。❤️
文章来源:https://dev.to/sendilkumarn/9-tips-to-increase-your-java-performance-1l4d
