天天看點

JAVA異常處理與容器(集合)

目錄

一.異常處理

二.JAVA容器

1.疊代器

2.ArrayList 和 LinkedList

3.Map:

一個鍵值(key)對應一個對象(value)的容器接口,并且沒有排序

1.異常

一、 異常機制的概述

      異常機制是指當程式出現錯誤後,程式如何處理。具體來說,異常機制提供了程式退出的安全通道。當出現錯誤後,程式執行的流程發生改變,程式的控制權轉移到異常處理器。

      程式錯誤分為三種:1.編譯錯誤;2.運作時錯誤;3.邏輯錯誤。

      (1)編譯錯誤是因為程式沒有遵循文法規則,編譯程式能夠自己發現并且提示我們錯誤的原因和位置,這個也是大家在剛接觸程式設計語言最常遇到的問題。

      (2)運作時錯誤是因為程式在執行時,運作環境發現了不能執行的操作,這種錯誤在編譯時發現不了,隻有在運作時才會報錯。

      (3)邏輯錯誤是因為程式沒有按照預期的邏輯順序執行。異常也就是指程式運作時發生錯誤,而異常處理就是對這些錯誤進行處理和控制。

 1.在Java中當程式出現異常時,可以使用try···catch、try···catch···finally或try···finally進行處理。

1. 使用try···catch處理異常

try後是正常執行的語句,而catch後是對異常處理的語句,catch的括号中是程式需要處理的異常類型。文法格式如下:

try {

正常執行的語句

} catch(Exception e) {

對異常進行處理的語句

}

這裡舉一個算數異常的例子,如下。

public class ExceptionTest {

public static void main(String[] args) {

int result = 1 / 0;

try {

System.out.println(result);

} catch (Exception e) {

System.out.println("抛出異常:" + e.getMessage());

}}}

2. 使用try···catch···finally處理異常

這裡try、catch後的語句與前面的相同,而finally後的語句無論是否發生異常都要執行,是以finally語句塊通常用于執行垃圾回收。文法格式如下:

try {

正常執行的語句

} catch(Exception e) {

對異常進行處理的語句

} finally {

一定會被處理的語句

}

3. 使用try···finally處理異常

在程式發生異常時,就可以在finally語句塊中對其進行相應的處理,另外當程式沒有發生異常時,執行完try和finally之間的語句後,也将執行finally語句塊中的代碼。

舉一個用try   catch的例子,如下所示:

【NumberFormatException異常】編寫一個程式,提示使用者輸入兩個整數,然後顯示它們的和。使用者輸入錯誤時提示使用者重新輸入。

如下所示:

JAVA異常處理與容器(集合)
JAVA異常處理與容器(集合)
package example;

import java.util.Scanner;

public class Test1 {
	public static void main(String[] args) {
		String string = new String();
		Scanner input = new Scanner(System.in);
		System.out.println("輸入數字");
		string = input.nextLine();
		int num = Integer.parseInt(string);
		System.out.println(num);
	}
}
           

進行異常抛出:

try{
				System.out.println("請輸入兩個數:");
				num1 = input.nextLine();
				num2 = input.nextLine();
				int sum = Integer.parseInt(num1.trim())+ 							Integer.parseInt(num2.trim());
				System.out.println(num1 + " + "+ num2 +" = " + sum);
				judge = false;
			}
			catch(NumberFormatException ex){
				System.out.println("請輸入兩個有意義的數");
	}
           

 注:

trim() 方法用于删除字元串的頭尾空白符,空白符包括:空格、制表符 tab、換行符等其他空白符等。

更多String方法可參考我的java基礎類庫部落格

JAVA基礎類庫(第四周)(三隻松鼠,奧利給)_阿狗哲哲的部落格-CSDN部落格

https://blog.csdn.net/qq_52438590/article/details/116951958?spm=1001.2014.3001.5501

pareInt()方法如下所示,即将字元串轉化為int類型 

var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六進制數)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 56(八進制數)
var num6 = parseInt("70"); // 70(十進制數)
var num7 = parseInt("0xf"); // 15(十六進制數)
var num8 = parseInt("AF", 16); //175
           
