JAVA集合框架之Map接口实现类

简介:

java.util.HashMap<K,V>

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。
如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使用足够大的初始容量创建它将使得映射关系能更有效地存储。

构造方法

方法名 说明
HashMap() 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap
HashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap
HashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空 HashMap
HashMap(Map<? extends K, ? extends V> m) 构造一个映射关系与指定 Map 相同的新 HashMap

方法摘要

返回值 方法名 说明
void clear() 从此映射中移除所有映射关系
Object clone() 返回此 HashMap 实例的浅表副本:并不复制键和值本身
boolean containsKey(Object key) 如果此映射包含对于指定键的映射关系,则返回 true
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true
Set<Map.Entry<K,V>> entrySet() 返回此映射所包含的映射关系的 Set 视图
V get(Object key) 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null
boolean isEmpty() 如果此映射不包含键-值映射关系,则返回 true
Set<K> keySet() 返回此映射中所包含的键的 Set 视图
V put(K key, V value) 在此映射中关联指定值与指定键
void putAll(Map<? extends K,? extends V> m) 将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系
V remove(Object key) 从此映射中移除指定键的映射关系(如果存在)
int size() 返回此映射中的键-值映射关系数
Collection<V> values() 返回此映射所包含的值的 Collection 视图

使用示例

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

public class HashMapDemo
{
   public static void main(String[] args)
   {
      HashMap<String, String> map = new HashMap<String, String>();
      // 向集合中添加数据
      for (int i = 0; i < 10; i++)
      {
         map.put("key" + i, "value" + i);
      }
      // 判断是否包含指定键
      System.out.println(map.containsKey("key1"));
      // 集合中元素个数
      System.out.println(map.size());
      // 遍历集合,使用keySet
      Iterator<String> iterator1 = map.keySet().iterator();
      while (iterator1.hasNext())
      {
         String key = iterator1.next();
         System.out.println(key + "=" + map.get(key));
      }
      System.out.println("==============================================");
      // 遍历集合,使用entrySet
      Iterator<Entry<String, String>> iterator2 = map.entrySet().iterator();
      while (iterator2.hasNext())
      {
         Entry<String, String> entry = iterator2.next();
         System.out.println(entry.getKey() + "=" + entry.getValue());
      }
   }
}
AI 代码解读

由上面例子的运行结果我们可以看出,遍历HashMap中的元素时顺序不是恒定不变的。

java.util.Hashtable<K,V>

Hashtable实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。
Hashtable与HashMap的区别主要有以下几点:

  1. Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
  2. Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:Map Collections.synchronizedMap(Map m)这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。
  3. 在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

构造方法

方法名 说明
Hashtable() 用默认的初始容量 (11) 和加载因子 (0.75) 构造一个新的空哈希表
Hashtable(int initialCapacity) 用指定初始容量和默认的加载因子 (0.75) 构造一个新的空哈希表
Hashtable(int initialCapacity, float loadFactor) 用指定初始容量和指定加载因子构造一个新的空哈希表
Hashtable(Map<? extends K, ? extends V> t) 构造一个与给定的 Map 具有相同映射关系的新哈希表

方法摘要

返回值 方法名 说明
void clear() 将此哈希表清空,使其不包含任何键。
Object clone() 创建此哈希表的浅表副本。
boolean contains(Object value) 测试此映射表中是否存在与指定值关联的键。
boolean containsKey(Object key) 测试指定对象是否为此哈希表中的键。
boolean containsValue(Object value) 如果此 Hashtable 将一个或多个键映射到此值,则返回 true。
Enumeration<V> elements() 返回此哈希表中的值的枚举。
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的键的 Set 视图。
boolean equals(Object o) 按照 Map 接口的定义,比较指定 Object 与此 Map 是否相等。
V get(Object key) 返回指定键所映射到的值,如果此映射不包含此键的映射,则返回 null. 更确切地讲,如果此映射包含满足 (key.equals(k)) 的从键 k 到值 v 的映射,则此方法返回 v;否则,返回 null。
int hashCode() 按照 Map 接口的定义,返回此 Map 的哈希码值。
boolean isEmpty() 测试此哈希表是否没有键映射到值。
Enumeration<K> keys() 返回此哈希表中的键的枚举。
Set<K> keySet() 返回此映射中包含的键的 Set 视图。
V put(K key, V value) 将指定 key 映射到此哈希表中的指定 value。
void putAll(Map<? extends K,? extends V> t) 将指定映射的所有映射关系复制到此哈希表中,这些映射关系将替换此哈希表拥有的、针对当前指定映射中所有键的所有映射关系。
protected void rehash() 增加此哈希表的容量并在内部对其进行重组,以便更有效地容纳和访问其元素。
V remove(Object key) 从哈希表中移除该键及其相应的值。
int size() 返回此哈希表中的键的数量。
String toString() 返回此 Hashtable 对象的字符串表示形式,其形式为 ASCII 字符 “, ” (逗号加空格)分隔开的、括在括号中的一组条目。
Collection<V> values() 返回此映射中包含的键的 Collection 视图

