day17-集合框架(HashSet/TreeSet)

17.01_HashSet存儲(chǔ)字符串并遍歷

  • A:Set集合概述及特點(diǎn)
    public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, Serializable
// Set集合妄呕,無索引,無重復(fù)數(shù)據(jù)卓缰,無序(存儲(chǔ)不一致)
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("a");         //因?yàn)閟et集合不能存儲(chǔ)重復(fù)數(shù)據(jù)攻礼,所以這里存儲(chǔ)失敗当编,返回false
set.add("xxoo");

for (String string : set) {    //迭代享甸,增強(qiáng)for
    System.out.println(string);
}

17.02_HashSet存儲(chǔ)自定義對(duì)象保證元素唯一性

  • 核心:重寫自定義對(duì)象的hashCode()equals()方法
  • 自動(dòng)生成即可。Eclipse自動(dòng)生成hashCode和equals方法
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}
為什么Eclipe自動(dòng)生成hashCode會(huì)選擇31
1.31是一個(gè)質(zhì)數(shù)孔庭,質(zhì)數(shù)能被1和自身整除尺上,減少重復(fù)性
2.31這個(gè)數(shù)不大也不小
3.31這個(gè)數(shù)好算,2的五次方-1,2向左移動(dòng)5次減1

17.04_HashSet如何保證元素唯一性的原理

  • 1.HashSet原理
    • 我們使用Set集合都是需要去掉重復(fù)元素的, 如果在存儲(chǔ)的時(shí)候逐個(gè)equals()比較, 效率較低,哈希算法提高了去重復(fù)的效率, 降低了使用equals()方法的次數(shù)
    • 當(dāng)HashSet調(diào)用add()方法存儲(chǔ)對(duì)象的時(shí)候, 先調(diào)用對(duì)象的hashCode()方法得到一個(gè)哈希值, 然后在集合中查找是否有哈希值相同的對(duì)象
      • 如果沒有哈希值相同的對(duì)象就直接存入集合
      • 如果有哈希值相同的對(duì)象, 就和哈希值相同的對(duì)象逐個(gè)進(jìn)行equals()比較,比較結(jié)果為false就存入, true則不存
  • 2.將自定義類的對(duì)象存入HashSet去重復(fù)
    • 類中必須重寫hashCode()equals()方法
    • hashCode(): 屬性相同的對(duì)象返回值必須相同, 屬性不同的返回值盡量不同(提高效率)
    • equals(): 屬性相同返回true, 屬性不同返回false,返回false的時(shí)候存儲(chǔ)

17.05_LinkedHashSet的概述和使用

//LinkedHashSet 底層是鏈表實(shí)現(xiàn)的圆到,是Set集合中唯一一個(gè)能保證怎么存就怎么取的集合對(duì)象
//雖然存順序和取順序是一樣的怎抛, 但是并沒有索引
//因?yàn)镠ashSet的子類,所以也能保證元素是唯一的
LinkedHashSet<String> link = new LinkedHashSet<>();
link.add("a");
link.add("a");
link.add("b");
System.out.println(link);    // [a,b]

17.06_產(chǎn)生10個(gè)1-20之間的隨機(jī)數(shù)要求隨機(jī)數(shù)不能重復(fù)

需求:編寫一個(gè)程序芽淡,獲取10個(gè)1至20的隨機(jī)數(shù)马绝,要求隨機(jī)數(shù)不能重復(fù)。并把最終的隨機(jī)數(shù)輸出到控制臺(tái)挣菲。

HashSet<Integer> set = new HashSet<>();
Random random = new Random();
while (10 > set.size()) {
    set.add(random.nextInt(20) + 1);  //注意這里的隨機(jī)數(shù)方法富稻, +1是因?yàn)殡S機(jī)數(shù)方法是前閉后開的
}
System.out.println(set);    //這里也可以使用foreach循環(huán)輸出

17.07_集合框架(練習(xí))

  • 使用Scanner從鍵盤讀取一行輸入,去掉其中重復(fù)字符, 打印出不同的那些字符
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
sc.close();
char[] arr = str.toCharArray();     //將字符串轉(zhuǎn)換成字符數(shù)組
LinkedHashSet<Character> set = new LinkedHashSet<>();  //創(chuàng)建LinkedHashSet集合對(duì)象(為了跟輸入順序一致)
for (char c : arr) {
    set.add(c);
}
System.out.println(set);   //輸入xxoo123,輸出[x,o,1,2,3]

