自定义(单链表)集合类

类的结构

 

 

接口:MyList

 1 package day2_19.inter;
 2 
 3 /**
 4  * 将arryList 和 linkedList 共性的方法进行抽取 --->保证体系的完整性
 5  *
 6  * @Author Tianhao
 7  * @create 2021-02-19-17:26
 8  */
 9 
10 public interface MyList<E>{
11 
12 
13     public int size();
14 
15 
16     public boolean isEmpty();
17 
18 
19     public boolean contains(Object o);
20 
21 
22     public boolean add(E e);
23 
24     public void add(int index, E element);
25 
26     public E remove(int index);
27 
28     public E get(int index);
29 
30 
31     public E set(int index, E element);
32 
33 
34     public int indexOf(Object o);
35 
36     public void clear();
37 
38     String toString();
39 
40 
41 //    public boolean remove(Object o);
42 
43 
44 //    public Iterator<E> iterator();
45 
46 
47 //    public Object[] toArray();
48 
49 
50 //    public <T> T[] toArray(T[] a);
51 
52 
53 //    public boolean containsAll(Collection<?> c);
54 //
55 //
56 //    public boolean addAll(Collection<? extends E> c);
57 //
58 //
59 //    public boolean addAll(int index, Collection<? extends E> c) ;
60 //
61 //
62 //    public boolean removeAll(Collection<?> c);
63 //
64 //
65 //    public boolean retainAll(Collection<?> c);
66 
67 
68 //    public int lastIndexOf(Object o);
69 //
70 //
71 //    public ListIterator<E> listIterator();
72 //
73 //
74 //    public ListIterator<E> listIterator(int index);
75 //
76 //
77 //    public List<E> subList(int fromIndex, int toIndex);
78 
79 }

抽象类:MyAbstractList

 1 package day2_19.abstractClass;
 2 
 3 import day2_19.inter.MyList;
 4 
 5 /**
 6  *
 7  * 用于实现arryList 和 linkedList中那些相同的方法
 8  *
 9  * @Author Tianhao
10  * @create 2021-02-19-17:46
11  */
12 
13 public abstract class MyAbstractList<E> implements MyList<E> {
14     protected int size;
15 
16     /**
17      * 获取元素个数
18      * @return 元素个数
19      */
20     @Override
21     public int size() {
22         return size;
23     }
24 
25     /**
26      * 判断集合是否为空
27      * @return
28      */
29     @Override
30     public boolean isEmpty() {
31         return size == 0;
32     }
33 
34     /**
35      * 判断集合是否包含指定元素
36      * indexOf(Object o):寻找对应的元素,如果找到了返回元素的索引,如果没有找到返回 -1
37      * @param o
38      * @return
39      */
40     @Override
41     public boolean contains(Object o) {
42         return indexOf(o) != -1;
43     }
44 
45 
46     /**
47      * 在集合的最后添加一个元素,也就是在索引为size处添加一个元素
48      * @param e
49      * @return
50      */
51     @Override
52     public boolean add(E e) {
53         add(size,e);
54         return true;
55     }
56 }

