List

数组可变大小:大概是把数组复制进新数组,扩展

  • Vector:内部是数组数据结构;同步的,线程安全;JDK1.0的时候就只有一种集合结构Vector;几乎不用了;增删查询都很慢。
  • ArrayList:内部是数组数据结构;不同步;替代了Vector;查询速度快。
  • LinkedList:内部是链表数据结构;不同步;增删元素速度快。

  • 数组增删慢是因为,牵一发而动全身,要中间加入或去掉一个元素,后面元素都得动,所以比较慢;链表增删快是因为,增加元素就是改动前后元素对下一元素或上一元素的指向,删除元素就是把下一元素的地址交给上一元素
  • 数组查询快是因为在一遍连续的空间;链表查询慢是因为需要丛头开始查找

List

  1. 添加 void add(index,ele) void add(index,collection)
  2. 删除 Object remove(index)
  3. 查询 Object get(index) int indexOf(object) int lastIndexOf(object) List subList(from,to)
  4. 修改 Object set(index,ele)
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");

//        list.add(1,"abc9");
//        System.out.println(list); //[abc1, abc9, abc2, abc3]

//        System.out.println(list.remove(2)); //abc3

//        System.out.println(list.set(1,"abc8")); //abc2

//        System.out.println(list.get(1)); //abc2

//        System.out.println(list.subList(1,2)); //[abc2]

//        Iterator it = list.iterator();
//        while (it.hasNext()){
//            System.out.println(it.next());
//        }
//        //list特有取值方式
//        for(int i=0;i<list.size();i++){
//            System.out.println(list.get(i));
//        }

ListIterator

//        Iterator it = list.iterator();
//        while (it.hasNext()){
//            Object obj = it.next();
//            //java.util.ConcurrentModificationException
//            //在迭代过程中不要使用集合操作元素,容易出现异常
//            //可以使用Iterator的子接口ListIterator来完成迭代中对元素的操作
//            if(obj.equals("abc2")){
//                list.add("abc9");
//            }else{
//                System.out.println(obj);
//            }
//        }
//        System.out.println(list);

ListIterator it = list.listIterator();
while (it.hasNext()){
    Object obj = it.next();
    if(obj.equals("abc2")){
        it.set("abc9");
    }
}
System.out.println(list); //[abc1, abc9, abc3]

LinkedList

LinkedList源码分析

LinkedList list = new LinkedList();
list.add("java");
/*
void linkLast(E e) {
	final Node<E> l = last;
	final Node<E> newNode = new Node<>(l, e, null);
	last = newNode;
	if (l == null)
		first = newNode;
	else
		l.next = newNode;
	size++;
	modCount++;
}
*/
list.addFirst("hello");
/*
private void linkFirst(E e) {
	final Node<E> f = first;
	final Node<E> newNode = new Node<>(null, e, f);
	first = newNode;
	if (f == null)
		last = newNode;
	else
		f.prev = newNode;
	size++;
	modCount++;
}
*/
list.addLast("world");
/*
void linkLast(E e) {
	final Node<E> l = last;
	final Node<E> newNode = new Node<>(l, e, null);
	last = newNode;
	if (l == null)
		first = newNode;
	else
		l.next = newNode;
	size++;
	modCount++;
}
*/
list.removeLast();
/*
private E unlinkLast(Node<E> l) {
	// assert l == last && l != null;
	final E element = l.item;
	final Node<E> prev = l.prev;
	l.item = null;
	l.prev = null; // help GC
	last = prev;
	if (prev == null)
		first = null;
	else
		prev.next = null;
	size--;
	modCount++;
	return element;
}
*/
list.removeFirst();
/*
private E unlinkFirst(Node<E> f) {
	// assert f == first && f != null;
	final E element = f.item;
	final Node<E> next = f.next;
	f.item = null;
	f.next = null; // help GC
	first = next;
	if (next == null)
		last = null;
	else
		next.prev = null;
	size--;
	modCount++;
	return element;
}
*/

System.out.println(list);
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
        
//        System.out.println(link.getFirst()); //abc3
//        System.out.println(link.removeFirst()); //abc3

