基于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 实际存的是下一个节点 个人重要理解。

 

转载于:https://www.cnblogs.com/xiaoyh/p/10372827.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值