集合类——List集合

集合类(容器)

集合可以理解为动态数组,但是他区别于传统数组,
传统数组,是静态、线性的,长度是固定的。传统数组是通过下标控制元素的,数组的线性顺序是由下标决定的。
动态数组,顾名思义,是可以改变的数组,改变长度。可实现若干个对象的存储。
  • 传统数组长度定下了就不能变。如果以后需要在此数组中新增元素,或者是需要删除元素,大大受限制。数组长度已经固定,也就是说明分配空间固定,即内存空间给定了大小。
    增加元素:新增的元素如果大于此长度,将出现ArrayIndexOutOfBoundsException异常,不能正常运行。
    删除元素:某一处元素为空指向状态,没有指针指向它,这是删除原理。并不是将那一个位置的元素修改为null就等于删除。
    而传统数组是做不到有空指向的。
    因此,从JDK1.2引入了集合类
    JDK1.8实现算法改进
    在这里插入图片描述

集合类概述

集合类主要是对常见的数据结构进行完整的实现包装,然后提供了一系列的接口和实现子类。依次来帮助用户减少数据结构所带来的开发困难。
所有的类都继承Object,集合类也是。

List集合

List集合继承于Collection(单值集合操作最大父接口)

在这里插入图片描述

List集合特点

  • 元素允许重复
  • 各元素的顺序就是插入对象的顺序

List接口的实现类

  1. ArrayList类(List集合使用中占90%)
    优点:实现了可变数组,允许保存所有元素,包括null。可以根据索引位置对集合进行快速的随机访问
    缺点:指向索引位置插入对象或删除对象的速度较慢。
    2.LinkedList类(占比8%)
    采用链表结构保存对象(链表的顺序是由各个对象里的指针决定的,即通过指针前后指向相连,而不能像数组直接根据脚标直接选择指定对象)
    优点:这样的结构优点是便于向集合中插入、删除对象,效率高
    缺点:对于随机访问集合中的对象,使用LinkedList类实现List集合的效率低。(链表只能通过前后相邻的对象指向才能找到,因此如果时查询一个对象,可能需要遍历整个集合,时间复杂度为O(n))
    3.Vector类(占比2%)——转载
    Vector 是同步访问的
    Vector 包含了许多传统的方法,这些方法不属于集合框架。
    Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。
    Vector 类支持 4 种构造方法。
    详见:https://www.runoob.com/java/java-vector-class.html.

根据各自的优缺点,我认为可以根据各自的优点,在需求不同的时候使用。例如ArrayList访问快,那么在查询数据的时候,那么这一方面多半都适合用ArrayListArrayList。而LinkedList用于修改等。

ArrayList子类继承结构

在这里插入图片描述

举例
import java.util.ArrayList;
import java.util.List;

public class Test {
	public static void main (String args[]) {
		
		List<String> all = new ArrayList<String>();
		all.add("ab");
		all.add("cd");
		all.add("ef");
		System.out.println(all);
		System.out.println(all.get(0));	//集合的索引同样也是从0开始。
	}
}

在这里插入图片描述

Java没有指针,实现链表练习代码
interface ILink<E> {				//设置泛型避免安全隐患
	public void add(E e);			//增加数据
	public int size();				//获取数据的个数
	public void delete(E e);			//输出链表数据
	public boolean isEmpty();		//判断是否为空集合
	public Object toArray();			//获得集合的数据 
	public E get(int index);		//获取对应索引的数据
	public void set(int index ,E data);	//根据给定的索引,修改该索引的数据
	public boolean contains(E data);	//判断数据书否存在
	public void clean();				//集合清空
}

