勿以惡小而爲之,勿以善小而不爲--------------------------劉備
勸諸君,多行善事積福報,莫作惡
上一章簡單介紹了 Java實現複數(二十一),如果沒有看過,請觀看上一章
一. 自定義LinkedList
LinkedList 位於 java.util 包下, 內部封裝的是鏈接, 用於快速 添加,刪除元素,也支持查詢元素。
由於是內部封裝鏈表,數據結構需要多看一下。
LinkedList 的源碼非常好,建議多讀一下。
老蝴蝶簡單自定義一個 LinkedList, 實現相應的基礎功能。
一.一 自定義 MyLinkedList, 實現 LinkedList 功能
package com.yjl.collection;
/**
* package: com.yjl.collection
* className: MyLinkedList
* Description: 請輸入相應的描述
*
* @author : yuezl
* @Date :2020/6/11 11:35
*/
public class MyLinkedList<E>{
/*內部定義一個Node. 靜態的*/
private static class Node<E>{
/**
* @param previous 上一節點
* @param next 下一節點
* @param e 當前元素
*
*/
private Node<E> previous;
private Node<E> next;
private E e;
public Node(){
}
public Node(Node previous,E e,Node next){
this.previous=previous;
this.e=e;
this.next=next;
}
}
/*需要定義三個屬性, 根節點,尾節點,和長度size*/
/**
* @param first 根節點
* @param last 尾節點
* @param size 當前長度
*
* 如果沒有元素的話, first=last=null,
* 如果只有一個元素的話, first=last=唯一的那個元素值構成的Node
* 如果有兩個或者兩個以上的話, first指向第一個,last指向最後一個
*/
private Node<E> first;
private Node<E> last;
private int size;
/*定義構造方法*/
public MyLinkedList(){
}
public MyLinkedList(MyLinkedList<E> mll){
addAll(mll);
}
/*關於添加的相應操作*/
/**
* 添加 到最後
* @param e
* @return
*/
public boolean add(E e){
addLast(e);
return true;
}
/**
* 有索引的添加
* @param index
* @param e
* @return
*/
public boolean add(int index,E e){
//如果是最後一個,那麼就是追加
if(index==size){
addLast(e);
}else{
addBefore(e,getNodeByIndex(index));
}
return true;
}
public boolean addAll(MyLinkedList<E> mll){
addAll(size,mll);
return true;
}
public boolean addAll(int index,MyLinkedList<E> mll){
//轉換成數組,獲取裏面的元素。
Object[] obj=mll.toArray();
int length=obj.length;
if(length==0){
throw new NullPointerException("傳入的集合爲空");
}
//定義兩個對象,一個上一個對象,一個當前對象。
Node<E> pre,local;
//說明是後面插入的,或者調用 addll()方法的。
if(index==size){
pre=last;
//當前的爲空
local=null;
}else{
local=getNodeByIndex(index);
pre=local.previous;
}
for(int i=0;i<obj.length;i++){
//構建新對象
Node<E> node=new Node(pre,obj[i],null);
//判斷一下,是否是開頭插入
if(pre==null){
first=node;
}else{
//上一個的下一個爲node
pre.next=node;
}
//新的pre
pre=node;
}
//判斷一下,是否是末尾插入
if(local==null){
last=pre;
}else{
pre.next=local;
local.previous=pre;
}
size+=length;
return true;
}
/**
* 添加到第一個
* @param e
*/
public void addFirst(E e){
// 構建Node,記錄一下,以前的第一個。 以前的第一個,將會變成新Node 的next
Node<E> f=first;
Node<E> node=new Node(null,e,f);
first=node;
//看以前是否有內容,來判斷是否有下一個。
if(f==null){
//以前沒有值的話, last爲現在的node
last=node;
}else{
//設置 以前的previous 爲node, 以前previous爲null
f.previous=node;
}
size++;
}
/**
* 添加到最後一個
* @param e
*/
public void addLast(E e){
//先構建 Node,記錄一下,以前的最後一個。 以前的最後一個,將變成新的前。
Node<E> l=last;
//新Node
Node node=new Node(l,e,null);
//最後一個,last 指向新的 node
last=node;
//判斷一下 l, 由此確定一下 first
if(l==null){
//根節點爲 node.
first=node;
}else{
//以前的下一個爲 last, 以前是null
l.next=last;
}
size++;
}
/**
* 在以前的任意結點上添加元素,不適用末尾添加。
* @param e
* @param node
*/
private void addBefore(E e,Node<E> node){
//獲取該節點的上一個節點。 下一個接點,是不變的。
final Node prev=node.previous;
//構建新的Node 新結點的上一個結點爲prev,下一個接點爲當前結點。
Node newNode=new Node(prev,e,node);
//將上一個結點變成新結點。
node.previous=newNode;
if(prev==null){
first=newNode;
}else{
prev.next=newNode;
}
size++;
}
/**
* 放置元素, 放置在最前面
* @param e
*/
public void push(E e){
addFirst(e);
}
/**
* 移除元素, 移除第一個。
* @return
*/
public E pop(){
return unLinkFirst(first);
}
/** 移除的操作*/
/**
* 移除第一個
* @return
*/
public E remove(){
return removeFirst();
}
/**
* 移除固定索引的元素
* @param index
* @return
*/
public E remove(int index){
return unLink(getNodeByIndex(index));
}
/**
* 按照對象移除
* @param obj
* @return
*/
public E remove(Object obj){
int index=indexOf(obj);
if(index>=0){
return remove(index);
}
return null;
}
/**
* 移除第一個
* @return
*/
public E removeFirst(){
return unLinkFirst(first);
}
/**
* 移除最後一個
* @return
*/
public E removeLast(){
return unLinkLast(last);
}
/**
* 移除中間的元素
* @param node
* @return
*/
private E unLink(Node<E> node){
//獲取上一個,獲取下一個。 上一個和下一個,均是有值的。
Node<E> pre=node.previous;
Node<E> next=node.next;
E element=node.e;
node.e=null;
//前面爲空,說明只有一個元素
if(pre==null){
first=null;
}else{
pre.next=next;
//當前元素斷開
node.previous=null;
}
//最後一個時
if(next==null){
last=pre;
}else{
pre.next=next;
node.next=null;
}
size--;
return element;
}
/**
* 移除頭部
* @param node
* @return
*/
private E unLinkFirst(Node<E> node){
//獲取下一個元素
Node next=node.next;
E element=node.e;
//GC
node.e=null;
node.next=null;
//first 就指向下一個元素了
first=next;
if(next==null){
last=null;
}else{
//令下一個元素的上一個元素爲null,下一個元素不變
next.previous=null;
}
size--;
return element;
}
/**
* 移除最後一個
* @param node
* @return
*/
private E unLinkLast(Node<E> node){
//獲取前面的元素
Node pre=node.previous;
E element=node.e;
node.previous=null;
node.e=null;
last=pre;
//看是否是第一個
if(pre==null){
first=null;
}else{
pre.next=null;
}
size--;
return element;
}
/*設置和獲取*/
/**
* 獲取長度
* @return
*/
public int size(){
return size;
}
/**
* 判斷是否爲空
* @return
*/
public boolean isEmpty(){
return size==0?true:false;
}
/**
* 是否包含某個對象
* @param obj
* @return
*/
public boolean contains(Object obj){
return indexOf(obj)>=0?true:false;
}
/**
* 索引位置
* @param obj
* @return
*/
public int indexOf(Object obj){
int index=-1;
//對象爲null
if(obj==null){
for(Node<E> node=first;node!=null;){
index++;
if(node.e==obj){
return index;
}
node=node.next;
}
}else{
for(Node<E> node=first;node!=null;){
index++;
if(obj.equals(node.e)){
return index;
}
node=node.next;
}
}
return -1;
}
/**
* 倒序的索引位置
* @param obj
* @return
*/
public int lastIndexOf(Object obj){
int index=-1;
//對象爲null
if(obj==null){
for(Node<E> node=last;node!=null;){
index++;
if(node.e==obj){
return index;
}
node=node.previous;
}
}else{
for(Node<E> node=last;node!=null;){
index++;
if(obj.equals(node.e)){
return index;
}
node=node.previous;
}
}
return -1;
}
/**
* 設置值
* @param index
* @param e
* @return
*/
public E set(int index,E e){
Node old=getNodeByIndex(index);
old.e=e;
return (E)old.e;
}
/**
* 獲取值
* @param index
* @return
*/
public E get(int index){
Node node=getNodeByIndex(index);
return (E)node.e;
}
/**
* 得到頭部
* @return
*/
public E getFirst(){
if(first==null){
return null;
}
return first.e;
}
/**
* 得到尾部
* @return
*/
public E getLast(){
if(last==null){
return null;
}
return last.e;
}
/**
* 根據索引編號獲取相應的節點
* @param index
* @return
*/
private Node<E> getNodeByIndex(int index){
//判斷一下,當前的index 是在左半部分,還是在右半部分
if(index<=(size>>2)){
Node node=first;
for(int i=0;i<index;i++){
node=node.next;
}
return node;
}else{
Node node=last;
for(int i=size-1;i>index;i--){
node=last.previous;
}
return node;
}
}
/**
* 清空
*/
public void clear(){
//需要將以前的那些鏈接清空,方便GC 收集
for(Node<E> node=first;node!=null;){
Node<E> next=node.next;
node.previous=null;
node.e=null;
node.next=null;
node=next;
}
first=null;
last=null;
size=0;
//
}
/**
* 轉換成數組
* @return
*/
public Object[] toArray(){
Object[] result=new Object[size];
int i=0;
for(Node<E>node=first;node!=null;node=node.next){
result[i++]=node.e;
}
return result;
}
/**
* 打印輸出
* @return
*/
public String toString(){
if(size==0){
return "[]";
}
StringBuilder sb=new StringBuilder();
sb.append("[");
for(Node<E> node=first;node!=null;node=node.next){
String temp= node.e.toString();
sb.append(temp+",");
}
sb.replace(sb.length()-1,sb.length(),"]");
return sb.toString();
}
}
一.二 測試自定義 MyLinkedList
package com.yjl.collection;
/**
* package: com.yjl.collection
* className: MyLinkedListTest
* Description: 請輸入相應的描述
*
* @author : yuezl
* @Date :2020/6/11 15:18
*/
public class MyLinkedListTest {
public static void main(String[] args) {
MyLinkedList<Integer> mal = new MyLinkedList<Integer>();
System.out.println("長度:" + mal.size() + ",是否爲空:" + mal.isEmpty());
//添加元素
mal.add(3);
mal.add(4);
//索引時添加
mal.add(0, 1);
mal.addFirst(0);
mal.addLast(100);
//打印
System.out.println("mal:" + mal.toString());
//集合構建
MyLinkedList<Integer> mal2 = new MyLinkedList<Integer>(mal);
System.out.println("mal2:" + mal2.toString());
//添加所有
mal2.addAll(mal);
System.out.println("新的mal2:" + mal2.toString());
//獲取值
Integer val = mal2.get(3);
System.out.println("輸出值爲:" + val);
//索引長度構造
MyLinkedList<Integer> mal3=new MyLinkedList<Integer>();
mal3.add(1);
mal3.add(2);
System.out.println("是否包含2:"+mal3.contains(2));
System.out.println("長度1:"+mal3.toArray().length);
//清除
mal3.clear();
System.out.println("長度:"+mal3.size()+",是否爲空:"+mal3.isEmpty());
}
}
控制檯打印輸出:
謝謝您的觀看,如果喜歡,請關注我,再次感謝 !!!