学习内容:
一、Map集合体系
二、Map常用方法
三、Map集合的2种遍历
四、JDK9的新特性
五、斗地主发牌案例(排序练习)
六、Debug调试
一、Map集合体系
和之间的集合体系不同,之前所学的集合都是单列集合(即Collection集合是单列集合,只有一个泛型),而Map集合是一个双列集合(有两个泛型),每一个元素其实是一个【键值对】(包含键-key 值-value,而key和value的数据类型可以相同或不同),key是唯一的,但value可以重复
Map集合接口的实现类:
HashMap
哈希表结构(数组+链表/红黑树)(即当链表的长度大于8时就转换为红黑树结构存储,查询快)
特点:
1).不允许键重复,允许值重复(不会出现两个相同的键)
2).无序的
3).线程不安全、效率高,速度快,是多线程集合
4).可以存储空值,空键
【HashSet集合的底层还是HashMap】
LinkedHashMap(HashMap的子类)
基于链表的哈希表结构(数组+链表/红黑树)
特点:
1).不允许键重复,允许值重复
2).元素是有序的
3).保证存入与获取元素的顺序一致
Hashtable(不常用)
基于链表的哈希表结构(数组+链表/红黑树)
特点:
1).不允许键重复,允许值重复
2).有序的
3).线程安全,效率低
4).不能存储空值,空键
【Hashtable和Vector集合一样,在jdk1.2版本之后都被更好的集合(HashMap,ArrayList)取代了。但是Hashtable的子类Properties任然在被使用–>因为Properties集合是唯一一个和IO流相结合的集合】
二、Map的常用方法
public V put(K keym,V value)
往集合里面添加键和值,如果键重复,就新的值替换旧的值
返回值:返回被替换的值(如果第一次存入键值对,返回值:null)
public V get(K key)
根据键获取值
返回值:返回该键对应的值
public V remove(K key)
根据键移除整个键值对
返回值:返回被移除键对应的值
public boolean containsKey(K key)
判断集合中是否包含指定键
返回值:如果包含:ture 不包含:返回false
public Set keySet()
获取所有的键组成的Set集合,即集合中所有的键存储到Set集合中并返回这个集合
public Set> entrySet()
把集合中所有的【键值对】获取出来,放在Set集合中
【键值对】:Map.Entry来表示每一个键值对的对象
小练习:
键盘录入一个字符串,求处每一个字符出现的次数
理解:得到键盘录入的字符串,通过遍历获取每个字符,并作为键存入map集合中,通过值记录存入相同键的个数
代码实现:
package com.itheima.Demo;
import java.util.HashMap;
import java.util.Scanner;
//键盘录入一个字符串,求处每一个字符出现的次数(利用HashMap实现)
public class Test {
public static void main(String[] args) {
//1)键盘录入一个字符串,使用Scanner
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = scanner.nextLine();
//2)创建HashMap 键(字符),值(次数)
HashMap map = new HashMap<>();
//3)遍历字符串获取每一个字符ch
for (int i = 0; i < str.length(); i++) {
char key = str.charAt(i);//获取字符串中的每个字符
if(!map.containsKey(key)){
map.put(key,1);//如果第一次存入的键值对,value默认为1
}else {
Integer value = map.get(key)+1;//如果存入的键已存在,其获取value并加1
map.put(key,value);//把key和新的value作为键值对存入map集合中
}
}
//4)打印Map集合
System.out.println(map);
}
}
允许结果:
请输入一个字符串:
hello world
{ =1, r=1, d=1, e=1, w=1, h=1, l=3, o=2}
三、Map集合的遍历
Map集合的两种遍历方式:
public static void test01() {
//方式1:【键找值】
//1.创建HashMap集合对象,并存入键值对
HashMap map = new HashMap<>();
map.put("杨过","小龙女");
map.put("令狐冲","任盈盈");
map.put("石破天","白阿秀");
map.put("郭靖","黄蓉");
//打印map集合
System.out.println(map);
//2.获取所有的键,并存放在Set集合中
Set keys = map.keySet();
//3.遍历Set集合,通过键获取值
for (String key : keys) {
String value = map.get(key);
System.out.println(key+"-->"+value);
}
}
运行结果:
//无序的
{令狐冲=任盈盈, 杨过=小龙女, 石破天=白阿秀, 郭靖=黄蓉}
令狐冲-->任盈盈
杨过-->小龙女
石破天-->白阿秀
郭靖-->黄蓉
//方式二:【获取键值对】
//1.创建HashMap集合对象,并存入键值对
HashMap map = new HashMap<>();
map.put("张三","北京");
map.put("李四","上海");
map.put("王五","广州");
map.put("王五","深圳");
//2.通过entrySet()方法获取集合中所有的【键值对】,存放在Set集合中
Set> entries = map.entrySet();
for (Map.Entry entry : entries) {
//获取键
String key = entry.getKey();
//获取值
String value = entry.getValue();
//3.打印集合
System.out.println(key+"--"+value);
}
运行结果:
//无序的
李四--上海
张三--北京
王五--深圳//如果键重复就替换旧的值
四、JDK9的新特性
List、Set、Map提供了一个静态的of方法,用来一次性添加多个元素。
public static void demo03() {
//jdk9的新特性
//向list集合内添加元素
List list = List.of("hello", "java", "world");
//向set集合添加元素
Set set = Set.of("hello", "world", "java");
//向map集合中添加元素
Map map1 = Map.of("张三", 13, "李四", 17, "王五", 18);
System.out.println(list);
System.out.println(set);
System.out.println(map1);
}
运行结果:
[hello, java, world]
[world, hello, java]
{张三=13, 李四=17, 王五=18}
对LinkedHashMap的理解:LinkedHashMap使得元素存入的顺序和取出的顺序一致
public static void test04() {
LinkedHashMap map = new LinkedHashMap<>();//LinkedHashMap使得元素有序排列
//存入自定义对象
map.put(new Student("张三", 18), "上海");
map.put(new Student("李四",19),"北京");
map.put(new Student("王五",20),"深圳");
Set> entries = map.entrySet();
for (Map.Entry entry : entries) {
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"现居"+value);
}
运行结果:
Student{name='张三', age=18}现居上海
Student{name='李四', age=19}现居北京
Student{name='王五', age=20}现居深圳
【注意:生成的集合是一个固定的集合,不能改变。】
package com.itheima.PokerGame01;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class PokerGame {
public static void main(String[] args) {
//1.准备牌
List colors=List.of("♥","♠","♦","♣");
List nums = List.of("2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");
//创建集合存放键值对
HashMap map = new HashMap<>();
//list集合专门用来存储键(序号)用于后期洗牌(这样就可以借助List集合特有接口Collections提供的shuffle方法打乱集合中的元素顺序和sort方法对集合元素的排序实现洗牌,和对每个玩家的牌的排序)
ArrayList list = new ArrayList<>();
//把大小王单独添加到map集合中
int index=0;
map.put(index,"大王");
list.add(index);//单独存入键
index++;
map.put(index,"小王");
list.add(index);//单独存入键
index++;
//把点数和花色拼接成每一张牌
for (String num : nums) {
for (String color : colors) {
//拼接成一张牌
String poker = color+num;
//添加到集合中
map.put(index,poker);
list.add(index);//单独存入每张牌对应的键
index++;
}
}
System.out.println(list.size());
//2.洗牌
Collections.shuffle(list);//传入单独存有键的集合对象
//3.发牌
//创建4个集合
ArrayList player1 = new ArrayList<>();
ArrayList player2 = new ArrayList<>();
ArrayList player3 = new ArrayList<>();
ArrayList loader = new ArrayList<>();
//遍历list集合,发牌
for (int i = 0; i < list.size(); i++) {
Integer p = list.get(i);
if(i>=51){
loader.add(p);
}else if(i%3==0){
player1.add(p);
}else if(i%3==1){
player2.add(p);
}else if(i%3==2){
player3.add(p);
}
}
//4.排序-调用List集合的工具类Collections的sort方法完成对键的排序
Collections.sort(player1);
Collections.sort(player2);
Collections.sort(player3);
//5.调用看牌方法
lookPoker(map, player1);
lookPoker(map, player2);
lookPoker(map, player3);
lookPoker(map, loader);
}
//看牌的实现方法
public static void lookPoker(HashMap map, ArrayList player1) {
for (Integer i : player1) {
String s = map.get(i);//map集合的get(key)-->value
System.out.print(s+" ");
}
System.out.println();
}
}
方法二、
利用面向对象的思想
创建poker类
package com.itheima.PokerGame02;
public class Poker {
private String color;//花色
private int num;//点数(11-J ,12-Q,13-K,14-A,15-2,16-小王,17-大王)
public Poker(String color, int num) {
this.color = color;
this.num = num;
}
public Poker() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
if(num==11){
return color+"J";
}
if(num==12){
return color+"Q";
}
if(num==13){
return color+"K";
}
if(num==14){
return color+"A";
}
if(num==15){
return color+"2";
}
if(num==16){
return "小王";
}
if(num==17){
return "大王";
}
return color+num;
}
}
package com.itheima.PokerGame02;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
斗地主发牌案例(面向对象)-但这种更耗内存(最优程序不能只凭对内存的消耗方面判定,还得看运行时间,独立性,可维护性各方面综合考虑)
1. 定义一个Poker类
属性:花色、点数
2. 创建一个ArrayList集合,存储54个Poker对象
3. 遍历ArrayList集合,分成4个集合(3个玩家、底牌)
4. 分别对4个集合进行排序
5. 打印输出4个集合
*/
public class Test03 {
public static void main(String[] args) {
//1.准备牌
List colors = List.of("♥","♠","♦","♣");
List nums = List.of(3,4,5,6,7,8,9,10,11,12,13,14,15);
//2.使用ArrayList集合存储Poker对象
ArrayList list = new ArrayList<>();
//.把每一种花色和不同点数封装到poker对象里
for (Integer num : nums) {
for (String color : colors) {
Poker poker = new Poker(color, num);//把花色和点数封装到poker对象中,调用有参构造器
list.add(poker);//将此对象存放到list集合中
}
}
//大王和小王单独添加
list.add(new Poker("",16));
list.add(new Poker("",17));
//3.调用List接口的工具类Collections提供的shuffle方法将传入集合中的元素打乱
Collections.shuffle(list);
//4发牌,创建3个玩家集合和一个底牌集合
ArrayList player1 = new ArrayList<>();
ArrayList player2 = new ArrayList<>();
ArrayList player3 = new ArrayList<>();
ArrayList dipai = new ArrayList<>();
//通过遍历实现发牌
for (int i = 0; i < list.size(); i++) {
Poker poker = list.get(i);//通过调用ArrayList提供的get方法,传入索引获取元素(poker对象)并交给Poker类型的变量管理
if(i>=51){
dipai.add(poker);
}else if(i%3==0){
player1.add(poker);
}else if(i%3==1){
player2.add(poker);
}else if(i%3==2){
player3.add(poker);
}
}
//5.排序
//自定义排序规则(创建比较器对象)
Comparator pokerComparator = new Comparator<>() {
@Override
public int compare(Poker o1, Poker o2) {
return o1.getNum()-o2.getNum();//升序排序
}
};
//调用Collections工具类的sort方法实现排序
Collections.sort(player1,pokerComparator);
Collections.sort(player2,pokerComparator);
Collections.sort(player3,pokerComparator);
Collections.sort(dipai,pokerComparator);
//6.看牌
System.out.println(player1);
System.out.println(player2);
System.out.println(player3);
System.out.println(dipai);
}
}
运行结果:
54
小王 ♦A ♣K ♣Q ♠J ♦J ♥10 ♦10 ♣10 ♥9 ♦8 ♣8 ♠6 ♠5 ♦5 ♣5 ♠4
♣2 ♠A ♣A ♥K ♠K ♦Q ♥J ♠9 ♣9 ♥8 ♠7 ♦7 ♣7 ♥6 ♥4 ♦4 ♣3
大王 ♥2 ♠2 ♥A ♦K ♥Q ♠Q ♣J ♠10 ♦9 ♥7 ♦6 ♥5 ♣4 ♥3 ♠3 ♦3
♠8 ♣6 ♦2
六、Debug调试【重点】
Debug可以让程序一步一步的执行,便于观察程序的执行流程,变量的变化情况。调试程序出现的bug
使用大体步骤
1)打断点
在代码编辑区域的最左边,点击即可(出现一个小圆点)
2)Debug执行
代码会停在打断点的那一行
单步执行(f8)
让代码逐行执行
进入方法执行(f7)
执行到下一个断点(f9)
停止调试(ctrl+f2)
详细图文说明:
1.在有效代码行,点击行号右边的空白区域,设置断点,程序执行到断点将停止,我们可以手动来运行程序
2.点击Debug运行模式
3.程序停止在断点上不再执行,而IDEA最下方打开了Debug调试窗口
4.Debug调试窗口介绍
5.快捷键F8,代码向下执行一行,第九行执行完毕,执行到第十行(还未执行)
6.点击切换到控制台面板
7.继续F8,程序继续向后执行,执行键盘录入操作,在控制台录入字符串
8.此时执行到findChar方法,快捷键F7,进入方法findChar里
9.继续快捷键F8,程序继续执行,创建了map对象,变量区域显示
10.快捷键F8继续执行,进入到循环中,循环变量i=0,F8再继续执行
11.继续F8,进入到判断语句中,应为该字符不再Map集合键集中,再按F8执行,进入该判断中
12.继续F8执行,循环结束,进入下一次循环,此时map集合中已经存在一对元素
13.继续F8,进入下次循环,再继续上面的操作,我们就可以看到代码每次是如何执行的了
14.F9让程序直接执行下去,跳出debug
Java第16天学习内容链接:
https://blog.csdn.net/LJN951118/article/details/89256443