Java之Set接口、Map接口、異常處理

目錄

一. Set接口

  • 1. HashSet

    • 1.1數(shù)據(jù)結構:哈希表

    • 1.2無序不重復

    • 1.3保證元素的唯一性

  • 2. TreeSet

    • 2.1 數(shù)據(jù)結構:紅黑樹(特殊的二叉查找樹)

    • 2.2 TreeSet集合排序的兩種方式

二. Map接口

  • 1. HashTable

  • 2. HashMap

    • 2.1 使用示例

    • 2.2鍵值對的遍歷

  • 3. TreeMap

三. Java異常處理

  • 1.主要內(nèi)容

  • 2. 自定義異常類

==============================================================

正文

一、Set接口

??Set繼承于Collection接口,是一個不允許出現(xiàn)重復元素,并且無序的集合,使用了默認排序,主要有HashSet和TreeSet兩大實現(xiàn)類。

  • 注意: 無序指的是:元素的存入和取出的順序不一定一致
  • 在判斷重復元素的時候,Set集合會調(diào)用hashCode()和equal()方法來實現(xiàn)。
  • 它沒有提供額外的方法,可以說Set就是一個Collection

set集合添加元素并使用迭代器迭代元素:

public class MyClass {
    public static void main(String[] args) throws IOException {
        //Set 集合存和取的順序不一致
        Set set = new HashSet();
        set.add("唐僧");
        set.add("孫悟空");
        set.add("豬八戒");
        set.add("沙和尚");
        System.out.println(set);
        //[沙和尚, 孫悟空, 豬八戒, 唐僧]

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
}

Set集合框架圖:
Set集合框架

Set常見方法 :

編號 方法 描述
1 add() 添加一個對象到集合中。
2 clear() 從集合中刪除所有對象。
3 contains() 如果指定的對象是集合中的元素,則返回true。
4 isEmpty() 如果集合沒有元素,則返回true。
5 iterator() 返回集合的Iterator對象,該對象可用于檢索對象。
6 remove() 從集合中刪除指定對象。
7 size() 返回集合中的元素數(shù)。

1. HashSet

  • LinkedHashSet會保存插入的順序。

1.1數(shù)據(jù)結構:哈希表

??Hash是一種數(shù)據(jù)結構,用戶查找對象。Hash為每一個對象計算出一個整數(shù),稱為Hash Code(哈希值)。哈希表是按照哈希值來存的。當我們添加元素時,哈希值是一樣的,這時候,會進行是否是同一對象判斷equals,如果不是同一對象,那么會在當前對象下順延(串下來的)。
??HashSet對于判斷元素是否存在以及刪除等操作依賴的方法是元素的hashcode和equals方法

查看哈希值:

       Person xw = new Person();
       System.out.println(xw);
       //swu.gyl.javatest.Person@75b84c92

 //Object 類的 toString 方法返回一個字符串
        //getClass().getName() + '@' + Integer.toHexString(hashCode())
//75b84c92就是哈希值

1.2無序不重復

 public static void main(String[] args) {
        HashSet<String> hs = new HashSet<String>();
        System.out.println(hs.add("java1"));
        System.out.println(hs.add("java1"));
        hs.add("java2");

        Iterator<String> it = hs.iterator();
        while(it.hasNext()){
            System.out.println(hs.add(it.next()));
        }
    }

//哈希值一樣,同一對象。添加失敗。存入和取出順序不一致。

輸出:
輸出

1.3保證元素的唯一性

( 1 ) 如果元素的hashCode值不同,不會調(diào)用equals,添加成功
( 2 ) 如果元素的hashCode值相同,才會判斷equals是否為true,為true添加失敗

舉一個栗子:hashSet存自定義對象Person,當姓名和年齡一致,元素重復。

所以,當我們自定義對象的時候,一般要復寫hashcode和equals方法,因為自定義對象可能要存放到hashSet集合中。還有,復寫hashCode要盡量保證哈希值的唯一性,一般根據(jù)判斷條件生成。

public static void main(String[] args) {
        HashSet<Person> hs = new HashSet<Person>();
        hs.add(new Person("a1", 11));
        hs.add(new Person("a2", 22));
        hs.add(new Person("a3", 33));
        hs.add(new Person("a3", 33));
        Iterator<Person> it = hs.iterator();
        while(it.hasNext()){
            Personperson = (Person)it.next();
            sop(person.getName()+"::"+person.getAge());
        }
        
        //重寫了equals,沒重寫hashcode方法。發(fā)現(xiàn)equals發(fā)現(xiàn)沒被調(diào)用,而且都存入成功。說明計算得到是不同的哈希值。
        // 鑒于需求,我們需要去重寫。說明,我們需要覆蓋hashcode方法,建立自己的哈希值。
        // 哈希值的生成根據(jù)判斷條件
        // 重寫hashcode方法,發(fā)現(xiàn),去重成功了。而且equals方法運行了。
}
class Person{
    private String name;
    private int age;
    public Person(String n,int a){
        this.name = n;
        this.age = a;
    }
    
