【问题标题】:How to retrieve a collection of values from a HashMap如何从 HashMap 中检索值的集合
【发布时间】:2012-05-14 17:17:26
【问题描述】:

我正在编写一个函数来测试 HashMap 是否具有空值。方法 .values() 应该只返回一个值的集合,但是我收到一个包含存储在里面的键和值的映射。这不好,因为我的函数的目的是检查值是否为空,但是如果我返回一个带有键和值的映射,那么如果我有一个没有值存储的键,则 .values().isEmpty() 将返回 false。

  public Map<KEY, List<VALUES>> methodName() {
    if (MAPNAME.values().isEmpty()) {
            throw new CustomErrorException(ExceptionHandler.getErrorWithDescription(ErrorConstants.ERROR_MSG_01));
        } else {
            return MAPNAME;
        }
    }

在上面的例子中,.values() 总是返回一个包含所有键和值的映射。如果 HashMap 有键,我的方法永远不会抛出 CustomErrorException,这很糟糕,因为它应该检测是否没有值。救命!

【问题讨论】:

  • @jahroy Map> MAPNAME = new HashMap>();
  • HashMaps 允许空值和单个空键。

标签: java list map hashmap


【解决方案1】:

没有像 Map 实现这样的东西,它存储了一个没有值的键。所有 Map 实现:

  • put 为 null 时抛出异常
  • 添加一个键和值为 null 的条目

映射到 null 的键与没有值的键非常不同。键有一个值,该值为 null(这意味着值集合不会为空,除非地图为空)。没有值的键是映射中不包含的键。

长话短说,您可能想使用MAPNAME.values().contains(null) 甚至只是MAPNAME.containsValue(null) 来做您想做的事。或者,如果您要检查 每个 键是否映射为 null,请通过迭代 .values() 集合来检查。

【讨论】:

  • 感谢您为我理清了地图的概念。使用 MAPNAME.values().contains(null) 非常适合我的目的。最后一件事 - .values() 到底应该做什么?就我而言,它返回了整个哈希映射、键和值。我只是想要一组值来执行逻辑。
  • 抱歉,您在这方面弄错了。 HashMap.values() 绝对不会返回 HashMap。由于 HashMap 和 Map 没有实现 Collection,如果 HashMap 从 values() 返回自身,它甚至不会编译。 values() 方法返回一个集合,其中包含一个键引用的每个值。可能有重复(不是集合),所以如果 3 个键映射到 null,那么 null 将在 Collection 中出现 3 次。此外,从 values Collection 中删除一个值也会更新地图。
  • 在 Eclipse 中,如果我在调试器中遍历我的代码并检查 HashMap 中包含的“值”,它会显示“this”。如果我展开 'this',它包含整个 HashMap,包括键和值(值导致另一个 'this',导致一系列无限的 HashMaps 包含在彼此中)。只是说'
  • 不一样。这意味着 values() 返回的类包含对原始 HashMap 的引用,而不是它原始 HashMap。造成这种情况的可能原因是 HashMap 返回的 values() 集合是 HashMap 的内部类。
【解决方案2】:

您返回的是地图——MAPNAME,而不是值:

return MAPNAME.values();

【讨论】:

  • 是的,你是对的 - 我正在返回 HashMap。我的问题是,如果 HashMap 中有键,我的 if 语句将永远不会抛出错误异常,这是行不通的,因为理论上存在 HashMap 将存储键但没有值的场景。该方法的目标不是简单地返回 HashMap 的值,而是如果值不为空/null,则返回整个 HashMap。
【解决方案3】:

如果您尝试确定地图是否包含任何空值,则应遍历值集合并检查每个值是否为空。

包含具有 null 值的条目的映射不为空。

【讨论】:

  • 问题是 MAPNAME.values() 返回一个哈希映射,尽管文档和几个示例表明它应该返回一个集合。实际上,它说'values'的值是'this',也就是哈希映射'values'存储在里面。
  • 然后更具体地说,我需要的是 MAPNAME.values() 只返回一个值的集合,其中没有存储任何键。目前情况并非如此,因为 MAPNAME.values() 返回一个包含所有键和所有值的映射。这不是 .values() 应该工作的方式吗?
  • 怎么可能有没有价值的键呢? “只有没有存储在里面的键的值”是什么意思? Map 的每个元素都包含一个映射到一个值的键。每个键都必须有一个值,每个值都必须有一个关联的键。一些地图可以包含空键和空值。其他人不能。
【解决方案4】:

您并不是很清楚自己想要什么——您的映射值是列表——考虑到这一点,有三种方法可以将键映射到“无值”:

  • 一个映射到null的键(那么测试是map.values().contains(null)
  • 一个键映射到一个空列表(那么测试是map.values().contains(Collections.emptyList())
  • 映射到一个包含nulls 的列表的键。

您上面的方法现在正在做的事情是,如果地图确实为空(没有键)则抛出异常,否则返回地图。

不清楚你想要什么。如果您希望该方法仅在映射没有有意义的值时引发异常(所有键都映射到 null 或空列表),那么您需要这样的东西:

public Map<KEY, List<VALUES>> methodName() {
    for( List<VALUES> values : MAPNAME.values() ) // 1
        if( null != values ) // 2
            for( VALUES value : values ) // 3
                if( null != value ) // 4
                    return MAPNAME;

    throw new CustomErrorException(ExceptionHandler.getErrorWithDescription(ErrorConstants.ERROR_MSG_01));
}

这会在所有合理想象的“空映射”场景中引发异常——如果 (1) 映射确实为空,或者 (2) 它只包含 null 键,或者 (3) 它只包含 @ 987654327@ 值或空列表,或 (4) 它仅包含 null 值或空列表或 nulls 的列表。

(上面文本中的“空性”测试级别对应于代码中的注释标签)。

【讨论】:

    【解决方案5】:

    以这种方式使用 values() 方法:- 集合 set=MAPNAME.values();

    然后使用foreach循环检查每个值是否为空。

    【讨论】:

    • *集合 set=MAPNAME.values();
    • 哦,是的!完全忘记了。谢谢!
    猜你喜欢
    • 2017-06-06
    • 2016-12-30
    • 1970-01-01
    • 2021-07-06
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 2019-01-31
    相关资源
    最近更新 更多