JavaSE笔记_day15_Map、Collections集合类

230 阅读12分钟

一.Map集合

1.Map集合的概述

1.Map集合:双列集合的顶层接口,来自于java.util包
    map:地图,地图上的每一个点都与现实生活中的一个地理位置一一对应的关系。
2.Map<K,V>:Map集合中,带有两个泛型,这两个泛型,都是引用数据类型。
    K-->Key-->键 
    V-->Value-->值 
    因此Map集合中存储的一对元素,称为键值对映射关系,是一种一对一的关系。
3.Map集合的特点
    Map集合中,Key值是不能重复的,Value是彼此可以重复的。

2.Map集合的常用方法

Map是一个接口,不能实例化对象,于是需要一个实现类,HashMap。
HashMap来自于java.util包 
//接口的多态性,父接口的引用指向一个实现类的对象 
Map<K,V> map = new HashMap();
1.put(K key,V value):表示将key与value的键值对映射对映射关系对象,添加到map集合中。
    (1)通过put方法,向map中添加不存在的key值,直接添加成功。
    (2)通过put方法,向Map中添加已经存在的key值,相当于修改,将后添加的value值,替换掉原来的key值对应的value。
2.remove(K key):将map集合对应的key值键值对删掉。返回值类型,V--->value,返回所删除的键值对中的value
3.clear():表示清空map集合,将集合中所有的键值对映射关系删除,Map集合仍然存在	
4.isEmpty():判断Map集合中,是否还有键值对的映射关系对象,如果没有,返回true,如果没有,返回false。
5.containsKey(Object key):判断Map集合中,是否包含指定的key值,包含返回true,不包含返回false。
6.containsValue(Object value):判断Map集合中,是否包含指定的value值,包含返回true,不包含返回false。
7.get(Object key):通过Map集合中的key的值,获取到对应的value值,返回值类型就是value。
8.size():求Map集合中的键值对映射关系数量,返回值类型int类型

import java.util.HashMap;
import java.util.Map;
public class MapMethod {
    public static void main(String[] args) {
        //Map集合存储的K和V的值,都必须是引用数据类型
        Map<Integer,String> map = new HashMap<>();
        putMethod(map);
        System.out.println(map);//{1=a, 2=hello, 3=c}
        removeMethod(map);
        clearMethod(map);
        isEmptyMethod(map);
        containsMethod();
    }
    //1.put(K,V):向map集合中添加键值对元
    public static void putMethod(Map<Integer,String> map){
        //1.通过put方法,向map中添加不存在的key值,直接添加成功。
        map.put(1,"a");
        map.put(2,"b");
        map.put(3,"c");
        System.out.println(map);//{1=a, 2=b, 3=c}
        //2.通过put方法,向Map中添加已经存在的key值,相当于修改。
        map.put(2,"hello");
        System.out.println(map);//{1=a, 2=hello, 3=c}
        }
        //2.map(K key):将map集合对应的key值键值对删掉。返回值类型,V--->value,返回所删除的键值对中的value
    public static void removeMethod(Map<Integer,String> map){
        String s = map.remove(1);
        System.out.println("刚刚删掉的是: "+s);//刚刚删掉的是: a
        System.out.println(map);//{2=hello, 3=c}
    }
    //3.clear():
    public static void clearMethod(Map<Integer,String> map){
        map.clear();
        System.out.println(map);//{}
    }
    //4.isEmpty():判断是否含有键值对关系,若没有返回true
    public static void isEmptyMethod(Map<Integer,String> map){
        if(map.isEmpty()){
            System.out.println("该map集合不存在键值对关系!");//该map集合不存在键值对关系!
        }
    }
    //5.containsKey():判断Map集合中,是否包含指定的key值,包含返回true,不包含返回false。
    //6.containsValue():判断Map集合中,是否包含指定的value值,包含返回true,不包含返回false。
    //7.get(Object key):通过Map集合中的key的值,获取到对应的value值,返回值类型就是value。
    //8.size():获取键值对数量
    public static void containsMethod(){
        Map<Integer,String> map = new HashMap<>();
        map.put(11,"a");
        map.put(22,"b");
        map.put(33,"c");
        System.out.println(map.containsKey(33));//true
        System.out.println(map.containsValue("def"));//false
        //7.get(Object key)
        String value = map.get(11);
        System.out.println(value);//a
        System.out.println(map.size());//3
    }
}

3.Map集合的遍历

1.keySet遍历
    keySet():将Map集合中的所有的Key值获取到,将所有Key值放置在一个Set集合中。