自定义(单链表)集合类:

  1 package day2_19.linked;
  2 
  3 import day2_19.abstractClass.MyAbstractList;
  4 
  5 /**
  6  * 
  7  * 自定义(单链表)集合类
  8  *
  9  * @Author Tianhao
 10  * @create 2021-02-19-18:01
 11  */
 12 public class MyLinkedList<E> extends MyAbstractList<E> {
 13 
 14     private Node<E> first;
 15 
 16     private static class Node<E>{
 17         E element;
 18         Node<E> next;
 19         Node(E element,Node<E> next){
 20             this.element = element;
 21             this.next = next;
 22         }
 23     }
 24 
 25 
 26 
 27     /**
 28      * 在指定索引index处插入指定元素
 29      * @param index 注意:index >= 0 && index <= size (是可以插入到最后一个元素的下一个位置的)
 30      * @param element
 31      */
 32     @Override
 33     public void add(int index, E element) {
 34         checkPositionIndex(index);//判断index >=0 && index <= size
 35         if (index == 0) {//这里不管first是否为null,都是没有问题的
 36             //如果最开始的first为null,则插入的节点为node(element,null),被first指向
 37             //如果最开始的first不为null,则插入的节点为node(element,first),除了被first指向,它还指向最开始的那个first
 38             first = new Node(element, first);
 39         } else {//插入位置索引不是0
 40             Node<E> pre = node(index - 1);//前一个节点
 41             Node<E> next = pre.next;//后一个节点
 42             pre.next = new Node(element,next);//前一个节点指向插入的节点,这个插入的节点指向后一个节点
 43         }
 44         size++;
 45     }
 46 
 47 
 48     private void checkPositionIndex(int index) {
 49         if (!isPositionIndex(index)) {
 50             throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
 51         }
 52     }
 53 
 54     private boolean isPositionIndex(int index) {
 55         return index >= 0 && index <= size;
 56     }
 57 
 58     /**
 59      * 移除集合中指定索引的元素,并返回这个元素
 60      * @param index
 61      * @return
 62      */
 63     @Override
 64     public E remove(int index) {
 65         checkElementIndex(index);
 66         Node<E> oldNode;
 67         if (index==0) {
 68             oldNode = first;
 69             first = first.next;
 70             size--;
 71             return oldNode.element;
 72         }
 73         //先从一般的规律入手,写下来,再看特殊情况,
 74         //如果index=0,那么index-1就为负数,肯定是不行的,所以才有上面if (index==0) 的情况
 75         Node<E> pre = node(index - 1);
 76         oldNode = pre.next;
 77         pre.next = oldNode.next;
 78         size--;
 79         return oldNode.element;
 80     }
 81 
 82     /**
 83      * 获取指定索引(节点)处的元素
 84      * 因为增删改都是基于先找到元素,所以这个方法最先实现比较好
 85      * @param index
 86      * @return
 87      */
 88     @Override
 89     public E get(int index) {
 90         checkElementIndex(index);
 91         return node(index).element;
 92 
 93     }
 94 
 95     /**
 96      * 检查指定索引,如果集合中不存在这个指定索引,则抛出异常
 97      * @param index
 98      */
 99     private void checkElementIndex(int index) {
100         if (!isElementIndex(index)) {
101             throw new IndexOutOfBoundsException("Index: " + index + ",Size: " + size);
102         }
103     }
104 
105     /**
106      * 找到指定索引index对应的Node节点
107      * @param index
108      * @return
109      */
110     private Node<E> node(int index) {
111         //获取集合第一个元素first
112         Node<E> x = first;
113         //通过x.next,循环遍历找到指定索引index对应的Node节点
114         for (int i = 0; i < index; i++) {
115             x = x.next;
116         }
117         return x;
118     }
119 
120     /**
121      * 判断集合中是否存在指定索引
122      * @param index
123      * @return
124      */
125     private boolean isElementIndex(int index) {
126         return index >= 0 && index < size;
127     }
128 
129 
130     /**
131      * 将指定索引处的元素替换为指定的元素
132      * @param index 指定的索引
133      * @param element 将要替换到指定索引处的元素
134      * @return 返回指定索引处被替换的元素
135      */
136     @Override
137     public E set(int index, E element) {
138         checkElementIndex(index);
139         Node<E> node = node(index);
140         E oldEle = node.element;
141         node.element = element;
142         return oldEle;
143     }
144 
145     /**
146      * 查找第一次出现指定元素o的索引位置
147      * @param o
148      * @return 如果有,返回o在集合中的索引;如果没有,返回-1
149      */
150     @Override
151     public int indexOf(Object o) {
152         int index = 0;
153         if (o == null) {
154             //多去理解这种遍历思维
155             for (Node<E> x = first; x != null; x = x.next) {
156                 if (x.element == o) {
157                     return index;
158                 }
159                 //还有这种返回索引的思维也要多学习
160                 index++;
161             }
162         } else {
163             for (Node<E> x = first; x != null; x = x.next) {
164                 if (o.equals(x.element)) {
165                     return index;
166                 }
167                 index++;
168             }
169         }
170         return -1;
171     }
172 
173     /**
174      * 清空集合的所有元素
175      *
176      * 可达性算法:判断对象是否是一个垃圾的标准
177      *  选取一个节点,作为GC ROOTS顶点,其他对象或者引用去指向这个GC ROOTS顶点,如果这些对象
178      *  能够到达这个GC ROOTS顶点,那么这些对象不是垃圾,反之就是。
179      *
180      */
181     @Override
182     public void clear() {
183         size = 0;
184         first = null;
185     }
186 
187     @Override
188     public String toString() {
189         if (size == 0) {
190             return "[]";
191         }
192         StringBuilder sb= new StringBuilder();
193         sb.append('[');
194         for( Node<E> x = first;x!=null;x=x.next){
195             sb.append(x.element);
196             if (x.next == null) {
197                 return sb.append(']').toString();
198             }
199             sb.append(',').append(' ');
200         }
201         return sb.toString();
202     }
203 }

 

posted @ 2021-02-20 18:55  dog_IT  阅读(99)  评论(0编辑  收藏  举报