HashSet集合
存儲自定義對象
HashSet集合的add方法去除重複元素依賴于HashCode()方法和equals()方法,存儲自定義對象的時候需要重寫這兩個方法。
String類型中底層已經重寫了equals()方法是以不用重寫。
package Set集合;
import java.util.HashSet;
import java.util.Set;
class Student {
private String name;
private int age;
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
// HashSet集合的add方法依賴于HashCode()方法和equals()方法
// 存儲自定義對象的時候需要重寫這兩個方法
// String類型中底層已經重寫了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;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "學生 [姓名=" + name + ", 年齡=" + age + "]";
}
}
public class SetTest {
public static void main(String[] args) {
Set<Student> s = new HashSet<Student>();
//建立學生類對象
Student s1 = new Student("張三", 21);
Student s2 = new Student("張三", 21);
//同名年齡不同屬于兩個人
Student s3 = new Student("張三", 25);
Student s4 = new Student("李四", 22);
Student s5 = new Student("王五", 22);
Student s6 = new Student("王五", 22);
Student s7 = new Student("王五", 22);
//添加到集合中
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
s.add(s6);
s.add(s7);
//周遊
for (Student stu : s) {
System.out.println(stu.toString());
}
}
}
/**
學生 [姓名=李四, 年齡=22]
學生 [姓名=張三, 年齡=25]
學生 [姓名=王五, 年齡=22]
學生 [姓名=張三, 年齡=21]
*/
可以發現輸出結果中除了排除了相同的實體外,順序也變化了。
LinkedHashSet
HashSet的子類,在HashSet的基礎上保證了元素的有序性。
- LinkedHashSet底層是一種連結清單和哈希表組成
- 可以保證元素的唯一性,是由哈希表決定的(hashCode()和equals())
- 可以保證元素的疊代順序一緻(有序),存儲和取出一緻,是由連結清單決定
import java.util.LinkedHashSet;
import java.util.Set;
class Student {
private String name;
private int age;
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@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;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "學生 [姓名=" + name + ", 年齡=" + age + "]";
}
}
public class SetTest {
public static void main(String[] args) {
//使用LinkedHashSet保證有序性
Set<Student> s = new LinkedHashSet<Student>();
//建立學生類對象
Student s1 = new Student("張三", 21);
Student s2 = new Student("張三", 21);
//同名年齡不同屬于兩個人
Student s3 = new Student("張三", 25);
Student s4 = new Student("李四", 22);
Student s5 = new Student("王五", 22);
Student s6 = new Student("王五", 22);
Student s7 = new Student("王五", 22);
//添加到集合中
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
s.add(s6);
s.add(s7);
//周遊
for (Student stu : s) {
System.out.println(stu.toString());
}
}
}
/**
學生 [姓名=張三, 年齡=21]
學生 [姓名=張三, 年齡=25]
學生 [姓名=李四, 年齡=22]
學生 [姓名=王五, 年齡=22]
*/
可以看到使用LinkedHashSet集合存儲不光可以去除重複元素還保證了和添加時的順序一緻。
TreeSet集合
是通過自然順序對集合中的元素排序,在Set集合元素的唯一性的前提下對元素進行排序。
TreeSet集合依賴于TreeMap紅黑樹結構實作,将存儲進集合的第一個元素作為根節點,以後每存儲一個元素都要依次和樹結構每一層的元素進行比較,以此來實作元素的排序。
import java.util.TreeSet;
public class TreeSetTese {
public static void main(String[] args) {
TreeSet<Integer> tr = new TreeSet<Integer>();
tr.add(11);
tr.add(5);
tr.add(1);
tr.add(8);
tr.add(3);
tr.add(9);
tr.add(10);
for (Integer inte : tr) {
System.out.print(inte + ",");// 1,3,5,8,9,10,11,
}
}
}
TreeSet集合存儲自定義對象
TrssSet集合底層依賴于compareTo方法來比較元素,傳回值為0的時候判定元素重複。當存儲自定義類的時候自定義類需要實作Comparable接口中的compareTo方法來給TrssSet集合提供比較對象的規則。
import java.util.TreeSet;
class Student implements Comparable<Student> {
// 自定義對象類需要實作Comparable接口重寫compareTo方法
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
// TreeSet排序必須按照一個規則,存儲自定義對象的時候需要重寫compareTo方法
@Override
public int compareTo(Student o) {
// 按年齡排序學生
int num = this.age - o.age;
// 為負數則說明目前對象比要比較的o對象小
// 為正數則說明目前對象比要比較的o對象大
// 為0則說明年齡相同,則按名字排序
int num2 = num == 0 ? this.name.compareTo(o.name) : num;
// 如果均為0說明兩個元素相同,則舍去重複元素
return num2;
}
@Override
public String toString() {
return "姓名:" + name + "\t年齡:" + age;
}
}
public class TreeSetTese {
public static void main(String[] args) {
TreeSet<Student> tr = new TreeSet<Student>();
Student s1 = new Student("zhangsan", 21);
Student s2 = new Student("lishi", 20);
Student s3 = new Student("zhangsan", 21);
Student s4 = new Student("wangwu", 20);
Student s5 = new Student("zhaoliu", 22);
Student s6 = new Student("zhaoliu", 25);
Student s7 = new Student("zhaoliu", 25);
tr.add(s1);
tr.add(s2);
tr.add(s3);
tr.add(s4);
tr.add(s5);
tr.add(s6);
tr.add(s7);
for (Student stu : tr) {
System.out.println(stu);
}
}
}
/**
姓名:lishi 年齡:20
姓名:wangwu 年齡:20
姓名:zhangsan 年齡:21
姓名:zhaoliu 年齡:22
姓名:zhaoliu 年齡:25
*/
匿名内部類實作方式
實際開發中多使用匿名内部類的方式去重寫compareTo
實作一個按姓名長度排序,長度一樣按年齡排序:
import java.util.Comparator;
import java.util.TreeSet;
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:" + name + "\t年齡:" + age;
}
}
public class TreeSetTese {
public static void main(String[] args) {
TreeSet<Student> tr = new TreeSet<Student>(new Comparator<Student>() {
//匿名内部類
@Override
public int compare(Student s1, Student s2) {
//s1相當于目前元素
//s2相當于比較的元素
//按長度比較
int num = s1.getName().length()-s2.getName().length();
//長度一樣按年齡比較
int num2=num==0?s1.getAge()-s2.getAge() :num;
return num2;
}
});
Student s1 = new Student("zhangsan", 21);
Student s2 = new Student("lishi", 20);
Student s3 = new Student("zhangsan", 21);//重複元素會被舍棄
Student s4 = new Student("wangwu", 20);
Student s5 = new Student("zhaoliu", 22);
Student s6 = new Student("zhaoliu", 25);
Student s7 = new Student("zhaoliu", 26);
Student s8 = new Student("lishi", 21);
Student s9 = new Student("zhangsan", 22);
tr.add(s1);
tr.add(s2);
tr.add(s3);
tr.add(s4);
tr.add(s5);
tr.add(s6);
tr.add(s7);
tr.add(s8);
tr.add(s9);
for (Student stu : tr) {
System.out.println(stu);
}
}
}
/**
姓名:lishi 年齡:20
姓名:lishi 年齡:21
姓名:wangwu 年齡:20
姓名:zhaoliu 年齡:22
姓名:zhaoliu 年齡:25
姓名:zhaoliu 年齡:26
姓名:zhangsan 年齡:21
姓名:zhangsan 年齡:22
*/