java學習-Set和Map集合
1.Set集合
1.1Set集合介紹
- Set集合Collection集合的一個子介面
- Set集合特點:
1)元素存取無序 : 儲存Set集合元素的順序與從Set集合中取出元素的順序不能保證一致
2)無索引 : Set集合中的每一個元素沒有索引位置
3)去重複 : Set集合中不儲存重複的元素
3.Set介面,不能例項化物件, 找到實現類HashSet, 雜湊表資料結構
Set<E> set = new HashSet<>();
程式碼
public class Demo01_Set集合介紹 { public static voidmain(String[] args) { Set<String> set = new HashSet<>(); set.add("999"); set.add("999"); set.add("a"); set.add("Hello"); set.add("a"); set.add("a"); System.out.println(set);//[a, Hello, 999] } }
1.2Set集合遍歷
- toArray() : 將集合中的元素轉換到一個Object[] 型別陣列中
- toArray(T[] arr) : 集合轉陣列; 但是列表中需要提供一個與集合資料型別相同的陣列型別引數, 將集合中元素同步到引數陣列中, 這個陣列具有指定型別, 遍歷陣列時候不需要向下轉型; 如果arr陣列大小不夠集合中的元素個數, toArray方法會為你生成一個新的T[]作為方法的返回; 返回值型別T[]
- 迭代器
- 增強for(forEach) :
1)forEach語句結構:
for( 元素資料型別 變數名 : 需要遍歷的集合或者陣列 ){
}
2)說明 :
a : 元素資料型別 : 表示需要遍歷的這個集合或者陣列中的元素具有的資料型別
b : 變數名 : 表示集合或者陣列中的每一個元素
3)注意 :
a : 增強for 語法底層是使用了迭代器的遍歷原理
b : 使用增強for有可能會發生併發修改異常
程式碼
public class Demo02_Set集合遍歷1 { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("999"); set.add("a"); set.add("Hello"); Object[] objArr = set.toArray(); for(int index = 0; index < objArr.length; index++) { Object obj = objArr[index]; String s = (String)obj; System.out.println(s); } } }
public class Demo03_Set集合遍歷2 { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("999"); set.add("a"); set.add("Hello"); String[] a = new String[set.size()]; set.toArray(a); for(int index = 0; index < a.length; index++) { String s = a[index]; System.out.println(s); } } }
public class Demo04_Set集合遍歷3 { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("999"); set.add("a"); set.add("Hello"); Iterator<String> it = set.iterator(); while(it.hasNext()) { String s = it.next(); System.out.println(s); } } }
public class Demo05_Set集合遍歷4 { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("999"); set.add("a"); set.add("Hello"); /*for( 元素資料型別 變數名 : 需要遍歷的集合或者陣列 ){ }*/ for(String s : set) { System.out.println(s); set.add("world"); } } }
1.3HashSet保證元素唯一原理
1.3.1HashSet儲存JDK提供型別
HashSet儲存JDK提供的型別時, 可以保證元素儲存是去重複的
1.3.2HashSet儲存自定義型別
- 自定義的類Person, Person中具有name和age屬性, 如果Person的姓名和年齡都相同,認為這是重複的資料,需要HashSet進行去重複儲存
- 設計好了Person型別之後,將多個Person物件儲存在HashSet中, 發現沒有給自定義型別進行去重複
- 認為與HashSet中add方法的實現有關, add方法中, 使用了hashCode() 和equals() 方法
- 試著將hashCode() 和equals() 方法在Person型別中重寫, alt + shift + s , 重寫後,去重複成功
- 總結 : 自定義型別重寫hashCode() 和equals() 方法,保證在HashSet中儲存元素唯一
程式碼
ublic class Person { 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 Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } @Override public String toString() { return "Person [name=" + name + ", 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; Person other = (Person) 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; } }
public class Demo07_HashSet儲存自定義Person { public static void main(String[] args) { // 要求 : 如果人員資訊, 姓名和年齡都相同,認為Person重複資料 HashSet<Person> set = new HashSet<>(); set.add(new Person("張三",20)); set.add(new Person("李四",20)); set.add(new Person("張三",20)); System.out.println(set);//[Person [name=李四, age=20], Person [name=張三, age=20]] } }
1.3.3hashCode方法
- hashCode方法來自於Object型別中, 可以被所有類繼承使用
- hashCode原始碼在Object中功能: 比較物件是否是同一個
1)求物件的雜湊碼值, 將一個物件在記憶體中的地址轉換成一個整數結果, 這個整數就稱為物件的雜湊碼值
2)不同的物件計算出不同的整數(雜湊碼值), 因為整數結果不同,驗證物件是否是同一個
3.hashCode計算規則:
1)同一物件多次呼叫 hashCode 方法時,必須一致地返回相同的整數
2)equals(Object) 方法,兩個物件是相等的,那麼對這兩個物件中的每個物件呼叫 hashCode 方法都必須生成相同的整數結果
3)equals(Object) 方法,兩個物件是不相等的, 那麼對這兩個物件中的每個物件呼叫 hashCode 方法整數結果儘量不相同
4.實際開發中, 比較兩個物件的地址沒有意義, 通過在子類中重寫hashCode方法, 重寫之後,比較的就是物件中的成員變數對應的hashCode值是否相等
1.3.4LinkedHashSet
- LinkedHashSet是HashSet的一個子類, 子類中方法與HashSet中的方法一樣, 同樣也可以保證元素的唯一性
- LinkedHashSet 底層結構 : 雙向連結串列, 能夠保證新增進入到集合中的元素與從集合中取出的元素順序一致,保證迭代順序
程式碼
public class Demo08_LinkedHashSet { public static void main(String[] args) { LinkedHashSet<String> linkSet = new LinkedHashSet<>(); linkSet.add("999"); linkSet.add("Hello"); linkSet.add("a"); System.out.println(linkSet);//[999, Hello, a] HashSet<String> set = new HashSet<>(); set.add("999"); set.add("Hello"); set.add("a"); System.out.println(set);// [a, Hello, 999] } }
2.Map集合
2.1Map集合的介紹
- Map是雙列集合頂層父介面, 來自於java.util包
Map<K,V> : 描述的鍵值對對映關係, 一對一 , 一個Key的值對應1個Value
K-----Key 鍵
V----Value 值
2.map類比記憶 : map英文中表示地圖概念, 地圖上的每一個點都對應現實生活中的一個地理位置, 將地圖一對一的關係類比成Map集合
3.Map集合的儲存特點:
1)Map集合中, Key值不重複(唯一)
2)Map集合中, Value值可以重複
通常對於Map集合的操作,使用唯一的Key值操作對應的Value的值
4.Map介面, 不能例項化物件, 需要實現類, HashMap--->雜湊表結構
2.2Map集合中的常用方法
- put(K key, V vlue):
1)如果新增的key值在Map集合中不存在, 那麼表示新增功能, 將鍵值對對映關係新增到Map集合中, 方法返回值型別V--->value
2)如果新增的key值在Map集合中已經存在, 那麼表示修改功能, 修改(覆蓋)指定key對應的value值
2.remove(Object key) : 將Map集合中指定key值所對應的鍵值對對映關係刪除, 返回值是value值
3.clear() : 清空Map集合中的所有元素
4.size() : 獲取Map集合中的鍵值對數量
5.get(Object key) : 通過Map集合中的key值, 獲取到對應的value
6.containsKey(Object k) : 驗證Map集合的key中,是否包含引數k, 包含返回true, 不包含返回false, 返回值型別boolean
7.containsValue(Object v) : 驗證Map集合的value值中,是否包含引數v, 包含返回true, 不包含返回false, 返回值型別boolean
程式碼
public class Demo01_Map集合常用方法 { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); // 1. put(K key, V vlue):如果新增的key的值在Map集合中不存在, 那麼表示新增功能, // 將鍵值對對映關係新增到Map集合中, 方法返回值型別V--->value map.put(11, "a"); map.put(12, "b"); map.put(13, "a"); System.out.println(map);// {11=a, 12=b, 13=a} System.out.println(map.size());// 3 // 2.put(K key, V vlue):如果新增的key的值在Map集合中已經存在, 那麼表示修改功能, 修改(覆蓋)指定key對應的value值 map.put(12, "new"); System.out.println(map);// {11=a, 12=new, 13=a} // 3. remove(Object key) : 將Map集合中指定key值, 鍵值對對映關係刪除, 返回就是value值 String value = map.remove(12); System.out.println(value);// new System.out.println(map);// {11=a, 13=a} // 4. clear() : 清空Map集合中的所有元素(成對) /*map.clear(); System.out.println(map);//{} // 5. size() : 獲取Map集合中的鍵值對數量 System.out.println(map.size());// 0 */ // 6. get(Object key) : 通過Map集合中的key的值, 獲取到對應的value String value1 = map.get(13); System.out.println(value1);// a // 7.containsKey(Object k) : 驗證Map集合的key中,是否包含引數k, 包含返回true, 不包含返回false, 返回值型別boolean System.out.println(map.containsKey(11));// true System.out.println(map.containsKey(12));// false // 8.containsValue(Object v) : 驗證Map集合的value值中,是否包含引數v, 包含返回true, 不包含返回false, 返回值型別boolean System.out.println(map.containsValue("a"));// true System.out.println(map.containsValue("b"));// false } }
2.3Map集合的第一種遍歷keySet(掌握)
- keySet() : 將Map集合中的所有的Key值獲取到, 放置到一個Set集合中
- 遍歷含有Key值的Set集合, 獲取到每一個Key值, 然後通過get(Key), 通過每一個Key值獲取到齊對應的Value值
程式碼
public class Demo02_Map第一種遍歷KetSet { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); map.put(11, "a"); map.put(13, "a"); map.put(12, "b"); // 1. 獲取到map中的所有的key的值 Set<Integer> setK= map.keySet(); // 2. 遍歷setK獲取到每一個Key值 for(Integer key : setK) { // 3. 通過get方法獲取對應的value值 String value = map.get(key); System.out.println(key + "-----" + value); } Iterator<Integer> it = setK.iterator(); while(it.hasNext()) { Integer key1 = it.next(); String value1 = map.get(key1); System.out.println(key1 + "*******" + value1); } } }
2.4Map集合的第二種遍歷entrySet(掌握)
greregegr你
1.entrySet() : 將Map集合中的所有的鍵值對關係獲取到(成對的資料), 放置到一個Set集合中, Map集合中的每一對資料就是Map.Entry<K,V>型別
2.遍歷裝有Map.Entry<K,V>鍵值對型別的Set集合, 獲取到每一對關係
3.在Map.Entry<K,V>型別中, 有方法能單獨獲取到一對元素中的key和value
1)getKey() : 獲取到鍵值對中key值, 返回值型別K
2)getValue() : 獲取到鍵值對中key值, 返回值型別V
程式碼
public class Demo03_Map第二中遍歷EntrySet { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); map.put(11, "a"); map.put(13, "a"); map.put(12, "c"); // 1. 獲取到Map集合中所有鍵值對資料 Set<Map.Entry<Integer, String>> set = map.entrySet(); // 2. 遍歷set集合, 將每一對對映關係獲取到 for(Map.Entry<Integer, String> entry: set) { // 3. 獲取到一對關係中的key和value Integer key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "?????" + value); } } }
2.5HashMap
- HashMap : Map雙列集合實現類, 底層雜湊表結構
- HashMap 集合對於元素的存取無序, Map集合沒有索引
- HashMap集合中的key值唯一, 保證key值不重複實現原理與HashSet一致
1)如果HashMap儲存JDK提供型別作為key, 直接保證key不重複
2)如果HashMap儲存自定義的型別作為key, 要求自定義型別中重寫hashCode和equals兩個方法
程式碼
public class Person { 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 Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "Person [name=" + name + ", 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; Person other = (Person) 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; } }
public class Demo04_HashMap儲存自定義型別 { public static void main(String[] args) { HashMap<Person, String> map = new HashMap<>(); map.put(new Person("zs",19), "新加坡"); map.put(new Person("lis",20), "香港"); map.put(new Person("zs",19), "北京"); System.out.println(map); } }
2.6LinkedHashMap
- LinkedHashMap 是HashMap的子類, 方法功能與HashMap一致, 但是LinkedHashMap維護了雙向連結串列, 效果 : 保證元素的迭代順序 (元素的存取順序一致)
程式碼
package com.ujiuye.map; import java.util.HashMap; import java.util.LinkedHashMap; public class Demo05_LinkedHashMap { public static void main(String[] args) { HashMap<Integer, String> map = new HashMap<Integer, String>(); map.put(11, "a"); map.put(13, "a"); map.put(12, "c"); System.out.println(map);// {11=a, 12=c, 13=a} LinkedHashMap<Integer, String> map1 = new LinkedHashMap<Integer, String>(); map1.put(11, "a"); map1.put(13, "a"); map1.put(12, "c"); System.out.println(map1);// {11=a, 13=a, 12=c} } }