2.List接口

一.Vector

  1. JDK2之前(在集合框架之前),要存储多个数据,此时存在一个叫Vector类.
    Vector类的底层其实就是一个Object数组,Vector类中的方法时支持同步(方法使用synchronized修饰)的.

  2. Vector类设计原理,查看源代码

image

  1. Vector类存储原理
    通过源码分析,发现在Vector类中有一个Object()[]类型数组.
    protected Ojbect[] elementDate;

    1. 表面上把数据存储到Vector对象中,其实底层依然是把数据存储到Object数组中
    2. 我们发现该数组元素类型是Object类型,意味着集合中只能存储任意类型的对象.
      集合中只能存储对象,不能存储基本数据类型的值
      在Java5之前,必须对基本数据类型手动装箱.
    v.addElement(Integer.valueOf(123));
    

    从Java5开始支持自动装箱操作,代码

    v.addElement(123);  
    

    其实底层依然是手动装箱

    注意:修改项目的编译级别到Java5或者Java5以上.

    ![image][Java5]
    3. 集合类中存储的对象,都存储对象的引用.而不是对象本身
    ![image][cite]

新建类VectorDemo

//Vector类的演示
public class VectorDemo {
	public static void main(String[] args) {
		Vector vector = new Vector();
		vector.addElement("a");
		vector.addElement("AA");
		vector.addElement(12);
		StringBuilder sb = new StringBuilder();
		sb.append("last");
		vector.addElement(sb);
		System.out.println(vector.toString());
		sb.append("com");
		System.out.println(vector.toString());		
	}
}

  1. 集合类的操作方法:

  2. 常用方法:

  3. 增加:

    1. boolean add(Object e): 将指定元素添加到此向量的末尾
    2. void add(int index,Object element):在此向量的指定位置插入指定的元素
    3. boolean addAll(Collection c):把c集合中的元素添加到当前集合对象中

![image][method]

  1. 删除:

    1. Object remove(int index):删除指定索引位置的元素,并返回删除之后的元素
    2. boolean remove(Object o):删除指定的元素.
    3. boolean removeAll(Collection c):从此集合中移除包含在指定集合c中的所有元素
    4. boolean retainAll(Collection c):在此集合中仅仅保留包含在指定集合c中的元素
  2. 修改:

    1. Object set(int index,Object element):修改当前集合中指定索引位置的元素
      返回被替换的旧元素
  3. 查询:

    1. int size():返回当前集合中存储几个元素
    2. boolean isEmpty():判断当前集合中元素个数是否为0
    3. Object get(int index):查询指定索引位置的元素
    4. Object[] toArray():把集合对象转换为Object数组

新建类VectorMethodDemo

public class VectorMethodDemo {

	public static void main(String[] args) {
		//testAdd();
		//testDelet();
		//testUpdate();
		testQuery();
	}

	//查询
	private static void testQuery() {
		Vector v = new Vector();
		v.add("A");
		v.add("B");
		v.add("C");
		v.add("C");
		v.add("F");
		System.out.println(v.toString());
		System.out.println(v.size());
		System.out.println(v.isEmpty());
		System.out.println(v.get(2));
		Object[] o = v.toArray();
		System.out.println(Arrays.toString(o));
	}

	//更新
	private static void testUpdate() {
		Vector v = new Vector();
		v.add("A");
		v.add("B");
		v.add("C");
		v.add("C");
		v.add("F");

		v.set(3, "D");
		System.out.println(v.toString());
	}

	//删除
	private static void testDelet() {
		Vector v = new Vector();
		v.add("A");
		v.add("B");
		v.add("C");
		v.add("C");
		v.add("F");
		v.remove(0);
		Vector v1 = new Vector();
		v1.add("C");
		v1.add("B");
		System.out.println(v.toString());
		v.remove("A");
		//v.removeAll(v1);
		v.retainAll(v1);
		System.out.println(v.toString());

	}

	//添加
	private static void testAdd() {
		Vector v = new Vector();
		v.add("A");
		v.add("B");
		v.add("C");
		v.add(1, "F");
		System.out.println(v.toString());
		Vector v1 = new Vector();
		v1.add("A");
		v1.add("B");
		v1.add("C");
		v.add(1, v1);
		System.out.println(v.toString());
		v.addAll(1, v1);
		System.out.println(v.toString());
	}

}

二.栈(Stack)

  1. 数据结构的一种,存储特点Last in First Out
  2. Stack 类表示后进先出(LIFO)的对象栈

官方建议:使用栈尽量使用ArrayDeque:

Deque 接口及其实现提供了 LIFO 堆栈操作的更完整和更一致的 set,应该优先使用此 set,而非此类。例如:

Deque<Integer> stack = new ArrayDeque<Integer>();

新建类StackDemo

public class StackDemo {
	public static void main(String[] args) {
		Stack s = new Stack();
		s.push("A");
		s.push("B");
		s.push("C");
		s.push("D");
		System.out.println(s.toString());
		System.out.println(s.peek());
		s.pop();
		System.out.println(s.peek());
		
		ArrayDeque as = new ArrayDeque();
		as.push("A");
		as.push("B");
		as.push("C");
		as.push("D");
		System.out.println(as.toString());
		System.out.println(as.peek());
		as.pop();
		System.out.println(as.peek());
	}
}

