Java從入門到高級(第二天)


經過不斷的學習

博主更新了Java進階高級第二天的知識

歡迎大家與我一起交流學習哦


目錄

1. List集合

1.1 ArrayList集合

1.2 LinkedList集合

1.3 List集合元素替換

2. Set接口

2.1 HashSet集合

2.2 HashSet集合存儲結構(哈希表)

2.3 HashSet存儲自定義類型元素

2.4 LinkedHashSet類

2.5 可變參數

3. Collections

3.1 Comparator比較器

3.2 Comparable和Comparator兩個接口的區別

4. Map集合

4.1 Map常用子類

4.2 Map接口中的常用方法

4.3 Map集合遍歷鍵找值方式

4.4 Entry鍵值對對象

4.5 Map集合遍歷鍵值對方式

4.6 LinkedHashMap

5. 異常

5.1 異常體系

5.2 異常分類

5.3 拋出異常throw

5.4 Objects非空判斷

5.5 聲明異常throws

5.6 throw與throws的區別

5.7 捕獲異常try…catch

5.8 finally 代碼塊

5.9 自定義異常


1. List集合

 java.util.List 接口繼承自 Collection 接口,是單列集合的一個重要分支,習慣性地會將實現了 List 接口的對象稱爲 List 集合。在 List 集合中允許出現重複的元素,所有的元素是以一種線性方式進行存儲的,在程序中可以通過索引來訪問集合中的指定元素。另外, List 集合還有一個特點就是元素有序,即元素的存入順序和取出順序一致。

 List 接口特點:

  1. 它是一個元素存取有序的集合。

  2. 它是一個帶有索引的集合,通過索引就可以精確的操作集合中的元素。

  3. 集合中可以有重複的元素,通過元素的 equals 方法,來比較是否爲重複的元素。

 List 常用方法:

  •  public void add(int index, E element) : 將指定的元素,添加到該集合中的指定位置上。

  •  public E get(int index) :返回集合中指定位置的元素。

  •  public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。

  •  public E set(int index, E element) :用指定元素替換集合中指定位置的元素,返回值的更新前的元素。


1.1 ArrayList集合

 java.util.ArrayList 集合數據存儲的結構是數組結構。元素增刪慢,查找快,由於日常開發中使用最多的功能爲查詢數據、遍歷數據,所以 ArrayList 是最常用的集合。


1.2 LinkedList集合

 java.util.LinkedList 集合數據存儲的結構是鏈表結構。方便元素添加、刪除的集合。

 LinkedList 常用方法:

  •  public void addFirst(E e) :將指定元素插入此列表的開頭。

  •  public void addLast(E e) :將指定元素添加到此列表的結尾。

  •  public E getFirst() :返回此列表的第一個元素。

  •  public E getLast() :返回此列表的最後一個元素。

  •  public E removeFirst() :移除並返回此列表的第一個元素。

  •  public E removeLast() :移除並返回此列表的最後一個元素。

  •  public E pop() :從此列表所表示的堆棧處彈出一個元素。

  •  public void push(E e) :將元素推入此列表所表示的堆棧。

  •  public boolean isEmpty() :如果列表不包含元素,則返回true


1.3 List集合元素替換

代碼實現: List 集合元素替換

public class ListTest {
    public static void main(String[] args) {
        // 創建List集合對象
        List<String> list = new ArrayList<>();
        
        // 存入數據
        list.add("張三");
        list.add("李四");
        list.add("王五");
        list.add("二麻子");
        list.add("老王");
        
        // 遍歷集合,找到"老王",將其替換爲"隔壁老王"
        // 利用普通for循環遍歷List集合
        for(int i = 0;i<list.size();i++) {
            // 獲取當前元素
            String thisName = list.get(i);
            
            // 如果當前元素是"老王"
            if("老王".equals(thisName)) {
                // 將其改爲"隔壁老王"
                list.set(i, "隔壁老王");
            }
        }
        System.out.println(list);
    }
}

2. Set接口

 java.util.Set 接口和 java.util.List 接口一樣,同樣繼承自 Collection 接口,它與 Collection 接口中的方法基本一致,並沒有對 Collection 接口進行功能上的擴充,只是比 Collection 接口更加嚴格了。與 List 接口不同的是, Set 接口中元素無序,並且都會以某種規則保證存入的元素不出現重複。

 Set 集合有多個子類,這裏我們介紹其中的 java.util.HashSet java.util.LinkedHashSet 這兩個集合。


