Map 接口和常用方法

简介: Map 接口和常用方法

Map 接口和常用方法

在这里插入图片描述

1. Map 接口实现类的特点

这里讲的是JDK8的Map接口特点
1) Map与Collection并列存在。用于保存具有映射关系的数据: Key-Value
2) Map中的key和value可以是任何 引用类型的数据,会封装到 HashMap$Node对象中
3) Map中的key不允许重复,原因和HashSet一样
4) Map 中的 value 可以重复
5) Map的key可以为 null, value也可以为 null,注意key为 null,只能有一个,value为 null,可以多个.
6) 常用 String类作为Map的key
7) key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
8) 当 key 相同时,就等价于替换

2. Map 接口源码分析

  • Map 接口的特点
  • Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的, 因为Node实现了Entry 接口,一对k- v就是一个Entry,Entry 再放到 EntrySet 里面

在这里插入图片描述

  • Key:Value 的类型:Key(Set):Value(Collection)
  • 真正的Key:Value 是放在 HashMap$Node 中,下面的 Set 和 Collection 集合只是指向了 HashMap$Node 而已(引用),为了遍历方便

在这里插入图片描述

  • 源码解读:
  1. k-v 最后是:HashMap$Node node = newNode(hash, key, value, null);
  2. k-v 为了方便遍历,还会创建 EntrySet(集合),该集合存放的元素的类型:Entry,而一个 Entry 对象就有k-v, EntrySet<Entry<k,v>>

查看 HashMap 源码可以发现,即:transient Set<Map.Entry<K,V>> entrySet;

证明:entrySet 类型是 HashMap$EntrySet

Set set = map.entrySet();
System.out.println(set.getClass()); // HashMap$EntrySet

在这里插入图片描述

  1. 在 entrySet 中,定义的类型是 Map.Entry,但实际上存放的还是 HashMap$Node
  • 验证 EntrySet 放的是 Entry
for (Object entry : set) {
    System.out.println(entry.getClass()); // HashMap$Node
}
  • 因为 HashMap$Node implements Map.Entry,即:static class Node<K,V> implements Map.Entry<K,V>
  1. 当把 HashMap$Node 对象存放到 entrySet 就方便遍历,因为 Map.Entry 提供了两个重要发方法
  • 查看Entry源码可以发现,K getKey(); V getValue();

在这里插入图片描述

  • 直观理解:就是先把 上图 中 HashMap$Node 中的 k-v 转成一个 entry ,再把 entry 放在右边图中 entrySet 中
Set set = map.keySet();
System.out.println(set.getClass());

Collection values = map.values();
System.out.println(values.getClass());

在这里插入图片描述

3. Map 接口常用方法

  1. put:添加
Map map = new HashMap();
map.put("bookName", new Book("未来的未来", 100));//OK
map.put("bookName", "老人与海");//替换
map.put("n1", "xdr");//OK
map.put("name", "兮动人");//OK
map.put("age", null);//OK
map.put(null, "2233");//OK
map.put("xdr", "xdr630");//OK

System.out.println("map=" + map);

在这里插入图片描述

  1. remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);

在这里插入图片描述

  1. get:根据键获取值
Object val = map.get("name");
System.out.println("val=" + val);

在这里插入图片描述

  1. size:获取元素个数
System.out.println("k-v=" + map.size());

在这里插入图片描述

  1. isEmpty:判断个数是否为空
System.out.println(map.isEmpty());

在这里插入图片描述

6.clear:清除k-v

map.clear();
System.out.println("map=" + map);

在这里插入图片描述

  1. containsKey:查找键是否存在
System.out.println(map.containsKey("name"));

在这里插入图片描述

4. Map 接口遍历方法

  • Map遍历 (比List和Set复杂点,但是基本原理样)

在这里插入图片描述

  1. 第一种方法: 先取出所有的Key , 通过Key 取出对应的Value
    Map map = new HashMap();
    map.put("n1", "xdr");
    map.put("n2", "兮动人");
    map.put("n3", null);
    map.put(null, "2233");
    map.put("xdr", "xdr630");
    
    Set keyset = map.keySet();
    //(1) 增强for
    System.out.println("-----第一种方式-------");
    for (Object key : keyset) {
        System.out.println(key + "-" + map.get(key));
    }
    //(2) 迭代器
    System.out.println("----第二种方式--------");
    Iterator iterator = keyset.iterator();
    while (iterator.hasNext()) {
        Object key =  iterator.next();
        System.out.println(key + "-" + map.get(key));
    }

在这里插入图片描述

  1. 第二种方法: 把所有的 values 取出
Collection values = map.values();
//这里可以使用所有的Collections使用的遍历方法

