As the Spring Festival approaches, the project is over and we are all waiting to go home for the New Year. Below is the relevant knowledge of the editor studying data structure for you. The linked list is a data structure that is often used. Now I will show my own implementation as follows. Welcome to the great master for advice.
The first version has no last node, and it starts traversing from the root node every time
public class LinkedList<E> {private Node head;public LinkedList() {}public E getFirst(){if(head==null){return null;}return head.value;}public LinkedList<E> addFirst(E e){head.pre=new Node(e, null, head);head=head.pre;return this;}public LinkedList<E> addNode(E e){Node lst=head;if(lst==null){this.head=new Node(e, null, null);return this;}else{while(true){if(lst.next==null){break;}else{lst=lst.next;}}lst.next=new Node(e, lst, null);return this;}}public LinkedList<E> remove(E e){Node lst=head;if(lst==null){throw new NullPointerException("the LinkedList is empty.");}else{while(true){if(e.equals(lst.value)){//Remove this element if(lst.pre!=null){lst.pre.next=lst.next;}if(lst.next!=null){lst.next.pre=lst.pre;}lst=null;break;}lst=lst.next;}return this;}}@Overridepublic String toString() {StringBuffer buff=new StringBuffer("[");Node lst=this.head;while(lst!=null){buff.append(lst.value+",");lst=lst.next;}return buff.substring(0, buff.length()-1)+"]";}/**Node information*/private class Node{public Node pre;public E value;public Node next;public Node(E value,Node pre,Node next) {this.value=value;this.pre=pre;this.next=next;}} }The second version has the last node
public class LinkedList<E> {private Node head;private Node last;public LinkedList() {}public E getFirst(){if(head==null){return null;}return head.value;}public E getLast(){if(last==null){return null;}return last.value;}public LinkedList<E> addFirst(E e){head.pre=new Node(e, null, head);head=head.pre;return this;}public LinkedList<E> addNode(E e){Node lst=last;if(lst==null){//If the last node is empty, this link list is empty this.last=new Node(e, null, null); this.head=this.last;return this;}else{while(true){if(lst.next==null){//break;}else{lst=lst.next;}}lst.next=new Node(e, lst, null);last=lst.next;return this;}}public LinkedList<E> remove(E e){Node lst=head;if(lst==null){throw new NullPointerException("the LinkedList is empty.");}else{while(true){if(e.equals(lst.value)){//Remove this element if(lst.pre!=null){lst.pre.next=lst.next;}if(lst.next!=null){lst.next.pre=lst.pre;}lst=null;break;}lst=lst.next;}return this;}}@Overridepublic String toString() {StringBuffer buff=new StringBuffer("[");Node lst=this.head;while(lst!=null){buff.append(lst.value+",");lst=lst.next;}return buff.substring(0, buff.length()-1)+"]";}/**Node information*/private class Node{public Node pre;public E value;public Node next;public Node(E value,Node pre,Node next) {this.value=value;this.pre=pre;this.next=next;}}}Note: Neither of the above two versions considers the use under multithreading.
The above is the relevant knowledge about implementing bidirectional linked lists (two versions) introduced to you by the editor. I hope it will be helpful to you.