您现在的位置是:网站首页> 内容页

编写高质量代码:改善Java程序的151个建议 --[52~64]

  • www.塞班島娛樂城客服
  • 2019-03-18
  • 192人已阅读
简介编写高质量代码:改善Java程序的151个建议--[52~64]推荐使用String直接量赋值Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String

编写高质量代码:改善Java程序的151个建议 --[52~64]

推荐使用String直接量赋值

Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String字符串是程序中最经常使用的类型),于是就设计了一个字符串池(也叫作字符串常量池,String pool或String Constant Pool或String Literal Pool),在字符串池中容纳的都是String字符串对象,它的创建机制是这样的:创建一个字符串时,首先检查池中是否有字面值相等的字符串,如果有,则不再创建,直接返回池中该对象的引用,若没有则创建之,然后放到池中,并返回新建对象的引用,这个池和我们平常说的池非常接近。对于此例子来说,就是创建第一个"詹姆斯"字符串时,先检查字符串池中有没有该对象,发现没有,于是就创建了"詹姆斯"这个字符串并放到池中,待创建str2字符串时,由于池中已经有了该字符串,于是就直接返回了该对象的引用,此时,str1和str2指向的是同一个地址,所以使用"=="来判断那当然是相等的了。

public class Client58 { public static void main(String[] args) { //建议 String str1 = "詹姆斯"; //建议 String str2 = "詹姆斯"; //不建议,直接声明一个String对象是不检查字符串池的,也不会把对象放到字符串池中 String str3 = new String("詹姆斯"); String str4 = str3.intern(); // 两个直接量是否相等 System.out.println(str1 == str2); // 直接量和对象是否相等 System.out.println(str1 == str3); // 经过intern处理后的对象与直接量是否相等, //intern会检查当前对象在对象池中是否存在字面值相同的引用对象,如果有则返回池中的对象,如果没有则放置到对象池中,并返回当前对象。 System.out.println(str1 == str4); }}

正确使用String、StringBuffer、StringBuilder

使用String类的场景:在字符串不经常变化的场景中可以使用String类,例如常量的声明、少量的变量运算等;使用StringBuffer的场景:在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程的环境中,则可以考虑使用StringBuffer,例如XML解析、HTTP参数解析和封装等;使用StringBuilder的场景:在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程的环境中,则可以考虑使用StringBuilder,如SQL语句的拼接,JSON封装等。

性能对比:StringBuffer和StringBuilder基本相同,都是可变字符序列,不同点是:StringBuffer是线程安全的,StringBuilder是线程不安全的,翻翻两者的源代码,就会发现在StringBuffer的方法前都有关键字syschronized,这也是StringBuffer在性能上远远低于StringBuffer的原因。在性能方面,由于String类的操作都是产生String的对象,而StringBuilder和StringBuffer只是一个字符数组的再扩容而已,所以String类的操作要远慢于StringBuffer 和 StringBuilder。

强烈建议使用UTF编码

使用Collator类排序汉字

如果排序对象是经常使用的汉字,使用Collator类排序完全可以满足我们的要求,毕竟GB2312已经包含了大部分的汉字,如果需要严格排序,则要使用一些开源项目来自己实现了,比如pinyin4j可以把汉字转换为拼音,然后我们自己来实现排序算法,不过此时你会发现要考虑的诸如算法、同音字、多音字等众多问题。

import java.text.Collator;import java.util.Arrays;import java.util.Comparator;import java.util.Locale;public class CollatorDemo { public static void main(String[] args) { String[] strs = { "张三(Z)", "李四(L)", "王五(W)" }; //定义一个中文排序器 Comparator c = Collator.getInstance(Locale.CHINA); Arrays.sort(strs,c); int i = 0; for (String str : strs) { System.out.println((++i) + "、" + str); } }}

结果:1、李四(L)2、王五(W)3、张三(Z)

性能要求较高的场景中使用数组代替集合

对基本类型进行求和运算时,数组的效率是集合的10倍。

//对数组求和 public static int sum(int datas[]) { int sum = 0; for (int i = 0; i < datas.length; i++) { sum += datas[i]; } return sum; }

// 对列表求和计算 public static int sum(List<Integer> datas) { int sum = 0; for (int i = 0; i < datas.size(); i++) { sum += datas.get(i); } return sum; }

基本类型是在栈内存中操作的,而对象是堆内存中操作的,栈内存的特点是:速度快,容量小;堆内存的特点是:速度慢,容量大(从性能上讲,基本类型的处理占优势)。其次,在进行求和运算时(或者其它遍历计算)时要做拆箱动作,因此无谓的性能消耗也就产生了。

若有必要,使用变长数组

public static <T> T[] expandCapacity(T[] datas, int newLen) { // 不能是负值 newLen = newLen < 0 ? 0 : newLen; // 生成一个新数组,并拷贝原值 return Arrays.copyOf(datas, newLen); }

public static void main(String[] args) { //一个班级最多容纳60个学生 Stu [] stuNums= new Stu[60]; //stuNums初始化...... //偶尔一个班级可以容纳80人,数组加长 stuNums=expandCapacity(stuNums,80); /* 重新初始化超过限额的20人...... */ }

在明确的场景下,为集合指定初始容量

ArrayList():默认构造函数,提供初始容量为10的空列表。ArrayList(int initialCapacity):构造一个具有指定初始容量的空列表。ArrayList(Collection<? extends E> c):构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。

  从这里我们可以看出,如果不设置初始容量,系统会按照1.5倍的规则扩容,每次扩容都是一次数组的拷贝,如果数据量大,这样的拷贝会非常消耗资源,而且效率非常低下。所以,我们如果知道一个ArrayList的可能长度,然后对ArrayList设置一个初始容量则可以显著提高系统性能。

文章评论

Top