JavaSE Map集合

JavaSE Map集合


目录

Map 集合是什么?有什么用?

Map 与 Collection 并列存在,用于保存具有映射关系的数据。具体来说,是键值对 <key, value>。

key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。

返回目录


Map 集合怎么用?

1 Map 集合的继承图(常用部分)

在这里插入图片描述

返回目录


2 Map 接口
2-1 介绍

Map 中的 key 和 value 可以实任何引用类型。

Map 中的 key 不允许重复, value 允许重复。

Map 中通过 equals 方法判断 key 是否相等。

Map 中添加重复的 key,会对 value 进行更新。

常用 String 类作为 Map 的 key。

返回目录

2-2 常用方法
public interface Map<K,V> {
    ...
 	// 1、增删改查

    // 添加一个 k-v 对。如果集合中相等的 key 已经存在,则更新 value 的值。
    V put(K key, V value);
    // 将指定 map 中的所有 k-v 对,复制到本 map 中。
    void putAll(Map m);

    // 删除指定 Key 所对应的 k-v 对,返回对应的 value。如果相等的 key 不存在,则返回 null。
    V remove(Object key);
    // 删除指定的 k-v 对。(key 和 value 必须都相等才删除)
    default boolean remove(Object key, Object value) {...}
    // 清空集合
    void clear();

    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回 null。
    V get(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回指定值 defaultValue。
    default V getOrDefault(Object key, V defaultValue) {...}
    // 查询集合中是否包含指定的 key
    boolean containsKey(Object key);
    // 查询集合中是否包含指定的 value
    boolean containsValue(Object value);
    
    // 2、集合属性
    // 查询集合中 k-v 对的数量。
    int size();
    // 查询集合是否为空。
    boolean isEmpty();
    
	// 3、遍历集合
    // 返回集合中所有的 key,以 Set 集合的形式返回。
    Set<K> keySet();
    // 返回集合中所有的 value,以 Collection 集合的形式返回。
    Collection<V> values();
    // 返回集合中所有的 k-v 对,以 Set 集合的形式返回。
    // Set 集合中的每个元素都是 Map.Entry 类型。
    Set<Map.Entry<K, V>> entrySet();
    // 内部类 Map.Entry,该类封装了一个 k-v 对。
    interface Entry<K,V> {
        // 返回 key 值
        K getKey();
        // 返回 value 值
        V getValue();
        // 更新 value 值,并返回旧的 value 值。
        V setValue(V value);
    }
    ...
}

返回目录

2-3 代码示例
  • 遍历 key
Map<String, String> map = new HashMap<>();
map.put("I", "我");
map.put("am", "是");
map.put("Chinese", "中国人");
Set<String> keys = map.keySet();
// 迭代器遍历
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
    String str = it.next();
    System.out.print(str + " "); // I Chinese am
}
// foreach 遍历
for (String str : keys) {
    System.out.print(str + " "); // I Chinese am
}
  • 遍历 value
Map<String, String> map = new HashMap<>();
map.put("I", "我");
map.put("am", "是");
map.put("Chinese", "中国人");
Collection<String> values = map.values();
// 迭代器遍历
Iterator<String> it = values.iterator();
while (it.hasNext()) {
    String str = it.next();
    System.out.print(str + " "); // 我 中国人 是
}
// foreach 遍历
for (String str : values) {
    System.out.print(str + " "); // 我 中国人 是
}
  • 遍历 k-v 对
Map<String, String> map = new HashMap<>();
map.put("I", "我");
map.put("am", "是");
map.put("Chinese", "中国人");
Set<Map.Entry<String, String>> entries = map.entrySet();
// 迭代器遍历
Iterator<Map.Entry<String, String>> it = entries.iterator();
while (it.hasNext()) {
    Map.Entry<String, String> entry = it.next();
    System.out.println(entry.getKey() + " " + entry.getValue()); // I 我 Chinese 中国人 am 是
}
// foreach 遍历
for (Map.Entry<String, String> entry : entries) {
    System.out.println(entry.getKey() + " " + entry.getValue()); // I 我 Chinese 中国人 am 是
}
  • 根据 value 值排序