    public String getName(){
        return this.name;
    }
    
    public int getAge(){
        return this.age;
    }
    
    public boolean equals(Object obj){
        if(!(obj instanceof Person))
            return false;
        Personp = (Person)obj;
        System.out.println(this.name+"...."+this.age);
        return this.name.equals(p.getName()) && this.age == p.getAge();
    }
    
    public int hashCode()
    {
        System.out.println(this.name+"...hashcode");
        //return 60; 會有很多重復比較
        return this.name.hashCode()+this.age*13;
    }

2. TreeSet

??紅-黑樹的數(shù)據(jù)結構,默認對元素進行自然排序,如果在比較的時候兩個對象返回值為0,那么元素重復

2.1 數(shù)據(jù)結構:紅黑樹(特殊的二叉查找樹)

紅黑樹算法的規(guī)則: 左小右大。

2.2 TreeSet集合排序的兩種方式:

  • 方式一: 讓元素自身具備比較性,實現(xiàn)Comparetor<t>接口,并重寫compare方法;
  //    可以排序的集合  
        TreeSet<People> score = new TreeSet<>(new Comparator<People>() {
            @Override
            public int compare(People people, People t1) {
                return people.compareTo(t1);
            }
        });


class People implements Comparable{
    String name;
    int age;

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

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

    }

  
  • 方式二:讓容器自身具備比較性,自定義比較器,實現(xiàn)Comparable接口,覆蓋compareTo 方法。
 TreeSet<People> score = new TreeSet<>((People p1,People p2) -> p1.compareTo(p2));

        People p1 = new People("jack",20);
        People p2 = new People("marry",30);
        People p3 = new People("Tom",25);

        score.add(p1);
        score.add(p2);
        score.add(p3);

        if (p1.hashCode() == p2.hashCode()){
            System.out.println("相同");
        }else{
            System.out.println("不相同");
        }

        System.out.println(score);

        //equals 比較對象內(nèi)部的內(nèi)容
       // 使用的兩個對象必須實現(xiàn) Comparable接口的compareTo方法
       //在compareTo里面實現(xiàn)具體該如何比較

  @Override
    public int compareTo(Object o) {
        // 1.判斷o對象是不是People的一個對象
        if (o instanceof People){
            People o1 = (People)o;
            //自己規(guī)定比較的策略
            if (this.age != o1.age){
                return this.age - o1.age;
            }else {
                //年齡相同的情況下 再比姓名的字母
                return this.name.compareTo(o1.name);
            }
        }else {
            return 0;
        }
    }
}

二、Map接口

??Map是一種依照鍵(key)存儲元素的容器,鍵(key)很像下標,在List中下標是整數(shù)。在Map中鍵(key)可以使任意類型的對象。Map中不能有重復的鍵(Key),每個鍵(key)都有一個對應的值(value)。

  • 一個鍵(key)和它對應的值構成map集合中的一個元素。

  • Map中的元素是兩個對象,一個對象作為鍵,一個對象作為值。鍵不可以重復,但是值可以重復。

  • 將鍵映射到值的對象,一個映射不能包含重復的鍵;每個鍵最多只能映射到一個值。
    [圖片上傳中...(image.png-7df4a3-1566048732614-0)]

Map 接口常用方法:

序號 方法 描述
1 void clear() 從此映射中移除所有映射關系。
2 boolean containsKey(Object k) 如果此映射包含指定鍵的映射關系,則返回 true。
3 boolean containsValue(Object v) 如果此映射將一個或多個鍵映射到指定值,則返回 true。
4 Set entrySet( ) 返回此映射中包含的映射關系的 Set 視圖。
5 boolean equals(Object obj) 比較指定的對象與此映射是否相等。
6 Object get(Object k) 返回指定鍵所映射的值;如果此映射不包含該鍵的映射關系,則返回 null。
7 nt hashCode( ) 返回此映射的哈希碼值。
8 boolean isEmpty( ) 如果此映射未包含鍵-值映射關系,則返回 true。
9 Set keySet( ) 返回此映射中包含的鍵的 Set 視圖。
10 Object put(Object k, Object v) 將指定的值與此映射中的指定鍵關聯(lián)。
11 void putAll(Map m) 從指定映射中將所有映射關系復制到此映射中。
12 Object remove(Object k) 如果存在一個鍵的映射關系,則將其從此映射中移除。
13 int size( ) 返回此映射中的鍵-值映射關系數(shù)。
14 Collection values( ) 返回此映射中包含的值的 Collection 視圖。
image.png

1. HashTable

??底層是哈希表數(shù)據(jù)結構,線程是同步的,不可以存入null鍵,null值。
效率較低,被HashMap 替代。

2. HashMap

??底層是哈希表數(shù)據(jù)結構,線程是不同步的,可以存入null鍵,null值。要保證鍵的唯一性,需要覆蓋hashCode方法,和equals方法。

??它的子類LinkedHashMap,是雙向鏈表來維護key-value對的次序,該鏈表定義了迭代順序,該迭代順序與key-value對的插入順序保持一致。

2.1 使用示例:

