java的开发人员数量_Java开发人员最容易出现的几类错误
一、把数组转成ArrayList
List list = Arrays.asList(arr);
//以下带伪代码来自Arrays类中
public static List asList(T... a) {
return new ArrayList<>(a);
}
private static class ArrayList extends AbstractList
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
}
使用Arrays.asList()方法可以得到一个ArrayList,但是得到这个ArrayList其实是定义在Arrays类中的一个私有的静态内部类。这个类虽然和java.util.ArrayList同名,但是并不是同一个类。java.util.Arrays.ArrayList类中实现了set(), get(), contains()等方法,但是并没有定义向其中增加元素的方法。也就是说通过Arrays.asList()得到的ArrayList的大小是固定的。
二、在循环中删除列表中的元素
ArrayList list = new ArrayList(Arrays.asList("a","b","c","d"));for(int i=0;i
list.remove(i);
}
System.out.println(list);
输出结果:
[b,d]
以上代码的目的是想遍历删除list中所有元素,但是结果却没有成功。原因是忽略了一个关键的问题:当一个元素被删除时,列表的大小缩小并且下标也会随之变化,所以当你想要在一个循环中用下标删除多个元素的时候,它并不会正常的生效。
也有些人知道以上代码的问题就由于数组下标变换引起的。所以,他们想到使用增强for循环的形式:
ArrayList list = new ArrayList(Arrays.asList("a","b","c","d"));for(String s:list){if(s.equals("a")){
list.remove(s);
}
}
但是,很不幸的是,以上代码会抛出ConcurrentModificationException,有趣的是,如果在remove操作后增加一个break,代码就不会报错:
ArrayList list = new ArrayList(Arrays.asList("a","b","c","d"));for(String s:list){if(s.equals("a")){
list.remove(s);break;
}
}
迭代器被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 迭代器会马上抛出java.util.ConcurrentModificationException 异常。
所以,正确的在遍历过程中删除元素的方法应该是使用Iterator:
ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
Iterator iter =list.iterator();while(iter.hasNext()) {
String s=iter.next();if (s.equals("a")) {
iter.remove();
}
}
next()方法必须在调用remove()方法之前调用。如果在循环过程中先调用remove(),再调用next(),就会导致异常ConcurrentModificationException。原因如上。
三、迷之求和
public voidtest_add(){int num = 0;for (int i = 0; i < 100; i++) {
num= num++;
}
System.out.println(num);
}
最终 num 结果为 0,num++ 根本没起啥作用。因为后++,是先用结果,在++操作,不会给赋值。正确写法是:num = ++ num;
四、无用日志
public booleanruleEngine(MatterReq req) {try{//业务流程
} catch(Exception e) {
logger.error(e);//只打异常,不打入参信息
}
}
五、耗时遍历
public voidtest_LinkedList() {//初始化100万数据
List list = new LinkedList(1000000);//遍历求和
int sum = 0;for (int i = 0; i < list.size(); i++) {
sum+=list.get(i);
}
}
乍一看可能觉得没什么问题,但是这个遍历求和会非常慢。主要因为链表的数据结构,每一次list.get(i)都是从链表的头开始查找,与ArrayList不同,LinkedList它时间复杂度是O(n)。那如果说你不知道对方传过来的是LinkedList还是ArrayList呢,其实可以通过list instanceof RandomAccess 进行判断。ArrayList 有随机访问的实现,LinkedList 是没有。同时也可以使用增强的for循环或者Iterator进行遍历。