Java面试总结(一)

陷阱:ArrayList遍历时问题

public class Demo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(5);
        list.add(5);
        list.add(6);
        list.add(7);

        int removeValue = 5;
        for (int i = 0; i < list.size(); i ++) {
            if ( list.get(i) == removeValue ) {
                list.remove(i);
            }
        }
        for (int i = 0; i < list.size(); i ++) {
            System.out.println(list.get(i));
        }
    } 
}

告诉我你认为的答案:

如果你原来没注意过这样的问题那么你一定会出错:

分析:
这里写图片描述
你一定在想为什么:

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
}

这里是remove的源码
这里看不到我们想要的跟到fastRemove()

private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
}

size肯定是list的有效元素长度
index是当前数组下标
但是fastRemove()一次后,index并没有回退,而是继续执行,所以结果你就知道了把

解决
我只是点一下,为什么这样做自己想
1. index –;
2. 向后遍历删除
3. 迭代器Iterator删除
4.

public E next() {
5.              checkForComodification();
6.              int i = cursor;
7.              if (i >= size)
8.                  throw new NoSuchElementException();
9.              Object[] elementData = ArrayList.this.elementData;
10.             if (i >= elementData.length)
11.                 throw new ConcurrentModificationException();
12.             cursor = i + 1;
13.             return (E) elementData[lastRet = i];
14. }

    1. 16.
public void remove() {
17.             if (lastRet < 0)
18.                 throw new IllegalStateException();
19.             checkForComodification();
20. 
21.             try {
22.                 ArrayList.this.remove(lastRet);
23.                 cursor = lastRet;
24.                 lastRet = -1;
25.                 expectedModCount = modCount;
26.             } catch (IndexOutOfBoundsException ex) {
27.                 throw new ConcurrentModificationException();
28.             }
29. }

Iterator里通过next()获取数据, i 执行当前cursor时,当前cursor + 1, 返回element[i]也是就当前的数据,lastRet则记录当前操作完的下标i。
因为我们通过迭代器获取数据时首先通过hasNext()看是否有数据,再通过next()得到当前数据,如果这进行remove(lastRet)说明删除了当前元素(lastRet在next()时指向了当前的索引),而remove中的cursor又重新指向lastRet相当于做了一次回退操作
扩展下
== 与 equals

public class Demo2 {
    public static void main(String[] args) {
        Integer a = 12;
        Integer b = 12;
        System.out.println(a == b);
        a = 9999;
        b = 9999;
        System.out.println(a == b);
    }
}

答案是: true false
为什么
源码:

public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}

对1 个字节长度(-128 ~ 127 )进入了一次缓存
缓存里的直接引用缓存地址,所以第一为true,不在缓存里的new一个对象出来,所以2为false

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
equals就更简单了,匹配类型,再匹配内容

如果扯远了就有String,StringBuffer,StringBuild, String 的 == 与equals, intern。还有Java对象值传递还是对象传递问题了。
多花点时间看看源码就都OK了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值