17.08_集合框架(練習(xí))

// 將集合中的重復(fù)元素去掉
public static void getSingle(List<String> list) {
     LinkedHashSet<String> lhs = new LinkedHashSet<>();
     lhs.addAll(list);    //將list集合中的所有元素添加到lhs
     list.clear();       //清空原集合
     list.addAll(lhs);   //將去除重復(fù)的元素添回到list中
}

17.09_TreeSet存儲(chǔ)Integer類型的元素并遍歷

// 1.TreeSet能保證數(shù)據(jù)唯一白胀,2.TreeSet是用來對(duì)元素排序的
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(2);
ts.add(2);
ts.add(1);
System.out.println(ts);   //輸出 [1, 2, 3]

17.10_TreeSet存儲(chǔ)自定義對(duì)象

TreeSet<Person> ts = new TreeSet<>();
ts.add(new Person("我日", 20));
ts.add(new Person("我2", 22));
ts.add(new Person("我xo", 80));

System.out.println(ts);

// 1. 直接存儲(chǔ)椭赋,會(huì)運(yùn)行報(bào)錯(cuò)
// 2. 想要不報(bào)錯(cuò),Person類必須實(shí)現(xiàn)Comparable<T>接口
// 3.Comparable<T>接口的規(guī)律如下:
@Override
public int compareTo(Person o) {
     //當(dāng)compareTo方法返回0 纹笼,集合只有一個(gè)元素
     //當(dāng)compareTo方法返回正數(shù)纹份,集合怎么存苟跪,就怎么取
     //當(dāng)compareTo方法返回負(fù)數(shù)廷痘,集合就會(huì)倒序
     int num = this.age - o.age ;  //年齡為主要條件,年齡一樣比較姓名
     return num == 0 ? this.name.compareTo(o.name) : num;
}

17.11_TreeSet保證元素唯一和自然排序的原理和圖解

TreeSet.png

17.12_TreeSet存儲(chǔ)自定義對(duì)象并遍歷練習(xí)1

TreeSet存儲(chǔ)自定義對(duì)象并遍歷練習(xí)1(按照姓名排序)
關(guān)鍵-->Person的compareTo方法
public int compareTo(Person o) {
     int num = this.name.compareTo(o.name);  //姓名是主要條件 
     return num == 0 ? this.age - o.age : num; //年齡是次要條件
}

// 字符串的比較件已,是比較字符串每個(gè)字符的Unicode值

17.14_TreeSet保證元素唯一和比較器排序的原理及代碼實(shí)現(xiàn)

//匿名類 實(shí)現(xiàn)構(gòu)造器
Comparator<String> com = new Comparator<String>() {
     @Override
     public int compare(String o1, String o2) {
          // 安裝字符串長(zhǎng)度比較
          int num = o1.length() - o2.length();
          return num == 0 ? o1.compareTo(o2) : num; //長(zhǎng)度相同比較內(nèi)容
     }
};

// 比較器排序  TreeSet有個(gè)傳入構(gòu)造器的構(gòu)造方法
TreeSet<String> ts = new TreeSet<>(com);
ts.add("aabbcc");
ts.add("0125");
ts.add("c");
System.out.println(ts);

17.15_TreeSet原理

  • TreeSet是用來排序的, 可以指定一個(gè)順序, 對(duì)象存入之后會(huì)按照指定的順序排列
  • a.自然順序(Comparable)
- TreeSet類的add()方法中會(huì)把存入的對(duì)象提升為Comparable類型
- 調(diào)用對(duì)象的compareTo()方法和集合中的對(duì)象比較
- 根據(jù)compareTo()方法返回的結(jié)果進(jìn)行存儲(chǔ)
  • b.比較器順序(Comparator)
- 創(chuàng)建TreeSet的時(shí)候可以制定 一個(gè)Comparator
- 如果傳入了Comparator的子類對(duì)象, 那么TreeSet就會(huì)按照比較器中的順序排序
- add()方法內(nèi)部會(huì)自動(dòng)調(diào)用Comparator接口中compare()方法排序
- 調(diào)用的對(duì)象是compare方法的第一個(gè)參數(shù),集合中的對(duì)象是compare方法的第二個(gè)參數(shù)
  • c.兩種方式的區(qū)別
- TreeSet構(gòu)造函數(shù)什么都不傳, 默認(rèn)按照類中Comparable的順序(沒有就報(bào)錯(cuò)ClassCastException)
- TreeSet如果傳入Comparator, 就優(yōu)先按照Comparator

