在 Java 中向 HashMap 添加空键或值有啥用?
Posted
技术标签:
【中文标题】在 Java 中向 HashMap 添加空键或值有啥用?【英文标题】:What is the use of adding a null key or value to a HashMap in Java?在 Java 中向 HashMap 添加空键或值有什么用? 【发布时间】:2011-02-26 01:58:04 【问题描述】:HashMap 允许一个空键和任意数量的空值。它有什么用?
【问题讨论】:
“也许问题不在于没有什么在困扰我们,而是我们正在困扰它。” 在 Guava、google 集合中,许多类不允许 null 其背后的原因是 95% 的情况不需要 null 并且它们可以表示错误,可能很难找到。 奇怪的是,ConcurrentHashMap
不支持空键,而 HashMap
支持。
只有 HashMap 允许 null :)
【参考方案1】:
我不确定您要问什么,但是如果您正在寻找一个何时想要使用空键的示例,我经常在地图中使用它们来表示默认情况(即如果给定的键不存在,则应使用):
Map<A, B> foo;
A search;
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);
HashMap
专门处理空键(因为它不能在空对象上调用 .hashCode()
),但空值并没有什么特别之处,它们像其他任何东西一样存储在映射中
【讨论】:
那么如果 .hashCode() 在 null 上是不可能的,那么谁来决定 null 键将进入哪个托架? @Pacerier 在HashMap
(putForNullKey
) 中有一个特殊的方法可以处理它;它将它存储在表 0 中
@MichaelMrozek 你的最后一行B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);
我想我们可以简单地在搜索键上调用 get 方法,它会得到相同的结果。 B val = foo.get(search);
如果我有什么不对的地方请纠正我吗?
@dheeraj92 如果密钥不存在,您的代码会将val
设置为null
;我的将其设置为 null
映射到地图中的任何内容。这就是重点,我在地图中的 null
键处存储了一个默认的非空值,如果实际键不存在则使用它【参考方案2】:
一个例子是为树建模。如果您使用 HashMap 表示树结构,其中键是父节点,值是子节点列表,则 null
键的值将是根节点。
【讨论】:
【参考方案3】:null
的一个使用示例值 是使用 HashMap
作为可能返回 @ 的昂贵操作(例如调用外部 Web 服务)结果的缓存时987654323@.
将null
值放入映射中,然后您可以区分未对给定键执行操作(cache.containsKey(someKey)
返回false
)和已执行操作但返回的情况null
值(cache.containsKey(someKey)
返回 true
,cache.get(someKey)
返回 null
)。
如果没有 null
值,您将不得不在缓存中放入一些特殊值来指示 null
响应,或者根本不缓存该响应并每次都执行操作。
【讨论】:
【参考方案4】:到目前为止的答案只考虑拥有null
密钥的价值,但问题还涉及any number of null values
。
将值 null
存储在 HashMap 中的键的好处与在数据库等中相同 - 您可以记录具有空值(例如字符串“”)和不具有值(null)。
【讨论】:
【参考方案5】:这是我唯一有点做作的例子,说明null
键可能有用:
public class Timer
private static final Logger LOG = Logger.getLogger(Timer.class);
private static final Map<String, Long> START_TIMES = new HashMap<String, Long>();
public static synchronized void start()
long now = System.currentTimeMillis();
if (START_TIMES.containsKey(null))
LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms");
START_TIMES.put(null, now);
public static synchronized long stop()
if (! START_TIMES.containsKey(null))
return 0;
return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis());
public static synchronized void start(String name)
long now = System.currentTimeMillis();
if (START_TIMES.containsKey(name))
LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms");
START_TIMES.put(name, now);
public static synchronized long stop(String name)
if (! START_TIMES.containsKey(name))
return 0;
return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis());
private static long printTimer(String name, long start, long end)
LOG.info(name + " timer ran for " + (end - start) + "ms");
return end - start;
【讨论】:
如果你试图停止一个不存在的计时器,或者一个已经停止的计时器,那应该是一个错误,而不是被忽略。 @QPaysTaxes - 取决于您的意图。如果您想要一个易于使用的轻量级实用程序,您通常不想要throw Exception
左右。此外,尝试停止不存在或已经停止的计时器并不是调用者通常可以从中恢复的东西。【参考方案6】:
另一个例子:我用它来按日期对数据进行分组。 但有些数据没有日期。我可以将它与标题“NoDate”分组
【讨论】:
【参考方案7】:当映射存储 UI 选择的数据时,空键也很有用,其中映射键表示 bean 字段。
例如,相应的空字段值将在 UI 选择中表示为“(请选择)”。
【讨论】:
以上是关于在 Java 中向 HashMap 添加空键或值有啥用?的主要内容,如果未能解决你的问题,请参考以下文章