身为java开发人员,这份Java泛型与容器知识点整理你真得好好看看了

235 篇文章 4 订阅

容器框架图:

Collection接口

Set接口:Collection的子接口>>无序不可重复
HashSet:Set接口的实现类

List接口:Collection的子接口>>有序可重复

ArrayList:Lis接口t的实现类(数组列表)查询效率高
LinkedList:List接口的实现类(链表)增删效率高
Vector:List接口的实现类(底层是数组)线程安全

Map接口

HashMap:Map接口的实现类

Collection< E >接口常用方法

下面的方法一般用于2个容器间的操作;不过也可以使用1个容器,自己与自己进行交、并、差等操作,一般没这个必要。
注意:2个容器的数据类型必须一致

代码测验如下:
import java.util.ArrayList;
import java.util.Collection;

public class TestCollection {
	
	public static void main(String[] args) {
		
		Collection<String> coll = new ArrayList<>();		
		coll.add("1");
		coll.add("2");
		coll.add("3");
		System.out.println(coll);//[1, 2, 3]
		coll.clear();
		System.out.println(coll);//[]
		
		coll.add("A");
		coll.add("B");
		coll.add("C");
		coll.add("DE");
		System.out.println(coll);//[A, B, C, DE]
		
//		coll.remove(2);//这里表示的含义是移除整数2,而不是移除数组下标为2的元素
		coll.remove("DE");
		System.out.println(coll);//[A, B, C]
		
		int a = coll.size();
		System.out.println(a);//3
		
		boolean b = coll.isEmpty();
		System.out.println(b);//false
		
		boolean c = coll.contains("A");
		System.out.println(c);//true
		
		Object[] d = coll.toArray();
		System.out.println(d);//[Ljava.lang.Object;@15db9742
		
		System.out.println("=========================================");
		
		Collection<String> coll02 = new ArrayList<>();
		coll02.add("B");
		coll02.add("C");
		coll02.add("D");
		System.out.println("coll:"+coll);//coll:[A, B, C]
		System.out.println("coll02:"+coll02);//coll02:[B, C, D]
		
		boolean e = coll.containsAll(coll02);
		System.out.println(e);//false
		
		coll.retainAll(coll02);
		System.out.println(coll);//[B, C]
		
		coll.addAll(coll02);
		System.out.println(coll);//[B, C, B, C, D]
		
		coll.removeAll(coll02);
		System.out.println(coll);//[]
		
	}
	
}

List< E >接口常用方法

代码测验如下:
import java.util.ArrayList;
import java.util.List;
/**
 * 	List接口中的方法多加了一个索引、下标
 */
public class TestList {
	
	public static void main(String[] args) {
		
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		System.out.println(list);//[1, 2, 3, 4, 5]
		
		list.add(1,11);
		System.out.println(list);//[1, 11, 2, 3, 4, 5]
		
//		list.remove(11);//此处默认将11当成下标来运算,而不是将11当成一个元素内容
		
		list.remove(1);
		System.out.println(list);//[1, 2, 3, 4, 5]
		
		list.set(0,11);
		System.out.println(list);//[11, 2, 3, 4, 5]
		
		int a = list.get(0);
		System.out.println(a);//11
		
		list.add(5);
		list.add(4);
		list.add(3);
		list.add(2);
		list.add(11);
		
		int b = list.indexOf(11);
		System.out.println(b);//0
		
		int c = list.lastIndexOf(11);
		System.out.println(c);//9
		
		List<Integer> list02 = new ArrayList<>();
		list02.add(12);
		list02.add(14);
		list02.add(16);
		
		list.addAll(1,list02);
		System.out.println(list);//[11, 12, 14, 16, 2, 3, 4, 5, 5, 4, 3, 2, 11]
			
	}
	
}

区分Collection接口中的remove方法、List接口中的remove方法

import java.util.ArrayList;
import java.util.List;
/**
 * 	区分Collection接口中的remove方法、List接口中的remove方法
 * 	
 */
