Java14-------------Map集合

Map集合概述和特点

  • 将键映射到值的对象
    一个映射不能包含重复的键
    Map:双列集合,一个键只能映射一个值,键是唯一的,键相同,值覆盖。

  • 某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。

  • Map接口中的内部类:
    public static interface Map.Entry<K,V>映射项(键-值对)
    Map.entrySet 方法返回映射的 collection 视图,该方法返回的是的对象能查看每个结点对象的键与值;后面在遇到集合遍历的时候可以很好的理解。

  • Map集合的方法
    在这里插入图片描述

  • Map接口的常见的实现类:
    HashMap、TreeMap、Hashtable、LinkedHashMap

HashMap类

HashMap 他的键的数据结构是哈希表,键无序,且唯一。并允许使用 null 值和 null 键。线程不安全,效率高。

1、 在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。

2、 而JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

保证键的唯一性:

3.Map类的集合只与键有关,我们可以通过添加元素的方法查看底层的代码;它的底层是调用键对象的equals()和hashCode()方法来保证键的唯一性;与hashSet集合一样,重写hashCode()是为了减少碰撞。由于键是存在哈希表中,为了保证键的唯一性,如果键的类型时自定义引用数据类型(例如Student对象),每一个new的对象地址值不同,那么就会被当做是不同的对象在哈希表均会存储;因此就需要重写Student类的hashcode与equals方法,重写的hashcode根据对象的成员变量值来获取哈希表的地址值,重写的equals方法比较字符串字面值而不是地址值,就可以筛选出两个地址值不同但是成员变量相同的对象,避免重复存储。

HashMap的方法:
在这里插入图片描述
举例理解:

