Java 在映射中将NULL用作键值

Java 在映射中将NULL用作键值,java,coding-style,map,null,key,Java,Coding Style,Map,Null,Key,我想知道在Map对象中使用NULL作为键是否被认为是好的样式,如果不是,还有什么替代方法?这通常被认为是不好的样式。 由于NULL通常表示未确定或未设置的值,因此将其用作映射的键通常会造成混淆。(尽管,在某些特定情况下,这是有意义的) 备选方案取决于具体情况,因此让我举一个例子。假设我们希望文本中包含特定于颜色的字符串,并且我们还希望文本的默认颜色与任何字符串都不匹配 private HashMap<String,Color> stringColors; private Color

我想知道在
Map
对象中使用
NULL
作为键是否被认为是好的样式,如果不是,还有什么替代方法?

这通常被认为是不好的样式。

由于
NULL
通常表示未确定或未设置的值,因此将其用作映射的键通常会造成混淆。(尽管,在某些特定情况下,这是有意义的)

备选方案取决于具体情况,因此让我举一个例子。假设我们希望文本中包含特定于颜色的字符串,并且我们还希望文本的默认颜色与任何字符串都不匹配

private HashMap<String,Color> stringColors;
private Color defaultColor;
私有HashMap stringColors;
私人色彩;
不要使用
NULL
键将默认颜色存储在
HashMap
中,而是将默认颜色放在特定变量中。这使任何查看代码的人都清楚地知道这种颜色的确切含义


我想说的是,驱动因素是,你是否真的在某个地方有一个
NULL
值,可以直接在地图上查找。(根据我的经验,这种情况并不经常发生)在我给出的这个特定示例中,默认颜色将用于地图中不存在的任何字符串。在这种情况下,没有您想要的颜色的
NULL
字符串。

我个人建议使用NULL对象(请参阅)或某种默认键,而不是
NULL
作为键。使用
null
总是意味着您必须编写代码来防御
NullPointerException
,并且应尽可能避免使用

编辑 例如,如果您正在创建一个允许用户向映射添加值的API(无论是自制的
map
实现,还是使用映射存储其数据的实用程序类),并且您的第一个版本允许用户使用
null
作为键,那么您必须始终支持
null
键。因此,您的备份
Map
必须是一个接受
null
密钥的实现,或者您必须捕获密钥,并用表示
null
密钥的不同密钥替换它们


正如@Erick Robertson提到的,有些情况下接受
null
键是有意义的。然而,如果您正在设计一个API,您应该确实确保您想要处理这样的键,因为这总是意味着需要检查更多的代码来检查
null
。它还意味着为API的客户端提供更多的防御性代码。

有时,将默认值存储在map中作为
Null
键的值是很有用的。我不知道还有其他情况。但是它是合法的,所以如果它可以获利,为什么不应该呢?

考虑使用类似于a的东西,如果映射不包含给定的键,它将返回一个已知值


根据您的用例,它可能比使用(a)一个
null
键或(b)一个null对象更干净。如果您描述您的实际用例,可能会更容易提供帮助。

一般来说,空键和空值都是糟糕的样式

Google Guava站点有两个很棒的页面,解释了不使用Null的方法和原因

引述:

但万一呢?

如果你发现自己想要把一个空元素放到这些空元素敌对的野兽中呢

  • 如果在集合中或作为地图中的键,请不要;如果在查找操作期间显式地使用特殊情况null,则更为清晰(不那么令人惊讶)
  • 如果将其作为映射中的一个值--请省略该条目;保留一组单独的非空键(或空键)
  • 如果在一个列表中--如果列表是稀疏的,你会更愿意使用地图吗
  • 考虑是否存在可以使用的自然“空对象”。并不总是这样。但是有时候。 示例:如果它是一个枚举,则添加一个常量来表示您希望null在此处表示的任何内容
  • 只需使用不同的集合实现,例如Collections.unmodifiableList(Lists.newArrayList())而不是ImmutableList
  • 屏蔽空值(这需要更多细节)
  • 使用

空值通常被视为未初始化的值。为什么要将它放在映射中?在什么上下文中,您需要null键?默认值?将Null对象()存储为Null键的值可以减少Null检查的次数。