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
則不存
- 我們使用Set集合都是需要去掉重復(fù)元素的, 如果在存儲(chǔ)的時(shí)候逐個(gè)
- 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
集合可以使用Enumeration
的hasMoreElements()
和nextElement()
方法
- a.普通for循環(huán), 使用
- 2.Set集合遍歷方法
- a.調(diào)用
iterator()
方法得到Iterator
, 使用hasNext()
和next()
方法 - b.增強(qiáng)for循環(huán), 只要可以使用
Iterator
的類都可以用
- a.調(diào)用
- 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ì)拒絕的饺律。