public class TestRemove {
	
	public static void main(String[] args) {
		
		List<String> list01 = new ArrayList<>();
		list01.add("1");
		list01.add("2");
		list01.add("3");
		list01.add("4");
		list01.add("5");
		System.out.println(list01);//[1, 2, 3, 4, 5]
		
		//父接口Collection中的remove方法
		list01.remove("1");
		System.out.println(list01);//[2, 3, 4, 5]
		
		//List接口中的remove方法
		list01.remove(1);
		System.out.println(list01);//[2, 4, 5]
		
		System.out.println("=========================================");
		
		List<Integer> list02 = new ArrayList<>();
		list02.add(1);
		list02.add(2);
		list02.add(3);
		list02.add(4);
		list02.add(5);
		list02.add(11);
		
		list02.remove(1);
		System.out.println(list02);//[1, 3, 4, 5, 11]
		
		/**
		 * java.lang.IndexOutOfBoundsException: Index: 11, Size: 5
		 */
		list02.remove(11);//此处会报下表越界异常,因为在int类型中它默认指的是下标索引
		
	}
	
}

练习一:手写模拟ArrayList创建数组,添加元素功能(加入泛型):

/**
 * 	手写ArrayList创建容器,添加元素功能
 * 	增加泛型
 */
public class WriteArrayList<E> {
	
	private Object[] array;
	private int size;//数组下标
	private static final int DEFAULT = 10;
	
	public WriteArrayList() {
		array = new Object[DEFAULT];
	}
	
	public WriteArrayList(int index) {
		array = new Object[index];
	}
	
	public void add(E data) {
		array[size++] = data;
	}
	
	@Override
	public String toString() {
		//以[a,b,c]格式输出
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for(int i=0; i<size; i++) {
			sb.append(array[i]+",");
		}
		sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
		return sb.toString();
	}
	
	public static void main(String[] args) {
		WriteArrayList<Integer> wal = new WriteArrayList<>();
		wal.add(11);
		wal.add(12);
		wal.add(13);
		System.out.println(wal);
	}
	
}

练习二:在练习一的基础上增加数组扩容

/**
 * 	增加数组扩容
 */
public class WriteArrayList<E> {
	
	private static Object[] array;
	private int size;//数组下标
	private static final int DEFAULT = 10;
	
	public WriteArrayList() {
		array = new Object[DEFAULT];
	}
	
	public WriteArrayList(int index) {
		array = new Object[index];
	}
	
	public void add(E data) {
		//什么时候扩容?
		if(size==array.length) {
			//如何扩容?
			Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
			System.arraycopy(array, 0, newArray, 0, array.length);
			array = newArray;
		}
		array[size++] = data;
	}
	
	@Override
	public String toString() {
		//以[a,b,c]格式输出
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for(int i=0; i<size; i++) {
			sb.append(array[i]+",");
		}
		sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
		return sb.toString();
	}
	
	public static void main(String[] args) {
		WriteArrayList<Integer> wal = new WriteArrayList<>();
		for(int i=0; i<40; i++) {
			wal.add(i);
		}
		System.out.println(wal);
	}
	
}

练习三:在练习二的基础上增加set()、get()方法,增加数组边界检测

/**
 * 	增加set()、get()方法
 * 	增加数组边界检查(判断索引是否合法)
 */
public class WriteArrayList<E> {
	
	private static Object[] array;
	private int size;//数组下标
	private static final int DEFAULT = 10;
	
	public WriteArrayList() {
		array = new Object[DEFAULT];
	}
	
	public WriteArrayList(int index) {
		//加入判断
		if(index<0) {
			throw new RuntimeException("容器的容量不能为负数:"+index);
		} else if(index==0) {
			array = new Object[DEFAULT];
		} else {
			array = new Object[index];
		}
	}
	
