做java开发也有一年多了,对于数组、集合的使用也不少,今天抽出时间把它们系统的梳理一下,整理出以下内容:
首先让我们来看Collection FrameWork:
Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)
一、ArrayList(动态数组),Vector(对象数组), LinkedList(链表)的存储性能和特性
1、ArrayList使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢
2、Vector同样也是使用了数组方式存储数据,但是由于使用了synchronized方法(线程安全),通常性能上较ArrayList要差
3、LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
二、ArrayList和Vector同样都是使用数组方式存储数据,那么它们有区别吗
ArrayList和Vector的区别主要体现在以下两个方面
1、同步性:Vector是线程安全的,是线程同步的,而ArrayList是线程序不安全的,线程不同步的。如果只有一个线程会访问到集
合,最好使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程访问集合,最好使用Vector。
2、数据增长:ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList
与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在
内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从
源代码看到的是增长为原来的1.5倍)。ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而
ArrayList没有提供设置增长空间的方法。可见:即Vector增长原来的一倍,ArrayList增加原来的0.5倍。
三、ArrayList的大小是如何自动增加的
事实上,当有人试图在ArrayList中增加一个对象的时候,Java会去检查ArrayList,以确保已存在的数组中有足够的容量来存储
这个新的对象。如果没有足够容量的话,那么就会新建一个长度更长的数组,旧的数组就会使用Arrays.copyOf方法被复制到新的数
组中去,现有的数组引用指向了新的数组。代码如下:
//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);
}
}
四、什么时候使用ArrayList,什么时候使用LinkedList
根据ArrayList和LinkedList的存储性能和特性,多数情况下,当遇到访问元素比插入或者是删除元素更加频繁的时候,应该使
用ArrayList。另一方面,当在某个特别的索引中,插入或者是删除元素更加频繁,或者压根就不需要访问元素的时候,此时应选择
LinkedList。这里的主要原因为,在ArrayList中访问元素的最糟糕的时间复杂度是“1″,而在LinkedList中可能就是“n”了。在ArrayList中增加或者删除某个元素,通常会调用System.arraycopy方法,这是一种极为消耗资源的操作,因此,在频繁的插入或者是删除元素的情况下,LinkedList的性能会更加好,效率更高。
五、当传递ArrayList到方法中,或者方法返回ArrayList,什么时候需要考虑安全问题呢?如何避免?
当array被当做参数传递到某个方法中,如果array在没有被复制的情况下直接被分配给了成员变量,那么就可能发生这种情
况,即当原始的数组被调用的方法改变的时候,传递到这个方法中的数组也会改变。
public void setMyArray(String[] myArray) {
this.myArray = myArray;
}
如何避免:
public void setMyArray(String[] newMyArray) {
if(newMyArray == null) {
this.myArray = new String[0];
} else {
this.myArray = Arrays.copyOf(newMyArray ,newMyArray .length);
}
}
六、如何复制某个ArrayList到另一个ArrayList中去
以下是把某个ArrayList复制到另一个ArrayList中去的几种技术:
1、使用clone()方法,例:ArrayList newArray = oldArray.clone();
2、使用ArrayList构造方法,
例:ArrayList myObject = new ArrayList(myTempObject);
3、使用Collection的copy方法
七、在ArrayList中增加或者删除元素时效率怎样
在ArrayList中增加或者是删除元素时,需要调用System.arraycopy这种效率很低的操作,所以效率很低。