目錄
一.異常處理
二.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異常】編寫一個程式,提示使用者輸入兩個整數,然後顯示它們的和。使用者輸入錯誤時提示使用者重新輸入。
如下所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90zZOlXSqFGcWJDZsx2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0kTM0UTMyMjMzATMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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容器,功能很強大。
容器嘛,是以裡邊的操作必然是添加、删除、判斷、加擷取。
上圖所示為所有容器的示意圖:
其中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的子類。
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++中的動态連結清單也是大同小異,具體詳情可翻閱之前的部落格連結清單
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()用來傳回子樹。