数据结构-ArrayLIst-一起探索顺序表的底层实现

打印 上一主题 下一主题

主题 835|帖子 835|积分 2505

各位看官早安午安晚安呀
  假如您以为这篇文章对您有帮助的话
  欢迎您一键三连,小编尽尽力做到更好
欢迎您分享给更多人哦


  大家好,我们本日来学习java数据结构的第一章ArrayList(顺序表)
  1.ArrayList的概念

   那小伙伴就要问了线性表到底是什么呢?           线性表    (    linear list    )    是    n    个具有雷同特性的数据元素的有限序列。     线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...(我们后续都会进行讲授)         线性表起首是一个序列,也就是说,元素之间是有顺序的,假如元素存在多个,那么第一个元素无前驱。末了一个元素无后驱。其他每个元素都必须有一个前驱和后驱。     例如:   
      usedSize这个变量黑白常紧张的,我们的增删查改都要用到   1.2ArrayList的模拟实现

  1. import java.util.Arrays;
  2. public class MyArrayList {
  3.     private int []elem;//用来存放数据
  4.     private int usedSize;//非常重要,代表当前顺序表当中的有效数据个数
  5.     private static final int DEFAULT_SIZE = 2;
  6.     public MyArrayList() {
  7.         this.elem = new int[DEFAULT_SIZE];
  8.     }
  9.     public MyArrayList(int initCapacity){
  10.         this.elem = new int[initCapacity];
  11.     }
  12.     // 新增元素,默认在数组最后新增
  13.     public void add(int data) {
  14.         if(elem.length == usedSize){
  15.             elem = Arrays.copyOf(elem,elem.length*2);
  16.         }
  17.         elem[usedSize] = data;
  18.         this.usedSize++;//一定不要忘记加
  19.     }
  20.     // 在 pos 位置新增元素
  21.     public void add(int pos, int data) {//只要带pos的都要进行检查
  22.         if(checkPos(pos) ==false ){
  23.             return;
  24.         }
  25.             if (elem.length == usedSize) {
  26.             elem = Arrays.copyOf(elem, elem.length * 2);
  27.         }
  28.             //下面这种写法就错误了,导致pos后面的值都是pos位置的值
  29.         /*for (int i = pos; i < usedSize -1; i++) {
  30.             elem[i+1] = elem[i];
  31.         }*/
  32.         //应该从后往前
  33.         for (int i = usedSize-1 ; i >= pos; i--) {
  34.             elem[i+1] = elem[i];
  35.         }
  36.         elem[pos] = data;
  37.         usedSize++;
  38.     }
  39.     /*public void delete(int pos){
  40.         if(checkPos(pos) == false)
  41.         if(this.usedSize == 0){
  42.             System.out.println("数组里面没有元素了");
  43.             return;
  44.         }
  45.         for (int i = 0; i < usedSize - 1; i++) {
  46.             elem[i] = elem[i+1];
  47.         }
  48.     }
  49. */
  50.     // 判定是否包含某个元素
  51.     public boolean contains(int toFind) {//啥意思
  52.         for (int i = 0; i < usedSize; i++) {
  53.             if(elem[i] == toFind ) //这里是int类型,所以你能够直接比较,其他类型的话,要重写equals方法
  54.                 return true;
  55.         }
  56.         return false;
  57.     }
  58.     // 查找某个元素对应的位置
  59.     public int indexOf(int toFind) {
  60.         for (int i = 0; i < usedSize; i++) {
  61.             if(elem[i] == toFind)
  62.             return i;
  63.         }
  64.         System.out.println("没有你要找的值");
  65.         return -1;
  66.     }
  67.     public boolean checkPos(int pos){
  68.         if( pos < 0 || pos >= usedSize){
  69.             System.out.println("下标错误");
  70.             return false;
  71.         }
  72.         return true;
  73.     }
  74.     // 获取 pos 位置的元素
  75.     public int get(int pos) {
  76.         if(checkPos(pos) == false){
  77.             return -1;
  78.         }
  79.         return elem[pos];
  80.     }
  81.     // 给 pos 位置的元素设为 value
  82.     public void set(int pos, int value) {
  83.         if(checkPos(pos) == false){
  84.             return;
  85.         }
  86.         elem[pos] = value;
  87.     }
  88.     //删除第一次出现的关键字key
  89.     public void remove(int data) {
  90.         int index = this.indexOf(data);
  91.         if(index == -1){
  92.             System.out.println("没有这个数据");
  93.             return;
  94.         }
  95.         for (int i = data; i < usedSize - 1; i++) {
  96.             elem[i] = elem[i+1];
  97.         }
  98.        //如果是引用类型的话: elem[index] = null;
  99.         this.usedSize--;
  100.     }
  101.     // 获取顺序表长度
  102.     public int size() {
  103.         return this.usedSize;
  104.     }
  105.     // 清空顺序表
  106.     public void clear() {
  107.         this.usedSize = 0;
  108.         //但是如果是引用类型的话
  109. /*
  110.         for (int i = 0; i < usedSize; i++) {
  111.             elem[i] = null;
  112.             记得全部置为空
  113.             引用类型的话,删除也要置为null
  114.         }
  115. */
  116.     }
  117.     // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
  118.     public void display() {
  119.         for (int i = 0; i < usedSize; i++) {
  120.             System.out.print(this.elem[i] + " ");
  121.         }
  122.     }
  123. }
