List集合实现类之ArrayList、Vector和LinkedList

List集合的实现类有3种,分别是ArrayList、Vector和LinkedList,下面我将对这3个实现类的区别进行详细讲解。

1)ArrayList
ArrayList继承自AbstractList而实现了List,它是最常用的List实现类,内部是通过数组实现的,所以插入或者删除元素时,需要对数组进行复制、移动、代价比较高,因此,它适合随机查找和遍历,不适合插入和删除。

public class ArrayListTest {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(5);
		list.add(6);
		list.add(7);
		list.add(8);
		list.add(9);
		list.add(10);
		
		// 通过迭代器遍历
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + " ");
		}
		System.out.println("\n--------------------------");
		
		// for循环遍历
		for (Integer integer : list) {
			System.out.print(integer + " ");
		}
		System.out.println("\n--------------------------");
		
		// 随机访问,通过list.get(i)获得索引值去遍历。
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " ");
		}
	}
}

ArrayList之所以线程不安全,从其add()方法就可以看出:

public boolean add(E e) {
	ensureCapacityInternal(size + 1);  //确保容量是否充足
	elementData[size++] = e;           //将元素添加至数组
	return true;
}

从底层源码可以看出,add()添加元素的时候是分两步走的:

(1)elementData[size] = e;           

(2)size++;

     假设有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停(线程A仅仅完成了步骤1,Size没有自增),线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,此时 Size 仍然等于 0 ,所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。 那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。 

2)LinkedList
LinkedList底层采用链表结构进行数据存储,很适合数据的动态插入和删除(add()和remove()方法),随机访问和遍历速度比较慢。需要注意的是:LinkedList提供了List接口中未定义的方法,专门用于操作表头和表尾元素,所以可以当作堆栈、队列和双向队列使用。

public class LinkedListTest {
	public static void main(String[] args) {
		List<Integer> list = new LinkedList<Integer>();
		list.add(5);
		list.add(6);
		list.add(7);
		list.add(8);
		list.add(9);
		list.add(10);

		// 通过迭代器遍历
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + " ");
		}
		System.out.println("\n--------------------------");
		
		// for循环遍历
		for (Integer integer : list) {
			System.out.print(integer + " ");
		}
		System.out.println("\n--------------------------");
		
		// 随机访问,通过list.get(i)获得索引值去遍历,不建议
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " ");
		}

	}
}

3)Vector
Vector底层也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。


public class VectorTest {
	public static void main(String[] args) {
		Vector<Integer> vec = new Vector<Integer>();
		vec.add(5);
		vec.add(6);
		vec.add(7);
		vec.add(8);
		vec.add(9);
		vec.add(10);

		// 通过迭代器遍历
		Integer value = null;
		for (int i = 0; i < vec.size(); i++) {
			value = (Integer) vec.get(i);
			System.out.println(value + " ");
		}
		System.out.println("\n--------------------------");

		// for循环遍历
		Integer value2 = null;
		for (Integer integ : vec) {
			value2 = integ;
			System.out.println(value2 + " ");
		}
		System.out.println("\n--------------------------");

		// 随机访问,通过索引值去遍历(Vector实现了RandomAccess接口,支持通过索引值去随机访问元素)
		Integer value3 = null;
		for (int i = 0; i < vec.size(); i++) {
			value3 = (Integer) vec.get(i);
			System.out.println(value3 + " ");
		}
		System.out.println("\n--------------------------");

		// Enumeration遍历
		Integer value4 = null;
		Enumeration enu = vec.elements();
		while (enu.hasMoreElements()) {
			value4 = (Integer) enu.nextElement();
			System.out.println(value4 + " ");
		}

	}
}
发布了224 篇原创文章 · 获赞 34 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_39309402/article/details/104858819