Java中的Map集合介绍

一、Map是什么?

Map是Java中集合的两大分类之一,Java概念中的集合与数学中的集合意义不同,Java中的集合是存储一组数据的容器。而从存储数据的类型,集合又可以分为两大类:Collection(即单列集合)、Map(即双列集合)。

单列集合很容易理解,存储的便是一组数据,与数组类似,但数组长度不可变,集合的长度是可变的(ArrayList底层仍然是数组,扩容是通过创建一个新的更长的数组来实现,严格意义上来说只是对数组的封装、强化,但链表就不同了)。

双列即键值对,Map中将一对Key-Value看作一个整体,Map集合中存储的便是这种键值对。例如:Map<String,Integer>表示Key为String类型,Value为Integer类型的键值对集合,我们可以在其中存储例如

"张三":22,

"李四":33,

"王五":44

这样的一组数据,如果将前面的String类型视作人名,Integer类型视作票数,我们就可以用这样的一个集合来存储每个人的票选情况。

值得注意的是,Map中要求Key不可重复,Value可以重复,我们可以把Key看成一条数据的身份证,那它当然是需要独一无二的。此外以上的例子限制了Key-Value的类型,我们也可以不限制这两项的类型,这样默认采用的是Object,因此我们可以存储任意类型的键值对数据,这点根据实际使用的要求来设定。

二、Map的常用方法

  • void clear();

        删除集合中所有数据,返回空集合。

  • boolean containsKey(Object key);

        判断集合中是否存在某个key(1个或0个)。

  • boolean equals(Object o);

        判断两个集合中是否相等。

  • V get(Object key);

        根据key获取value,key不存在则会返回空值。

  • boolean isEmpty();

        判断集合是否为空。

  • V put(K key, V value);

        往集合中添加数据(键值对),如果key已存在,则修改为新的value并返回原本的value。 

  • int size();

       返回集合的长度。

  • void putAll(Map<? extends K, ? extends V> m);

        (java8以后新增)一次性往集合中添加多条数据(将一个map中的数据添加到另一个Map中,等同于遍历后对每条数据执行put(key,value)操作)。

  • V remove(Object key);

        根据key删除数据,并返回value,如果key不存在则返回null。

  • V replace(K key, V value);

        (java8以后新增)根据key替换value,如果key不存在则返回null。

  • boolean containsValue(Object value);

        判断集合中是否存在某个value(可能存在多个)。

  • Collection<V> values();

        以一个新的集合返回map集合中所有的value。


三、Map的遍历方式

java8以后新增了一些遍历方法 ,此处将java8作为分界点。

java8以前主要通过增强for循环与迭代器来进行遍历(一般不考虑反射)。

迭代器:

1.keySet(不推荐,只能获取到key,还是得从map中查找)

Map<String, Integer> map;

//初始化map、添加数据

Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
    String key = iterator.next();
    Integer value = map.get(key);
    System.out.println("Key: " + key + ", Value: " + value);
}

2.entrySet(推荐)

Map<String, Integer> map;

//初始化map、添加数据

Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Integer> entry = iterator.next();
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println("Key: " + key + ", Value: " + value);
}

增强for循环:

3.entrySet

Map<String, Integer> map;

//初始化map、添加数据

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println("Key: " + key + ", Value: " + value);
}

4.keySet

与第一种方法相同的原因,效率低不推荐,此处省略。

java8以后添加了stream流以及lambda表达式,因此产生了一些新的遍历方法,也可以结合keySet、entrySet使用,下面展示两种比较简洁的遍历方式。

5.直接使用forEach

map.forEach((key, value) -> {
    System.out.println("Key: " + key + ", Value: " + value);
});

6.stream流

map.entrySet().stream().forEach(entry -> {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println("Key: " + key + ", Value: " + value);
});

四、常见的Map集合

1.HashMap

这是最基本也是最常用的Map实现类,用于快速查找键值对,key可以为null,但只能有一条。

特点:线程不安全,无序

底层实现:java8以前是hash表+链表,java8以后则是hash表+链表+红黑树,当链表过长以后转为红黑树。

2.LinkedHashMap

在HashMap的基础上,用双向链表连接所有数据,因此可以保证数据的有序性。

特点:线程不安全,有序

底层实现:与HashMap类似,多了一个双向链表维护元素插入顺序。

3.ConcurrentHashMap

在HashMap的基础上,采用分段锁的技术来保证线程安全性,在高并发环境下使用。

特点:线程安全,无序

底层实现:与HashMap大致相同。

4.Hashtable

是早期的Map实现类,与HashMap类似,但线程安全,由于是早期的API,为了线程安全导致开销很大,效率较低,且没有对key的空值进行特殊处理,因此key不能为空,不推荐使用

特点:线程安全,无序

底层实现:与HashMap大致相同。

5.TreeMap

由于底层是红黑树,因此可以轻松实现排序效果,可以根据key进行排序,实现了NavigableMap接口(是一个SortedMap的扩展接口)。

特点:有序,线程不安全

底层实现:红黑树。

补充:虽然TreeMap与LinkedHashMap都是有序的,但TreeMap是根据元素的key进行了排序,而LinkedHashMap是能保留插入顺序这个概念上的有序,不能混为一谈。

  • 35
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值