//        Iterator it = link.iterator();
//        while(it.hasNext()) {
//        	System.out.println(it.next()); //abc3 abc2 abc1
//        }

LinkedList模拟堆栈

  • 堆栈:先进后出
  • 队列:先进先出
/*
 * LinkedList模拟队列和堆栈
 */
public class LinkedListSQ {
	
	private LinkedList link;
	private String type;
	
	public LinkedListSQ() {
		this.link = new LinkedList();
	}
	
	public void setType(String type) {
		this.type = type;
	}
	
	public void myAdd(Object obj) {
		this.link.addLast(obj);
	}
	
	public Object myPop() {
		if(this.type == "stack") {
			return this.link.removeLast();
		}else {
			return this.link.removeFirst();
		}
		
	}
	
	public boolean isNull() {
		return this.link.isEmpty();
	}

}

//main
LinkedListSQ sq = new LinkedListSQ();
sq.myAdd("abc1");
sq.myAdd("abc2");
sq.myAdd("abc3");

//sq.setType("stack");

while(!sq.isNull()) {
    System.out.println(sq.myPop()); //abc1 abc2 abc3   abc3 abc2 abc1
}

LinkedList底层是双向链表

从结构上,我们还看到了LinkedList实现了Deque接口,因此,我们可以操作LinkedList像操作队列和栈一样~

add

remove

get

ArrayList

ArrayList源码分析

ArrayList所有方法

List list = new ArrayList();

//add
list.add("hello");
list.add("world");
//AbstractCollection中定义了toString直接输出数组格式
System.out.println(list); //[hello, world]

//size
System.out.println(list.size()); //2
//empty
System.out.println(list.isEmpty()); //false

//add addAll
List list2 = new ArrayList();
list2.add("hello");
list2.add(123); //自动装箱
list.addAll(list2);
System.out.println(list); //[hello, world, hello, 123]

//remove removeAll
list.remove("hello");
System.out.println(list); //[world, hello, 123]
//list.remove(123);  //java.lang.IndexOutOfBoundsException
list.remove(new Integer(123));
System.out.println(list); //[world, hello]
list.remove(0);
System.out.println(list); //[hello]
System.out.println(list2); //[hello, 123]
list.add("world");
list.add(123);
list.removeAll(list2); //删除交集
System.out.println(list);

//retainAll
list.add("hello");
list.add(123);
System.out.println(list);
list.retainAll(list2); //交集
System.out.println(list2);
System.out.println(list); //[hello, 123]

//contains containsAll
list.add("world");
System.out.println(list.contains(123)); //true
System.out.println(list.containsAll(list2)); //true

//clear
list2.clear();
System.out.println(list2); //[]

//get
System.out.println(list); //[hello, 123, world]
System.out.println(list.get(0)); //hello
//set
list.set(1, 456);
System.out.println(list); //[hello, 456, world]
//add
list.add(1,true);
System.out.println(list); //[hello, true, 456, world]
//indexOf
System.out.println(list.indexOf(true)); //1

//foreach
for (Object object : list) {
	System.out.println(object);
}
//for
for(int i=0;i<list.size();i++) {
	System.out.println(list.get(i));
}
//iterator
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
	System.out.println(iterator.next());
}
//listIterator
ListIterator iterator2 = list.listIterator();
while(iterator2.hasNext()) {
	System.out.println(iterator2.next());
}
while(iterator2.hasPrevious()) {
	System.out.println(iterator2.previous());
}

注意自定义对象在遍历的时候需要向下转型

ArrayList al = new ArrayList();
al.add(new Person("list1",21));  //向上转型为了Object
al.add(new Person("list2",22));
al.add(new Person("list3",23));

