zoukankan      html  css  js  c++  java
  • Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)

    横看成岭侧成峰,远近高低各不同。
    不识庐山真面目,只缘身在此山中。

                  ——苏轼

    这一块儿学的是云里雾里,咱们先从简单的入手。逐渐的拨开迷雾见太阳。本次先做List集合的三个实现类的学习笔记

    List特点:有序,元素可重复。其实它的本质就是一个线性表(下面会说到)

    先上图,Java集合有Collection体系和Map体系:

    然后简单介绍一下数据结构和算法:

    数据结构就是数据和数据之间的关系,好比分子结构,晶体结构。碳原子按照一定的方式组合在一起形成碳分子,碳分子再按照一定方式形成晶体。

    算法是对解题步骤的描述,体现在计算机上就是指令的有限序列

    数据结构分为逻辑结构和物理结构。

    逻辑结构:

    物理结构:

    顺序存储结构和链式存储结构。

    顺序存储结构:在内存中开辟若干的连续空间,将每个空间存入数据,数据关联与其地址一致。比如数组。

    上代码:

     1 public class Test01 {
     2 
     3     public static void main(String[] args) {
     4         Integer[] arr = new Integer[10];
     5         //向数组中插入元素
     6         for (int i = 0; i < arr.length; i++) {
     7             arr[i] = i;
     8         }
     9         //将其中一个元素变为null;
    10         arr[3] = null;
    11         //出现碎片
    12         for (Integer item : arr) {
    13             System.out.println(item);
    14         }
    15         System.out.println("===========");
    16         arr[3] = 12;//存取方便,可直接赋值或取值
    17         //删除第X个元素,但要避免碎片产生:
    18         int x = 2;
    19         arr[x-1]=null;//第二个元素引用变为null,该步骤可以省略,因为下面又更改了arr[x-1]的引用。写上仅为便于理解
    20         //第X个元素之后的元素前移,代码表现为把后面的值依次赋给前面,从第X个开始
    21         for (int i = x-1; i < arr.length-1; i++) {
    22             arr[i] = arr[i+1];
    23         }
    24         //length-1,需要新建数组来保存原数组
    25         Integer[] newArr = new Integer[arr.length-1];
    26         for (int i = 0; i < newArr.length; i++) {
    27             newArr[i]=arr[i];
    28             System.out.println(newArr[i]);
    29         }
    30         System.out.println("============");
    31         //第Y个位置插入一个元素
    32         int y = 5;
    33         //需要后移,所以先创建数组length+1
    34         Integer [] newArr2 = new Integer[newArr.length+1];
    35         for (int i = 0; i < newArr.length; i++) {
    36             newArr2[i] = newArr[i];
    37         }
    38         //后移
    39         for (int i = newArr2.length-1; i > y-1 ; i--) {
    40             newArr2[i]=newArr2[i-1];
    41         }
    42         //插入
    43         newArr2[y-1] = 22;
    44         //遍历输出
    45         for (int i = 0; i < newArr2.length; i++) {
    46             System.out.println(newArr2[i]);
    47         }
    48     }
    49     
    50 }
    View Code

    出结论:

    顺序存储结构:

    优点:1无需为表示表中元素之间的逻辑关系而添加空间

       2可以快速地存取表中任意位置的元素

    缺点:1插入和删除操作需要移动大量元素

         2需要考虑索引越界为题

         3扩容空间可能会造成空间浪费,缩小空间又可能会索引越界

         4null值会造成空间“碎片”

    链式存储结构:每个元素只记住它下一个元素是谁(地址)。

    链式存储结构有多种,这里只介绍Java的链式存储结构:双向链表

    上代码:

     1 public class MyLinkedListDemo {
     2 
     3     public static void main(String[] args) throws Exception {
     4         MyLinkList<String> list = new MyLinkList<>();
     5         list.addFist("张三");
     6         list.addFist("李四");
     7         list.addLast("张三");
     8         list.addLast("李四");
     9         list.print();
    10         System.out.println("===========");
    11         list.add(2,"王五");
    12         list.print();
    13         System.out.println("===========");
    14         list.add(5,"王五");
    15         System.out.println(list.getSize());
    16         list.add(7,"王五");//这里会抛出空指针异常
    17     }
    18 }
    View Code
     1 public class MyLinkList<E> {
     2 
     3     Node<E> first;
     4     Node<E> last;
     5     
     6     public void addFist(E e){
     7         if (first == null) {
     8             final Node<E> newNode = new Node<E>(null, e, null);//第一次加入数据,为first,last赋初值
     9             first = newNode;
    10             last = newNode;
    11         }else{//否则把first的prev指向newNode,把newNode的next指向first,最后把newNode变为first
    12             final Node<E> newNode = new Node<E>(null, e, first);
    13             first.prev = newNode;
    14             first = newNode;
    15         }
    16     }
    17     public void addLast(E e){
    18         if (last == null) {
    19             final Node<E> newNode = new Node<E>(null, e, null);//第一次加入数据,为first,last赋初值
    20             first = newNode;
    21             last = newNode;
    22         }else{//否则把last的next指向newNode,把newNode的prev指向last,最后把newNode变为last
    23             final Node<E> newNode = new Node<E>(last, e, null);
    24             last.next = newNode;
    25             last = newNode;
    26         }
    27     }
    28     public void add (int index,E e) throws Exception{//下标超出链表长度会空指针,因为超出长度的部分prev和next都是null
    29         if(index == 0){
    30             addFist(e);
    31         }else if (index == getSize()) {
    32             addLast(e);
    33         }else {
    34             //这里画张图想一下,我要在1处插入x,就要把x的prev指向0,next指向1,把0的next指向x,把1的prev指向x
    35             //这里的1和0就是index和index-1,通过循环Node.next获取index对应的Node
    36             //先拿到0和1
    37             Node<E> tempNodeNext = first;
    38             for (int i = 0; i < index; i++) {
    39                 tempNodeNext = tempNodeNext.next;
    40             }
    41             Node<E> tempNodePrev = tempNodeNext.prev;
    42             //这里改指向
    43             final Node<E> newNode = new Node<E>(tempNodePrev, e, tempNodeNext);
    44             tempNodeNext.prev = newNode;
    45             tempNodePrev.next = newNode;
    46         }
    47     }
    48     public int getSize (){
    49         Node<E> temp = first;
    50         int i = 0;
    51         while(temp != null){
    52             temp = temp.next;
    53             i++;
    54         }
    55         return i;
    56     }
    57     //由于不实现Iterable,只能提供打印方法
    58     public void print() {
    59         Node<E> temp = first;
    60         while(temp != null){
    61             System.out.println(temp.item);
    62             temp = temp.next;
    63         }
    64     }
    65     private static class Node<E>{
    66         Node<E> prev;
    67         E item;
    68         Node<E> next;
    69         Node(Node<E> prev, E item, Node<E> next) {
    70             super();
    71             this.prev = prev;
    72             this.item = item;
    73             this.next = next;
    74         }
    75     }
    76 }
    View Code

    出结论:

    链式存储结构:

    优点:插入和删除操作只需改变节点next和prev成员的指向即可,无需移位,无需扩容

    缺点:失去了直接存取表中任意位置元素的能力

    顺序存储结构和链式存储结构的对比:

    1、存储分配方式:

    顺序存储结构使用一段连续的存储单元依次存储线性表元素

    链式存储结构使用任意存储单元存放线性表的元素

    2、时间性能:

    查找:

    顺序存储结构O(1)

    链式存储结构O(n)

    插入和删除:

    顺序存储结构O(n)

    链式存储结构O(1)

    3、空间性能:

    顺序存储结构:空间分大了浪费,分小了上溢,还得扩容

    链式存储结构:有空间就能分配,元素个数不受限制

    言归正传。

    ArrayList是顺序存储的线性表,LinkedList是链式存储的线性表

    它们的特点都是有序,元素值可以重复。区别是底层算法不同。

    Vector,这里我简单浏览了一下源代码,Vector底层算法和ArrayList是一样的

    这里就不赘述了,直接说区别:

    1、Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法线程不安全,由于线程的同步必然要影响性能,因此ArrayList的性能比Vector好。 
    2、Vector扩容时容量翻倍,而ArrayList只增加50%的大小,(直接查它们的grow()方法)这样,ArrayList就有利于节约内存空间。

    总之ArrayList比Vector在性能方面(无论时间性能还是空间性能)都是能省则省。

    List就说到这里。下一篇说说队列

  • 相关阅读:
    Android Logcat使用技巧
    SqlClient使用存储过程并获取输出参数的指
    内存调试的东西D/dalvikvm( 809 ): GC_CONCURRENT freed
    android 读写sd卡的权限设置
    Android中EditText的使用方法持續更新
    RSL编译方式的FLEX站点出现#2046错误
    从网络读取数据并动态的显示在ListView中
    LEFT JOIN INNER JOIN 效率比较
    使用Installshield2009 在IIS6部署Asp.net mvc 应用程序
    Installshield2009中使用osql.exe执行数据库脚本
  • 原文地址:https://www.cnblogs.com/tomasman/p/6819276.html
Copyright © 2011-2022 走看看