2.1 HashSet集合

 java.util.HashSet Set 接口的一個實現類,它所存儲的元素是不可重複的,並且元素都是無序的(即存取順序不一致)。 java.util.HashSet 底層的實現其實是一個 java.util.HashMap 支持。

 HashSet 是根據對象的哈希值來確定元素在集合中的存儲位置,因此具有良好的存取和查找性能。保證元素唯一性的方式依賴於: hashCode equals 方法。


2.2 HashSet集合存儲結構(哈希表)

JDK1.8之前,哈希表底層採用【數組+鏈表】實現,即使用鏈表處理衝突,同一 hash 值的鏈表都存儲在一個鏈表裏。但是當位於一個桶中的元素較多,即 hash 值相等的元素較多時,通過 key 值依次查找的效率較低。而JDK1.8中,哈希表存儲採用【數組+鏈表+紅黑樹】實現,當鏈表長度超過閾值8時,將鏈表轉換爲紅黑樹,這樣大大減少了查找時間。 如下圖:


2.3 HashSet存儲自定義類型元素

HashSet 中存放自定義類型元素時,需要重寫對象中的 hashCode equals 方法,建立自己的比較方式,才能保證 HashSet 集合中的對象唯一。

代碼實現:重寫 equals 方法和 hashCode 方法

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    // 重寫equals()方法
    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        Student student = (Student) o;
        return age == student.age &&
               Objects.equals(name, student.name);
    }

    // 重寫hashCode()方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

2.4 LinkedHashSet類

HashSet 下面有一個子類 java.util.LinkedHashSet ,它是鏈表和哈希表組合的一個數據存儲結構。能夠保證存放進去的元素有序且唯一。

代碼實現:使用 LinkedHashSet 子類實例

public class LinkedHashSetTest {
    public static void main(String[] args) {
        // 創建LinkedHashSet
        LinkedHashSet<String> Set = new LinkedHashSet<String>();

        // 使用add方法添加元素到LinkedHashSet
        Set.add("玩家1");
        Set.add("玩家1");
        Set.add("玩家2");
        Set.add("玩家1");
        Set.add("玩家3");
        Set.add("玩家4");

        // 使用迭代器獲取LinkedHashSet中的元素
        Iterator<String> iterator = Set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        // 使用增強for獲取LinkedHashSet中的元素
        for (String string : Set) {
            System.out.println(string);
        }
    }
}

2.5 可變參數

JDK1.5之後,如果我們定義一個方法需要接受多個參數,並且多個參數類型一致,我們可以對其簡化成如下兩種格式:

修飾符 返回值類型 方法名(參數類型... 形參名){  }

修飾符 返回值類型 方法名(參數類型[] 形參名){  }


3. Collections

 java.utils.Collections 是集合工具類,用來對集合進行操作。部分方法如下:

  •  public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。

  •  public static void shuffle(List<?> list) :打亂集合順序。

  •  public static <T> void sort(List<T> list) :將集合中元素按照默認規則排序。

  •  public static <T> void sort(List<T> list,Comparator<? super T> ) :將集合中元素按照指定規則排序。


3.1 Comparator比較器

 public static <T> void sort(List<T> list) :將集合中元素按照默認規則排序。

說到排序了,簡單的說就是兩個對象之間比較大小,那麼在JAVA中提供了兩種比較實現的方式,一種是比較死板的採用 java.lang.Comparable 接口去實現,一種是靈活的當我需要做排序的時候在去選擇的 java.util.Comparator 接口完成。

代碼實現:使用 Comparator 接口排序字符串

public class CollectionsDemo {
    public static void main(String[] args) {
        ArrayList<String>  list = new ArrayList<String>();
        list.add("cba");
        list.add("aba");
        list.add("sba");
        list.add("nba");
        
        //排序方法
        Collections.sort(list);
        System.out.println(list);
    }
}

 public int compare(String o1, String o2) :比較其兩個參數的順序。

兩個對象比較的結果有三種:大於,等於,小於

如果要按照升序排序,則o1 小於o2,返回(負數),相等返回0,o1大於o2返回(正數)

如果要按照降序排序,則o1 小於o2,返回(正數),相等返回0,o1大於o2返回(負數)

代碼實現:使用 compare 方法排序字符串

public class CollectionsDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("cba");
        list.add("aba");
        list.add("sba");
        list.add("nba");
        
        // 排序方法:按照單詞的第一個字母降序排列
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.charAt(0) - o1.charAt(0);
            }
        });
        System.out.println(list);
    }
}

