Map集合的学习

本文详细介绍了Map集合的特点及遍历方式,包括使用keySet和entrySet两种方法,并对比了HashMap与HashTable的不同,如线程安全性、对null值的处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Map集合的特点:

Map集合以键值对的形式保存数据
Map没有继承Collection接口
键(key)不能重复唯一,如果键的值相同那么就会覆盖原来的值
值(value)值可以重复

先来学map的遍历方式

Map集合没是先转成Set集合,在通过迭代获取元素
第一种:keySet是键的集合,Set里面的类型即key的类型
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取ke

@Test
     public void test01() {
    	 //创建HashMap集合
    	 Map<String,Integer> phone = new HashMap<String,Integer>();
         phone.put("Apple", 7299);
         phone.put("SAMSUNG", 6000);
         phone.put("Meizu", 2698);
         phone.put("Xiaomi", 2400);
         //遍历map集合
         Set<String> set = phone.keySet();
         //利用set的遍历方式
         for(String key:set) {
        	 //通过key获取值
        	 Integer value = phone.get(key);
        	 System.out.println(key+"-->"+value);
         }
    	 
     }

第二种:entrySet是 键-值 对的集合,Set里面的类型是Map.Entry
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。 Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口

@Test
     public void test02() {
    	 //创建HashMap集合
    	 Map<String,Integer> phone = new HashMap<String,Integer>();
         phone.put("Apple", 7299);
         phone.put("SAMSUNG", 6000);
         phone.put("Meizu", 2698);
         phone.put("Xiaomi", 2400);
         //遍历map集合
         Set<Entry<String,Integer>> set = phone.entrySet();
         for(Entry<String, Integer> entry:set) {
        	 //获取key
        	 String key = entry.getKey();
        	 Integer value = entry.getValue();
        	 //输出
        	 System.out.println(key+"--->"+value);
         }
    	 
     }

以上就是map集合的遍历的方式:
map集合可以转为set集合
使用set集合的迭代器遍历或者是增强for或者是普通for遍历

再来学习map集合里面的重要部分

在这里插入图片描述

HashMap

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

可以发现HashMap继承了AbstractMap这个抽象类又实现了Implements(实现)Map的接口

HashTable

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

可以发现HashMap和HashTable两个类继承不同

不同点:

HashMap继承AbstartMap
HashTable继承了Dictionary

相同点:

  实现了Map接口,意味着它们都支持key-value键值对操作。支持“添加key-value键值对”、“获取key”、“获取value”、“获取map大小”、“清空map”等基本的key-value键值对操作。
  实现了Cloneable接口,意味着它能被克隆。
  实现了java.io.Serializable接口,意味着它们支持序列化,能通过序列化去传输

两者继承不同决定了HashMap和HashTable的之间不同

Dictionary:

public abstract
class Dictionary<K,V> {}

其一:这个类是一个抽象类没有继承或者实现;里面提供了Enumeration(枚举类)去遍历的方法所以‘由于Hashtable也实现了Map接口,所以,它即支持Enumeration遍历,也支持Iterator遍历(同时也实现了Map接口)
通过源码可以发现HashTable几乎所有的方法都有**synchronized**这个关键字;所以HashTable是线程安全的
支持多线程
但是HashMap的函数则是非同步的,它不是线程安全的;
若要在多线程中使用HashMap,需要我们额外的进行同步处理。 对HashMap的同步处理可以使用Collections类提供的synchronizedMap静态方法,或者直接使用java.util.concurrent包里的ConcurrentHashMap类(这以后会写)
其二:对null值的处理不同
下面是HashTable的保存key-value的方法:

public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
        	//如果value为空那么此方法就会抛出空指针异常
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
        addEntry(hash, key, value, index);
        return null;
    }

根据上面的源码可以发现HashTable的key和value都不能为空,如果为空那么会抛出
NullPointerException(空指针异常)


下面是HashMap的put方法:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        //// 空表,需要初始化
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

HashMap的key、value都可以为null

	 Hashtable的key或value,都不能为null!否则,会抛出异常NullPointerException。
	 HashMap的key、value都可以为null

<think>嗯,用户想了解Java中Map集合的使用方法、示例教程以及数据结构。首先,我需要确认用户对Map的基础了解程度。可能他们知道Map是一种键值对结构,但需要具体的使用示例和常见操作。 根据提供的引用内容,引用[1]提到Map是键值对的数据结构,引用[2]说明HashMap基于哈希表实现,引用[3]给出了具体的代码示例,包括put、entrySet等方法的使用。用户可能需要从基础到进阶的内容,比如创建Map、添加元素、遍历、常用方法等。 用户可能希望看到代码示例,所以需要准备不同操作的代码片段,比如初始化、添加元素、获取值、遍历键值对等。同时,需要解释每个方法的作用和注意事项,比如键的唯一性、HashMap和TreeMap的区别。 另外,用户可能对性能或应用场景感兴趣,比如什么时候用HashMap,什么时候用TreeMap或LinkedHashMap。可能需要比较不同Map实现类的特点,帮助用户选择合适的结构。 还要注意引用格式,在解释过程中适当添加引用标记。例如,在提到HashMap实现时引用[^2],在展示entrySet遍历时引用[^3]。 此外,用户的问题可能隐含更深入的需求,比如并发情况下的Map选择(如ConcurrentHashMap),或者如何解决哈希冲突。但根据现有引用,可能先集中在基础使用上,再生成相关问题引导进一步学习。 需要确保回答结构清晰,分步骤讲解,每个部分有代码示例,并自然融入引用。最后生成的相关问题应覆盖使用场景、性能优化、实现类比较等,帮助用户扩展知识。</think># Java Map集合使用详解 ## 一、Map集合基础 Java Map集合采用键值对(Key-Value)存储结构,其中键不可重复,值可以重复。常用实现类包括: - `HashMap`:基于哈希表的无序实现(时间复杂度O(1))[^2] - `TreeMap`:基于红黑树的有序实现(时间复杂度O(log n)) - `LinkedHashMap`:保持插入顺序的哈希表实现 ## 二、核心操作示例 ### 1. 创建Map对象 ```java Map<String, Integer> hashMap = new HashMap<>(); Map<String, Integer> treeMap = new TreeMap<>(); ``` ### 2. 添加/修改元素 ```java hashMap.put("apple", 10); // 添加键值对 hashMap.put("banana", 5); hashMap.put("apple", 15); // 修改已有键的值 ``` ### 3. 获取元素 ```java Integer count = hashMap.get("apple"); // 返回15 Integer missing = hashMap.get("orange"); // 返回null ``` ### 4. 遍历操作 ```java // 遍历键集合 for (String key : hashMap.keySet()) { System.out.println(key); } // 遍历值集合 for (Integer value : hashMap.values()) { System.out.println(value); } // 遍历键值对(推荐方式) for (Map.Entry<String, Integer> entry : hashMap.entrySet()) { System.out.println(entry.getKey() + " => " + entry.getValue()); } ``` ## 三、常用方法说明 | 方法 | 功能描述 | 时间复杂度 | |------|----------|------------| | `put(K, V)` | 添加/更新键值对 | O(1) | | `get(K)` | 获取指定键的值 | O(1) | | `containsKey(K)` | 检查键是否存在 | O(1) | | `remove(K)` | 删除指定键值对 | O(1) | | `size()` | 返回元素数量 | O(1) | ## 四、应用场景建议 1. 数据缓存:快速存取配置信息 2. 频率统计:统计单词出现次数 3. 索引构建:建立数据库字段索引 4. 对象映射:存储用户ID与用户对象关系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值