• 基于Java的ArrayList和LinkedList的实现与总结


    一、定义MyList接口,包含列表常见方法:

     1 import java.util.Iterator;
     2 
     3 /**
     4  * 线性表(列表)的接口定义
     5  */
     6 public interface MyList<T> extends Iterator<T> {
     7     
     8     /** 新增一个元素 */
     9     void add(T element);
    10 
    11     /** 删除相同元素 */
    12     void delete(T element);
    13 
    14     /** 根据索引删除元素 */
    15     void delete(int index);
    16 
    17     /**
    18      * 将指定索引位置的元素替换成新元素
    19      * 
    20      * @param index
    21      * @param newElement
    22      */
    23     void update(int index, T newElement);
    24 
    25     /**
    26      * 当前列表中是否含有target这个元素
    27      * 
    28      * @param target
    29      * @return
    30      */
    31     boolean contains(T target);
    32 
    33     /**
    34      * 返回指定索引处的元素
    35      * 
    36      * @param index
    37      * @return
    38      */
    39     T at(int index);
    40 
    41     /**
    42      * 查找element的索引,如果没有返回-1
    43      * 
    44      * @param element
    45      * @return
    46      */
    47     int indexOf(T element);
    48 
    49 }
    View Code

    二、实现ArrayList类:

     1 /**
     2  * 用顺序存储(数组)方式来实现列表
     3  */
     4 public class MyArrayList<T> implements MyList<T> {
     5     private T[] elements;// 真正存储元素的底层结构
     6 
     7     private int size = 0;// 元素个数
     8 
     9     private int capacity = 10;// 容量
    10 
    11     public MyArrayList(int capacity) {
    12         this.capacity = capacity;
    13         elements = (T[]) new Object[capacity];
    14     }
    15 
    16     public MyArrayList() {
    17         elements = (T[]) new Object[capacity];
    18     }
    19 
    20     @Override
    21     public void add(T element) {
    22         if (size == capacity) {// 扩容
    23             capacity *= 2;// 增加一倍的容量
    24             T[] newArr = (T[]) new Object[capacity];// 新建一个数组
    25             for (int i = 0; i < size; i++) {
    26                 newArr[i] = elements[i];
    27             }
    28             elements = newArr;// 把旧的那个柜子扔掉
    29         }
    30         elements[size++] = element;
    31     }
    32 
    33     @Override
    34     public void delete(T element) {
    35         int index = indexOf(element);
    36         if (index >= 0) {
    37             delete(index);
    38         }
    39     }
    40 
    41     @Override
    42     public void delete(int index) {
    43         // 重新调整空间
    44         for (int i = index; i < size - 1; i++) {
    45             elements[i] = elements[i + 1];
    46         }
    47         elements[size - 1] = null;
    48         size--;
    49     }
    50 
    51     @Override
    52     public void update(int index, T newElement) {
    53         elements[index] = newElement;
    54     }
    55 
    56     @Override
    57     public boolean contains(T target) {
    58         return indexOf(target) >= 0;
    59     }
    60 
    61     @Override
    62     public T at(int index) {
    63         return elements[index];
    64     }
    65 
    66     @Override
    67     public int indexOf(T element) {
    68         for (int i = 0; i < size; i++) {
    69             if (elements[i].equals(element)) { 
    70                 return i;
    71             }
    72         }
    73         return -1;
    74     }
    75 
    76     @Override
    77     public String toString() {
    78         StringBuilder sb = new StringBuilder("[");
    79         for (int i = 0; i < size; i++) {
    80             sb.append(elements[i] + (i == size - 1 ? "" : " , "));
    81         }
    82         sb.append("]");
    83         return sb.toString();
    84     }
    85 
    86     // 
    87     @Override
    88     public boolean hasNext() {
    89         return false;
    90     }
    91 
    92     @Override
    93     public T next() {
    94         return null;
    95     }
    96 }
    View Code

    三、链表结点类:

     1 /*节点*/
     2 public class ListNode<T> {
     3     T data;
     4     ListNode<T> pre;
     5     ListNode<T> next; // next 实际存的是下一个节点  重要理解
     6 
     7     public ListNode(T data) {
     8         this.data = data;
     9     }
    10 
    11     public T getData() {
    12         return data;
    13     }
    14 
    15     public ListNode<T> getPre() {
    16         return pre;
    17     }
    18 
    19     public void setNext(ListNode<T> next) {
    20         this.next = next;
    21     }
    22 
    23     public void setPre(ListNode<T> pre) {
    24         this.pre = pre;
    25     }
    26 
    27     public ListNode<T> getNext() {
    28         return next;
    29     }
    30 }
    View Code

    四、单链表实现:

    public class SingleLinkedList<T> implements MyList<T> {
        private ListNode<T> first;  // 头节点 head
        private ListNode<T> last;     // 尾节点 
        private int size;
    
        @Override
        public void add(T element) {
            if (first == null) {
                first = new ListNode(element);
                last = first;
            } else {
                last.next = new ListNode(element);  // next 实际存的是下一个节点  重要理解
                last = last.next;
            }
            size++;
        }
    
        @Override
        public void delete(T element) {
            ListNode p = first;
            ListNode pre = null;
            while (p != null) {
                if (p.data.equals(element)) {
                    if (p == first)
                        first = first.next;
                    else
                        pre.next = p.next;
                    size--;
                    break;// 注意这里
                }
                pre = p;
                p = p.next;
            }
        }
    
        // 链表删除
        // 参数为索引
        @Override
        public void delete(int index) {
            if (index < 0 || index >= size) {
                return;// 啥也不干
            }
            int i = 0;// 指针指向的节点的索引
            ListNode p = first;
            ListNode pre = null;
    
            while (p != null) {
                if (i == index) {
                    if (p == first)
                        first = first.next;
                    else
                        pre.next = p.next;
                    break;// 注意这里
                }
                pre = p;
                p = p.next;
                i++;
            }
            size--;
        }
    
        @Override
        public void update(int index, T newElement) {
            if (index < 0 || index >= size) {
                return;// 啥也不干
            }
            int i = 0;// 指针指向的节点的索引
            ListNode p = first;
    
            while (p != null) {
                if (i == index) {
                    p.data = newElement;
                }
                p = p.next;
                i++;
            }
        }
    
        @Override
        public boolean contains(T target) {
            ListNode p = first;
            while (p != null) {
                if (p.data.equals(target)) {
                    return true;
                }
                p = p.next;
            }
            return false;
        }
    
        // 返回索引所在的data
        @Override
        public T at(int index) {
            if (index < 0 || index >= size) {
                return null;
            }
            int i = 0;// 指针指向的节点的索引
            ListNode<T> p = first;
    
            while (p != null) {
                if (i == index) {
                    return p.data;
                }
                p = p.next;
                i++;
            }
            return null;
        }
    
        @Override
        public int indexOf(T element) {
            int i = 0;// 指针指向的节点的索引
            ListNode p = first;
    
            while (p != null) {
                if (p.data.equals(element)) {
                    return i;
                }
                p = p.next;
                i++;
            }
            return -1;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("[");
            ListNode p = first;
            while (p != null) {
                sb.append(p.data);
                if (p.next != null)
                    sb.append(",");
                p = p.next;
            }
            sb.append("]");
            return sb.toString();
        }
    
        @Override
        public boolean hasNext() {
            return false;
        }
    
        @Override
        public T next() {
            return null;
        }
    }
    View Code

    五、双链表实现

      1 import java.util.Iterator;
      2 
      3 public class DoubleLinkedList<T> implements MyList<T> {
      4     
      5     // 多了两个没有数据的头节点和尾节点 哑元
      6     protected ListNode<T> first = new ListNode(null);
      7     protected ListNode<T> last = new ListNode(null);
      8     protected int size;
      9 
     10     public int getSize() {
     11         return size;
     12     }
     13 
     14     public DoubleLinkedList() {
     15         first.next = last;
     16         last.pre = first;
     17     }
     18 
     19     @Override
     20     public void add(T element) {
     21         ListNode<T> newNode = new ListNode(element);
     22         last.pre.next = newNode;
     23         newNode.next = last;
     24         newNode.pre = last.pre;
     25         last.pre = newNode;
     26         size++;
     27     }
     28 
     29     @Override
     30     public void delete(T element) {
     31         ListNode<T> p = first.next;
     32         while (p != last) {
     33             if (p.data.equals(element)) {
     34                 p.pre.next = p.next;
     35                 p.next.pre = p.pre;
     36                 p.next = null;
     37                 p.pre = null;
     38                 size--;
     39                 break;
     40             }
     41             p = p.next;
     42         }
     43     }
     44 
     45     @Override
     46     public void delete(int index) {
     47         if (index < 0 || index >= size) {
     48             return;// 啥也不干
     49         }
     50         int i = 0;// 指针指向的节点的索引
     51         ListNode p = first.next;
     52 
     53         while (p != last) {
     54             if (i == index) {
     55                 p.pre.next = p.next;
     56                 p.next.pre = p.pre;
     57                 p.next = null;
     58                 p.pre = null;
     59                 size--;
     60                 break;// 注意这里
     61             }
     62             p = p.next;
     63             i++;
     64         }
     65     }
     66 
     67     @Override
     68     public void update(int index, T newElement) {
     69         if (index < 0 || index >= size) {
     70             return;// 啥也不干
     71         }
     72         int i = 0;// 指针指向的节点的索引
     73         ListNode p = first.next;
     74 
     75         while (p != last) {
     76             if (i == index) {
     77                 p.data = newElement;
     78             }
     79             p = p.next;
     80             i++;
     81         }
     82     }
     83 
     84     @Override
     85     public boolean contains(T target) {
     86         ListNode p = first.next;
     87         while (p != last) {
     88             if (p.data.equals(target)) {
     89                 return true;
     90             }
     91             p = p.next;
     92         }
     93         return false;
     94     }
     95 
     96     @Override
     97     public T at(int index) {
     98         if (index < 0 || index >= size) {
     99             return null;
    100         }
    101         int i = 0;// 指针指向的节点的索引
    102         ListNode<T> p = first.next;
    103 
    104         while (p != last) {
    105             if (i == index) {
    106                 return p.data;
    107             }
    108             p = p.next;
    109             i++;
    110         }
    111         return null;
    112     }
    113 
    114     @Override
    115     public int indexOf(T element) {
    116         int i = 0;// 指针指向的节点的索引
    117         ListNode<T> p = first.next;
    118 
    119         while (p != last) {
    120             if (p.data.equals(element)) {
    121                 return i;
    122             }
    123             p = p.next;
    124             i++;
    125         }
    126         return -1;
    127     }
    128 
    129     @Override
    130     public String toString() {
    131         StringBuilder sb = new StringBuilder("[");
    132         ListNode p = first.next;
    133         while (p != last) {
    134             sb.append(p.data);
    135             if (p.next != last)
    136                 sb.append(",");
    137             p = p.next;
    138         }
    139         sb.append("]");
    140         return sb.toString();
    141     }
    142 
    143     
    144     // 实现迭代器  MyList 继承Iterator<T>这个接口
    145     private ListNode now = first;
    146 
    147     @Override
    148     public boolean hasNext() {
    149         return now.next != last;
    150     }
    151 
    152     @Override
    153     public T next() {
    154         ListNode<T> next = now.next;
    155         now = now.next;
    156         return next.data;
    157     }
    158 }
    View Code

    六、Java ListApi的基本使用:

     1 import java.util.*;
     2 
     3 public class ListApiDemo {
     4     public static void main(String[] args) {
     5     List<String> list = new ArrayList<>();
     6     list = new LinkedList<>();
     7     list.add("adnda");
     8     list.add("xyz");
     9     list.add("def");
    10     list.remove("");
    11     //  ......
    12 
    13     Collections.sort(list);
    14 
    15     System.out.println(list);
    16     List<Student> list1 = new ArrayList<>();
    17     list1.add(new Student("zhangsan", 10));
    18     list1.add(new Student("lsii", 20));
    19     list1.add(new Student("wangwu", 40));
    20     list1.add(new Student("wangsu", 30));
    21 
    22     Collections.sort(list1, (o1, o2) -> {
    23       return o1.getAge() - o2.getAge();
    24     });
    25 
    26     System.out.println(list1);
    27 
    28     for (int i = 0; i < list1.size(); i++) {
    29       System.out.println(list1.get(i));
    30     }
    31 
    32     System.out.println("===============");
    33     for (Student stu : list1) {
    34       System.out.println(stu);
    35     }
    36     System.out.println("++++++++++++++++++++");
    37     Iterator<Student> iterator = list1.iterator();
    38     while (iterator.hasNext()) {
    39       System.out.println(iterator.next());
    40     }
    41   }
    42 }
    43 class Student{
    44     String name;
    45     int age;
    46     public Student(String name, int age) {
    47         super();
    48         this.name = name;
    49         this.age = age;
    50     }
    51     public int getAge() {
    52         return age;
    53     }
    54     public void setAge(int age) {
    55         this.age = age;
    56     }
    57     
    58 }
    View Code

    七、ArrayList和LinkedList总结: 

      1、ArrayList和LinkedList都是实现了List接口的容器类,用于存储一系列的对象引用。他们都可以对元素的增删改查进行操作。
      2、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
      3、对ArrayList和LinkedList的空间复杂度而言,对 ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Node对象。ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间 。
      4、对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。 ArrayList可以根据索引直接算出地址。
      5、在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
      6、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。对于查找和修改操作,如果按照索引查找和修改,ArrayList优于LinedList,如果按照内容来进行查找和修改,ArrayList和LinedList所花费的时间差不多。
      7、LinkedList不支持高效的随机元素访问。 比如二分查找就是才有的随机策略,就不适合采用LinkedList,适合ArrayList。
      可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中 间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。 所以,如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是对其它指定位置的插入、删除操作,最好选择LinkedList。

    注意:next 实际存的是下一个节点 个人重要理解。

  • 相关阅读:
    分享一个在线生成站点地图SiteMap制作工具
    去掉tppabs冗余代码,怎样批量去掉tppabs代码
    js文字无缝滚动
    史上最全的Win8快捷键大全
    原码, 反码, 补码
    Java [Leetcode 136]Single Number
    拉格朗日对偶
    随机森林与GBDT
    GBDT(Gradient Boosting Decision Tree)算法&协同过滤算法
    Java [Leetcode 165]Compare Version Numbers
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10372827.html
Copyright © 2020-2023  润新知