0

This is my first experience in writing code using HashMap and HashSet and I am a little confused where to start from. I want to read a file and count the number of strings used but I have to do this using HashMap and HashSet.

Any ideas on where to start from?

So I will read the file and put the strings in an array and then read it from the array and putting them into a HashSet? Is this an idiotic idea?

The constraint is that The only O(n) operation in the program should be iterating through the text file.

Thank you for the contribution in increasing my knowledge ;)

dabadaba
  • 9,064
  • 21
  • 85
  • 155
sajaMega
  • 23
  • 7
  • 3
    You don't need a set, just a map (because the keys of a map are already in a set). You would want a `Map` where the key which refers to the word is a string and the value an integer which is the count. So you read the file word by word and add the word to the map with a count of 1 if the key mapping doesn't exist in the map, or increment it by 1 if the key mapping exists. – dabadaba May 10 '16 at 10:01
  • Read a line in a loop, and for every word in the line increase its count in the frequency table. – Joop Eggen May 10 '16 at 10:09
  • How can i return this integer? or Should I store it in another variable and then return it? – sajaMega May 10 '16 at 10:09
  • @database thank you for the suggestions ^_^ – sajaMega May 10 '16 at 10:11
  • @JoopEggen Thank you too – sajaMega May 10 '16 at 10:12
  • @SaidaHoca my name is database now? lol answering you last question, you don't need to return anything, just set the map's value to what I said above. – dabadaba May 10 '16 at 10:39
  • 3
    *"Read a file and spit out ..."* - Don't teach your program to "spit". It is unhygienic. A polite program should always output things ... without unwanted saliva. :-) – Stephen C May 10 '16 at 10:48

3 Answers3

0

first you read entire data from file and store in string object now use java.util.StringTokenizer class .it will split up all words in token now read all token one by one and check it like following use word as Key and its frequency as value in HashMap

HashMap map=new HashMap();
HashSet set=new HashSet();
StringTokenizer st = new StringTokenizer(strObj);
String s;
while (st.hasMoreTokens()) {
     s=st.nextToken();
    if(map.containsKey(s))
    {
        count=(Integer)map.get(s);
        count++;
        map.put(s,count);
        set.add(s);
    }
    else
    {
        map.put(s,count);
        set.add(s);
    }
}
Sharad Gautam
  • 91
  • 5
  • 11
0

You're close, but can miss out the middle man (that array).

You can use a HashMap<String, Integer> to store a map of string to count of string.
What you need your program to do is:

  1. Read the next string from the file.
  2. Check if that string exists in you HashMap:
    1. If it does exist, just grab the Integer that the String maps onto from the map, increment it, and put it back into the map.
    2. If it does not exist, put the String in the map with the Integer 1.
  3. Repeat from step 1 until the file has been read.
  4. Grab the value collection from the HashMap and store it using Collection<Integer> counts = map.values();
  5. Sum the collection using streams int sum = counts.stream().mapToInt(i -> i).sum();
  6. Output the value of sum.

I'm sure you can figure out to convert that to code yourself! :)


You can find more info on HashMap here (check out the values() method), more info on Stream here, and more info on that funky bit of code from step 5 here.

Community
  • 1
  • 1
Tiz
  • 680
  • 5
  • 17
  • Integer is immutable, so you have to put a new instance into the map. This is why I used my own wrapper class in my answer... – Aconcagua May 10 '16 at 10:41
  • @Aconcagua You're right, it is. I'll update my answer to make the process a little clearer. Thanks. – Tiz May 10 '16 at 10:47
0

In addition to Sharad's answer: Reading from file...

// would loved to use Integer, but it is immutable...
class Wrapper
{
    public Wrapper(int value)
    {
        this.value = value;
    }
    public int value;
}

HashMap<String, Wrapper> counts = new HashMap<String, Wrapper>();
Scanner scanner = new Scanner(new File(fileName));
while(scanner.hasNext())
{
    String token = scanner.next();
    Wrapper count = counts.get(token);
    if(count == null)
    {
        counts.put(token, new Wrapper(1));
    }
    else
    {
        ++count.value;
    }
}
scanner.close();

I varied sharad's algorithm a little, not having to calculate the hash value twice if the value is already in the map, and using generics saves you from having to cast.

If you need only the strings in the file as set, you get it via counts.keySet();.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • thank u, I have a last question. Inside what class will the code you provided be in? – sajaMega May 10 '16 at 17:40
  • @SaidaHoca There are many options. If you do not want to do anything else in your program, you can have the Wrapper class as inner class of the one containing main and place the loop directly into the main method - iterating over the map directly afterwards to output the results. You can have the loop in a separate method (parallel to main), which would return the HashMap. Or you can create a separate class with Wrapper as inner class and the loop in a static method. Alternatively, the HashMap can be a member variable and the loop (including the scanner instance) placed in a non-static method. – Aconcagua May 10 '16 at 18:00
  • I got what you said and I tried to do it but there is an error which says that can not resolve the get method :/ – sajaMega May 10 '16 at 19:49
  • @SaidaHoca Oh, sorry, must be counts.get, of course... And before you stumble over yourself: If you use Wrapper as an inner class, you need to make it static if using in a static method (including main). – Aconcagua May 10 '16 at 20:43
  • @SaidaHoca And we should close the scanner again. – Aconcagua May 10 '16 at 20:45