集合Map

223 阅读2分钟

体系结构:双列集合的顶层接口

image.png

基础方法

1、V put(K key, V value):向集合中添加一个键值对对象,注意:如果向其中添加一个不存在的key,成功后会返回一个null;若向其中添加的key已经存在,则会返回被覆盖的那个对象的value值 2、V remove(Object key):根据键,删除集合中的元素 3、void clear():将集合清空 4、boolean containsKey(Object key):存在集合中是否存在某个key 5、boolean containsValue(Object value):存在集合中是否存在某个value 6、boolean isEmpty():判断集合是否为空,底层是用size来判断的 7、int size():获取集合的长度,也是集合中键值对的数量

put方法演示

@Test
void test3() {
    // 1.创建集合
    Map<String, Integer> map = new HashMap<>();

    // 2.向集合中添加元素
    Integer i1 = map.put("zhangsan", 23);
    System.out.println(i1);  // null
    Integer i2 = map.put("zhangsan", 28);
    System.out.println(i2);  // 23
    map.put("lisi", 30);
    map.put("wangwu", 40);

    // 3.查看集合中的元素
    // {lisi=30, zhangsan=28, wangwu=40}
    System.out.println(map);
}

由此可见,第一个键值对对象被第二个给覆盖掉了

Map集合的遍历方式

根据键查找值

@Test
void test4() {
    // 1.创建集合
    Map<String, Integer> map = new HashMap<>();

    // 2.向集合中添加元素
    map.put("zhangsan", 23);
    map.put("lisi", 30);
    map.put("wangwu", 40);

    // 3.遍历集合方式1
    // 拿到集合中的所有key的集合
    Set<String> keys = map.keySet();
    for (String key : keys) {
        // lisi:30  zhangsan:23  wangwu:40
        System.out.println(key + ":" + map.get(key));
    }
}

根据键值对遍历

@Test
void test5() {
    // 1.创建集合
    Map<String, Integer> map = new HashMap<>();

    // 2.向集合中添加元素
    map.put("zhangsan", 23);
    map.put("lisi", 30);
    map.put("wangwu", 40);

    // 3.遍历集合方式2
    // 先获取到集合中所有的键值对集合,然后再遍历这个集合,依次取出键值对对象的键和值
    Set<Map.Entry<String, Integer>> entries = map.entrySet();

    for (Map.Entry<String, Integer> entry: entries) {
        // lisi:30  zhangsan:23  wangwu:40
        System.out.println(entry.getKey() + ":" + entry.getValue());
    }
}

使用lambda遍历

@Test
void test6() {
    // 1.创建集合
    Map<String, Integer> map = new HashMap<>();

    // 2.向集合中添加元素
    map.put("zhangsan", 23);
    map.put("lisi", 30);
    map.put("wangwu", 40);

    // 3.遍历集合方式3,forEach底层是使用增强for进行遍历的,拿到每一个键值对对象,然后获取到这个对象的key和value,再传给方法accept,也就是我们在匿名内部类中重写的方法中
    // 使用lambda进行遍历
    // 匿名内部类的写法
    map.forEach(new BiConsumer<String, Integer>() {
        @Override
        public void accept(String s, Integer integer) {
        // lisi:30  zhangsan:23  wangwu:40
        System.out.println(s + ":" + integer);

        }
    });
    // 因为BiConsumer是一个函数式的接口,所以可以使用lambda进行简化
    // lisi:30  zhangsan:23  wangwu:40
    map.forEach((s, integer) -> System.out.println(s + ":" + integer));
}

具体案例

案例1:向集合中存储自定义对象,要求同姓名、同年龄是同一个学生

注意:实体类中需要重写equals和hashCode方法

实体类:Student.java

public class Student implements Comparable<Student>{
    private String name;
    private Integer 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 Objects.equals(name, student.name) &&
                Objects.equals(age, student.age);
    }

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

测试类:

@Test
void test7() {
    // 1.创建集合
    Map<Student, String> map = new HashMap<>();

    Student zhangsan = new Student("zhangsan", 23);
    Student lisi = new Student("lisi", 24);
    Student wangwu = new Student("wangwu", 25);
    Student wangwu2 = new Student("wangwu", 25);

    // 2.向集合中添加元素
    map.put(zhangsan, "浙江");
    map.put(lisi, "上海");
    map.put(wangwu, "北京");
    map.put(wangwu2, "北京");

    // 3.查看结果
    // {Student(name=wangwu, age=25)=北京, Student(name=lisi, age=24)=上海, Student(name=zhangsan, age=23)=浙江}
    System.out.println(map);
}

案例2:map中按照id的升序或降序排序,TreeMap

键:id,整数 值:字符串类型的 要求:map中按照id的升序或降序排序

升序排序

@Test
void test8() {
    // 1.创建集合
    TreeMap<Integer, String> treeMap = new TreeMap<>();
    
    // 2.向集合中添加元素
    treeMap.put(2, "啤酒");
    treeMap.put(1, "西瓜");
    treeMap.put(4, "可乐");
    treeMap.put(3, "红酒");

    // 3.查看结果,默认会按照升序进行排序,因为Integer中重写了compareTo方法:(x < y) ? -1 : ((x == y) ? 0 : 1);
    // {1=西瓜, 2=啤酒, 3=红酒, 4=可乐}
    System.out.println(treeMap);
}

但是如果想要按照id的降序,进行排序,那么Integer中的compareTo方法是不能满足我们的需求的,所以我们需要在创建集合的时候,传入一个比较器对象

降序排序

@Test
    void test9() {
        // 1.创建集合
        TreeMap<Integer, String> treeMap = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // o1是当前要添加的元素
                // o2是已经在红黑树中的元素
                // 该返回值规则同TreeSet
//                return o2 - o1;
                return o2 - o1;
            }
        });

        // 2.向集合中添加元素,在调用put的时候回去调用上面的compare方法
        treeMap.put(2, "啤酒");
        treeMap.put(1, "西瓜");
        treeMap.put(4, "可乐");
        treeMap.put(3, "红酒");

        // 3.查看结果,此时会按照降序进行排序,因为在创建集合的时候指定了比较器
        // {4=可乐, 3=红酒, 2=啤酒, 1=西瓜}
        System.out.println(treeMap);
    }

HashMap和TreeMap使用选择

如果没有要求元素存放的顺序的话,优先使用HashMap;如果要求按照指定的顺序存放元素的话,那么请使用TreeMap。