1. 程式人生 > 實用技巧 >vue 中使用 webSocket 收發資料

vue 中使用 webSocket 收發資料

Set介面

Set介面中沒有定義額外的新的方法,使用的都是Collection中宣告的方法

儲存資料特點

無序的,不可重複的資料

  • 無序性

    • 不等於隨機性
    • 以HashSet為例說明
      • 儲存的資料在底層陣列中並非按照陣列索引的順序進行新增,而是根據資料的雜湊值決定的
  • 不可重複性

    • 保證新增的元素按照equals()判斷時,不能返回true,即相同的元素只能新增一個

要求

  1. 向Set中新增資料,其所在的類一定要重寫hashCode()和equals()方法,兩個方法可以自動生成

    (如果沒有重寫hashCode()方法,相當於系統隨機安排一個數字給該元素的hash值,即使兩個元素相同,但是他們的hash值不同,還是會新增到陣列中。重寫hashCode(),兩個元素的hash值根據同一個邏輯算出)

  2. 重寫的hashCode()和equals()方法儘可能保持一致性

  3. 相等的物件必須具有相等的雜湊碼(雜湊值)

自動生成的hashCode()方法中會出現31這個係數的原因

  • 選擇係數的時候儘量選擇大的係數,計算出的hash值越大,“衝突”就越少,查詢起來效率也會提高
  • 31佔用5bits,相乘造成的資料溢位的概率較小
  • 31是個素數,素數本身只能被本身和1整除,可以減少衝突

HashSet(主要實現類)

新增元素的過程

(hashSet底層是一個數組,長度為16)

圖解



過程

底層:陣列 + 連結串列

  1. 向HashSet中新增元素a,首先呼叫元素a所在類的hashCode()方法,計算元素a的雜湊值
  2. 此雜湊值接著通過某種演算法計算出在HashSet底層陣列中的存放位置(即為索引位置)
  3. 判斷陣列此位置上是否已有元素
    • 如果此位置沒有其他元素,則元素a新增成功

    • 如果此位置上有其他元素b(或以連結串列形式存在的多個元素),則比較a與元素b的雜湊值

      (存放位置相同的兩個元素雜湊值不一定相同)

      • 如果hash值不相同,則元素新增成功
      • 如果hash值相同,進而呼叫元素a所在的equals()方法
        • equals()返回true,元素a新增失敗
        • equals()返回false,元素a新增成功

說明

兩個元素的hash值不同或者equals返回false時,元素a與已經存在指定索引位置上的資料以連結串列的方式儲存

  • jdk7:元素a放到陣列中,指向原來的元素
  • jdk8:原來的元素在陣列中,指向元素a
  • 總結:七是頭插法,八是尾插法(七上八下)

LinkedHashSet

  • HashSet的子類
  • 遍歷其內部資料是可以按照新增的順序去遍歷

注意:即使遍歷出的資料順序是按照新增順序顯示的,但是LinkedHashHashSet中的資料特點依舊是無序的,不可重複的

新增元素的過程

  • 在新增資料的同時,每個資料還維護了兩個引用,記錄此資料前一個數據和後一個數據的地址值
  • 優點:對於頻繁的遍歷操作,使用LinkedHashSet效率高於HashSet

TreeSet

  • 要求放入的資料屬於同一個類的物件
  • 可以按照新增物件的指定屬性,進行排序
  • 會使用到Comparable和Comparator兩個排序介面
  • 底層採用紅黑樹儲存結構(小放左,大放右),其特點是有序,查詢速度比List快

注意:向TreeSet中新增的資料,要求是相同類的物件

自定義類兩種排序方式(Java比較器)

https://www.cnblogs.com/CrabDumplings/p/13339146.html

自然排序(實現Comparable介面)

比較兩個函式是否相同的標準為compareTo()方法返回0,不再是equals()方法

程式碼實現
  • 普通情況,按照名字進行排序
