Java容器知識整理

一、Collection和Map的簡單結構圖
在這裏插入圖片描述
在這裏插入圖片描述
二、容器的介紹與比較
1、Collection容器:一組各自獨立的元素集合

(1)List、Set對比
List:有序可重複的元素集合
Set:無序不可重複的元素集合,底層實現爲Map

(2)ArrayList、LinkedList、Vector對比
ArrayList、LinkedList、Vector均爲List接口的實現類
ArrayList:底層實現爲數組,線程不安全,查詢效率高,插入刪除效率低
LinkedList:底層實現爲鏈表,線程不安全,查詢效率低,插入刪除效率高
Vector:底層實現爲數組,線程安全

(3)Set與HashSet使用方法區別
Set是接口,HashSet是Set的一個實現子類。
Set變量實現時發生多態,需要指向具體的實現類對象,可以是HashSet類對象、也可以是其他子類對象,HashSet變量實現時創建的是HashSet類對象
定義Set變量,實例化時創建需要的子類對象,後續如果需要修改存儲的類型,直接修改實例化時創建的對象就可以,修改方便

2、Map容器:以key-value(鍵值對)形式存儲數據,key允許重複,底層實現形式:數組+鏈表

(1)HashMap、HashTable對比
HashMap:基於哈希表;線程不安全;沒有contains()方法;key值不重複,key和value值允許出現null值;重新計算hashCode
HashTable:基於哈希表;線程安全;有contains()方法;key值不重複,key和value都不允許出現null值;直接使用對象的hashCode

(2)Map與HashMap使用方法區別
Map是接口,HashMap是Map的一個實現子類。
Map變量實現時發生多態,需要指向具體的實現類對象,可以是HashMap類對象、也可以是其他子類對象,HashMap變量實現時創建的是HashMap類對象
定義Map變量,實例化時創建需要的子類對象,後續如果需要修改存儲的類型,直接修改實例化時創建的對象就可以,修改方便

三、容器的使用
1、容器的方法調用
(1)Map接口類方法使用

import java.util.HashMap;
import java.util.Map;

/**
 * Map接口類的方法使用
 * put、get、remove、putAll、constaintKey、constaintValue、clear、size、isEmpty
 *
 */
public class MapTest {
	public static void main(String[] args) {
		Map map = new HashMap();
		//put(key,value):向容器中添加鍵值對,key值不可以重複,若key重複,後面新添加的value會覆蓋前面的value
		map.put("姓名", "張三");
		map.put("部門", "信息部");
		map.put("姓名", "李四");
		map.put("單位", "信息部");
		//get(key):根據key從元素中獲取value,返會value對象
		String name = (String) map.get("姓名");
		System.out.println(name);
		//size():返回容器中鍵值對的個數
		int size = map.size();
		System.out.println(size);
		//containsKey(key):判斷容器中是否包含與參數key相等的key,返回boolean,底層比較實用equals
		boolean b1 = map.containsKey("姓名");
		System.out.println(b1);
		//containsValue(value):判斷容器中是否包含與參數value相等的value,返回boolean,底層比較實用equals
		boolean b2 = map.containsValue("信息部");
		System.out.println(b2);
		//remove(key):刪除容器中key等於參數key的鍵值對
		map.remove("單位");
		//isEmpty():判斷容器中是否有元素,若存在元素,則返回false,若不存在元素,返回true
		boolean b3 = map.isEmpty();
		System.out.println(b3);
		//putAll(Map m):將參數容器m中的所有元素添加到當前容器中
		Map m = new HashMap();
		m.put("薪資", 3000);
		m.put("年齡", 20);
		map.putAll(m);
		System.out.println(map.get("年齡"));
		//clear():清空容器中所有元素
		map.clear();
		System.out.println(map.size());
		
	}
}

(2)Set接口類方法使用

import java.util.HashSet;
import java.util.Set;

/**
 * Set接口類方式使用
 * add,addAll,size,contains,containsAll,isEmpty,remove,removaAll,clear
 *
 */
public class SetTest {
	public static void main(String[] args) {
		Set set = new HashSet();
		//add(e):向Set集合中添加元素,添加元素不可重複
		set.add("aaa");
		set.add("bbb");
		//addAll(Collection c):將參數集合c中的所有元素添加到當前集合set中
		Set set1 = new HashSet();
		set1.add("ccc");
		set.addAll(set1);
		//size():返回集合中的元素個數
		System.out.println(set.size());
		//contains(e):判斷Set集合中是否包含e對象,若包含返回true,否則返回false
		boolean b = set.contains("aaa");
		System.out.println(b);
		//containsAll(Collect c):判斷集合Set中是否包含參數set集合,若包含返回true,否則返回false
		boolean b1 = set.containsAll(set1);
		System.out.println(b1);
		//isEmpty():判斷集合中是否有元素,若存在元素,則返回false,若不存在元素,返回true
		boolean b2 = set.isEmpty();
		System.out.println(b2);
		//remove(e):將元素e從結合中移除
		set.remove("aaa");
		//removeAll(Collect c):將當前集合中所有包含在集合c中的元素全部移除
		set.removeAll(set1);
		//clear():清空集合中的所有元素
		set.clear();
		System.out.println(set.size());
	}
}

