带有.class对象的Hashmap作为键

时间:2014-07-08 14:21:08

标签: java hashmap key

我已经为键创建了一个带有.class对象的hashmap。

Hashmap<Class<? extends MyObject>, Object> mapping = new Hashmap<Class<? extends MyObject>, Object>();

这一切都很好,但是我得到了奇怪的行为,我只能用哈希函数归因于奇怪。在运行时期间随机迭代遍历hashmap不会命中每个值;它会错过一两个。我认为这可能是由于.class对象不是最终的,因此它会发生变化,导致它映射到不同的哈希值。使用不同的哈希值,哈希映射将无法正确地将密钥与值相关联,从而使其看起来已丢失该值。

我是否纠正这是怎么回事?我该如何解决这个问题?有没有更好的方法来完成这种形式的数据结构?

编辑:我真的以为我是在使用哈希函数的东西,但我会发布我的真实代码来试图解决这个问题。这可能是我实现多图的问题。我已经使用它已经有一段时间了,直到最近才发现任何问题。

/**
 * My own implementation of a map that maps to a List. If the key is not present, then
 * the map adds a List with a single entry. Every subsequent addition to the key
 * is appended to the List.
 * @author 
 *
 * @param <T>   Key
 * @param <K>   Value
 */

public class MultiMap<T, K> implements Map<T, List<K>>, Serializable, Iterable<K> {

    /**
     * 
     */
    private static final long serialVersionUID = 5789101682525659411L;

    protected HashMap<T, List<K>> set = new HashMap<T, List<K>>();

    @Override
    public void clear() {
        set = new HashMap<T, List<K>>();

    }

    @Override
    public boolean containsKey(Object arg0) {
        return set.containsKey(arg0);
    }

    @Override
    public boolean containsValue(Object arg0) {
        boolean output = false;

        for(Iterator<List<K>> iter = set.values().iterator();iter.hasNext();) {
            List<K> searchColl = iter.next();
            for(Iterator<K> iter2 = searchColl.iterator(); iter2.hasNext();) {
                K value = iter2.next();
                if(value == arg0) {
                    output = true;
                    break;
                }
            }
        }

        return output;
    }

    @Override
    public Set<Entry<T, List<K>>> entrySet() {

        Set<Entry<T, List<K>>> output = new HashSet<Entry<T,List<K>>>();

        for(Iterator<T> iter1 = set.keySet().iterator(); iter1.hasNext();) {
            T key = iter1.next();
            for(Iterator<K> iter2 = set.get(key).iterator(); iter2.hasNext();) {
                K value = iter2.next();
                List<K> input = new ArrayList<K>();
                input.add(value);
                output.add(new AbstractMap.SimpleEntry<T,List<K>>(key, input));
            }
        }
        return output;
    }

    @Override
    public boolean isEmpty() {
        return set.isEmpty();
    }

    @Override
    public Set<T> keySet() {
        return set.keySet();
    }

    @Override
    public int size() {
        return set.size();
    }

    @Override
    public Collection<List<K>> values() {
        Collection<List<K>> values = new ArrayList<List<K>>();
        for(Iterator<T> iter1 = set.keySet().iterator(); iter1.hasNext();) {
            T key = iter1.next();
            values.add(set.get(key));
        }
        return values;
    }

    @Override
    public List<K> get(Object key) {
        return set.get(key);
    }

    @Override
    public List<K> put(T key, List<K> value) {
        return set.put(key, value);
    }

    public void putValue(T key, K value) {
        if(set.containsKey(key)) {
            set.get(key).add(value);
        }
        else {
            List<K> setval = new ArrayList<K>();
            setval.add(value);
            set.put(key, setval);
        }
    }

    @Override
    public List<K> remove(Object key) {
        return set.remove(key);
    }

    public K removeValue(Object value) {
        K valueRemoved = null;
        for(T key:this.keySet()) {
            for(K val:this.get(key)) {
                if(val.equals(value)) {
                    List<K> temp = this.get(key);
                    temp.remove(value);
                    valueRemoved = val;
                    this.put(key, temp);
                }
            }
        }
        return valueRemoved;
    }

    @Override
    public void putAll(Map<? extends T, ? extends List<K>> m) {
        for(Iterator<? extends T> iter = m.keySet().iterator(); iter.hasNext();) {
            T key = iter.next();
            set.put(key, m.get(key));
        }
    }

    @Override
    public Iterator<K> iterator() {
        return new MultiMapIterator<K>(this);
    }
}

也许我的迭代器有问题?我也会发布那些代码。

import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

public class MultiMapIterator<T> implements Iterator<T> {

    private MultiMap <?, T> map;
    private Iterator<List<T>> HashIter;
    private Iterator<T> govIter;
    private T value;
    public MultiMapIterator(MultiMap<?, T> map) {
        this.map = map;
        HashIter = map.values().iterator();
        if(HashIter.hasNext()) {
            govIter = HashIter.next().iterator();
        }
        if(govIter.hasNext()) {
            value = govIter.next();
        }
    }

    @Override
    public boolean hasNext() {
        if (govIter.hasNext()) {
            return true;
        }
        else if(HashIter.hasNext()) {
            govIter = HashIter.next().iterator();
            return this.hasNext();
        }
        else {
            return false;
        }
    }

    @Override
    public T next() {
        if(!this.hasNext()) {
            throw new NoSuchElementException();
        }
        else {
            value = govIter.next();
            return value;
        }
    }

    @Override
    public void remove() {
        map.remove(value);
    }
}

很抱歉代码很长。感谢您花时间帮助我。

1 个答案:

答案 0 :(得分:0)

您从构造函数中的govIter中拉出一个值,但永远不会返回它。

你的迭代器删除方法是完全错误的。您正在迭代,但调用由{em>键删除的map.remove。你只想调用govIter.remove()(除非你需要避免空列表,在这种情况下它更复杂)。

您的hasNext()方法也可能会出现问题,具体取决于您是否允许多地图中的空列表值。