Java invert map

2019-01-09 08:31发布

I need create inverse map - select unique values and for them find keys. Seems that only way is to iterate all key/value pairs, because entrySet returns set of so value not unique? Thanks.

标签: java map invert
8条回答
聊天终结者
2楼-- · 2019-01-09 09:26

You have to assume that values may be identical, since the Map contract allows it.

In my opinion the best solution lies in using a wrapper. It will contain the original value, and add an id. Its hashCode() function will rely on the id, and you provide a Getter for the original value. Code would be something like this:

public class MapKey
{
    /**
     * A new ID to differentiate equal values 
     */
    private int _id;
    /**
     * The original value now used as key
     */
    private String _originalValue;

    public MapKey(String originalValue)
    {
        _originalValue = originalValue;
       //assuming some method for generating ids...
        _id = getNextId();
    }

    public String getOriginalValue()
    {
        return _originalValue;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + _id;
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MapKey other = (MapKey) obj;
        if (_id != other._id)
            return false;
        return true;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("MapKey value is ");
        sb.append(_originalValue);
        sb.append(" with ID number ");
        sb.append(_id);
        return sb.toString();
    }

Inverting the map would be something like this:

public Map <MapKey, Integer> invertMap(Map <Integer, String> map)
{

     Map <MapKey, Integer> invertedMap = new HashMap <MapKey, Integer>();

   Iterator<Entry<Integer, String>> it = map.entrySet().iterator();

   while(it.hasNext())
   {
       //getting the old values (to be reversed)
       Entry<Integer, String> entry = it.next();
       Integer oldKey = entry.getKey();
       String oldValue = entry.getValue();

       //creating the new MapKey
       MapKey newMapKey = new MapKey(oldValue);
       invertedMap.put(newMapKey, oldKey);
   }

   return invertedMap;
}

Printing the values something like this:

for(MapKey key : invertedMap.keySet())
       {
           System.out.println(key.toString() + " has a new value of " +  invertedMap.get(key));

       }

None of this code is tested, but I believe it's the best solution since it makes use of OO inheritance design instead of "c" style checks and allows you to display all the original keys and values.

查看更多
仙女界的扛把子
3楼-- · 2019-01-09 09:28

With Guava

Multimaps.transformValues(Multimaps.index(map.entrySet(), Map.Entry::getValue),
        Map.Entry::getKey)

You'll get a multimap (basically a map of lists) in return.

查看更多
登录 后发表回答