ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Collection集合

2022-05-15 23:31:15  阅读:130  来源: 互联网

标签:下标 当前 int 元素 Collection 数组 集合


目录

集合

1. 数组的弊端

1. 数据类型一旦确定,只能存储对应类型数据【类型单一】
2. 容量无法修改
3. 配套方法少

集合!!!
	1. 集合支持数据类型多样性,同时满足数据类型一致化 【泛型】
	2. 集合数据存储容量不需要程序员关注,会自动的扩容或者调整
	3. 方法众多!!!各种辅助工具,操作方便!!!【背方法】

2. Java 中集合的整体结构

interface Collection<E> Java中所有集合的总接口!!!
--| interface List<E> extends Collection<E>
	List 接口,对应集合特征: 有序,可重复,存在【下标】操作
	--| class ArrayList<E> implements List<E>
    	可变长数组结构,也是开发中使用较多的一种结构
	--| class LinkedList<E> implements List<E>
    	双向链表结构【火车】
	--| class Vector<E> implements List<E>  
		可变长数组结构,线程安全结构,效率低,是ArrayList的老版
--| interface Set<E> extends Collection<E> 
	Set 接口,对应集合特征: 无序,不可重复
	--| class HashSet<E> implements Set<E>
		底层数据存储结构为【哈希表 Excel】结构
	--| class TreeSet<E> implements Set<E>	
		底层数据存储结构为【平衡二叉树】结构

3. Collection 接口常用方法

增
	add(E e);
		添加在实例化对象过程中约束泛型对应具体数据类型元素对象。
	addAll(Collection<? extends E> c);
		添加参数集合到当前调用方法集合中,要求参数集合对象存储数据类型必须是当前集合对象实例化过程中,约束泛
		型对应具体数据类型,或者其他子类类型。
删
	remove(Object obj);
		在当前集合中,删除指定元素
    removeAll(Collection<?> c);
    	在当前集合中,删除参数集合和当前集合的交集
    retainAll(Collection<?> c);
    	在当前集合中,仅保留参数集合和当前集合的交集
    clear();
    	清空当前集合中所有数据内容
查
	int size();
		当前集合中有效元素个数
	boolean isEmpty();
		判断当前集合是否为空
	boolean contains(Object obj);
		判断参数对象是否在当前集合中存在
	boolean containsAll(Collection<?> c);
		判断参数集合是否是当前集合的子集合
	Object[] toArray();
		返回当前集合中所有元素对象的Object类型数组
	

4. 补充知识点,泛型上限

addAll(Collection<? extends E> c);
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Pig extends Animal {}

Collection<Animal>
	Collection<? extends Animal> c
	限制泛型的数据类型上限,要求集合中存储数据类型必须是 Animal类型或者其子类类型
	? 泛型通配符

Collection<?> c
	对于当前集合数据存储类型不限制

5. List集合

5.1 List 集合特征演示
有序
	添加顺序和存储顺序一致,采用的存储方式为【尾插法】
可重复
	元素允许出现重复情况!!!

List集合可以通过【下标/索引】方式操作使用!!!
5.2 List 常用方法
增
	add(E e);
		添加在实例化对象过程中约束泛型对应具体数据类型元素对象。
	addAll(Collection<? extends E> c);
		添加参数集合到当前调用方法集合中,要求参数集合对象存储数据类型必须是当前集合对象实例化过程中,约束泛
		型对应具体数据类型,或者其他子类类型。
	add(int index, E e);
		在指定下标位置,添加在实例化对象过程中约束泛型对应具体数据类型元素对象。
	addAll(int index, Collection<? extends E> c);
		在指定下标位置,添加参数集合到当前调用方法集合中,要求参数集合对象存储数据类型必须是当前集合对象实例化
		过程中,约束泛型对应具体数据类型,或者其他子类类型。
删
	E remove(int index);
		在当前List集合中,删除指定下标元素,返回值是被删除元素对象本身		
	remove(Object obj);
		在当前集合中,删除指定元素
    removeAll(Collection<?> c);
    	在当前集合中,删除参数集合和当前集合的交集
    retainAll(Collection<?> c);
    	在当前集合中,仅保留参数集合和当前集合的交集
    clear();
    	清空当前集合中所有数据内容
改
	E set(int index, E e);
		在 List 集合中,使用符合实例化对象过程中约束泛型对应具体数据类型对象,替换指定下标元素,返回值是被替换
		元素对象本身
查
	int size();
		当前集合中有效元素个数
	boolean isEmpty();
		判断当前集合是否为空
	boolean contains(Object obj);
		判断参数对象是否在当前集合中存在
	boolean containsAll(Collection<?> c);
		判断参数集合是否是当前集合的子集合
	Object[] toArray();
		返回当前集合中所有元素对象的Object类型数组
	E get(int index);
		在当前集合中,获取指定下标元素
	int indexOf(Object obj);
		获取指定元素在当前集合中第一次出现的下标位置
	int lastIndexOf(Object obj);
		获取指定元素在当前集合中最后一次出现的下标位置
	List<E> subList(int fromIndex, int toIndex);
		从 fromIndex 下标开始,到 toIndex 下标结束,获取子集合对象,要求要头不要尾
