如何为 Map 实现创建自定义迭代器?

发布于 2024-11-18 03:46:27 字数 1294 浏览 2 评论 0原文

我实现了一个独特的地图。它是一个双向的哈希图,其中不仅键是唯一的,而且值也是唯一的。

public interface UniqueMap<K,V>{

    V uniquePut(K key, V value);

    UniqueMap<V,K> inverse(); 
}

这是一个可能的实现:

public class SimpleUniqueMap<K,V> implements UniqueMap<K,V>, Iterable<K>{

    public HashMap<K,V> uniqueMap = new HashMap<K,V>();

    class EnumSimpleUniqueMap implements Iterator<K>{

        int count = uniqueMap.size();

        public boolean hasNext(){
            return count > 0;
        }

        public K next(){
            if(count == 0){
                throw new NoSuchElementException();     
            }else{
                count--;
                //...
            }
        }

        public void remove(){
            throw new UnsupportedOperationException();
        }
    }

    public Iterator<V> iterator(){
        return new EnumSimpleUniqueMap();
    }

    public V uniquePut(K key, V value){ 
        return null;
    }

    public UniqueMap<V,K> inverse(){
        return null;
    }
}

如您所见,我已经尝试为我的独特映射实现迭代器。但从哈希图中,值不是通过位置而是通过键来访问的。所以通常我会获取计数器并访问值,但在这种情况下这是不可能的。

实际上,迭代这些键并逐个检索它们就足够了。我怎样才能做到这一点?有没有办法检索某种包含键和值的条目对象?

我知道我可以从地图对象中检索迭代器,但这对我来说不是一个选择。

I implemented a unique map. It's a hashmap which is bi-directional, where not only keys are unique but values too.

public interface UniqueMap<K,V>{

    V uniquePut(K key, V value);

    UniqueMap<V,K> inverse(); 
}

This is a possible implementation:

public class SimpleUniqueMap<K,V> implements UniqueMap<K,V>, Iterable<K>{

    public HashMap<K,V> uniqueMap = new HashMap<K,V>();

    class EnumSimpleUniqueMap implements Iterator<K>{

        int count = uniqueMap.size();

        public boolean hasNext(){
            return count > 0;
        }

        public K next(){
            if(count == 0){
                throw new NoSuchElementException();     
            }else{
                count--;
                //...
            }
        }

        public void remove(){
            throw new UnsupportedOperationException();
        }
    }

    public Iterator<V> iterator(){
        return new EnumSimpleUniqueMap();
    }

    public V uniquePut(K key, V value){ 
        return null;
    }

    public UniqueMap<V,K> inverse(){
        return null;
    }
}

As you can see I already tried to implement an iterator for my unique map. But from a hashmap values are not accessed by position but by key. So usually I would take the counter and access values but in this case it is not possibe.

Actually it would be enough to iterate over the keys and retrieve them one by another. How can I do that? Is there a way to retrieve some kind of entry object containing both key and value?

I know that I can retrieve the iterator from an map object but this is not an option for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尐籹人 2024-11-25 03:46:28

您可以通过简单地委托给支持哈希映射的键集迭代器来实现您的 iterator() 方法:

public Iterator<K> iterator(){
    return uniqueMap.keySet().iterator();
}

当然,正如 Lukas 所说,通常映射不会是可迭代的,但提供本身是可迭代的集合视图。

另外,对于您独特的映射实现来说,在两个方向上都有 HashMap 可能是一个好主意。

另外,请考虑(并在界面中指定):如果用户插入具有已存在值的新键,会发生什么情况 - 会失败、被忽略、删除现有映射还是什么?

You could implement your iterator() method by simply delegating to your backing hashmap's keyset iterator:

public Iterator<K> iterator(){
    return uniqueMap.keySet().iterator();
}

Of course, as Lukas said, usually a map will not be iterable, but provide collection views which themselves are iterable.

Also, it might be a good idea for your unique map implementation to have HashMaps in both directions.

Also, think about (and specify it in the interface): What should happen if the user inserts a new key with an already existing value - does this fail, get ignored, remove the existing mapping, or what?

℡Ms空城旧梦 2024-11-25 03:46:28

更新:最简单的是,使用

org.apache.commons.collections.BidiMap

但如果你真的想推出自己的,那么请考虑这一点:

通常,Maps不实现Iterable。在您的情况下,您可以通过调用地图上的任何一个来免费获取Iterator

map.keys().iterator(); // is the same as
map.inverse().values().iterator();

map.values().iterator(); // is the same as
map.inverse().keys().iterator();

map.entrySet().iterator(); // almost the same as
map.inverse().entrySet().iterator();

,具体取决于您想要迭代的内容。为此,您必须

public interface UniqueMap<K,V> extends Map<K, V> {
    // no need for uniquePut(), you already have Map.put()
    UniqueMap<V,K> inverse(); 
}

使您的实现扩展

java.util.AbstractMap<K, V>

已经具有很多地图的基本功能,这也是一个好主意。

UPDATE: Most simple of all, use

org.apache.commons.collections.BidiMap

But if your really want to roll your own, then consider this:

Usually, Maps don't implement Iterable. In your case, you can get the Iterator for free by calling any of these

map.keys().iterator(); // is the same as
map.inverse().values().iterator();

map.values().iterator(); // is the same as
map.inverse().keys().iterator();

map.entrySet().iterator(); // almost the same as
map.inverse().entrySet().iterator();

on your map, depending on what you want to iterate over. For that, you'd have to make

public interface UniqueMap<K,V> extends Map<K, V> {
    // no need for uniquePut(), you already have Map.put()
    UniqueMap<V,K> inverse(); 
}

It's also a good idea to make your implementation extend

java.util.AbstractMap<K, V>

Which has a lot of base functionality for maps already.

鸵鸟症 2024-11-25 03:46:28

您应该查看Guava 库(Google Collection)。他们有一个 BiMap 实现这似乎正是您想要实现的......

You should have a look to the Guava library (Google Collection). They have a BiMap implementation that seems to be exactly what your are trying to implement...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文