4.3. HashMap.TreeMap.Properties

一. Map接口

1、Map和Collection没有继承关系

2、Map集合以keyvalue的方式存储数据:键值对

keyvalue都是引用数据类型
keyvalue都是存储对象的内存地址
key 起主导的地位,valuekey 的一个附属品

1. Map接口中的常用方法

  1. V put​(K key, V value) 向 Map 集合中添加键值对


  2. V get​(Object key) 通过可以获取 value


  3. Void clear () 清空 Map 集合


  4. Boolean containsKey (Object key) 判断 Map 中是否包含某个 key


  5. Boolean containsValue (Object value) 判断 Map 中是否包含某个 value


  6. Boolean isEmpty () 判断 Map 集合中元素个数是否为 0


  7. Set<K> keySet () 获取 Map 集合所有的 key(所有的键是一个 set 集合)


  8. V remove​(Object key) 通过 key 删除键值对


  9. Int size () 获取 Map 集合中键值对的个数。


  10. Collection<V> values () 获取 Map 集合中所有的 value,返回一个 Collection


  11. Set<Map.Entry<K,​V>> entrySet () b 将 Map 集合转换成 Set 集合


注意:

Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态类
Map集合通过entrySet()的方法转换成的这个Set集合,Set集合中的元素的类型都是Map.Entry<K,V>

2. 遍历Map集合

import java.util.*;

public class MapText {
    public static void main(String[] args) {

        //第一种方式:获取所有Key,通过遍历key。来遍历value
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");
        map.put(4,"zhaoliu");
    }
}

2.1. 第一种方式:

获取所有Key,通过遍历key。来遍历value

//遍历Map集合
     //获取所有的key,所有的key是一个Set集合
     Set<Integer> keys = map.keySet();
     //遍历key,通过key返回value
     //迭代器也可以
     Iterator<Integer> it = keys.iterator();
     while (it.hasNext()){
         Integer key = it.next();
         String value = map.get(key);
         System.out.println(key + "=" + value);
     }

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

2.2. 第二种方法:

Set<Map.Entry<K,​V>> entrySet() b 将 Map 集合转换成 Set 集合,Set 集合中元素的类型是:Map.Entry

Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态类

image.png|775

Set<Map.Entry<Integer,String>> set = map.entrySet();
       //遍历Set集合,每一次取出一个Node
       //迭代器
       Iterator<Map.Entry<Integer,String>> it = set.iterator();
       while (it.hasNext()){
           System.out.println(it.next());
       }

或者

Set<Map.Entry<Integer,String>> set = map.entrySet();
//遍历Set集合,每一次取出一个Node
//迭代器
Iterator<Map.Entry<Integer,String>> it = set.iterator();
while (it.hasNext()){
    Map.Entry<Integer,String> node = it.next();
    Integer key = node.getKey();
    String value = node.getValue();
    System.out.println(key + "=" + value );
}

foreach:

  • 这种方式效率比较高,因为获取key和value都是直接从node对象中获取的属性值
  • 这种方式比较适合大数据
Set<Map.Entry<Integer,String>> set = map.entrySet();
      for (Map.Entry<Integer,String> node: set){
          System.out.println(node.getKey() + "--->" + node.getValue());
      }

二. HashMap集合

HashMap 集合底层是哈希表/散列表的数据结构。

在 JDK 8 之后,如果哈希表单向链表中元素超过 8 个单向链表这种数据结构会变成红黑树数据结构。当红黑树上的节点数量小于 6 时,会重新把红黑树变成单向链表数据结构。

这种方式也是为了提高检索效率,二叉树的检索会再次缩小扫描范围。提高效率。

1. 哈希表

哈希表是一个怎样的数据结构?
是一个一维数组,这个数组中每一个元素是一个单向链表。(数组和链表的结合体)