// 按照字符出现频率排序
Map<Character, Integer> map = new HashMap<>();
map.put('a', 3);
map.put('b', 6);
map.put('c', 1);
map.put('d', 5);
Set<Map.Entry<Character, Integer>> entries = map.entrySet();
// 借助 List 保存 k-v 对
List<Map.Entry<Character, Integer>> entryList = new ArrayList<>(entries);
System.out.println(entryList); // [a=3, b=6, c=1, d=5]
// 对 List 排序
entryList.sort((e1, e2) -> {
    return e2.getValue() - e1.getValue();
});
System.out.println(entryList); // [b=6, d=5, a=3, c=1]

返回目录


3 HashMap 类
3-1 介绍

HashMap 是线程不安全的。

HashMap 的 key 可以为 null,但是只能有一个;value 可以为 null,可以有多个。

HashMap 不能保证元素的顺序。

HashMap 根据 key 的 hashCode,将其添加到数组的特定位置上。通过 equals 方法判断两个 key 是否相等。

返回目录

3-2 底层结构

(1)HashMap 底层是数组+链表的数据结构。

数组是 Node[] table,数组的每个位置上,存放着 Node 节点,该节点可以指向下一个 Node节点,从而形成链表。

(2)k-v 包装在 Node 类中,该类是 HashMap 的内部类。

public class HashMap<K,V> ...{
    ...
    transient Node<K,V>[] table;

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

返回目录

3-3 扩容机制
  • 初始化:

无参构造器,默认数组为 null,负载因子为 0.75。第一次添加元素时创建数组,数组容量为 16,扩容临界值为 16*0.75=12。

有参构造器,自定义容量,自定义负载因子,默认数组为 null。第一次添加元素时创建数组,自定义容量生效(最终实际容量>=自定义容量,并且是 2^n (1, 2, 4, 8…) 的数),同时扩容临界值更新为 实际容量 * 负载因子。

  • 扩容:

第一次添加元素后,每次扩容,数组容量扩大为原来的 2 倍;

而对于扩容临界值,如果原数组容量>=16,则扩容临界值扩大为原来的 2 倍;如果原数组容量<16,则扩容临界值更新为 扩容后的 容量 * 负载因子。

  • 链表树化:

同时满足(1)链表节点数 >8;(2)数组长度 >=64;则进行树化。

public class HashMap<K,V> ...{
    ...
    static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认负载因子 0.75
    final float loadFactor; // 负载因子
    int threshold;	// 扩容的临界值

    // 无参构造器,默认负载因子为 0.75
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    // 有参构造器,自定义容量,最终容量为 >=initialCapacity 并且为 2^n 的数;默认负载因子为 0.75。
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    // 有参构造器,自定义容量,最终容量为 >=initialCapacity 并且为 2^n 的数;自定义负载因子。
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }
    // 计算容量:返回 >=cap 并且为 2^n 的数
    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }
	...
}
public class HashMap<K,V> ...{
    ...
    static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认负载因子 0.75
    static final int MAXIMUM_CAPACITY = 1 << 30;	// 数组最大容量
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默认数组初始化容量 16
    static final int TREEIFY_THRESHOLD = 8;	// 链表进行树化的链表长度临界值 8
    static final int MIN_TREEIFY_CAPACITY = 64; // 链表进行树化的数组长度临界值 64
    final float loadFactor; // 负载因子
    int threshold;	// 扩容临界值