使用示例

Hashtable与HashMap使用方式类似,这里就不写例子了。

java.util.LinkedHashMap<K,V>

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入键,则插入顺序不受影响。(如果在调用 m.put(k, v) 前 m.containsKey(k) 返回了 true,则调用时会将键 k 重新插入到映射 m 中。)
此实现可以让客户避免未指定的、由 HashMap(及 Hashtable)所提供的通常为杂乱无章的排序工作,同时无需增加与 TreeMap 相关的成本。

构造方法

方法名 说明
LinkedHashMap() 构造一个带默认初始容量 (16) 和加载因子 (0.75) 的空插入顺序LinkedHashMap 实例
LinkedHashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子 (0.75) 的空插入顺序LinkedHashMap 实例
LinkedHashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空插入顺序 LinkedHashMap 实例
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 构造一个带指定初始容量、加载因子和排序模式的空 LinkedHashMap 实例
LinkedHashMap(Map<<? extends K, ? extends V> m) 构造一个映射关系与指定映射相同的插入顺序 LinkedHashMap 实例

方法摘要

返回值 方法名 说明
void clear() 从该映射中移除所有映射关系
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true
V get(Object key) 返回此映射到指定键的值
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) 如果此映射移除其最旧的条目,则返回 true

使用示例

LinkedHashMap继承自HashMap,所以LinkedHashMap具有HashMap的所有功能,可直接将HashMap例子中的类名替换为LinkedHashMap,运行后注意观察遍历集合的结果,这也是LinkedHashMap与HashMap最大的不同。遍历LinkedHashMap中的元素时,元素顺序与元素添加顺序相同。

java.util.TreeMap<K,V>

基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

构造方法

方法名 说明
TreeMap() 使用键的自然顺序构造一个新的、空的树映射
TreeMap(Comparator<? super K> comparator) 构造一个新的、空的树映射,该映射根据给定比较器进行排序
TreeMap(Map<? extends K,? extends V> m) 构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序
TreeMap(SortedMap<K,? extends V> m) 构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射

方法摘要

返回值 方法名 说明
Map.Entry<K,V> ceilingEntry(K key) 返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null
K ceilingKey(K key) 返回大于等于给定键的最小键;如果不存在这样的键,则返回 null
void clear() 从此映射中移除所有映射关系
Object clone() 返回此 TreeMap 实例的浅表副本
Comparator<? super K> comparator() 返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回 null
boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true
boolean containsValue(Object value) 如果此映射为指定值映射一个或多个键,则返回 true
NavigableSet<K> descendingKeySet() 返回此映射中所包含键的逆序 NavigableSet 视图
NavigableMap<K,V> descendingMap() 返回此映射中所包含映射关系的逆序视图
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图
Map.Entry<K,V> firstEntry() 返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null
K firstKey() 返回此映射中当前第一个(最低)键
Map.Entry<K,V> floorEntry(K key) 返回一个键-值映射关系,它与小于等于给定键的最大键关联;如果不存在这样的键,则返回 null
K floorKey(K key) 返回小于等于给定键的最大键;如果不存在这样的键,则返回 null
V get(Object key) 返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null
SortedMap<K,V> headMap(K toKey) 返回此映射的部分视图,其键值严格小于 toKey
NavigableMap<K,V> headMap(K toKey, boolean inclusive) 返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey
Map.Entry<K,V> higherEntry(K key) 返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null
K higherKey(K key) 返回严格大于给定键的最小键;如果不存在这样的键,则返回 null
Set<K> keySet() 返回此映射包含的键的 Set 视图
Map.Entry<K,V> lastEntry() 返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null
K lastKey() 返回映射中当前最后一个(最高)键
Map.Entry<K,V> lowerEntry(K key) 返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null
K lowerKey(K key) 返回严格小于给定键的最大键;如果不存在这样的键,则返回 null
NavigableSet<K> navigableKeySet() 返回此映射中所包含键的 NavigableSet 视图
Map.Entry<K,V> pollFirstEntry() 移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null
Map.Entry<K,V> pollLastEntry() 移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null
V put(K key, V value) 将指定值与此映射中的指定键进行关联
void putAll(Map<? extends K,? extends V> map) 将指定映射中的所有映射关系复制到此映射中
V remove(Object key) 如果此 TreeMap 中存在该键的映射关系,则将其删除
int size() 返回此映射中的键-值映射关系数
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) 返回此映射的部分视图,其键的范围从 fromKey 到 toKey
SortedMap<K,V> subMap(K fromKey, K toKey) 返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)
SortedMap<K,V> tailMap(K fromKey) 返回此映射的部分视图,其键大于等于 fromKey
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) 返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey
Collection<V> values() 返回此映射包含的值的 Collection 视图