哈希表是一个数组和单向链表的结合体

  • 数组:在查询方面效率很高,随机增删效率很低。
  • 单向链表:在随机增删方面效率很高,在查询方面效率很低
  • 哈希表将以上的两种数据结构融合在一起,充分发挥了它们各自的优点。

对于哈希表数据结构来说:

  • 如果 o 1 和 o 2 的 hash 值相同,一定是放到同一个单向链表上。
  • 当然如果 o 1 和 o 2 的 hash 值不相同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”

2. HashMap集合底层的源代码

public class HashMap{

    //HashMap底层实际上就是一个数组。(一维数组)
    Node<K,V>[] table;
    
    //静态的内部类HashMap.Node
    static class Node<K,V>{
        final int hash;//哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数,可以转换成数组的下标)
        final K ley; //存储到Map集合中的那个key
        V value;//存储到Map集合中的那个value
        Node<K,V> next;//下一个节点的内存地址
    }
}

HashMap

image.png|900

2.1. 为什么哈希表的随机增删,以及查询效率都很高?

增删是在链表上完成的。
查询也不需要都扫描,只需要部分扫描。

3. HashMap集合的key特点

无序不可重复

  • 为什么无序? 因为不一定挂在哪个单向链表上。
  • 不可重复是怎么保证的? equals () 方法来保证 HashMap 集合的 key 不可重复。如果 key 重复了,value 会覆盖。

放在 HashMap 集合 key 部分的元素其实就是放到 HashSet 集合中了。

所以 HashSet 集合中的元素也需要同时重写 hashCode ()+equals () 方法

4. 哈希表HashMap使用不当时无法发挥性能

假设将所有的 hashCode () 方法返回值固定为某个值,那么会导致底层哈希表变成了纯单向链表。这种情况我们称为:散列分布不均匀

什么实际散列分布均匀?

假设有 100 个元素,10 个单向链表,那么每个单向链表上有 10 个节点,这是最好的,是散列分布均匀的。

假设将所有的 hashCode () 方法返回值都设定为不一样的值,可以吗?

不可以,因为这样的话导致底层哈希表就变成了一维数组了,没有链表的概念了。也是散列分布不均匀。

5. 必须同时重写hashCode和equals方法

放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法

并且 equals() 方法返回如果是true,hasCode() 方法返回的值必须一样

6. HashMap集合容量

HashMap 集合的默认初始化容量是 16,默认加载因子是 0.75

这个默认加载因子是当 HashMap 集合底层数组的容量达到 75%的时候,数组开始扩容。

重点:HashMap 集合的初始化容量必须是 2 的倍数,这也是官方推荐的,这是因为达到散列均匀,为了提高 HashMap 集合的存取效率,所必需的。

7. HashMap集合key允许为null

注意:但是HashMap集合keynull只能有一个

三. HashMap和Hashtable的区别

Hashtable的keyvalue都是不能为null的。
HashMap集合的keyvalue都是可以为null的。

Hashtable集合初始化容量是11集合扩容是:原容量*2+1

四. TreeMap集合

TreeMap集合底层实际上是一个二叉树。

五. Properties类

Properties是一个Map集合继承Hashtable,Properties的keyvalue都是String类型;

Properties被称为属性类对象

Properties是线程安全的。

import java.util.Properties;

public class PropertiesText {
    public static void main(String[] args) {
        //创建一个Properties对象
        Properties pro = new Properties();

        //需要掌握Properties的两个方法,一个存,一个取
        pro.setProperty("url","jdbc:mysql://localhost:3306/bjpowernode");
        pro.setProperty("driver","com.mysql.jdbc.Driver");
        pro.setProperty("username","root");
        pro.setProperty("password","123");

        //通过key获取value
         String url = pro.getProperty("url");
         String driver = pro.getProperty("driver");
         String username = pro.getProperty("username") ;
         String password = pro.getProperty("password");

        System.out.println(url);
        System.out.println(driver);
        System.out.println(username);
        System.out.println(password);
    }
}
image.png|375

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