Map集合概述和特點
- A:Map接口概述
- 查看API可以知道:
- 將鍵映射到值的對象
- 一個映射不能包含重復的鍵
- 每個鍵最多只能映射到一個值
- 查看API可以知道:
- B:Map接口和Collection接口的不同
- Map是雙列的,Collection是單列的
- Map的鍵唯一,Collection的子體系Set是唯一的
- Map集合的數據結構值針對鍵有效,跟值無關;Collection集合的數據結構是針對元素有效
Map集合的功能概述
- A:Map集合的功能概述
- a:添加功能
- V put(K key,V value):添加元素。
- 如果鍵是第一次存儲,就直接存儲元素,返回null
- 如果鍵不是第一次存在,就用值把以前的值替換掉,返回以前的值
- V put(K key,V value):添加元素。
- b:刪除功能
- void clear():移除所有的鍵值對元素
- V remove(Object key):根據鍵刪除鍵值對元素,並把值返回
- c:判斷功能
- boolean containsKey(Object key):判斷集合是否包含指定的鍵
- boolean containsValue(Object value):判斷集合是否包含指定的值
- boolean isEmpty():判斷集合是否為空
- d:獲取功能
- Set<Map.Entry<K,V>> entrySet():
- V get(Object key):根據鍵獲取值
- Set
keySet():獲取集合中所有鍵的集合 - Collection
values():獲取集合中所有值的集合
- e:長度功能
- int size():返回集合中的鍵值對的個數
- a:添加功能
package com.hwh.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class Demo1_Map {
public static void main(String[] args) {
//demo1();
//demo2();
Map<String, Integer> map = new HashMap<>();
map.put("張三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("趙六", 26);
Collection<Integer> c = map.values();
System.out.println(c);//[24, 23, 25, 26]
System.out.println(map.size());//4
}
public static void demo2() {
Map<String, Integer> map = new HashMap<>();
map.put("張三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("趙六", 26);
//Integer value = map.remove("張三"); //根據鍵刪除元素,返回鍵對應的值
//System.out.println(value);//23
System.out.println(map.containsKey("張三")); //true //判斷是否包含傳入的鍵
System.out.println(map.containsValue(100)); //false //判斷是否包含傳入的值
System.out.println(map);//{李四=24, 張三=23, 王五=25, 趙六=26}
}
public static void demo1() {
Map<String, Integer> map = new HashMap<>();
Integer i1 = map.put("張三", 23);
Integer i2= map.put("李四", 24);
Integer i3 = map.put("王五", 25);
Integer i4 = map.put("趙六", 26);
Integer i5 = map.put("張三", 26); //相同的鍵不存儲,值覆蓋,把被覆蓋的值返回
System.out.println(map);//{李四=24, 張三=26, 王五=25, 趙六=26}
System.out.println(i1);//null
System.out.println(i2);//null
System.out.println(i3);//null
System.out.println(i4);//null
System.out.println(i5);//23
}
}
Map集合的遍歷之鍵找值
- 鍵找值思路:
- 獲取所有鍵的集合
- 遍歷鍵的集合,獲取到每一個鍵
- 根據鍵找值
package com.hwh.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo2_Iterator {
/**
* 通過查看Map集合的api發現沒有iterator方法,那么雙列集合如何迭代呢?
* 根據鍵獲取值
*/
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("張三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("趙六", 26);
//Integer i = map.get("張三"); //根據鍵獲取值
//System.out.println(i);//23
//獲取所有的鍵
//使用迭代器方法遍歷
/*Set<String> keySet = map.keySet(); //獲取所有鍵的集合
Iterator<String> it = keySet.iterator(); //獲取迭代器
while(it.hasNext()) { //判斷集合中是否有元素
String key = it.next(); //獲取每一個鍵
Integer value = map.get(key); //根據鍵獲取值
System.out.println(key + "=" + value);//李四=24 張三=23 王五=25 趙六=26
}*/
//使用增強for循環遍歷
for(String key : map.keySet()) { //map.keySet()是所有鍵的集合
System.out.println(key + "=" + map.get(key));////李四=24 張三=23 王五=25 趙六=26
}
}
}
Map集合的遍歷之鍵值對對象找鍵和值
- 鍵值對對象找鍵和值思路:
- 獲取所有鍵值對對象的集合
- 遍歷鍵值對對象的集合,獲取到每一個鍵值對對象
- 根據鍵值對對象找鍵和值
package com.hwh.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Demo3_Iterator {
/**
* Map集合的第二種迭代,根據鍵值對對象,獲取鍵和值
*/
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("張三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("趙六", 26);
//Map.Entry說明Entry是Map的內部接口,將鍵和值封裝成了Entry對象,並存儲在Set集合中
/*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
//獲取每一個對象
Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
while(it.hasNext()) {
//獲取每一個Entry對象
Map.Entry<String, Integer> en = it.next(); //父類引用指向子類對象
//Entry<String, Integer> en = it.next(); //直接獲取的是子類對象
String key = en.getKey(); //根據鍵值對對象獲取鍵
Integer value = en.getValue(); //根據鍵值對對象獲取值
System.out.println(key + "=" + value);//李四=24 張三=23 王五=25 趙六=26
}*/
for(Entry<String, Integer> en : map.entrySet()) {
System.out.println(en.getKey() + "=" + en.getValue());//李四=24 張三=23 王五=25 趙六=26
}
}
}
HashMap集合鍵是Student值是String的案例
創建學生類alt shift s +c +o +r +s +h
package com.hwh.bean;
public 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;
}
@Override
public String toString() {
return "Student [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;
Student other = (Student) 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;
}
}
package com.hwh.map;
import java.util.HashMap;
import com.hwh.bean.Student;
public class Demo5_HashMap {
/*
* HashMap集合鍵是Student值是String的案例
* 鍵是學生對象,代表每一個學生
* 值是字符串對象,代表學生歸屬地
*/
public static void main(String[] args) {
HashMap<Student, String> hm = new HashMap<>();
hm.put(new Student("張三", 23), "北京");
hm.put(new Student("張三", 23), "上海");
hm.put(new Student("李四", 24), "廣州");
hm.put(new Student("王五", 25), "深圳");
System.out.println(hm);
}
}
運行結果{Student [name=張三, age=23]=上海, Student [name=李四, age=24]=廣州, Student [name=王五, age=25]=深圳}
LinkedHashMap的概述和使用
- LinkedHashMap的特點
- 底層是鏈表實現的可以保證怎么存就怎么取
package com.hwh.map;
import java.util.LinkedHashMap;
public class Demo6_LinkedHashMap {
public static void main(String[] args) {
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
lhm.put("張三", 23);
lhm.put("李四", 24);
lhm.put("趙六", 26);
lhm.put("王五", 25);
System.out.println(lhm);//{張三=23, 李四=24, 趙六=26, 王五=25}
}
}
TreeMap集合鍵是Student值是String的案例
學生類實現Comparable接口, Ctrl+1
重寫compareTo
public class Student implements Comparable<Student>{
..............
@Override
public int compareTo(Student o) {
int num = this.age - o.age; //以年齡為主要條件
return num == 0 ? this.name.compareTo(o.name) : num;
}
package com.hwh.map;
import java.util.Comparator;
import java.util.TreeMap;
import com.hwh.bean.Student;
public class Demo7_TreeMap {
public static void main(String[] args) {
//demo1();
TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getName().compareTo(s2.getName()); //按照姓名比較
return num == 0 ? s1.getAge() - s2.getAge() : num;
}
});
tm.put(new Student("張三", 23), "北京");
tm.put(new Student("李四", 13), "上海");
tm.put(new Student("王五", 33), "廣州");
tm.put(new Student("趙六", 43), "深圳");
System.out.println(tm);//{Student [name=張三, age=23]=北京, Student [name=李四, age=13]=上海, Student [name=王五, age=33]=廣州, Student [name=趙六, age=43]=深圳}
}
public static void demo1() {
TreeMap<Student, String> tm = new TreeMap<>();
tm.put(new Student("張三", 23), "北京");
tm.put(new Student("李四", 13), "上海");
tm.put(new Student("王五", 33), "廣州");
tm.put(new Student("趙六", 43), "深圳");
System.out.println(tm);//{Student [name=李四, age=13]=上海, Student [name=張三, age=23]=北京, Student [name=王五, age=33]=廣州, Student [name=趙六, age=43]=深圳}
}
}
統計字符串中每個字符出現的次數
package com.hwh.test;
import java.util.HashMap;
public class Test1 {
/**
* 分析:
* 1,定義一個需要被統計字符的字符串
* 2,將字符串轉換為字符數組
* 3,定義雙列集合,存儲字符串中字符以及字符出現的次數
* 4,遍歷字符數組獲取每一個字符,並將字符存儲在雙列集合中
* 5,存儲過程中要做判斷,如果集合中不包含這個鍵,就將該字符當作鍵,值為1存儲,如果集合中包含這個鍵,就將值加1存儲
* 6,打印雙列集合獲取字符出現的次數
*/
public static void main(String[] args) {
//1,定義一個需要被統計字符的字符串
String s = "aaaabbbbbccccccccccccc";
//2,將字符串轉換為字符數組
char[] arr = s.toCharArray();
//3,定義雙列集合,存儲字符串中字符以及字符出現的次數
HashMap<Character, Integer> hm = new HashMap<>();
//4,遍歷字符數組獲取每一個字符,並將字符存儲在雙列集合中
for(char c: arr) {
//5,存儲過程中要做判斷,如果集合中不包含這個鍵,就將該字符當作鍵,值為1存儲,如果集合中包含這個鍵,就將值加1存儲
/*if(!hm.containsKey(c)) { //如果不包含這個鍵
hm.put(c, 1);
}else {
hm.put(c, hm.get(c) + 1);
}*/
hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
}
//6,打印雙列集合獲取字符出現的次數
for (Character key : hm.keySet()) { //hm.keySet()代表所有鍵的集合
System.out.println(key + "=" + hm.get(key));//hm.get(key)根據鍵獲取值
}
}
}
運行結果為a=4 b=5 c=13
集合嵌套之HashMap嵌套HashMap
package com.hwh.map;
import java.util.HashMap;
import com.hwh.bean.Student;
public class Demo8_HashMapHashMap {
public static void main(String[] args) {
/**
* 需求:
* 學校有很多班
* 第88班定義成一個雙列集合,鍵是學生對象,值是學生的歸屬地
* 第99班定義成一個雙列集合,鍵是學生對象,值是學生的歸屬地
*
* 無論88還是99都是班級對象,所以為了便於統一管理,把這些班級對象添加到學校集合中
*/
//定義88班
HashMap<Student, String> hm88 = new HashMap<>();//Student類要重寫hashCode和equals//hm88選中alt shift r修改整塊hashmap名
hm88.put(new Student("張三", 23), "北京");
hm88.put(new Student("李四", 24), "北京");
hm88.put(new Student("王五", 25), "上海");
hm88.put(new Student("趙六", 26), "廣州");
//定義99班
HashMap<Student, String> hm99 = new HashMap<>();
hm99.put(new Student("唐僧", 1023), "北京");
hm99.put(new Student("孫悟空",1024), "北京");
hm99.put(new Student("豬八戒",1025), "上海");
hm99.put(new Student("沙和尚",1026), "廣州");
//定義學校
HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
hm.put(hm88, "第88班");
hm.put(hm99, "第99班");
//遍歷雙列集合
for(HashMap<Student, String> h : hm.keySet()) { //hm.keySet()代表的是雙列集合中鍵的集合
String value = hm.get(h); //get(h)根據鍵對象獲取值對象
//遍歷鍵的雙列集合對象
for(Student key : h.keySet()) { //h.keySet()獲取集合總所有的學生鍵對象
String value2 = h.get(key);
System.out.println(key + "=" + value2 + "=" + value);
}
}
}
}
運行結果為Student [name=唐僧, age=1023]=北京=第99班
Student [name=沙和尚, age=1026]=廣州=第99班
Student [name=孫悟空, age=1024]=北京=第99班
Student [name=豬八戒, age=1025]=上海=第99班
Student [name=張三, age=23]=北京=第88班
Student [name=李四, age=24]=北京=第88班
Student [name=趙六, age=26]=廣州=第88班
Student [name=王五, age=25]=上海=第88班
HashMap和Hashtable的區別
- Hashtable是JDK1.0版本出現的,是線程安全的,效率低,HashMap是JDK1.2版本出現的,是線程不安全的,效率高
- Hashtable不可以存儲null鍵和null值,HashMap可以存儲null鍵和null值
package com.hwh.map;
import java.util.HashMap;
import java.util.Hashtable;
public class Demo9_Hashtable {
public static void main(String[] args) {
/**
* HashMap和Hashtable的區別
* 共同點:
* 底層都是哈希算法,都是雙列集合
* 區別:
* 1,HashMap是線程不安全的,效率高,JDK1.2版本
* Hashtable是線程安全的,效率低,JDK1.0版本的
* 2,HashMap可以存儲null鍵和null值
* Hashtable不可以存儲null鍵和null值
*/
HashMap<String, Integer> hm = new HashMap<>();
hm.put(null, 23);
hm.put("李四", null);
System.out.println(hm);//{null=23, 李四=null}
/*Hashtable<String, Integer> ht = new Hashtable<>();
ht.put(null, 23);//java.lang.NullPointerException
ht.put("張三", null);//java.lang.NullPointerException
System.out.println(ht);*/
}
}
Collections工具類的概述和常見方法
-
Collections成員方法
-
public static
void sort(List list)
public staticint binarySearch(List<?> list,T key)
public staticT max(Collection<?> coll)
public static void reverse(List<?> list)
public static void shuffle(List<?> list) -
binarySearch如果搜索鍵包含在列表中,則返回搜索鍵的索引;否則返回 (-(插入點) - 1)
package com.hwh.collections;
import java.util.ArrayList;
import java.util.Collections;
public class Demo1_Collections {
public static void main(String[] args) {
//demo1();
//demo2();
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("c");
list.add("d");
list.add("g");
list.add("f");
System.out.println(Collections.max(list)); //g //根據默認排序結果獲取集合中的最大值
Collections.reverse(list); //反轉集合
System.out.println(list);//[f, g, d, c, a]
Collections.shuffle(list); //隨機置換,可以用來洗牌
System.out.println(list);//每次結果不一樣
}
public static void demo2() {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("c");
list.add("d");
list.add("f");
list.add("g");
System.out.println(Collections.binarySearch(list, "c"));//1
System.out.println(Collections.binarySearch(list, "b"));//-2
}
public static void demo1() {
ArrayList<String> list = new ArrayList<>();
list.add("c");
list.add("a");
list.add("a");
list.add("b");
list.add("d");
System.out.println(list);//[c, a, a, b, d]
Collections.sort(list); //將集合排序
System.out.println(list);//[a, a, b, c, d]
}
}
模擬斗地主洗牌和發牌
package com.hwh.test;
import java.util.ArrayList;
import java.util.Collections;
public class Test2 {
public static void main(String[] args) {
/**
* 模擬斗地主洗牌和發牌,牌沒有排序
* 分析:
* 1,買一副撲克,其實就是自己創建一個集合對象,將撲克牌存儲進去
* 2,洗牌
* 3,發牌
* 4,看牌
*/
//1,買一副撲克,其實就是自己創建一個集合對象,將撲克牌存儲進去
String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] color = {"紅桃","黑桃","方片","梅花"};
ArrayList<String> poker = new ArrayList<>();
//拼接花色和數字
for(String s1 : color) {
for(String s2 : num) {
poker.add(s1.concat(s2)); //concat連接兩個字符串
}
}
poker.add("小王");
poker.add("大王");
//2,洗牌
Collections.shuffle(poker);
//3,發牌
ArrayList<String> gaojin = new ArrayList<>();
ArrayList<String> longwu = new ArrayList<>();
ArrayList<String> me = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
for(int i = 0; i < poker.size(); i++) {
if(i >= poker.size() - 3) {
dipai.add(poker.get(i)); //將三張底牌存儲在底牌集合中
} else if(i % 3 == 0) {
gaojin.add(poker.get(i));
} else if(i % 3 == 1) {
longwu.add(poker.get(i));
} else {
me.add(poker.get(i));
}
}
//4,看牌
System.out.println(gaojin);
System.out.println(longwu);
System.out.println(me);
System.out.println(dipai);
}
}
運行結果為
[紅桃4, 小王, 梅花7, 方片5, 方片7, 紅桃7, 黑桃7, 梅花5, 梅花Q, 大王, 黑桃K, 方片6, 黑桃6, 方片4, 梅花10, 梅花6, 梅花A]
[梅花2, 紅桃3, 方片10, 梅花4, 黑桃3, 方片A, 方片2, 黑桃10, 紅桃6, 方片9, 黑桃9, 方片Q, 黑桃5, 黑桃4, 紅桃5, 方片K, 梅花9]
[黑桃8, 紅桃8, 梅花K, 紅桃A, 方片3, 黑桃J, 紅桃Q, 黑桃2, 方片8, 紅桃J, 梅花3, 黑桃Q, 梅花J, 梅花8, 紅桃K, 紅桃10, 方片J]
[黑桃A, 紅桃2, 紅桃9]
模擬斗地主洗牌和發牌並對牌進行排序的原理圖解
模擬斗地主洗牌和發牌並對牌進行排序的代碼實現
package com.hwh.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class Test3 {
public static void main(String[] args) {
/**
* 分析:
* 1,買一副撲克,其實就是自己創建一個集合對象,將撲克牌存儲進去
* 2,洗牌
* 3,發牌
* 4,看牌
*/
//1,買一副撲克,其實就是自己創建一個集合對象,將撲克牌存儲進去
String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] color = {"紅桃","黑桃","方片","梅花"};
HashMap<Integer, String> hm = new HashMap<>(); //存儲索引和撲克牌
ArrayList<Integer> list = new ArrayList<>(); //存儲索引
int index = 0;
//拼接撲克牌並索引和撲克牌存儲在hm中
for(String s1 : num) { //獲取數字
for(String s2 : color) { //獲取顏色
hm.put(index, s2.concat(s1));
list.add(index); //將索引0到51添加到list集合中
index++;
}
}
//將小王添加到雙列集合中
hm.put(index, "小王");
list.add(index); //將52索引添加到集合中
index++;
hm.put(index, "大王");
list.add(index); //將52索引添加到集合中
//2,洗牌
Collections.shuffle(list);
//3,發牌
TreeSet<Integer> gaojin = new TreeSet<>();
TreeSet<Integer> longwu = new TreeSet<>();
TreeSet<Integer> me = new TreeSet<>();
TreeSet<Integer> dipai = new TreeSet<>();
for(int i = 0; i < list.size(); i++) {
if(i >= list.size() - 3) {
dipai.add(list.get(i)); //將三張底牌存儲在底牌集合中
}else if(i % 3 == 0) {
gaojin.add(list.get(i));
}else if(i % 3 == 1) {
longwu.add(list.get(i));
}else {
me.add(list.get(i));
}
}
//看牌
lookPoker(hm, gaojin, "高進");
lookPoker(hm, longwu, "龍五");
lookPoker(hm, me, "馮佳");
lookPoker(hm, dipai, "底牌");
}
/*
* 看牌
* 1,返回值類型void
* 2,參數列表HashMap,TreeSet,String name
*/
public static void lookPoker(HashMap<Integer, String> hm,TreeSet<Integer> ts ,String name) {
System.out.print(name + "的牌是:");
for(Integer i : ts) { //i代表雙列集合中的每一個鍵
System.out.print(hm.get(i) + " ");
}
System.out.println();
}
}
運行結果為
高進的牌是:方片3 梅花4 黑桃5 方片5 紅桃6 方片8 梅花8 紅桃10 方片10 梅花10 黑桃J 梅花J 紅桃K 梅花K 紅桃2 黑桃2 方片2
龍五的牌是:紅桃3 紅桃4 黑桃6 紅桃7 梅花7 紅桃8 紅桃J 方片J 紅桃Q 黑桃Q 方片Q 黑桃K 方片K 黑桃A 梅花A 梅花2 大王
馮佳的牌是:黑桃3 梅花3 方片4 紅桃5 梅花5 方片6 梅花6 黑桃7 黑桃8 紅桃9 黑桃9 梅花9 黑桃10 梅花Q 紅桃A 方片A 小王
底牌的牌是:黑桃4 方片7 方片9