Map集合的学习

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

猜你喜欢

转载自blog.csdn.net/Yang975222579/article/details/85694073