Map接口和常用方法
  TEZNKK3IfmPf 2023年11月13日 41 0

注意:这里讲的是JDK8的Map接口特点Map java

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

代码在com.stulzl.map_.包中

map_

package com.stulzl.map_;

import java.util.HashMap;
import java.util.Map;

//Map接口实现类的特点  530
@SuppressWarnings({"all"})
public class Map_ {
    public static void main(String[] args) {
        //使用实现类HashMap来讲解
        //1) Map与Collection并列存在。 用于保存具有映射关系的数据:Key-Value(双列元素)
        //2. Map 中的 key 和  value 可以是任何引用类型的数据,会封装到HashMap$Node 对象中
        Map map = new HashMap();
        map.put("no1", "中国");//k-v
        map.put("no2", "张无忌");//k-v

        //3. Map 中的 key 不允许重复,原因和HashSet 一样,前面分析过源码.
        map.put("no1", "张三丰");//当有相同的K是就等价于替换  map={no2=张无忌, no1=张三丰}

        //4. Map 中的 value 可以重复
        map.put("no3", "张三丰");

        //5. Map 的key 可以为 null, value 也可以为null ,注意 key 为null,只能有一个
        // ,value 为null 可以多个
        map.put(null,null);
        map.put(null,"jack");//这不就相当于第三条中的替换效果嘛
        map.put("no4", null); //k-v
        map.put("no5", null); //k-v

        //6. 常用String类作为Map的 key,其实只要是Object子类都可以
        map.put(1,"赵敏");//这个就是int类型的
        map.put(new Object(), "金毛狮王");//k-v//甚至直接new一个Object类也可以

        //7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
        // 通过get 方法,传入 key ,会返回对应的value
        System.out.println(map.get("no2"));//张无忌

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

1.1Map存放数据key-value的底层  531

8) Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的, 因为Node实现了Entry 接口,有些书上也说一对k~v就是一个Entry(如图) [代码演示]

Map接口和常用方法

代码在com.stulzl.map_source.包中

map_source
package com.stulzl.map_source;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

//分析Map存放数据的key-value底层  531  看视频
@SuppressWarnings({"all"})
public class Map_Source {
    public static void main(String[] args) {
        //8) Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的,
        //因为Node实现了Entry 接口,有些书上也说一对k~v就是一个Entry [代码演示]
        Map map = new HashMap();
        map.put("no1", "韩顺平");//k-v
        map.put("no2", "张无忌");//k-v
        //map.put(new Car(), new Person());//k-v

        //解读
        //1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null)
        //2. k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry, 而一个Entry
        //   对象就有k,v EntrySet> 即: transient Set> entrySet;
        //3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node
        //   这时因为 static class Node implements Map.Entry
        //4. 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry 提供了重要方法
        //   K getKey(); V getValue();

        //Map集合调用entrySet()方法返回一个set集合编译类型为HashMap$EntrySet
        // 但实际Set的运行类型还是Node需要强转为Entry类型才能调用Entry接口中的方法遍历
        Set set = map.entrySet();
        //System.out.println(set.getClass());//类型是HashMap$EntrySet
        //遍历
        for (Object obj :set) {//Object类型是几乎所有类型的父类包括Node
            //System.out.println(obj.getClass());//类型是HashMap$Node
            //为了从 HashMap$Node 取出k-v
            //1. 先做一个向下转型
            Map.Entry entry = (Map.Entry)obj;//向下转型
            System.out.println(entry.getKey()+"-"+entry.getValue());
        }

        //演示直接使用keySet方法遍历set1集合中k
        Set set1 = map.keySet();//将k单独放在一个set1集合中
        System.out.println(set1);//[no2, no1]
        System.out.println(set1.getClass());//class java.util.HashMap$KeySet

        //演示直接使用values方法遍历values集合中V
        Collection values = map.values();//将V单独放在一个values集合中
        System.out.println(values);//[张无忌, 韩顺平]
        System.out.println(values.getClass());//class java.util.HashMap$Values

        //总结
        // k,v是被Entry接口封装且指向的,而Entry又被放在EntrySet集合中即 EntrySet>
        // 将Entry放在EntrySet集合中是为了方便管理
        // EntrySet是一个集合,里面的元素是Entry类型,而一个Entry对象就是一对k,v
        // 但实际k,v是Node结点类型,因为Node实现了 Entry接口,之所以将Node对象以Entry类型
        // 存放到 entrySet 集合中就是为了方便我们的遍历,因为本身HashMap$Node没有遍历方法,但是Entry接口
        // 中有getKey(),getValue方法可以直接遍历
        //Map提供了一些常用方法,如keySet()、values()、entrySet()等方法。
        //Map是java中的接口,Map.Entry是Map的一个内部接口,此接口为泛型,
        //定义为Entry。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
        //entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
    }
}
class Car {

}

class Person{

}

2. Map接口的常用方法  532

put:添加

remove:根据键删除映射关系

get:根据键获取值

size:获取元素个数

isEmpty:判断个数是否为0

clear:清除k-v

containsKey:查找键是否存在

代码在com.stulzl.map_method.包中

map_method

package com.stulzl.map_method;

import java.util.HashMap;
import java.util.Map;

//Map接口的常用方法  532
@SuppressWarnings({"all"})
public class Map_Method {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("邓超", new Book("", 100));//OK
        map.put("邓超", "孙俪");//替换-> 一会分析源码
        map.put("王宝强", "马蓉");//OK
        map.put("宋喆", "马蓉");//OK
        map.put("刘令博", null);//OK
        map.put(null, "刘亦菲");//OK
        map.put("鹿晗", "关晓彤");//OK
        map.put("hsp", "hsp的老婆");

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

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

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

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

//        isEmpty:判断个数是否为0
        System.out.println(map.isEmpty());//f

//        clear:清除k-v
       // map.clear();
       // System.out.println("map="+map);

//        containsKey:查找键是否存在
        System.out.println(map.containsKey("hsp"));//t

    }
}
class Book{
    private String name;
    private int num;

