本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
- 线性表
- 顺序表
- ArrayList
一. 线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结
构,常见的线性表:顺序表、链表、栈、队列…
线性表在逻辑上是线性结构,也就说是连续的一条直线。
但是在物理结构上并不一定是连续的,线性表在物
理上存储时,通常以 数组和链式结构的形式存储。
二. 顺序表
1.顺序表简介
顺序表是用一段物理地址连续的存储单元依次存储数据 元素的线性结构,一般情况下采用数组存储。
在数组上完成数据的 增删查改 。
了解了这些功能
那么我们就来仔细瞧瞧小伙伴的顺序表是怎么实现的吧 💖 💖 💖
2. 顺序表的实现
IList.Java
package ArrayList; public interface IList { // 新增元素,默认在数组最后新增 void add(int data); // 在 pos 位置新增元素 void add(int pos, int data); // 判定是否包含某个元素 boolean contains(int toFind); // 查找某个元素对应的位置 int indexOf(int toFind); // 获取 pos 位置的元素 int get(int pos); // 给 pos 位置的元素设为 value -> 更新 void set(int pos, int value); //删除第一次出现的关键字key void remove(int toRemove); // 获取顺序表长度 int size(); // 清空顺序表 void clear(); // 打印顺序表, // 注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的 void display(); boolean isFull(); // 判断数组是否为 空 public boolean isEmpty(); }
MyArrayList.Java
package ArrayList; import java.util.Arrays; public class MyArrayList implements IList{ // 定义一个数组 public int []elem; //存放数据的长度 public int usesize; // 默认容量大小 public static final int DEFINESIZE=2; // 初始化顺序表 public MyArrayList() { elem=new int[DEFINESIZE]; try { CheckArrayNullException(); } catch (NullArrayException e) { e.printStackTrace(); } } // 尾插数据 @Override public void add(int data) { if (isFull()) { this.elem= Arrays.copyOf(elem,2*elem.length); } this.elem[usesize]=data; usesize++; } // 检查合法性 private void IndexOutOfBoundsAdd(int pos) throws PosNotLegalException{ if (pos<0 || pos > usesize) { throw new PosNotLegalException("顺序表下标异常,无法处理数据!"); } } // 指定位置插入数据 @Override public void add(int pos, int data) { try { IndexOutOfBoundsAdd(pos); } catch (PosNotLegalException e) { e.printStackTrace(); } if (isFull()) { this.elem= Arrays.copyOf(elem,2*elem.length); } for (int i = usesize-1; i >=pos ; i--) { elem[i+1]=elem[i]; } this.elem[pos]=data; this.usesize++; } // 声明一个下标查找和删除的异常 private void IndexOutOfBoundsFindandset(int pos) throws PosNotLegalException{ if (pos<0 || pos >= usesize) { throw new PosNotLegalException("顺序表下标异常,无法处理数据!"); } } // 检查数据是否包含 @Override public boolean contains(int toFind) { for (int i = 0; i < usesize; i++) { if (elem[i]==toFind) { return true; } } return false; } // 查找数据.索引 @Override public int indexOf(int toFind) { if (isEmpty()) { System.out.println("顺序表无数据,查找失败!"); return -1; } for (int i = 0; i < usesize; i++) { if (elem[i]==toFind) { return i; } } System.out.println("不存在该数据,查找失败!"); return -1; } // 得到数组数据 @Override public int get(int pos) { return elem[pos]; } // 在指定位置修改数据 @Override public void set(int pos, int value) { try { IndexOutOfBoundsFindandset(pos); } catch (PosNotLegalException e) { e.printStackTrace(); } elem[pos]=value; } // 删除数据 @Override public void remove(int toRemove) { int pos=this.indexOf(toRemove); try { IndexOutOfBoundsFindandset(pos); } catch (PosNotLegalException e) { e.printStackTrace(); return; } for (int i = pos; i < usesize-1; i++) { elem[i] = elem[i + 1]; } usesize--; } // 用户得到顺序表现有数据长度 @Override public int size() { return usesize; } // 清除顺序表数据 @Override public void clear() { usesize=0; } // 打印数据 @Override public void display() { for (int i = 0; i < usesize; i++) { System.out.print(elem[i]+" "); } System.out.println(); } // 检查数据是否满 @Override public boolean isFull() { return usesize==elem.length; } // 检查数据是否为空 @Override public boolean isEmpty() { return usesize==0; } // 异常检查: 顺序表是否为 null private void CheckArrayNullException() throws NullArrayException{ if (elem==null) { throw new NullArrayException("顺序表为 null 异常"); } } }
NullArrayException.java
package ArrayList; public class NullArrayException extends RuntimeException { public NullArrayException() { super(); } public NullArrayException(String message) { super(message); } }
Test.Java
package ArrayList; public class Test { public static void main(String[] args) { IList list=new MyArrayList(); System.out.println("=======增加功能========"); list.add(1); list.add(3); list.add(4); list.add(1,2); list.display(); System.out.println("========删除功能========="); // list.add(-1,4); list.remove(2); list.remove(1); list.display(); System.out.println("=====查找功能======="); int num=4; boolean b1=list.contains(num); if (b1) { System.out.println("含有该数据"); System.out.println("下标为:"+list.indexOf(num)); } else { System.out.println("该数据不存在!"); } System.out.println("========修改数据======="); list.set(1,9); list.display(); System.out.println("=======得到数据======="); System.out.println(list.get(0)); System.out.println("=======释放顺序表======="); list.clear(); } }
从而在我们 main方法中实现我们的增删查改的功能(如下图)
以上是我们看到的顺序表的实现的全过程
主要框架是以数组为底层,用不同的方法建立我们的对数据的功能的连接,从而实现我们想要的各种的数据的处理的效果(增删查改)
鱼式疯言
细节说明
- 当数组容量不够时怎么办 ???
this.elem= Arrays.copyOf(elem,2*elem.length);
这时我们需要 拷贝原数据 ,并创建 新空间 用 copyof 方法就再合适不过了
- 当下标越界时怎么办 ???
try { IndexOutOfBoundsAdd(pos); } catch (PosNotLegalException e) { e.printStackTrace(); }
我们就可以用 try…catch… 来抛出异常
- 当 顺序表为null 时怎么办 ? ? ?
if (elem==null) { throw new NullArrayException("顺序表为 null 异常"); }
我们就也可以用 try…catch… 来抛出异常
而这些异常我们即可以自己实现(上面)
也可以借助异常类来使用
三. ArrayList
1. ArrayList
在集合框架中, ArrayList是一个普通的类,实现了List接口 ,具体框架图如下:
小小说明下
- ArrayList 是以泛型方式实现的,使用时必须要先实例化
- ArrayList实现了 RandomAccess 接口,表明 ArrayList支持随机访问
- ArrayList 实现了 Cloneable 接口,表明 ArrayList是可以clone的
- ArrayList实现了 Serializable接口,表明ArrayList是支持序列化的
- 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
- ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
以上说明小伙伴们了解即可,无须熟悉掌握哦 ,重点小编都会重点强调哦💕 💕 💕
ArrayList的实现
IGist
package generarraylist; public interface IGList<T>{ // 新增元素,默认在数组最后新增 void add(T data); // 在 pos 位置新增元素 void add(int pos, T data); // 判定是否包含某个元素 boolean contains(T toFind); // 查找某个元素对应的位置 int indexOf(T toFind); // 获取 pos 位置的元素 T get(int pos); // 给 pos 位置的元素设为 value -> 更新 void set(int pos, T value); //删除第一次出现的关键字key void remove(T toRemove); // 获取顺序表长度 int size(); // 清空顺序表 void clear(); // 打印顺序表, // 注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的 void display(); boolean isFull(); // 判断数组是否为 空 public boolean isEmpty(); }
GMyArrayList.java
package generarraylist; import ArrayList.IList; import ArrayList.NullArrayException; import ArrayList.PosNotLegalException; import java.util.Arrays; public class GMyArrayList<T> implements IGList<T> { // 定义一个数组 public Object []elem; //存放数据的长度 public int usesize; // 默认容量大小 public static final int DEFINESIZE=2; // 初始化顺序表 public GMyArrayList() { elem=new Object[DEFINESIZE]; try { CheckArrayNullException(); } catch (NullArrayException e) { e.printStackTrace(); } } // 尾插数据 @Override public void add(T data) { if (isFull()) { this.elem= Arrays.copyOf(elem,2*elem.length); } this.elem[usesize]=data; usesize++; } // 检查合法性 private void IndexOutOfBoundsAdd(int pos) throws PosNotLegalException { if (pos<0 || pos > usesize) { throw new PosNotLegalException("顺序表下标异常,无法处理数据!"); } } // 指定位置插入数据 @Override public void add(int pos, T data) { try { IndexOutOfBoundsAdd(pos); } catch (PosNotLegalException e) { e.printStackTrace(); } if (isFull()) { this.elem= Arrays.copyOf(elem,2*elem.length); } for (int i = usesize-1; i >=pos ; i--) { elem[i+1]=elem[i]; } this.elem[pos]=data; this.usesize++; } // 声明一个下标查找和删除的异常 private void IndexOutOfBoundsFindandset(int pos) throws PosNotLegalException{ if (pos<0 || pos >= usesize) { throw new PosNotLegalException("顺序表下标异常,无法处理数据!"); } } // 检查数据是否包含 @Override public boolean contains(T toFind) { for (int i = 0; i < usesize; i++) { if (elem[i].equals(toFind)) { return true; } } return false; } // 查找数据.索引 @Override public int indexOf(T toFind) { if (isEmpty()) { System.out.println("顺序表无数据,查找失败!"); return -1; } for (int i = 0; i < usesize; i++) { if (elem[i].equals(toFind)) { return i; } } System.out.println("不存在该数据,查找失败!"); return -1; } // 得到顺序表数据 @Override public T get(int pos) { return (T)elem[pos]; } // 在指定位置修改数据 @Override public void set(int pos, T value) { try { IndexOutOfBoundsFindandset(pos); } catch (PosNotLegalException e) { e.printStackTrace(); return; } elem[pos]=value; } // 删除数据 @Override public void remove(T toRemove) { int pos=this.indexOf(toRemove); try { IndexOutOfBoundsFindandset(pos); } catch (PosNotLegalException e) { e.printStackTrace(); return; } for (int i = pos; i < usesize-1; i++) { elem[i] = elem[i + 1]; } usesize--; } // 用户得到顺序表现有数据长度 @Override public int size() { return usesize; } // 清除顺序表数据 @Override public void clear() { for (int i = 0; i < elem.length; i++) { elem[i]=null; } usesize=0; } // 打印数据 @Override public void display() { for (int i = 0; i < usesize; i++) { System.out.print(elem[i]+" "); } System.out.println(); } // 检查数据是否满 @Override public boolean isFull() { return usesize==elem.length; } // 检查数据是否为空 @Override public boolean isEmpty() { return usesize==0; } // 异常检查: 顺序表是否为 null private void CheckArrayNullException() throws NullArrayException{ if (elem==null) { throw new NullArrayException("顺序表为 null 异常"); } } }
GNullArrayException
package generarraylist; public class GNullArrayException extends RuntimeException { public GNullArrayException() { super(); } public GNullArrayException(String message) { super(message); } }
GPosNotLegalException
package generarraylist; public class GPosNotLegalException extends RuntimeException{ public GPosNotLegalException() { super(); } public GPosNotLegalException(String message) { super(message); } }
Test.java
package generarraylist; import ArrayList.IList; import ArrayList.MyArrayList; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Test { public static void main(String[] args) { IGList<String> s=new GMyArrayList<>(); System.out.println("&&&&&&&&&&&&&&插入数据&&&&&&&&&&&"); s.add("1"); s.add("2"); s.add("3"); s.add(3,"4"); s.display(); System.out.println("^^^^^^^^^^^^^删除数据^^^^^^^^^^^^"); s.remove("2"); s.display(); System.out.println("###########查找数据############"); String str="4"; boolean b=s.contains(str); System.out.println(b); if (b) { System.out.println(s.indexOf(str)); } System.out.println("@@@@@@@@@@@@@修改数据@@@@@@@@@@@@@@@"); s.set(1,"2"); s.set(2,"3"); s.display(); s.clear(); } }
小伙伴们觉得咋样这个代码的展示效果是不是比我们前面单纯的顺序表牛多了呢,是的呢 ! ! !
这个代码虽然功能是相同的,但唯一的优势是在 原来的顺序表的基础上加上我们的泛型的应用,使代码从单纯的整型变成了可以传递任何参数的类型
鱼式疯言
需要注意几点
- 我们这里的类型 一定是引用类型,包装类型,类类型(et:String,Interge ,Boolean,Student…),不允许是基本数据类型哦(et:int,double,char…)
- 定义数组的时候要注意我们是使用 object
- 返回数据时需要 强转类型
- 实例化对象时 注意加类型
ArrayList的使用
在上面的 main方法 中,小编已经展示了然后调用我们的 ArrayList中各种方法,小编在这里就不赘述了 💖 💖 💖
透露一下哦,在下篇文章中我们结合 ArrayList 具体讲解他的实际运用:洗牌游戏
小伙们到时候将会对ArrayList中的各种方法理解的更深刻哦
总结
- 线性表: 我们主要讲解了线性表的概念,以及线性表都有哪些
- 顺序表: 我们主要是对顺序表进行了实现,并重点说明了顺序表的各种实现细节
- ArrayList: 在我们Java自带的一种顺序表,我们也进行了实现并理解了细节
如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正
希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 💖 💖 💖