public class test {
    public static void main(String[] args) {  
        HashMap<String, String> hm = new HashMap<>();
        //当键相同,值就会覆盖,返回的是上一次这个键所映射的那个旧值。
        String s = hm.put("1", "11");
        String s1 = hm.put("1", "12");
        String s2 = hm.put("2", "13");
        String s3 = hm.put("3", "13");
        String s4 = hm.put("4", "13");
        String s5 = hm.put("5", "13");
        String s66 = hm.put(null, null);
        System.out.println(hm);//{null=null, 1=12, 2=13, 3=13, 4=13, 5=13}
        //当键相同,值就会覆盖,返回的是上一次这个键所映射的那个旧值。
        System.out.println(s);//null
        System.out.println(s1);//11
        System.out.println(s2);//null

        //清空集合
        //hm.clear();
        //获取集合的长度
        System.out.println(hm.size());//6
        //删除一个键,返回的是那个键所对应的值。
        String s6 = hm.remove("1");
        System.out.println(hm);//{null=null, 2=13, 3=13, 4=13, 5=13}
        System.out.println(s6);//12
        //传入key与value进行删除 返回布尔值
        boolean remove = hm.remove("2", "13");
        System.out.println(remove); //true


        //判断集合是否包含键"1"
        boolean b = hm.containsKey("1");
        //判断集合是否包含值
        boolean b1 = hm.containsValue("13");
        //判断集合是否为空isEmpty()
        boolean b3 = hm.isEmpty();

        //通过键来获取值,没有返回null
        String s7 = hm.get("2");
        //通过键来获取值,没有对应的值,可以给一个默认值。
        System.out.println(hm.getOrDefault("1", "no value"));//no value

        //values();获取所有值的集合
        Collection<String> values = hm.values();
        System.out.println(values);//[null,13, 13, 13]
        System.out.println("============================");
        // Map 集合的遍历
        //第一种:通过键找值的方式来遍历  keySet();获取所有键的集合
        Set<String> keySet = hm.keySet();
        System.out.println(keySet);//[null,3, 4, 5]
        for (String key : keySet) {
            String value = hm.get(key);
            System.out.println(key + "==" + value);
        }
        /*null==null
        3==13
        4==13
        5==13*/
        //第二种:把键值对,看做一个对象,把所有键值对,对象获取出来,然后使用键值对,对象中的方法来获取键和值。
        Set<Map.Entry<String, String>> entries1 = hm.entrySet();
   /*   Map.Entry<String, String>
        K getKey ()
        返回与此项对应的键。
        V getValue ()
        返回与此项对应的值。*/
        for (Map.Entry<String, String> stringStringEntry : entries1) {
            String key = stringStringEntry.getKey();
            String value = stringStringEntry.getValue();
            System.out.println(key + "==" + value);
        }
        /*

        null==null
        3==13
        4==13
        5==13*/

        //第三种:JDK1.8 提供的遍历方式forEach()方法 采用匿名内部类的方式重写方法来遍历集合
        hm.forEach(new BiConsumer<String, String>() {
            @Override
            //传入的就是hm的键与值
            public void accept(String key, String value) {
                System.out.println(key + "==" + value);
            }
        });
/*
null==null
3==13
4==13
5==13*/
       

LinkedHashMap类

键的数据结构链表和哈希表。链表保证了键有序,哈希表保证了键唯一。


        LinkedHashMap<String, String> stringStringLinkedHashMap = new LinkedHashMap<>();
        stringStringLinkedHashMap.put("1", "100");
        stringStringLinkedHashMap.put("6", "100");
        stringStringLinkedHashMap.put("3", "100");
        stringStringLinkedHashMap.put("2", "100");
        stringStringLinkedHashMap.put("41", "100");
        stringStringLinkedHashMap.put("4", "100");
        System.out.println(stringStringLinkedHashMap);//{1=100, 6=100, 3=100, 2=100, 41=100, 4=100}

TreeMap类

TreeMap:
键的数据结构是红黑树, 可保证键的排序和唯一性,线程是不安全的效率比较高

        
       // 排序分为自然排序和比较器排序
        //空参构造,就使用的自然排序。
        //自然排序,他对键的要求是,要求键实现Comparable接口,重写  compareTo方法,根据此方法的返回值的正负0 来决定键的排列顺序

        //自然排序
        //Integer类型的键 默认实现了Comparable接口,因此不需要手动重写就可以对键排序
        TreeMap<Integer, String> integerStringTreeMap = new TreeMap<>();
        integerStringTreeMap.put(10, "a");
        integerStringTreeMap.put(11, "a");
        integerStringTreeMap.put(14, "a");
        integerStringTreeMap.put(70, "a");
        System.out.println(integerStringTreeMap);//{10=a, 11=a, 14=a, 70=a}

        //自定义一个学生类,需要重写Comparable接口,才可以对于学生对象进行排序
        //重写的方法是按照学生姓名长度来排序:
        TreeMap<Student, String> hm1 = new TreeMap<>();
        hm1.put(new Student("张三", 23), "s002");
        hm1.put(new Student("李四", 24), "s003");
        hm1.put(new Student("王五", 25), "s004");
        hm1.put(new Student("赵六", 20), "s005");
        System.out.println(hm1);
        //{Student{name='张三', age=23}=s002, Student{name='李四', age=24}=s003, Student{name='王五', age=25}=s004, Student{name='赵六', age=20}=s005}


        //使用比较器排序,根据年龄大小排序
        TreeMap<Student, String> hm3 = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student a, Student b) {
                int num = a.getAge() - b.getAge();
                int num1 = num == 0 ? a.getName().compareTo(b.getName()) : num;
                return num1;
            }

        });
        hm3.put(new Student("张三", 23), "s002");
        hm3.put(new Student("李四", 24), "s003");
        hm3.put(new Student("王五", 25), "s004");
        hm3.put(new Student("赵六", 20), "s005");
        System.out.println(hm3);
        //{Student{name='赵六', age=20}=s005, Student{name='张三', age=23}=s002, Student{name='李四', age=24}=s003, Student{name='王五', age=25}=s004}

Hashtable类

不允许存储null值和null键 线程安全效率低

   

        Hashtable<Object, Object> objectObjectHashtable = new Hashtable<>();
        // objectObjectHashtable.put(null,"abc");不允许键或者值 为 null

