2021-03-31

Map集合

1、Map集合的遍历方式

1.1、遍历Map集合需要用到的方法

public Set keySet() 将Map所有的ksy封装到一个Set的集合
public V get(Object key) 根据key(键)获取Map中对应的value(值)
public Set<Map.Entry<K,V>> entrySet() 获取所有的键值对对象集合
public Collection values() 将Map中所有的value封装到一个Collection体系的集合

1.2、代码实现

public class MapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("1","小明");
        map.put("2","小廖");
        map.put("3","小邹");
        /*第一种遍历:键找值方式遍历Map集合
        * 使用的方法:public V get(Object key)    根据key(键)获取Map中对应的value(值)
        *           public Set<K> keySet()      将Map所有的key封装到一个Set的集合
        * */
        Set<String> set1 = map.keySet();
        for (String key : set1) {
            String value=map.get(key);
            System.out.println("员工编号:"+key+"员工姓名:"+value);
        }
        System.out.println("-------------------------------------------");
        /*第二种遍历:获取键值对对象集合,迭代器遍历集合获取键值对
        使用方法:public Set<Map.Entry<K,V>> entrySet(): 获取所有的键值对对象集合

        * */
        Set<Map.Entry<String, String>> set2 = map.entrySet();
        /*获取迭代器对象*/
        Iterator<Map.Entry<String, String>> iterator = set2.iterator();
        while(iterator.hasNext()){
            Map.Entry<String, String> entry = iterator.next();
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println("员工编号:"+key+"员工姓名:"+value);
        }
        System.out.println("---------------------------------------------");
        /*第三种遍历:获取键值对对象集合,增强for遍历集合获取键和值
        使用方法 public Set<Map.Entry<K,V>> entrySet()  :获取所有的键值对对象集合
        * */
        Set<Map.Entry<String, String>> set3 = map.entrySet();
        for (Map.Entry<String, String> entry : set3) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println("员工编号:"+key+"员工姓名:"+value);

        }
        System.out.println("----------------------------------------------");
        /*
        * 第四种遍历:Map集合中的value方法拿到所有的值
        * 使用的方法:public Collection<V>  values()    将Map中所有的value封装到一个Collection体系的集合
        *
        * */
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println("员工姓名:"+value);
        }
    }
}

1.3、Map的实现类有哪些

1、TreeMap:使用二叉树进行存储key-value
2、HashTable:版本比较低,线程安全,效率低,不能使用null作为key和value,对应的HashMap线程不安全,但是效率高
3、LinkedHashMap:底层使用链表来维护key-value的次序
4、Properties:也是以key-value作为键值对存储信息

2、HashMap的特性

2.1、Map集合的特性

  • Map是一个双列集合,将键映射到值的对象
  • Map集合的数据结构,只针对键有效,跟值没有关系
  • 一个映射不能包括重复的键,每个键最多只能映射到一个值

2.2、HahsMap集合的数据结构是什么

哈希表结构:数组+链表
- 通过哈希表结构配合对象的hashCode和equals方法就可以保证键的唯一性
- jdk8版本之后,在哈希表结构中引入了红黑树,当一个数组元素下挂载的链表长度为8时就会从链表转成红黑树,从而提高了查询的效率
- 注意:今后键的位置如果存储的是自定义类型,建议不要忘记重写hashCode和equals方法
在这里插入图片描述

2.3、HashMap保存元素的步骤

  1. 调用对象的hashCode()方法,获得要存储元素的哈希值
  2. 将哈希值与表的长度(即数组的长度16)进行求余运算得到一个整数值,该值就是新元素要存放的位置
    - 如果索引值对应的位置上没有存储任何元素,就可以确保这个键是唯一的,则直接将元素存储到该位置上
    - 如果索引值对应的位置上已经存储了元素,则执行第三步
  3. 遍历该位置上的所有旧元素,依次比较每个旧元素的哈希值和新元素的哈希值是否相同
    - 如果有哈希值相同的旧元素,则执行第4步
    - 如果没有哈希值相同的旧元素,则执行第五步
  4. 比较新元素和旧元素的地址是否相同
    - 如果地址相同则用新的元素替换旧的元素,停止比较
    - 如果地址值不同,则新元素调用equalse方法与旧元素比较内容是否相同
    - 如果返回true,用新的元素替换旧的元素,停止比较
    - 如果返回false,则继续比较下一个旧元素
  5. 说明没有重复,则将新元素放到该位置上并让新元素记住之前该位置的元素
    源码if(e.hash==hash&&(k=e.key)==key||(key!=null&&key.equals(k)))) 意思就是先判断hash是否相同如果相同就判断地址值是否相同如果也是相同就为true如果不同就使用重写后的equals对比内容(和上面的五步一样)

2.4、 HashMap扩容机制

其底层HashMap实例的默认初始容量(数组)是16,加载因子是0.75就是所在哈希表中的数组如果满了0.75就会扩容比如:16(数组长度)*0.75加载因子等于12,如果存储已经大于12就会扩容就会用数组的长度乘以2,产生一个新的数组,然后还有一个叫再哈希机制,比如原本扩容前的长度是16就是2122(哈希值)%16=1,而新数组长度是32就会变成2122(哈希值) 2122%32=2就会放进不同的下标的数组,也可以通过不同参数的构造方法指导初始化容量和加载因子

3、HashMap key只能唯一的特性的应用场景

3.1、需求记录商品卖出了多少件

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

public class MapDemo2 {
    public static void main(String[] args) {
        Goods g1 = new Goods("泡面", 5);
        Goods g2 = new Goods("火腿肠", 2.5);
        Goods g3 = new Goods("茶叶蛋", 1.5);
        Goods g4 = new Goods("泡面", 5);
        Goods[] goodsArr=new Goods[4];
        goodsArr[0]=g1;
        goodsArr[1]=g2;
        goodsArr[2]=g3;
        goodsArr[3]=g4;
        Map<Goods, Integer> goodsMap = new HashMap<>();
        for (Goods g : goodsArr) {
            //判断在集合中g这个商品是否存在如果不存在就说明是第一次出现
            if(!goodsMap.containsKey(g)){
                //第一次出现保存元素并记录1
                goodsMap.put(g,1);
            }else{
                //如果不是第一次出现就更新该元素的value,每一次出现都+1记录该商品的出现次数
                goodsMap.put(g,goodsMap.get(g)+1);
            }
        }
        System.out.println(goodsMap);
    }

}
class Goods{
    private String brand;
    private double price;

    public Goods(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    public Goods() {
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Goods goods = (Goods) o;
        return Double.compare(goods.price, price) == 0 &&
                Objects.equals(brand, goods.brand);
    }

    @Override
    public int hashCode() {
        return Objects.hash(brand, price);
    }

    @Override
    public String toString() {
        return "Goods{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值