当前位置: 首页 > 知识库问答 >
问题:

Java-如何通过键获取存储在HashMap中的键对象(或条目)?

越雨泽
2023-03-14

我想为可用于查询地图的每个键获取“规范”键对象。看这里:

Map<UUID, String> map = new HashMap();
UUID a = new UUID("ABC...");
map.put(a, "Tu nejde o zamykání.");

UUID b = new UUID("ABC...");
String string = map.get(b); // This gives that string.

// This is what I am looking for:
UUID againA = map.getEntry(b).key();
boolean thisIsTrue = a == againA;

HashMap使用的是相同的多个唯一对象。所以我想从地图中获取实际的密钥,无论使用哪个对象来查询地图,它都将始终是相同的。

有没有办法从地图中获取实际的关键对象?我在界面上看不到任何东西,但可能是我忽略了一些聪明的技巧?

(迭代所有条目或键不算数。)

共有3个答案

袁谭三
2023-03-14

我认为有充分的理由需要实际的密钥。例如,为了节省内存。还要记住,实际关键点可能存储其他对象。例如,假设您有一个图的顶点。顶点可以存储实际数据(例如字符串)以及关联顶点。顶点哈希值只能依赖于数据。因此,要查找包含一些数据D的顶点,请查找包含数据D和无关联值的顶点。现在,如果可以返回贴图中的实际顶点,则可以获得顶点的实际关联。

在我看来,许多map实现都可以轻松地提供getEntry方法。例如,get的HashMap实现是:

  public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
  }

  final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
 }

可以使用getNode方法返回条目:

 public getEntry(Object key){
   Node<K,V> e = getNode(hash(key),key);
   if(e == null) return null;
   return new Entry<>(e.key,e.value);
 }
梁丘安晏
2023-03-14

有一种(相对)简单的方法可以做到这一点。我不时在需要时在我的应用程序中这样做...不是为了==测试,而是为了在存在数万个对象时减少存储的相同对象的数量,并相互交叉引用。这大大减少了我的内存使用,提高了性能...同时仍然使用equals()进行相等性测试。

只需维护一个用于插入密钥的平行映射。

Map<UUID, UUID> interned_keys = ...

UUID key = ...
if (interned_keys.contains(key))
    key = interned_keys.get(key)

当然,当被存储的对象知道自己的身份时,情况要好得多。然后你基本上可以免费得到实习机会。

class Item {
    UUID key;
    // ...
}

Map<UUID, Item> map = ...
map.put(item.key, item);

UUID key = ...
key = map.get(key).key;  // get interned key
牟星火
2023-03-14

有没有办法从地图中获取实际的关键对象

好的,我要对你的意思做一些假设。毕竟,你说过你的问题不需要澄清,所以我能看到的明显含义一定是正确的。对吗?:-)

答案是否定的,没有办法。

示例场景(不可编译!)

UUID uuid = UUID.fromString("xxxx-yyy-zzz");
UUID uuid2 = UUID.fromString("xxxx-yyy-zzz");  // same string
println(uuid == uuid2);  // prints false
println(uuid.equals(true));  // prints true

Map<UUID, String> map = new ...
map.put(uuid, "fred");
println(map.get(uuid)); // prints fred
println(map.get(uuid2)); // prints fred (because uuid.equals(uuid2) is true)

... 但是,除了迭代键集或条目集之外,API没有提供在映射中查找实际键的方法(在上面的示例中,它是uuid)。而且我还不知道有任何现有的映射类(标准或第三方)提供这种映射。

但是,您可以使用一个用于返回实际键对象的附加方法来实现自己的映射类。没有技术上的原因可以解释为什么您不能,尽管您将有更多的代码要编写、测试、维护等等。

但我要补充一点,我同意吉姆·加里森的观点。如果您有一个场景,其中有UUID对象(具有值相等语义),并且还希望实现标识相等语义,那么您的应用程序的设计可能有问题。正确的方法是更改UUID。fromString(…) 实现始终为相同的输入字符串返回相同的UUID对象。

这并不是说这种映射实现不存在。但如果是这样的话,如果你仔细看的话,你应该能够找到它。请注意,要求我们查找或推荐图书馆的问题是离题的

 类似资料:
  • 初学者问题:我有一个hashmap,它将整数数组存储为值。每个值的键是一个由两个整数(坐标)组成的对象。 我的问题是:如何根据对象中的两个坐标(我的“键”)从hashmap检索值? 我的协和类(在Eclipse的一点帮助下): 构建Hashmap: 如果我想访问坐标12,13上的数组,如何检索它?是否需要迭代(我希望不是,我想添加100000个坐标,当然要快速访问)。 我希望这能在某种程度上符合

  • 问题内容: 我正在尝试使用HashMap将唯一字符串映射到字符串ArrayList,如下所示: 基本上,我希望能够通过数字访问密钥,而不是使用密钥名称。我希望能够访问所述键的值,以对其进行迭代。我在想像这样的事情: 是否有捷径可寻? 问题答案: 您可以通过调用来遍历键,也可以通过调用来遍历项。遍历条目可能会更快。 如果要确保按插入键的顺序遍历键,请使用。 顺便说一句,我建议将地图的声明类型更改为。

  • 问题内容: 我有一个非常简单的JavaScript对象,用作关联数组。是否有一个简单的函数可以让我获取值的键,还是必须迭代该对象并手动找到它? 问题答案: 使用Underscore.js库:

  • 问题内容: 我从字符串定义一个新的gson对象: 此处的字符串示例:http : //api.soundrop.fm/spaces/XJTt3mXTOZpvgmOc 然后尝试返回一个值: 最后用: 但是我得到一个错误: 完整班:主班:http : //pastebin.com/v4LrZm6k 无线电班:http : //pastebin.com/2BWwb6eD 问题答案: 这是Java。字段根

  • 我正在做一个程序。我将用户存储在ArrayList中,所以我有一个UserCollection类作为用户的储存类别。但是鉴于UserCollection被认为是一个数据库,数据库中的每个用户条目都应该有一个唯一的id。最初我有一个userID作为User类中的字段,但现在我试图处理UserCollection中的id部分。如果我使用一个hashmap,其中键将是id,值是User我将如何继续迭代i

  • 问题内容: 如果我有,并且为其返回a ,那么如何获取相应的键?我是否必须遍历哈希图?最好的方法是什么? 问题答案: 如果你选择使用Commons Collections库而不是标准Java Collections API,则可以轻松实现此目的。 Collections库中的BidiMap接口是一个双向映射,使你可以将键映射到值(如法线映射),也可以将值映射到键,从而允许你在两个方向上执行查找。ge