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]);
		}
	}

}

``

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