	public void add(E data) {
		//什么时候扩容?
		if(size==array.length) {
			//如何扩容?
			Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
			System.arraycopy(array, 0, newArray, 0, array.length);
			array = newArray;
		}
		array[size++] = data;
	}
	
	@Override
	public String toString() {
		//以[a,b,c]格式输出
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for(int i=0; i<size; i++) {
			sb.append(array[i]+",");
		}
		sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
		return sb.toString();
	}
	
	public E get(int index) {
		checkIndex(index);
		return (E)array[index];
	}
	
	public void set(int index, E data) {
		checkIndex(index);
//		//索引合法判断,索引区间应满足[0,size)
//		if(index<0||index>size-1) {
//			//不合法,手动抛出异常
//			throw new RuntimeException("索引不合法:"+index);
//		}
		array[index] = data;
	}

	/**
	 * 	由于许多地方都需要判断index索引是否合法,
	 * 	所以在此处写一个独立的方法,需要时直接调用即可
	 */
	public void checkIndex(int index) {
		//索引合法判断,索引区间应满足[0,size)
		if(index<0||index>size-1) {
			//不合法,手动抛出异常
			throw new RuntimeException("索引不合法:"+index);
		}
	}

	public static void main(String[] args) {
		WriteArrayList<Integer> wal = new WriteArrayList<>();
		for(int i=0; i<40; i++) {
			wal.add(i);
		}
		System.out.println(wal.get(10));
		
		wal.set(1,100);
		System.out.println(wal);
		
	}
	
}

练习四:在练习三的基础上增加remove()、size()、isEmpty()方法的实现

/**
 * 	增加2种remove()实现方法
 * 	增加size()、isEmpty()方法
 */
public class WriteArrayList<E> {
	
	private static Object[] array;
	private int size;//数组下标
	private static final int DEFAULT = 10;
	
	public WriteArrayList() {
		array = new Object[DEFAULT];
	}
	
	public WriteArrayList(int index) {
		//加入判断
		if(index<0) {
			throw new RuntimeException("容器的容量不能为负数:"+index);
		} else if(index==0) {
			array = new Object[DEFAULT];
		} else {
			array = new Object[index];
		}
	}
	
	public void add(E data) {
		//什么时候扩容?
		if(size==array.length) {
			//如何扩容?
			Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
			System.arraycopy(array, 0, newArray, 0, array.length);
			array = newArray;
		}
		array[size++] = data;
	}
	
	@Override
	public String toString() {
		//以[a,b,c]格式输出
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for(int i=0; i<size; i++) {
			sb.append(array[i]+",");
		}
		sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
		return sb.toString();
	}
	
	public E get(int index) {
		checkIndex(index);
		return (E)array[index];
	}
	
	public void set(int index, E data) {
		checkIndex(index);
//		//索引合法判断,索引区间应满足[0,size)
//		if(index<0||index>size-1) {
//			//不合法,手动抛出异常
//			throw new RuntimeException("索引不合法:"+index);
//		}
		array[index] = data;
	}

	/**
	 * 	由于许多地方都需要判断index索引是否合法,
	 * 	所以在此处写一个独立的方法,需要时直接调用即可
	 */
	public void checkIndex(int index) {
		//索引合法判断,索引区间应满足[0,size)
		if(index<0||index>size-1) {
			//不合法,手动抛出异常
			throw new RuntimeException("索引不合法:"+index);
		}
	}

	public void remove(int index) {
		//数组中需要移动的元素个数
		int numMoved = array.length - index - 1;
		if(numMoved>0) {
			//底层原理:数组的拷贝
			System.arraycopy(array, index+1, array, index, numMoved);
		}
		array[--size] = null;
	}
	
	public void remove(E data) {
		for(int i=0; i<size; i++) {
			if(array[i].equals(data)) {
				remove(i);
			}
		}
	}
	
	public int size() {
		return size;
	}
	
	public boolean isEmpty() {
		return size==0?true:false;
	}
	
