Java集合框架(四)Map

Java集合框架(四)Map

具体分布

  • Map(接口)
    • HashMap(类)
    • SortedMap(接口)
      • TreeMap(类)

Map父接口

Map的特点

  • 存储一对数据(键值对)(Key-Value)
  • 存储无序、无下标,键不可重复值可重复
  • 在存储时,如果存储元素的key重复,则覆盖原值(新的value覆盖旧的value)
  • 在删除时,通过键值删除(因为键值唯一)

Map接口的方法

  • V put(K key,V value) //将对象存入到集合中,关联键值。key重复则分布
    
  • Object get(Object key) // 根据键获取对应的值
    
  • keySet<K> //返回所有key
    
  • Collection<V> values() //返回包含所有值的Collection集合
    
  • entrySet<Map.Entry<K,V>> //键值匹配的Set集合,Set集合中的每个元素都是键值对类型
    
  • containsKey(A) //判断是否有键A
    
  • containsValue(A) //判断是否有值A
    

举例

public class Demo01 {
    public static void main(String[] args) {
        //创建map对象(<键,值>)
        Map<String,String> map = new HashMap<>();
        map.put("cn","中国");//(key,value)
        map.put("uk","英国");
        map.put("us","美国");
        map.put("ap","苹果");
        System.out.println("--------元素个数---------");
        System.out.println(map.size());
        System.out.println("--------元素的内容(键值)---------");
        System.out.println(map.toString());
        System.out.println("--------删除---------");
        map.remove("us");
        System.out.println("--------元素个数---------");
        System.out.println(map.size());
        System.out.println("--------元素的内容(键值)---------");
        System.out.println(map.toString());
        //遍历1
        System.out.println("--------遍历1:通过keySet遍历---------");
        //先将键转换成set类型,再用set方式遍历
        //同时通过get方法直接获得键所对应的值
        Set<String> k1 = map.keySet();
        for (String s : k1) {
            System.out.println(s+":"+map.get(s));
        }
        //遍历2(效率高)
        System.out.println("--------遍历2:通过entrySet遍历---------");
        Set<Map.Entry<String,String>> k2 = map.entrySet();//set中的每个元素都是键值对类型
        for (Map.Entry<String, String> Entry : k2) {
            System.out.println(Entry.getKey()+":"+Entry.getValue());
        }
        //判断
        System.out.println("------判断是否有cn键-------");
        System.out.println(map.containsKey("cn"));
        System.out.println("------判断是否有泰国值-------");
        System.out.println(map.containsValue("泰国"));
    }
}
//输出:
--------元素个数---------
4
--------元素的内容(键值)---------
{uk=英国, cn=中国, us=美国, ap=苹果}
--------删除---------
--------元素个数---------
3
--------元素的内容(键值)---------
{uk=英国, cn=中国, ap=苹果}
--------遍历1:通过keySet遍历---------
uk:英国
cn:中国
ap:苹果
--------遍历2:通过entrySet遍历---------
uk:英国
cn:中国
ap:苹果
------判断是否有cn键-------
true
------判断是否有泰国值-------
false

HashMap (Map的实现类)

HashMap特点

  • 线程不安全,运行效率快;允许用null作为key或者value

  • 存储方式:哈希表(数组+链表+红黑树)

  • 相同的键添加只会造成覆盖,判断是否相同是更加是不是同一个对象,而不是键的内容

    通过重写key的hashcode和equals来让内容相同的键不能重复(举例)

    重写hashcode和equals,通过Alt+Insert来快捷选择

  • 当每个链表长度大于8,并且元素个数大于等于64时,会调整为红黑树,目的提高效率(jdk1.8)

  • 当链表长度小于6时,调整成链表(jdk1.8)

举例