三.ArrayList类

  1. ArrayList类是Java集合框架出现之后,取代Vector类的
    二者底层原理相同
  2. 区别:
    1. Vector:所有方法使用synchronized修饰符.
    2. 线程安全但是性能较低,使用于多线程环境
    3. ArrayList:所有方法都没有使用synchronized修饰符 线程不安全,但是性能高

以后即使在多线程的环境下,也不使用Vector类

ArrayList list = Collections.synchronizedList(new ArrayList(...));
  1. 阅读源码发现
    1. Vector和ArrayList的源代码差异有点大(从设计上考虑)
    2. 有时候某个方法需要返回一个ArrayList对象:
      但是在该方法中,如果一个都没有查询到,我们不会返回null,我们会返回一个空集对象(没有元素的集合)
public ArrayList getAll(){
    //return Collections.emptyList();//最好的方式
    return new ArrayList();//但是很多人最直观,最简单选用的方式
}
  1. 在Java7之前,即使使用new ArrayList创建对象,一个元素都不存储,但是在对空间依然初始化了长度10
    的Object数据,没有必要.
    从Java7开始优化这个设计,
    new ArrayList,其实底层创建的使用一个空数组.
Object[] elementDate = new Object[]{};

在第一次调用add方法的时候,才会从新去初始化数组.

四.LinkedList

  1. LinkedList类是双向链表,单向队列,双向队列的实现类

  2. LinkedList类实现单向队列和双向队列的接口,自身提高了栈操作的方法,链表操作的方法.

  3. LinkedList类中存在很多方法,但是功能都是相同的,LinkedList表示了多种数据结构的实现,每一种数据
    结构的操作名字都不同.

![image][table1]

![image][table2]

![image][table3]

![image][table4]

  1. LinkedList类是线程不安全的类,在多行程环境下,下面保证线程的安全
List list = Collections.synchronizedList(new LinkedList(...));

  1. 面试题:编写一个双向链表
    无论是链表还是队列,都特别擅长操作头和尾的节点
    在LinkedList中大多数方法都是xxFirst/xxLast

  2. 在LinkList中存在Object get(int index),表示根据索引位置获取对应的元素.
    链表没有索引的概念,但是从Java2开始,存在了集合框架,让LinkedList类作为List接口的实现类.

  3. List类中提供了该根据索引查询元素的方法,LinkedList内部类提供了一个变量来当做索引
    该方法少用,因为LinkedList不擅长查询操作.

新建类LinkedListDemo

public class LinkedlistDemo {
	public static void main(String[] args) {
		LinkedList ll = new LinkedList();
		ll.addFirst("H");
		ll.addFirst("K");
		ll.addLast("U");
		System.out.println(ll.toString());		
		System.out.println(ll.get(2));
		System.out.println(ll.indexOf("K"));
	}
}

五.Java集合框架-重构设计

![image][Java1]

![image][Java2]

![image][Java3]

  1. 根据Vector类,ArrayList类,LinkedList类,所具有的存储特点以及拥有的方法入手,发现共性就往上抽取.
    共同特点:
    1. 允许元素重复的
    2. 会记录先后添加的顺序
  2. 共同方法:如上图
  3. 根据他们的特点,可以指定规范:
    遵循该规范的实现类,无论底层算法如何,都必须保证允许元素重复和保证添加先后顺序.
  4. 给该规范起名:List
    在Java中规范使用接口表示

![image][Iterable]

六.List类特点和性能分析

![image][ListClass]

  1. 面向接口编程:
接口类型 变量 = new 实现类();
List list = new ArrayList();
  1. 三者共同的特点(共同遵循的规范)

    1. 允许元素重复
    2. 记录元素的先后添加顺序
  2. Vector类:底层才有数组结构算法,方法都使用synchronized修饰,线程安全,但是性能相对于ArrayList较低

  3. ArrayList类:底层才有数组结构算法,方法没有使用synchronized修饰,线程不安全,性能相对于Vector较高

  4. 现在ArrayList几乎已经取代了Vector

  5. 为了保证ArrayList线程安全:

List list = new Collections.synchronizedList(new ArrayList(....));
  1. LinkedList类:底层才有双向链表结构算法,方法没有使用synchronized修饰,线程不安全

  2. 数组结构算法和双向结构算法的性能问题:

  3. 数组结构算法:插入和删除操作速度低,查询和更改较快

  4. 链表结构算法:插入和删除操作速度快,查询和更改较慢

  5. 使用选择:

  6. 不使用Vector类,

  7. 如果删除和插入操作频繁,应该使用LinkedList类

  8. 如果查询操作频繁,应该使用ArrayList类

发布了65 篇原创文章 · 获赞 0 · 访问量 972

猜你喜欢

转载自blog.csdn.net/huang_kuh/article/details/105275117