Java類(lèi)中集合的關(guān)系圖
1. 集合類(lèi)概述
1.1 為什么出現(xiàn)集合類(lèi)春锋?
面向?qū)ο笳Z(yǔ)言對(duì)事物的體現(xiàn)都是以對(duì)象的形式居触,所以為了方便對(duì)多個(gè)對(duì)象的操作遗遵,Java就提供了集合類(lèi)搬味。
1.2 數(shù)組和集合類(lèi)同是容器境氢,有何不同?
1.3 集合類(lèi)的特點(diǎn)
集合只用于存儲(chǔ)對(duì)象碰纬,集合長(zhǎng)度是可變的萍聊,集合可以存儲(chǔ)不同類(lèi)型的對(duì)象。
2. Collection接口概述
Collection 層次結(jié)構(gòu)中的根接口悦析。Collection 表示一組對(duì)象寿桨,這些對(duì)象也稱(chēng)為 collection 的元素。一些 collection 允許有重復(fù)的元素强戴,而另一些則不允許亭螟。一些 collection 是有序的,而另一些則是無(wú)序的骑歹。
3. Collection接口成員方法
4. Collection實(shí)現(xiàn)類(lèi)
4.1 List接口概述
有序的 collection(也稱(chēng)為序列)预烙。此接口的用戶(hù)可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制。用戶(hù)可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問(wèn)元素道媚,并搜索列表中的元素扁掸。與 set 不同,列表通常允許重復(fù)的元素最域。
4.1.1 ArrayList類(lèi)概述
底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組也糊,查詢(xún)快,增刪慢羡宙,線(xiàn)程不安全,效率高掐隐。
4.1.2 Vector類(lèi)概述
底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組狗热,查詢(xún)快,增刪慢虑省,線(xiàn)程安全匿刮,效率低。
4.1.3 Vector類(lèi)特有功能
- public void addElement(E obj):添加元素
- public E elementAt(int index):根據(jù)索引獲取元素
- public Enumeration elements():獲取所有的元素
4.1.4 LinkedList類(lèi)概述
底層數(shù)據(jù)結(jié)構(gòu)是鏈表探颈,查詢(xún)慢熟丸,增刪快,線(xiàn)程不安全伪节,效率高
方法聲明 | 功能描述 |
---|---|
public void addFirst(E e) | 將指定元素插入此列表的開(kāi)頭 |
public voidaddLast(E e) | 將指定元素添加到此列表的結(jié)尾 |
public E getFirst() | 將指定元素添加到此列表的結(jié)尾 |
public E getLast() | 獲取集合的最后一個(gè)元素 |
public E removeFirst() | 刪除集合的第一個(gè)元素 |
public E removeLast() | 刪除最后一個(gè)元素 |
代碼示例:使用LinkedList來(lái)模擬一個(gè)棧數(shù)據(jù)結(jié)構(gòu)
package cn.itcast;
import java.util.LinkedList;
/*
*使用LinkedList模擬棧數(shù)據(jù)結(jié)構(gòu)的集合光羞,并測(cè)試
*1绩鸣、棧的特點(diǎn)先進(jìn)后出
*2、 LinkedList的特有添加功能addFirst()
*/
class MyStack {
private LinkedList link;
public MyStack() {
link = new LinkedList();
}
public void add(Object obj) {
// 將指定元素插入此列表的開(kāi)頭
link.addFirst(obj);
}
public Object get() {
// 移除并返回此列表的第一個(gè)元素纱兑。
// return link.getFirst();
return link.removeFirst();
}
public boolean isEmpty() {
return link.isEmpty();
}
}
/*
* MyStack的測(cè)試
*/
public class MyStackDemo {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
MyStack ms = new MyStack();
// 添加元素
ms.add("hello");
ms.add("world");
ms.add("java");
ms.add("android");
ms.add("javase");
while (!ms.isEmpty()) {
System.out.println(ms.get());
}
}
}
運(yùn)行結(jié)果:
4.2 Set接口概述
一個(gè)不包含重復(fù)元素的 collection呀闻,無(wú)序。
哈希表確定元素是否相同
1潜慎、 判斷的是兩個(gè)元素的哈希值是否相同捡多。
如果相同,再判斷兩個(gè)對(duì)象的內(nèi)容是否相同铐炫。
2垒手、 判斷哈希值相同,其實(shí)判斷的是對(duì)象的HashCode方法倒信。判斷內(nèi)容相同科贬,用的是equals方法。
4.2.1 HashSet類(lèi)概述
- 不保證 set 的迭代順序堤结,特別是它不保證該順序恒久不變唆迁。
- HashSet如何保證元素唯一性
- 底層數(shù)據(jù)結(jié)構(gòu)是哈希表(元素是鏈表的數(shù)組)
- 哈希表依賴(lài)于哈希值存儲(chǔ)
- 添加功能底層依賴(lài)兩個(gè)方法:int hashCode()、boolean equals(Object obj)
HashSet存儲(chǔ)元素保證唯一性的代碼及圖解:
package cn.itcast;
import java.util.HashSet;
class Dog {
private String name;
private int age;
private String color;
private char sex;
public Dog() {
super();
}
public Dog(String name, int age, String color, char sex) {
super();
this.name = name;
this.age = age;
this.color = color;
this.sex = sex;
}
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 String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + sex;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (age != other.age)
return false;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex != other.sex)
return false;
return true;
}
}
/*
* HashSet集合存儲(chǔ)自定義對(duì)象并遍歷竞穷。如果對(duì)象的成員變量值相同即為同一個(gè)對(duì)象
*
* 注意了: 你使用的是HashSet集合唐责,這個(gè)集合的底層是哈希表結(jié)構(gòu)。 而哈希表結(jié)構(gòu)底層依賴(lài):hashCode()和equals()方法瘾带。
* 如果你認(rèn)為對(duì)象的成員變量值相同即為同一個(gè)對(duì)象的話(huà)鼠哥,你就應(yīng)該重寫(xiě)這兩個(gè)方法。 如何重寫(xiě)呢?不同擔(dān)心看政,自動(dòng)生成即可朴恳。
*/
public class DogDemo {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
HashSet<Dog> hs = new HashSet<Dog>();
// 創(chuàng)建狗對(duì)象
Dog d1 = new Dog("秦檜", 25, "紅色", '男');
Dog d2 = new Dog("高俅", 22, "黑色", '女');
Dog d3 = new Dog("秦檜", 25, "紅色", '男');
Dog d4 = new Dog("秦檜", 20, "紅色", '女');
Dog d5 = new Dog("魏忠賢", 28, "白色", '男');
Dog d6 = new Dog("李蓮英", 23, "黃色", '女');
Dog d7 = new Dog("李蓮英", 23, "黃色", '女');
Dog d8 = new Dog("李蓮英", 23, "黃色", '男');
// 添加元素
hs.add(d1);
hs.add(d2);
hs.add(d3);
hs.add(d4);
hs.add(d5);
hs.add(d6);
hs.add(d7);
hs.add(d8);
// 遍歷
for (Dog d : hs) {
System.out.println(d.getName() + "---" + d.getAge() + "---"
+ d.getColor() + "---" + d.getSex());
}
}
}
運(yùn)行結(jié)果:
4.2.2 LinkedHashSet類(lèi)概述
元素有序唯一,由鏈表保證元素有序允蚣,由哈希表保證元素唯一于颖。
4.3 TreeSet類(lèi)概述
使用元素的自然順序?qū)υ剡M(jìn)行排序,或者根據(jù)創(chuàng)建 set 時(shí)提供的 Comparator 進(jìn)行排序嚷兔,具體取決于使用的構(gòu)造方法森渐。
TreeSet是如何保證元素的排序和唯一性
底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹(shù)(紅黑樹(shù)是一種自平衡的二叉樹(shù))TreeSet判斷元素唯一性的方式
就是根據(jù)比較方法的返回結(jié)果是否是0,是0冒晰,就是相同元素同衣,不存。TreeSet對(duì)元素進(jìn)行排序的方式一
讓元素自身具備比較功能壶运,元素就需要實(shí)現(xiàn)Comparable接口耐齐,覆蓋compareTo方法。
如果不要按照對(duì)象中具備的自然順序進(jìn)行排序。如果對(duì)象中不具備自然順序埠况。怎么辦耸携?可以使用TreeSet集合第二種排序方式
讓集合自身具備比較功能,定義一個(gè)類(lèi)實(shí)現(xiàn)Comparator接口询枚,覆蓋compare方法违帆。將該類(lèi)對(duì)象作為參數(shù)傳遞給TreeSet集合的構(gòu)造函數(shù)。
TreeSet存儲(chǔ)元素自然排序和唯一的圖解:
package cn.itcast;
import java.util.Comparator;
import java.util.TreeSet;
class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
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;
}
}
class MyComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
// int num = this.name.length() - s.name.length();
// this -- s1
// s -- s2
// 姓名長(zhǎng)度
int num = s1.getName().length() - s2.getName().length();
// 姓名內(nèi)容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
// 年齡
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
}
/*
* 需求:請(qǐng)按照姓名的長(zhǎng)度排序
*
* TreeSet集合保證元素排序和唯一性的原理 唯一性:是根據(jù)比較的返回是否是0來(lái)決定金蜀。 排序: A:自然排序(元素具備比較性)
* 讓元素所屬的類(lèi)實(shí)現(xiàn)自然排序接口 Comparable B:比較器排序(集合具備比較性) 讓集合的構(gòu)造方法接收一個(gè)比較器接口的子類(lèi)對(duì)象 Comparator
*/
public class TreeSetDemo {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
// TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
// public TreeSet(Comparator comparator) //比較器排序
// TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());
// 如果一個(gè)方法的參數(shù)是接口刷后,那么真正要的是接口的實(shí)現(xiàn)類(lèi)的對(duì)象
// 而匿名內(nèi)部類(lèi)就可以實(shí)現(xiàn)這個(gè)東西
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student s1, Student s2) {
// 姓名長(zhǎng)度
int num = s1.getName().length() - s2.getName().length();
// 姓名內(nèi)容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
: num;
// 年齡
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
});
// 創(chuàng)建元素
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);
Student s8 = new Student("linqingxia", 29);
// 添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8);
// 遍歷
for (Student s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
運(yùn)行結(jié)果:
4.4 集合的遍歷
迭代:是取出集合中元素的一種方式。
而每一個(gè)容器的數(shù)據(jù)結(jié)構(gòu)不同渊抄,所以取出的動(dòng)作細(xì)節(jié)也不一樣尝胆。但是都具有共性?xún)?nèi)容: 判斷和取出。那么就可以將這些共性抽取护桦。那么這些內(nèi)部類(lèi)都符合一個(gè)規(guī)則(或者說(shuō)都抽取出來(lái)一個(gè)規(guī)則)含衔。該規(guī)則就是Iterator。通過(guò)一個(gè)對(duì)外提供的方法:iterator();二庵,來(lái)獲取集合的取出對(duì)象贪染。因?yàn)镃ollection中有iterator方法,所以每一個(gè)子類(lèi)集合對(duì)象都具備迭代器催享。
迭代的常見(jiàn)操作
PS:在迭代時(shí)循環(huán)中next調(diào)用一次杭隙,就要hasNext判斷一次。
并發(fā)修改異常因妙,原因:迭代器依賴(lài)于集合存在痰憎,修改集合元素而迭代器卻不知道。
解決方法:
A:迭代器迭代元素攀涵,迭代器修改铣耘。因?yàn)镮terator沒(méi)有添加功能,所以使用其子接口ListIterator以故,元素在迭代元素的后面添加蜗细。
B:集合遍歷元素,集合修改元素(普通for和get(index)結(jié)合)怒详,元素在最后添加
package cn.itcast;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/*
* 問(wèn)題:有一個(gè)集合鳄乏,如下,請(qǐng)問(wèn)棘利,我想判斷里面有沒(méi)有"world"這個(gè)元素,如果有朽缴,我就添加一個(gè)"javaee"元素善玫,請(qǐng)寫(xiě)代碼實(shí)現(xiàn)。
*
* ConcurrentModificationException:當(dāng)方法檢測(cè)到對(duì)象的并發(fā)修改,但不允許這種修改時(shí)茅郎,拋出此異常蜗元。
* 產(chǎn)生的原因:
* 迭代器是依賴(lài)于集合而存在的,在判斷成功后系冗,集合的中新添加了元素奕扣,而迭代器卻不知道,所以就報(bào)錯(cuò)了掌敬,這個(gè)錯(cuò)叫并發(fā)修改異常惯豆。
* 其實(shí)這個(gè)問(wèn)題描述的是:迭代器遍歷元素的時(shí)候,通過(guò)集合是不能修改元素的奔害。
* 如何解決呢?
* A:迭代器迭代元素楷兽,迭代器修改元素,元素是跟在剛才迭代的元素后面的。
* B:集合遍歷元素华临,集合修改元素(普通for),元素在最后添加的芯杀。
*/
public class ListIteratorDemo {
public static void main(String[] args) {
// 創(chuàng)建List集合對(duì)象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// 迭代器遍歷
// Iterator it = list.iterator();
// while (it.hasNext()) {
// String s = (String) it.next();
// if ("world".equals(s)) {
// list.add("javaee");
// }
// }
// 方式1:迭代器迭代元素,迭代器修改元素
// 而Iterator迭代器卻沒(méi)有添加功能雅潭,所以我們使用其子接口ListIterator
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("world".equals(s)) {
lit.add("javaee");
}
}
// 方式2:集合遍歷元素揭厚,集合修改元素(普通for)
for (int x = 0; x < list.size(); x++) {
String s = (String) list.get(x);
if ("world".equals(s)) {
list.add("javaee");
}
}
System.out.println("list:" + list);
}
}
5. Map接口概述
5.1 Map接口概述
將鍵映射到值的對(duì)象,一個(gè)映射不能包含重復(fù)的鍵扶供,每個(gè)鍵最多只能映射到一個(gè)值筛圆。其實(shí)Map集合中存儲(chǔ)的就是鍵值對(duì)。map集合中必須保證鍵的唯一性诚欠。
Map接口和Collection接口的不同
- Map是雙列的,Collection是單列的
- Map的鍵唯一,Collection的子體系Set是唯一的
- Map集合的數(shù)據(jù)結(jié)構(gòu)值針對(duì)鍵有效顽染,跟值無(wú)關(guān)
- Collection集合的數(shù)據(jù)結(jié)構(gòu)是針對(duì)元素有效
Map常用的子類(lèi):
- Hashtable:內(nèi)部結(jié)構(gòu)是哈希表,是同步的轰绵。不允許null作為鍵粉寞,null作為值。
- Properties:用來(lái)存儲(chǔ)鍵值對(duì)型的配置文件的信息左腔,可以和IO技術(shù)相結(jié)合唧垦。
- HashMap:內(nèi)部結(jié)構(gòu)式哈希表,不是同步的液样。允許null作為鍵振亮,null作為值。
- TreeMap:內(nèi)部結(jié)構(gòu)式二叉樹(shù)鞭莽,不是同步的坊秸。可以對(duì)Map結(jié)合中的鍵進(jìn)行排序澎怒。
- HashSet實(shí)現(xiàn)Set接口褒搔,由哈希表(實(shí)際上是一個(gè)HashMap實(shí)例)支持抄瑟。
5.2 Map集合遍歷
方式1:根據(jù)鍵找值嫂易。獲取所有鍵的集合,遍歷鍵的集合,獲取到每一個(gè)鍵猴誊,根據(jù)鍵找值抖拴。
package cn.itcast;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* Map集合的遍歷绵跷。
* Map -- 夫妻對(duì)
* 思路:
* A:把所有的丈夫給集中起來(lái)硝桩。
* B:遍歷丈夫的集合,獲取得到每一個(gè)丈夫念逞。
* C:讓丈夫去找自己的妻子困食。
*
* 轉(zhuǎn)換:
* A:獲取所有的鍵
* B:遍歷鍵的集合,獲取得到每一個(gè)鍵
* C:根據(jù)鍵去找值
*/
public class MapDemo {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
Map<String, String> map = new HashMap<String, String>();
// 創(chuàng)建元素并添加到集合
map.put("楊過(guò)", "小龍女");
map.put("郭靖", "黃蓉");
map.put("楊康", "穆念慈");
map.put("陳玄風(fēng)", "梅超風(fēng)");
// 遍歷
// 獲取所有的鍵
Set<String> set = map.keySet();
// 遍歷鍵的集合肮柜,獲取得到每一個(gè)鍵
for (String key : set) {
// 根據(jù)鍵去找值
String value = map.get(key);
System.out.println(key + "---" + value);
}
}
}
方式2:根據(jù)鍵值對(duì)對(duì)象找鍵和值陷舅。
- 獲取所有鍵值對(duì)對(duì)象的集合
- 遍歷鍵值對(duì)對(duì)象的集合,獲取到每一個(gè)鍵值對(duì)對(duì)象
- 根據(jù)鍵值對(duì)對(duì)象找鍵和值
package cn.itcast;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* Map集合的遍歷审洞。
* Map -- 夫妻對(duì)
*
* 思路:
* A:獲取所有結(jié)婚證的集合
* B:遍歷結(jié)婚證的集合莱睁,得到每一個(gè)結(jié)婚證
* C:根據(jù)結(jié)婚證獲取丈夫和妻子
*
* 轉(zhuǎn)換:
* A:獲取所有鍵值對(duì)對(duì)象的集合
* B:遍歷鍵值對(duì)對(duì)象的集合,得到每一個(gè)鍵值對(duì)對(duì)象
* C:根據(jù)鍵值對(duì)對(duì)象獲取鍵和值
*
* 這里面最麻煩的就是鍵值對(duì)對(duì)象如何表示呢?
* 看看我們開(kāi)始的一個(gè)方法:
* Set<Map.Entry<K,V>> entrySet():返回的是鍵值對(duì)對(duì)象的集合
*/
public class MapDemo {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
Map<String, String> map = new HashMap<String, String>();
// 創(chuàng)建元素并添加到集合
map.put("楊過(guò)", "小龍女");
map.put("郭靖", "黃蓉");
map.put("楊康", "穆念慈");
map.put("陳玄風(fēng)", "梅超風(fēng)");
// 獲取所有鍵值對(duì)對(duì)象的集合
Set<Map.Entry<String, String>> set = map.entrySet();
// 遍歷鍵值對(duì)對(duì)象的集合芒澜,得到每一個(gè)鍵值對(duì)對(duì)象
for (Map.Entry<String, String> me : set) {
// 根據(jù)鍵值對(duì)對(duì)象獲取鍵和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "---" + value);
}
}
}
3仰剿、HashMap類(lèi)概述
鍵是哈希表結(jié)構(gòu),可以保證鍵的唯一性
4痴晦、LinkedHashMap類(lèi)概述
Map 接口的哈希表和鏈接列表實(shí)現(xiàn)南吮,具有可預(yù)知的迭代順序。
5誊酌、TreeMap類(lèi)概述
鍵是紅黑樹(shù)結(jié)構(gòu)部凑,可以保證鍵的排序和唯一性,自然排序碧浊,比較器排序涂邀。
6、Map集合的應(yīng)用及擴(kuò)展
package cn.itcast;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
/*
* 需求 :"aababcabcdabcde",獲取字符串中每一個(gè)字母出現(xiàn)的次數(shù)要求結(jié)果:a(5)b(4)c(3)d(2)e(1)
*
* 分析:
* A:定義一個(gè)字符串(可以改進(jìn)為鍵盤(pán)錄入)
* B:定義一個(gè)TreeMap集合
* 鍵:Character
* 值:Integer
* C:把字符串轉(zhuǎn)換為字符數(shù)組
* D:遍歷字符數(shù)組箱锐,得到每一個(gè)字符
* E:拿剛才得到的字符作為鍵到集合中去找值比勉,看返回值
* 是null:說(shuō)明該鍵不存在,就把該字符作為鍵驹止,1作為值存儲(chǔ)
* 不是null:說(shuō)明該鍵存在浩聋,就把值加1,然后重寫(xiě)存儲(chǔ)該鍵和值
* F:定義字符串緩沖區(qū)變量
* G:遍歷集合臊恋,得到鍵和值衣洁,進(jìn)行按照要求拼接
* H:把字符串緩沖區(qū)轉(zhuǎn)換為字符串輸出
*
* 錄入:linqingxia
* 結(jié)果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
*/
public class TreeMapDemo {
public static void main(String[] args) {
// 定義一個(gè)字符串(可以改進(jìn)為鍵盤(pán)錄入)
Scanner sc = new Scanner(System.in);
System.out.println("請(qǐng)輸入一個(gè)字符串:");
String line = sc.nextLine();
// 定義一個(gè)TreeMap集合
TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
// 把字符串轉(zhuǎn)換為字符數(shù)組
char[] chs = line.toCharArray();
// 遍歷字符數(shù)組,得到每一個(gè)字符
for (char ch : chs) {
// 拿剛才得到的字符作為鍵到集合中去找值抖仅,看返回值
Integer i = tm.get(ch);
// 是null:說(shuō)明該鍵不存在坊夫,就把該字符作為鍵毙替,1作為值存儲(chǔ)
if (i == null) {
tm.put(ch, 1);
} else {
// 不是null:說(shuō)明該鍵存在,就把值加1践樱,然后重寫(xiě)存儲(chǔ)該鍵和值
i++;
tm.put(ch, i);
}
}
// 定義字符串緩沖區(qū)變量
StringBuilder sb = new StringBuilder();
// 遍歷集合,得到鍵和值凸丸,進(jìn)行按照要求拼接
Set<Character> set = tm.keySet();
for (Character key : set) {
Integer value = tm.get(key);
sb.append(key).append("(").append(value).append(")");
}
// 把字符串緩沖區(qū)轉(zhuǎn)換為字符串輸出
String result = sb.toString();
System.out.println("result:" + result);
}
}
示例2:在很多項(xiàng)目中拷邢,應(yīng)用比較多的是一對(duì)多的映射關(guān)系,這就可以通過(guò)嵌套的形式將多個(gè)映射定義到一個(gè)大的集合中屎慢,并將大的集合分級(jí)處理瞭稼,形成一個(gè)體系。
package cn.itcast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
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;
}
}
/*
* 黑馬程序員
* bj 北京校區(qū)
* jc 基礎(chǔ)班
* 林青霞 27
* 風(fēng)清揚(yáng) 30
* jy 就業(yè)班
* 趙雅芝 28
* 武鑫 29
* sh 上海校區(qū)
* jc 基礎(chǔ)班
* 郭美美 20
* 犀利哥 22
* jy 就業(yè)班
* 羅玉鳳 21
* 馬征 23
* gz 廣州校區(qū)
* jc 基礎(chǔ)班
* 王力宏 30
* 李靜磊 32
* jy 就業(yè)班
* 郎朗 31
* 柳巖 33
* xa 西安校區(qū)
* jc 基礎(chǔ)班
* 范冰冰 27
* 劉意 30
* jy 就業(yè)班
* 李冰冰 28
* 張志豪 29
*/
public class HashMapDemo {
public static void main(String[] args) {
// 創(chuàng)建大集合
HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();
// 北京校區(qū)數(shù)據(jù)
HashMap<String, ArrayList<Student>> bjCzbkMap = new HashMap<String, ArrayList<Student>>();
ArrayList<Student> array1 = new ArrayList<Student>();
Student s1 = new Student("林青霞", 27);
Student s2 = new Student("風(fēng)清揚(yáng)", 30);
array1.add(s1);
array1.add(s2);
ArrayList<Student> array2 = new ArrayList<Student>();
Student s3 = new Student("趙雅芝", 28);
Student s4 = new Student("武鑫", 29);
array2.add(s3);
array2.add(s4);
bjCzbkMap.put("基礎(chǔ)班", array1);
bjCzbkMap.put("就業(yè)班", array2);
czbkMap.put("北京校區(qū)", bjCzbkMap);
// 西安校區(qū)數(shù)據(jù)
HashMap<String, ArrayList<Student>> xaCzbkMap = new HashMap<String, ArrayList<Student>>();
ArrayList<Student> array3 = new ArrayList<Student>();
Student s5 = new Student("范冰冰", 27);
Student s6 = new Student("劉意", 30);
array3.add(s5);
array3.add(s6);
ArrayList<Student> array4 = new ArrayList<Student>();
Student s7 = new Student("李冰冰", 28);
Student s8 = new Student("張志豪", 29);
array4.add(s7);
array4.add(s8);
xaCzbkMap.put("基礎(chǔ)班", array3);
xaCzbkMap.put("就業(yè)班", array4);
czbkMap.put("西安校區(qū)", xaCzbkMap);
// 遍歷集合
Set<String> czbkMapSet = czbkMap.keySet();
for (String czbkMapKey : czbkMapSet) {
System.out.println(czbkMapKey);
HashMap<String, ArrayList<Student>> czbkMapValue = czbkMap
.get(czbkMapKey);
Set<String> czbkMapValueSet = czbkMapValue.keySet();
for (String czbkMapValueKey : czbkMapValueSet) {
System.out.println("\t" + czbkMapValueKey);
ArrayList<Student> czbkMapValueValue = czbkMapValue
.get(czbkMapValueKey);
for (Student s : czbkMapValueValue) {
System.out.println("\t\t" + s.getName() + "---"
+ s.getAge());
}
}
}
}
}
運(yùn)行結(jié)果:
6. 集合框架的綜合應(yīng)用
代碼示例:模擬斗地主洗牌和發(fā)牌
package cn.itcast_04;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
/*
* 思路:
* A:創(chuàng)建一個(gè)HashMap集合
* B:創(chuàng)建一個(gè)ArrayList集合
* C:創(chuàng)建花色數(shù)組和點(diǎn)數(shù)數(shù)組
* D:從0開(kāi)始往HashMap里面存儲(chǔ)編號(hào)腻惠,并存儲(chǔ)對(duì)應(yīng)的牌
* 同時(shí)往ArrayList里面存儲(chǔ)編號(hào)即可环肘。
* E:洗牌(洗的是編號(hào))
* F:發(fā)牌(發(fā)的也是編號(hào),為了保證編號(hào)是排序的集灌,就創(chuàng)建TreeSet集合接收)
* G:看牌(遍歷TreeSet集合悔雹,獲取編號(hào),到HashMap集合找對(duì)應(yīng)的牌)
*/
public class PokerDemo {
public static void main(String[] args) {
// 創(chuàng)建一個(gè)HashMap集合
HashMap<Integer, String> hm = new HashMap<Integer, String>();
// 創(chuàng)建一個(gè)ArrayList集合
ArrayList<Integer> array = new ArrayList<Integer>();
// 創(chuàng)建花色數(shù)組和點(diǎn)數(shù)數(shù)組
// 定義一個(gè)花色數(shù)組
String[] colors = { "?", "?", "?", "?" };
// 定義一個(gè)點(diǎn)數(shù)數(shù)組
String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
"K", "A", "2", };
// 從0開(kāi)始往HashMap里面存儲(chǔ)編號(hào)欣喧,并存儲(chǔ)對(duì)應(yīng)的牌,同時(shí)往ArrayList里面存儲(chǔ)編號(hào)即可腌零。
int index = 0;
for (String number : numbers) {
for (String color : colors) {
String poker = color.concat(number);
hm.put(index, poker);
array.add(index);
index++;
}
}
hm.put(index, "小王");
array.add(index);
index++;
hm.put(index, "大王");
array.add(index);
// 洗牌(洗的是編號(hào))
Collections.shuffle(array);
// 發(fā)牌(發(fā)的也是編號(hào),為了保證編號(hào)是排序的唆阿,就創(chuàng)建TreeSet集合接收)
TreeSet<Integer> fengQingYang = new TreeSet<Integer>();
TreeSet<Integer> linQingXia = new TreeSet<Integer>();
TreeSet<Integer> liuYi = new TreeSet<Integer>();
TreeSet<Integer> diPai = new TreeSet<Integer>();
for (int x = 0; x < array.size(); x++) {
if (x >= array.size() - 3) {
diPai.add(array.get(x));
} else if (x % 3 == 0) {
fengQingYang.add(array.get(x));
} else if (x % 3 == 1) {
linQingXia.add(array.get(x));
} else if (x % 3 == 2) {
liuYi.add(array.get(x));
}
}
// 看牌(遍歷TreeSet集合益涧,獲取編號(hào),到HashMap集合找對(duì)應(yīng)的牌)
lookPoker("風(fēng)清揚(yáng)", fengQingYang, hm);
lookPoker("林青霞", linQingXia, hm);
lookPoker("劉意", liuYi, hm);
lookPoker("底牌", diPai, hm);
}
// 寫(xiě)看牌的功能
public static void lookPoker(String name, TreeSet<Integer> ts,
HashMap<Integer, String> hm) {
System.out.print(name + "的牌是:");
for (Integer key : ts) {
String value = hm.get(key);
System.out.print(value + " ");
}
System.out.println();
}
}
運(yùn)行結(jié)果: