java中的双列集合(Map,HashMap,TreeMap,LinkedHashMap)

双列集合的特点

双列集合一次需要存一对数据,分别为键和值
键不能重复,值可以重复
键和值是一一对应的,每一个键只能找到自己对应的值
键+值这个整体 ,我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”

Map的常见API

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()                集合的长度,也就是集合中键值对的个数 

put 添加元素

那么这个返回值是什么呢?我们来试试看添加第二个"张三"

可以看到返回的是18,是"张三"之前对应的值,再来看看👇

还没有添加第二个”张三“的时候,返回的是null

总结:

在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null

在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。 

V remove(object key)                根据键删除键值对元素

可以看到返回的是删除键所对应的值

void clear()                移除所有的键值对元素

清空了

boolean containsKey(object key)                判断集合是否包含指定的键

boolean containsValue(object value)        判断集合是否包含指定的值

boolean isEmpty()                判断集合是否为空

如果我给数据清空了,就是👇这样

 

int size()                集合的长度,也就是集合中键值对的个数 

 

Map的遍历方式 

键找值 

装着健的单列集合使用增强for形式进行遍历

装着健的单列集合使用迭代器形式进行遍历

装着健的单列集合使用lambda表达式形式进行遍历 

键值对

装着健值对的单列集合使用增强for形式进行遍历 

装着健值对的单列集合使用迭代器形式进行遍历

装着健值对的单列集合使用lambda表达式形式进行遍历

lambda表达式 

HashMap的特点

  1. HashMap是Map里面的一个实现类,
  2. 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了
  3. 特点都是由键决定的:无序、不重复、无索引
  4. HashMap跟Hashset底层原理是一模一样的,都是哈希表结构

HashMap底层是哈希表结构的

依赖hashcode方法和equals方法保证键的唯一

如果键存储的是自定义对象,需要重写hashCode和equals方法

如果值存储自定义对象,不需要重写hashcode和equals方法 

练习 

1、创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。
存储三个键值对元素,并遍历
要求:同姓名,同年龄认为是同一个学生

HashMap的键位置如果存储的是自定义对象,需要重写hashcode和equals方法。

先写Student类

package Map;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }



    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    @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 String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
import java.util.HashMap;
import java.util.Map;
import java.util.Set;



public class MapTest1 {
    public static void main(String[] args) {
        /*创建一个HashMap集合,键是学生对象(Student),值是住址(String)。
        存储三个键值对元素,并遍历
        要求:同姓名,同年龄认为是同一个学生*/
        HashMap<Student,String>hm=new HashMap<>();
        Student s1=new Student("张三",18);
        Student s2=new Student("李四",20);
        Student s3=new Student("王五",25);
        hm.put(s1,"北京");
        hm.put(s2,"南京");
        hm.put(s3,"上海");
        //遍历集合
        //第一种方法键找值
        Set<Student> keys = hm.keySet();
        for (Student key : keys) {
            System.out.println(key+"="+hm.get(key));
        }
        System.out.println("--------------------------------------");
        //第二种方法键值对
        Set<Map.Entry<Student, String>> entries = hm.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
        System.out.println("--------------------------------------");
        //第三种方法lambda表达式
        hm.forEach((student, s) ->System.out.println(student+"="+s));
    }
}

 2、某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

package Map;

import java.util.*;



public class MapTest2 {
    public static void main(String[] args) {
        String[] arr={"A","B","C","D"};
        Random r=new Random();
        ArrayList<String>list=new ArrayList<>();
        //将
        for (int i = 0; i < 80; i++) {
            int index = r.nextInt(arr.length);
            list.add(arr[index]);
        }
        HashMap<String,Integer>hm=new HashMap<>();
        for (String s : list) {
            if(hm.containsKey(s)){
                //存在
                Integer count = hm.get(s);
                count++;
                hm.put(s,count);
            }
            else{
                //不存在
                hm.put(s,1);
            }
        }
        System.out.println(hm);
        //求最大值
        Set<Map.Entry<String, Integer>> entries = hm.entrySet();
        int max=0;
        for (Map.Entry<String, Integer> entry : entries) {
            if (entry.getValue()>max) {
                max=entry.getValue();
            }
        }
        //确定哪个景点的次数与最大值一样
        for (Map.Entry<String, Integer> entry : entries) {
            if (entry.getValue()==max) {
                System.out.println(entry.getKey());
            }
        }
    }
}

