vue 中使用 webSocket 收發資料
Set介面
Set介面中沒有定義額外的新的方法,使用的都是Collection中宣告的方法
儲存資料特點
無序的,不可重複的資料
-
無序性
- 不等於隨機性
- 以HashSet為例說明
- 儲存的資料在底層陣列中並非按照陣列索引的順序進行新增,而是根據資料的雜湊值決定的
-
不可重複性
- 保證新增的元素按照equals()判斷時,不能返回true,即相同的元素只能新增一個
要求
-
向Set中新增資料,其所在的類一定要重寫hashCode()和equals()方法,兩個方法可以自動生成
(如果沒有重寫hashCode()方法,相當於系統隨機安排一個數字給該元素的hash值,即使兩個元素相同,但是他們的hash值不同,還是會新增到陣列中。重寫hashCode(),兩個元素的hash值根據同一個邏輯算出)
-
重寫的hashCode()和equals()方法儘可能保持一致性
-
相等的物件必須具有相等的雜湊碼(雜湊值)
自動生成的hashCode()方法中會出現31這個係數的原因
- 選擇係數的時候儘量選擇大的係數,計算出的hash值越大,“衝突”就越少,查詢起來效率也會提高
- 31佔用5bits,相乘造成的資料溢位的概率較小
- 31是個素數,素數本身只能被本身和1整除,可以減少衝突
HashSet(主要實現類)
新增元素的過程
(hashSet底層是一個數組,長度為16)
圖解
過程
底層:陣列 + 連結串列
- 向HashSet中新增元素a,首先呼叫元素a所在類的hashCode()方法,計算元素a的雜湊值
- 此雜湊值接著通過某種演算法計算出在HashSet底層陣列中的存放位置(即為索引位置)
- 判斷陣列此位置上是否已有元素
-
如果此位置沒有其他元素,則元素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());
}
}
執行截圖