Java 中 10 大简单的性能优化( 三 )
Boolean a1 = true; // ... syntax sugar for:Boolean a2 = Boolean.valueOf(true); Byte b1 = (byte) 123; // ... syntax sugar for:Byte b2 = Byte.valueOf((byte) 123);
对于其他整数基本类型的低值也是如此,包括char, short, int, long 。但仅当您自动装箱或调用TheType.valueOf()时,才不会在调用构造函数时!
永远不要在包装类型上调用构造函数,除非你真的想要一个新实例
这个事实也可以帮助你为你的同事写一个复杂的愚人节笑话 堆 外 当然,你可能还想尝试堆外库,尽管它们更多的是战略决策,而不是本地优化 。
6、避免递归像 Scala 这样的现代函数式编程语言鼓励使用递归,因为它们提供了将尾递归算法优化回迭代算法的方法 。如果你的语言支持这样的优化,你可能没问题 。但即便如此,算法的最轻微变化也可能会产生一个分支,阻止你的递归是尾递归的 。希望编译器会检测到这一点!否则,您可能会浪费大量堆栈帧,而这些堆栈帧可能仅使用几个局部变量就可以实现 。当你深入N.O.P.E.分支时,总是更喜欢迭代而不是递归
7、使用 entrySet()当您想要遍历 aMap并且需要键和值时,您必须有充分的理由编写以下内容:
for (K key : map.keySet()) {V value : map.get(key);}
而不是以下内容:
for (Entry<K, V> entry : map.entrySet()) {K key = entry.getKey();V value = https://www.isolves.com/it/cxkf/yy/JAVA/2022-04-22/entry.getValue();}
当你在N.O.P.E.分支时,无论如何你都应该警惕地图,因为大量的O(1)地图访问操作仍然是大量的操作 。而且访问也不是免费的 。但至少,如果您不能没有地图,请使用它entrySet()来迭代它们!无论如何,该Map.Entry实例都在那里,您只需要访问它 。entrySet()在 map 迭代过程中同时需要键和值时 始终使用 。
8、使用 EnumSet 或 EnumMap在某些情况下,映射中可能的键的数量是预先知道的——例如在使用配置映射时 。如果该数字相对较小,您应该真正考虑使用EnumSetor EnumMap,而不是常规HashSetor HashMap 。这很容易通过查看来解释EnumMap.put():
private transient Object[] vals; public V put(K key, V value) {// ...int index = key.ordinal();vals[index] = maskNull(value);// ...}
这个实现的本质是,我们有一个索引值数组,而不是一个哈希表 。当插入一个新值时,为了查找映射条目,我们所要做的就是向enum查询它的常数序数,该常数序数是由Java编译器在每个enum类型上生成的 。如果这是一个全局配置映射(即只有一个实例),增加的访问速度将帮助EnumMap大大超过HashMap,它可能使用更少的堆内存,但必须在每个键上运行hashCode()和equals() 。Enum和EnumMap是非常亲密的朋友 。当您使用类似于枚举的结构作为键时,请实际考虑将这些结构作为枚举,并在EnumMap中使用它们作为键 。
9、优化你的 hashCode() 和 equals() 方法如果不能使用EnumMap,至少优化hashCode()和equals()方法 。一个好的hashCode()方法是必要的,因为它将防止进一步调用开销大得多的equals(),因为它将为每个实例集生成更多不同的散列桶 。在每个类层次结构中,都可能有流行的和简单的对象 。hashCode()最简单、最快的实现是这样的:
// AbstractTable, a common Table base implementation: @Overridepublic int hashCode() {// [#1938] This is a much more efficient hashCode()// implementation compared to that of standard// QueryPartsreturn name.hashCode();}
name表名在哪里 。我们甚至不考虑表的模式或任何其他属性,因为表名通常在数据库中足够不同 。此外,它name是一个字符串,所以它里面已经有一个缓存hashCode()值 。注释很重要,因为AbstractTableextends是任何AST(抽象语法树)元素AbstractQueryPart的通用基础实现 。通用 AST 元素没有任何属性,因此它不能对优化实现做出任何假设 。因此,被覆盖的方法如下所示:hashCode()
// AbstractQueryPart, a common AST element// base implementation: @Overridepublic int hashCode() {// This is a working default implementation.// It should be overridden by concrete subclasses,// to improve performancereturn create().renderInlined(this).hashCode();}
换句话说,必须触发整个 SQL 渲染工作流来计算一个普通 AST 元素的哈希码 。事情变得更有趣equals()
// AbstractTable, a common Table base implementation: @Overridepublic boolean equals(Object that) {if (this == that) {return true;}// [#2144] Non-equality can be decided early,// without executing the rather expensive// implementation of AbstractQueryPart.equals()if (that instanceof AbstractTable) {if (StringUtils.equals(name,(((AbstractTable<?>) that).name))) {return super.equals(that);}return false;}return false;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 生肖|2022年,鸿运高照,职场机遇多,前景可观,前程似锦的三大生肖
- |有报告称中高端人才的职场危机年龄早于 35 岁,真是这样的吗?
- 乐视|乐视发布九大声明 调侃:活到今天“何止是奇迹简直不科学”
- 网友热议|上海大爷在江景房阳台钓到8斤大鱼 网友:这房买值了
- 中海地产怎么样?中海物业管理的优势
- 十大男装皮衣品牌
- 事业遇贵人的四大属相是什么?
- 大学绩点2.5很差吗?
- 徐凤年打败北莽了吗?
- 布朗红大树红茶的泡法,国艳普洱茶布朗大树