    public Book(String name, int num) {
        this.name = name;
        this.num = num;
    }
}

3. Map接口的遍历方法  533

Map接口和常用方法

3.1 ➢Map遍历方式案例演示

1) containsKey;查找键是否存在

2) keySet:获取所有的键

3) entrySet:获取所有关系k-v

4) values:获取所有的值

代码在com.stulzl.map_for.包中

map_for
package com.stulzl.map_for;

import java.util.*;

//Map遍历方式 533
@SuppressWarnings({"all"})
public class Map_For {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("邓超", "孙俪");
        map.put("王宝强", "马蓉");
        map.put("宋喆", "马蓉");
        map.put("刘令博", null);
        map.put(null, "刘亦菲");
        map.put("鹿晗", "关晓彤");

        //第一组: 先取出 所有的Key , 通过Key 取出对应的Value
        Set keyset = map.keySet();
        //(1)增强for
        System.out.println("=====增强for=====");
        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();//next()方法下移后位置的集合元素返回
            System.out.println(key+"-"+map.get(key));
        }

        //第二组: 把所有的values取出
        Collection values = map.values();
        //增强for
        System.out.println("=====增强for=====");
        for (Object value :values) {
            System.out.println(value);
        }
        //迭代器
        System.out.println("=====迭代器======");
        Iterator iterator1 = values.iterator();
        while (iterator1.hasNext()) {
            Object value =  iterator1.next();
            System.out.println(value);
        }

        //第三组: 通过EntrySet 来获取 k-v
        Set entryset = map.entrySet();//将entry 转成 Map.Entry
        System.out.println("======使用entrySet的增强for=====");
        for (Object o :entryset) {
            Map.Entry m = (Map.Entry)o;//向下转型为Map.Entry
            System.out.println(m.getKey()+"-"+m.getValue());
        }
        //使用迭代器
        System.out.println("======使用entrySet的迭代器=====");
        Iterator iterator2 = entryset.iterator();
        while (iterator2.hasNext()) {
            Object next =  iterator2.next();//HashMap$Node
            //HashMap$Node -实现-> Map.Entry接口 (getKey,getValue)
            Map.Entry m = (Map.Entry)next;//向下转型为Map.Entry
            System.out.println(m.getKey()+"-"+m.getValue());
        }
    }
}

4. Map 接口课堂练习   534

使用HashMap添加3个员工对象,要求

键:员工id

值:员工对象

并遍历显示工资> 18000的员工(遍历方式最少两种)

员工类:姓名、工资、员工id

代码在com.stulzl.map_exercise01.包中

map_exercise01

package com.stulzl.map_exercise01;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

//Map 接口课堂练习  534
//使用HashMap添加3个员工对象,要求
//键:员工id
//值:员工对象
//并遍历显示工资> 18000的员工(遍历方式最少两种)
//员工类:姓名、工资、员工id
@SuppressWarnings({"all"})
public class Map_Exercise01 {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put(123,new Employee("jack",18500,"123"));
        map.put(456,new Employee("tom",19000,"456"));
        map.put(789,new Employee("smith",16000,"789"));
        //遍历 2 种方式
        //并遍历显示工资>18000 的员工(遍历方式最少两种)
        //1. 使用 keySet -> 增强 for
        System.out.println("=====第一种遍历方式增强for=====");
        Set keySet = map.keySet();//先取出 所有的Key , 通过Key 取出对应的Value
        for (Object key :keySet) {
            //先获取value  map.get(key)的编译类型是Object  运行类型就是Employee
            //因为你想要的是工资,而工资只有value包括,如果你要用key强转的话是得不到工资的,
            // 因为key只是integer类型,并不是Employee类型的,
            // 只有value是Employee类型才能符合强转并得到想要的结果
            Employee employee = (Employee)map.get(key);//向下转型Object->Employee
            if(employee.getSalary()>18000){
                System.out.println(employee);
            }
        }

        //2. 使用 EntrySet -> 迭代器
        System.out.println("=====第二种遍历方式迭代器=====");
        Set entryset = map.entrySet();
        Iterator iterator = entryset.iterator();//调用迭代器
        while (iterator.hasNext()) {
            Object next = iterator.next();//将下一个集合元素(Node结点类型)返回
            Map.Entry m = (Map.Entry)next;//将Node结点类型向下转型为Map.Entry
            //通过entry 取得key 和 value   m.getValue()就是得到value,编译类型为Object
            Employee employee2 = (Employee)m.getValue();//将得到的v向下转型为Employee
            if(employee2.getSalary()>18000){
                System.out.println(employee2);
            }

        }
    }
}
class Employee{
    private String name;
    private double salary;
    private String id;

    public Employee(String name, double salary, String id) {
        this.name = name;
        this.salary = salary;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                ", id='" + id + '\'' +
                '}';
    }
}

5. Map 接口实现类-HashMap  535

5.1 HashMap 小结

1) Map接口的常用实现类HashMap、 Hashtable和Properties.

2) HashMap是Map接口使用频率最高的实现类。

3) HashMap是以key-val对的方式来存储数据(HashMap$Node类型)

4) key不能重复,但是值可以重复,允许使用null键和null值。

5)如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)

6)与HashSet-样,不保证映射的顺序,因为底层是以hash表的方式来存储的. jdk8的

hashMap底层数组+链表+红黑树)

7) HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有

synchronized

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   15天前   34   0   0 java
  TEZNKK3IfmPf   29天前   43   0   0 java
TEZNKK3IfmPf