一、Map(图):双列,类似链表
1.1 格式:
Interface Map<K,V> K:键的类型; V:值的类型
Map集合的概述:
将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
举例:学生的学号和姓名
001 帕梅拉
002 斯塔克
003 皮特
创建Map集合的对象
多态的方式实现:
用HashMap(实现类)
HashMap的特点:
①无序,键值不可重复
1.2 Map集合的基本功能:
V put(K key,V value):添加元素
V remove(Object key):根据键删除键值对的元素
void clear():移除所有的键值对元素
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
int size():集合的长度,也就是集合中键值对的个数
功能测试:
public class MapTest02 {
public static void main(String[] args) {
//创建HashMap集合对象
Map<String,String> hashMap = new HashMap<String,String>();
//V put(K key,V value):添加元素
hashMap.put("Stark","Pamela");
hashMap.put("美羊羊","沸羊羊");
hashMap.put("大乔","小乔");
hashMap.put("Rose","Jisoo");
//V remove(Object key):根据键删除键值对的元素
/*System.out.println(hashMap.remove("Rose"));
System.out.println(hashMap.remove("List"));*/
//void clear():移除所有的键值对元素
//hashMap.clear();
//boolean containsKey(Object key):判断集合是否包含指定的键
System.out.println(hashMap.containsKey("大乔")); //true
System.out.println(hashMap.containsKey("中乔")); //false
//boolean containsValue(Object value):判断集合是否包含指定的值
System.out.println(hashMap.containsValue("Pamela"));//true
System.out.println(hashMap.containsValue("Lara"));//false
//boolean isEmpty():判断集合是否为空
System.out.println(hashMap.isEmpty());//false
//int size():集合的长度,也就是集合中键值对的个数
System.out.println(hashMap.size());//4
//输出集合对象
System.out.println(hashMap);
}
}
输出结果:
true
false
true
false
false
4
{美羊羊=沸羊羊, 大乔=小乔, Rose=Jisoo, Stark=Pamela}
1.3 Map集合的获取功能
V get(Object key):根据键获取值
Set KeySet():获取所有键的集合,键是唯一的所以返回Set集合
Collection values():获取所有值,值并不知道是不是可重复的所以返回Collection集合
Set<Map.Entry<K,V>>entrySet():获取所有键值对象的集合
功能测试:
public class MapTest03 {
public static void main(String[] args) {
//创建HashMap集合对象
Map<String,String> hashMap = new HashMap<String,String>();
//V put(K key,V value):添加元素
hashMap.put("Stark","Pamela");
hashMap.put("美羊羊","沸羊羊");
hashMap.put("大乔","小乔");
hashMap.put("Rose","Jisoo");
//V get(Object key):根据键获取值
System.out.println(hashMap.get("Stark")); //Pamela
//键不存在返回null
System.out.println(hashMap.get("Lara")); //null
//Set<K> KeySet():获取所有键的集合 键是唯一的所以返回Set集合
Set<String> keySet = hashMap.keySet();
for (String s : keySet){
System.out.print(s + " ");
}
System.out.println("\n--------------------");
//Collection<V> values():获取所有值 值并不知道是不是可重复的所以返回Collection集合
Collection<String> values = hashMap.values();
for (String s : values){
System.out.print(s + " ");
}
}
}
输出结果:
Pamela
null
美羊羊 大乔 Rose Stark
沸羊羊 小乔 Jisoo Pamela
1.4 Map集合的遍历(方式一)
遍历思路:
①获取所有键的集合,keySet()
②遍历键的集合,获取每一个键
③根据键去找对应的值,get(Object key)
public class MapTest04 {
public static void main(String[] args) {
//创建HashMap集合对象
Map<String,String> hashMap = new HashMap<>();
//添加元素到hashMap集合
hashMap.put("Rose","Jennie");
hashMap.put("Stark","Pamela");
hashMap.put("美羊羊","沸羊羊");
hashMap.put("小乔","大乔");
//①获取所有键的集合,keySet()
Set<String> set = hashMap.keySet();
//②遍历键的集合,获取每一个键
for (String key : set){
//③根据键去找对应的值,get(Object key)
String value = hashMap.get(key);
System.out.println("Key:" + key + "," + "value:" + value);
}
}
}
输出结果:
key:美羊羊,value:沸羊羊
key:Rose,value:Jennie
key:Stark,value:Pamela
key:小乔,value:大乔
Map集合的遍历(方式二)
遍历思路:
①获取所有键值对 对象的集合,set<Map.Entry<K,V>>entrySet()
②遍历所有键值对集合,得到每一个键值对,使用增强for循环,得到Map.Entry
③根据键值对获取key值和value值,getKey()得到key,getValue()得到value
public class MapTest05 {
public static void main(String[] args) {
//创建HashMap集合对象
Map<String, String> hashMap = new HashMap<String, String>();
//添加元素
hashMap.put("Rose", "Jennie");
hashMap.put("Stark", "Pamela");
hashMap.put("美羊羊", "沸羊羊");
hashMap.put("小乔", "大乔");
//①获取所有键值对 对象的集合,set<Map.Entry<K,V>>entrySet()
Set<Map.Entry<String, String>> entrySet = hashMap.entrySet();
//②遍历所有键值对集合,得到每一个键值对,使用增强for循环,得到Map.Entry
for (Map.Entry<String, String> me : entrySet) {
//③根据键值对获取key值和value值,getKey()得到key,getValue()得到value
String key = me.getKey();
String value = me.getValue();
System.out.println("key:" + key + " , " + "value:" + value);
}
}
}
输出结果:
key:美羊羊 , value:沸羊羊
key:Rose , value:Jennie
key:Stark , value:Pamela
key:小乔 , value:大乔
练习:HashMap集合存储学生对象并遍历1
需求:
创建一个HashMap集合,键值学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历
public class HashMapTest {
public static void main(String[] args) {
//创建一个HashMap集合
Map<String,Student> hashMap = new HashMap<String,Student>();
//键值学号(String),值是学生对象(Student),存储三个键值对元素
hashMap.put("001",new Student("Pamela",22));
hashMap.put("002",new Student("Lara",25));
hashMap.put("003",new Student("Jennie",23));
//遍历 方式一 通过键找值
Set<String> keySet = hashMap.keySet();
for (String key : keySet){
Student value = hashMap.get(key);
System.out.println("学号:" + key + value);
}
System.out.println("----------------------------");
//遍历 方式二 通过键值对对象找值和对象
Set<Map.Entry<String, Student>> entrySet = hashMap.entrySet();
for (Map.Entry<String,Student> me : entrySet){
String key = me.getKey();
Student value = me.getValue();
System.out.println("学号:" + key + value);
}
}
}
输出结果:
学号:001姓名:Pamela , 年龄:22
学号:002姓名:Lara , 年龄:25
学号:003姓名:Jennie , 年龄:23
学号:001姓名:Pamela , 年龄:22
学号:002姓名:Lara , 年龄:25
学号:003姓名:Jennie , 年龄:23
练习:HashMap集合存储学生对象并遍历2
创建一个HashMap集合,键是学生对象(Student),值是居住地(String)。存储多个键值对元素,并遍历。
要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
学生实体类:
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;
}
@Override
public String toString() {
return "姓名:" + name +
" , 年龄:" + age;
}
//要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
测试类:
public class HashMapTest {
public static void main(String[] args) {
//创建一个HashMap集合,键是学生对象(Student),值是居住地(String)
Map<Student,String> hashMap = new HashMap<Student,String>();
//存储多个键值对元素
hashMap.put(new Student("Lily",20),"拉斯维加斯");
hashMap.put(new Student("Pamela",22),"俄国");
hashMap.put(new Student("Jennie",26),"韩国");
//此对象的键具有唯一性,学生对象的成员变量不能相同 此数据没能存储
hashMap.put(new Student("Stark",30),"美国");
//此对象的键具有唯一性,学生对象的成员变量不能相同 此数据覆盖了原来键学生对象的值
hashMap.put(new Student("Stark",30),"文莱");
//此条数据的键 学生对象成员变量的年龄并不相同,所以存储了
hashMap.put(new Student("Stark",35),"文莱");
//遍历 方式一 通过键获取值
Set<Student> studentSet = hashMap.keySet();
for (Student key : studentSet){
String value = hashMap.get(key);
System.out.println("键:" + key + " ; " + "值:" + value);
}
System.out.println("----------------------------------");
//遍历 方式二 通过键值对对象获取键和值
Set<Map.Entry<Student, String>> entrySet = hashMap.entrySet();
for (Map.Entry<Student,String> me : entrySet){
Student key = me.getKey();
String value = me.getValue();
System.out.println("键:" + key + " ; " + "值:" + value);
}
}
}
输出结果:
键:姓名:Pamela , 年龄:22 ; 值:俄国
键:姓名:Stark , 年龄:30 ; 值:文莱
键:姓名:Stark , 年龄:35 ; 值:文莱
键:姓名:Lily , 年龄:20 ; 值:拉斯维加斯
键:姓名:Jennie , 年龄:26 ; 值:韩国
键:姓名:Pamela , 年龄:22 ; 值:俄国
键:姓名:Stark , 年龄:30 ; 值:文莱
键:姓名:Stark , 年龄:35 ; 值:文莱
键:姓名:Lily , 年龄:20 ; 值:拉斯维加斯
键:姓名:Jennie , 年龄:26 ; 值:韩国
案例1:ArrayList集合存储HashMap元素并遍历(集合嵌套)
需求:创建一个ArrayList集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的值和键都是String,并遍历
public class NestCollection01 {
public static void main(String[] args) {
//创建ArrayList集合对象
List<HashMap<String,String>> arrayLists = new ArrayList<HashMap<String,String>>();
//创建HashMap集合对象
HashMap<String,String> hashMap1 = new HashMap<String,String>();
hashMap1.put("001","Lara");
hashMap1.put("002","Pamela");
HashMap<String,String> hashMap2 = new HashMap<String,String>();
hashMap2.put("003","Lily");
hashMap2.put("004","Stark");
HashMap<String,String> hashMap3 = new HashMap<String,String>();
hashMap3.put("005","Sour");
hashMap3.put("006","Lee");
//存储三个元素,每一个元素都是HashMap
arrayLists.add(hashMap1);
arrayLists.add(hashMap2);
arrayLists.add(hashMap3);
//遍历
for (HashMap<String,String> hashMap : arrayLists){
Set<String> keySet = hashMap.keySet();
for (String key : keySet){
String value = hashMap.get(key);
System.out.println(key + " , " + value);
}
}
}
}
输出结果:
001 , Lara
002 , Pamela
003 , Lily
004 , Stark
005 , Sour
006 , Lee
案例2:HashMap集合存储ArrayList元素并遍历
创建一个HashMap集合,存储三个键值对元素,每一个键值对的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历
public class NestCollection02 {
public static void main(String[] args) {
//创建一个HashMap集合
HashMap<String, ArrayList> hashMap = new HashMap<String,ArrayList>();
//创建ArrayList1集合对象
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("Rose");
arrayList1.add("Lisa");
//创建ArrayList2集合对象
ArrayList<String> arrayList2 = new ArrayList<>();
arrayList2.add("Jennie");
arrayList2.add("Jisoo");
//存储三个键值对元素,每一个键值对的键是String,值是ArrayList
hashMap.put("BlackPink",arrayList1);
hashMap.put("whitePink",arrayList2);
//遍历 通过键获取值
Set<String> keySet = hashMap.keySet();
for (String key : keySet){
ArrayList<String> value = hashMap.get(key);
for (String s : value){
System.out.println("key:"+key+" , "+"value:" + s);
}
}
}
}
输出结果:
key:Lisa , value:Rose
key:Pamela , value:Stark
key:Lara , value:Elence
案例3:统计字符串中每个字符出现的次数
需求:键盘录入一个字符串,要求统计字符串中每个字符串出现的次数。
举例:键盘录入“aababcabcdabcde“ 在控制台输出:“a(5)b(4)c(3)d(2)e(1)"
public class StringCount {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner scanner = new Scanner(System.in);
System.out.println("请数字字符串:");
String line = scanner.nextLine();
//创建HashMap集合,键是字符,值是字符个数
TreeMap<Character, Integer> hashMap = new TreeMap<>();
//遍历字符串,得到每一个字符
for (int i = 0; i < line.length(); i++) {
char key = line.charAt(i);
//通过每一个键去hashMap中获取值
Integer value = hashMap.get(key);
//为空之则是字符还未出现过在HashMap集合中不存在
if (value == null) {
//把该字符作为键,1作为值存储
hashMap.put(key,1);
//else则是出现过
}else{
//就将他的value值再加一
value++;
//把该字符做为键,值加一
hashMap.put(key,value);
}
}
//遍历集合
StringBuilder stringBuilder = new StringBuilder();
Set<Character> keySet = hashMap.keySet();
for (Character key : keySet){
int value = hashMap.get(key);
stringBuilder.append(key).append("(").append(value).append(")");
}
System.out.println(stringBuilder);
}
}
输出结果:
请数字字符串:
aababcabcdabcde
a(5)b(4)c(3)d(2)e(1)
二、Collections概述和使用
2.1 Collections类的概述:
是针对集合操作的工具类;
2.2 Collections类的常用方法:
public static <T extends Comparable<? super T>> void sort(List list):将指定的列表按升序排序;
public static void reverse(List < ? > list):反转指定列表中的元素;
public static void shuffle(List<?> list):使用默认的随机源随机排列指定的列表;
测试方法:
public class CollectionsTest {
public static void main(String[] args) {
//创建集合对象
List<Integer> list = new ArrayList<Integer>();
//添加元素
list.add(30);
list.add(40);
list.add(10);
list.add(80);
list.add(70);
//public static <T extends Comparable<? super T>> void sort(List<T> list):将指定的列表按升序排序;
Collections.sort(list);
System.out.println(list);
//public static void reverse(List < ? > list):反转指定列表中的元素;
Collections.reverse(list);
System.out.println(list);
//public static void shuffle(List<?> list):使用默认的随机源随机排列指定的列表;
Collections.shuffle(list);
System.out.println(list);
}
}
输出结果1:
[10, 30, 40, 70, 80]
[80, 70, 40, 30, 10]
[80, 40, 70, 30, 10]
输出结果2:
[10, 30, 40, 70, 80]
[80, 70, 40, 30, 10]
[40, 80, 10, 70, 30]
2.3 Collections案例1:ArrayList存储学生对象并排序
需求:
ArrayList存储学生对象,使用Collections对ArrayList进行排序
要求:按照年龄从大到小排序,年龄相同时,按照姓名的字母顺序排序
考察:
集合中Collections的使用;
学生类 :
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;
}
@Override
public String toString() {
return "姓名:" + name +
" , 年龄:" + age ;
}
}
测试类:
public class CollectionsCase01 {
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<Student>();
arrayList.add(new Student("Rose",20));
arrayList.add(new Student("Pamela",22));
arrayList.add(new Student("Lisa",20));
arrayList.add(new Student("Jennie",21));
arrayList.add(new Student("Jisoo",20));
//使用Collections对ArrayList进行排序
//sort(List<T> list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序。
Collections.sort(arrayList, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//主要条件:按照年龄从大到小排序
int num = o1.getAge()-o2.getAge();
//次要排序:年龄相同时,按照姓名的字母顺序排序
int num1 = num==0 ? o1.getName().compareTo(o2.getName()): num;
return num1;
}
});
for (Student student : arrayList){
System.out.println(student);
}
}
}
输出结果:
姓名:Jisoo , 年龄:20
姓名:Lisa , 年龄:20
姓名:Rose , 年龄:20
姓名:Jennie , 年龄:21
姓名:Pamela , 年龄:22
集合中Collections的使用总结:
在集合中泛型为引用数据类型时,又要求对集合中对象进行排序的时候,就使用Collections.sort()方法,其方法有两个构造器:
①一个是将引用数据类型的实体类实现Collection接口,重写CompareTo();
②另一个就是使用Comparator比较器排序,sort(List list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序。
只要使用到排序时就用自己考虑用Comparable还是Comparator,在Collection的实现类均可使用;
Collections案例2:模拟斗地主
需求:通过程序实现斗地主过程中的洗牌,发牌,看牌
思路:
①创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
②往牌盒里面装牌
③洗牌,也就是把牌打乱,用Collections的shuffle()方法实现
④发牌,也就是遍历集合,给三个玩家发牌
public class PokerTest {
public static void main(String[] args) {
//①创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
ArrayList<String> arrayList = new ArrayList<String>();
//②往牌盒里面装牌
/*
♦2,♦3...♦K,♦A
♥2...♥A
♠2...♠A
♣2...♣A
*/
//定义花色数组
String[] colors = {"♦","♥","♠","♣"};
//定义点数数组
String[] numbers = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
for (String color : colors){
for (String number : numbers){
arrayList.add(color + number);
}
}
arrayList.add("小王");
arrayList.add("大王");
//③洗牌,也就是把牌打乱,用Collections的shuffle()方法实现
Collections.shuffle(arrayList);
// System.out.println(arrayList);
//④发牌,也就是遍历集合,给三个玩家发牌
//创建三个玩家
ArrayList<String> rose = new ArrayList<String>();
ArrayList<String> pamela = new ArrayList<String>();
ArrayList<String> stark = new ArrayList<String>();
ArrayList<String> dpArray = new ArrayList<String>();
//给三个玩家发牌
for (int i = 0;i < arrayList.size();i++){
String poker = arrayList.get(i);
if (i>=arrayList.size()-3){
dpArray.add(poker);
}else if (i%3==0){
rose.add(poker);
}else if (i%3==1){
pamela.add(poker);
}else if (i%3==2){
stark.add(poker);
}
}
//看牌,也就是三个玩家分别遍历自己的牌
lookPoker("rose",rose);
lookPoker("pamela",pamela);
lookPoker("stark",stark);
lookPoker("底牌",dpArray);
}
public static void lookPoker(String name,ArrayList arrayList){
System.out.print(name + "的牌是:");
for (Object poker : arrayList){
System.out.print(poker + " ");
}
System.out.println();
}
}
输出结果:
rose的牌是:♠2 ♠4 ♠8 ♣4 ♣9 ♣A ♣J ♣K ♣Q ♥3 ♥5 ♥6 ♥9 ♥K ♦6 ♦8 ♦A
pamela的牌是:♣5 ♥7 ♥8 ♦K ♦7 ♦J ♠A ♦4 ♦10 小王 ♦5 ♠5 ♠10 ♣3 大王 ♦3 ♥J
stark的牌是:♠K ♦2 ♦Q ♥Q ♠6 ♠9 ♣6 ♦9 ♣8 ♥2 ♠Q ♠7 ♣10 ♥10 ♠3 ♥4 ♥A
底牌的牌是:♣7 ♠J ♣2
Collections案例2:模拟斗地主模拟斗地主升级版
思路:
1.创建HashMap集合,键为编号,值为牌
2.创建ArrayList集合,存储编号
3.创建花色和点数的数组
4.将编号和花色存储到map集合中,将编号单独存储list集合中
5.使用Collections中的shuffle()方法将list集合进行随机置换
6.创建玩家和底牌的TreeSet集合,并进行发牌
7.遍历集合,查看内容
public class PokerTest02 {
public static void main(String[] args) {
//创建HashMap集合,键是编号 ,值是牌
HashMap<Integer,String> hashMap = new HashMap<Integer,String>();
//创建ArrayList,存储编号
ArrayList<Integer> keyArray = new ArrayList<Integer>();
//创建花色数组和点数数组
String[] colors = {"♦","♥","♠","♣"};
String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
//从零开始往HashMap内存编号,并存储相应的牌
int index = 0;
for (String number : numbers){
for (String color : colors){
hashMap.put(index,color+number);
keyArray.add(index);
index++;
}
}
hashMap.put(index,"小王");
keyArray.add(index);
index++;
hashMap.put(index,"大王");
keyArray.add(index);
//洗牌(洗编号)
Collections.shuffle(keyArray);
//发牌,发的也是编号,为了保证排序,用的是TreeSet集合接收
TreeSet<Integer> rose = new TreeSet<Integer>();
TreeSet<Integer> stark = new TreeSet<Integer>();
TreeSet<Integer> jennie = new TreeSet<Integer>();
TreeSet<Integer> dpSet = new TreeSet<Integer>();
for (int i = 0;i < keyArray.size();i++){
int x = keyArray.get(i);
if (i >= keyArray.size() - 3){
dpSet.add(x);
}if (i % 3 == 0){
rose.add(x);
}else if (i%3==1){
stark.add(x);
}else if (i%3 ==2){
jennie.add(x);
}
}
//玩家看牌
lookPoker("rose",rose,hashMap);
lookPoker("stark",stark,hashMap);
lookPoker("jennie",jennie,hashMap);
lookPoker("底牌",dpSet,hashMap);
}
//定义方法看牌(遍历TreeSet集合,获取编号,到HahMap集合找对应的牌)
public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hashMap){
System.out.print(name + "的牌是:");
for (Integer key : ts){
String poker = hashMap.get(key);
System.out.print(poker + " ");
}
System.out.println();
}
}
输出结果:
rose的牌是:♣3 ♣4 ♠5 ♣5 ♦7 ♥7 ♠7 ♣7 ♣9 ♦10 ♥10 ♠10 ♣10 ♦J ♠J ♣J ♦Q ♦K
stark的牌是:♥3 ♠3 ♠4 ♥6 ♦8 ♥8 ♣8 ♦9 ♥9 ♥J ♠Q ♣Q ♥K ♣K ♥A ♠A ♠2 小王
jennie的牌是:♦3 ♦4 ♥4 ♦5 ♥5 ♦6 ♠6 ♣6 ♠8 ♠9 ♥Q ♠K ♦A ♣A ♦2 ♥2 ♣2 大王
底牌的牌是:♦8 ♦Q ♦A