	public static void main(String[] args) {
		WriteArrayList<Integer> wal = new WriteArrayList<>();
		for(int i=0; i<40; i++) {
			wal.add(i);
		}
		System.out.println(wal.get(10));
		
		wal.set(1,100);
		System.out.println(wal);
		
		wal.remove(2);
		System.out.println(wal);
		
		WriteArrayList<String> s = new WriteArrayList<String>();
		s.add("A");
		s.add("B");
		s.add("C");
		s.add("D");
		System.out.println(s);
		s.remove(1);
		System.out.println(s);
		s.remove("D");
		System.out.println(s);
		
		System.out.println(s.size());
		System.out.println(s.isEmpty());
	}
	
}

学习StringBuilder类,及它提供的append()、setCharAt()方法
掌握数组拷贝arraycopy()方法:
System.arraycopy(被复制的数组, 从第几个元素开始复制, 要复制到哪个数组, 粘贴到什么位置, 一共要复制多少个元素);
自己独立重写ArrayList实现类的功能

练习1到4心得:

下面的代码是我独立完成的,与练习4的代码的本质区别是:size和array.length具体代表的含义。
我下面的代码中size代表容器中元素的个数,array.length表示容器大小,由于数组扩容,容器大小一般大于元素个数。
注意==与equals的区别。

public class WriteArrayList02<E> {

	private Object[] array;
	private int size;
	private static final int DEFAULT = 10;
	
	public WriteArrayList02() {
		array = new Object[DEFAULT];
	}
	
	public WriteArrayList02(int index) {
		if(index == 0) {
			array = new Object[DEFAULT];
		}else if(index<0) {
			throw new RuntimeException("索引不能为负数:"+index);
		}else {
			array = new Object[index];
		}
	}
	
	public void add(E element) {
		if(size==array.length) {
			Object[] newArray = new Object[array.length+(array.length>>1)];
			System.arraycopy(array, 0, newArray, 0, array.length);
			array = newArray;
		}
		array[size++] = element;
	}
	
	public void set(int index, E element) {
		checkIndex(index);
		array[index] = element;
	}
	
	public E get(int index) {
		checkIndex(index);
		return (E)array[index];
	}
	
	public void checkIndex(int index) {
		if(index<0||index>=size) {
			throw new RuntimeException("索引异常:"+index);
		}
	}
	
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for(int i=0; i<size; i++) {
			sb.append(array[i]+",");
		}
		sb.setCharAt(sb.length()-1,']');
		return sb.toString();
	}
	
	public void remove(E element) {
		for(int i=0; i<size; i++) {
			if(array[i].equals(element)) {
				remove(i);
			}
		}
	}
	
	public void remove(int index) {
		System.out.println(array.length);
		//1,2,3,4,5,6,7
		int numCopy = size - index - 1;
		if(numCopy<0) {
			throw new RuntimeException("索引异常:"+index);
		}else if(numCopy==0) {
			array[size] = null;
		}else {
			System.arraycopy(array, index+1, array, index, numCopy);
		}	
		//array[size-1] = null;
		size--;
		System.out.println(array.length);
	}
	
	public int size() {
		return size;
	}
	
	public boolean isEmpty() {
		return size==0?true:false;
	}
	
	public static void main(String[] args) {
		WriteArrayList02<String> wal = new WriteArrayList02<>();
		for(int i=0; i<40; i++) {
			wal.add(i+"");
		}
		System.out.println(wal);
		
		wal.set(1,"11");
		System.out.println(wal);
		
		System.out.println(wal.get(39));
		
		wal.set(39,"12");
		System.out.println(wal);
		
		wal.remove(0);
		System.out.println(wal);
//		wal.remove(38);
//		System.out.println(wal);
		wal.remove("12");
		System.out.println(wal);
		System.out.println(wal.size());
		System.out.println(wal.isEmpty());
	}
	
}

LinkedList链表存储结构

最后

感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值