17.16_集合框架(練習(xí)一)

  • 在一個(gè)集合中存儲(chǔ)了無序并且重復(fù)的字符串,定義一個(gè)方法,讓其有序(字典順序),而且還不能去除重復(fù)
ArrayList<String> list = new ArrayList<>();
list.add("ccc");
list.add("ccc");
list.add("aaa");
list.add("aaa");
list.add("bbb");
list.add("ddd");
list.add("ddd");

Comparator<String> com = new Comparator<String>() {  //匿名構(gòu)造器
     @Override
     public int compare(String s1, String s2) {
          int num = s1.compareTo(s2);
          return num == 0 ? 1 : num;  //如果內(nèi)容一樣返回一個(gè)不為0的數(shù)字即可
     }
};

TreeSet<String> set = new TreeSet<>(com);
set.addAll(list);  //講ArrayList的元素笋额,一次性添加到TreeSet里面

list.clear();  //清空原來的ArrayList
list.addAll(set); //再將排序后的添加來
System.out.println(list);

17.17_集合框架(練習(xí)二)

  • 從鍵盤接收一個(gè)字符串, 程序?qū)ζ渲兴凶址M(jìn)行排序,例如鍵盤輸入: helloitcast程序打印:acehillostt
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
sc.close();
char[] arr = str.toCharArray();  //轉(zhuǎn)為char[]數(shù)組

// 方法一
Arrays.sort(arr);           // Arrays排序
System.out.println(arr);    // 搞定

// 方法二 (使用TreeSet)
Comparator<Character> com = new Comparator<Character>() {
     @Override
     public int compare(Character c1, Character c2) {
          int temp = c1 - c2;     //自動(dòng)拆箱
          return temp == 0 ? 1 : temp;
     }
};

TreeSet<Character> set = new TreeSet<>(com);
for (Character ch : arr) {  //其實(shí)這里Character和char都可以,自動(dòng)裝箱
     set.add(ch);
}
str = "";
for (Character character : set) {   //轉(zhuǎn)字符串
     str += character;
}
System.out.println(str);

17.18_集合框架(練習(xí)三)

  • 程序啟動(dòng)后, 可以從鍵盤輸入接收多個(gè)整數(shù), 直到輸入quit時(shí)結(jié)束輸入. 把所有輸入的整數(shù)倒序排列打印.
Scanner sc = new Scanner(System.in);

TreeSet<Integer> set = new TreeSet<>(new Comparator<Integer>() { //匿名類
     @Override 
     public int compare(Integer t1, Integer t2) {
          int num = t2 - t1 ;  //自動(dòng)拆箱   使用t2.compareTo(t1)也可以
          return num == 0 ? 1 : num;
     }
});

while (true) {
     String str = sc.nextLine();
     //如果字符串常量和變量比較,常量放前面,這樣不會(huì)出現(xiàn)空指針異常,變量里面可能存儲(chǔ)null
     if ("quit".equals(str)) break; 
     set.add(Integer.valueOf(str));  //兩個(gè)方法都可以:Integer.parseInt(str);
     // 其實(shí)這里應(yīng)該加異常處理篷扩,后面會(huì)異常再講
}

sc.close();
System.out.println(set);

17.19_鍵盤錄入學(xué)生信息按照總分排序后輸出在控制臺(tái)

  • 需求:鍵盤錄入5個(gè)學(xué)生信息(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)),按照總分從高到低輸出到控制臺(tái)兄猩。
Scanner sc = new Scanner(System.in);
System.out.println("請(qǐng)輸入5個(gè)學(xué)生成績(jī)格式是:(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī))");
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
     @Override
     public int compare(Student s1, Student s2) {
          int num = s2.getSum() - s1.getSum();  //根據(jù)學(xué)生的總成績(jī)降序排列
          return num == 0 ? 1 : num;
     }
});

while(ts.size() < 5) {
     String line = sc.nextLine();
     try {
          String[] arr = line.split(",");  //分割字符串,方法需要記住枢冤!
          int chinese = Integer.parseInt(arr[1]);                //轉(zhuǎn)換語(yǔ)文成績(jī)
          int math = Integer.parseInt(arr[2]);                   //轉(zhuǎn)換數(shù)學(xué)成績(jī)
          int english = Integer.parseInt(arr[3]);                //轉(zhuǎn)換英語(yǔ)成績(jī)
          ts.add(new Student(arr[0], chinese, math, english));
     } catch (Exception e) {
          System.out.println("錄入格式有誤,輸入5個(gè)學(xué)生成績(jī)格式是:(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)");
     }
}
sc.close();
System.out.println(ts);

