String value : strings.get(i);
// Do something useful here
}
for (String value : stringArray) {
// Do something useful here
}
小结
无论是大年夜易读写的角度来说,照样大年夜API设计的角度来说迭代器、Iterable接口和 foreach 轮回都是异常好用的。但价值是,应用它们时是会额外在堆上为每个轮回子创建一个对象。如不雅轮回要履行很多很多遍,请留意避免生成无意义的实例,最好用根本的指针轮回方法来代替上述迭代器、Iterable接口和 foreach 轮回。
评论辩论
一些与上述内容持否决看法的看法(尤其是用指针操作替代迭代器)详见Reddit上的评论辩论。
4、不要调用高开销办法
有些办法的开销很大年夜。以 N.O.P.E 分支为例,我们没有提到叶子的相干办法,不过这个可以有。假设我们的JDBC驱动须要清除万难去计算 ResultSet.wasNull() 办法的返回值。我们本身实现的SQL框架可能像下面如许:
if (type == Integer.class) {
result = (T) wasNull(rs,
Integer.valueOf(rs.getInt(index)));
}
// And then...
static final <T> T wasNull(ResultSet rs, T value)
Pattern.compile("(((X)*Y)*Z)*");
throws SQLException {
return rs.wasNull() ? null : value;
一般来说,应用 StringBuilder 的效不雅要优于应用 + 操作符。如不雅可能的话请在须要跨多个办法传递引用的情况下选择 StringBuilder,因为 String 要消费额外的资本。JOOQ在生成复杂的SQL语句便应用了如许的方法。在全部抽象语法树(AST Abstract Syntax Tree)SQL传递过程中仅应用了一个 StringBuilder 。
}
在膳绫擎的逻辑中,每次大年夜结不雅集中取得 int 值时都要调用 ResultSet.wasNull() 办法,然则 getInt() 的办法定义为:
返回类型:变量值;如不雅SQL萌芽结不雅为NULL,则返回0。
所以一个简荡竽暌剐效的改良办法如下:
static final <T extends Number> T wasNull(
更不消说下面的写法:
ResultSet rs, T value
)
throws SQLException {
return (value =http://news.51cto.com/art/201710/= null ||
(value.intValue() == 0 && rs.wasNull()))
? null : value;
Boolean a2 = Boolean.valueOf(true);
这是易如反掌的工作。
小结
@Override
将办法调用缓存起来替代在叶子节点的高开销办法,或者在办法商定许可的情况下避免调用高开销办法。
5、应用原始类型和栈
膳绫擎介绍潦攀来自 jOOQ的例子中应用了大年夜量的泛型,导致的结不雅是应用了 byte、 short、 int 和 long 的包装类。但至少泛型在Java 10或者Valhalla项目中被专门化之前,不该该成为代码的限制。因为可以经由过程下面的办法来进行调换:
//存储在堆上
Integer i = 817598;
……如不雅如许写的话:
// 存储在栈上
int i = 817598;
在应用数组时情况可能会变得加倍糟糕:
//在堆上生成了三个对象
Integer[] i = { 1337, 424242 };
……如不雅如许写的话:
// 仅在堆上生成了一个对象
int[] i = { 1337, 424242 };
小结
@Override
当我们处于 N.O.P.E. 分支的深处时,应当逝世力避免应用包装类。如许做的坏处是给GC带来了很大年夜的压力。GC将会为清除包装类生成的对象而忙得弗成开交。
所以一个有效的优化办法是应用根本数据类型、定长数组,并用一系列瓜分变量来标识对象在数组中所处的地位。
例外
下面的情况对这条规矩例外:因为 boolean 和 byte 类型不足以让JDK为其供给缓存办法。我们可以如许写:
Boolean a1 = true; // ... syntax sugar for:
Byte b1 = (byte) 123; // ... syntax sugar for:
Byte b2 = Byte.valueOf((byte) 123);
其它整数根本类型也有类似情况,比如 char、short、int、long。
不要在调用构造办法时将这些整型根本类型主动装箱或者调用 TheType.valueOf() 办法。
也不要在包装类上调用构造办法,除非你想获得一个不在堆上创建的实例。
6、避免递归(真技巧文)
如今,类似Scala如许的函数式编程说话都鼓励应用递归。因为递归通平平易近味着能分化到零丁个别优化的尾递归(tail-recursing)。如不雅你应用的编程说话可以或许支撑那是再好不过。不过即使如斯,也要留意对算法的细微调剂将会使尾递归变为通俗递归。
欲望编译器能主动探测到这一点,不然本来我们将为只需应用几个本地变量就能搞定的工作而白白浪费大年夜量的客栈框架(stack frames)。
小结
这节中没什么好说的,除了在 N.O.P.E 分支尽量应用迭代来代替递归。
7、应用entrySet()
}
当我们想遍历一个用键值对情势保存的 Map 时,必须要为下面的代码找到一个很好的来由:
for (K key : map.keySet()) {
}
K key = entry.getKey();
V value = http://news.51cto.com/art/201710/entry.getValue();
}
在我们应用 N.O.P.E. 分支应当慎用map。因为很多看似时光复杂度为 O(1) 的拜访操作其实是由一系列的操作构成的。并且拜访本身也不是免费的。至少,如不雅不得不应用map的话,那么要用 entrySet() 办法去迭代!如许的话,我们要拜访的就仅仅是Map.Entry的实例。
小结
在须要迭代键值对情势的Map时必定要用 entrySet() 办法。
8、应用EnumSet或EnumMap(真是技巧文)
在某些情况下,比如在应用设备map时,我们可能会预先知道保存在map中键值。如不雅这个键值异常小,我们就应当推敲应用 EnumSet 或 EnumMap,而并非应用我们常用的 HashSet 或 HashMap。下面的代码给出了很清跋扈的解释:
推荐阅读
2017年架构师最重要的48个小时 | 8折倒计时 一、大年夜主动化需求说起对于这个问题,秉承实在用主义的精力,我本来也不会去深究。毕竟,安装的时刻会设置暗码,安装完毕后能经由过程passwd>>>详细阅读
本文标题:Java程序员应知道的十条Java优化策略,让你的系统健步如飞
地址:http://www.17bianji.com/lsqh/38303.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示