    // 添加元素
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    // 真正添加元素的方法
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        // 如果数组 table 为空,则进行扩容。
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        // 插入的 key 没有产生冲突,直接插入。
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        // 插入的 key 产生冲突
        else {
            Node<K,V> e; K k;
            // 相等的 key 已经存在,更新 value,并返回旧的 value。
            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);
                        // 链表节点数 >8 时,判断是否进行树化。
                        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;
                }
            }
            // 更新 value,并返回旧的 value。
            if (e != null) { 
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
    
    // 扩容方法
    final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap > 0) {
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            // 老数组的容量 >=16,则数组容量扩大为原来 2 倍,扩容临界值扩大为原来 2 倍。
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }
        else if (oldThr > 0) 
            newCap = oldThr;
        else { 
            // 空数组,扩容临界值为 0;第一次添加元素时,初始化数组容量为 16,扩容的临界值为 16*0.75=12
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        // 如果新的扩容临界值为 0,则使其为 newCap * loadFactor。
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        @SuppressWarnings({"rawtypes","unchecked"})
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = newTab;
        // 将老数组的数据移到新数组
        if (oldTab != null) {
            for (int j = 0; j < oldCap; ++j) {
				...
            }
        }
        return newTab;
    }
    
    // 判断链表是否进行树化
    // 树化条件:(1)链表长度 >8。(2)数组长度 >=64。
    final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; Node<K,V> e;
        // 如果数组长度 <64,则不树化,转而扩容数组。
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize();
        // 树化。
        else if ((e = tab[index = (n - 1) & hash]) != null) {
            TreeNode<K,V> hd = null, tl = null;
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);
                if (tl == null)
                    hd = p;
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
            if ((tab[index] = hd) != null)
                hd.treeify(tab);
        }
    }
	...
}

返回目录

3-4 常用方法
public class HashMap<K,V> ...{
	// 1 构造器
    // 无参构造器,默认数组容量为 16,默认负载因子为 0.75。
    public HashMap() {...}
    // 有参构造器,自定义数组容量,,默认负载因子为 0.75。
    public HashMap(int initialCapacity) {...}
    // 有参构造器,自定义数组容量,自定义负载因子。
    public HashMap(int initialCapacity, float loadFactor) {...}
    // 有参构造器,复制 Map 集合元素。
    public HashMap(Map<? extends K, ? extends V> m) {...}
    
    // 2 作为 Map(详见 Map 接口的常用方法)
    // 添加一个 k-v 对。如果集合中相等的 key 已经存在,则更新 value 的值。
    V put(K key, V value);
    // 删除指定 Key 所对应的 k-v 对,返回对应的 value。如果相等的 key 不存在,则返回 null。
    V remove(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回 null。
    V get(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回指定值 defaultValue。
    default V getOrDefault(Object key, V defaultValue) {...}
}

返回目录


4 LinkedHashMap 类
4-1 介绍

LinkedHashMap 是 HashMap 的子类。

HashMap 是无序的,即它不能保证元素的迭代顺序和插入顺序一致。

而 LinkedHashMap 可以保证元素的迭代顺序和插入顺序一致。

返回目录

4-2 底层结构

LinkedHashMap 底层是 HashMap + 双向链表。具体的说,LinkedHashMap 的节点与 HashMap 的节点不同,

多了 before 和 after 两个引用变量,分别指向“之前插入的元素”和“之后插入的元素”,从而形成双向链表。

该链表上的元素顺序,和插入顺序一致。

同时,LinkedHashMap 维护者 head 和 tail 两个引用变量,分别指向“插入的第一个节点”和“插入的最后一个节点”。

public class LinkedHashMap<K,V> ...{
    ...
    // 指向插入的第一个节点
    transient LinkedHashMap.Entry<K,V> head;
    // 指向插入的最后一个节点
    transient LinkedHashMap.Entry<K,V> tail; 
    
    // LinkedHashMap 节点的类型。与 HashMap 中的节点不同,不同点在于多了 before 和 after 两个引用变量。
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

    // 创建节点
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        // 额外操作:对插入的元素,按其插入顺序连接起来,形成双向链表。
        linkNodeLast(p);
        return p;
    }
    
    // 额外操作:对插入的元素,按其插入顺序连接起来,形成双向链表。
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }
    ...
}

返回目录

4-3 扩容机制

和 HashMap 一样。

返回目录