Iterator it = al.iterator();
while(it.hasNext()) {
    Person p = (Person)it.next();
    System.out.println(p.getName()+"--"+p.getAge());
}
//Person
public class Person {
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

ArrayList去重

//main
ArrayList al = new ArrayList();
al.add(new Person("list1",21));
al.add(new Person("list2",22));
al.add(new Person("list3",23));
al.add(new Person("list4",24));
al.add(new Person("list1",21));
System.out.println(al);
al = getSingleArrayList(al);
System.out.println(al);

private static ArrayList getSingleArrayList(ArrayList al) {
ArrayList temp = new ArrayList();
Iterator it = al.iterator();
while(it.hasNext()) {
	Object obj = it.next();
	//contains和remove都是使用的equals方法来比较筛选,所以可以操作equals来控制
	//ArrayList不关系到hashCode
	if(!temp.contains(obj)) {
		temp.add(obj);
	}
}
return temp;
}
//Person
public class Person extends Object {
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	//覆盖hashCode和equals方法
	@Override
	public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		if(!(obj instanceof Person)) {
			throw new ClassCastException("类型错误!");
		}
		System.out.println(this+"..equals.."+obj);
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}
	@Override
	public int hashCode() {
		System.out.println(name+"|"+age+"...hashCode=" + (name.hashCode()+age*35));
		return name.hashCode()+age*35;
	}
	
}

ArrayCopy

int[] arr = {1,2,3,4,5,6};
System.arraycopy(arr, 3, arr, 2, 3); //arr位置为3的元素开始复制3个,替换arr位置为2开始的3个元素
System.out.println(Arrays.toString(arr));

ArrayList源码分析-扩容

public class TestArrayList {
	/**ArrayList源码分析
	 * (1)无参构造方法
	 *       this.elementData 是一个Object类型的数组
	 *       DEFAULTCAPACITY_EMPTY_ELEMENTDATA;也是一个Object类型的数组
	 *       DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};默认长度为0
	 *     public ArrayList() {
               this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
               //相当于this.elementData={};
          }
        (2)带参构造方法
            
         public ArrayList(int initialCapacity) {
	        if (initialCapacity > 0) {
	            this.elementData = new Object[initialCapacity];
	            //this.elementData=new Object[20];
	        } 
    	}
    	(3)添加方法 add(Object obj)
    	 public boolean add(E e) {
    	        //检测空间容量是否够用
		        ensureCapacityInternal(size + 1);  // Increments modCount!!
		        //添加元素    elementData[size]=e; size++;
		        elementData[size++] = e;
		        return true;
    	}
    	(4)检测空间容量是否够用
    	private void ensureCapacityInternal(int minCapacity) {
        	ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    	}
    	首先调用执行 ,计算容量
         calculateCapacity(elementData, minCapacity)
         
         //calculateCapacity方法定义
         private static int calculateCapacity(Object[] elementData, int minCapacity) {
		            //以下代码相当于elementData=={}
		        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  //true
		                   //Math.max(10,1);
		            return Math.max(DEFAULT_CAPACITY, minCapacity);
		        }
        return minCapacity;  //执行完之后的结果为  10
       }
        //容量计算完毕后,执行ensureExplicitCapacity方法    ensureExplicitCapacity(10)
         ensureExplicitCapacity方法定义
         
         private void ensureExplicitCapacity(int minCapacity) {  //10
	        modCount++;
	
	        // overflow-conscious code
	         * 10-0 >0  true
	        if (minCapacity - elementData.length > 0)
	            grow(minCapacity);
	    }
	    (5)扩充容量
	      private void grow(int minCapacity) {    //10
	        // overflow-conscious code
	        int oldCapacity = elementData.length;        //int oldCapactiy=0;
	        
	        int newCapacity = oldCapacity + (oldCapacity >> 1);   //int newCapacity=0+0>>1  结果为0
	      
	        if (newCapacity - minCapacity < 0)       // 0-10<0    true
	        
	            newCapacity = minCapacity;           //newCapacity=10;
	            
	      
	        elementData = Arrays.copyOf(elementData, newCapacity); //数组拷贝 elementData的长度就是 10
    }
	 * */
       