使用示例

TreeMap与HashMap的用法也基本相同,不同之处也是元素的顺序。

java.util.Properties

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
一个属性列表可包含另一个属性列表作为它的“默认值”;如果未能在原有的属性列表中搜索到属性键,则搜索第二个属性列表。
因为 Properties 继承于 Hashtable,所以可对 Properties 对象应用 put 和 putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。相反,应该使用 setProperty 方法。如果在“不安全”的 Properties 对象(即包含非 String 的键或值)上调用 store 或 save 方法,则该调用将失败。类似地,如果在“不安全”的 Properties 对象(即包含非 String 的键)上调用propertyNames 或 list 方法,则该调用将失败。

构造方法

方法名 说明
Properties() 创建一个无默认值的空属性列表
Properties(Properties defaults) 创建一个带有指定默认值的空属性列表

方法摘要

返回值 方法名 说明
String getProperty(String key) 用指定的键在此属性列表中搜索属性
String getProperty(String key, String defaultValue) 用指定的键在属性列表中搜索属性
void list(PrintStream out) 将属性列表输出到指定的输出流
void list(PrintWriter out) 将属性列表输出到指定的输出流
void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)
void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
void loadFromXML(InputStream in) 将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中
Enumeration<?> propertyNames() 返回属性列表中所有键的枚举,如果在主属性列表中未找到同名的键,则包括默认属性列表中不同的键
void save(OutputStream out, String comments) 已过时如果在保存属性列表时发生 I/O 错误,则此方法不抛出 IOException保存属性列表的首选方法是通过 store(OutputStream out, String comments) 方法或 storeToXML(OutputStream os, String comment) 方法来进行
Object setProperty(String key, String value) 调用 Hashtable 的方法 put
void store(OutputStream out, String comments) 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流
void store(Writer writer, String comments) 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符
void storeToXML(OutputStream os, String comment) 发出一个表示此表中包含的所有属性的 XML 文档
void storeToXML(OutputStream os, String comment, String encoding) 使用指定的编码发出一个表示此表中包含的所有属性的 XML 文档
Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键

使用示例

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo
{
   public static void main(String[] args)
   {
      Properties properties = new Properties();
      // 向集合中添加数据
      for (int i = 0; i < 10; i++)
      {
         properties.setProperty("key" + i, "value" + i);
      }
      // 将集合持久化到资源文件中,对应的读取使用load方法
      FileOutputStream out = null;
      try
      {
         out = new FileOutputStream("PropertiesDemo.properties");
         properties.store(out, "PropertiesDemo");
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
      finally
      {
         if (out != null)
         {
            try
            {
               out.close();
            }
            catch (IOException e)
            {
            }
         }
      }
   }
}
AI 代码解读

打开持久化文件的查看内容(文本)如下:
#PropertiesDemo
#Tue Dec 29 09:44:52 CST 2015
key9=value9
key8=value8
key7=value7
key6=value6
key5=value5
key4=value4
key3=value3
key2=value2
key1=value1
key0=value0

上述例子中,只介绍了如何将Properties持久化到properties文件中,Properties还可以直接持久化到XML中,大家可以自己试一下。

目录
打赏
0
0
0
0
33
分享
相关文章
|
30天前
|
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
57 0
Java 类和对象
本文介绍了Java编程中类和对象的基础知识,作为面向对象编程(OOP)的核心概念。类是对象的蓝图,定义实体类型;对象是具体实例,包含状态和行为。通过示例展示了如何创建表示汽车的类及其实例,并说明了构造函数、字段和方法的作用。同时,文章还探讨了访问修饰符的使用,强调封装的重要性,如通过getter和setter控制字段访问。最后总结了类与对象的关系及其在Java中的应用,并建议进一步学习继承等概念。
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
46 5
|
7天前
|
java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
19 0
|
30天前
|
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
45 1
|
28天前
|
java常见的集合类有哪些
Map接口和Collection接口是所有集合框架的父接口: 1. Collection接口的子接口包括:Set接口和List接口 2. Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及 Properties等 3. Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等 4. List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
|
28天前
使用 entrySet 遍历 Map 类集合 KV
使用 entrySet 遍历 Map 类集合 KV
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等