Java学习笔记——Java语言基础(十六)(Map集合(HashMap、LinkedHahMap、TreeMap)集合嵌套、Collections工具类、斗地主案例实现)

一、Map集合

1.在生活中,存在一种对应关系的集合。比如:IP地址与主机名,身份证号与个人。这种对应关系叫做映射。Java中提供了专门的集合类即Map集合用来存放这种对象关系的对象。
2.Map接口与Collection接口的不同:

	Map是双列的,Collection是单列的
	Map的键唯一,Collection的子体系Set是唯一的
	Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储
Map中的集合,元素是成对存在的。每个元素都有键和值两部分组成,通过键可以找到对应的值
Map集合中不能包含重复的键,值可以重复。每个键只能对应一个值。

1.1 Map集合的方法

public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。
public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
public Set<K> keySet() : 获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。
public class MapDemo1 {
    public static void main(String[] args) {
        /*HashMap  键值对
        键的数据结构是哈希表(无序),所有的双列集合的数据结构只和键有关,与值无关*/
        //创建一个map对象
        HashMap<String, String> map = new HashMap<>();
        /*public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中
        使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;
        若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。
         */
        map.put("AAA","aaa");
        map.put("BBB","bbb");
        map.put("CCC","ccc");
        String s = map.put("CCC", "ddd");
        System.out.println(s);//ccc
        System.out.println(map);//{AAA=aaa, CCC=ccc, BBB=bbb}
        //public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
        System.out.println(map.remove("AAA"));//aaa
        System.out.println(map);//{CCC=ccc, BBB=bbb}
        //public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
        System.out.println(map.get("BBB"));//bbb
        System.out.println(map.get("sss"));//null
        System.out.println(map);//{CCC=ccc, BBB=bbb}
        /*
        判断功能
        boolean containsKey(Object key):判断集合是否包含指定的键
		boolean containsValue(Object value):判断集合是否包含指定的值
		boolean isEmpty():判断集合是否为空
         */
        boolean b = map.containsKey("AAA");
        System.out.println(b);//false
        boolean b1 = map.containsValue("bbb");
        System.out.println(b1);//true
        System.out.println(map.isEmpty());//false
        /*
        删除功能
		void clear():移除所有的键值对元素
		V remove(Object key):根据键删除键值对元素,并把值返回
         */
        String s1 = map.remove("BBB");
        System.out.println(s1);//bbb
        map.clear();
        System.out.println(map.isEmpty());//true
    }
}

1.2 Map 集合遍历键找值方式

(1)键找值方式

通过元素中的键,获取到键所对应的值
步骤:
1.获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示: keyset()
2. 遍历键的Set集合,得到每一个键。
3. 根据键,获取键所对应的值。
代码:

import java.util.HashMap;
import java.util.Set;

public class MapDemo02 {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("AAA","aaa");
        map.put("BBB","bbb");
        map.put("CCC","ccc");
        //获取所有的键,获取到键的一个集合
        Set<String> keySet = map.keySet();
        //遍历键的集合,得到每一个键
        for (String key : keySet) {
            //通过get方法获取对应的值
            String value = map.get(key);
            System.out.println(value);
        }
    }
}
(2)键值对对象找键与值

键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值
步骤:

  1. 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示: entrySet() 。
  2. 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
  3. 通过键值对(Entry)对象,获取Entry对象中的键与值。
    代码:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo03 {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("AAA","aaa");
        map.put("BBB","bbb");
        map.put("CCC","ccc");
         获取所有的键值对entry对象,以Set集合形式返回
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //遍历得到每个键值对entry对象
        for (Map.Entry<String, String> entry : entries) {
            //获取键
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println("值:"+key+"对应的值是--->"+value);
            /*
            值:AAA对应的值是--->aaa
			值:CCC对应的值是--->ccc
			值:BBB对应的值是--->bbb
            */
        }
    }
}

1.3 HashMap集合存储自定义类型键值

HashMap集合键是String类型,值是自定义Student类型。

自定义Student