5.3 ArrayList 可变长数组集合
ArrayList集合底层是一个 Object 类型数组,在使用过程中,可以自行扩容或者根据条件进行缩容操作。
使用 无参数构造方法创建 ArrayList 可变长集合对象,默认底层 Object 数组初始化容量为 10
  /**
   * Default initial capacity.
   */
  private static final int DEFAULT_CAPACITY = 10;
 
整个 ArrayList 集合允许的最大容量是 Integer 数据最大值 - 8
 /**
 * The maximum size of array to allocate.
 * Some VMs reserve some header words in an array.
 * Attempts to allocate larger arrays may result in
 * OutOfMemoryError: Requested array size exceeds VM limit
 */
 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

可变长功能实现依赖于核心方法 grow(int minCapacity)
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
增删慢
查询快
5.4 增删慢
增:
	1. 尾插法
	2. 指定下标位置添加
	增加影响效率的情况
		1. 底层数组扩容导致时间浪费和空间浪费。
			空间浪费在于新数组容量占用空间和原数组容量占用空间
			时间浪费在新数组创建,原数组内存销毁,数据移动复制操作
		2. 指定下标位置数据添加,从添加位置开始,数组中的每一个元素整体向后移动,

删:
	1. 删除指定下标元素,或者删除指定元素
	2. 删除操作之后,数组中有效元素个数和数组容量比例超过一定范围。【缩容】
	删除影响效率的情况
		1. 删除元素之后,从删除位置开始,数组中元素整体向前移动,时间效率较低
		2. 触发缩容操作,数组中的内存会释放,内存需要时间来销毁。【trimToSize】
5.5 补充知识点 内存地址问题
什么是内存地址???
	计算机按照最小数据单元(byte 字节),对内存进行编号!!!编号从 0 开始到内存的最大值
	以 4GB 内存为例地址范围
		0 ~ 4294967295 为了操作方便,内存按照 十六进制数据处理
		0x0 ~ 0xFFFF FFFF
	编号之后,CPU 可以通过内存地址直达内存目标,读取对应数据,执行相关内容,效率极高【寻址】。

null ==> 0x0 内存编号为 0 的内存。
	0x0 受到系统保护,任何程序,任何代码不允许读取或者写入数据到 0x0 中,一旦操作。操作系统发送 kill 命令
	Java中的 NullPointerException 就是因为程序操作使用了 0x0 内存导致报错!!!
5.6 数组内存分析图

5.7 查询快
	ArrayList 底层是一个 Object 数组结构,数据存储空间连续,同时有下标/索引操作。ArrayList 完成可以按照数组+下标方式计算对应元素的内存空间地址,直接操作对应元素内容。
5.8 ArrayList 原码实现
增
	add(E e);
		添加在实例化对象过程中约束泛型对应具体数据类型元素对象。
	add(int index, E e);
		在指定下标位置,添加在实例化对象过程中约束泛型对应具体数据类型元素对象。
删
	E remove(int index);
		在当前List集合中,删除指定下标元素,返回值是被删除元素对象本身		
	remove(Object obj);
		在当前集合中,删除指定元素
    clear();
    	清空当前集合中所有数据内容
改
	E set(int index, E e);
		在 List 集合中,使用符合实例化对象过程中约束泛型对应具体数据类型对象,替换指定下标元素,返回值是被替换
		元素对象本身
查
	int size();
		当前集合中有效元素个数
	boolean isEmpty();
		判断当前集合是否为空
	boolean contains(Object obj);
		判断参数对象是否在当前集合中存在
	Object[] toArray();
		返回当前集合中所有元素对象的Object类型数组
	E get(int index);
		在当前集合中,获取指定下标元素
	int indexOf(Object obj);
		获取指定元素在当前集合中第一次出现的下标位置
	int lastIndexOf(Object obj);
		获取指定元素在当前集合中最后一次出现的下标位置
	MyArrayList<E> subList(int fromIndex, int toIndex);
		从 fromIndex 下标开始,到 toIndex 下标结束,获取子集合对象,要求要头不要尾
package com.qfedu.b_list;

import java.util.Arrays;

/**
 * MyArrayList 可变长数组结构原码实现
 * @author Anonymous
 *
 * @param <E> 自定义泛型占位符
 */
public class MyArrayList<E> {
	/**
	 * 底层 Object 数组,用于存储元素
	 */
	private Object[] elementData;
	
	/**
	 * 默认 MyArrayList 可变长数组容量 为 10
	 */
	private static final int DEFAULT_CAPACITY = 10;
	
	/**
	 * 允许的数组最大容量
	 */
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
	
	/**
	 * 记录有效元素个数
	 */
	private int size;
	
