2

I have a hashmap which contains student id as key and some string as value.

Map<Integer, String> data = new HashMap<Integer, String>();

it contains data like

1 a
2 b
3 a
4 c
5 b
6 a

i want to find the duplicate values in map and replace them with integer values. i.e. i want a map like

1 1
2 2
3 1
4 3
5 2
6 1

i.e. map shud pick first value(a), find all keys for that value and then replace value of those keys with 1. Then pick second value(b) find all keys and replace them with 2 and so on. The file i am reading is too large so i cannot replace all keys manually by specifying each key. So, what i have tried so far is

Map<Integer,Integer> finalmap = new HashMap<Integer,Integer>();
int a=0;
     List mapkey = new ArrayList(data.keySet());
     List mapval = new ArrayList(data.values());
     Iterator valit = mapval.iterator();
     while(valit.hasNext()){
         a=a+1;
         Object valuet = valit.next();

         Iterator keyit = mapkey.iterator();
         while(keyit.hasNext()){
             Object keyt = keyit.next();

             String comp1 = data.get(keyt).toString();
             String comp2 = valuet.toString();
             if(comp1.equals(comp2)){
                 finalmap.put((String)keyt,a);
             }

         }

     }  

but this is not giving me correct output. it doesnt start with a=1. I think probably it first calculates all the incremented values of a. I have a text file with 1000 records. And the output i get is

1 1000
2 987
3 1000
4 298
5 987
6 1000

I dont know where i m wrong. Please help me regarding this. Thank You

3
  • "first" value. What does that mean? There is no "first" value in a HashMap Commented Dec 2, 2014 at 3:05
  • How do you determine what your integer values should be? Can't you just figure that out as new values arrive? Commented Dec 2, 2014 at 4:27
  • @Jared..i simply want to insert increasing integer values starting from 1. all i want is to replace values(which are string) with integer values in hashmap. Commented Dec 2, 2014 at 5:08

5 Answers 5

4

First thing you need to understand, there is no such thing as "first" value in HashMap. If you want that to be ordered base on the key, you should use TreeMap instead.

If that ordering is not a concern for you, and what you need is only same integer to replace same value, there are lots of way to do. One way is (code is not accurate, but should demonstrate the idea):

// setup a map of oldValue to newValue
HashMap<String, Integer> valueMap = ...;
int i = 0;
for (String oldValue : data.values()) {
    if ( ! valueMap.contains(oldValue )) {
        valueMap.put(oldValue, ++i);
    }
}

// replace everything in data
for (Map.Entry<Integer, String> dataEntry : data.entrySet()) {
    finalMap.put(dataEntry.getKey(), valueMap.get(dataEntry.getValue());
}
Sign up to request clarification or add additional context in comments.

1 Comment

my fault, the last line should be getting from valueMap base on the entry's value. Fixed in answer already. (But I don't mean to give the code for you to copy, I am expecting you to understand the rationale and write it yourself in fact :P )
3

You can try the following program, where we build set of values and then replace.

public class Sample {

public static void main(String[] args) {
    Map<Integer,Integer> finalMap = new TreeMap<Integer, Integer>();
    Map<Integer,String> map = new TreeMap<Integer, String>();
    map.put(1, "a");
    map.put(2, "b");
    map.put(3, "a");
    map.put(4, "c");
    map.put(5, "b");
    map.put(6, "a");

      Map<String,Integer> setOfValues = new TreeMap<>();

      int count = 0 ;
       /**
       * Build set of values.
       */
      for(Map.Entry<Integer,String> entry : map.entrySet()){
          if(!setOfValues.containsKey(entry.getValue())){
              count++;
              setOfValues.put(entry.getValue(), count);
          }
      }
      /**
       * Replace values.
       */
      for(Map.Entry<Integer,String> entry : map.entrySet()){
          finalMap.put(entry.getKey(), setOfValues.get(entry.getValue()));
      }
      /**
       * Print values.
       */
      for(Map.Entry<Integer,Integer> entry : finalMap.entrySet()){
          System.out.println(entry.getKey()+" - "+entry.getValue());

      }
}
}

2 Comments

If your only data is alphabets a,b,c and you want to replace them with 1,2,3 etc. Then following might help(replacing with ASCII values). Code is in next comment.
for(Map.Entry<Integer,String> entry : map.entrySet()){ finalMap.put(entry.getKey(), ((int)entry.getValue().charAt(0))-96); }
1

Create another Map to contain the new values to generate. (It's a Map so you can look up values quickly). As you walk through your orig map, look up entries in your new map. When a value isn't found, create a new one, perhaps off an incremented int.

Comments

0

You need to use two separate inner loop for this job. Using the first loop on the map find the number of a certain value, for example, 'a', using another loop to update all the entries whose value is 'a'.

Comments

0

I don't quite understand what you mean by "The file i am reading is too large so i cannot replace all keys manually by specifying each key." If the file is "too large" then you shouldn't be able to fit the hash table into main memory (or any map or list data structure for that matter). So disregarding that, it seems to me the simple solution is to maintain a hash of your values' values:

private int currIntVal = 1;

private final Map<Integer, Integer> idToValue = 
    new HashMap<Integer, Integer>(DEF_ID_SIZE);

private final Map<String, Integer> valToInt = 
    new HashMap<String, Integer>(DEF_VALUES_SIZE);

private void addMapping(final int id, final String value){
    idTovalue.put(id, getIntValue(value));
}

private int getIntValue(final String value){
    Integer val = valToInt.get(value);
    if(val == null){
        val = currIntVal++;
        valToInt.put(value, val);
    }

    return val;
}

Based on the fact that it appears you are assigning letter grades to student IDs, most likely the best solution is to simply enumerate all possible grades, something like:

public static final String A_PLUS_GRADE = "A+";
public static final String A_GRADE = "A";
public static final STring A_MINUS_GRADE = "A-";
...

private final Map<Integer, String> idToGrade = 
    new HashMap<Integer,String>(DEF_ID_SIZE);

private void addMapping(final int id, final String grade){
    final String UPPER_GRADE = grade.toUpperCase();
    switch(UPPPER_GRADE){
    case A_PLUS_GRADE: idToGrade.put(id, A_PLUS_GRADE);
        break; // or return;
    case A_GRADE: idtoGrade.put(id, A_GRADE);
        break;
    case A_MINUS_GRADE: idToGrade.put(id, A_MINUS_GRADE);
        break;
    ...
    default: throw new RuntimeException(grade + " is an unrecognized grade");
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.