//Students類中的compareTo方法,按照名字進行排序
public int compareTo(Object o) {
        if(o instanceof Students){
            Students s = (Students)o;
            return this.name.compareTo(s.name);
        }else{
            throw new RuntimeException("傳入資料型別不一致");
        }

    }

//測試函式
public void test13(){
        TreeSet set = new TreeSet();

        set.add(new Students("Tom",18,90));
        set.add(new Students("Ann",19,75));
        set.add(new Students("Lisa",20,86));
        set.add(new Students("Jack",21,50));
        set.add(new Students("Jerry",19,60));

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

執行結果

  • 排序的資訊有相同的情況(名字相同,其他資訊不相同)

    利用二次排序

    按照名字進行比較,如果名字相同,在compareTo中比較返回值為0(TreeSet中判斷是否相同的標準不再是equals,而是compareTo)

//姓名從小到大排列,姓名相同的年齡從小到大排列
    @Override
    public int compareTo(Object o) {
        if(o instanceof Students){
            Students s = (Students)o;
//            return this.name.compareTo(s.name);
            int compare = this.name.compareTo(s.name);
            //姓名不一樣
            if(compare != 0){
                return compare;
            }else {
                //姓名一樣
                return Integer.compare(this.age,s.age);
            }
        }else{
            throw new RuntimeException("傳入資料型別不一致");
        }

    @Test
    public void test13(){
        TreeSet set = new TreeSet();

        set.add(new Students("Tom",18,90));
        set.add(new Students("Ann",19,75));
        set.add(new Students("Lisa",20,86));
        set.add(new Students("Jack",21,50));
        set.add(new Students("Jerry",19,60));
        set.add(new Students("Jerry",22,70));

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

執行結果

定製排序(實現Comparator介面)

在定製排序中,比較兩個物件是否相同的標準為compare(),是否返回0,不再是equals()方法

TreeSet set = new TreeSet();

構造器沒有引數的時候直接為自然排序

TreeSet set = new TreeSet(com);

構造器有蠶食的時候,按照com的定製排序進行排序

程式碼實現
  • 普通情況,按照年齡進行排序
//年齡從小到大進行排序
public void test14(){
        Comparator com = new Comparator() {
            //按照年齡從小到大排列
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Students || o2 instanceof Students){
                    Students s1 = (Students)o1;
                    Students s2 = (Students)o2;
                    return Integer.compare(s1.getAge(),s2.getAge());
                }else{
                    throw new RuntimeException("傳入資料型別不一致");
                }
            }
        };
        TreeSet set = new TreeSet(com);
        set.add(new Students("Tom",18,90));
        set.add(new Students("Ann",19,75));
        set.add(new Students("Lisa",20,86));
        set.add(new Students("Jack",21,50));
        set.add(new Students("Jerry",19,60));
        set.add(new Students("Jerry",22,70));

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

執行結果

  • 排序的資訊有相同的情況(年齡相同,其他資訊不相同)
public void test14(){
        Comparator com = new Comparator() {
            //按照年齡從小到大排列
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Students || o2 instanceof Students){
                    Students s1 = (Students)o1;
                    Students s2 = (Students)o2;
//                    return Integer.compare(s1.getAge(),s2.getAge());
                    int compare = Integer.compare(s1.getAge(), s2.getAge());
                    if(compare != 0){
                        return Integer.compare(s1.getAge(),s2.getAge());
                    }else{
                        return s1.getName().compareTo(s2.getName());
                    }
                }else{
                    throw new RuntimeException("傳入資料型別不一致");
                }
            }
        };
        TreeSet set = new TreeSet(com);
        set.add(new Students("Tom",18,90));
        set.add(new Students("Ann",19,75));
        set.add(new Students("Lisa",20,86));
        set.add(new Students("Jack",21,50));
        set.add(new Students("Jerry",19,60));
        set.add(new Students("Jerry",22,70));

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

執行截圖