除了上面的try···catch語句處理之外,還可以使用throws聲明或throws語句抛出異常。 

1. 使用throws聲明抛出異常

throws用于方法聲明,在聲明方法時使用throws聲明抛出異常,然後在調用該方法中對異常進行處理。

如需聲明多個異常,各異常間要用逗号分隔,文法格式如下:

資料類型 方法名(形參清單) throws 異常類1, 異常類2, ……, 異常類n {

方法體;

}

2. 使用throw語句抛出異常

如果希望程式自行抛出異常,可以使用throw語句來實作。文法格式如下: throw new Exception("對異常的說明");

使用throw語句抛出的是異常類的執行個體,通常與if語句一起使用。

2.數組與容器

1.可與前面的部落格作比較:連結清單c語言_阿狗哲哲的部落格-CSDN部落格

https://blog.csdn.net/qq_52438590/article/details/116943029?spm=1001.2014.3001.5501

c語言中的數組與連結清單的差別與JAVA中的數組與容器的差別有相似相通之處:

優勢:數組是一種線性序列,本身是一種數組容器可快速通路數組元素,效率高。

劣勢:數組容器需要事先定義好容量,不能随時擴容,是以需要一種功能更強大的數組 來存放資料,是以有了容器的概念java容器可以動态調節自己的大小,是以程式設計中可以将任意數量的對象放置到容器中,類似于c++中的vector容器,功能很強大。

容器嘛,是以裡邊的操作必然是添加、删除、判斷、加擷取。

JAVA異常處理與容器(集合)

 上圖所示為所有容器的示意圖:

其中Collection與Map是并列的概念,

Collection接口是List,Set等的父接口,該接口定義的方法既可以操作List也可以操作Set,

Map接口用于存放鍵值對形式的元素,描述了由不重複的鍵到值的映射。

1. List

存儲的元素是有序的、可重複的。

Arraylist: Object[]數組

Vector:Object[]數組

LinkedList: 雙向連結清單(JDK1.6 之前為循環連結清單,JDK1.7 取消了循環)

2. Set

存儲的元素是無序的、不可重複的。

HashSet:無序,唯一,基于 HashMap 實作的,底層采用 HashMap 來儲存元素

LinkedHashSet:LinkedHashSet 是 HashSet 的子類,并且其内部是通過 LinkedHashMap 來實作的。有點類似于 LinkedHashMap 其内部是基于 HashMap 實作一樣

TreeSet:有序,唯一,紅黑樹

3. Map

HashMap:JDK1.8之前HashMap由數組+連結清單組成的,數組是HashMap的主體,連結清單則是主要為了解決哈希沖突⽽存在的。JDK1.8以後在解決哈希沖突時有了變化, 當連結清單⻓度⼤于門檻值(預設為8)時,将連結清單轉化為紅⿊樹,以減少搜尋時間

LinkedHashMap:LinkedHashMap繼承⾃HashMap,是以它的底層仍然是基于數組和連結清單/紅⿊樹組成。另外,LinkedHashMap 在上面結構的基礎上,增加了⼀條雙向連結清單,使得上面的結構可以保持鍵值對的插入順序。同時通過對連結清單進行相應的操作,實作了通路順序相關邏輯。

Hashtable: 數組+連結清單組成的,數組是 Hashtable 的主體,連結清單則是主要為了解決哈希沖突而存在的

TreeMap: 紅黑樹

其中,紅黑樹的了解感悟可參考csdn大佬的部落格

漫畫算法:5 分鐘搞明白紅黑樹到底是什麼?_CSDN資訊-CSDN部落格

原文連結:https://data.newrank.cn/m/s.html?s=PigpOzA/LTE%3D

1.疊代器

在說具體容器之前,有必要先了解一下疊代器。作為一種設計模式,疊代器給我們提供了周遊容器中元素的方法, Iterator是作為一個接口存在的,它定義了疊代器所具有的功能,接口如下:

package java.util;    
public interface Iterator<E> {    
    boolean hasNext();    
    E next();    
    void remove();    
} 
           