类(重写equals和hashCode):

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

  }

  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;
  }
  public String toString(){
      return "["+this.name+" "+this.age+"]";
  }

  public Student(String name, int age) {
      this.name = name;
      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 class Demo02 {
  public static void main(String[] args) {
      //键记录学生信息,值记录学生地址
      HashMap<Student,String> student = new HashMap<>();
      Student s1 = new Student("张三",18);
      Student s2 = new Student("李四",20);
      Student s3 = new Student("王五",21);
      Student s4 = new Student("赵六",19);
      Student s5 = new Student("赵六",19);
      student.put(s1,"北京");
      student.put(s2,"天津");
      student.put(s3,"上海");
      student.put(s4,"武汉");
      student.put(s5,"秦岭");
      System.out.println("--------元素个数---------");
      System.out.println(student.size());
      System.out.println("--------元素的内容(键值)---------");
      System.out.println(student.toString());
      System.out.println("---------删除-----------");
      student.remove(new Student("张三",18));
      System.out.println("--------元素个数---------");
      System.out.println(student.size());
      System.out.println("--------元素的内容(键值)---------");
      //遍历1
      System.out.println("--------遍历1:通过keySet遍历---------");
      Set k1 = student.keySet();
      for (Object o : k1) {
          System.out.println(o+":"+student.get(o));
      }
      //遍历2(效率高)
      System.out.println("--------遍历2:通过entrySet遍历---------");
      Set<Map.Entry<Student,String>> k2 = student.entrySet();
      for (Map.Entry<Student, String> st : k2) {
          System.out.println(st.getKey()+":"+st.getValue());
      }
      //判断
      System.out.println("------判断是否有王五键-------");
      System.out.println(student.containsKey(new Student("王五",21)));
      System.out.println("------判断是否有福建值-------");
      System.out.println(student.containsValue("福建"));
  }
}
//输出:
--------元素个数---------
4
--------元素的内容(键值)---------
{[赵六 19]=秦岭, [张三 18]=北京, [李四 20]=天津, [王五 21]=上海}
---------删除-----------
--------元素个数---------
3
--------元素的内容(键值)---------
--------遍历1:通过keySet遍历---------
[赵六 19]:秦岭
[李四 20]:天津
[王五 21]:上海
--------遍历2:通过entrySet遍历---------
[赵六 19]:秦岭
[李四 20]:天津
[王五 21]:上海
------判断是否有王五键-------
true
------判断是否有福建值-------
false

HashSet和HashMap的区别

  • HashSet里面用的就是HashMap
  • 例如HashSet里面的添加add方法就是用HashMap的put实现的(用HashMap的key来保存数据,value不存东西)

扩展Hashtable

  • Hashhtable接口(jdk1.0):线程安全,运行效率慢,不允许null作为key或value
    • Properties实现类:
      • 要求key和value都是String。通常用于配置文件的读取
      • Properties可保存在流中或从流中加载

TreeMap(Map的子接口SortedMap的实现类)

TreeMap特点

  • 存储方式:红黑树(左小右大),用的时候和TreeSet一样

  • 和TreeSet一样(属性过多时要用Comparable或Comparator来确定通过什么属性比较大小):

    • 实现Comparable接口(举例2)

    • 通过Comparator实现定制比较(比较器)(举例3)

举例

类:

public class Student2 implements Comparable<Student2>{
    private String name;
    private int age;
    public Student2(){

    }

    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;
    }
    public String toString(){
        return "["+this.name+" "+this.age+"]";
    }
    public Student2(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Student2 o) {
        //先看名字是否相同,再看年龄是否相同
        int s1=this.age-o.age;
        int s2=this.getName().compareTo(o.getName());
        return s2==0?s1:s2;
    }
}

主函数:

public class Demo03 {
    public static void main(String[] args) {
        TreeMap<Student2,String> treeMap = new TreeMap<>();
        Student2 s1 = new Student2("张三",18);
        Student2 s2 = new Student2("李四",20);
        Student2 s3 = new Student2("王五",21);
        Student2 s4 = new Student2("赵六",19);
        treeMap.put(s1,"北京");
        treeMap.put(s2,"天津");
        treeMap.put(s3,"上海");
        treeMap.put(s4,"武汉");
        System.out.println("--------元素个数---------");
        System.out.println(treeMap.size());
        System.out.println("--------元素的内容(键值)---------");
        System.out.println(treeMap.toString());
        System.out.println("------------------键相同会被覆盖--------------------");
        treeMap.put(new Student2("赵六",19),"新疆");
        System.out.println("--------元素个数---------");
        System.out.println(treeMap.size());
        System.out.println("--------元素的内容(键值)---------");
        System.out.println(treeMap.toString());
        System.out.println("--------元素的内容(键值)---------");
        //遍历1
        System.out.println("--------遍历1:通过keySet遍历---------");
        Set k1 = treeMap.keySet();
        for (Object o : k1) {
            System.out.println(o+":"+treeMap.get(o));
        }
        //遍历2(效率高)
        System.out.println("--------遍历2:通过entrySet遍历---------");
        Set<Map.Entry<Student2,String>> k2 = treeMap.entrySet();
        for (Map.Entry<Student2, String> st : k2) {
            System.out.println(st.getKey()+":"+st.getValue());
        }
        //判断
        System.out.println("------判断是否有王五键-------");
        System.out.println(treeMap.containsKey(new Student2("王五",21)));
        System.out.println("------判断是否有福建值-------");
        System.out.println(treeMap.containsValue("武汉"));
    }
}
//输出:
--------元素个数---------
4
--------元素的内容(键值)---------
{[张三 18]=北京, [李四 20]=天津, [王五 21]=上海, [赵六 19]=武汉}
------------------键相同会被覆盖--------------------
--------元素个数---------
4
--------元素的内容(键值)---------
{[张三 18]=北京, [李四 20]=天津, [王五 21]=上海, [赵六 19]=新疆}
--------元素的内容(键值)---------
--------遍历1:通过keySet遍历---------
[张三 18]:北京
[李四 20]:天津
[王五 21]:上海
[赵六 19]:新疆
--------遍历2:通过entrySet遍历---------
[张三 18]:北京
[李四 20]:天津
[王五 21]:上海
[赵六 19]:新疆
------判断是否有王五键-------
true
------判断是否有福建值-------
false

TreeSet和TreeMap的区别

  • TreeSet里面用的就是TreeMap
  • 例如TreeSet里面的添加add方法就是用TreeMap的put实现的(用TreeMap的key来保存数据,value不存东西)
posted @   史小鹏  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示