Pergunta

I am trying to build a many to one key value pair in java. Till now all I have manged is this

  public class KeyStore {
    int i=1;
    Map<Integer,String> map1=new HashMap<Integer,String>();
    Map<String,List<Integer>> map2=new HashMap<String,List<Integer>>();

    public synchronized int put(String blobString) {
    if(map1.containsValue(blobString)){
    int r=blobString.hashCode()+i*blobString.hashCode();
    i++;
    map1.put(r, blobString);
    List<Integer> j=map2.get(blobString);
    List<Integer> k=j;
    map2.remove(blobString);
    k.add(r);
    map2.put(blobString, k);
    return r;

}
else{
    map1.put(blobString.hashCode(),blobString);
    List<Integer> x=new ArrayList<Integer>();
    x.add(blobString.hashCode());
    map2.put(blobString,x);
    return blobString.hashCode();
}
}

     public synchronized String get(int objectId) {
         return map1.get(objectId);
  }

What this does is if i put

  ks.put("abc") 

  ks.put("abc")

Here ks is an instant of the class containing the above methods.

it results in

{1916062554=abc, 958031277=abc}

But what I want is

191602554,958031277=abc

and if i use get() on either of these keys it should output the value abc. Also delete() should delete the most recent key and not harm the other keys.

I thought of using

Map<ArrayList<Integer>,String> keystore=new HashMap<ArrayListInteger>,String>();

but I dont know how to implement the put method i.e how to insert a key in a map of lists. Need help with this.

EDIT 1

I am able to make the get and put methods work. Struggling with the delete method. Wrote it some what like this

Map<Integer,String> map1=new HashMap<Integer,String>();
Map<String,List<Integer>> map2=new HashMap<String,List<Integer>>();

public synchronized void delete(int objectId) {
  map1.remove(objectId);
  Iterator<Entry<String, List<Integer>>> it = map2.entrySet().iterator();
 loop1: while (it.hasNext()) {
        @SuppressWarnings("rawtypes")
        Map.Entry pairs = (Map.Entry)it.next();
        @SuppressWarnings("unchecked")
        List<Integer> z=(List<Integer>) pairs.getValue();
         if(z.contains(objectId)){
             //System.out.println(z.size());
             String key=(String) pairs.getKey();
             System.out.println(z+" "+key);
            if(z.size()==1){
                map2.remove(key);
                break loop1;
            }
            else{
                z.remove(objectId);
                map2.remove(key);
                map2.put(key, z);
                break loop1;
            }
        }
  }
  }

Basically map1 contains the mappings

123=>abc,456=>abc

and map2 contains

abc=>[123,456]

I am getting an arrayindexoutofbound exception. What I am trying in the delete method is to iterate across each blob String and then check in the list of values associated with the blobstring whetehr the required objectID is present. if it is then I remove that object id from the list and append the new mapping. Any help?

EDIT 2

The updated and working get and put methods are given above.

Nenhuma solução correta

Outras dicas

The Map JavaDoc says:

A map cannot contain duplicate keys; each key can map to at most one value.

But you can get around this by making the value a list of strings:

   import  java.util.ArrayList;
   import  java.util.HashMap;
   import  java.util.Iterator;
   import  java.util.List;
   import  java.util.Map;
   import  java.util.Set;

/**
   <P>{@code java MultiValueHashMap}</P>
 **/
public class MultiValueHashMap  {
   public static final void main(String[] ignored)  {
      Map<Integer,List<String>> mapOfIntStrs = new HashMap<Integer,List<String>>();

      //Add elements
         addStringToMap(mapOfIntStrs, 1, "one");
         addStringToMap(mapOfIntStrs, 1, "two");
         addStringToMap(mapOfIntStrs, 1, "three");
         addStringToMap(mapOfIntStrs, 2, "four");
         addStringToMap(mapOfIntStrs, 2, "five");

      //Output 
         Set<Integer> keyNumSet = mapOfIntStrs.keySet();
         Iterator<Integer> keyNumItr = keyNumSet.iterator();
         while(keyNumItr.hasNext())  {
            Integer keyNum = keyNumItr.next();
            List<String> strList = mapOfIntStrs.get(keyNum);
            System.out.println(keyNum);
            for(String s : strList)  {
               System.out.println("  " + s);
            }
         }
   }
   private static final void addStringToMap(Map<Integer,List<String>> mapTo_addTo, int keyNum, String value)  {
      if(mapTo_addTo.containsKey(keyNum))  {
         mapTo_addTo.get(keyNum).add(value);
      }  else  {
         List<String> strList = new ArrayList<String>();
         strList.add(value);
         mapTo_addTo.put(keyNum, strList);
      }
   }

}

Output:

[C:\java_code\]java MultiValueHashMap
1
  one
  two
  three
2
  four
  five

Regarding multiple keys per value, you could certainly do this, although I'm not sure it's recommended. According to the HashMap API:

The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.

And the Hashtable API:

To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.

So while this would work with ArrayList<Integer> keys, for anything with customized keys, containing non-standard classes, unless you are correctly implementing hashCode() for those objects, the HashMap may not function properly.

It seems like you need a couple of data structures as fields in your class:

  • stringMap: Map<Integer,String>
    • {1916062554=abc, 958031277=abc}, etc.
    • because for get you want to look up items by key
  • keys: Map<String,List<Integer>>
    • { "abc" = {1916062554, 958031277}
    • because for delete you want to know the keys for a given item, in order.

To add to the Map:

 public void put(String item) {
     List<Integer> list = getOrCreateList(item,keys);
     int key = calculateKey(item,list);
     list.add(key);
     stringMap.put(key,item);
 }

 private static List<Integer> getOrCreateList(String item, Map<String,List<Integer>> map) {
     List<Integer> list = map.get(item);
     if(list == null) {
         list = new ArrayList<Integer>();
         map.put(item,list);
     }
     return list;
 }

To get from the map is easy:

 public String get(int key) {
     return stringMap.get(key);
 }

To delete from the map -- if I understand your requirements correctly -- you need to find the most recent key in the list corresponding to the key provided...

 public void delete(int key) {
     String item = stringMap.get(key);
     if(item == null) {
        // ... deal with
     }
     List<Integer> keys = keys.get(item);

     // lazily using methods which don't exist in the Java API
     // but which illustrate the point.
     keys.removeLast();
     if(keys.isEmpty()) {
         stringMap.remove(key);
         list.remove(item);
     }
 }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top