2.entrySet遍历
    Map.entrySet<Integer,String>:获取Map集合中的键值对映射关系对象,放置到一个Set集合中。
    映射关系对象:Map接口中的Entry<K,V>接口,表示Map集合中
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapBianLi {
    public static void main(String[] args) {
        //1.创建一个Map集合
        Map<Integer,String> map = new HashMap<>();
        //2.向Map集合中添加元素
        map.put(1,"a");
        map.put(2,"b");
        map.put(3,"c");
        bianLi1(map);
        bianLi2(map);
        bianLi3(map);
        bianLi4(map);
    }
    //1.使用keySet()+增强for遍历
    public static void bianLi1(Map<Integer,String> map){
        //3.keySet():获取到Map集合中的所有Key值,添加到set集合中
        Set<Integer> set = map.keySet();
        //4.将所有的Key值获取到,通过key值获取到对应的value值
        for(Integer key: set){
            //5.通过get(Object key)获取value值
            String value = map.get(key);
            System.out.println(key+"----"+value);
        }
    }
    //2.使用keySet()+迭代器遍历
    public static void bianLi2(Map<Integer,String> map){
        //3.keySet():获取到Map集合中的所有Key值,添加到set集合中
        Set<Integer> set = map.keySet();
        //4.获取到Set集合的迭代器对象iterator()
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
            //获取到集合的key值
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key+"++++"+value);
        }
    }
    //3.使用entrySet()和增强for遍历
    public static void bianLi3(Map<Integer,String> map){
        //3.使用entrySet()方法,获取到Map集合中的所有键值对映射关系
        //每一个键值对对象关系,都是一个Map.Entry<Integer,String>
        Set<Map.Entry<Integer,String>> set = map.entrySet();//一次性地获取到一对键值对关系,Map.Entry<Integer,String>键值对类型,放入set集合
        //4.使用增强for遍历这个set集合
        for(Map.Entry<Integer,String> entry: set){//然后单独拿出key,value
        //5.通过entry方法
        //getKey():将键值对关系中的key值获取到
        Integer key = entry.getKey();
        //getValue():将键值对关系中的value值获取到
        String value = entry.getValue();
        System.out.println(key+"~~~~"+value);
    }
}
    //4.使用entrySet()+迭代器遍历
    public static void bianLi4(Map<Integer,String> map){
        //3.使用entrySet()获取到Map集合中所有的键值对
        Set<Map.Entry<Integer,String>> set = map.entrySet();//集合中装的是键值对映射关系
        //4.使用迭代器进行set集合遍历
        Iterator<Map.Entry<Integer,String>> it = set.iterator();
        //循环将每一个键值对关系获取到
        while(it.hasNext()){
            Map.Entry<Integer,String> entry = it.next();
    	    Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"!!!!"+value);
        }
    }
}

练习:定义一个字符串:aaaabbccddd!@#@$@#$%cc66f
     统计字符串中每个字符出现的次数,

分析:
    1.拥有的字符串-->获取到字符串中的每一个字符-->String-->
        toCharArray():将一个字符串每个字符获取到,返回一个字符数组
    2.结果 a---4  b--2  c--3  键值对关系,最终结果用Map集合承装
        字符-->key值  数量-->value 
    3.数字符出现次数:
        Map<Character,Integer> map 
        (1)遍历char数组,获取到每一个数组
        (2)判断这个字符在map中是否存在
        不存在,证明第一次计数,put(字符,1)
        存在,原有计数(get(字符)-->字符对应的计数)基础上+1
import java.util.HashMap;
import java.util.Map;
public class MapTest {
    public static void main(String[] args) {
        //1.定义一个字符串
        String s = "aaaabbccddd!@#@$@#$%cc66f";
        //2.将字符串转换成字符数组。
        char[] ch = s.toCharArray();
        //3.准备一个Map集合
        Map<Character,Integer> map = new HashMap<>();
        //4.将字符串中的每一个字符获取到
        for (int i = 0; i < ch.length; i++) {
             //5.判断字符在Map集合中是否存在
            if(!map.containsKey(ch[i])){
                map.put(ch[i],1);//第一次不在集合中存在赋值1
            }else{
                map.put(ch[i],map.get(ch[i])+1);//在集合中存在,获取到当前的值+1
            }
        }
        System.out.println(map);//{@=3, a=4, !=1, b=2, c=4, #=2, d=3, $=2, %=1, 6=2, f=1}
    }
}

