巧用三目运算和逻辑运算符
String 类里的两个方法。(大家对比着看,体验一下如何巧用三目运算符)
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
精髓来了,用三目运算符和逻辑 && 巧妙的代替了多个 if 判断。没错,就是这么骚。
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true
: (anotherString != null)
&& (anotherString.value.length == value.length)
&& regionMatches(true, 0, anotherString, 0, value.length);
}
巧用 !=
public class Demo {
static int a;
public static void main(String[] args) {
int t= a;
a=2;
System.out.println(t!=(t=a));
System.out.println(t);
}
}
输出结果
true
2
t!=(t=a)
分析这行代码,a 是一个共享变量,这一句话话就干了两件事
- 将 t 这个临时变量的值修改为 a 的最新值
- 比较 a 这个共享变量有没有被修改
大大的缩短了代码量,对应的指令少了,性能自然也就高了。
巧用数组和范围查找
int
转成 String
的方法中用来判断某个整形的位数。
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
// 在 sizeTable 中找到第一个比 x 大的数,而此时这个数的索引+1 刚好是 x 的位数。不得不说,源码的设计之精巧。
if (x <= sizeTable[i])
return i+1;
}
1.空间局部性: sizeTable
为数组,存储在相邻的位置,CPU 一次加载一个块数据数据到 cache 中(多个数组数据),此后访问 sizeTable
不需要访问内存。
2.基于范围的查找,是很实用的设计技术
巧用移位
位移比乘法高效:
r = i – (( q << 6) + ( q << 5) + ( q << 2));
等价于
r = i – (q * 100);
乘法比除法高效:
q = ( i * 52429) >>> (16+3);
约等于q*0.1
注:乘法配合无符号移位可以代替除法
hashCode() 和 equals() 搭档干活
hashCode()
hashCode 是根据本地方法算出来的一个整型值,它可以代表你的对象 id(也就是唯一标识)。
hashCode 一般用于 hash 函数中。
equals()
equals() 这个方法本来是没有什么意义的,它需要你去重写超类 Object 的 equals(),从而来实现自己所需要表达的语义。
为了避免一些问题的出现,建议 hashCode() 和 equals() 一起重写,把它俩绑定在一起使用。
使用场景
hashMap
当 put 的元素 hashCode 一样时,也就是定位在同一个桶时,这个时候我们就需要 equals() 的帮助了。用 equals() 来解决 hash 冲突的情况。即当多个对象 hashCode 一样时,我们可以通过 equals() 来分辨它们。(当然这个的前提是你必须同时重写 hashCode() 和 equals())
泛型的使用
ArrayList<E> ,通过使用泛型,限制了加入的元素类型,从而可以在 get 的时候,安全的转型。
transient Object[] elementData;
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}