Java基础面试技巧

List集合常见错误总结(经验教训)

2019-04-15  本文已影响29人  莫问以

新手都容易犯这个错误,先看代码:

        List<String> list = new ArrayList<String>();
        
        for(int i=0;i<list.size();i++){
            System.err.println(list.get(i).toString());
        }
        if(list!=null){
            System.out.println("不为空");
        }else{
            System.out.println("为空,需进行赋值判断");
        }
结果是不为空.png

改代码如下:

        if(!list.isEmpty()){
            System.out.println("不为空");
        }else{
            System.out.println("为空,需进行赋值判断");
        }

改成以上代码,ok了!这个错误就是对集合判断是否为Null出错,需要加上list.size()>0或者使用才可以list.isEmpty()才行。
List list=new ArrayList();
像这样的list不为null(我们会错误地以为此时list为null),但是判断size的时候,实则是为0,所以判断集合的时候,一定记得要双重判断。即list!=null && list.size()>0才好。
PS:list.isEmpty()和list.size()==0 没有区别, isEmpty()判断有没有元素,而size()返回有几个元素,如果判断一个集合有无元素,建议用isEmpty()方法,该方法简单、清晰明了!

public class ListGu {
    
    private static List<String> list;
    
    public static void main(String[] args) {
        setList();
    }
    
    //对集合重新赋值
    private static void setList() {
        for(int i=0;i<10;i++){
            list.add(String.valueOf(i));
        }
        
        for(int i=0;i<list.size();i++){
            System.err.println(list.get(i).toString());
        }
    }   
}

上面的代码乍一看,没毛病,可是一运行:

竟然报空指针异常.png

按住ctrl键,点List进去看底层源码:

List底层源码.png

擦,竟然是个接口,竟然没new对象就直接赋值。发现问题,及时改正:

public class ListGu {
    
    private static List<String> list;
    
    public static void main(String[] args) {
        setList();
    }
    //对集合重新赋值
    private static void setList() {
        for(int i=0;i<10;i++){
            list = new ArrayList<String>();  //new对象
            list.add(String.valueOf(i));
        }
        
        for(int i=0;i<list.size();i++){
            System.err.println(list.get(i).toString());
        }
    }
}

运行代码,竟然不是预想中的结果:

竟然不是预想中的结果.png

这又是为什么呢?现在我们知道,使用List时,需要new对象,仔细一看,擦,竟然在循环里new对象,这种错误,特别容易犯!!

public static void main(String[] args) {
        List<List<String>> list=new ArrayList<>();

        List<String> list2=new ArrayList<>();
        for(int i=0;i<10;i++){
            list2.add(""+i);    
            list.add(list2);
            list2.clear();
        }
        // 遍历List
        for(int i=0;i<list.size();i++){
            System.err.println(list.get(i).toString());
        }
    }

乍一看以上代码,没毛病,很简单的逻辑,少new一个对象,可以达到节省优化代码,节省虚拟机内存,可是一运行,擦,竟然是这样的结果:

结果竟然是null.png

这个错误引起就是因为list中存储的是对象的引用,而不是对象本身。如果不清楚这一点,会常踩这个坑。该代码虽然可以达到一个对象重复使用的效果,但是因为list存储的是对象的引用,所以当list2.clear()的时候,list中的list2也会clear,这样最后得到的就只能是一堆空的集合。

集合对照图.png

上图完美的诠释了集合之间的关系,常见的集合分三大类:List,Set和map三种,List与Set是继承自Collection,而map(这里指统称)继承自Map。

List与Set的区别

List中的元素有存放顺序,而且可存放重复元素,检索效率高,插入删除效率低

Set没有存放顺序,而且不可以存放重复元素,后来的元素会把前面重复的元素替换掉,检索效率低,插入删除效率高。
(Set存储位置由HashCode码决定,所以它存储的对象必须有equals()方法,而且Set遍历只能用迭代,因为它没有下标。)

Vector和ArrayList与LinkedList

LinkedList与ArrayList是互相弥补对方而存在,二者为互补关系,所以如果使用过程中觉得ArrayList的缺点太多,你就可以使用LinkedList,相反也是如此。

ArrayList的特点?
集合中元素存储的位置是连续的,所以查询起来会比较快,但是插入删除效率低(会引起其他元素位置的变化)。

LinkedList的特点?
集合中元素位置是任意的,所以执行插入删除操作效率较高,查询效率较低。

Vector的特点?
线程安全,因为很多方法都用synchonized修饰,但是效率比较低,如果要考虑线程安全的话可以用。

上一篇 下一篇

猜你喜欢

热点阅读