关于ArrayList的几个知识点

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


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


//ArrayList Add方法:

public boolean add(E e){

    ensureCapacity(size+1); //ensureCapacity增加ArrayList此实例的容量

    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;//原来数组长度的1.5倍+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。这里的主要原因是,LinkedList只需要O(1)的时间复杂度,而在ArrayList中,需要O(n)的时间复杂度.通常会调用System.arraycopy方法,这是一种极为消耗资源的操作,因此,在频繁的插入或者是删除元素的情况下,LinkedList的性能会更加好一点。


总结:

时间复杂度来说,如果对list增加或删除操作较多,优先用LinkedList;如果查询操作较多,优先用ArrayList。

空间复杂度来说,LinkedList会占用较多空间。



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


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


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

public void setArray(String[] myArray){

this.myArray=myArray;

}


修复这个安全隐患:

public void setArray(String []myArray){

if(myArray==null){

myArray=new String[0];

}else{

this.myArray=Arrays.copyOf(myArray,myArray.length);

}

}


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

a、使用clone()方法,比如ArrayList newArray = oldArray.clone();

b、使用ArrayList构造方法,比如:ArrayList myObject = new ArrayList(myTempObject);

c、使用Collections的copy方法。


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


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


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


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



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


6、 如何边遍历边移除Collection中的元素


边遍历边修改Collection的唯一正确方式是使用Iterator.remove()方法,如下:


Iterator<Integer> it = list.iterator();

while(it.hasNext()){

    // do something

    it.remove();

}


一种最常见的错误代码如下:


for(Integer i : list){

    list.remove(i)

}


运行以上错误代码会报ConcurrentModificationException异常。这是因为当使用foreach(for(Integer i : list))语句时,会自动生成一个iterator来遍历该list,但同时该list正在被Iterator.remove()修改。在Java中,一般不允许一个线程在遍历collection时另一个线程在修改它。

7、如何将一个list转换成int[]类型的数组

通过list.toArray转换,实际是将list转换成了Integer [],而不是int[]。正确做法应该是使用for循环,取出元素重新赋值

8、如何删除一个list中的重复元素

a、如果没有要求元素顺序,可以考虑使用set集合

Set <Integer> set=new HashSet <Integer>(list);

list.clear();

list.addAll(set);


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值