3.2 Comparable和Comparator兩個接口的區別

Comparable:強行對實現它的每個類的對象進行整體排序。這種排序被稱爲類的自然排序,類的 compareTo 方法被稱爲它的自然比較方法。只能在類中實現 compareTo() 一次,不能經常修改類的代碼實現自己想要的排序。實現此接口的對象列表(和數組)可以通過 Collections.sort Arrays.sort 進行自動排序,對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。

Comparator:強行對某個對象進行整體排序。可以將 Comparator 傳遞給 sort 方法(如 Collections.sort Arrays.sort ),從而允許在排序順序上實現精確控制。還可以使用 Comparator 來控制某些數據結構(如有序 set 或有序映射)的順序,或者爲那些沒有自然順序的對象 collection 提供排序。


4. Map集合

現實生活中,我們常會看到這樣的一種集合:IP地址與主機名,身份證號與個人,系統用戶名與系統用戶對象等,這種一一對應的關係,就叫做映射。Java提供了專門的集合類用來存放這種對象關係的對象,即 java.util.Map 接口。

通過查看 Map 接口描述,發現 Map 接口下的集合與 Collection 接口下的集合,它們存在的不同如下:

  •  Collection 中的集合,元素是孤立存在的(理解爲單身),向集合中存儲元素採用一個個元素的方式存儲。

  •  Map 中的集合,元素是成對存在的(理解爲夫妻)。每個元素由鍵與值兩部分組成,通過鍵可以找對所對應的值。

  •  Collection 中的集合稱爲單列集合, Map 中的集合稱爲雙列集合。

  •  Map 中的集合不能包含重複的鍵,值可以重複;每個鍵只能對應一個值。


4.1 Map常用子類

  • HashMap<K,V>:存儲數據採用的哈希表結構,元素的存取順序不能保證一致。由於要保證鍵的唯一、不重複,需要重寫鍵的 hashCode() 方法與 equals() 方法。

  • LinkedHashMap<K,V> HashMap 下有個子類 LinkedHashMap ,存儲數據採用的哈希表結構+鏈表結構。通過鏈表結構可以保證元素的存取順序一致;通過哈希表結構可以保證的鍵的唯一、不重複,需要重寫鍵的 hashCode() 方法、 equals() 方法。


4.2 Map接口中的常用方法

 Map 接口中定義了很多方法,常用的如下:

  •  public V put(K key, V value) : 把指定的鍵與指定的值添加到 Map 集合中。

  •  public V remove(Object key) : 把指定的鍵所對應的鍵值對元素 在 Map 集合中刪除,返回被刪除元素的值。

  •  public V get(Object key) :根據指定的鍵,在 Map 集合中獲取對應的值。

  •  boolean containsKey(Object key) :判斷集合中是否包含指定的鍵。

  •  public Set<K> keySet() : 獲取 Map 集合中所有的鍵,存儲到 Set 集合中。

  •  public Set<Map.Entry<K,V>> entrySet() : 獲取到 Map 集合中所有的鍵值對對象的集合( Set 集合)。


4.3 Map集合遍歷鍵找值方式

鍵找值方式:即通過元素中的鍵,獲取鍵所對應的值。步驟如下:

  1. 獲取 Map 中所有的鍵,由於鍵是唯一的,所以返回一個 Set 集合存儲所有的鍵。方法提示: keyset()

  2. 遍歷鍵的 Set 集合,得到每一個鍵。

  3. 根據鍵,獲取鍵所對應的值。方法提示: get(K key)

代碼實現: Map 集合遍歷鍵找值方式

public class MapDemo {
    public static void main(String[] args) {
        // 創建Map集合對象 
        HashMap<String, String> map = new HashMap<String,String>();
        
        // 添加元素到集合 
        map.put("1529***5693", "玩家1");
        map.put("1624***9642", "玩家2");
        map.put("1486***5682", "玩家3");

        // 獲取所有的鍵、鍵集
        Set<String> keys = map.keySet();
        
        // 遍歷鍵集,得到每一個鍵
        for (String key : keys) {
            String value = map.get(key);
            System.out.println(key+"的對應值是:"+value);
        }  
    }
}