public class Student {
    private String name;
    private int age;
    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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        //存储一个键为String类型,值为Student类型
        HashMap<String, Student> hashMap = new HashMap<>();
        hashMap.put("s001",new Student("张三",20));
        hashMap.put("s002",new Student("李四",21));
        hashMap.put("s003",new Student("王五",22));
        System.out.println(hashMap);
        //使用键值对entrySet方法遍历集合元素,打印学生信息
        for (Map.Entry<String, Student> entry : hashMap.entrySet()) {
            String name = entry.getValue().getName();
            int age = entry.getValue().getAge();
            String key = entry.getKey();
            System.out.println("序号"+key+","+"姓名"+name+","+"年龄"+age);
        }
        //方法2
        Set<String> keys = hashMap.keySet();
        for (String key : keys) {
            Student student = hashMap.get(key);
            int age = student.getAge();
            String name = student.getName();
            System.out.println("序号"+key+","+"姓名"+name+","+"年龄"+age);
        }
        //方法3 迭代器
        Set<Map.Entry<String, Student>> entrySet = hashMap.entrySet();
        Iterator<Map.Entry<String, Student>> iterator = entrySet.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Student> entry = iterator.next();
            int age = entry.getValue().getAge();
            String name = entry.getValue().getName();
            String key = entry.getKey();
            System.out.println("序号"+key+","+"姓名"+name+","+"年龄"+age);
        }
    }
}
HashMap集合键是自定义Student类型,值是自定义String类型。

由于HashMap集合的特点是键唯一,所以自定义Student类需要重写hashCode方法 和 equals 方法
在上述Student类中加入hashCode方法 和 equals 方法

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

测试类:

public class StudentTest {
    public static void main(String[] args) {
        HashMap<Student, String> hashMap = new HashMap<>();
        hashMap.put(new Student("李四",28),"上海");
        hashMap.put(new Student("王五",25),"北京");
        hashMap.put(new Student("赵六",28),"西安");
        Set<Student> keySet = hashMap.keySet();
        for (Student student : keySet) {
            String address = hashMap.get(student);
            System.out.println(student.toString()+"----->"+address);
        }
    }
}

给 HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法
原因:由于没有重写hashcode方法,所以在往HashMap中存放元素时依旧调用的是Object类的hashcode方法,返回的是对象的内存地址。
那么在重写了hashcode方法,这里面的hashcode方法返回的id值是hashcode值,如果两个对象的内容相同,那么他们两个的hash值是相同的。但是这时不一定能够保证两个对象的hashcode值相同,因为我们只重写了hashcode方法,并没有重写equals方法。HashMap是用链地址法来处理碰撞冲突的,就是说,一条链表上的元素的hashcode返回的hash值是相同的。重写hashCode方法只能证明两个对象的hash直相同,由于没有重写equals方法,所以并不一定相同。这是会调用Object类的equlas方法,判断的依旧是地址值,由于对象是new出来的,地址值是不一样的。所以,当 HashMap中存放自定义对象时,必须重写对象的hashCode和equals方法。

1.4 LinkedHashMap集合存储自定义类型键值

HashMap集合能够保证元素唯一,并且查询速度快,但是并不能保证存取顺序相同,那么LinkedHashMap作为HashSet的子类。
LinkedHashMap的特点:

  • 底层的数据结构是链表加哈希表,哈希表能够保证元素唯一,链表能够保证元素有序
  • Map集合的数据结构只和键有关
public class LinkedHashMapDemo {
    public static void main(String[] args) {
        //底层哈希表+链表 链表保证有序
        HashMap<String,String> map=new LinkedHashMap<>();
        map.put("a","aa");
        map.put("b","bb");
        map.put("c","cc");
        map.put("a","dd");
        System.out.println(map);//{a=dd, b=bb, c=cc}
       
    }
}

1.5 TreeMap集合存储自定义类型键值

TreeMap集合特点

  • 键的数据结构是红黑树,可以保证键的排序和唯一性
  • TreeMap排序分为自然排序和比较器排序
  • 线程不安全,效率高
TreeMap集合键是String值是String的案例
public class MyTest {
    public static void main(String[] args) {
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("aaa","AAA");
        treeMap.put("bbb","BBB");
        treeMap.put("ccc","CCC");
        treeMap.put("ccc","DDD");
        System.out.println(treeMap);//{aaa=AAA, bbb=BBB, ccc=DDD}
    }
}
TreeMap集合键是自定义类Student 值是String的案例