	public static void main(String[] args) {
		ArrayList list=new ArrayList();
		//第一次调用添加方法时,完成Object类型数组的初始化容量 ,10
		list.add("hello");
		list.add("world");
		list.add("hello");
		list.add("world");
		list.add("hello");
		list.add("world");
		list.add("hello");
		list.add("world");
		list.add("hello");
		list.add("world");//10个元素对象
		/**当添加第11个元素时,所需容量为11,而数组的长度为10,已经无法容纳元素了,这个时候需要扩容,
		 * 原始容量+原始容量>>1   得到新容量
		 * 10+10>>1           15*/
		
		list.add("hello");//当添加第11个元素对象时 怎么办?
		
		Object [] obj={};
		
		
	}
}

ArrayList源码分析-操作

package com.bjsxt.arraylist.source;

import java.util.ArrayList;
import java.util.Iterator;

public class TestArrayList {
	/**
	 * ArrayList源码分析_2
	 * (1)add(int index,Object obj)
	 *  public void add(int index, E element) {
	       
	                        //源数组              ,源数组开始位置  ,新数组            ,新数组开始位置
	        System.arraycopy(elementData, index,  elementData, index + 1,
	                         size - index);  //size-index ,拷贝的元素的个数
	                         
	        elementData[index] = element;//将元素添加到索引为 index的位置上
	        size++;            //元素的个数+1
    }
     (2)get(int index)根据索引获取元素对象
        public E get(int index) {
        
            return elementData(index);  //调用了elementData()的方法
       }
         //elementData方法的定义
        E elementData(int index) {
        
        return (E) elementData[index];   //在Object类型的数组中根据索引取出元素对象
    }
    (3)size()
       public int size() {
        return size;   //用于记录集合中元素的个数
      }
    (4)isEmpty()
       public boolean isEmpty() {
        return size == 0;  //集合中一个元素都没有的时候,集合就是空的
       }
    (5)set(int index, Object obj)
	    public E set(int index, E element) {
	        
	        E oldValue = elementData(index);   //根据索引在数组中获取元素
	        
	        elementData[index] = element;  //将新元素设置到数组中索引为index的位置上
	        
	        return oldValue;        //返回原始元素对象
	    }
	  (6)remove(int index)
	  
		  public E remove(int index) {
	         
	        E oldValue = elementData(index);//根据索引获取原始元素对象
	
	        int numMoved = size - index - 1;   //拷贝的元素的个数
	        
	        if (numMoved > 0)
	            System.arraycopy(elementData, index+1, elementData, index,
	                             numMoved);
	                             
	        elementData[--size] = null; //   将最后一个位置设置为null
	
	        return oldValue;        //返回原始元素对象
     }
      (7)clear()
        public void clear() {
        
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
     }
      (8)iterator()
	 * */
	public static void main(String[] args) {
		//创建ArrayList集合对象
		ArrayList list=new ArrayList();
		list.add("hello");
		list.add("world");
		list.add(0, "java");//在索引为0的位置上添加"java"
		System.out.println(list);
		System.out.println(list.get(1));
		System.out.println(list.size());
		System.out.println(list.isEmpty());
		System.out.println(list.set(2, "sql"));
		System.out.println(list);
		list.remove(1);
		list.clear();
		Iterator ite= list.iterator();
		while(ite.hasNext()){
			Object obj=ite.next();
			System.out.println(obj);
		}
		
	}
}

属性:

根据上面我们可以清晰的发现:ArrayList底层其实就是一个数组,ArrayList中有扩容这么一个概念,正因为它扩容,所以它能够实现“动态”增长

add(int index, E element)

get方法

细节说明

  • ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
  • ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
  • 删除元素时不会减少容量,若希望减少容量则调用trimToSize()
  • 它不是线程安全的。它能存放null值。

总结

ArrayList:

  • 底层实现是数组
  • ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
  • 在增删时候,需要数组的拷贝复制(navite 方法由C/C++实现)

LinkedList:

  • 底层实现是双向链表[双向链表方便实现往前遍历]

Vector:

  • 底层是数组,现在已少用,被ArrayList替代,原因有两个:
  • Vector所有方法都是同步,有性能损失。
  • Vector初始length是10,超过length时 以100%比率增长,相比于ArrayList更多消耗内存。

总的来说:查询多用ArrayList,增删多用LinkedList。