(3)List接口方法使用


```java
import java.util.ArrayList;
import java.util.List;

/**
 * List接口方法使用
 * add、addAll、size、get、set、remove、clear、isEmpty、contains
 *
 */
public class ListTest {
	public static void main(String[] args) {
		List list = new ArrayList();
		//add(e):向List容器末尾添加元素
		list.add("aaa");
		list.add("bbb");
		//add(index, element):向List容器中index索引位置插入元素
		list.add(1, "ccc");
		//addAll(c):在List容器末尾添加參數容器c中所有元素
		List list1 = new ArrayList();
		list1.add("測試addAll");
		list.addAll(list1);
		//addAll(index, c):在List容器index索引位置插入參數容器c中所有元素
		list.addAll(0, list1);
		//size():返回集合中的元素個數
		int size = list.size();
		System.out.println(size);
		//get(index):查找索引index位置的元素並返回
		String str = (String) list.get(2);
		System.out.println(str);
		//set(index, element):將容器中index位置的元素修改爲element
		list.set(0, "修改數據");
		System.out.println(list.get(0));
		//remove(index):從容器中移除索引位置index的元素
		list.remove(1);
		System.out.println(list.get(1));
		//remove(o):從容器中移除元素o
		list.remove("aaa");
		//clear():清空容器中所有元素
		list.clear();
		//contains(o):判斷容器中是否包含元素o,若包含返回ture,否則返回false
		boolean b1 = list.contains("ccc");
		System.out.println(b1);
		//constainsAll(c):判斷容器中是否包含參數容器中的所有元素,若包含返回ture,否則返回false
		boolean b2 = list.containsAll(list1);
		System.out.println(b2);
		//isEmpty():判斷容器中是否有元素,若存在元素返回false,否則返回true
		boolean b3 = list.isEmpty();
		System.out.println(b3);
	}
}

2、自定義實現ArrayList類、LinkedList類(加深理解)
(1)自定義實現ArrayList類中主要方法


```java
package cn.cjy.collection;

import java.lang.reflect.Array;

/**
 * 自定義實現ArrayList
 */
public class MyArrayList {
	
	private Object[] elementData;
	private int size;
	
	public int size(){ //獲取容器元素個數
		return size;
	}
	
	public boolean isEmpty(){ //判斷容器中爲空
		return size==0;
	}
	
	public MyArrayList(){
		this(3);
	}
	