4.HashMap的key值保证元素唯一

  • 1.HashMap()是Map接口的实现类,来自于java.util包,也是带有两个泛型 HashMap<K,V> 
  • 2.HashMap如果存储的是 JDK定义好的引用数据类型,key值可以自动去重复 HashMap如果存储的是自定义好的引用数据类型,若果需要将自定义类型通过成员变量的值进行去重复,那么需要重写hashcode+equals方法。 
  • 原因:HashMap中的key值,去重复原理与HashSet原理一致 
  • 要求:定义一个person类,类中属性姓名,年龄,要求相同的姓名和年龄认为是重复的Person数据

5.LinkedHashMap

  • LinkedHash 是 HashMap 的子类 
  • HashMap 的 key 值,与 HashSet 原理一致,因此在HashMap中存储的元素,无序。 
  • LinkedHashMap 与 HashMap的区别就是能够让元素的存取是有序的  

import java.util.HashMap;
import java.util.LinkedHashMap;
public class MapOnly {
    public static void main(String[] args) {
        //1.创建Map集合
        HashMap<Person,String> map = new HashMap<>();
        map.put(new Person("李四",25),"a");
        map.put(new Person("张三",20),"a");
        map.put(new Person("张三",20),"b");
        //没有做到去重复
        //System.out.println(map);//{Person{name='李四', age=25}=a, Person{name='张三', age=20}=a, Person{name='张三', age=20}=b}
        //若想做到去重复,Person类中重写HashCode()+equals方法
        System.out.println(map);//{Person{name='张三', age=20}=b, Person{name='李四', age=25}=a}
        //2.使用LinkedHashMap进行有序存储
        LinkedHashMap<Person,String> lhm = new LinkedHashMap<>();
        lhm.put(new Person("李四",25),"a");
        lhm.put(new Person("张三",20),"a");
        lhm.put(new Person("张三",20),"b");
        System.out.println(lhm);//{Person{name='李四', age=25}=a, Person{name='张三', age=20}=b}
    }
}

6.HashMap 与 HashTable 的区别

  • HashMap 与 Hashtable 都是Map接口的实现类,都是用于键值对映射关系的存储 
  • 所有的引用数据类型的一个默认值都可以设置为null,null在堆内存中什么都没有。 
  • 区别: 
      1.Hashtable 从JDK1.0开始,HashMap 从JDK1.2开始 
      2.Hashtable 线程安全,运行速度慢; HashMap 线程不安全,运行速度快 
      3.Hashtable 不支持null的键或值; HashMap支持存储null的键或值

import java.util.HashMap;
import java.util.Hashtable;
public class HashTableDemo {
    public static void main(String[] args) {
        HashMap<Integer,String> map = new HashMap<>();
        map.put(null,"a");
        map.put(1,null);
        map.put(2,"b");
        System.out.println("---"+map);//---{null=a, 1=null, 2=b}
        Hashtable<Integer,String> table = new Hashtable<>();
        //table.put(null,"a");//java.lang.NullPointerException
        //table.put(1,null);
        table.put(2,"b");
        System.out.println(table);
    }
}

二.Collections集合类

Arrays工具类:功能,针对于数组做一些操作
Collections工具类:功能,针对于集合进行一些操作,来自于java.util包,其中所有的方法都是静态的,不需要new对象		
    1.sort(List list):对list集合进行默认升序排列,set集合不能排序								
    2.binarySearch(List list,Object key):检索key在List集合中的索引位置,返回值 索引int类型
        如果找到了,返回一个>=0的int整数; 如果没有找到,返回一个负数
        注意:1.要求List集合升序排列的;2.通过结果是否>=0来进行判断元素key是否存在于集合中
    3.max(Collection c):将集合中的最大值获取到,一般比较数值有意义								
    4.min(Collection c):将集合中的最小值获取到,一般比较数值有意义										
    5.shuffle(List list):将List集合中的数据任意打乱		
        使用场景:洗牌发牌,需要每次将牌任意打乱