ArrayList增删慢不是绝对的(在数量大的情况下,已测试):

  • 如果增加元素一直是使用add()(增加到末尾)的话,那是ArrayList要快

  • 一直删除末尾的元素也是ArrayList要快【不用复制移动位置】

  • 至于如果删除的是中间的位置的话,还是ArrayList要快!.

vector

  • 每次扩容1倍
  • 调用构造方法时就初始化容量为10

源码分析

package com.bjsxt.vector;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

public class TestVector {
	/**
	 * Vector的JDK源码分析
	 * (1)构造方法
	 * public Vector() {
        this(10);
      } 
        public Vector(int initialCapacity) {//10
        this(initialCapacity, 0);
     }
                        10            ,0
     public Vector(int initialCapacity, int capacityIncrement) {
       
        this.elementData = new Object[initialCapacity]; //相当于this.elementData=new Object[10];
        this.capacityIncrement = capacityIncrement;  //this.capacityIncrement=0;
    }
    (2)调用add方法添加元素
    
     public synchronized boolean add(E e) {
      
        ensureCapacityHelper(elementCount + 1); //检测容量是否够 用
        elementData[elementCount++] = e;  //添加元素,同时元素个数加1
        return true;
    }
	 * */
	public static void main(String[] args) {
		//创建了集合对象
		Vector vector=new Vector();
		System.out.println(vector.capacity()+"\t集合中元素的个数:"+vector.size());
		//ArrayList al=new ArrayList();
		//al.add("hello");
		//添加
		vector.add("hello");
		vector.add(0, "world");
		vector.addElement("java"); //添加元素
		vector.add("hello");
		vector.add(0, "world");
		vector.add("hello");
		vector.add(0, "world");
		vector.add("hello");
		vector.add(0, "world");
		
		vector.add(0, "world");
		vector.add("hello");//添加第十一个元素
		System.out.println(vector.capacity()+"\t集合中元素的个数:"+vector.size());
		System.out.println("集合中元素的个数:"+vector.size());
		System.out.println(vector);
		//删除
		//vector.remove(1);
		//vector.remove("java");
		//vector.clear();
		//vector.removeElement("java");
		//获取元素的方法
		System.out.println(vector.get(1));
		
		System.out.println(vector);
		System.out.println("加强for循环");
		for(Object obj:vector){
			System.out.println(obj);
		}
		System.out.println("使用迭代器遍历集合:");
		for(Iterator ite=vector.iterator();ite.hasNext();){
			System.out.println(ite.next());
		}
		
		Iterator ite=vector.iterator(); 
		while(ite.hasNext()){
			System.out.println(ite.next());
		}
	}
}

迭代器

ListIterator可以在迭代时添加元素

public class TestIterator {
	public static void main(String[] args) {
		ArrayList<String> arrayList = new ArrayList<String>();
		arrayList.add("java");
		arrayList.add("hello");
		arrayList.add("world");
		
		//Iterator<String> ite = arrayList.iterator();
		/*
		 * private class Itr implements Iterator<E> {
	        int cursor;       // index of next element to return
	        int lastRet = -1; // index of last element returned; -1 if no such
	        int expectedModCount = modCount;
	
	        Itr() {}
	
	        public boolean hasNext() {
	            return cursor != size;
	        }
	
	        @SuppressWarnings("unchecked")
	        public E next() {
	            checkForComodification();
	            int i = cursor;
	            if (i >= size)
	                throw new NoSuchElementException();
	            Object[] elementData = ArrayList.this.elementData;
	            if (i >= elementData.length)
	                throw new ConcurrentModificationException();
	            cursor = i + 1;
	            return (E) elementData[lastRet = i];
	        }
	      }
		 * */
//		while(ite.hasNext()) {
////			if(ite.next().equals("hello")) {
////				arrayList.add("sql");  //java.util.NoSuchElementException
////			}
//			System.out.println(ite.next());
//		}
		
		ListIterator<String> it = arrayList.listIterator();
		while(it.hasNext()) {
			String string = it.next();
			if("hello".equals(string))
				it.add("sql");
		}
		System.out.println(arrayList);
	}
}

书籍推荐