Java集合-----Map接口

昨天写了Java集合中的Collection接口,今天继续写Map接口,记得要对之前的知识点做好巩固与复习的哦!!!

Map接口

Map接口储存一组成对的键-值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。最常见的Map实现类是HashMap,他的储存方式是哈希表,优点是查询指定元素效率高。

Map接口提供了将键映射到集合的对象,一个映射不能包含重复的键.

每个键最多只能映射到一个值.Map接口中同样提供了集合的常用方法,如clear()方法,isEmpty()方法,Size()方法等。

Map接口中有一个内部接口Entry,每个Entry对象用于封装一对key/valuevalue允许修改,但是key不允许修改。

interface Entry<K,V>{
    K getKey();
    V getValue();
    V setValue(V value);
}

Map接口中的常见方法:

Object put(Object key, Object value)用于存储一个键值对,如果出现key值冲突,则后盖前;允许 key和valuenull,但是key值只能有一个nullvalue没有null的个数限制

int size()获取集合中元素Entry的个数

Object remove(Object key)根据key值移除对应的key-value键值对,并且返回删除的value

Object get(Object key)按照key值获取对应的value值,如果key值不存在则返回null

boolean containsKey(Object key)判断map中是否存在某个特定的key

boolean containsValue(Object value)判断map中是否存在某个特定的value

void clear() 清空当前map中的所有元素

Set keySet()返回所有key所组成的Set集合,然后就可以通过key值获取对应的 value

Collection values()获取所有value值所构成的Collection集合

Set entrySet()返回map中所存储的所有entry对象,一个 entry中保存一个key/value键值对

forEach和lambda表达式实现map输出

Map<String,Integer> map=new HashMap<>(); //String--key,Integer--value 
for(int i=0;i<10;i++){ 
    map.put("key-"+i,i);//按照key值存储数据,key要求必须唯一,如果出现key值重复,则 后盖前;value没有任何特殊要求 
}
//判断map中的key知否有一个叫做key-5的键 
if(map.containsKey("key-5")){ 
    Integer value=map.get("key-5");//按照key值获取key所对应的value值 
    System.out.println(value); map.remove("key-5"); //删除对应的key-5的value值 
}
System.out.println(map.size());//获取map中所存储的key-value对的数量

遍历访问:

1.依赖key值进行遍历

Set<String> keys=map.keySet();//获取map中所有的key所组成的Set集合 
Iterator<String> it=keys.iterator(); 
while(it.hasNext()){ 
    String key=it.next(); 
    Integer value=map.get(key); //根据key获取key所对应的value值 
}

2.直接遍历所有的value

Collection<Integer> values=map.values(); //没有直接提供方法根据value获取对应的 key,因为value值没有唯一性的约束 
values.forEach(System.out::println);

3.获取所有的entry,存储在map中的键值对都是封装为Entry对象,一个key-value对对应一个entry对象

