interface List:儲存有序的、可重複的資料 => “動態"陣列,替換原有的陣列
interface Set:儲存無序的、不可重複的資料
HashSet 新增元素的過程: 我們向 HashSet 中新增元素a,首先調用元素a的 hashCode(),計算元素a的哈希值,以此哈希值計算出在 HashSet 底層陣列中的存放位置(即為:索引位置),判斷陣列此索引位置上是否有元素:
若此位置上沒有其他元素,則元素a新增成功 => 情況1
若此位置上有其他元素b(或以鏈結串列形式存在多個元素),則比較元素a與元素b的哈希值
若哈希值不相同,則元素a新增成功 => 情況2
若哈希值相同,進而需要調用元素a所在類別的 equals()
equals() 回傳true,元素a新增失敗
equals() 回傳false,元素a新增成功 => 情況3
HashSet 底層結構: 陣列 + 鏈結串列
要求向 Set 新增元素時,其元素所在的類別一定要 override hashCode() 與 equals()
要求 override 的 hashCode() 與 equals() 盡可能保持一致性:相同物件元素必須具有相同的散列碼
TreeSet:可以按照新增元素的指定屬性
進行排序
/**
* @author sunwc
* @create 2023-03-28 下午 09:31
*/
public class TreeSetTest {
/**
* 自然排序
*/
@Test
public void treeSetTest() {
TreeSet treeSet = new TreeSet();
treeSet.add(new User("Flask", 33));
treeSet.add(new User("Ice", 18));
treeSet.add(new User("Gary", 54));
treeSet.add(new User("Tim", 26));
treeSet.add(new User("Daniel", 40));
treeSet.add(new User("Daniel", 37));
System.out.println(treeSet.size());
// 在建立多個User物件、放入TreeSet中後,卻拋出以下例外
// java.lang.ClassCastException: com.atguigu.java.User cannot be cast to java.lang.Comparable
// 因為TreeSet的特性會針對指定元素屬性進行比較,而自定義類別要有比較的功能就必須實現 interface Comparable - compareTo()
// 另外,若比較User的姓名若有重複,就要在compareTo()中定義要如何比較另一個屬性,
// 否則TreeSet就會認定只要新增的元素去調用compareTo()回傳的值為0時,就代表該元素是重複的而造成新增失敗;反之,就可以新增成功
Iterator iterator = treeSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
/**
* 定制排序
*/
@Test
public void treeSetTest2() {
Comparator comparator = new Comparator<User>() {
/**
* 只比較年齡從小到大
* @param o1
* @param o2
* @return
*/
@Override
public int compare(User o1, User o2) {
return Integer.compare(o1.getAge(), o2.getAge());
}
};
TreeSet treeSet = new TreeSet(comparator);
treeSet.add(new User("Flask", 33));
treeSet.add(new User("Ice", 18));
treeSet.add(new User("Gary", 54));
treeSet.add(new User("Tim", 26));
treeSet.add(new User("Daniel", 26));
treeSet.add(new User("Daniel", 37));
Iterator iterator = treeSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class User implements Comparable<User> {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
/**
* 排序規則
* 姓名從大到小排
* 年齡從小到大排
* @param o
* @return
*/
@Override
public int compareTo(User o) {
int compareNameVal = -this.name.compareTo(o.name);
// 姓名不一樣就直接回傳compareNameVal
if (compareNameVal != 0) {
return compareNameVal;
} else {
// 姓名一樣就還要再比較年齡
return Integer.compare(this.age, o.age);
}
}
}
TreeSet 自然排序 輸出結果:
6
User{name='Tim', age=26}
User{name='Ice', age=18}
User{name='Gary', age=54}
User{name='Flask', age=33}
User{name='Daniel', age=37}
User{name='Daniel', age=40}
TreeSet 定制排序 輸出結果:
User{name='Ice', age=18}
User{name='Tim', age=26}
User{name='Flask', age=33}
User{name='Daniel', age=37}
User{name='Gary', age=54}
@Test
public void test3() {
List list = new ArrayList();
list.add(new Integer(1));
list.add(new Integer(2));
list.add(new Integer(2));
list.add(new Integer(4));
list.add(new Integer(4));
List list1 = removeDuplicate(list);
for (Object o : list1) {
System.out.println(o);
}
}
private List removeDuplicate(List list) {
Set set = new HashSet();
set.addAll(list);
return new ArrayList(set);
}
public class HashSetTest {
@Test
public void test4() {
HashSet set = new HashSet();
Person2 p1 = new Person2(1001, "AA");
Person2 p2 = new Person2(1002, "BB");
set.add(p1);
set.add(p2);
System.out.println(set);
p1.name = "CC";
set.remove(p1); // 以1001, CC 換算hashcode找到的索引位置 沒有值
System.out.println(set);
set.add(new Person2(1001, "CC")); // 同上,1001, CC 換算hashcode找到的索引位置 沒有值,所以這個元素新增成功
System.out.println(set);
set.add(new Person2(1001, "AA")); // 以1001, AA 換算hashcode找到的索引位置 有值 但是 !"CC".equals("AA"),所以這個元素也新增成功
System.out.println(set); // 最後這個set實際會輸出4個元素
}
}
class Person2 {
int id;
String name;
public Person2(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Person2{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person2 person2 = (Person2) o;
return id == person2.id && Objects.equals(name, person2.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}