集合的嵌套练习

        //练习:
       /* 统计字符串中每个字符出现的次数:“aababcabcdabcde”,获取字符串中每一个字母出现的次数要求结果:
        a(5)b(4)c(3)d(2)e(1)*/
        //分析:使用键值对集合存储,键是字符,值是次数
        String str = "aababcabcdabcde";
        HashMap<Character, Integer> characterIntegerHashMap = new HashMap<>();
        //遍历字符串中的元素,如果没有遍历的字符就存入,并先设置次数为1;如果已经存在遍历的元素,就在value值的基础上加1,并重新存储覆盖原key值。
        for (int i = 0; i < str.length(); i++) {
            if (!characterIntegerHashMap.containsKey(str.charAt(i))) {
                characterIntegerHashMap.put(str.charAt(i), 1);
            } else {
                Integer integer = characterIntegerHashMap.get(str.charAt(i));
                integer++;
                characterIntegerHashMap.put(str.charAt(i), integer);
            }
        }
        Set<Map.Entry<Character, Integer>> entries = characterIntegerHashMap.entrySet();
        for (Map.Entry<Character, Integer> entry : entries) {
            System.out.print(entry.getKey() + "(" + entry.getValue() + ")");
        }
        //a(5)b(4)c(3)d(2)e(1)
           /*
          基础班
            张三 20
            李四 22
          就业班
            王五 21
            赵六 23

            集合嵌套之HashMap嵌套HashMap
            */
        HashMap<String, Integer> jcMap = new HashMap<>();
        jcMap.put("张三",20);
        jcMap.put("李四", 22);
        HashMap<String, Integer> jyMap = new HashMap<>();
        jyMap.put("王五", 21);
        jyMap.put("赵六", 23);
        HashMap<String, HashMap<String, Integer>> maxMap = new HashMap<>();
        maxMap.put("基础班",jcMap);
        maxMap.put("就业班",jyMap);
        //遍历集合
        Set<Map.Entry<String, HashMap<String, Integer>>> entries2 = maxMap.entrySet();
        for (Map.Entry<String, HashMap<String, Integer>> stringHashMapEntry : entries2) {
            System.out.println(stringHashMapEntry.getKey());
            Set<Map.Entry<String, Integer>> entries3 = stringHashMapEntry.getValue().entrySet();
            for (Map.Entry<String, Integer> stringIntegerEntry : entries3) {
                System.out.println("\t"+stringIntegerEntry.getKey() + " " + stringIntegerEntry.getValue());
            }
            System.out.println();

        }
          /*
     三国演义
	 	吕布
	 	周瑜
	 笑傲江湖
	 	令狐冲
	 	林平之
	 神雕侠侣
	 	郭靖
	 	杨过

        Map 集合 嵌套List集合
        * */
        ArrayList<String> sgList = new ArrayList<>();
        sgList.add("吕布");
        sgList.add("周瑜");
        ArrayList<String> xaList = new ArrayList<>();
        xaList.add("令狐冲");
        xaList.add("林平之");


        ArrayList<String> sdList = new ArrayList<>();
        sdList.add("郭靖");
        sdList.add("杨过");
        HashMap<String, ArrayList<String>> bigMap = new HashMap<>();
        bigMap.put("三国演义",sgList);
        bigMap.put("笑傲江湖", xaList);
        bigMap.put("神雕侠侣", sdList);

        Set<Map.Entry<String, ArrayList<String>>> entries3 = bigMap.entrySet();
        for (Map.Entry<String, ArrayList<String>> stringArrayListEntry : entries3) {
            System.out.println(stringArrayListEntry.getKey());
            ArrayList<String> value = stringArrayListEntry.getValue();
            for (String s8 : value) {
                System.out.println(s8);
            }
            System.out.println();

        }
          /* A:
        案例演示
                集合嵌套之ArrayList嵌套HashMap
        假设ArrayList集合的元素是HashMap。有3个。
        每一个HashMap集合的键和值都是字符串。

        周瑜-- - 小乔
        吕布-- - 貂蝉

        郭靖-- - 黄蓉
        杨过-- - 小龙女

        令狐冲-- - 任盈盈
        林平之-- - 岳灵珊*/
        HashMap<String, String> sgMap = new HashMap<>();
        sgMap.put("周瑜","小乔");
        sgMap.put("吕布", "貂蝉");

        HashMap<String, String> sdMap = new HashMap<>();
        sdMap.put("郭靖", "黄蓉");
        sdMap.put("杨过", "小龙女");

        HashMap<String, String> xaMap = new HashMap<>();
        xaMap.put("令狐冲", "任盈盈");
        xaMap.put("林平之", "岳灵珊");

        ArrayList<HashMap<String, String>> bigList = new ArrayList<>();
        bigList.add(sgMap);
        bigList.add(sdMap);
        bigList.add(xaMap);
        //遍历集合
        for (HashMap<String, String> stringStringHashMap : bigList) {
            Set<Map.Entry<String, String>> entries4 = stringStringHashMap.entrySet();
            for (Map.Entry<String, String> stringStringEntry : entries4) {
                System.out.println(stringStringEntry.getKey() + "---" + stringStringEntry.getValue());
            }
            System.out.println();
        }

工具类Collections

Java针对 Collection 集合,提供了一个工具类Collections 为了方便的去操作 Collection 集合

Collections成员方法