4-4 常用方法
public class LinkedHashMap<K,V> ...{
	// 1 构造器
    // 无参构造器,默认数组容量为 16,默认负载因子为 0.75。
    public LinkedHashMap() {...}
    // 有参构造器,自定义数组容量,,默认负载因子为 0.75。
    public LinkedHashMap(int initialCapacity) {...}
    // 有参构造器,自定义数组容量,自定义负载因子。
    public LinkedHashMap(int initialCapacity, float loadFactor) {...}
    // 有参构造器,复制 Map 集合元素。
    public LinkedHashMap(Map<? extends K, ? extends V> m) {...}
    
    // 2 作为 Map(详见 Map 接口的常用方法)
    // 添加一个 k-v 对。如果集合中相等的 key 已经存在,则更新 value 的值。
    V put(K key, V value);
    // 删除指定 Key 所对应的 k-v 对,返回对应的 value。如果相等的 key 不存在,则返回 null。
    V remove(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回 null。
    V get(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回指定值 defaultValue。
    default V getOrDefault(Object key, V defaultValue) {...}
}

返回目录

4-5 代码示例
  • 按存储顺序遍历
Map<String, String> map = new LinkedHashMap<>();
map.put("I", "我");
map.put("am", "是");
map.put("Chinese", "中国人");
// 遍历 k-v 对
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
    System.out.println(entry.getKey() + " " + entry.getValue()); // I 我 am 是 Chinese 中国人
}
// 遍历 key
Set<String> keys = map.keySet();
for (String key : keys) {
    System.out.println(key); //  I am Chinese
}
// 遍历 value
Collection<String> values = map.values();
for (String value : values) {
    System.out.println(value); // 我 是 中国人
}

返回目录


5 Hashtable 类
5-1 不推荐使用

Hashtable 是一个古老的类,它从 JDK 1.0 起就已经出现了。

Hashtable 是线程安全的,所以它比 HashMap 效率低一些。

Hashtable 不允许使用 null 作为 key 和 value,如果这么做,会抛出异常。

返回目录

5-2 替代方案

如果需要线程安全呢的 Map 实现类,无须使用 Hashtable 实现类,可以用 Collections 工具类把 HashMap 变成线程安全的。

返回目录


6 Properties 类
6-1 介绍

Properties 类是 Hashtable 类的子类,该对象在处理属性文件时特别方便。

返回目录


7 TreeMap 类
7-1 介绍

TreeMap 存储 k-v 对时,根据 key 对节点进行排序,TreeMap 可以保证所有的 k-v 对处于有序状态。

TreeMap 的 key 需要实现 Comparable 接口,或者创建 TreeMap 是传入比较器。

如果传入的 key 值相同,则更新 value 值。相同是指,比较器返回 0。

TreeMap 的 key 不允许为 null,会报空异常。value 允许为 null。

返回目录

7-2 底层结构

TreeMap 底层是树,树节点的类型是 Entry 类,这是 TreeMap 的内部类。

TreeMap 通过2种方式比较 key 的大小:

Comparable 接口,使用无参构造器创建 TreeMap 时,插入的 key 必须实现 Comparable 接口,并且所有的 key 应该是同一种数据类型。

Comparator 接口,创建 TreeMap 时,传入一个 Comparator 对象(可使用 lamda 表达式),则该对象负责对 key 的大小进行比较(优先于 Comparable 接口)。

public class TreeMap<K,V>...{
    ...
    private final Comparator<? super K> comparator;
    private transient Entry<K,V> root;

    public TreeMap() {
        comparator = null;
    }
    
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
    
    // 节点的类型,内部类
    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK;
		// 有参构造器
        Entry(K key, V value, Entry<K,V> parent) {...}
		// 获取键
        public K getKey() {...}
		// 获取值
        public V getValue() {...}
        // 设置值
        public V setValue(V value) {...}
        ...
    }
	...
}

返回目录

