java集合框架:List/Set 介面和其子類
阿新 • • 發佈:2020-12-30
目錄
ArrayList
1. List介面
-
java.util.List介面 extends Collecton介面
-
特點:
- 有序的集合
- 有索引,包含了一些帶索引的方法
- 允許儲存重複的元素
-
帶索引的方法(特有)(注意防止索引越界異常)
public void add(int index ,E element)
:將元素新增到指定位置。public E get(int index)
public E remove (int index)
:移除列表中指定的元素,返回的是被移除的元素public E set (int index , E element)
:用指定元素替換集合中指定位置的元素,返回值為更新前的元素。
public class Demo01 { public static void main(String[] args) { //使用多型建立一個集合物件 List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("a"); System.out.println(list);//[a, b, c, d, a] 重寫了toString()方法 // public void add(int index ,E element):將元素新增到指定位置。 list.add(3,"new3"); System.out.println(list);//[a, b, c, new3, d, a] //remove() System.out.println("被移除的元素:"+list.remove(2));//被移除的元素:c System.out.println(list);//[a, b, new3, d, a] //set() System.out.println("被替換的元素:"+list.set(4,"A"));//被替換的元素:a System.out.println(list);//[a, b, new3, d, A] //遍歷三種方式: // 1.普通for迴圈 for (int i=0;i<list.size();i++){ System.out.println(list.get(i)); } // 2.使用迭代器 Iterator<String> it=list.iterator(); while (it.hasNext()){ System.out.println(it.next()); } //增強for for (String s:list){ System.out.println(s); } } }
2. List的子類
ArrayList
java.util.ArrayList
集合資料儲存的結構是陣列結構- 增刪慢、查詢快
- 此實現不是同步的
LinkedList集合
java.util.LinkedList
集合資料儲存的結構是連結串列結構- 查詢慢、增刪快
- 是一個雙向連結串列:有大量對首位操作的方法
- 使用特有的方法,不能使用多型
- 此實現不是同步的
Vector
Vector
底層也是陣列,是同步的,速度慢;- 從Java 2平臺v1.2,這個類被改造為實現List介面,可以使用List接口裡的方法
- 如果不需要執行緒安全的實現,建議使用ArrayList代替Vector
3. Set介面
- 不包含重複元素的集合
- 沒有索引,沒有帶索引的方法,不能使用普通的for迴圈遍歷
HashSet
- 此類實現Set介面,由雜湊表(實際為HashMap例項)支援。
- 是個無序集合:對集合的迭代順序不作任何保證; 特別是,它不能保證該順序恆久不變。
- 允許null元素。
- 此實現不是同步的
雜湊值
-
是一個十進位制的整數,由系統隨機給出(就是物件的地址,是一個邏輯地址,是模擬出來得到的地址,不是資料實際儲存的實體地址)
-
在Object類有一個方法,可以獲取物件的雜湊值:
int hashCode()
//hashCode方法的原始碼: public native int hashCode(); //native:代表該方法呼叫的是本地作業系統的方法 //toString方法原始碼:也用了hashCode方法,輸出的邏輯地址是一樣的 public String toString(){ return getClass().getName()+"@"+Integer.toHexString(hashCode()); }
-
String類的雜湊值:String類重寫了Object類的hashCode方法
String s1=new String("abc"); String s2=new String("abc"); System.out.println(s1.hashCode());//96354 System.out.println(s2.hashCode());//96354
-
兩個元素不同,但是雜湊值相同:雜湊衝突
System.out.println("重地".hashCode());//1179395 System.out.println("通話".hashCode());//1179395
HashSet集合儲存資料的結構:雜湊表
-
jdk1.8之前:雜湊表=陣列+連結串列
-
jdk1.8之後:雜湊表=陣列+連結串列;雜湊表=陣列+紅黑樹(提高查詢的速度)
-
雜湊表的特點:速度快
-
陣列結構:把元素進行了分組(相同雜湊值的元素是一組),連結串列/紅黑樹結構把相同雜湊值的元素連線到一起
儲存資料到集合中時:先計算元素的雜湊值
如果連結串列的長度超過了8位,那麼就會把連結串列轉換為紅黑樹
HashSet儲存自定義型別元素
-
Set集合不允許重複元素的原理
- Set集合在呼叫add方法時,回撥用元素的hashCode方法和equals方法判斷元素是否重複
-
HashSet存放自定義型別元素時,需要重寫物件中的
hashCode()
和equals()
方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一
//例:要求:同名同年齡的人只能儲存一次
public class Person {
private String name;
private int age;
//重寫equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
//重寫hashCode方法
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//測試類
public class Demo01 {
public static void main(String[] args) {
HashSet<Person> set=new HashSet<>();
Person p1=new Person("aa",20);
Person p2=new Person("bb",22);
Person p3=new Person("aa",20);
System.out.println(p1.hashCode());//97205
System.out.println(p2.hashCode());//98199
System.out.println(p3.hashCode());//97205
System.out.println(p1==p3);//false
System.out.println(p1.equals(p3));//true
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);//[Person{name='aa', age=20}, Person{name='bb', age=22}]
}
}
LinkedHashSet
- HashSet下有一個子類
java.util.LinkedHashSet
,是連結串列和雜湊表組合的一個數據儲存結構; - 此實現與 HashSet 的不同之外在於,後者維護著一個運行於所有條目的雙重連結列表,多了一條連結串列用來記錄元素的儲存順序,保證元素有序