2

谁能解释一下,为什么下一个代码没有编译?
我正在为它创建一个部分专业化的 Map 和 Map.Entry:

public class Trie<T> implements Map<String, T> {
    private class TrieEntry<S> implements Map.Entry<String, S> {
        // stupid implementation here
    }
    // uninterested code here
}

这里一切正常,但是我正在实现 entrySet() 方法:

public Set<java.util.Map.Entry<String, T>> entrySet() {
    Set<java.util.Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();
    // some uninterested code here
}

日食 说

“类型不匹配:无法转换HashSet<Trie<T>.TrieEntry<T>>Set<Map.Entry<String,T>>

所以,在我的脑海里TrieEntry<T>应该展开Map.Entry<String, T>并符合定义中的表达。

我哪里错了?

4

2 回答 2

5

你是对的, aTrieEntry<T>是 a Map.Entry<String, T>。AHashSet<TrieEntry<T>>也是 a Set<TrieEntry<T>>,但它不是a Set<Map.Entry<String, T>>

如果是你可以这样做:

Set<TrieEntry<T>> trieSet = ...;
Set<Map.Entry<String, T>> mapSet = trieSet;
mapSet.add(mapEntry);

所以现在 trieSet 现在将包含一个Map.Entry<String, T>! 这会破坏泛型。

那么如何解决这个特殊问题呢?简单 - 使用有界通配符:

Set<? extends Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();

你可以读? extends Map.Entry<String, T>作“任何至少是一个Map.Entry<String, T>”。


好的,现在到您的实施问题。我实际上相信,由于方法 entrySet() 的当前定义,这是无法以这种方式解决的。应该返回? extends Map.Entry<String, T>,但它确实返回Map.Entry<String, T>

实际上有一个关于这个问题的错误报告(或功能请求)。查看提交日期和优先级,不能指望很快修复。

所以你有两个选择:

  1. 放弃您的TrieEntry课程并尝试使用Map.Entry,将信息存储在您的键和/或值中。

  2. 放下Map接口,让您的自定义entrySet方法返回? extends Map.Entry<String, T>

这两种解决方案可能都不理想,可能还有更好的解决方案,但这是我目前能告诉你的全部。

于 2012-04-08T21:04:52.540 回答
4

HashSet当然实现了Set,但HashSet<some subclass of X>不是Set<X>. 你可以这样做:

Set<? extends Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();

但我怀疑你稍后会在你的entrySet方法中遇到麻烦(你不能从方法中返回它,因为它仍然需要你返回 a Set<Map.Entry<String, T>>)。

另一种解决方案是这样做:

Set<Map.Entry<String, T>> x = new HashSet<Map.Entry<String, T>>();

您可以向其中添加TrieEntry<T>对象Set,也可以从entrySet().

我认为您还可以TrieEntry通过省略类型参数S并仅使用T封闭类中的来简化您的内部类:

class Trie<T> implements Map<String, T> {
    private class TrieEntry extends Map.Entry<String, T> {
        // ...

        @Override
        public T getValue() {
            // ...
        }
    }

    // ...
}
于 2012-04-08T21:02:29.353 回答