复制代码
  目前我们自己实现了顺序表这种结构,以后用到的时间,Java已经为我们提供好了
  ArrayList(就是一个平凡的类实现了List接口)
  (自己看一下方法)(ArrayLIst内里的方法,底层方法)(我们可以看出来ArrsyList底层的数组我们在实例化对象时也是默认长度为我们的常量值,有效元素个数非常紧张,我们增加删除元素等方法都要用的)

2:构造方法

我们要了解一个类起首要了解他的构造方法
ArrayList<E>中的E就表现列表中存储的元素的类型
ArrayList

2.1:构造方法一,三

  1.        ArrayList<Integer> list = new ArrayList<>();   这种能用的方法更多
  2.        List<Integer> list = new ArrayList<>();    一般我们用这一种,向上转型,动态绑定的等等,你俩用哪个主要看自己业务场景
  3.        ArrayList<Integer> list = new ArrayList<>(15)
复制代码
我们可以看到默认数组长度是10,前面源码图解上有
2.2:构造方法二



然后我把list1指定的类型换成Integer就解决问题了!


大家也可以看到我显着对于list3只add了一次但是,打印出来的值却把list1数组内里的内容也拷贝过来了(拷贝在外面构造方法那一步就完成了)
2.3:ArrayList常见利用

  


  1. public static void main(String[] args) {
  2.         ArrayList<Integer> list = new ArrayList<>();
  3.         list.add(1);
  4.         list.add(2);
  5.         list.add(3);
  6.         list.add(1,4);
  7.         System.out.println(list);//到这里是【1,4,2,3】
  8.         list.remove(1);//这两个老是搞混,这个是删除1小标的值
  9.         list.remove(new Integer(1));//要删除1这个元素的值一定要用这种方法,因为这个参数是Object类型的
  10.         System.out.println(list);//到这里是【2,3】
  11.         // list.get(2);//这里会报一个数组越界异常,就是用来和UsedSize比较
  12.         list.add(99);
  13.         list.add(100);
  14.         list.add(101);
  15.         boolean isFalse = list.contains(new Integer(100));//这里最好用Integer类型的
  16.         System.out.println(isFalse);//true
  17.         List<Integer> list1 = list.subList(1,4);//左闭右开
  18.         System.out.println(list1);
  19.         list.set(1,200);
  20.         System.out.println(list);
  21.         System.out.println(list1);
  22.         //list1得到的是从list数组里面的引用,只要改变其中一个元素的值,另一个也会改变
  23.         list.clear();
  24.         System.out.println(list);
  25.         //全部清除
  26.     }