class LinkImpl<E> implements ILink<E>{	
	//——————————————————————LinkImpl内部类——————————————————————————————
	private class Node{						
		private E data;						//所需保存的数据
		private Node next;					//保存下一个引用
		private Object returnData[];
		public Node(E data) {				//存储数据
			this.data = data;
		}
		//连接外部,实现内容增加
		public void addNode(Node newNode) {	//判断当前所在节点
			if(this.next == null) {
				this.next = newNode;		//将下一个节点指向添加的节点元素
			}else {
				this.next.addNode(newNode);	
				//如果下一个节点有元素了,继续向后递归调用此方法,直到下一个节点为空,然后添加元素
			}
		}
		//连接外部,实现集合内容获取
		public void toArrayNode() {
			LinkImpl.this.returnData[LinkImpl.this.foot ++] = this.data ;		//将每个节点的数据依次存入数组,遇到空元素时停止存入
			if(this.next != null) {					//当下一个节点还有元素时
				this.next.toArrayNode();			//递归存入
			}
		}
		//连接外部,实现指定索引的内容获取
		public E getNode(int index) {
			if(LinkImpl.this.foot ++ == index) {	//根据脚标是否相等,返回相应元素
				return this.data;
			} else {
				return this.next.getNode(index);			//脚标不相等,递归,脚标向后指
			}
		}
		//连接外部的set方法,实现内容修改
		public void setNode(int index ,E data) {			//类似getNode 方法
			if(LinkImpl.this.foot ++ == index) {
				this.data = data;
			} else {
				this.next.setNode(index ,data);
			}
		}
		//连接外部的contains方法,实现内容查询
		public boolean containsNode(E data) {
			if(this.data.equals(data)) {
				return true;
			}else {
				if(this.next == null) {
					return false;
				}else {
					return this.next.containsNode(data);			//递归,直到内容相同
				}
			}
		}
		//连接外部,实现指定内容的删除
		public void deleteNode(Node prev ,E data) {
			if(this.data.equals(data)) {
				prev.next = this.next;
			} else {
				if(this.next != null) {
					this.next.deleteNode(this, data);		//向后继续删除
				}
			}
		}
	}
	//————————————————————————Link类中定义的成员和方法————————————————————
	private Node root;						//保存根元素
	private int count;						//次数
	private Object[] returnData;			//数组存储信息
	private int foot ;						//存储脚标
	public void add(E e) {					//添加数据方法
		if(e == null) {						//如果添加的没有数据,则结束方法
			return ;
		}
		//如果添加的有数据,则开始检测
		Node newNode = new Node(e);			
		//首节点没有数据时,此时已经将调用该方法的数据赋予给临时内部类对象newNode
		if(this.root == null) {				//首节点为空时,即此时只有空的表头,应该先将表头给值。
			this.root = newNode;			//将第一个节点作为根节点
		}
		else {
			this.root.next = newNode;
		}
		this.count ++;						//调用多少次add方法即增加多少数据
	}
	public int size() {						//获得数据个数
		return count;
	}
	public boolean isEmpty() {				//返回是否为空集合判断
		return this.root == null;
	}
	public Object[] toArray() {					//获取集合信息
		if(this.isEmpty()) {
			return null;
		}else {
			this.foot = 0 ;
			this.returnData = new Object[this.count] ;	//根据现在已有额长度开辟一个数组
			//利用Node类进行数据递归存取
			this.root.toArrayNode();
			return this.returnData;
		}
	}
	public E get(int index) {				//根据索引输出元素
		if(index > this.count) {
			return null;
		}	//索引类的数据获取应该由Node类完成
		this.foot = 0;
		return this.root.getNode(index);
	}
	//修改指定索引数据
	public void set(int index ,E data) {
		if(index >= this.count) {
			return;
		}
		this.foot = 0;
		this.root.setNode(index, data);
	}
	//判断数据是否存在
	public boolean contains(E data) {
		if(data == null)
			return false;
		return this.root.containsNode(data);
	}
	//删除集合元素
	public void delete(E data) {
		if(this.contains(data)) {
			if(this.root.data.equals(data)) {
				this.root = this.root.next;
			} else {
				this.root.next.deleteNode(this.root, data);		
				//递归调用内部类删除方法,下一个继续查询,直到有与data内容相同的元素
			}
			this.count --;
		}
	}
	//集合清空
	public void clean() {
		this.root = null;
		this.count = 0;
	}
}
public class Test{
	public static void main(String[] args) {
		//
		LinkImpl<String> out = new LinkImpl<String>();
		System.out.println("数据集合创建完毕");
		System.out.println("数据添加之前拥有个数:" + out.size() + "\t空集合?" + out.isEmpty());
		out.add("数据一");
		out.add("数据二");
		System.out.println("添加后拥有数据个数:" + out.size() + "\t空集合?" + out.isEmpty());
		//修改第二个数据为666
		out.set(1, "666");	
		//输出集合所有数据
		System.out.println("数据集合:");
		{
			Object res[] = out.toArray();
			for(Object obj : res) {
				System.out.println(obj);		
			}
		}
		//获取集合第一个数据
		System.out.println("集合第一个数据:" + out.get(1));
		//查询是否有“六零五”这一个数据
		System.out.println("数据“六零五”是否存在?" + out.contains("六零五"));
		//删除数据一
		out.delete("数据一");
		System.out.println("删除数据一后的集合:");
		{
			Object res[] = out.toArray();
			for(Object obj : res) {
				System.out.println(obj);		
			}
		}
		out.clean();			//已清空集合
		System.out.println(out.get(0));
	}
}

运行结果
在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值