//导入语句import java.util.Map.Entry; 
Set<Entry<String,Integer>> sets=map.entrySet(); 
for(Entry<String,Integer> tmp:sets){ 
    String key=tmp.getKey(); //获取一个key-value中的key值 
    Integer value=tmp.getValue(); //获取一个key-value中的value值 
}

 Map的实现类:(HashMap、Hashtable、TreeMap、LinkedHashMap

1、HashMapMap接口的实现类。

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

具体的内部数据存储方式:

transient Node<K,V>[] table;
//哈希表的本质就是一个数组,数组中的每个元素称为一个桶,桶里存放的是一个key-value组成的链表或者红黑树

补充:哈希表是数组的一种扩展,底层依赖数组支持按照下标快速访问元素的特性,可以通过hash函数将元素的键值映射为下标,然后将对应下标的数据存储在数组中的对应位置。当按照键值查询元素时,使用相同的hash函数将key转换为数组下标,从数组中按照下标对应的位置获取数据。

静态内部类Node用于实现了Entry接口,HashMap中存储的key-value对的数据被封装为Node对象,其中key就是存放的键值,用于决定具体的存放位置【桶的位置】;value就是具体存放的数据;hash就是当前Node对象的hash值缓存;next用于指向下一个Node节点【单向链表】。

static class Node<K,V> implements Map.Entry<K,V> { 
    final int hash; 
    final K key; 
    V value; 
    Node<K,V> next;
}

HashMap采用的是链表法解决哈希冲突问题,同时引入红黑树可以避免单个链表长度过长的问题 hash函数的涉及需要考虑简单高效和分布均匀两个方面,所以首先获取对象的hashCode值,然后要将hash值的高位和低位进行与运算后再针对数组长度进行求余。

HashMap线程不安全,进行多线程操作时可能会出现扩容时执行rehash操作的死循环问题、脏读问题和size值不精确的问题。

2、HashtableMap接口的实现类。

继承的是字典类,而不是AbstractMap,目前已经不再建议使用了。

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable

hashtable的绝大多数方法上都有同步约束,所以线程安全的,但是hashtable线程安全的策略实现代价太大了。getput所有相关操作都是synchronized的,相当于给整个hashtable添加一个所,多线程并发时只能有一个线程访问,其它线程只能阻塞等待,相当于将所有操作串行化,性能非常差

存储数据:使用Entry数组,hashmap采用的是Node数组

private transient Entry<?,?>[] table;

hashtable也是一个散列表,存储内容是key-value映射,通过链地址法实现的哈希表hashtable中不允许null值的keyvalue。

注意:在Hashtable的类注释中可以看到,Hashtable是保留类,已经不建议使用;推荐在单线程环境下使用HashMap替代,如果需要多线程使用ConcurrentHashMap。

3、TreeMapMap接口的实现类。

 TreeMap用于实现一个key-value的有序集合,是通过红黑树实现的。该Map根据key的自然顺序进行排序【Comparable接口】,同时允许根据创建Map时提供的Comparator比较器进行排序,具体使用取决于所使用的构造器。

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable { 
    private transient Entry<K,V> root; //具体存放数据 
    private final Comparator<? super K> comparator;//排序的比较器 
    private transient int size = 0; //元素个数 
    private transient int modCount = 0; //修改次数,为了实现fail-fast
}

类定义:

继承于AbstractMap同时实现了Map接口,所以是一个Map类型,其中存储key-value

实现了NavigatableMap接口,意味着支持一系列的导航方法,比如获取有序的key集合

实现了Cloneable接口,意味着支持浅克隆操作

实现了Serializable接口,意味着支持序列化和反序列化操作

节点定义:

static final class Entry<K,V> implements Map.Entry<K,V> { 
    K key; //节点中存储的key值 
    V value;//节点中存储的对应key的value值 
    Entry<K,V> left; //左子树 
    Entry<K,V> right; //右子树 
    Entry<K,V> parent; //当前节点的父节点 
    boolean color = BLACK; //节点的颜色,红黑树
}

常用方法:

put(K key, V value)用于添加一个Entry节点,其中key为指定的value所关联的键,value为指定key 对应的值,如果key值已经存在,则将key对应的value修改为新值

V get(K key)用于获取对应keyvalue

特殊方法:

firstEntry返回TreeMap中最小的key

higherEntry(K key)获取位于key后一位的key-value

lowerEntry(K key)获取位于指定key前一个的key-value

HashMap通过hashCode值对其内容进行快速查找,而TreeMap中的所有元素会保持其固定的顺序。如果需要得到一个有序的结果集则应该使用TreeMap,注意:key需要实现Comparable接口或者创建TreeMap时需要指定实现Comparator接口的比较器。

HashMap通常比TreeMap效率要高一些,HashMap采用的是hash表,而TreeMap采用的是红黑树。建议多使用HashMap,只有在需要排序时才使用TreeMap。

4、LinkedHashMapMap接口的实现类。

 LinkedHashMap是HashMap的子类,LinkedHashMap额外维护了一个运行于所有条目的双向链表,默 认存储的是数据的插入顺序。HashMap是无序的,如果需要记录顺序的方式存取key-value可以使用LinkedHashMap

Map<Integer, String> map = new LinkedHashMap<>(); 
    Random r = new Random(); 
    for (int i = 0; i < 10; i++) 
        map.put(r.nextInt(100), i + "-value"); 
System.out.println(map); 

Map<Integer,String> map2=new HashMap<>(); 
    for (int i = 0; i < 10; i++) 
        map2.put(r.nextInt(100), i + "-value"); 
System.out.println(map2);

 特殊构造器:

设置采用访问顺序:如果一个key被访问过则自动调整位置到默认位置的末尾,如果不进行访问则插入顺序一致。

Map<Integer,String> map=new LinkedHashMap(10,0.75f,true); 
Random r=new Random(); 
map.put(111,"value1"); 
for(int i=0;i<10;i++) 
    map.put(r.nextInt(100),i+"-value"); 
System.out.println(map.get(111));//如果访问过111则自动排到双向链的末尾 System.out.println(map);

总结:

HashMap存取的顺序不一致,无序性,key值对象hashCodeequals方法(equals为true,要求hashCode值必须相等);

Hashtable底层采用数组+链表的方式实现,线程安全

LinkedHashMapHashMap的子类,可以2种遍历顺序可以选择,是有序的,在HashMap存储数 据的基础上引入了双向链表,通过链表可以记录顺序(自定义缓存,会增加额外的时间和空间开销)

TreeMap底层采用红黑树,key要求Comparable接口或者Comparator接口的实现(HashMap和LinkedHashMap存储速度优于TreeMap,完成所有元素的添加操作后排序则TreeMap明显优于HashMap,key要求Comparable或者构建TreeMap对象时指定Comparator,equals和compareTo)


好了,今天就先总结学习到这里吧,要记得多多学习巩固,还要多理解一些其他相关知识点,让我们一起加油!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值