-1

I have this HashMap containing words and the count for each word from a given text file;

{word=1, word2=1, word3=2, word4=1, word5=1, word6=4, word7=1, word8=1};

i was following your suggestion in other topics; but i have notice that if use fro example sorted Collections and i search for a specific KEY which could be 1 in this case it only return me one word while instead can return more values for same key;

the point is between all the collections:

Lists Maps ArrayLists Trees HashMaps HashTables

which is the most advisable to use?

on my Class the user will input an int and that int will correspond to the 1st or 2nd or 3rd or 4th and so on..... words used in the files base on the count and occurences;

it's challenging

so far i have managed to store in hashmap and eventually order it in a Tree by Desc Key; so first element will be the greater; but still the algorithm needs more sense;

ps. i do not expect solution or pieces of codes but a good input to start ... a very good advise or direction best to follow;

Beau Grantham
  • 3,435
  • 5
  • 33
  • 43
Franco
  • 875
  • 1
  • 6
  • 14
  • from above if i say: int rank = 3; it should realistically return me "word8 word7 word5 word4 word3 word" as the 3rd rank is equal to count 1 and for count 1 i have those 5 words listed line above; if obviously i input rank =2 it should display "word3" only ans the second ranked is "word3" with count of 2; HOPE MAKE SENSE WHAT I AM TRYING TO ACHIEVE; – Franco Dec 29 '13 at 03:27

2 Answers2

0

Maps, by nature, store (will return) only one element per key. That means that if you'll store [key:1, val:a] and then store again [key:1, val:2]. The second insertion will override the first and when you'll "get" key:1 the returned result will be b.

You can, however, to store a List per key. This list can store all the value values per the same key. So we'll declare the map that we'l use as follows:

Map<String, LinkedList<String>> map = new HashMap<>();

This is how insert should look like:

public void insert(String key, String value){
    List<String> values = map.get(key);
    if (values == null){ // this is the first time we use this key
        values = new LinkedList<String>(); // so we need to create a new values List
    }
    values.add(value);
    map.put(key, values)
}

the "get" is pretty straightforward:
you get the list of values and if it's not null - iterate the values and print/do whatever you want with them.

public List<String> get(String key){
    return map.get(key);
}
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
0

If I understand you correctly, you have a Map<String,Integer> map; which maps words to their frequencies, and now you want to look up words by frequency.

Create a new map that Map<Integer,List<String>> and fill it using the first map:

Map<Integer,List<String>> reverseMap = new HashMap<>();
for (Map.Entry<String,Integer> entry : map.entrySet()) {
    List<String> list = reverseMap.get(entry.getValue());
    if (list == null) {
        reverseMap.put(entry.getValue(), list = new ArrayList<>());
    }
    list.add(entry.getKey());
}

You will get a map like:

java.util.HashMap[3] {
    1=[word2, word4, word, word5, word7, word8]
    2=[word3]
    4=[word6]
}

In this map, each key is the frequency, each value is a list of words having that frequency.

Edit: To pull out the words having the second-most used frequency ("rank 2"), generate a list of the most used frequencies:

List<Integer> frequencies = new ArrayList<>(reverseMap.keySet());
Collections.sort(frequencies, Collections.reverseOrder());

Then:

System.out.println(reverseMap.get(frequences.get(2 - 1)));

Or, to sort the entire map in descending order of frequency (4, 2, 1), declare it as a TreeMap instead of a HashMap, with a reverseOrder comparator:

Map<Integer,List<String>> reverseMap = new TreeMap<>(Collections.reverseOrder());
Boann
  • 48,794
  • 16
  • 117
  • 146
  • do you think can i create something like DB Table; – Franco Dec 29 '13 at 09:56
  • do you think can i create something like DB Table; having 3 different columns {RANK (1) COUNT/WORD(4=[word6])} - {RANK (2) COUNT/WORD(2=[word3])} - {RANK (3) COUNT/WORD(1=[word2, word4, word, word5, word7, word8])} ..... then i will input 2 from the main and it will return word3 as it the second most used word...then if i enter 5 it will return NULL as there is no 5th most used word; your example is GREAT and it gave an idea; but i think to much with a SQL logic :); JAVA i think is limited in this way; or maybe is just me be an amateur? – Franco Dec 29 '13 at 10:03