关于ArrayList的5道面试题

我以面试官的身份参加过很多Java的面试,以下是五个比较有技巧的问题,我发现有些初级到中级的Java研发人员在这些问题上没有完全弄明白,似懂非懂。所以我写了一篇相关的文章,帮助初级Java研发人员弄清楚这些问题。文章列举了和Java ArrayList相关的5个比较具有迷惑性的问题,我相信如果面试者能够很好的回答出这些问题,那么在面试的时候你一定能够得到不错的分数。如果你同意我的看法,或者除了下面的问题,你还有其他比较好的问题,那么就请联系我吧。

1、ArrayList的大小是如何自动增加的?你能分享一下你的代码吗?

这是最有技巧性的的一个问题,大多数人都无法回答。事实上,当有人试图在arraylist中增加一个对象的时候,Java会去检查arraylist,以确保已存在的数组中有足够的容量来存储这个新的对象。如果没有足够容量的话,那么就会新建一个长度更长的数组,旧的数组就会使用Arrays.copyOf方法被复制到新的数组中去,现有的数组引用指向了新的数组。看如下的代码段(摘自GrepCode.com中的Java ArrayList Code):

//ArrayList Add方法:
public boolean add(E e){
    ensureCapacity(size+1); //Increment modCount!!
    elementData[size++] = e;
    return true;
}

//ensureCapacity方法:处理ArrayList的大小
public void ensureCapacity(int minCapacity) {
	modCount++;
	int oldCapacity = elementData.length;
	if (minCapacity > oldCapacity) {
	Object oldData[] = elementData;
	int newCapacity = (oldCapacity * 3)/2 + 1;
	if (newCapacity < minCapacity)
		newCapacity = minCapacity;
	// minCapacity is usually close to size, so this is a win:
	elementData = Arrays.copyOf(elementData, newCapacity);
    }
}

请注意这样一个情况:新建了一个数组;旧数组的对象被复制到了新的数组中,并且现有的数组指向新的数组。

2、什么情况下你会使用ArrayList?什么时候你会选择LinkedList?

这又是一个大多数面试者都会困惑的问题。多数情况下,当你遇到访问元素比插入或者是删除元素更加频繁的时候,你应该使用ArrayList。另外一方面,当你在某个特别的索引中,插入或者是删除元素更加频繁,或者你压根就不需要访问元素的时候,你会选择LinkedList。这里的主要原因是,在ArrayList中访问元素的最糟糕的时间复杂度是”1″,而在LinkedList中可能就是”n”了。在ArrayList中增加或者删除某个元素,通常会调用System.arraycopy方法,这是一种极为消耗资源的操作,因此,在频繁的插入或者是删除元素的情况下,LinkedList的性能会更加好一点。

3、当传递ArrayList到某个方法中,或者某个方法返回ArrayList,什么时候要考虑安全隐患?如何修复安全违规这个问题呢?

当array被当做参数传递到某个方法中,如果array在没有被复制的情况下直接被分配给了成员变量,那么就可能发生这种情况,即当原始的数组被调用的方法改变的时候,传递到这个方法中的数组也会改变。下面的这段代码展示的就是安全违规以及如何修复这个问题。

ArrayList被直接赋给成员变量——安全隐患:

修复这个安全隐患:

4、如何复制某个ArrayList到另一个ArrayList中去?写出你的代码?

下面就是把某个ArrayList复制到另一个ArrayList中去的几种技术:

  1. 使用clone()方法,比如ArrayList newArray = oldArray.clone();
  2. 使用ArrayList构造方法,比如:ArrayList myObject = new ArrayList(myTempObject);
  3. 使用Collection的copy方法。

注意1和2是浅拷贝(shallow copy)。

5、在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?

在ArrayList中增加或者是删除元素,要调用System.arraycopy这种效率很低的操作,如果遇到了需要频繁插入或者是删除的时候,你可以选择其他的Java集合,比如LinkedList。看一下下面的代码:

在ArrayList的某个索引i处添加元素:

删除ArrayList的某个索引i处的元素:

原文链接: vitalflux 翻译: ImportNew.com - kobekillerjun
译文链接: http://www.importnew.com/9928.html
[ 转载请保留原文出处、译者和译文链接。]



相关文章

发表评论

Comment form

(*) 表示必填项

10 条评论

  1. chenssy 说道:

    我真心不知道这5个问题有什么弄不懂的?对于第二个问题LZ你真的测试过了么?你试试20W+个数据在25W+处插入1W个数据看看,看谁快谁慢!

    Thumb up 1 Thumb down 0

  2. 王骞 说道:

    泼点冷水:这几个问题问的真烂,显得面试官一点水平也没有。Importnew多推些像HashMap Hastable面试题那样质量好点的文章

    Thumb up 3 Thumb down 2

  3. coffee_guy 说道:

    是说第一个怎么看着有点问题,原来JDK和OpenJDK有差异的说。分析了JDK6、JDK7里面的实现ArrayList的扩容方式是一样的。下面是实现过程
    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity – minCapacity 0)
    newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    自我感觉要优于openjdk中的实现

    Thumb up 1 Thumb down 0

  4. zhuven 说道:

    try to commit

    Thumb up 1 Thumb down 0

  5. andyyuan 说道:

    第四个问题Collection的copy方法 是不是也是浅拷贝?

    Thumb up 0 Thumb down 0

  6. andyyuan 说道:

    第三个问题,如果是对数组中元素的修改,这种方法还是无效,arrays是浅拷贝。

    Thumb up 0 Thumb down 0

  7. jfzlnyf 说道:

    Collections.copy()也是浅copy,可以去看下源码。
    大家千万别被误导了。

    Thumb up 1 Thumb down 0

  8. sam 说道:

    第四个的第三个类写错了,是collections,少了s

    Thumb up 1 Thumb down 0

  9. tony 说道:

    问题四 我表示 浅拷贝 深拷贝傻傻分不清楚

    Thumb up 0 Thumb down 0

  10. twocold 说道:

    System.arraycopy 效率很高的啊

    Thumb up 0 Thumb down 0

跳到底部
返回顶部