17.20_day17總結(jié)

  • 1.List 集合遍歷方法:
    • a.普通for循環(huán), 使用get()逐個(gè)獲取元素
    • b.調(diào)用iterator()方法得到Iterator, 使用hasNext()next()方法
    • c.增強(qiáng)for循環(huán), 只要可以使用Iterator的類都可以用
    • d.Vector集合可以使用EnumerationhasMoreElements()nextElement()方法
  • 2.Set集合遍歷方法
    • a.調(diào)用iterator()方法得到Iterator, 使用hasNext()next()方法
    • b.增強(qiáng)for循環(huán), 只要可以使用Iterator的類都可以用
  • 3.普通for循環(huán),迭代器,增強(qiáng)for循環(huán)是否可以在遍歷的過程中刪除
    • 普通for循環(huán) --> 能 --> i(索引)需要--
    • 迭代器 --> 能鸠姨,但是需要使用迭代器的刪除方法
    • 增強(qiáng)for循環(huán) --> 不能

END。
我是小侯爺淹真。
在魔都艱苦奮斗炼吴,白天是上班族臊诊,晚上是知識(shí)服務(wù)工作者。
如果讀完覺得有收獲的話,記得關(guān)注和點(diǎn)贊哦署咽。
非要打賞的話,我也是不會(huì)拒絕的饺律。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炭序,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子徙鱼,更是在濱河造成了極大的恐慌宅楞,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袱吆,死亡現(xiàn)場(chǎng)離奇詭異咱筛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)杆故,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門迅箩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人处铛,你說我怎么就攤上這事饲趋。” “怎么了撤蟆?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵奕塑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我家肯,道長(zhǎng)龄砰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任讨衣,我火速辦了婚禮换棚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘反镇。我一直安慰自己固蚤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布歹茶。 她就那樣靜靜地躺著夕玩,像睡著了一般你弦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上燎孟,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天禽作,我揣著相機(jī)與錄音,去河邊找鬼揩页。 笑死领迈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碍沐。 我是一名探鬼主播狸捅,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼累提!你這毒婦竟也來了尘喝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤斋陪,失蹤者是張志新(化名)和其女友劉穎朽褪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體无虚,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缔赠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了友题。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤堰。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖度宦,靈堂內(nèi)的尸體忽然破棺而出踢匣,到底是詐尸還是另有隱情,我是刑警寧澤戈抄,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布离唬,位于F島的核電站,受9級(jí)特大地震影響划鸽,放射性物質(zhì)發(fā)生泄漏输莺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一裸诽、第九天 我趴在偏房一處隱蔽的房頂上張望嫂用。 院中可真熱鬧,春花似錦崭捍、人聲如沸尸折。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)实夹。三九已至,卻和暖如春粒梦,著一層夾襖步出監(jiān)牢的瞬間亮航,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來泰國(guó)打工匀们, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缴淋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓泄朴,卻偏偏與公主長(zhǎng)得像重抖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祖灰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法钟沛,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法局扶,繼承相關(guān)的語(yǔ)法恨统,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,669評(píng)論 18 399
  • 上一篇文章介紹了Set集合的通用知識(shí)三妈。Set集合中包含了三個(gè)比較重要的實(shí)現(xiàn)類:HashSet畜埋、TreeSet和En...
    Ruheng閱讀 15,653評(píng)論 3 57
  • 3.3 集合 一方面, 面向?qū)ο笳Z(yǔ)言對(duì)事物的體現(xiàn)都是以對(duì)象的形式畴蒲,為了方便對(duì)多個(gè)對(duì)象的操作悠鞍,就要對(duì)對(duì)象進(jìn)行存儲(chǔ)。另...
    閆子揚(yáng)閱讀 735評(píng)論 0 1
  • Java8張圖 11模燥、字符串不變性 12狞玛、equals()方法、hashCode()方法的區(qū)別 13涧窒、...
    Miley_MOJIE閱讀 3,710評(píng)論 0 11
  • 愛攝影的你心肪,有沒有想過再現(xiàn)經(jīng)典畫面,拍出充滿電影代入感的照片?一張照片就可以講述一個(gè)故事纠吴,一個(gè)普通物件就能變出神秘...
    ElanLive閱讀 7,186評(píng)論 0 0