JavaSE——类集(下)(Set、Comparable、Collections、Comparator、Map)
第2節(jié) 集合(下)
一、Set接口
java.util.Set 接口和 java.util.List接口一樣,同樣繼承自 Collection接口,它與Collection接口中的方法基本一致,并沒有對 Collection接口進行功能上的擴充,只是比Collection接口更加嚴(yán)格了。
與 List接口不同的是, Set接口中元素無序 ,并且都會以某種規(guī)則保證存入的元素不出現(xiàn)重復(fù) 。
Set接口有很多子類:
比較常用的有HashSet、LinkedHashSet、TreeSet三個,后面分別介紹。
二、HashSet類
2.1 概述與使用
java.util.HashSet是 Set接口的一個實現(xiàn)類,它所存儲的元素是不可重復(fù)的,并且元素都是無序的(即存取順序不一致)。 java.util.HashSet底層的實現(xiàn)其實是一個java.util.HashMap 支持,即將數(shù)據(jù)存在HashMap的鍵的位置,值的位置全部存放空對象。
HashSet是根據(jù)對象的哈希值來確定元素在集合中的存儲位置,因此具有良好的存取和查找性能。保證元素唯一性的方式依賴于: hashCode與 equals方法。hashCode就是一個生成哈希值(int型)的函數(shù)。
先來看一個使用HashSet存儲的例子:
public class HashSetDemo {public static void main(String[] args) {//創(chuàng)建 Set集合HashSet<String> set = new HashSet<String>();//添加元素set.add(new String("123"));set.add("123");set.add("123");set.add("321");//遍歷for (String name : set) {System.out.println(name);}} } 結(jié)果如下: 123 321 說明Set集合中不能存儲重復(fù)元素2.2 構(gòu)造方法與方法
其中涉及到散列因子,后續(xù)介紹,**這里注意最后一種構(gòu)造方法,可以將其他類型的Collection實現(xiàn)轉(zhuǎn)為HashSet類,其他的一些類也有類似的操作** 。方法也不多,增加刪除遍歷獲取元素數(shù)比較常用。
2.3 哈希表
因為HashSet是由HashMap實現(xiàn)的,而HashMap又是由哈希表這種數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,所以有必要介紹一下java中哈希表是什么。
在JDK1.8之前,哈希表底層采用數(shù)組+鏈表 實現(xiàn),即使用鏈表處理沖突,同一hash值的鏈表都存儲在一個鏈表里。但是當(dāng)位于一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。而JDK1.8中,哈希表存儲采用數(shù)組+鏈表+紅黑樹 實現(xiàn),當(dāng)鏈表長度超過閾值(8)時,將鏈表轉(zhuǎn)換為紅黑樹,這樣大大減少了查找時間 。
當(dāng)紅黑樹中數(shù)據(jù)個數(shù)減少到6時,從紅黑樹變回為鏈表 。這里要注意,如果本身就是鏈表,那么降到6也不會發(fā)生這種轉(zhuǎn)變。
它存入數(shù)據(jù)時的完整過程如下圖所示:
總而言之,JDK1.8引入紅黑樹大程度優(yōu)化了HashMap的性能,那么對于我們來講保證HashSet集合元素的唯一,其實就是根據(jù)對象的hashCode和equals方法來決定的。如果我們往集合中存放自定義的對象,那么保證其唯一,就必須復(fù)寫hashCode和equals方法建立屬于當(dāng)前對象的比較方式。
2.4 LinkedHashSet類
此實現(xiàn)使客戶免于HashSet提供的未指定的,通常是混亂的排序,而不會產(chǎn)生與TreeSet相關(guān)的增加的成本。無論原始集合的實現(xiàn)如何,它都可用于生成與原始集合具有相同順序的集合的副本 。
三、TreeSet類與Comparable接口
3.1 TreeSet類概述
它與HashSet相比,最大的區(qū)別在于TreeSet是有序存儲的。先來看一下它的構(gòu)造方法和方法:
看一個例子:
package com.kaikeba.coreclasslibrary.set;import java.util.TreeSet;public class treeset {//TreeSet:public static void main(String[] args) {TreeSet<String> data = new TreeSet<>();data.add("B");data.add("C");data.add("A");data.add("D");for(String s:data) {System.out.println(s);}} }結(jié)果如下: A B C D它有一個問題,當(dāng)存入的數(shù)據(jù)是自定義的對象時, TreeSet通過什么來比較大小,或者再一般一些,傳入上述字符串對象時,TreeSet是通過說明比較順序的?
它本身是不知道的,所以必須實現(xiàn)Comparable接口。
3.2 Comparable接口
此接口對實現(xiàn)它的每個類的對象強加一個總排序。 這種排序被稱為類的自然順序 ,類的compareTo方法被稱為其自然比較方法 。
它只有一個抽象方法:compareTo,它將傳入的對象與此對象進行比較以獲得順序。返回負(fù)整數(shù),零,正整數(shù),表示此對象小于,等于或大于指定對象。
看一個例子:
package com.kaikeba.coreclasslibrary.set;import java.util.Objects; import java.util.TreeSet;public class treeset2 {//TreeSet:public static void main(String[] args) {TreeSet<Person> data = new TreeSet<>();Person p1 = new Person("張三", 20);Person p2 = new Person("李四", 19);Person p3 = new Person("麻子", 19);data.add(p1);data.add(p2);data.add(p3); //不能存一樣大的值for(Person p:data) {System.out.println(p);}}static class Person implements Comparable<Person>{private String name;private int age;@Overridepublic int compareTo(Person o) {//this 與 o 比較//返回的數(shù)據(jù)是:負(fù)數(shù)this小、零一樣大、整數(shù)this大if(this.age > o.age) {return 1;}else if(this.age == o.age) {return 0;}return -1;}public Person() {}public Person(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;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}} }結(jié)果如下:
Person{name='李四', age=19} Person{name='張三', age=20}Person類實現(xiàn)了Comparable接口,實現(xiàn)了compareTo方法,這里對年齡進行了排序,而且也可以發(fā)現(xiàn),當(dāng)兩者一樣大時,不會存入數(shù)據(jù)。
那是不是String也做了同樣的事才可以使得它能排序呢?看一下String源碼:
它也是做了相同的事,才可以比較大小進行排序的。
四、Collections類和Comparator接口
4.1 Collections類
是一個集合工具類,用來對集合進行操作,部分方法如下:
public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。
public static void shuffle(List<?> list): 打亂集合順序。
public static <T> void sort(List<T> list) :將集合中元素按照默認(rèn)規(guī)則排序。
public static <T> void sort(List<T> list,Comparator<? super T> ) :將集合中元素按照指定規(guī)則排序。
舉個例子:
public class CollectionsDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();//原來寫法//list.add(12);//list.add(14);//list.add(15);//list.add(1000);//采用工具類 完成 往集合中添加元素Collections.addAll(list, 5, 222, 1,2);System.out.println(list);//排序方法Collections.sort(list);System.out.println(list);} } 結(jié)果: [5, 222, 1, 2] [1, 2, 5, 222]這里的排序是采用的默認(rèn)順序,如果想要自定義順序怎么操作?
4.2 Comparator接口
排序的規(guī)則是怎么定義出來的呢?說到排序,簡單說就是兩個對象之間比較大小,那么在Java中提供了兩種比較實現(xiàn)的方式:
一種是比較死板的采用java.lang.Comparable接口去實現(xiàn);
一種是靈活的當(dāng)我需要做排序的時候再去選擇java.util.Comparator接口完成。
Comparable接口中的實現(xiàn),把比較規(guī)則寫死了,比如想要字符串按照字符降序排序,那么就要修改String的源代碼,這是不可能的,所以這個時候可以使用Comparator接口靈活的完成。
Comparator接口中主要需要重寫的方法是compare方法:
public int compare(String o1, String o2): //比較其兩個參數(shù)的順序。兩個對象比較的結(jié)果有三種:大于,等于,小于。
如果要按照升序排序,
則o1 小于o2,返回(負(fù)數(shù)),相等返回0,01大于02返回(正數(shù))
如果要按照降序排序
則o1 小于o2,返回(正數(shù)),相等返回0,01大于02返回(負(fù)數(shù))
操作如下:
public class CollectionsDemo3 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("cba");list.add("aba");list.add("sba");list.add("nba");//排序方法 按照第一個單詞的降序Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o2.charAt(0) - o1.charAt(0);}});System.out.println(list);} }結(jié)果如下: [sba, nba, cba, aba]4.3 Comparable和Comparator接口的區(qū)別
Comparable:強行對實現(xiàn)它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的compareTo方法被稱為它的自然比較方法。只能在類中實現(xiàn)compareTo()一次,不能經(jīng)常修改類的代碼實現(xiàn)自己想要的排序。實現(xiàn)此接口的對象列表(和數(shù)組)可以通過Collections.sort(和Arrays.sort)進行自動排序,對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。
Comparator:強行對某個對象進行整體排序??梢詫omparator傳遞給sort方法(如Collections.sort或 Arrays.sort),從而允許在排序順序上實現(xiàn)精確控制。還可以使用Comparator來控制某些數(shù)據(jù)結(jié)構(gòu)(如有序set或有序map)的順序,或者為那些沒有自然順序的對象collection提供排序。
練習(xí):
創(chuàng)建一個學(xué)生類,存儲到ArrayList集合中完成指定排序操作。
Student 初始類:
public class Student{private String name;private int age;public Student() {} public Student(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;} @Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';} }測試類:
public class Demo {public static void main(String[] args) {// 創(chuàng)建四個學(xué)生對象 存儲到集合中ArrayList<Student> list = new ArrayList<Student>();list.add(new Student("rose",18));list.add(new Student("jack",16));list.add(new Student("abc",16));list.add(new Student("ace",17));list.add(new Student("mark",16));/*讓學(xué)生 按照年齡排序 升序*/// Collections.sort(list);//要求 該list中元素類型 必須實現(xiàn)比較器Comparable接口for (Student student : list) {System.out.println(student);}} }發(fā)現(xiàn),當(dāng)我們調(diào)用Collections.sort()方法的時候 程序報錯了。
原因:如果想要集合中的元素完成排序,那么必須要實現(xiàn)比較器Comparable接口。
于是我們就完成了Student類的一個實現(xiàn),如下:
public class Student implements Comparable<Student>{....@Overridepublic int compareTo(Student o) {return this.age-o.age;//升序} }再次測試,代碼就OK 了效果如下:
Student{name='jack', age=16} Student{name='abc', age=16} Student{name='mark', age=16} Student{name='ace', age=17} Student{name='rose', age=18}補充:
如果想要規(guī)則更多一些,可以參考下面代碼:
Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 年齡降序int result = o2.getAge()-o1.getAge()//第一個規(guī)則判斷完了 下一個規(guī)則 姓名的首字母 升序if(result==0){result = o1.getName().charAt(0)-o2.getName().charAt(0);} return result;} });效果如下:
Student{name='rose', age=18} Student{name='ace', age=17} Student{name='abc', age=16} Student{name='jack', age=16} Student{name='mark', age=16}五、Map接口
5.1 概述
以上的Collection中,每次操作的都是一個單獨對象,而Map接口,可以實現(xiàn)鍵值對的存儲 ,如下所示:
-
張三 123456
-
李四 234567
Map中不能包含重復(fù)的鍵,即鍵必須唯一,而且每個鍵最多可以映射一個值 。
Map接口與Collection接口沒有任何的關(guān)系,是第二大集合操作接口。
注意:如果將可變對象用作鍵,則必須非常小心,因為一旦中途更改對象的屬性,根據(jù)hashCode和equals方法的定義,將無法找到原來存在以該對象為鍵的值,即發(fā)生了哈希值錯亂,后面再結(jié)合源碼和例子詳細(xì)解釋。
5.2 方法介紹
介紹一下常用法方法:
1、刪除所有映射
2、是否包含指定的鍵、值
3、返回Map.Entry或Set視圖
4、equals
5、根據(jù)鍵獲取值
6、返回哈希碼值
7、判斷是否不包含映射關(guān)系
8、將鍵作為Set集合返回,遍歷常用
9、返回包含若干個映射的不可修改Map,靜態(tài)方法
10、存入指定的鍵值對
11、刪除某映射對
12、替換某映射對
13、返回此Map中的鍵值對數(shù)量
14、返回此Map中所有值的Collection集合
Map本身是一個接口,所以一般會使用以下的幾個子類:HashMap、TreeMap、Hashtable。
六、HashMap、Hashtable、ConcurrentHashMap類
6.1 HashMap類
6.1.1 概述
基于哈希表的Map接口的實現(xiàn)。 此實現(xiàn)提供了所有可選的映射操作,并允許null值和null鍵。 ( HashMap類大致相當(dāng)于Hashtable ,除了它是不同步的并且允許空值。)此類不保證順序。
此類定義如下:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable它繼承了AbstractMap類,同時可以被克隆,可以被序列化。
看一個例子:
package com.kaikeba.coreclasslibrary.set;import java.util.Collection; import java.util.HashMap; import java.util.Set;public class map {//Map//HashMap/Hashtable/ConcurrentHashMap//TreeMap//LinkedHashMappublic static void main(String[] args) {HashMap<String, String> data = new HashMap<>();data.put("key1", "鋤禾日當(dāng)午");data.put("key2", "汗滴禾下土");data.put("key2", "勇敢牛牛"); //新的內(nèi)容將替換舊的內(nèi)容//根據(jù)鍵來遍歷鍵值對Set<String> set = data.keySet();for(String key:set) {System.out.println(key+"->"+data.get(key));}//遍歷值Collection<String> values = data.values();for(String value:values) {System.out.println(value);}} }結(jié)果如下所示: key1->鋤禾日當(dāng)午 key2->勇敢牛牛 鋤禾日當(dāng)午 勇敢牛牛6.1.2 可變對象作為鍵
前面也提到了,可變對象作為鍵會出現(xiàn)哈希值錯亂的問題,先來看一個例子:
package com.kaikeba.coreclasslibrary.set;import java.util.HashMap; import java.util.Objects;public class Demo {public static void main(String[] args) {//為防止鍵改變導(dǎo)致哈希值錯亂的問題,盡量不要使用對象來作為鍵,如果要做,不要修改對象的屬性HashMap<Book, String> data = new HashMap<>();Book book1 = new Book("三體", "科幻小說");data.put(book1, "第一本書");Book book2 = new Book("平凡的世界", "紀(jì)實小說");data.put(book2, "第二本書");book1.setName("四體");//哈希值通過對象屬性計算,哈希值計算的與原來不一樣,是找不到值的System.out.println(data.get(book1));//哈希值雖然計算一樣,但是equals不相等,傳入的“三體”與鍵對象的“四體不相等,也找不到”Book book3 = new Book("三體", "科幻小說");System.out.println(data.get(book3));}static class Book {private String name;private String info;public Book() {}public Book(String name, String info) {this.name = name;this.info = info;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Book book = (Book) o;return Objects.equals(name, book.name) && Objects.equals(info, book.info);}@Overridepublic int hashCode() {return Objects.hash(name, info);}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", info='" + info + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}} }結(jié)果如下: null null因為中途將作為鍵的可變對象的屬性改變,導(dǎo)致后續(xù)找不到該鍵對應(yīng)的值了,上述涉及到了兩種情況:
直接通過改變后的對象去get,發(fā)現(xiàn)找不到;
新new一個與原來對象的屬性完全一樣的新對象去get,也找不到。
為了解釋上述的現(xiàn)象,需要看get方法的源碼:
public V get(Object key) {Node<K,V> e;return (e = getNode(hash(key), key)) == null ? null : e.value; }調(diào)用getNode方法,根據(jù)哈希值和key來獲取值,首先來看一下哈希值是如何來的:
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }其實就是根據(jù)鍵來獲取哈希值,若鍵為null,哈希值為0,若不為空,調(diào)用hashCode方法生成,而hashCode在創(chuàng)建類的時候已經(jīng)生成:
@Override public int hashCode() {return Objects.hash(name, info); }就是根據(jù)鍵的屬性計算的一個int值,到這里就解釋了第一個問題,因為存入的時候是new Book("三體", "科幻小說");,而修改了屬性后鍵變?yōu)閚ew Book("四體", "科幻小說");兩者屬性不一樣,根據(jù)哈希值計算方法來看,計算得到的哈希值是不一樣的,而getNode中哈希值就是尋找位置的關(guān)鍵,哈希值不一樣肯定找不到。
最后再看一下getNode方法內(nèi)部:
注意這里:
還有這里:
以及若在紅黑樹中g(shù)etTreeNode方法里也有一樣的判斷條件,要想返回值,必須先滿足這個,這里的意思就是除了哈希值要一樣,鍵也要保持一樣,但是修改之后的鍵是"四體", "科幻小說",而book3是"三體", "科幻小說",它們哈希值雖然一樣了,但是key不一樣了,這就是問題2的原因。
綜上,為防止鍵改變導(dǎo)致哈希值錯亂的問題,盡量不要使用可變對象來作為鍵,如果對象必須可變,那就不要拿它作為鍵使用 。
6.2 Hashtable類
Hashtable是一個最早的鍵值對操作類,本身是在JDK1.0的時候推出的,其基本操作與HashMap是類似的。
import java.util.Hashtable; import java.util.Map; public class HashtableDemo01 {public static void main(String[] args) {Map<String, Integer> numbers = new Hashtable<String, Integer>();numbers.put("one", 1);numbers.put("two", 2);numbers.put("three", 3);Integer n = numbers.get("two");if (n != null) {System.out.println("two = " + n);}} }操作的時候, 可以發(fā)現(xiàn)與 HashMap基本上沒有什么區(qū)別, 而且本身都是以 Map為操作標(biāo)準(zhǔn)的, 所以操作的結(jié)果形式都一樣。 但是 Hashtable中是不能向集合中插入 null值的。
6.3 HashMap與Hashtable的區(qū)別
在整個集合中除了ArrayList和Vector的區(qū)別之外,另外一個最重要的區(qū)別就是HashMap與Hashtable的區(qū)別:
6.4 ConcurrentHashMap類
HashMap是異步處理,線程不安全,但是性能較高;Hashtable是同步處理,線程安全,但是性能較低;而ConcurrentHashMap是對這兩類的一個優(yōu)化,采用了分段鎖機制,在保證線程安全的同時,效率也比較高。
分段鎖機制 就是每個哈希桶內(nèi)部需要同步保證線程安全,但是桶與桶之間是異步的,提高性能。
6.5 哈希表的散列操作
注意一下這三類的構(gòu)造方法,以HashMap為例:
涉及到兩個參數(shù):初始容量 和加載因子 。無參的默認(rèn)初始容量為16,所有的默認(rèn)加載因子為0.75。
-
初始容量 :哈希表中哈希桶的數(shù)量;
-
加載因子 :哈希表中有多少百分比的哈希桶中有數(shù)據(jù),就需要進行擴容,一般是擴容為2倍,0.75就是75%。0.75是在時間和空間成本之間進行的良好的折中。較高的值會減少空間開銷,但是會增加查找的成本。
為了盡量減少重新哈希(擴容)的操作,事先選擇好初始容量和加載因子是很關(guān)鍵的(加載因子一般就選0.75)。
七、TreeMap類
TreeMap子類是允許 key 進行排序的操作子類, 其本身在操作的時候?qū)凑?key 進行排序, 另外, key 中的內(nèi)容可以為任意的對象, 但是要求對象所在的類必須實現(xiàn) Comparable接口。這一點和TreeSet是類似的,畢竟,TreeSet就是TreeMap實現(xiàn)的。
import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class TreeMapDemo01 {public static void main(String[] args) {Map<String, String> map = new TreeMap<String, String>();map.put("ZS", "張三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "趙六");map.put("SQ", "孫七");Set<String> set = map.keySet(); // 得到全部的keyIterator<String> iter = set.iterator();while (iter.hasNext()) {String i = iter.next(); // 得到keySystem.out.println(i + " --:> " + map.get(i));}} }結(jié)果如下: LS --:> 李四 SQ --:> 孫七 WW --:> 王五 ZL --:> 趙六 ZS --:> 張三此時的結(jié)果已經(jīng)排序成功了, 但是從一般的開發(fā)角度來看, 在使用 Map 接口的時候并不關(guān)心其是否排序, 所以此類只需要知道其特點即可。
八、關(guān)于Map集合的輸出
8.1 使用Map.Entry接口
在Collection接口中,可以使用 iterator()方法為Iterator接口實例化,并進行輸出操作,但是在 Map接口中并沒有此方法的定義, 所以 Map接口本身是不能直接使用 Iterator進行輸出的。
因為 Map接口中存放的每一個內(nèi)容都是一對值, 而使用 Iterator 接口輸出的時候, 每次取出的都實際上是一個完整的對象。 如果此時非要使用Iterator進行輸出的話, 則可以按照如下的步驟進行:
使用Map接口中的entrySet()方法將 Map接口的全部內(nèi)容變?yōu)?Set 集合;
可以使用Set 接口中定義的iterator()方法為 Iterator接口進行實例化;
之后使用 Iterator接口進行迭代輸出,每一次的迭代都可以取得一個Map.Entry的實例;
通過Map.Entry進行 key和 value的分離。
那么, 到底什么是 Map.Entry 呢?
Map.Entry 本身是一個接口。此接口是定義在 Map接口內(nèi)部的,是 Map的內(nèi)部接口。此內(nèi)部接口使用 static進行定義,所以此接口將成為外部接口。
實際上來講,對于每一個存放到 Map集合中的 key和 value都是將其變?yōu)榱薓ap.Entry 并且將Map.Entry 保存在了Map集合之中。
在Map.Entry接口有如下的方法:
在Map.Entry接口中以下的方法最為常用:
看一個例子:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapOutDemo01 {public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("ZS", "張三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "趙六");map.put("SQ", "孫七");// 變?yōu)镾et實例Set<Map.Entry<String, String>> set = map.entrySet();Iterator<Map.Entry<String, String>> iter = set.iterator();while (iter.hasNext()) {Map.Entry<String, String> me = iter.next();System.out.println(me.getKey() + " --> " + me.getValue());}} }結(jié)果如下: WW --> 王五 ZL --> 趙六 LS --> 李四 ZS --> 張三 SQ --> 孫七以上的代碼一定要記住,Map集合中每一個元素都是 Map.Entry 的實例, 只有通過Map.Entry才能進行 key和 value的分離操作。
8.2 foreach遍歷
在 JDK 1.5 之后也可以使用 foreach 完成同樣的輸出, 只是這樣的操作基本上不使用。
import java.util.HashMap; import java.util.Map; public class MapOutDemo02 {public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("ZS", "張三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "趙六");map.put("SQ", "孫七");for (Map.Entry<String, String> me : map.entrySet()) {System.out.println(me.getKey() + " --> " + me.getValue());}} }結(jié)果如下: WW --> 王五 ZL --> 趙六 LS --> 李四 ZS --> 張三 SQ --> 孫七九、類集總結(jié)
類集就是一個動態(tài)的對象數(shù)組,可以向集合中加入任意多的內(nèi)容;
List接口中是允許有重復(fù)元素的,Set接口中是不允許有重復(fù)元素;
所有的重復(fù)元素依靠hashCode()和equals進行區(qū)分;
List接口常用子類:ArrayList、Vector;
Set接口常用子類:HashSet、TreeSet;
TreeSet是可以排序的,一個類的對象依靠Comparable接口排序;
Map接口中允許存放一對內(nèi)容,key→value;
Map接口的常用子類:HashMap、Hashtable、TreeMap;
Map使用Iterator輸出的詳細(xì)步驟(Map.Entry)
總結(jié)
以上是生活随笔為你收集整理的JavaSE——类集(下)(Set、Comparable、Collections、Comparator、Map)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Relu神经网络输出预测全为0或1,对所
- 下一篇: IndexError: tensors