Java的数据结构-Map集合

Map概述

  • 1、Map和collection没有继承关系
  • 2、Map集合以key和value的方式存储数据:键值对
  • key和value都是引用数据类型。
  • key和value都是存储对象的内存地址。
  • key起到主导的地址,value是key的一个附属品。

Map常用方法

V put(K key,V value) 向Map集合中添加键值对
V get(Object key) 通过Key获取value
void clear() 清空Map集合
boolean containsKey(Object key) 判断Map中是否包含某个Key
boolean containsValue(Object value) 判断Map中是否包含某个value
boolean isEmpty() 判断Map集合中元素个数是否为0
V remove(Object key) 通过key删除键值对
int size() 获取Map集合中键值对的个数
Set keySet() 获取Map集合中所有的key(所有的键是一个set集合)
Collection values() 获取Map集合中所有的value,返回一个Collection
Set<Map.Entry<K,V> entrySet> 将Map集合转换成Set集合遍历key-value
public class MapTest01 {
    
    
    public static void main(String[] args) {
    
    
        Map<Integer,String> map = new HashMap<>();
        //1.向Map中添加key-value
        map.put(101,"zhangsan");
        map.put(202,"lisi");
        map.put(303,"wangwu");
        map.put(404,"zhaoliu");

        //2.获取添加到Map中的key-value的个数
        System.out.println("2.Map中所有键值对的个数:"+map.size());

        //3.通过key取value
        String value = map.get(303);
        System.out.println("3.通过key取到的value为:"+value);

        //4.获取所有的value
        Collection<String> values = map.values();
        System.out.println("4.values()获取Map中的所有value:"+values);
        //foreach values
        for(String str : values){
    
    
            System.out.println("5.遍历取出:"+str);
        }

        //5.获取所有的key
        Set<Integer> keys = map.keySet();
        System.out.println("9.keySet()返回Map中所有的key:"+keys);

        //6.判断是否包含某个key和value
        System.out.println("7.判断是否包含202的key的结果为:"+map.containsKey(202));
        System.out.println("8.判断是否包含zhaoliu的value的结果为:"+map.containsValue("leilei"));

        //7.通过key删除key-value
        map.remove(404);
        System.out.println("6.调用remove()方法后的键值对的数量:"+map.size());

        //8.清空Map集合
        map.clear();
        System.out.println("10.clear()后键值对的数量为:"+map.size());
    }
}

在这里插入图片描述

put(K key,V value)实现原理

put(K key,V value)实现原理
   第一步:先将K,V封装到Node对象当中。
   第二步:底层会调用k的hashCode()方法得出hash值,然后通过哈希函数/哈希算法,将hash值转换成数组的下标,
          下标位置上如果没有任何元素,就把Node添加到这个位置上了。
          如果说下标对应的位置上有链表,此时会拿着k和链表上每一个节点中的k进行equals,
          如果所有的equals方法返回都是false,那么这个新节点将被添加到链表的末尾,
          如果其中一个equals返回可true,那么这个节点的value将会被覆盖。

get(k)实现原理

v=map.get(k)实现原理
   先调用k的hashCode方法得出哈希值,通过哈希算法转换成数组下标。
   通过数组下标快速定位到某个位置,如果这个位置上什么也没有,则返回null。
   如果这个位置上有单向链表,那么会拿着参数k和单向链表上的每个节点的k进行equals,
   如果所有的equals方法返回false,那么get方法返回null,
   只要其中有一个节点的k和参数k equals的时候返回value,那么此时这个节点的value就是我们要找的value,get方法最终返回这个要找的value。

为什么哈希表的随机增删和查询效率都很高

为什么哈希表的随机增删和查询效率都很高
   增删是在链表上完成。
   查询也不需要都扫描,只需要部分扫描

哈希表是数组和链表的结合体,所以没有将数组和链表的单独特性发挥到极致,但是效率已经很高了。

Map遍历元素的方法

1.方法一:keySet()

在这里插入图片描述

public class MapTest02Foreach {
    
    
    public static void main(String[] args) {
    
    
        Map<Integer,String> map = new HashMap<>();
        //1.向Map中添加key-value
        map.put(101,"zhangsan");
        map.put(202,"lisi");
        map.put(303,"wangwu");
        map.put(404,"zhaoliu");

        //2.keySet()遍历Map集合的第一种方法
        Set<Integer> keys = map.keySet();

        //2.1通过迭代器
        Iterator<Integer> it = keys.iterator();
        while(it.hasNext()){
    
    
            Integer key = it.next();
            String value = map.get(key);
            System.out.println("Iterator遍历:"+value);
        }

        //2.2foreach
        for(Integer key : keys){
    
    
            System.out.println("foreach遍历:"+map.get(key));
        }
    }
}

在这里插入图片描述

2.方法二:entrySet()

在这里插入图片描述

public class MapTest02Foreach {
    
    
    public static void main(String[] args) {
    
    
        Map<Integer,String> map = new HashMap<>();
        //1.向Map中添加key-value
        map.put(101,"zhangsan");
        map.put(202,"lisi");
        map.put(303,"wangwu");
        map.put(404,"zhaoliu");

        //2.entrySet()遍历Map集合的第二种方法
        Set<Map.Entry<Integer,String>> entry = map.entrySet();
        //2.1迭代器
        Iterator<Map.Entry<Integer,String>> it1 = entry.iterator();
        while(it1.hasNext()){
    
    
           Map.Entry<Integer,String> node = it1.next();
           Integer key = node.getKey();
           String value = node.getValue();
           System.out.println(key+"-->"+value);
        }

        //2.2foreach
        //这种方式效率比较高,因为获取key和value都是直接从node对象中获取的属性值
        //这种方式比较合适于大数据量
        for(Map.Entry<Integer,String> node1 : entry){
    
    
           System.out.println(node1);
        }
    }
}

在这里插入图片描述

HashMap

老杜说:哈希表的数据结构像西游记里面的珠珠门帘。横着的是数组,竖着一条一条的是链表,如下图
在这里插入图片描述

 * HashMap集合:
     *   1、HashMap集合底层是哈希表/散列表的数据结构。
     *   2、哈希表是一个怎样的数据结构呢?
     *      哈希表是一个"数组""单向链表"的结合体。哈希表将这个两种数据结构结合在一起,充分发挥它们的各自的优点。
     *      数组:在查询方面效率很高,随机增删方面效率很低。
     *      单向链表:在随机增删方面效率较高,在查询方面效率很低。
     *   3、HashMap集合底层源代码:
     *       public class HashMap{
    
    
     *           // HashMap底层实际上就是一个数组。(一维数组)
     *           Node<K,V>[] table;
     *           //静态内部类HashMap.Node
     *           static class Node<K,V>{
    
    
     *               final int hash;  //哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法),可以转换存储成数组的下标。
     *               final K key;     //存储到Map集合中的那个Key
     *               final V value;   //存储到Map集合中的那个value
     *               Node<K,V> next;  //下一个节点的内存地址。
     *           }
     *       }
     *     哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表。(数组和链表的结合体)
     */

猜你喜欢

转载自blog.csdn.net/flytalei/article/details/131721592