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

Java-如何通过键获取存储在HashMap中的键对象(或项)?,java,dictionary,key,Java,Dictionary,Key,我想为每个可用于查询映射的键获取“规范”键对象。请看这里: 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 loo

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

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;
Map Map=newhashmap();
UUID a=新的UUID(“ABC…”);
放在地图上(a,“Tu nejde o zamykání”);
UUID b=新的UUID(“ABC…”);
String String=map.get(b);//这就是那根弦。
//这就是我想要的:
UUID againA=map.getEntry(b.key();
布尔thisIsTrue=a==againA;
HashMap
使用
equals()
,这对于多个唯一对象是相同的。所以我想从地图中获取实际的密钥,无论使用什么对象来查询地图,它都是相同的

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


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

这可能会有所帮助。您可以为下面的每一项使用一个

Map<String,Object> map = new HashMap<>();
        map.put("hello1", new String("Hello"));
        map.put("hello2", new String("World"));
        map.put("hello3", new String("How"));
        map.put("hello4", new String("Are u"));

        for(Map.Entry<String,Object> e: map.entrySet()){
             System.out.println(e.getKey());
        }
Map Map=newhashmap();
map.put(“hello1”,新字符串(“Hello”);
地图放置(“hello2”,新字符串(“世界”);
map.put(“hello3”,新字符串(“How”);
map.put(“hello4”,新字符串(“areu”);
对于(Map.Entry e:Map.entrySet()){
System.out.println(e.getKey());
}
有没有办法从地图中获取实际的关键对象

好的,我将对你的意思做一些假设。毕竟,你说过你的问题不需要澄清,所以我能理解的明显含义必须是正确的。对吧?:-)

答案是否定的,没有办法

示例场景(不可编译!)

UUID-UUID=UUID.fromString(“xxxx-yyy-zzz”);
UUID uuid2=UUID.fromString(“xxxx yyy zzz”);//一串
println(uuid==uuid2);//打印错误
println(uuid.equals(true));//打印正确
地图=新的。。。
地图放置(uuid,“fred”);
println(map.get(uuid));//印刷品弗雷德
println(map.get(uuid2));//打印fred(因为uuid.equals(uuid2)为true)
。。。但是,
Map
API除了迭代密钥或条目集之外,没有提供在
Map
中查找实际密钥的方法(在上面的示例中,它是
uuid
)。我还不知道有任何现有的
Map
类(标准或第三方)提供此功能1

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


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


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

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

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

Map<UUID, UUID> interned_keys = ...

UUID key = ...
if (interned_keys.contains(key))
    key = interned_keys.get(key)
Map interned\u key=。。。
UUID键=。。。
if(内部密钥包含(密钥))
密钥=实习密钥。获取(密钥)
当然,当被存储的对象知道它自己的身份是什么时,情况要好得多。然后你基本上可以免费得到实习机会

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

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

UUID key = ...
key = map.get(key).key;  // get interned key
类项目{
UUID密钥;
// ...
}
地图=。。。
地图放置(item.key,item);
UUID键=。。。
key=map.get(key).key;//实习钥匙

我认为需要实际密钥是有充分理由的。例如,为了节省内存。还要记住,实际关键点可能存储其他对象。例如,假设你有一个图的顶点。顶点可以存储实际数据(例如字符串)以及事件顶点。顶点散列值只能依赖于数据。所以要查找带有一些数据的顶点, 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;
 }
public V get(对象键){
节点e;
返回(e=getNode(散列(键),键))==null?null:e.value;
}
最终节点getNode(int散列,对象键){
节点[]选项卡;节点第一,e;int n;K;
如果((tab=table)!=null&(n=tab.length)>0&&
(first=tab[(n-1)&散列]!=null){
如果(first.hash==hash&&//始终检查第一个节点
((k=first.key)==key | |(key!=null&&key.equals(k)))
先返回;
if((e=first.next)!=null){
if(树节点的第一个实例)
return((TreeNode)first).getTreeNode(hash,key);
做{
如果(e.hash==hash&&
((k=e.key)==key | |(key!=null&&key.equals(k)))
返回e;
}而((e=e.next)!=null);
}
}
返回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);
 }
publicGetEntry(对象键){
Node e=getNode(散列(key),key);
如果(e==null)返回null;
返回新条目(e.key,e.value);
}
 public getEntry(Object key){
   Node<K,V> e = getNode(hash(key),key);
   if(e == null) return null;
   return new Entry<>(e.key,e.value);
 }