【Java八股文之基础篇(十五)】集合的高频面试问题(三)

集合-3

常用Map集合

Map集合的概述

Map接口是双列集合的顶层接口,下面是Map接口的定义

interface Map<K,V>  K:键的类型;V:值的类型

存储的数据必须包含key和value。

​key和value在Map集合中是一一对应的关系。一个key对应一个value。

​key在map集合中是不会重复的。

HashMap

HashMap集合的特点:

  • 底层数据结构是哈希表
  • 存储元素的顺序和遍历获取出来的顺序可能不一致
  • key不会重复
创建对象
HashMap<key的数据类型,value的数据类型> map = new HashMap<>();

例子:

 public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        HashMap<String,Integer> map = new HashMap<>();
    }
常用方法
V put(K key, V value)   //添加元素,如果key不存在就添加,如果key已经存在则是修改对应的value,并且返回修改前的value
V get(Object key)  //根据key获取对应的value值返回。如果key不存在就返回null
V remove(Object key) //根据key删除map中对应的键值对。并且把删除的value返回
boolean containsKey(Object key) //判断key是否存在
int size() //集合中键值对的对数
void clear() //清空集合中的所有键值对    
public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        //添加元素
        map.put("name", "Kplusone");
        map.put("age", "15");
        String v = map.put("name", "Kplusone666");//V=Kplusone
        String name = map.get("name");//name=Kplusone666
        String age = map.get("age");//age="15"
        //删除元素
        String delV = map.remove("age");//delV="15"
        //判断key是否存在
        if(map.containsKey("name")){
            String age111 = map.get("name");//Kplusone666
            System.out.println(age111.length());//11
        }
        //size
        int size = map.size();//1
        map.clear();
    }
遍历
  1. 使用entrySet遍历
    map集合的entrySet方法可以获取一个Set集合集合中存放的是Entry对象一个Entry对象相当于一个键值对。我们可以遍历set集合拿到Entry对象,然后获取出里面的键和值。
 public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put("name","kplusone");
        map.put("age","15");

        Set<Map.Entry<String, String>> entries = map.entrySet();
        //使用迭代器遍历entrySet
        Iterator<Map.Entry<String, String>> it = entries.iterator();
        while (it.hasNext()){
            Map.Entry<String, String> entry = it.next();
            System.out.println(entry.getKey()+"===="+entry.getValue());
        }
    }
 public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put("name","kplusone");
        map.put("age","15");
		
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //使用foreach遍历entrySet
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey()+"===="+entry.getValue());
        }
    }
  1. 使用keySet遍历
    map集合的keySet方法可以获取一个Set集合,集合中存放的是所有的key。我们可以遍历set集合拿到key对象,然后通过key获取对应的value
public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put("name","kplusone");
        map.put("age","15");

        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key+"===="+map.get(key));
        }
    }

HashMap的key去重原理

HashMap在添加元素的时候会判断集合中是否有key和本次存入的key相同。判断的时候主要是通过hashCode方法和equals方法来进行判断的。hashCode相同,并且equals判断也相同就会认为是同一个key。但是这个好像对String类型不是绝对可靠的,因为有可能存在哈希值不同,但是equals返回true的两个不同字符串对象(这种情况不可能出现,下一篇博客好好看看String类和equals方法和hashcode方法,就可以打消这个顾虑)。

所以如果我们要存储到HashMap中的key是一个自定义的类型。就需要根据情况判断下是否需要重写下hashCode方法和equals方法。重写的时候使用IDEA的提示即可。

public class Student {
    private int age;
    private String name;
	// ....此次省略了构造方法和set/get方法

    @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(age, name);
    }
}

注意:HashSet存储数据其实也是使用了HashMap。所以如果往HashSet中存储自定义对象也要看情况是否需要重写hashCode方法和equals方法。

时间关系,这篇博客先这样,但是后面这个去重原理还有很多不是很清晰的地方,下一篇博客找时间再看,补上这个坑,把知识点嚼透,这样由一个知识点引发到另一个知识点有利于将知识连接成网,面试直接以点带面,一通输出,效果会很好。其实面试提问也是这种思路,从一个简单的知识不断深挖,然后带出一堆有关联的知识。

每一个对象的hashcode是由JVM生成的,hashcode不是对象的内存地址,它的生成有很多方法,而且不同的对象hashcode有可能相同。为啥生成的值叫哈希码,是因为这个值会安装哈希算法得出一个哈希表的key,然后把这个对象放入哈希表,因为这样再次取出这个对象很快。(误区:hashcode是通过对象的内存地址通过hash算法得来的)。所以某种意义上,哈希值相同,对象可能是同一个,为什么说是可能,因为哈希表这个数据结构相同的key对应的可能是一个链表,里面有很多对象。equals相同(比较的对象内存地址)那一定是同一个对象(String除外,他重写了equals)。判断两个对象是否是同一个,先比较哈希码再比较equals,是为了提高效率。

之所以会有重写equals方法的场景,是因为我们根据自己的业务需求来判断两个对象是否相等,比如:订单号相同的订单就是相同的,那我们就重写订单的equals方法。

以上三篇博客都是整理自三更的笔记,还需要再看其他的进行补充(代码随想录、面试重点)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kplusone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值