1.如何优雅的避免空指针异常
1.1 使用if-else判断,避免空指针问题,但是嵌套层次多
if (!Objects.isNull(user.getName())){
mike.setName(user.getName());
}
1.2 使用Optional直接判空处理,使代码结构更加美观
public static void main(String[] args) {
SmLineInfoVo lineInfoVo = new SmLineInfoVo();
String infoVo = Optional.ofNullable(lineInfoVo.getWorkshopVo())
.map(SmWorkshopVo::getWorkshopCode)
.orElse(null);
System.out.println(infoVo);
}
1.3 使用断言处理空指针异常,返回提示信息
Assert.notNull(user.getName(),"名称不可为空")
注意,直接嵌套的调用的话,比如x.getA().getB(),如果A为null,无论什么方法都会报错空指针
2.CopyOnWrite
实现原理就是当你想对一块内存进行修改的时候,不在原有的内存条中进行操作,而是将内存拷贝一份,在新的内存中进行写操作,然后再将原来内存的指针指向新的内存,原来的内存就可以被回收掉了
情景条件:多线程场景下使用迭代器进行读取操作和其他线程对集合进行写入操作会操作并发异常
解决办法:使用CopyOnWriteArrayList去进行并发操作
优点:线程安全,并且操作不会抛出并发异常
问题:写操作性能较低,每一次写操作,都需要复制一份,内存占用成本增加,由于是并发遍历操作读取,可能会读到旧数据,没有时效性
3.List操作的常见问题
3.1 Arrays.asList转化基本类型数组错误
原因:不可以直接使用基础类型直接转化
解决办法:1.将数组类型修改为包装类
2.Arrays.stream(arr).boxed(),将原数组数据类型通过代码转化为包装类型
3.2 Arrays.asList返回的List不支持增删修操作,异常报错
原因:返回的List是Arrays的内部类,没有实现add和remove方法
解决办法:new出一个心的ArrayList接收返回的List,对新的集合进行操作
3.3 当对原始数组修改时,会影响转化得到的List
原因:asList中创建了ArrayList,但是他直接引用的原本的数据对象
解决办法:new出一个心的ArrayList接收返回的List,对新的集合进行操作
3.4 ArrayList中的subList强转ArrayList导致异常,对子集合操作,父集合也会一起变化
原因:subList返回的是ArrayList的内部类SubList,而不是ArrayList,是ArrayList的一个视图,等于SubList子列表的所有操作会反映到原列表上
解决办法:new出一个心的ArrayList接收返回的List,对新的集合进行操作
3.5 ArrayList的subList切片造成的OOM
原因:由于原List是强引用,得不到回收,导致了OOM
解决办法:切断与原始List的关系,subList返回List后,重新new一个ArrayList来接受,使用独立的ArrayList,或者使用Steam中的skip和limit来进行切片
4.如何优雅的删除HashMap元素
4.1 使用增强for循环删除
使用HashMap的entrySet方法获取所有元素集合,再进行循环遍历,判定value值是否需要删除,再移除对应的key,但是需要注意的是for循环的底层使用的是迭代器Iterator,而HashMap是fail-fast原则的错误机制,所以遍历时删除元素会出现并发异常,可以使用CopyOnWriteArraySet封装一层,避免出现并发修改异常
4.2 使用forEach循环删除
使用forEach方法循环删除目标元素,使用ConcurrentHashMap避免出现并发修改异常
4.3 使用Iterator迭代器删除
由于HashMap是不安全的,也是使用ConcurrentHashMap避免出现并发修改异常
4.4 使用removeIf删除(推荐使用,老优雅了)
但是底层其实还是利用迭代器实现的,所以也是要考虑线程安全的并发情况的
4.5 使用Stream删除(推荐使用,也十分优雅)
先调用entrySet调出所有元素,然后使用steam流的filter条件过滤,发回一个新的map,没有并发问题
5.使用BigDecimal的坑
5.1 使用BigDecimal.valueOf()的方式或者字符串的方式避免出现精度问题
5.2 使用compareTo的方法和equals()方法进行数值比较
备注:equals还会比较精度,精度不同也会返回false。compareTo为0表示相同
5.3 使用正确的舍入模式
在进行BigDecimal运算前,明确指定精度和舍入模式很重要,避免异常情况,使用setScale方式设置精度,使用setRoundingMode方式设置舍入模式