自定义类Student

//Student类实现Comparator接口
public class Student implements Comparable<Student>{
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", 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;
    }
    //重写compareTo方法
    @Override
    public int compareTo(Student o) {
        int num= this.age-o.age;
        int num2=num==0?this.name.compareTo(o.name):num;
        return num2;
    }
}

测试类:

public class TreeMapDemo01 {
    public static void main(String[] args) {
        /*
        排序:
            1.自然排序,使用空参构造,对键有有一定的要求,必须实现Comparable接口
         */
        //双列集合的数据结构,只和键有关
        //对键进行自然排序,键需要实现Comparator接口 Student类实现Comparator接口
        TreeMap<Student,String> treeMap = new TreeMap<>();
        treeMap.put(new Student("张三",23),"001");
        treeMap.put(new Student("张三2",24),"002");
        treeMap.put(new Student("张三3",25),"003");
        treeMap.put(new Student("张三4",26),"004");
        treeMap.put(new Student("张三5",27),"005");
        treeMap.put(new Student("张三6",28),"006");
        treeMap.put(new Student("张三7",29),"007");
        System.out.println(treeMap);
        for (Map.Entry<Student, String> studentStringEntry : treeMap.entrySet()) {
            String value = studentStringEntry.getValue();
            Student key = studentStringEntry.getKey();
            System.out.println(key+value);
        }
    }
}

在构建TreeMap对象时,参数传入比较器Comparator 重写compare方法

public class TreeMapDemo02 {
    public static void main(String[] args) {
        //参数传入比较器排序 重写compare方法
        TreeMap<Student,String> treeMap = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按着姓名长度排序
                int num=o1.getName().length()-o2.getName().length();
                int num2=num==0?o1.getName().compareTo(o2.getName()):num;
                return num2;
            }
        });
        treeMap.put(new Student("张三",23),"001");
        treeMap.put(new Student("张三2sss",24),"002");
        treeMap.put(new Student("张三3ddd",25),"003");
        treeMap.put(new Student("张三4",26),"004");
        treeMap.put(new Student("张三5",27),"005");
        treeMap.put(new Student("张三6",28),"006");
        treeMap.put(new Student("张三7",29),"007");
        for (Map.Entry<Student, String> studentStringEntry : treeMap.entrySet()) {
            String value = studentStringEntry.getValue();
            Student key = studentStringEntry.getKey();
            System.out.println(key+value);
        }
    }
}

1.6 Map集合练习

统计一个字符串中每个字符出现的次数

public class MyTest01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("输入一个字符串");
        String s = sc.nextLine();
        HashMap<Character, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (!hashMap.containsKey(c)){
                hashMap.put(c,1);
            }else {
                Integer count = hashMap.get(c);
                hashMap.put(c,++count);
            }
        }

        for (Map.Entry<Character, Integer> entry : hashMap.entrySet()) {
            Character key = entry.getKey();
            Integer value = entry.getValue();
            //System.out.print(key+"("+value+")"+" ");
            StringBuilder stringBuilder = new StringBuilder();
            StringBuilder append = stringBuilder.append(key).append("(").append(value).append(")");
            System.out.println(append);
        }
    }
}

执行结果:
在这里插入图片描述

二、集合嵌套

集合嵌套之HashMap嵌套HashMap

public class MapAndMap {
    public static void main(String[] args) {
        HashMap<HashMap<String, String>, String> hashMap = new HashMap<>();
        HashMap<String, String> hashMap1 = new HashMap<>();
        hashMap1.put("张三","20");
        hashMap1.put("李四","22");
        HashMap<String, String> hashMap2 = new HashMap<>();
        hashMap2.put("王五","24");
        hashMap2.put("赵六","26");
        hashMap.put(hashMap1,"第一组");
        hashMap.put(hashMap2,"第二组");
        //集合遍历 ,获取一个Set集合  元素为HashMap集合
        Set<HashMap<String, String>> maps = hashMap.keySet();
        for (HashMap<String, String> map : maps) {
            //遍历每个元素HashMap
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println("key"+key+" ,Value"+value);
            }
        }
    }
}

集合嵌套之ArrayList嵌套HashMap