//(1) 增强for
System.out.println("---取出所有的value 增强for----");
for (Object value : values) {
    System.out.println(value);
}
//(2) 迭代器
System.out.println("---取出所有的value 迭代器----");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
    Object value =  iterator2.next();
    System.out.println(value);

}

在这里插入图片描述

  1. 第三种方法: 通过 EntrySet 来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强for
System.out.println("----使用EntrySet的增强for----");
for (Object entry : entrySet) {
    //为了方便遍历,将entry 转成 Map.Entry
    Map.Entry m = (Map.Entry) entry;
    System.out.println(m.getKey() + "-" + m.getValue());
}
//(2) 迭代器
System.out.println("----使用EntrySet的迭代器----");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
    Object entry =  iterator3.next();
    //System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
    //向下转型 Map.Entry
    Map.Entry m = (Map.Entry) entry;
    System.out.println(m.getKey() + "-" + m.getValue());
}

在这里插入图片描述

5. Map 接口实战

  • 使用HashMap添加3个员工对象,要求 键:员工id,值:员工对象,并遍历显示 工资> 18000 的员工 (遍历方式最少两种)
  • 员工类:姓名、工资、员工id
public class MapExercise {
    public static void main(String[] args) {
    
        Map hashMap = new HashMap();
        //添加对象
        hashMap.put(1, new Emp("xdr", 30000, 1));
        hashMap.put(2, new Emp("mike", 20000, 2));
        hashMap.put(3, new Emp("jack", 10000, 3));


        //遍历2种方式
        //并遍历显示工资>18000的员工(遍历方式最少两种)
        //1. 使用keySet  -> 增强for
        Set keySet = hashMap.keySet();
        System.out.println("====增强for遍历方式====");
        for (Object key : keySet) {
            //先获取value
            Emp emp = (Emp) hashMap.get(key);
            if(emp.getSal() >18000) {
                System.out.println(emp);
            }
        }

        //2. 使用EntrySet -> 迭代器
        Set entrySet = hashMap.entrySet();
        System.out.println("======迭代器遍历方式======");
        Iterator iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Map.Entry entry =  (Map.Entry)iterator.next();
            //通过entry 取得key 和 value
            Emp emp = (Emp) entry.getValue();
            if(emp.getSal() > 18000) {
                System.out.println(emp);
            }
        }

    }
}


class Emp {
    private String name;
    private double sal;
    private int id;
    // 省略 set/get toString 构造方法
}

在这里插入图片描述

目录
相关文章
|
2月前
|
存储
`map()`方法在什么场景下会比 `forEach()`方法更高效?
综上所述,当需要对数组元素进行复杂的转换并生成新数组、进行链式调用和函数式编程、处理元素之间存在明确映射关系的情况以及与其他数组方法结合使用时,`map()`方法比`forEach()`方法更高效,能够使代码更加简洁、清晰和易于维护。
62 32
WK
|
2月前
|
Python
Python中format_map()方法
在Python中,`format_map()`方法用于使用字典格式化字符串。它接受一个字典作为参数,用字典中的键值对替换字符串中的占位符。此方法适用于从字典动态获取值的场景,尤其在处理大量替换值时更为清晰和方便。
WK
102 36
|
2月前
|
存储 JavaScript 前端开发
如何选择使用`map()`方法和`forEach()`方法?
选择使用`map()`方法还是`forEach()`方法主要取决于操作的目的、是否需要返回值、代码的可读性和维护性等因素。在实际开发中,需要根据具体的业务需求和场景来灵活选择合适的方法,以实现更高效、更易读和更易维护的代码。
29 3
|
3月前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
37 1
|
3月前
|
存储 JavaScript 前端开发
《进阶篇第8章:vuex》包括理解vuex、安装vuex、搭建vuex环境、四个map方法的使用、模块化+名命空间
《进阶篇第8章:vuex》包括理解vuex、安装vuex、搭建vuex环境、四个map方法的使用、模块化+名命空间
26 3
|
3月前
|
Java
vue2知识点:vuex中四个map方法的使用,包括:mapState、mapGetters、mapMutations、mapActions
vue2知识点:vuex中四个map方法的使用,包括:mapState、mapGetters、mapMutations、mapActions
185 1
|
4月前
|
存储 JavaScript 前端开发
`forEach()`方法和`map()`方法哪个执行效率更高?
`forEach()`方法和`map()`方法哪个执行效率更高?
|
4月前
|
JavaScript 前端开发
JavaScript Array map() 方法
JavaScript Array map() 方法
|
4月前
数组方法中的`forEach()`方法和`map()`方法有什么区别?
数组方法中的`forEach()`方法和`map()`方法有什么区别?
|
4月前
|
JavaScript 前端开发
JavaScript 中 五种迭代数组的方法 every some map filter forEach
本文介绍了JavaScript中五种常用数组迭代方法:every、some、filter、map和forEach,并通过示例代码展示了它们的基本用法和区别。