LinkedHashMap 

由键决定:序、不重复、无索引

这里的有序指的是保证存储和取出的元素顺序一致

原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序 

 与hashmap一样键也是唯一的

这里我给存储的顺序打乱了👇

可以看到存取顺序一致

TreeMap

TreeMap跟TreeSet底层原理一样,都是红黑树结构的。

键决定特性:不重复、无索引、可排序

可排序:对键进行排序。

注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则

代码书写两种排序规则

  1. 实现Comparable接口,指定比较规则。
  2. 创建集合时传递Comparator比较器对象,指定比较规则。 

练习 

1、键;整数表示id  值:字符串表示商品名称     要求:按照id的升序排列、按照id的降序排列

id的升序排列👇

package Map;

import java.util.Comparator;
import java.util.TreeMap;

public class TreeMapTest1 {
    public static void main(String[] args) {
       /* 键;整数表示id
       值:字符串表示商品名称
       要求:按照id的升序排列、按照id的降序排列*/
        TreeMap<Integer,String>tm=new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        tm.put(1,"张三");
        tm.put(3,"王五");
        tm.put(2,"李四");
        System.out.println(tm);
    }
}

id的降序排列👇

o1:当前要添加的元素

o2:表示已经在红黑树中存在的元素

2、键:学生对象   值:籍贯    要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人

Student类

package Map;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }



    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    @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 String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }

    @Override
    public int compareTo(Student o) {
        //this:表示当前要添加的元素
        // o:表示已经在红黑树中存在的元素
        /*返回值:
            负数:表示当前要添加的元素是小的,存左边
            正数:表示当前要添加的元素是大的,存右边
            0:表示当前要添加的元素已经存在,舍弃*/
        int i=this.getAge()-o.getAge();
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        return i;
    }
}

测试类

package Map;

import java.util.TreeMap;

public class TreeMapTest2 {
    public static void main(String[] args) {
        /*键:学生对象
        值:籍贯
        要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人*/
        TreeMap<Student,String>tm=new TreeMap<>();
        Student s1=new Student("张三",18);
        Student s3=new Student("王五",22);
        Student s2=new Student("李四",20);
        tm.put(s1,"北京");
        tm.put(s2,"南京");
        tm.put(s3,"上海");
        System.out.println(tm);
    }
}

 

3、字符串:"aababcabcdabcde”请统计字符串中每一个字符出现的次数,并按照以下格式输出输出结果:a(5)b(4)c(3)d(2)e(1)

 

package Map;

import java.util.TreeMap;
import java.util.function.BiConsumer;

public class TreeMapTest3 {
    public static void main(String[] args) {
        /*字符串:"aababcabcdabcde"
        请统计字符串中每一个字符出现的次数,
        并按照以下格式输出输出结果:a(5)b(4)c(3)d(2)e(1)*/
        String str="aababcabcdabcde";
        TreeMap<Character,Integer>tm=new TreeMap<>();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(tm.containsKey(c)){
                //存在
                int count=tm.get(c);
                count++;
                tm.put(c,count);
            }else{
                //不存在
                tm.put(c,1);
            }
        }
        //遍历集合,并按照指定的格式进行拼接
        StringBuilder sb = new StringBuilder();
        tm.forEach(new BiConsumer<Character, Integer>() {
            @Override
            public void accept(Character key, Integer value) {
                sb.append(key).append("(").append(value).append(")");
            }
        });
        System.out.println(sb);
    }
}


这一期就到这里啦!!!感谢观看!!!

努力遇见更好的自己!!!

  • 29
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力敲代码的小火龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值