7-3 常用方法
public class TreeMap<K,V>...{
	// 1 构造器
    // 无参构造器,元素需要实现 Comparable 接口。
    public TreeMap() {...}
    // 有参构造器,传入比较器,使用比较器进行排序。
    public TreeMap(Comparator<? super K> comparator) {...}
    // 有参构造器,复制 Map 集合。
    public TreeMap(Map<? extends K, ? extends V> m) {...}
    // 有参构造器,复制 SortedMap 集合。
    public TreeMap(SortedMap<K, ? extends V> m) {...}
    
    // 2 作为 Map(详见 Map 接口的常用方法)
    // 添加一个 k-v 对。如果集合中相等的 key 已经存在,则更新 value 的值。
    V put(K key, V value);
    // 删除指定 Key 所对应的 k-v 对,返回对应的 value。如果相等的 key 不存在,则返回 null。
    V remove(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回 null。
    V get(Object key);
    // 返回指定 key 所对应的 value,如果集合中不存在相等的 key,则返回指定值 defaultValue。
    default V getOrDefault(Object key, V defaultValue) {...}
    
    // 3 作为树
    // 获取特定位置的 Entry
    // 返回 key 最小的 k-v 对,如果不存在,则返回 null。不删除。
    public Map.Entry<K,V> firstEntry() {...}
    // 返回 key 最大的 k-v 对,如果不存在,则返回 null。不删除。
    public Map.Entry<K,V> lastEntry() {...}
    // 返回 Map 中位于 key 前一位(小的在前)的 Entry,如果不存在,返回 null。不删除。
    //key 可以不在 Map 中)
    public Map.Entry<K,V> lowerEntry(K key) {...}
    // 返回 Map 中位于 key 后一位(小的在前)的 Entry,如果不存在,返回 null。不删除。
    //key 可以不在 Map 中
    public Map.Entry<K,V> higherEntry(K key) {...}
    // 返回并删除 key 最小的 k-v 对,如果不存在,则返回 null。
    public Map.Entry<K,V> pollFirstEntry() {...}
    // 返回并删除 key 最大的 k-v 对,如果不存在,则返回 null。
    public Map.Entry<K,V> pollLastEntry() {...}
    
    // 获取特定位置的 key
    // 返回最小的 key,如果不存在,则返回 null。不删除。
    public K firstKey() {...}
    // 返回最大的 key,如果不存在,则返回 null。不删除。
    public K lastKey() {...}
    // 返回 Map 中位于 key 前一位(小的在前)的 key,如果不存在,返回 null。不删除。
    // key 可以不在 Map 中
    public K lowerKey(K key) {...}
    // 返回 Map 中位于 key 后一位(小的在前)的 key,如果不存在,返回 null。不删除。
    // key 可以不在 Map 中
    public K higherKey(K key) {...}

    // 获取特定范围的子集
    // 获取子集,子集 key 的范围从 fromKey 到 toKey,是否包括取决于第二、四个参数
    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {...}
    // 获取子集,子集 key 的范围是小于 toKey,是否包括取决于第二个参数
    public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {...}
    // 获取子集,子集 key 的范围是大于 fromKey,是否包括取决于第二个参数
    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {...}
}

返回目录

7-4 代码示例
  • 根据 key 值排序
TreeMap<String, Integer> treeMap = new TreeMap<>((s1, s2) -> {
    return s1.length() - s2.length();
});
treeMap.put("abcde", 5);
treeMap.put("abc", 3);
treeMap.put("a", 1);
treeMap.put("ab", 2);
treeMap.put("abcd", 4);
for(Map.Entry<String, Integer> entry : treeMap.entrySet()){
    System.out.print("{" + entry.getKey() + " " + entry.getValue() + "} ");
}
// {a 1} {ab 2} {abc 3} {abcd 4} {abcde 5} 

返回目录


8 不同 Map 集合的使用场景

HashMap:允许键无序时使用。

LinkedHashMap:需要键的取出顺序和插入顺序一致时使用。

Hashtable:不推荐使用。

Properties:读取属性文件时使用。

TreeMap:需要对键进行排序时使用。

返回目录


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值