	/**
	 * 无参数构造方法
	 */
	public MyArrayList() {
		/*
		 * 在构造方法中,this(实际参数)。会根据实际参数的数据类型,参数个数,参数顺序
		 * 选择调用类内的其他构造方法。
		 * 
		 * Constructor call must be the first statement in a constructor
		 * 在一个构造方法中,使用 this(实际参数) 调用其他构造方法,必须是整个代码块的第一行!!!
		 */
		this(DEFAULT_CAPACITY);
	}
	
	/**
	 * 提供给用户明确 MyArrayList 底层数组初始化容量构造方法
	 * 
	 * @param initCapacity 用户指定的底层数组初始化容量
	 */
	public MyArrayList(int initCapacity) {
		if (initCapacity < 0 || initCapacity > MAX_ARRAY_SIZE) {
			/*
			 * IllegalArgumentException 非法参数异常
			 */
			throw new IllegalArgumentException("非法参数异常");
		}
		
		elementData = new Object[initCapacity];
	}
	
	/**
	 * 尾插法添加实例化对象明确的泛型约束数据类型元素
	 * 
	 * @param e 泛型约束对应具体数据类型
	 * @return 操作成功返回true,否则返回false
	 */
	public boolean add(E e) {
		/*		
		if (size == elementData.length)
		ensureCapacity(size + 1);	
		elementData[size++] = e;
		return true;
		给用户多样性的选择,同时满足方法执行任务的一致性!!!
		*/
		return add(size, e);
	}
	
	/**
	 * 在指定下标位置添加符合实例化对象明确的泛型约束数据类型元素
	 * 
	 * @param index 用户指定添加元素的下标位置
	 * @param e     符合实例化对象明确的泛型约束数据类型元素
	 * @return 操作成功返回true,否则返回false
	 */
	public boolean add(int index, E e) {
		// add 添加方法指定下标是否合法校验
		addRangCheck(index);
	
		// add 添加操作容量是否足够校验
		ensureCapacity(size + 1);
			
		// 从最后一个有效下标位置开始移动数据
		for (int i = size; i > index; i--) {
			elementData[i] = elementData[i - 1];
		}
		
		elementData[index] = e;
		size += 1;
		
		return true;
	}

 	/**
 	 * 添加另一个MyArrayList集合对象到当前集合中,要求参数集合存储类型和当前集合存储类型一致
 	 * 
 	 * @param list MyArrayList 集合对象,存储元素必须和当前集合一致
 	 * @return 操作成功返回true,否则返回false
 	 */
	public boolean addAll(MyArrayList<E> list) {
		
		ensureCapacity(size + list.size());
		
		return true;
	}
	
	/**
	 * 在指定下标位置,添加另一个MyArrayList集合对象到当前集合中,要求参数集合存储类型和当前集合存储类型一致
	 * 
	 * @param index 指定添加操作者下标位置
	 * @param list  MyArrayList 集合对象,存储元素必须和当前集合一致
	 * @return  操作成功返回true,否则返回false
	 */
	public boolean addAll(int index, MyArrayList<E> list) {
		addRangCheck(index);

		ensureCapacity(size + list.size());
		
		return true;
	}
	
	/**
	 * 获取当前MyArrayList 集合中的有效元素个数
	 * 
	 * @return 有效元素个数
	 */
	public int size() {
		return size;
	}
	
	/**
	 * 判断当前添加操作集合当前容量是否足够,如果不足,调用 grow 方法进行扩容
	 * 
	 * @param minCapacity 是当前集合添加操作所需最小容量要求
	 */
	private void ensureCapacity(int minCapacity) {
		if (minCapacity > elementData.length) {
			grow(minCapacity);
		}
	}
	
	/**
	 * 底层数组扩容方法
	 * 
	 * @param minCapacity 扩容操作最小集合容量需求
	 */
	private void grow(int minCapacity) {
		int oldCapacity = elementData.length;
		int newCapacity = oldCapacity + oldCapacity / 2;
		
		if (newCapacity < minCapacity) {
			newCapacity = minCapacity;
		}
		
		if (newCapacity > MAX_ARRAY_SIZE) {
			throw new OutOfMemoryError("内存溢出错误");
		}
		
		/*
		Object[] newArray = new Object[newCapacity];
		
		for (int i = 0; i < oldCapacity; i++) {
			newArray[i] = elementData[i];
		}
		
		elementData = newArray;
		
		 * Arrays 数组工具类方法
		 * 
		 * public static <T> T[] Arrays.copyOf(T[] t, int newLength);
		 *    根据用户传入的数组,以及新数组容量,创建对应当前数组存储数据类型新数组,并且将数据从原数组
		 * 中复制到新数组中,返回新数组首地址
		 */
		elementData = Arrays.copyOf(elementData, newCapacity);
	}
	
	/**
	 * private 修饰的私有方法,用于校验添加方法指定下标位置是否合法
	 * 
	 * @param index 用户指定添加操作的下标位置
	 */
	private void addRangCheck(int index) {
		if (index < 0 || index > size) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
	}
}

标签:下标,当前,int,元素,Collection,数组,集合
来源: https://www.cnblogs.com/A-Nan-q/p/16275235.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有