4.4 Entry鍵值對對象

 Map 中存放的是兩種對象,一種稱爲key(鍵),一種稱爲value(值),它們在 Map 中是一一對應關係,這一對對象又稱做 Map 中的一個 Entry(項) Entry 將鍵值對的對應關係封裝成了對象。即鍵值對對象,這樣我們在遍歷 Map 集合時,就可以從每一個鍵值對 (Entry) 對象中獲取對應的鍵與對應的值。獲取對應鍵和對應值得方法:

  •  public K getKey() :獲取 Entry 對象中的鍵。

  •  public V getValue() :獲取 Entry 對象中的值。

  •  public Set<Map.Entry<K,V>> entrySet() : 獲取到 Map 集合中所有的鍵值對對象的集合( Set 集合)。


4.5 Map集合遍歷鍵值對方式

鍵值對方式:即通過集合中每個鍵值對 (Entry) 對象,獲取鍵值對 (Entry) 對象中的鍵與值。操作步驟如下:

  1. 獲取 Map 集合中,所有的鍵值對 (Entry) 對象,以Set集合形式返回。方法提示: entrySet()

  2. 遍歷包含鍵值對 (Entry) 對象的 Set 集合,得到每一個鍵值對 (Entry) 對象。

  3. 通過鍵值對 (Entry) 對象,獲取 (Entry) 對象中的鍵與值。 方法提示: getkey() getValue()

代碼實現:獲取鍵值對 (Entry) 對象中的鍵與值

public class MapDemo {
    public static void main(String[] args) {
        // 創建Map集合對象 
        HashMap<String, String> map = new HashMap<String,String>();
        
        // 添加元素到集合 
        map.put("1685***5203", "玩家1");
        map.put("1695***7512", "玩家2");
        map.put("1575***5623", "玩家3");

        // 獲取所有的entry對象
        Set<Entry<String,String>> entrySet = map.entrySet();

        // 遍歷得到每一個entry對象
        for (Entry<String, String> entry : entrySet) {
            String key = entry.getKey();
            String value = entry.getValue();  
            System.out.println(key+"的對應值是:"+value);
        }
    }
}

4.6 LinkedHashMap

  • 當給 HashMap 中存放自定義對象時,如果自定義對象作爲 key 存在,這時要保證對象唯一,必須複寫對象的 hashCode equals 方法。

  • 如果要保證 map 中存放的 key 和取出的順序一致,可以使用 java.util.LinkedHashMap 集合來存放。


5. 異常

  • 異常 :指的是程序在執行過程中,出現的非正常的情況,最終會導致JVM的非正常停止。

Java等面向對象的編程語言中,異常本身是一個類,產生異常就是創建異常對象並拋出了一個異常對象。Java處理異常的方式是中斷處理。


5.1 異常體系

異常機制其實是幫助我們找到程序中的問題,異常的根類是 java.lang.Throwable ,其下有兩個子類: java.lang.Error java.lang.Exception ,平常所說的異常指 java.lang.Exception

Throwable體系:

  • Error:嚴重錯誤 Error ,無法通過處理的錯誤,只能事先避免。

  • Exception:表示異常,異常產生後程序員可以通過代碼的方式糾正,使程序繼續運行,是必須要處理的。

Throwable中的常用方法:

  •  public void printStackTrace() :打印異常的詳細信息。

    包含了異常的類型,異常的原因,還包括異常出現的位置,在開發和調試階段,都得使用 printStackTrace()

  •  public String getMessage() :獲取發生異常的原因。

    提示給用戶的時候,就提示錯誤原因。

  •  public String toString() :獲取異常的類型和異常描述信息。


5.2 異常分類

  • 編譯時期異常: checked 異常。在編譯時期,就會檢查,如果沒有處理異常,則編譯失敗。(如日期格式化異常)

  • 運行時期異常: runtime 異常。在運行時期,檢查異常.在編譯時期,運行異常不會編譯器檢測(不報錯)。(如數學異常)


5.3 拋出異常throw

java中,提供了一個 throw 關鍵字,它用來拋出一個指定的異常對象。那麼,拋出一個異常具體如何操作呢?

  1. 創建一個異常對象。封裝一些提示信息(信息可以自己編寫)。

  2. 需要將這個異常對象告知給調用者。 throw 異常對象。並且 throw 用在方法內,用來拋出一個異常對象,將這個異常對象傳遞到調用者處,並結束當前方法的執行。

格式如下:

throw new 異常類名(參數);

代碼實現:方法體中 throw 的使用