	public MyArrayList(int initialCapacity){
		if(initialCapacity<0){
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		elementData = new Object[initialCapacity];
	}
	
	//向容器中添加元素
	public void add(Object obj){
		ensureCapacity();//數組擴容
		elementData[size++] = obj;
	}
	
	//向容器中指定位置插入元素
	public void add(int index,Object obj){
		rangeCheck(index);
		ensureCapacity();
		System.arraycopy(elementData, index, elementData, index+1, size-index);
		elementData[index] = obj;
		size++;
	}
	
	//修改容器中指定位置元素
	public void set(int index,Object obj){
		rangeCheck(index);
		elementData[index] = obj;
	}
	
	//移除容易中指定位置元素
	public void remove(int index){
		rangeCheck(index);
		int noveNum = size-index-1;
		if(noveNum>0){
			System.arraycopy(elementData, index+1, elementData, index, noveNum);
		}
		elementData[size--]=null;
	}
	
	//移除容器中的等於obj的元素
	public void remove(Object obj){
		for(int i=0;i<size;i++){
			if(get(i).equals(obj)){
				remove(i);
			}
		}
	}
	
	//獲取容器中指定位置元素
	public Object get(int index){
		rangeCheck(index);
		return elementData[index];
	}
	
	//檢查索引是否合法
	private void rangeCheck(int index){
		if(index<0 || index>=size){
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	} 
	
	//數組擴容
	private void ensureCapacity(){
		if(size == elementData.length){
			Object[] newArray = new Object[size*2+1];
			System.arraycopy(elementData, 0, newArray, 0, elementData.length);
			elementData = newArray;
		}
	}
	
	public static void main(String[] args) {
		MyArrayList list = new MyArrayList();
		list.add("測試");
		list.add("測試2");
		list.add("測試3");
		list.add("測試4");
		list.add(2,"我是中途加進來的");
		list.remove(0);
		list.set(2, "我是修改");
		list.remove("測試4");
		for(int i=0;i<list.size();i++){
			System.out.println(list.get(i));
		}
	} 
}

(2)自定義實現LinkedList類中主要方法

package cn.cjy.collection;
/**
 * 自定義雙向鏈表集合 LinkedList
 */
public class MyLinkedList {
	private MyNode first;
	private MyNode last;
	private int size;
	
	public int size(){ //返回容器中元素個數
		return size;
	}
	
	public MyLinkedList(){
	}
	
	//獲取指定位置元素
	public Object get(int index){
		rangeCheck(index);
		
		MyNode temp = node(index);		
		if(temp != null){
			return temp.getNode();	
		}		
		return null;		
	}
	
	public MyNode node(int index){ //根據索引遍歷找對象
		MyNode temp=null;
		if(first != null){
			if(index < (size>>1)){ //如果index小於size的一半,從前往後找,否則從後往前找
				temp = first;
				for(int i=0;i<index;i++){
					temp = temp.getNext();
				}	
			}else{
				temp = last;
				for(int i=size-1; i>index; i--){
					temp = temp.getPrevious();
				}
			}
		}
		return temp;
	}
		
	//向容器中添加元素
	public void add(Object obj){
		MyNode myNode = new MyNode();
		if(first == null){		
			myNode.setNode(obj);
			first = myNode;
			last = myNode;
		}else{
			myNode.setPrevious(last);
			myNode.setNode(obj);
			last.setNext(myNode);
			last = myNode;
		}
		size++;
	}
	
	//向容器中指定位置插入元素
	public void add(int index,Object obj){
		rangeCheck(index);
		MyNode temp = node(index); //找到節點
		MyNode myNode = new MyNode();//創建新節點
		
		if(temp !=null){			
			myNode.setPrevious(temp.getPrevious());
			myNode.setNode(obj);
			myNode.setNext(temp);
			
			temp.getPrevious().setNext(myNode);//原index節點的上節點的下節點改爲新節點			
			temp.setPrevious(myNode); //原index節點的上節點設爲新節點
			
			size++;
		}
	}
	
	//修改容器中指定位置元素
	public void set(int index,Object obj){
		rangeCheck(index);
		MyNode temp = node(index); //找到節點
		if(temp != null){
			temp.setNode(obj);
		}
	}
	
	//移指定位置元素
	public void remove(int index){
		rangeCheck(index);
		MyNode temp = node(index); //找到節點
			
		if(temp != null){
			if(first == temp){
				if(first.getNext() != null){
					first.getNext().setPrevious(null);
					first = first.getNext();
				}else{
					first = null;
					last = null;
				}
			}else if(last == temp){
				if(last.getPrevious() != null){
					last.getPrevious().setPrevious(null);
					last = last.getPrevious();
				}else{
					first = null;
					last = null;
				}
			}else{
				temp.getPrevious().setNext(temp.getNext());
				temp.getNext().setPrevious(temp.getPrevious());
			}			
			size--;
		}
	}
	
	public void rangeCheck(int index){  //檢查索引是否合法
		if(index<0 || index >= size){
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		MyLinkedList list = new MyLinkedList();
		list.add("鏈表測試");
		list.add("111");
		list.add("222");
		list.add(1,"test");
		list.set(1,"test002");
		System.out.println(list.get(1));
		list.remove(1);
		System.out.println(list.get(1));
		//list.remove("鏈表測試");
		//System.out.println(list.get(0));
		
	}
}

3、迭代器遍歷容器中的元素
(1)Set集合的遍歷方式

package cn.cjy.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 迭代器遍歷Set
 */
public class IteratorSet {
	public static void main(String[] args) {
		Set set = new HashSet();
		set.add("語文");
		set.add("數學");
		set.add("英語");
		
		//while循環遍歷
		Iterator itera = set.iterator();
		while(itera.hasNext()){
			String str = (String) itera.next();
			System.out.println(str);
		}
		
		//for循環遍歷
		for(Iterator itera1 = set.iterator();itera1.hasNext();){
			String str1 = (String) itera1.next();
			System.out.println(str1);
		}
	}
}

(2)Map的2種遍歷方式

package cn.cjy.collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 迭代器遍歷Map
 *
 */
public class IteratorMap {
	public static void main(String[] args) {
		Map map = new HashMap();
		map.put("姓名", "張三");
		map.put("性別", "男");
		map.put("部門", "信息部");
		
		//遍歷Map的第一種方式
		Set<Entry> set1 = map.entrySet(); //將Map轉換成存放鍵值對的Set集合
		Iterator itera1 = set1.iterator();
		while(itera1.hasNext()){
			Entry entry =  (Entry) itera1.next();
			String str1 = (String) entry.getKey();
			String str2 = (String) entry.getValue();
			System.out.println(str1+":"+str2);
		}
		
		//遍歷Map的第二種方式
		Set set2 = map.keySet(); //將Map的鍵放入Set集合
		Iterator itera2 = set2.iterator();
		while(itera2.hasNext()){
			String str1 = (String) itera2.next();  //獲取鍵
			String str2 = (String) map.get(str1); //獲取值
			System.out.println(str1+":"+str2);
		}
	}
}

(3)List的遍歷方式

package cn.cjy.collection;

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

/**
 * List的遍歷方式
 */
public class IteratorList {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("語文");
		list.add("數學");
		list.add("英語");
		
		//根據索引循環遍歷
		for(int i=0;i<list.size();i++){
			String str = (String) list.get(i);
			System.out.println(str);
		}
		
		//根據迭代器循環遍歷
		Iterator itera = list.iterator();
		while(itera.hasNext()){
			String str1 = (String) itera.next();
			System.out.println(str1);
		}
	}
}

4、容器裝載數據應用舉例
(1)List形式
用List
封裝幾組數據,然後輸出Map的值

package cn.cjy.collection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * List<Map>存儲數據
 */
public class MapStore {
	public static void main(String[] args) {
		List<Map> list = new ArrayList<Map>();
		
		Map map1 = new HashMap();
		map1.put("姓名", "張三");
		map1.put("年齡", 20);
		map1.put("入職日期", "2019-01-01");
		
		Map map2 = new HashMap();
		map2.put("姓名", "李四");
		map2.put("年齡", 21);
		map2.put("入職日期", "2018-01-01");
		
		Map map3 = new HashMap();
		map3.put("姓名", "王二");
		map3.put("年齡", 22);
		map3.put("入職日期", "2017-01-01");
		
		list.add(map1);
		list.add(map2);
		list.add(map3);
		
		for(Map m : list){
			String name = (String) m.get("姓名");
			int age = (Integer) m.get("年齡");
			String inDate = (String) m.get("入職日期");
			
			System.out.println(name+"  "+age+"  "+inDate);
		}
		
	}
}

(2)ArrayList存儲數據
自定義一個實體類:Employee 列:姓名、年齡、入職日期。然後裝載到 ArrayList容器中,最後增強for循環輸出姓名

package cn.cjy.collection;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Employee {
	private String name; //姓名
	private int age;  //年齡
	private Date inDate; //入職日期
	
	public Employee(){
		
	}
	
	public Employee(String name, int age, String inDate) {
		super();
		this.name = name;
		this.age = age;
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		try {
			this.inDate = format.parse(inDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	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;
	}
	public Date getInDate() {
		return inDate;
	}
	public void setInDate(Date inDate) {
		this.inDate = inDate;
	}
	
	
}

package cn.cjy.collection;

import java.util.ArrayList;
import java.util.List;

/**
 * ArrayList存儲數據
 */
public class ArrayListStore {
	public static void main(String[] args) {
		Employee e1 = new Employee("張三", 20, "2019-01-01");
		Employee e2 = new Employee("李四", 21, "2018-01-01");
		Employee e3 = new Employee("王二", 22, "2017-01-01");
		
		List<Employee> list = new ArrayList<Employee>();
		list.add(e1);
		list.add(e2);
		list.add(e3);
		
		for(Employee e : list){
			System.out.println(e.getName());
		}
	}
}

四、補充
1、ArrayList中size與length的區別
size是ArrayList中元素的個數,length是數組長度,size<=length

2、System.arraycopy() 函數:複製數組

package cn.cjy.collection;
/**
 * 使用System.arraycopy()函數複製數組
 * System.arraycopy(src, srcPos, dest, destPos, length)
 * src:源數組
 * srcPos:源數組開始複製位置
 * dest:目標數組
 * destPos:目標數組開始放的位置
 * length:複製的長度
 */
public class ArrayCopyTest {
	public static void main(String[] args) {
		String[] arr1 = new String[5];
		arr1[0] = "測試數組複製";
		String[] arr2 = new String[]{"aaa","bbb","ccc"};
		System.arraycopy(arr2, 1, arr1, 1, 2);
		for(int i=0;i<arr1.length;i++){
			System.out.println(arr1[i]);
		}
	}

}

``

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章