import java.util.ArrayList;
import java.util.Collections;
public class CollectionsDemo {
    public static void main(String[] args) {
        //1.sort(List list):升序排序
        ArrayList<Integer> arr = new ArrayList<>();
        arr.add(12);
        arr.add(-8);
        arr.add(1);
        arr.add(99);
        arr.add(0);
        Collections.sort(arr);
        System.out.println(arr);//[-8, 0, 1, 12, 99]
      
      //2.binarySearch(List list,Object key)
        int index = Collections.binarySearch(arr,99);
        System.out.println(index);//4
        System.out.println(Collections.binarySearch(arr,199));//-6  [-8, 0, 1, 12, 99,199](-1,-2,-3,-4,-5,-6)
        System.out.println(Collections.binarySearch(arr,11));//-4   [-8, 0, 1,11, 12, 99](-1,-2,-3,-4,-5,-6)
       
    //3.max(Collection c);min(Collection c)
        int max = Collections.max(arr);
        int min = Collections.min(arr);
        System.out.println("该集合最大值为:"+max+"最小值为:"+min);//该集合最大值为:99最小值为:-8
       
    //4.shuffle(List list):任意打乱
        Collections.shuffle(arr);
        System.out.println("~~"+arr);//~~[1, 12, 0, -8, 99]
    }
}

斗地主案例,完成洗牌发牌动作
    规则: 
        1.组装54张扑克牌
        2.将54张牌顺序打乱
        3.三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌
        4.查看三人手中各自的牌(升序排序)、底牌
    手中扑克牌从大到小的摆放顺序:大王、小王、2、A、K、Q、J、10、9、8、7、6、5、4、3
    分析: 
        牌共54张
        大王 小王 2 A K Q....3(2...3 每张牌有4个花色)
        每一张牌对应一个数字,牌从大到小,对应的数字从小到大----小数字对应大牌  查表法
    1.组装牌 Map<Integer,String>
    2.洗牌 Collections.shuffle(List list)  <--创建list集合存放key值
    3.发牌
        底牌 -- 3张	list索引0,1,2
        玩家1 --17张 	list索引%3==0
        玩家2 --17张	list索引%3==1
        玩家3 --17张	list索引%3==2
    4.看牌:需要将玩家和底牌按照从大到小的顺序进行排列
    看牌逻辑
        1.将玩家手中的牌号码,进行升序排列,对应牌从大到小
        2.通过牌号码,获取到对应的真实牌,展示到控制台上

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class DouDiZhu {
    public static void main(String[] args) {
        //1.设置牌的4个花色
        String[] flower = {"?","?","?","?"};
        //2.准备牌
        String[] puke = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
        //3.创建Map集合,用于装54张牌和牌大小号的对应关系
        Map<Integer,String> map = new HashMap<>();
        //创建一个List集合,用于存放所有牌的牌号,为了后面的洗牌和发牌
        ArrayList<Integer> list = new ArrayList<>();
        //定义一个牌号的初始值,0和1留给大小王
        int count = 2;
        for(String pai : puke){
            for(String f : flower){
                //4.将带有花色的牌放入Map集合中
                map.put(count,f+pai);
                list.add(count);
                count++;
            }
        }
        map.put(0,"大王");
        list.add(0);
        map.put(1,"小王");
        list.add(1);
        System.out.println("李英楠新买一个puke儿: "+map);
        System.out.println("puke儿不少,一共"+map.size()+"张");
        //5.洗牌,将List中对的所有牌号打乱
        System.out.println("小张把牌洗一下!~~");
        System.out.println("好嘞!");
        Collections.shuffle(list);
        //6.创建玩家牌,底牌的容器
        ArrayList<Integer> play1 = new ArrayList<>();
        ArrayList<Integer> play2 = new ArrayList<>();
    	ArrayList<Integer> play3 = new ArrayList<>();
        ArrayList<Integer> bottom = new ArrayList<>();
        //7.发牌,三个玩家每人17张,底牌三张,实际上是发给玩家的是list集合中的牌号
        //前三张发给底牌
        System.out.println("开始发牌:");
        for (int i = 0; i < list.size(); i++) {
            if(i<3){//发给底牌
                bottom.add(list.get(i));
            }else{
                if(i%3==0){//发给玩家1
                    play1.add(list.get(i));
                }else if(i%3==1){//发给玩家2
                    play2.add(list.get(i));
                }else{//发给玩家3
                    play3.add(list.get(i));
                }
            }
        }
        //8.看牌
        System.out.print("小李的牌是:");
        lookPai(play1,map);
        System.out.print("小张的牌是:");
        lookPai(play2,map);
        System.out.print("小英的牌是:");
        lookPai(play3,map);
        System.out.println("底牌是:");
        lookPai(bottom,map);
    }
    public static void lookPai(ArrayList<Integer> play,Map<Integer,String> map){
        //1.将玩家手中的牌号进行升序排序
        Collections.sort(play);
        //2.通过牌号到map集合中获取到真实的value值,就是真实底牌
        for(Integer key : play){
            String value = map.get(key);
            System.out.print(value+" ");
        }
        System.out.println();
    }
}