public class ListAndMap {
    public static void main(String[] args) {
        ArrayList<HashMap<String,String>> arrayList = new ArrayList<>();
        HashMap<String, String> hashMap1 = new HashMap<>();
        hashMap1.put("周瑜","小乔");
        hashMap1.put("吕布","貂蝉");
        HashMap<String, String> hashMap2 = new HashMap<>();
        hashMap2.put("郭靖","黄蓉");
        hashMap2.put("杨过","小龙女");
        HashMap<String, String> hashMap3 = new HashMap<>();
        hashMap3.put("令狐冲","任盈盈");
        hashMap3.put("林平之","岳灵珊");
        arrayList.add(hashMap1);
        arrayList.add(hashMap2);
        arrayList.add(hashMap3);
        //集合遍历
        for (HashMap<String, String> hashMap : arrayList) {
            for (Map.Entry<String, String> entry : hashMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println("\t"+key+"---"+value);
            }
        }

    }
}

HashMap和Hashtable的区别
HashMap: 线程不安全,效率高.允许null值和null键
Hashtable: 线程安全 , 效率低.不允许null值和null键

三、Collections工具类

public class Collections {
    public static void main(String[] args) {
        /*
        集合的工具类 Collections工具类
         */
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);
        arrayList.add(140);
        //根据指定顺序进行排序
      /*  arrayList.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return  o1-o2;
            }
        });*/
        Collections.sort(arrayList);
        // //根据指定顺序进行排序
        Collections.sort(arrayList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-02;
            }
        });
        /*
        最值的方法
         */
        Integer max = Collections.max(arrayList);
        System.out.println(max);
        Integer min = Collections.min(arrayList);
        System.out.println(min);
        System.out.println(arrayList);
        //二分查找 前提元素有序
       Collections.sort(arrayList);
        int i = Collections.binarySearch(arrayList, 10);
        System.out.println(i);
        //打乱
        Collections.shuffle(arrayList);
        System.out.println(arrayList);
        //反转
        Collections.reverse(arrayList);
        System.out.println(arrayList);
        //随机置换
    }
}

模拟斗地主洗牌和发牌并对牌进行排序

public class Test2 {
    /*
    实现斗地主 实现发牌,洗牌,看牌 排序
     */
    public static void main(String[] args) {
        ArrayList<Integer> pokerIndex = new ArrayList<>();
        HashMap<Integer, String> poker = new HashMap<>();
        //定义两个集合  存储花色和序号
        String[] colors = {"♥", "♣", "♠", "♦"};
        //定义一个数字数组
        String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
        //存储大小王
        int index=0;
        poker.put(index,"大王");
        pokerIndex.add(index);
        index++;
        poker.put(index,"小王");
        pokerIndex.add(index);

            for (String number : numbers) {
                for (String color : colors) {
                    index++;
                    poker.put(index,number+color);
                    pokerIndex.add(index);
                }
        }
        //洗牌
        Collections.shuffle(pokerIndex);
        //发牌
        ArrayList<Integer> users1 = new ArrayList<>();
        ArrayList<Integer> users2 = new ArrayList<>();
        ArrayList<Integer> users3 = new ArrayList<>();
        ArrayList<Integer> dipai = new ArrayList<>();
        for (int i = 0; i < pokerIndex.size(); i++) {
            Integer integer = pokerIndex.get(i);
            if (i>=51){
                dipai.add(integer);
            }else if (i%3==1){
                users2.add(integer);
            }else if (i%3==2){
                users3.add(integer);
            }else if (i%3==0){
                users1.add(integer);
            }
        }
        Collections.sort(users1);
        Collections.sort(users2);
        Collections.sort(users3);
        Collections.sort(dipai);
        lookPoker("玩家1",poker,users1);
        lookPoker("玩家2",poker,users2);
        lookPoker("玩家3",poker,users3);
        lookPoker("玩家1",poker,dipai);
    }

    private static void lookPoker(String name,HashMap<Integer,String> hashMap,ArrayList<Integer> arrayList) {
        System.out.print(name+" ");
        for (Integer integer : arrayList) {
            String s = hashMap.get(integer);
            System.out.print(s+" ");
        }
        System.out.println();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值