(1)java优化的目的:
a>减少代码量
b>提高java运行的效率
(2)java常见的优化场景:
1.开发过程中声明常量,不可继承类,不可重写方法,使用final
如:private final String hello="wolrd";
2.String,StringBuffer,StringBuilder
a>常量字符串拼接选择“String”
String s1="hello"+"world"; //选择String
StringBuilder sb=new StringBuilder();
sb.append("hello");
sb.append("world");
b>一般执行速度StringBuilder>StringBuffer>String
c>StringBuffer线程安全,StringBuilder是非线程安全
StringBuilder//在单线程下,操作大量数据可以使用,应该保证了线程安全且执行速度很快
StringBuffer//在多线程下,操作大量数据可以使用,保证了线程安全
d>String是字符串常量,StringBuilder和StringBuffer是字符串变量
String:private final char value[];
StringBuilder/StringBuffer:char[] value;
3.及时关闭io流,释放资源
文件操作,数据库操作
4.减少变量重复计算
for (int i = 0; i < list.size(); i++) {}//每次循环,就得计算一次list.size()
建议替换为:
for (int i = 0, int length = list.size(); i < length; i++) {}
5.尽量使用懒加载
String str = "aaa";
if (i == 1) {
list.add(str);
}
建议替换为:
if (i == 1) {
String str = "aaa";
list.add(str);
}
6.不要在循环中使用try…catch…,应该把其放在最外层
try{
for(){}
}
catch(){
}
7.如果能估计到待添加的内容长度,为底层以数组方式实现的集合、工具类指定初始长度
比如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等
StringBuilder()// 默认分配16个字符的空间
StringBuilder(int size)// 默认分配size个字符的空间
StringBuilder(String str) // 默认分配16个字符+str.length()个字符空间
注意:当StringBuilder达到最大容量的时 候,它会将自身容量增加到当前的2倍再加2,
无论何时只要StringBuilder达到它的最大容量,它就不得不创建一个新的字符数组然后将旧的字符数 组内容拷贝到新字符数组中—-这是十分耗费性能的一个操作
8.乘法和除法使用移位操作
for (val = 0; val < 100000; val += 5) {
a = val * 8;
b = val / 2;
}
建议改成:
for (val = 0; val < 100000; val += 5) {
a = val << 3;
b = val >> 1;
}
9.循环内不要不断创建对象引用
for (int i = 1; i <= count; i++) {
Object obj = new Object();
}
建议为改为:
Object obj = null;
for (int i = 0; i <= count; i++) { obj = new Object(); }
10.线程安全和效率不能同时兼得
尽量使用HashMap、ArrayList、StringBuilder,
除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,
后三者由于使用同步机制而导致了性能开销
11.尽量避免随意使用静态变量
public class A {
private static B b = new B();
}
注意:当某个对象被定义为static的变量所引用,那么gc通常是不会回收这个对象所占有的堆内存的
12.实现RandomAccess接口的集合比如ArrayList,应当使用最普通的for循环而不是foreach循环来遍历
实际经验表明,实现RandomAccess接口的类实例,假如是随机访问的,
使用普通 for循环效率将高于使用foreach循环;反过来,
如果是顺序访问的,则使用Iterator会效率更高。可以使用类似如下的代码作判断
13.将常量声明为static final,并以大写命名
private static final String NAME="Robin";
14.不要创建一些不使用的对象,不要导入一些不使用的类
清除多余无关的类
15.使用数据库连接池和线程池
这两个池都是用于重用对象的,前者可以避免频繁地打开和关闭连接,
后者可以避免频繁地创建和销毁线程
16.使用带缓冲的输入输出流进行IO操作
带缓冲的输入输出流,即BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,
这可以极大地提升IO效率
17.顺序插入和随机访问比较多的场景使用ArrayList,元素删除和中间插入比较多的场景使用LinkedList
这个,理解ArrayList和LinkedList的原理就知道了
18.字符串变量和字符串常量equals的时候将字符串常量写在前面
String str = "123";
if (str.equals("123")) { }
建议改成:
String str = "123";
if ("123".equals(str)) {}
19.请知道,在java中if (i == 1)和if (1 == i)是没有区别的,但从阅读习惯上讲,建议使用前者
int i = 2;
if (i == 1) {}
如果将“==”误写成了“=”
int i = 2;if (i = 1) { ... }else{ ... }
20.把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+”"最慢
请不要使用数据+"";
a>String.valueOf()方法底层调用了Integer.toString()方法,但是会在调用前做空判断
b>Integer.toString()方法就不说了,直接调用了
c>i + ""底层使用了StringBuilder实现,先用append方法拼接,再用toString()方法获取字符串
如:String s=1+"";
21.使用最有效率的方式去遍历Map<KeySet,EntrySet,values,Iterator>
map最全的4种遍历方式:
a>在for-each循环中使用entries来遍历
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
b>在for-each循环中遍历keys或values。
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//遍历map中的键
for (Integer key : map.keySet()) {
System.out.println("Key = " + key);
}
//遍历map中的值
for (Integer value : map.values()) {
System.out.println("Value = " + value);
}
c>通过键找值遍历(效率低)
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
Integer value = map.get(key);
System.out.println("Key = " + key + ", Value = " + value);
}
d>最快的方式:
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("111", "222");
Set<Map.Entry<String, String>> entrySet = hm.entrySet();
Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
while (iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
System.out.println(entry.getKey() + "\t" + entry.getValue());
}
如果想要获取key,只需要获得keyset
22.对资源的close()建议分开操作
try{
XXX.close();
YYY.close();
}catch (Exception e) {
}
建议改成:
try{
XXX.close();
}
catch (Exception e) {
}
try{
YYY.close();
}
catch (Exception e) {
}
|
|