案例1:输出debug信息需要加enable判断
log.debug("userId:"+ user.getId())//-->
if(log.isDebugEnable()){
log.debug("userId:"+ user.getId())
}
分析:1、不加enable判断,括号中的字符串相加会产生中间字符,大量调用时创建和销毁的数量非常庞大,会造成gc频繁执行,进而影响性能。2、线上日志一般不会是debug,因此执行字符串拼接是无意义的运算。根据log优先级,对error、warn可以不用判断
案例2:遍历map时,特别是数据量较大时不要使用get(key)取值
for(Iterator<String> ite = map.keySet().iterator(); ite.hasNext();){
String key = ite.next();
String value = map.get(key);
}
-->
for(Iterator<Entry<String,String>> ite = map.entrySet().iterator(); ite.hasNext();){
Entry<String,String> entry = (Entry<String,String>) ite.next();
String key = entry.getKey();
String value = entry.getValue();
}
分析:Map类的get(key)方法会进行两次hashCode的运算,造成效率低
public V get(Object paramObject)
{
if (paramObject == null)
return getForNullKey();
int i = hash(paramObject.hashCode());
for (Entry localEntry = this.table[indexFor(i, this.table.length)];
localEntry != null;
localEntry = localEntry.next)
{
Object localObject;
if ((localEntry.hash == i) && (((localObject = localEntry.key) == paramObject) || (paramObject.equals(localObject))))
return localEntry.value;
}
return null;
}
案例3: Java5的正则表达式没有执行事实上perl标准,也有有若干缺陷,一是可能会导致JVM的崩溃,二是在递归处理上性能低下,使用时也需要预编译。
Pattern p = Pattern.compile("^[a-zA-Z]+[a-zA-Z0-9]+");
Matcher m = p.matcher("12aa");
if(m.matches()){...}
->
private static final Pattern p = Pattern.compile("^[a-zA-Z0-9]+");
or
private static final Pattern p = new Perl5Compiler().compile("^[a-zA-Z0-9]+$", '''Perl5Compiler.READ_ONLY_MASK''');
//由于Pattern本身不是线程安全的,只有加了READ_ONLY_MASK的编译参数才能用于共享使用,否则会出现并发访问的问题,导致错误结果
PatternMatcher matcher = new Perl5Matcher();
if(matcher.matches("123", p)){...}
分析:建议使用oro库处理RegExp,表达式一定要求是预先编译的,编译过程是非常消耗性能的。我们经常用的String.split()方法里的实现:Pattern.compile(paramString).split(this, paramInt),可以看出性能也是不高的,最好使用pattern.split(str)
. 匹配任意一个字符 $ 匹配一行的结尾 ^ 匹配一行的开头(在[]里面表示否定) {} 定义了一个范围 [] 定义了一个字符类 () 定义了一个组 *前面出现0次以上 + 前面匹配一次以上 ?前面出现0次或一次 \ 后面的字符不会看作metacharacter \w 字母数字下划线 \W 非字母数字下划线 \d 单个数字 \D单个非数字 | 或,二者之一 &&与操作符 \b单词边界
案例5:serialVersionUID 来解决软件兼容性的问题,即在版本升级时(对象新增或减少字段)反序列化仍保持对象的唯一性。有些情况不能更改 serialVersionUID ,比如分布式环境下,如果要修改,只能关联系统都暂停服务,发布完后再对外统一提供服务。有些情况必须修改serialVersionUID ,比如缓存中的数据,新增了字段,但缓存中的数据还是老的数据,不修改serialVersionUID ,反序列化回来会缺少新增的字段值,这时修改serialVersionUID 值则会在反序列化时报错,重新put新的缓存数据。
private static final long serialVersionUID = 7311398892155614476L;