Day10-Java
文章目錄
- Day10-Java
- 1、例外的捕獲與處理
- 1.1 處理例外
- 1.2 例外處理的流程
- 1.3 throw關鍵字
- 1.4 例外處理模型
- 1.5 RuntimeException
- 1.6 斷言:assert
- 1.7 自定義例外
- 2、鏈表
- 2.1 鏈表基本的結構
- 2.2 鏈表實作結構說明
- 2.3 增加鏈表資料—public void add(資料)
- 2.4 增加多個資料—public void addAll(資料陣列)
- 2.5 統計資料個數—public int size()
- 2.6 鏈表資料轉換為物件陣列—public Object[] toArray()
- 2.7 鏈表查詢資料—public boolean contains(查找物件)
- 2.8 根據索引取得資料—public Object get(int index)
- 2.9 修改指定索引資料—public void set(int index,Object newData)
- 2.10 洗掉資料—public void remove(資料)
- Link鏈表類模板
- 綜合案例
1、例外的捕獲與處理
例外時導致程式中斷執行的一種指令流,程式出現例外沒用合理處理,就會導致程式終止執行,
觀察沒有例外產生的程式
public class TestDemo1{
public static void main(String args[]){
System.out.println("1、除法程式開始");
int result =10/2;
System.out.println("2、除法程式結果:"+result);
System.out.println("3、除法程式結束");
}
}
/*
1、除法程式開始
2、除法程式結果:5
3、除法程式結束
*/
產生例外的程式
public class YiChang{
public static void main(String args[]){
System.out.println("1,除法程式開始");
int result =10/0;//會出現錯誤
System.out.println("2,除法程式結果:"+result);
System.out.println("3,除法程式結束");
}
}
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
at YiChang.main(YiChang.java:5)
*/
這個時候程式出現了錯誤,那么出現錯誤之后程式不執行了,而是直接進行了錯誤資訊的輸出,并且直接結束了程式,但是,出現了錯誤,應該去處理才對,但是現在沒有處理,
1.1 處理例外
現在,如果希望程式出現了例外之后,程式依然可以正常的完成的話,那么就可以使用如下的格式進行例外的處理;
try{
可能出現例外的陳述句
}[catch(例外型別 例外物件){
處理例外;
}catch(例外型別 例外物件){
處理例外;
}…][finally{
例外統一出口
不管是否出現例外,都執行此代碼;
}]
使用該操作進行例外的處理
public class TestDemo1{
public static void main(String args[]){
System.out.println("1、除法程式開始");
try{
int result =10/0;
System.out.println("2、除法程式結果:"+result);
}catch(ArithmeticException e){
System.out.println("例外被正確的處理了");
}
System.out.println("3、除法程式結束");
}
}
/*
1、除法程式開始
例外被正確的處理了
3、除法程式結束
*/
可以發現加入了例外處理之后,程式之中即使有了例外,程式也可以正常執行完畢,但是現在發現,例外處理時的錯誤輸出資訊和之前相比,出錯的資訊不明確了,那么為了讓錯誤的資訊更加完整,一般而言,都會呼叫printStackTrace()方法進行例外資訊的列印
這個方法(printStackTrace)列印的例外資訊是最完整的:
try{
int x = 10/0; //例外
System.out.println("2,除法程式結果:"+x);
}catch(ArithmeticException e){
e.printStackTrace();
}
try catch finallly 操作
public class TestDemo1{
public static void main(String args[]){
System.out.println("1,除法程式開始");
try{
int x = 10/0; //例外
System.out.println("2,除法程式結果:"+x);
}catch(ArithmeticException e){
e.printStackTrace();
}finally{
System.out.println("不管是否例外都會執行");
}
System.out.println("3,除法程式結束");
}
}
但是,對于之前的程式現在又有了問題:現在執行數學計算的兩個引數,都是由程式默認提供,那么如果說現在兩個計算的引數通過初始化引數傳遞呢?
public class TestDemo2{
public static void main(String args[]){
System.out.println("1,除法程式開始");
try{
int x = Integer.parseInt(args[0]); //接收引數
int y = Integer.parseInt(args[1]); //接收引數
int result = x/y;
System.out.println("2,除法程式結果:"+result);
}catch(ArithmeticException e){
e.printStackTrace();
}finally{
System.out.println("不管是否例外都會執行");
}
System.out.println("3,除法程式結束");
}
}
時候發現,資料由外部傳送,那么在這種情況下,就有可能出現一下幾類問題:
? 執行時不輸入引數,ArrayIndexOutOfBoundsException,未處理,
? 輸入的引數不是數字,NumberFormatException,未處理,
? 被除數為0,ArithmeticException,已處理,
可以發現,以上的程式實際上是存在三種例外,而程式之中只能處理一種,而對于不能處理的例外,發現程式依然會直接中斷執行,
public class TestDemo2{
public static void main(String args[]){
System.out.println("1,除法程式開始");
try{
int x = Integer.parseInt(args[0]); //接收引數
int y = Integer.parseInt(args[1]); //接收引數
int result = x/y;
System.out.println("2,除法程式結果:"+result);
}catch(ArithmeticException e){
e.printStackTrace();
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}catch(NumberFormatException e){
e.printStackTrace();
}finally{
System.out.println("不管是否例外都會執行");
}
System.out.println("3,除法程式結束");
}
}
此時,問題就來了,如果按照以上的方式一次一次的測驗來進行例外型別的推斷,還不如直接撰寫if…else,
1.2 例外處理的流程
以上已經完成了例外的基本處理流程,但是也可以發現問題,所有的例外都像之前那樣一條條的判斷似乎是一件不可能完成的任務,因為以后肯定會接觸到一些不常見的例外資訊,那么下面就必須首先研究例外的流程和結構,
首先查看兩個例外的繼承結構
ArithmeticException
java.lang.Object
java.lang.Throwable
java.lang.Exception java.lang.RuntimeException
java.lang.ArithmeticException
ArrayIndexOutOfBoundsException
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
可以發現所有的例外型別最高的繼承類是Throwable,通過doc檔案可以發現Throwable下有兩個子類:
? Error:指的是JVM錯誤,這個時候的程式并沒有執行,無法處理;
? Exception:指的是程式之中出現了錯誤資訊,可以進行例外處理,主要關心Exception,
? 那么通過繼承關系可以發現,肯定在進行日常處理的時候是以Exception為主,而這個時候就可以形成以下的例外處理流程,
1.3 throw關鍵字
throws關鍵字主要是在方法定義上使用的,表示的是此方法之中不進行例外處理,而交給被呼叫處處理,
class MyMath{
//現在的div()方法之中拋了一個例外出來,表示的是,所有的例外交給被呼叫處進行處理,
public int div(int x,int y) throws Exception{
return x/y;
}
}
public class TestDemo3{
public static void main(String args[]){
try{
System.out.println(new MyMath().div(10,0));
}catch(Exception e){
e.printStackTrace();
}
}
}
在呼叫throws宣告方法的時候,一定要使用例外處理操作進行例外的處理,這是是屬于強制性的處理,而現在主方法本身也屬于方法,那么實際上在主方法上也可以繼續使用throws進行例外的拋出,
class MyMath{
//現在的div()方法之中拋了一個例外出來,表示的是,所有的例外交給被呼叫處進行處理,
public int div(int x,int y) throws Exception{
return x/y;
}
}
public class TestDemo3{
public static void main(String args[]) throws Exception{
try{
System.out.println(new MyMath().div(10,0));
}catch(Exception e){
e.printStackTrace();
}
}
}
這個時候表示的是將例外繼續向上拋,交給JVM進行例外的處理,
請解釋throw和throws區別?
- throw用于方法內部表示進行手工的拋出
- throws主要用于方法宣告上使用,明確的告訴本方法可能產生的例外,同時該方法可能不處理例外,
1.4 例外處理模型
現在覺得有兩個內容實在沒用finally,throw,
現在要求定義一個div()方法,而這個方法有如下一些要求:
? 在進行除法操作之前,輸出一行提示資訊,
? 在除法操作執行完畢后,輸出一行提示資訊,
? 如果中間產生了例外,則應該交給被呼叫處來進行處理,
class MyMath{
public static int div(int x, int y) throws Exception{
int result = 0;
//不寫catch陳述句的執行流程
//首先進行try代碼塊的執行后執行finally代碼塊執行完成后執行
//throws進行例外捕獲,捕獲完成后再主方法catch陳述句中進行執行
try{
System.out.println("before進行除法計算");
result = x / y;
}finally{
System.out.println("after進行除法計算");
}
return result;
}
}
public class TestDemo4{
public static void main(String args[]){
try{
System.out.println(MyMath.div(10,0));
}catch(Exception e){
e.printStackTrace();
}
}
}
1.5 RuntimeException
public class TestDemo4{
public static void main(String args[]){
String str = "123";
int num = Integer.parseInt(str);
System.out.println(num*num);
}
}
這個方法就是將一個字串變為了基本資料型別,而后執行乘法操作,但是下面來看一下parseInt()方法的定義:
Public static int parseInt(String s) throws NumberFomatException
發現這個方法上拋出了一個NumberFomatException的例外,按照之前所講,如果存在了throw,則必須使用try….catch進行處理,可是現在去沒有強制要求處理,來觀察一下NumberFomatException的繼承結構,
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IllegalArgumentException
java.lang.NumberFormatException
發現NumberFormatException屬于RuntimeException的子類,而在Java之中明確規定了,對于RuntimeException的例外型別可以有選擇型的來進行處理,在開發之中,如果,沒有處理,那么出現例外之后將交給JVM默認進行處理,
Exception和RuntimeException的區別?請你舉出常見的RuntimeException?
-
Exception是RuntimeException的父類,使用Exception定義的例外必須使用例外處理
-
RuntimeException可以由用戶選擇性的例外處理
-
常見的Exception:NumberFormatException,ClassCastException,NullPointException,ArithmeticException,ArrayIndexOutBoundException,
1.6 斷言:assert
斷言指的是程式執行到某行之后,其結果一定是預期的結果,而在JDK1.4之后增加了一個assert關鍵字,
public class DuanYan{ public static void main(String args[]){ int x = 10; //假設經過了很多操作 assert x == 30:"x的內容不是三十"; System.out.println(x); }}
默認情況下,Java之中的斷言不會在正常執行的代碼中出現,如果想要啟用斷言,則應該早呢更加一些選項,
1.7 自定義例外
在Java之中本省已經提供了大量的例外型別,但是在開發之中,這些例外型別根本就不能滿足開發的需要,所以在一些系統架構之中往往會提供一些新的例外型別,來表示一些特殊的錯誤,而這種操作就稱為自定義例外類,而要想實作這種自定義例外類,那么可以讓一個類繼承Exception或RuntimeException,
class MyException extends Exception{ public MyException(String str){ super(str); }}public class TestDemo5{ public static void main(String args[]) throws Exception{ throw new MyException("自己的例外類"); }}
如果以后見到了一些沒見過的例外型別,那么基本都是自定義的例外類,
2、鏈表
鏈表是一種基本的資料結構,但好似對于資料結構的部分,強調一下幾點:
- 在整個Java開發領域之中,沒有一本書去真正講解資料結構的書,只能去看C語言的資料結構:
- 在所有開發之中,都會存在資料結構的身影,可以這樣去解釋:資料結構的精通與否,完全域定于以后,
- 資料結構的核心:參考資料型別操作,
鏈表實際上可以理解為遺傳資料,或者按照專業性的說法,可以理解為動態的物件陣列,物件陣列的最大優點:是表示“多”的概念,例如:多個雇員,但是傳統的物件陣列有一個最大的問題在于,里面保存的資料長度是固定的,思考:如果現在想要擴大一個物件陣列的范圍?
建立一個新的物件陣列,而后將原本的內容拷貝到新的陣列之中,再改變原陣列的參考方式,
public class TestLinkDemo{
public static void main(String args[]){
Object ob[] = new Object [3];
}
}
但是再實際的開發之中,要面臨的一個問題是:陣列是一個定長的線性結構,也就是說雖然以上代碼可以滿足于存放多個內容,但是一旦我們呢的內容不足或者是內容過多,可能會導致資源的浪費,要想解決此類問題最好的做法就是不定義一個固定長度的陣列 ,有多少資料就保存多少資料,
2.1 鏈表基本的結構
class Node{//因為只有Node類才可以在保存資料的同時設定資料
private Object data;//真正要保存的資料
private Node next;//定義下一個節點
public Node(Object data){
this.data = data;
}
public void setData(Object data){
this.data = data;
}
public Object getData(){
return this.data;
}
public void setNext(Node next){
this.next = next;
}
public Node getNext(){
return this.next;
}
}
public class TestLinkDemo{
public static void main(String args[]){
//1.封裝幾個節點
Node root = new Node("火車頭");
Node n1 = new Node("車廂1");
Node n2 = new Node("車廂2");
Node n3 = new Node("車廂3");
//2.設定節點關系
root.setNext(n1);
n1.setNext(n2);
n2.setNext(n3);
//3.輸出鏈表
print(root);
}
public static void print(Node node){
if(node != null){//表示當前是有節點的
System.out.println(node.getData());
print(node.getNext());//繼續向下取出
}
}
}
在整個鏈表的實作程序中,Node類的作用:保存資料和保存下一個節點,但是我們發現客戶端需要自己來進行節點的創建操作以及關系的配置,所謂的鏈表就是需要有一個單獨的類,假設叫Link,通過Link類來實作Node的資料保存和關系處理,
2.2 鏈表實作結構說明
通過之前的分析,可以發現鏈表的最大作用類就是Node,但是以上程式都是由用戶自己去匹配節點關系的,但是這些節點的匹配作業不應該由用戶完成,應該由一個程式專門去負責,
那么專門負責幾點操作的類,就成為鏈表類——Link,負責處理幾點關系,而用戶不用關心節點的問題,只需關心Link的處理操作即可,

真實開發——標準程序

class Link{//負責對鏈表的操作
//將Node定義內部類,表示Node類只能為Link類提供服務
private class Node{//負責資料與節點的關系匹配
private Object data;//真正要保存的資料
private Node next;//定義下一個節點
public Node(Object data){
this.data = data;
}
public void setData(Object data){
this.data = data;
}
public Object getData(){
return this.data;
}
}
//以下為Link類
}
public class TestLinkDemo{
public static void main(String args[]){
}
}
2.3 增加鏈表資料—public void add(資料)
通過上面程式的分析,可以發下,對于鏈表的實作,Node類是整個操作的關鍵,但是首先來研究一下之前程式的問題:Node是一個單獨的類是可以被用戶直接使用的,但是這個類由用戶直接去使用,沒有任何意義,即:這個類有用,但不能讓用戶去使用,讓Link類去使用,
class Link{//負責對鏈表的操作
//將Node定義內部類,表示Node類只能為Link類提供服務
private class Node{//負責資料與節點的關系匹配
private Object data;//真正要保存的資料
private Node next;//定義下一個節點
public Node(Object data){
this.data = data;
}
public void setData(Object data){
this.data = data;
}
public Object getData(){
return this.data;
}
public void setNext(Node next){
this.next = next;
}
public Node getNext(){
return this.next;
}
//第一次呼叫:this = Link.root
//第二次呼叫:this = Link.root.next
//第三次呼叫:this = Link.root.next.next
public void addNode(Node newNode){//處理節點關系
if(this.next == null){ //當前節點下一個為空
this.next = newNode;
}else{//當前節點的下一個不為空
this.next.addNode(newNode);
}
}
public void nodePrint(){
System.out.println(this.getData());
if (this.getNext()==null)
{
return;
}else{
this.getNext().nodePrint();
}
}
}
//以下為Link類------------------------------------------------
private Node root; //屬于根節點,沒有根節點就無法資料的保存
//增加資料
public void add(Object data){
if(data == null){//人為追加規定,不允許存放null值
return ;//結束方法呼叫
}
//如果要想進行資料的保存,那么必須將資料封裝在Node類里面
//如果沒有封裝,則無法確認好節點的先后順序
Node newNode = new Node(data);
if(this.root == null){
this.root = newNode;//第一個節點設定為根節點
}else{//根節點存在了
this.root.addNode(newNode);
}
}
//輸出資料
public void print(){
if (this.root == null){
return;
}
System.out.println(this.root.getData());
if (this.root.getNext()==null){
return;
}
else{
this.root.getNext().nodePrint();
}
}
}
public class TestLinkDemo1{
public static void main(String args[]){
Link link = new Link();
link.add("Hello");
link.add("World");
link.print();
}
}
2.4 增加多個資料—public void addAll(資料陣列)
public void addAll(String date[]){
for(int x = 0;x<date.length;x++){
this.add(date[x]);
}
}
2.5 統計資料個數—public int size()
在Link類中定義
private int count;//統計個數
在增加資料的最后一行添加count++
public void add(Object data){
if(data == null){//人為追加規定,不允許存放null值
return ;//結束方法呼叫
}
//如果要想進行資料的保存,那么必須將資料封裝在Node類里面
//如果沒有封裝,則無法確認好節點的先后順序
Node newNode = new Node(data);
if(this.root == null){
this.root = newNode;//第一個節點設定為根節點
}else{//根節點存在了
this.root.addNode(newNode);
}
count++;
}
2.6 鏈表資料轉換為物件陣列—public Object[] toArray()
對于鏈表的這種資料結構,最為關鍵的是兩個操作:洗掉和取得全部資料,
在Link類中定義一個操作陣列的腳標:
private int foot = 0;
要把資料保存的陣列,Link類和Node類都需要使用,那么可以在Link類中定義回傳陣列,必須以屬性的形式出現,只有這樣,Node類才可以訪問這個陣列并進行操作,
private Object [] retData ; //回傳型別
在Link類中增加toArray()方法:
//鏈表資料轉換為物件陣列
public Object[] toArray(){
if(this.count == 0){
return null;
}
this.retData = new Object[this.count];
this.root.toArrayNode();
this.foot = 0;//下表清零操作
return this.retData;
}
在Node中增加toArrayNode()方法:
public void toArrayNode(){
Link.this.retData[Link.this.foot++] = this.data;
if(this.next != null){
this.next.toArrayNode();
}
}
不過按照以上的方式進行開發,每一次呼叫toArray()方法,都要重復的進行資料的的遍歷,如果在資料沒有修改的情況下,這種做法是一種低效的做法,最好的方法是增加一個修改標記,如果發現資料增加了或洗掉的話,表示要重新遍歷資料,

2.7 鏈表查詢資料—public boolean contains(查找物件)
現在如果想查詢某個資料是否存在,那么基本的操作原理:逐個盤查,盤查的具體物件應該交給Node去完成,前提是:有資料存在,
在Link類之中,增加查詢操作:
//查找鏈表的指定資料是否存在
public boolean contains(Object search){
if(search == null && this.root == null)
return false;
return this.root.containsNode(search);
}
在Node類中,完成具體查詢,查詢流程為:
? 判斷當前節點的內容是否滿足于查詢內容,如果滿足回傳ture;
? 如果當前節點內容不滿足,則向后繼續查詢,如果沒有后續節點了,則回傳false,
public boolean containsNode(Object search){
if(search.equals(this.data))
return true;
else{
if(this.next != null){//判斷下一個節點是否為空
return this.next.containsNode(search);
}
return false;
}
}
2.8 根據索引取得資料—public Object get(int index)
在一個鏈表之中會有多個節點保存資料,現在要求可以取得指定節點的資料,但是在進行這一操作的程序之中,有一個小問題:如果要取得資料的索引超過了資料的保存個數,那么是無法取得的,
? 在Link類之中增加一個get(int index)方法:
//根據索引取得資料
public Object get(int index){
if(index >= this.count){
return null;
}
this.foot = 0;
return this.root.getNode(index);
}
在Node類之中增加一個getNdoe(int index)方法:
//第一次this == Link.root
//第二次this == Link.root.next
public Object getNode(int index){
if(Link.this.foot++ == index){
return this.data;
}else{
return this.next.getNode(index);
}
}
2.9 修改指定索引資料—public void set(int index,Object newData)
如果修改資料只需要進行資料的替換,
在Link類之中增加一個set(int index,Object newData)方法:
//修改指定索引資料
public void set(int index,Object newData){
if(index >= this.count){
return ;
}
this.foot = 0;
this.root.setNode(index,newData);
}
在Node類之中增加一個getNode(int index)方法:
public void setNode(int index, Object newData){
if(Link.this.foot ++ == index){//索引相同
this.data = newData;
}else{
if(this.next != null){
this.next.setNode(index,newData);
}
}
}
2.10 洗掉資料—public void remove(資料)
對于鏈表之中的內容,之前完成的是增加操作和查詢操作,但是從鏈表之中也會存在洗掉資料的操作,可是洗掉資料的操作要分為兩種情況討論:
? 情況一:洗掉的資料不是根節點,待刪節點的上一個next指向待刪節點的next,
? 所有的處理操作應該交給Node進行處理,
? 情況二:洗掉的資料是根節點,下一個節點保存為跟節點,
? 如果洗掉的是根節點,意味著Link中的根節點的保存需要發生變化,該操作主要在Link中處理,

在Link中增加一個洗掉remove(Object data)方法
//洗掉資料
public void remove(Object data){
if(this.contains(data)){//如果資料存在則進行資料處理
if(this.root.data.equals(data)){//首先需要判斷要洗掉的資料是否為根節點資料
this.root = this.root.next;//根節點變為下一個節點
}else{//不是根節點
this.root.next.removeNode(this.root,data);
}
this.count --;
}
}
在Node類之中增加一個removeNode(Node previous, Object data)方法:
//第一次:this = Link.root.next、previous= Link.root;
//第二次:this = Link.root.next.next、previous= Link.root.next;
public void removeNode(Node previous, Object data){
if(this.data.equals(data)){//當前節點為要洗掉的節點
previous.next = this.next;
}else{
this.next.removeNode(this,data);
}
}
Link鏈表類模板
class Link{//負責鏈表的操作
//將Node定義內部類,表示Node類只能為Link類提供服務
private class Node{//負責資料與節點的關系匹配
private Object data;//真正要保存的資料
private Node next;//定義下一個節點
public Node(Object data){
this.data = data;
}
public void setData(Object data){
this.data = data;
}
public Object getData(){
return this.data;
}
public void setNext(Node next){
this.next = next;
}
public Node getNext(){
return this.next;
}
//第一次呼叫:this = Link.root
//第二次呼叫:this = Link.root.next
//第三次呼叫:this = Link.root.next.next
public void addNode(Node newNode){//處理節點關系
if(this.next == null){ //當前節點下一個為空
this.next = newNode;
}else{//當前節點的下一個不為空
this.next.addNode(newNode);
}
}
public void nodePrint(){
System.out.println(this.getData());
if (this.getNext()==null)
{
return;
}else{
this.getNext().nodePrint();
}
}
public void toArrayNode(){
Link.this.retData[Link.this.foot++] = this.data;
if(this.next != null){
this.next.toArrayNode();
}
}
public boolean containsNode(Object search){
if(search.equals(this.data))
return true;
else{
if(this.next != null){//判斷下一個節點是否為空
return this.next.containsNode(search);
}
return false;
}
}
//第一次this == Link.root
//第二次this == Link.root.next
public Object getNode(int index){
if(Link.this.foot++ == index){
return this.data;
}else{
return this.next.getNode(index);
}
}
public void setNode(int index, Object newData){
if(Link.this.foot ++ == index){//索引相同
this.data = newData;
}else{
if(this.next != null){
this.next.setNode(index,newData);
}
}
}
//第一次:this = Link.root.next、previous= Link.root;
//第二次:this = Link.root.next.next、previous= Link.root.next;
public void removeNode(Node previous, Object data){
if(this.data.equals(data)){//當前節點為要洗掉的節點
previous.next = this.next;
}else{
this.next.removeNode(this,data);
}
}
}
//以下為Link類------------------------------------------------
private Object [] retData ; //回傳型別
private int foot = 0;//操作下標
private int count;//統計個數
private Node root; //屬于根節點,沒有根節點就無法資料的保存
//增加資料
public void add(Object data){
if(data == null){//人為追加規定,不允許存放null值
return ;//結束方法呼叫
}
//如果要想進行資料的保存,那么必須將資料封裝在Node類里面
//如果沒有封裝,則無法確認好節點的先后順序
Node newNode = new Node(data);
if(this.root == null){
this.root = newNode;//第一個節點設定為根節點
}else{//根節點存在了
this.root.addNode(newNode);
}
count++;
}
//判斷鏈表是否為空
public boolean isEmpty(){
this.count=0;
return false;
}
//增加多個資料
public void addAll(String date[]){
for(int x = 0;x<date.length;x++){
this.add(date[x]);
}
}
public int size(){
return this.count;
}
//輸出資料
public void print(){
if (this.root == null){
return;
}
System.out.println(this.root.getData());
if (this.root.getNext()==null){
return;
}
else{
this.root.getNext().nodePrint();
}
}
//鏈表資料轉換為物件陣列
public Object[] toArray(){
if(this.count == 0){
return null;
}
this.retData = new Object[this.count];
this.root.toArrayNode();
this.foot = 0;//下表清零操作
return this.retData;
}
//查找鏈表的指定資料是否存在
public boolean contains(Object search){
if(search == null && this.root == null)
return false;
return this.root.containsNode(search);
}
//根據索引取得資料
public Object get(int index){
if(index >= this.count){
return null;
}
this.foot = 0;
return this.root.getNode(index);
}
//修改指定索引資料
public void set(int index,Object newData){
if(index >= this.count){
return ;
}
this.foot = 0;
this.root.setNode(index,newData);
}
//洗掉資料
public void remove(Object data){
if(this.contains(data)){//如果資料存在則進行資料處理
if(this.root.data.equals(data)){//首先需要判斷要洗掉的資料是否為根節點資料
this.root = this.root.next;//根節點變為下一個節點
}else{//不是根節點
this.root.next.removeNode(this.root,data);
}
this.count --;
}
}
}
綜合案例
建立寵物商店,包括銷售寵物上架、下架、關鍵字查詢,要求程式的關系即可,對于寵物的資訊只要有三項:名字、年齡、顏色,
對應的關系:一個寵物商店有多種寵物,如果按照表設計應該屬于一對多關系映射,但是現在問題,一方是寵物商店,多方是寵物,但是寵物又分為貓、狗、豬、驢、魚等,

1、建立寵物標準
interface Pet{//定義寵物
public String getName();
public String getColor();
public int getAge();
}
2、對于寵物商店,只關注于寵物的標準,而不關心具體是那種寵物
class PetShop{
private Link pets = new Link();//開辟一個鏈表,保存寵物資訊
public void add(Pet pet){//上架寵物
this.pets.add(pet);
}
public void delete(Pet pet){//下架寵物
this.pets.delete(pet);
}
public Link getPets(){ //得到全部寵物
return this.pets;
}
public Link search(String keyword){//關鍵字查找
Link result = new Link();
Object [] data = this.pets.toArray();
for(int i = 0; i < data.length ; i++){
Pet pet = (Pet) data[i];
if(pet.getName().contains(keyword) || pet.getColor().contains(keyword)){
result.add(pet); //滿足查詢結果
}
}
return result;
}
}
3、定義寵物狗
class Dog implements Pet{
private String name;
private String color;
private int age;
public String getName(){
return this.name;
}
public String getColor(){
return this.color;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return false;
}
if(!(obj instanceof Dog)){
return false;
}
Dog pet = (Dog) obj;
return this.name.equals(pet.name) && this.color.equals(pet.color) && this.age.equals(pet.age);
}
public int getAge(){
return this.age;
}
public Dog(String name, String color, int age){
this.name = name ;
this.color = color;
this.age = age;
}
public String toString(){
return "【狗】名字 = " + this.name +
"顏色 = " + this.color +
"年齡 = " +this.age;
}
}
定義寵物貓
class Cat implements Pet{
private String name;
private String color;
private int age;
public String getName(){
return this.name;
}
public String getColor(){
return this.color;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return false;
}
if(!(obj instanceof Cat)){
return false;
}
Cat pet = (Cat) obj;
return this.name.equals(pet.name) && this.color.equals(pet.color) && this.age.equals(pet.age);
}
public int getAge(){
return this.age;
}
public Cat(String name, String color, int age){
this.name = name ;
this.color = color;
this.age = age;
}
public String toString(){
return "【貓】名字 = " + this.name +
"顏色 = " + this.color +
"年齡 = " +this.age;
}
}
5、測驗類
public class Pets{
public static void main(String args[]){
PetShop ps = new PetShop();
ps.add(new Dog("小黑","黑色",1));
ps.add(new Dog("金毛","金色",2));
ps.add(new Dog("拉布拉多","白色",3));
ps.add(new Dog("薩摩耶","白色",2));
ps.add(new Cat("加菲貓","黃色",3));
ps.add(new Dog("波斯貓","金色",4));
ps.delete(new Dog("薩摩耶","白色",2));
Link all = ps.search("白");
Object [] data = all.toArray();
for(int i = 0 ; i < data.length ; i++){
System.out.println(data[i]);
}
}
}
6、完整代碼
class Link{//負責鏈表的操作
//將Node定義內部類,表示Node類只能為Link類提供服務
private class Node{//負責資料與節點的關系匹配
private Object data;//真正要保存的資料
private Node next;//定義下一個節點
public Node(Object data){
this.data = data;
}
public void setData(Object data){
this.data = data;
}
public Object getData(){
return this.data;
}
public void setNext(Node next){
this.next = next;
}
public Node getNext(){
return this.next;
}
//第一次呼叫:this = Link.root
//第二次呼叫:this = Link.root.next
//第三次呼叫:this = Link.root.next.next
public void addNode(Node newNode){//處理節點關系
if(this.next == null){ //當前節點下一個為空
this.next = newNode;
}else{//當前節點的下一個不為空
this.next.addNode(newNode);
}
}
public void nodePrint(){
System.out.println(this.getData());
if (this.getNext()==null)
{
return;
}else{
this.getNext().nodePrint();
}
}
public void toArrayNode(){
Link.this.retData[Link.this.foot++] = this.data;
if(this.next != null){
this.next.toArrayNode();
}
}
public boolean containsNode(Object search){
if(search.equals(this.data))
return true;
else{
if(this.next != null){//判斷下一個節點是否為空
return this.next.containsNode(search);
}
return false;
}
}
//第一次this == Link.root
//第二次this == Link.root.next
public Object getNode(int index){
if(Link.this.foot++ == index){
return this.data;
}else{
return this.next.getNode(index);
}
}
public void setNode(int index, Object newData){
if(Link.this.foot ++ == index){//索引相同
this.data = newData;
}else{
if(this.next != null){
this.next.setNode(index,newData);
}
}
}
//第一次:this = Link.root.next、previous= Link.root;
//第二次:this = Link.root.next.next、previous= Link.root.next;
public void removeNode(Node previous, Object data){
if(this.data.equals(data)){//當前節點為要洗掉的節點
previous.next = this.next;
}else{
this.next.removeNode(this,data);
}
}
}
//以下為Link類------------------------------------------------
private Object [] retData ; //回傳型別
private int foot = 0;//操作下標
private int count;//統計個數
private Node root; //屬于根節點,沒有根節點就無法資料的保存
//增加資料
public void add(Object data){
if(data == null){//人為追加規定,不允許存放null值
return ;//結束方法呼叫
}
//如果要想進行資料的保存,那么必須將資料封裝在Node類里面
//如果沒有封裝,則無法確認好節點的先后順序
Node newNode = new Node(data);
if(this.root == null){
this.root = newNode;//第一個節點設定為根節點
}else{//根節點存在了
this.root.addNode(newNode);
}
count++;
}
//判斷鏈表是否為空
public boolean isEmpty(){
this.count=0;
return false;
}
//增加多個資料
public void addAll(String date[]){
for(int x = 0;x<date.length;x++){
this.add(date[x]);
}
}
public int size(){
return this.count;
}
//輸出資料
public void print(){
if (this.root == null){
return;
}
System.out.println(this.root.getData());
if (this.root.getNext()==null){
return;
}
else{
this.root.getNext().nodePrint();
}
}
//鏈表資料轉換為物件陣列
public Object[] toArray(){
if(this.count == 0){
return null;
}
this.retData = new Object[this.count];
this.root.toArrayNode();
this.foot = 0;//下表清零操作
return this.retData;
}
//查找鏈表的指定資料是否存在
public boolean contains(Object search){
if(search == null && this.root == null)
return false;
return this.root.containsNode(search);
}
//根據索引取得資料
public Object get(int index){
if(index >= this.count){
return null;
}
this.foot = 0;
return this.root.getNode(index);
}
//修改指定索引資料
public void set(int index,Object newData){
if(index >= this.count){
return ;
}
this.foot = 0;
this.root.setNode(index,newData);
}
//洗掉資料
public void remove(Object data){
if(this.contains(data)){//如果資料存在則進行資料處理
if(this.root.data.equals(data)){//首先需要判斷要洗掉的資料是否為根節點資料
this.root = this.root.next;//根節點變為下一個節點
}else{//不是根節點
this.root.next.removeNode(this.root,data);
}
this.count --;
}
}
}
interface Pet{//定義寵物
public String getName();
public String getColor();
public int getAge();
}
class PetShop{
private Link pets = new Link();//開辟一個鏈表,保存寵物資訊
public void add(Pet pet){//上架寵物
this.pets.add(pet);
}
public void delete(Pet pet){//下架寵物
this.pets.remove(pet);
}
public Link getPets(){ //得到全部寵物
return this.pets;
}
public Link search(String keyword){//關鍵字查找
Link result = new Link();
Object [] data = this.pets.toArray();
for(int i = 0; i < data.length ; i++){
Pet pet = (Pet) data[i];
if(pet.getName().contains(keyword) || pet.getColor().contains(keyword)){
result.add(pet); //滿足查詢結果
}
}
return result;
}
}
class Dog implements Pet{
private String name;
private String color;
private int age;
public String getName(){
return this.name;
}
public String getColor(){
return this.color;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return false;
}
if(!(obj instanceof Dog)){
return false;
}
Dog pet = (Dog) obj;
return this.name.equals(pet.name) && this.color.equals(pet.color) && this.age == pet.age;
}
public int getAge(){
return this.age;
}
public Dog(String name, String color, int age){
this.name = name ;
this.color = color;
this.age = age;
}
public String toString(){
return "【狗】名字 = " + this.name +
",顏色 = " + this.color +
",年齡 = " +this.age;
}
}
class Cat implements Pet{
private String name;
private String color;
private int age;
public String getName(){
return this.name;
}
public String getColor(){
return this.color;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return false;
}
if(!(obj instanceof Cat)){
return false;
}
Cat pet = (Cat) obj;
return this.name.equals(pet.name) && this.color.equals(pet.color) && this.age == pet.age;
}
public int getAge(){
return this.age;
}
public Cat(String name, String color, int age){
this.name = name ;
this.color = color;
this.age = age;
}
public String toString(){
return "【貓】名字 = " + this.name +
",顏色 = " + this.color +
",年齡 = " +this.age;
}
}
public class Pets{
public static void main(String args[]){
PetShop ps = new PetShop();
ps.add(new Dog("小黑","黑色",1));
ps.add(new Dog("金毛","金色",2));
ps.add(new Dog("拉布拉多","白色",3));
ps.add(new Dog("薩摩耶","白色",2));
ps.add(new Cat("加菲貓","黃色",3));
ps.add(new Dog("波斯貓","金色",4));
ps.delete(new Dog("薩摩耶","白色",2));
Link all = ps.search("白");
Object [] data = all.toArray();
for(int i = 0 ; i < data.length ; i++){
System.out.println(data[i]);
}
}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/293948.html
標籤:java
