Java编程的一些小技巧系列一

Java编程的一些小技巧系列一

1.for循环

  • 这一种循环,会额外创建一个迭代器,然后遍历值。当遇到链表、Hashmap表时,用它速度很快。因为这样不需要通过遍历整个集合查找元素。
for(String str : list){
}
  • 这一种循环,不用创建迭代器,当遇到数组、ArrayList时,用它速度最快,节省创建迭代器时间。如果遇到链表、HashMap则每一个都必须通过遍历整个集合来查找元素,时间复杂度立马上升。
int len=list.size();
for(int i=0;i<len;i++){
    String str=list[i];
}

2.集合处理

(1)、ArrayList的subList结果不可强转成ArrayList,否则会抛出 ClassCastException异常: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList。subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

(2)、在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生 ConcurrentModificationException 异常。

(3)、使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()。

(4)、使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

(5)、不要在 foreach 循环里进行元素的 remove/add 操作。 remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

(6)、集合初始化时,指定集合初始值大小。

(7)、使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

3.Array、ArrayList、LinkedList

Array

  • 优点:
    • Array是固定大小,创建时分配内存,速度最快
    • 查找通过索引,速度快
    • 数组可以多维
  • 缺点
    • 不易扩容
  • 适用场景
    • 确定集合需要固定长度时推荐使用数组

ArrayList

  • 优点:
    • 底层存储是数组,查找通过索引,速度快
    • 增加删除操作方便
  • 缺点
    • 当底层数组存满时,再添加一个元素,ArrayList会创建一个新的数组,长度是原数组的1.5倍(jdk1.8是1.5倍,有说是2倍,可能是老版本),然后把原数组元素拷贝到新数组,这个过程比较耗时,所以在能估计到集合大小时,创建对象指定初始化集合大小。
    • 由于底层是数组,在数组未满时,如果往中间插入元素,首先插入索引往后的元素复制并往后移动一位,然后添加元素,速度较慢;在中间删除元素时也是类似的操作。
  • 适用场景
    • 无法预估准确的集合大小,且没有中间插入删除的操作

LinkedList

  • 优点:
    • 底层存储是链表结构,中间插入删除的操作速度快
  • 缺点
    • 查找时需要从头开始遍历,速度较慢
  • 适用场景
    • 中间插入删除的操作较多,查找操作较少

4.return

当一个方法返回的时候尽量不要返回null,否则一般需要加上if条件判空,稍不注意会造成空指针异常

例如返回集合的时候,可以返回一个空的集合。

5.String、StringBuffer、StringBuilder

  • String:不可变类型,在做拼接的时候会先找常量池,常量池没有再创建新的对象,性能消耗很大
  • StringBuffer:可变类型,且线程安全,拼接字符串时比String大大提升,由于加锁保证线程安全,性能稍低于StringBuilder
  • StringBuilder:可变类型,线程不安全,性能最快。推荐使用StringBuilder,因为很少用多线程操作一个字符串的场景,大部分作为局部变量

6.finally

在try catch中要加finally,释放一些特殊的操作

  • 文件流操作,不释放的话容易导致流溢出。
  • 解锁问题

1> try、catch、finally语句中,在如果try语句有return语句,则返回的之后当前try中变量此时对应的值,此后对变量做任何的修改,都不影响try中return的返回值

2> 如果finally块中有return 语句,则返回try或catch中的返回语句忽略。

3 >如果finally块中抛出异常,则整个try、catch、finally块中抛出异常

所以使用try、catch、finally语句块中需要注意的是

1> 尽量在try或者catch中使用return语句。通过finally块中达到对try或者catch返回值修改是不可行的。

2 >finally块中避免使用return语句,因为finally块中如果使用return语句,会显示的消化掉try、catch块中的异常信息,屏蔽了错误的发生

3 >finally块中避免再次抛出异常,否则整个包含try语句块的方法回抛出异常,并且会消化掉try、catch块中的异常

7.奇数的判断

public static boolean oddOrNot(int num) {
    return num % 2 == 1;
}

看似正确,但是当num为负数时会出现bug

public static boolean oddOrNot(int num) {
    return (num & 1) != 0;
}

使用此代码,不仅是解决了奇数为负的问题,而且这个代码也高度优化。因为,算术和逻辑运算的速度更快,比除法和乘法,结果取得了更快。

8.单引号和双引号之间的区别

public static void main(String[] args) {
    System.out.println("H" + "a");
    System.out.println('H' + 'a');
}
-----------------------------------------
Ha
169

注意加号既能做加法也能做拼接,字符串时拼接,字符默认会转为int,所以做了加法

9.synchronized、ReentrantLock和ReadWriteLock的区别

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

  • ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁
  • ReentrantLock可以获取各种锁的信息
  • ReentrantLock可以灵活地实现多路通知

另外,二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word,这点我不能确定。

首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。

因为这个,才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

10.日志规约

1、对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。

说明: logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象,会执行 toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。

正例: (条件)

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}

正例: (占位符)

logger.debug("Processing trade with id: {} symbol : {} ", id, symbol); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值