public static int getElement(int[] arr,int index){ 
    // 判斷:索引是否越界
    if(index<0 || index>arr.length-1){
        // 如果條件滿足,執行完throw拋出異常後,方法無法繼續運算
        throw new ArrayIndexOutOfBoundsException("角標越界!");
    }
    int element = arr[index];
    return element;
}

5.4 Objects非空判斷

 public static <T> T requireNonNull(T obj) :查看指定引用對象不是null

代碼實現:對爲null的進行了拋出異常操作

public static <T> T requireNonNull(T obj) {
    if (obj == null)
      	throw new NullPointerException();
    return obj;
}

5.5 聲明異常throws

聲明異常:將問題標識出來,報告給調用者。如果方法內通過 throw 拋出了編譯時異常,而沒有捕獲處理,那麼必須通過 throws 進行聲明,讓調用者去處理。關鍵字 throws 運用於方法聲明之上,用於表示當前方法不處理異常,而是提醒該方法的調用者來處理異常(拋出異常)。

聲明異常格式:

修飾符 返回值類型 方法名(參數) throws 異常類名1,異常類名2…{   }   


5.6 throw與throws的區別

 throw 關鍵字通常用在方法體中,並且拋出一個異常對象。程序在執行到 throw 語句時立即停止,它後面的語句都不執行。

 throws 關鍵字通常被應用在聲明方法時,用來指定可能拋出的異常。多個異常可以使用逗號隔開。當在主函數中調用該方法時,如果發生異常,就會將異常對象拋給方法調用處。


5.7 捕獲異常try…catch

如果異常出現的話,會立刻終止程序,所以我們得處理異常:

  1. 該方法不處理,而是聲明拋出,由該方法的調用者來處理 (throws)

  2. 在方法中使用 try-catch 的語句塊來處理異常。

  try-catch 的方式就是捕獲異常。捕獲異常Java中對異常有針對性的語句進行捕獲,可以對出現的異常進行指定方式的處理。

捕獲異常語法如下:

try{
     編寫可能會出現異常的代碼
}catch(異常類型  e){
     處理異常的代碼
     //記錄日誌/打印異常信息/繼續拋出異常
}

try:該代碼塊中編寫可能產生異常的代碼。

catch:用來進行某種異常的捕獲,實現對捕獲到的異常進行處理。


5.8 finally 代碼塊

finally:有一些特定的代碼無論異常是否發生,都需要執行。另外,因爲異常會引發程序跳轉,導致有些語句執行不到。而 finally 就是解決這個問題的,在 finally 代碼塊中存放的代碼都是一定會被執行的。

代碼實現:實現 try-catch-finally 操作參考

public class TryCatchDem {
    public static void main(String[] args) {
        try {
            read("a.txt");
        } catch (FileNotFoundException e) {
            // 抓取到的是編譯期異常,拋出去的是運行期異常
            throw new RuntimeException(e);
        } finally {
            System.out.println("不管程序怎樣,finally中程序都會被執行。");
        }
        System.out.println("結束!");
    }
    
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {
            // 如果不是a.txt這個文件,拋出異常 
            throw new FileNotFoundException("文件不存在!");
        }
    }
}

5.9 自定義異常

異常類如何定義:

  1. 自定義一個編譯期異常: 自定義類 並繼承於 java.lang.Exception

  2. 自定義一個運行時期的異常類:自定義類 並繼承於 java.lang.RuntimeException

多個異常使用捕獲又該如何處理呢?

  1. 多個異常分別處理。

  2. 多個異常一次捕獲,多次處理。

  3. 多個異常一次捕獲一次處理。

一般處理方式的格式如下:

try{
     編寫可能會出現異常的代碼
}catch(異常類型A  e){  // 當try中出現A類型異常,就用該catch來捕獲
     處理異常的代碼
     // 記錄日誌/打印異常信息/繼續拋出異常
}catch(異常類型B  e){  // 當try中出現B類型異常,就用該catch來捕獲
     處理異常的代碼
     // 記錄日誌/打印異常信息/繼續拋出異常
}
  • 運行時異常被拋出可以不處理。即不捕獲也不聲明拋出。

  • 如果 finally return 語句,永遠返回 finally 中的結果,避免該情況。

  • 如果父類拋出了多個異常,子類重寫父類方法時,拋出和父類相同的異常或者是父類異常的子類或者不拋出異常。

  • 父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。此時子類產生該異常,只能捕獲處理,不能聲明拋出。


 

歡迎關注博主,歡迎互粉,一起學習!

感謝您的閱讀,不足之處歡迎指正!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章