复制代码
2.4:ArrayList的三种遍历

   ArrayList   可以使用三方方式遍历:  for  循环  +  下标、  foreach  、使用迭代器
  1. public static void main(String[] args) {
  2. List<Integer> list = new ArrayList<>();
  3. list.add(1);
  4. list.add(2);
  5. list.add(3);
  6. list.add(4);
  7. list.add(5);
  8. // 使用下标+for遍历
  9. for (int i = 0; i < list.size(); i++) {
  10. System.out.print(list.get(i) + " ");
  11. }
  12. System.out.println();
  13. // 借助foreach遍历
  14. for (Integer integer : list) {
  15. System.out.print(integer + " ");
  16. }
  17. System.out.println();
  18. //迭代器
  19. Iterator<Integer> it = list.listIterator();
  20. //ListIterator<Integer> it = list.listIterator();也可以
  21. //ListIterator是Iterator的子类
  22. while(it.hasNext()){
  23. System.out.print(it.next() + " ");
  24. }
  25. System.out.println();
  26. }
复制代码
     注意:        1. ArrayList   最长使用的遍历方式是:   for   循环   +   下标 以及    foreach        2.    迭代器是设计模式的一种,后续博客我会继续讲授    2.5:ArrayList的扩容机制的缺陷

   ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。以下是ArrayList源码中扩容方式           【    总结    】           1.     检测是否真正必要扩容,假如是调用    grow    准备扩容           2.     预估必要库容的大小           初步预估按照    1.5    倍大小扩容 ,假如用户所需大小超过预估1.5    倍大小,则按照用户所需大小扩容           真正扩容之前检测是否能扩容成功,防止太大导致扩容失败           3.     使用    copyOf    进行扩容       3:杨辉三角

力扣杨辉三角
实现:
  1. import java.util.ArrayList;
  2. import java.util.Iterator;
  3. import java.util.List;
  4. public class Test {
  5.     public static void main(String[] args) {
  6.         int num = 5;
  7.         List<Integer> row = new ArrayList<>();
  8.         List<List<Integer>> ret = new ArrayList<>();
  9.         row.add(1);
  10.         ret.add(row);
  11.         for (int i = 1; i < num; i++) {
  12.             List<Integer> curRow1 = new ArrayList<>();
  13.             curRow1.add(1);//每行的第一个元素都是1
  14.             List<Integer> previousRow = ret.get(i - 1);
  15.             for (int j = 1; j < i; j++) {
  16.                 Integer x = previousRow.get(j) + previousRow.get(j - 1);
  17.                 curRow1.add(x);
  18.             }
  19.             curRow1.add(1);//每行的最后一个元素也都是1
  20.             ret.add(curRow1);//把这一行的数组加进去
  21.         }
  22.         for (List<Integer>list:ret   //遍历数组
  23.              ) {
  24.             System.out.println(list);
  25.         }
  26.         System.out.println("============================");
  27.         Iterator<List <Integer>> it = ret.listIterator();//使用迭代器遍历数组
  28. //ListIterator<Integer> it = list.listIterator();也可以
  29. //ListIterator是Iterator的子类
  30.         while(it.hasNext()){
  31.             System.out.print(it.next() + " ");
  32.             System.out.println();
  33.         }
  34.     }
  35.     }
复制代码

   上述就是数据结构-ArrayLIst-数组的深入包装 的全部内容了,能看到这里相信您肯定对小编的文章有了肯定的认可,数据结构的出现让我们对于数据的组织的使用有了更加方便的使用~~
  有什么问题欢迎各位大佬指出
欢迎各位大佬评论区留言修正

您的支持就是我最大的动力​​​!!!!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莱莱

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表