        //HashMap 集合 存儲數(shù)據(jù)的特點  鍵key-值value
        //key不能重復 可以是任意的對象類型 通常使用字符串String
        HashMap<String,Integer> score = new HashMap<>();

        //添加對象 鍵值對
        score.put("Chinese",89);
        score.put("Math",95);
        score.put("English",99);

        //更改某個鍵對應的值
        score.put("Chinese",91);

        //獲取鍵值對的個數(shù)
        score.size();

        //獲取所有的key
        System.out.println(score.keySet());

        //獲取所有的值
        System.out.println(score.values());

        //獲取Entry:key-value
        System.out.println(score.entrySet());

        //獲取一個key對應的值
        System.out.println(score.get("English"));

2.2鍵值對的遍歷

  • 方式一:通過遍歷key來得到每一個 key對應的值
        for (String key:score.keySet()){
            //通過key得到值value
            int s = score.get(key);
            System.out.println("key: "+key+" value: "+s);
        }
  • 方式二:通過EntrySet 得到Entry對象的集合
        //一個Entry管理一個鍵值對 getKey getValue
        Set<Map.Entry<String,Integer>> entries = score.entrySet();
        for (Map.Entry entry:entries){
            //得到Entry對應的key
            String key = (String)entry.getKey();

            //獲取Entry對應的值
            Integer value = (Integer) entry.getValue();

            System.out.println("key: "+key+" value: "+value);
        }
  • 方式三:通過values 獲取所有值,不能獲取到key對象
Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "aaaa");
        map.put(2, "bbbb");
        map.put(3, "cccc");
        System.out.println(map);

        // 通過values 獲取所有值,不能獲取到key對象
        // Collection<V> values()
 
        Collection<String> vs = map.values();
        Iterator<String> it = vs.iterator();
        while (it.hasNext()) {
            String value = it.next();
            System.out.println(" value=" + value);
        }

3. TreeMap

??底層是哈希表數(shù)據(jù)結構,線程是不同步的,可以存入null鍵,null值。要保證鍵的唯一性,需要覆蓋hashCode方法,和equals方法。

//主要實現(xiàn)
Set<Entry<Person, String>> entrySet = hm.entrySet();
        Iterator<Entry<Person, String>> it = entrySet.iterator();
        while (it.hasNext()) {
            Entry<Person, String> next = it.next();
            Person key = next.getKey();
            String value = next.getValue();
            System.out.println(key + " = " + value);
        }

 


@Override
    public int hashCode() {
 
        return this.name.hashCode() + age * 37;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Person) {
            Person p = (Person) obj;
            return this.name.equals(p.name) && this.age == p.age;
        } else {
            return false;
        }
    }
 
    @Override
    public String toString() {
 
        return "Person@name:" + this.name + " age:" + this.age;
    }

三、異常處理(點擊了解更多)

??異常處理 ,處理運行過程中出現(xiàn)的不可控的錯誤,使程序更健壯。


image.png

1.主要內(nèi)容

  • 如果需要自己處理異常 就catch
  • 如果有多個異常 可以使用多個catch來捕獲, catch 的順序從小到大
  • 如果異常出現(xiàn) 后面的代碼將不會執(zhí)行
  • finally關鍵字用來創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊。無論是否發(fā)生異常,finally 代碼塊中的代碼總會被執(zhí)行。在 finally 代碼塊中,可以運行清理類型等收尾善后性質(zhì)的語句。
  • 使用throws拋出異常 交給外部處理
public static void test() throws FileNotFoundException,NullPointerException{
        FileReader fr = new FileReader("");
    }
  • 使?throw拋出?個??創(chuàng)建的異常對象
public static void test2() throws IllegalAccessException {
        //自己拋出異常
        if (1 > 2){
            throw new IllegalAccessException();
        }
    }

2. 自定義異常類:能夠??定義輸出內(nèi)容 更快地找到出現(xiàn)問題的位置

 public static void test3() throws GYLException {
        //....
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        StackTraceElement e = stackTrace[2];
        String detail = e.getFileName()+"->"+e.getMethodName()+"->"+e.getLineNumber();
        throw new GYLException("自己的異常類:無所作為"+detail);
    }


//自定義異常
class GYLException extends Exception{
    //1.提供一個無參構造方法
    public GYLException(){

    }

    //2.提供一個有參構造方法 參數(shù)是一個字符串
    public GYLException(String desc){
        super(desc);
    }
}


//捕獲自己的異常
try {
            TException.test3();
        } catch (GYLException e) {
            e.printStackTrace();
        }


// 輸出結果:
// GYLException: 自己的異常類:無所作為Exception1.java->main->74

四、心得體會

??今天學到了很多新知識點,要花更多的時間來消化,加油?。?!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容