java版链表增删查改,插入,排序,反转,从左到右或从右到左遍历
演示代码:
package linklist;
public class Main {
public static void main(String[] args) {
LinkList<String> linkList = new LinkList<>();
linkList.add("a");
linkList.add("c");
linkList.add("b");
linkList.add(null);
linkList.add("e");
linkList.add("d");
linkList.add(null);
System.out.println(linkList.size());
System.out.println(linkList);
linkList.reverse();
System.out.println(linkList);
linkList.sort(String::compareTo);
System.out.println(linkList);
LinkList<Integer> linkList1 = LinkList.fromArray(4, 6, 6, 5, 9);
linkList1.sort(Integer::compareTo);
System.out.println(linkList1);
linkList1.reverse();
System.out.println(linkList1);
LinkList<String> linkList2 = LinkList.fromArray("a", "d", "b");
System.out.println(linkList2);
linkList2.insert(1, "c");
System.out.println(linkList2);
linkList2.insert(0, "e");
System.out.println(linkList2);
System.out.println(linkList2.get(1));
System.out.println(linkList2.set(1, "-"));
System.out.println(linkList2.get(1));
linkList2.remove(1);
System.out.println(linkList2);
linkList2.forEach(System.out::println);
System.out.println("------");
linkList2.forEachFromRight(System.out::println);
}
}
实现代码:
package linklist;
import com.sun.istack.internal.NotNull;
import java.util.Comparator;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class LinkList<T> {
public static class Node<T> {
T data;
Node prev;
Node next;
public Node() {
}
public Node(T data, Node prev, Node next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
private final int TO_STRING_MAX_COUNT = 1000;
private Node head = null;
private Node tail = null;
private long size;
public void add(T data) {
if(size == Long.MAX_VALUE) {
throw new OutOfMemoryError();
}
if (head == null) {
tail = head = new Node();
}
Node newNode = new Node(data, head, null);
tail.next = newNode;
newNode.prev = tail;
tail = newNode;
size = size + 1;
}
public void insert(long index, T data) {
if (index < 0) {
throw new IndexOutOfBoundsException(String.format("Size: %d, Index: %d", size, index));
}
if (index >= size) {
add(data);
return;
}
Node pre = head;
long i = 0;
while (i < index) {
pre = pre.next;
i = i + 1;
}
Node preNext = pre.next;
pre.next = new Node(data, pre, preNext);
preNext.prev = pre.next;
}
public T set(long index, T data) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(String.format("Size: %d, Index: %d", size, index));
}
Node<T> curent = head.next;
long i = 0;
while (i < index) {
curent = curent.next;
i = i + 1;
}
T old = curent.data;
curent.data = data;
return old;
}
public T get(long index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(String.format("Size: %d, Index: %d", size, index));
}
Node<T> curent = head.next;
long i = 0;
while (i < index) {
curent = curent.next;
i = i + 1;
}
return curent.data;
}
public boolean remove(long index) {
if (head == null) {
return false;
}
Node current = head.next;
long i = 0;
while (current != null) {
if (i == index) {
if (current == tail) {
tail = current.prev;
tail.next = null;
} else {
current.next.prev = current.prev;
current.prev.next = current.next;
}
current.prev = null;
current.next = null;
current.data = null;
--size;
return true;
}
current = current.next;
i = i + 1;
}
return false;
}
public boolean remove(T data) {
if (head == null) {
return false;
}
Node current = head.next;
while (current != null) {
if (Objects.equals(current.data, data)) {
if (current == tail) {
tail = current.prev;
tail.next = null;
} else {
current.next.prev = current.prev;
current.prev.next = current.next;
}
current.prev = null;
current.next = null;
current.data = null;
size = size - 1;
return true;
}
current = current.next;
}
return false;
}
public boolean find(T data) {
if (head == null) {
return false;
}
Node current = head.next;
while (current != null) {
if (Objects.equals(current.data, data)) {
return true;
}
current = current.next;
}
return false;
}
public void reverse() {
if (head == null) {
return;
}
Node temp = null;
Node current = head.next;
while (current != null) {
Node currentNext = current.next;
if (temp == null) {
temp = current;
temp.next = null;
tail = temp;
} else {
current.next = temp;
temp.prev = current;
temp = current;
}
current = currentNext;
}
head.next = temp;
}
public void sort(@NotNull Comparator<T> comparator) {
if (comparator == null) {
throw new NullPointerException("comparator for sort required not null");
}
if (size < 2) {
return;
}
Node<T> sorted = head.next;
Node<T> current = head.next.next;
sorted.next = null;
while (current != null) {
Node<T> currentNext = current.next;
Node<T> sortedCurrent = sorted;
Node<T> pre = head;
while (sortedCurrent != null) {
if (current == sortedCurrent) {
continue;
}
int cp;
if (sortedCurrent.data == null || current.data == null) {
if (sortedCurrent.data == null) {
cp = -1;
} else {
cp = 1;
}
} else {
cp = comparator.compare(current.data, sortedCurrent.data);
}
if (cp <= 0) {
pre.next = current;
current.prev = pre;
current.next = sortedCurrent;
sorted = head.next;
break;
} else if (sortedCurrent.next == null) {
sortedCurrent.next = current;
current.prev = sortedCurrent;
current.next = null;
break;
}
pre = sortedCurrent;
sortedCurrent = sortedCurrent.next;
}
current = currentNext;
}
}
public void forEach(Consumer<? super T> action) {
Node<T> current = head.next;
while (current != null) {
action.accept(current.data);
current = current.next;
}
}
public void forEachFromRight(Consumer<? super T> action) {
Node<T> current = tail;
while (current != head) {
action.accept(current.data);
current = current.prev;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (head == null) {
sb.append("[]");
} else {
boolean showAll = true;
long count = 0;
sb.append("[");
Node current = head.next;
while (current != null) {
if (current.data == null) {
sb.append("null, ");
} else {
sb.append(current.data.toString()).append(", ");
}
current = current.next;
if (++count == TO_STRING_MAX_COUNT) {
showAll = false;
break;
}
}
sb.delete(sb.length() - 2, sb.length());
if (!showAll) {
sb.append(", ...");
}
sb.append("]");
}
return sb.toString();
}
public long size() {
return size;
}
public static <T> LinkList<T> fromArray(T... arr) {
if (arr == null || arr.length == 0) {
return new LinkList<>();
}
LinkList<T> linkList = new LinkList<>();
Stream.of(arr).forEach(linkList::add);
return linkList;
}
}