public static void sort (List < T > list):排序, 默认按照自然顺序
public static int binarySearch (List < ? > list, T key):二分查找 前提 元素有序
public static T max(Collection < ? > coll):获取最大值
public static T min(Collection < ? > coll):获取最小值
public static void reverse (List < ? > list):反转
public static void shuffle (List < ? > list):随机置换

        
  ArrayList<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(100);
        list.add(203);
        list.add(20333);
        list.add(2014);
        Collections.sort(list);
        System.out.println(list);//[20, 100, 203, 2014, 20333]
        //可以重写排序比较器 自定义排序方式
        /*Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return 0;
            }
        });*/

        System.out.println(Collections.binarySearch(list, 200000));
        System.out.println(Collections.max(list));//20333
        System.out.println(Collections.min(list));//20

        Collections.reverse(list);
        Collections.shuffle(list);
        System.out.println(list);//[20333, 20, 100, 2014, 203]

        //先创建一个集合充当牌盒子
        ArrayList<String> pokerBox = new ArrayList<>();
        //生成54张牌放进牌盒子
        String[] colors={"♠","♥","♦","♣"};
        String[] nums={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        for (String color : colors) {
            for (String num : nums) {
                String poker = color.concat(num);
                pokerBox.add(poker);
            }
        }
        //手动添加大小王
        pokerBox.add("☀");
        pokerBox.add("☼");

        //洗牌
        Collections.shuffle(pokerBox);
        //发牌:得有三个人来斗地主,还得留三张底牌
        ArrayList<String> 星仔 = new ArrayList<>();
        ArrayList<String> 刀仔 = new ArrayList<>();
        ArrayList<String> 高进 = new ArrayList<>();
        ArrayList<String> 底牌 = new ArrayList<>();

        //发牌方式1: 一人数个10来张发给你
        /*List<String> strings = pokerBox.subList(0, 11);
        for (String string : strings) {
            星仔.add(string);
        }*/

        // 方式2:传统发牌 一人一张转着发
        //用牌的索引对3取余
      /*  星仔 0 3 6 9   余数 0
        刀仔 1 4 7 10  余数 1
        高进 2 5 8  11  余数 2 */
        for (int i = 0; i < pokerBox.size(); i++) {
            if(i>=pokerBox.size()-3){
                底牌.add(pokerBox.get(i));
            }else if(i%3==0){
                星仔.add(pokerBox.get(i));
            } else if (i % 3 == 1) {
                刀仔.add(pokerBox.get(i));
            }else{
                高进.add(pokerBox.get(i));
            }

        }
        //看牌
        System.out.println(星仔);

斗地主排序版,牌发好之后,从小到大排好

      
/*分析思路:
* 使用HashMap存储牌与对应的索引,此时牌的顺序已经存储完成
* 将索引放入一个ArrayList中,并打乱顺序发给三个人
* 三个人使用TreeSet存储索引,完成自动排序
* */
        HashMap<Integer, String> box = new HashMap<>();
        ArrayList<String> poker = new ArrayList<>();
        //生成54张牌放进牌盒子
        String[] colorss={"♠","♥","♦","♣"};
        String[] numss={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        for (String numss1 : numss) {
            for (String colorss1 : colorss) {
                String concat = colorss1.concat(numss1);
                poker.add(concat);
            }
        }
        //手动添加大小王
        poker.add("☀");
        poker.add("☼");

        //生成索引与牌的Map集合
        for (int i = 0; i < 54; i++) {
            box.put(i,poker.get(i));
        }

    //生成三个TreeSet 接收索引
        TreeSet<Integer> one = new TreeSet<>();
        TreeSet<Integer> two = new TreeSet<>();
        TreeSet<Integer> three = new TreeSet<>();
        TreeSet<Integer> four = new TreeSet<>();
        ArrayList<TreeSet<Integer>> treeSets = new ArrayList<>();
        treeSets.add(four);
        treeSets.add(one);
        treeSets.add(two);
        treeSets.add(three);

        //将索引放入一个集合中
        ArrayList<Integer> integers = new ArrayList<>();
        for (int i = 0; i < 54; i++) {
            integers.add(i);
        }
        //洗牌
        Collections.shuffle(integers);
     //根据索引发牌
        for (Integer integer : integers) {

            if (integer>= 51) {
                four.add(integers.get(integer));
            } else if (integer % 3 == 0) {
                one.add(integers.get(integer));
            } else if (integer % 3 == 1) {
                two.add(integers.get(integer));
            } else {
                three.add(integers.get(integer));
            }
        }

    //根据索引查看对应的牌
        for (TreeSet<Integer> treeSet : treeSets) {
            for (Integer integer : treeSet) {
                String s8 = box.get(integer);
                System.out.print(s8+" ");
            }
            System.out.println();
        }
    }
        
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值