疊代器隻能通過容器本身得到,每個容器都通過自己的内部類完成疊代器,是以可以通過疊代器周遊容器,類似于c++中vector的周遊,也是需要通過疊代器周遊vector

其中,c++的周遊如下所示:

vector<Phonecard_contact>::iterator temp;                       //phone_contact類型的指針
        for(temp=phonecard_contact.begin();temp!=phonecard_contact.end();temp++)//周遊
        {
            cout<<(*temp);
            cout<<endl;
        }
           

java的周遊如下所示,差別非常大:

ArrayList<String> list = new ArrayList<String>();
//省略初始化list……
……
//從list得到其疊代器
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    //
    String element = iterator.next();
    System.out.println(element);
}
           

如果隻是向前周遊List,并不打算修改List對象本身,使用foreach文法會更加簡潔。

for(String e : list){
    System.out.println(e);
}
           

2.ArrayList 和 LinkedList

ArrayList詳解

ArrayList是順序容器,底層是數組,允許放入null值。每個ArrayList都有一個容量capacity,表示底層實作數組的大小,當添加元素的時候,如果capacity不夠,會自動增加數組的大小。

List 元素可重複,且有序。ArrayList和LinkedList是List的子類。

JAVA異常處理與容器(集合)

1.add()方法

(1)ArrayList末尾添加元素的方法是add(E e),指定位置插入元素的方法是add(int index, E e),在添加的過程中,可能會存在capacity容量不足的問題,在每次添加前都要進行容量檢查,如果容量不足,需要使用grow()擴容方法進行自動擴容

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //原來的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
        //擴充空間完成後複制
    elementData = Arrays.copyOf(elementData, newCapacity);
}
           

add(int index, E e)需要先對插入位置之後的元素進行移動,然後完成插入操作,數組size+1,方法有線性時間複雜度。

(2)Linkedlist

add()方法包含兩個,add(E e)方法在連結清單末尾插入元素,借助last指針,末尾插入隻需常數時間;add(int index, E element)方法在指定下标處插入元素,需要先查找位置再執行插入。

add(E e)方法與add(int index, E element)大同小異,隻介紹難度更複雜的add(int index, E element),其實add(int index, E element)與c++中的動态連結清單也是大同小異,具體詳情可翻閱之前的部落格連結清單

JAVA異常處理與容器(集合)
public void add(int index, E element) {
    //下标越界檢查(index >= 0 && index <= size)
    checkPositionIndex(index);
    if (index == size)
        //插入位置是末尾,或清單為空
        add(element);
    else{
        //先根據index找到要插入的位置
        Node<E> succ = node(index);
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
    }
           

3.Map:

一個鍵值(key)對應一個對象(value)的容器接口,并且沒有排序

//周遊方式:由于Map沒有提供iterator()函數,而是用keySet(),values()方法取代
		//方法一
		Collection<String> c=m.values();
		for(Iterator<String> it=c.iterator();it.hasNext();) {
			System.out.print(it.next()+" ");
		}
		System.out.println();
		//方法二
		Set<Integer> s=m.keySet();
		for(Iterator<Integer> it=s.iterator();it.hasNext();) {
			System.out.print(it.next()+" ");
		}
		System.out.println();
		
           

HashMap:

一個我們平常使用最最頻繁的Map容器,它的查詢速度是最快的,HashMap 根據鍵的 hashCode 值存儲資料,大多數情況下可以直接定位到它的值,因而具有很快的通路速度,但周遊順序卻是不确定的。 HashMap 最多隻允許一條記錄的鍵為 null,允許多條記錄的值為 null。HashMap 非線程安全,即任一時刻可以有多個線程同時寫 HashMap,可能會導緻資料的不一緻。如果需要滿足線程安全,可以用 Collections 的 synchronizedMap 方法使HashMap 具有線程安全的能力,或者使用 ConcurrentHashMap。

TreeMap:

TreeMap:和TreeSet類似,紅黑樹結構,同樣進行排序(次序由存入TreeMap的類的compare()或compareTo()方法決定,也就是說裝入TreeMap的類必須實作HashCode(),equals(),compare()三個方法),同時TreeMap還有一個subMap()用來傳回子樹。

繼續閱讀