hat_to_the_back
hat_to_the_back

Reputation: 291

More efficient way of getting frequency of words

I want to count the frequency of each word in an ArrayList by the start of the word. e.g [cat, cog, mouse] will mean there are 2 words begining with c and one word begining with m. The code I have works fine but there are 26 letters in the alphabet which will require alot more if s. Is there any other way of doing this?

public static void  countAlphabeticalWords(ArrayList<String> arrayList) throws IOException
{
    int counta =0, countb=0, countc=0, countd=0,counte=0;
    String word = "";
    for(int i = 0; i<arrayList.size();i++)
    {

        word = arrayList.get(i);

          if (word.charAt(0) == 'a' || word.charAt(0) == 'A'){ counta++;}
          if (word.charAt(0) == 'b' || word.charAt(0) == 'B'){ countb++;}    

    }
    System.out.println("The number of words begining with A are: " + counta);
    System.out.println("The number of words begining with B are: " + countb);

}

Upvotes: 1

Views: 1385

Answers (3)

Jaa-c
Jaa-c

Reputation: 5137

How about this? Considering that the words start only with [a-zA-Z]:

public static int[] getCount(List<String> arrayList) {
    int[] data = new int[26];
    final int a = (int) 'a';

    for(String s : arrayList) {
        data[((int) Character.toLowerCase(s.charAt(0))) - a]++;
    }

    return data;
}

edit:

Just out of curiosity, I made a very simple test comparing my method and Steph's method with map. List with 236 items, 10000000 iterations (without printing the result): my code took ~10000ms and Steph's took ~65000ms.

Test: http://pastebin.com/HNBgKFRk

Data: http://pastebin.com/UhCtapZZ

Upvotes: 4

Steph
Steph

Reputation: 2049

Use a Map

public static void  countAlphabeticalWords(List<String> arrayList) throws IOException {
  Map<Character,Integer> counts = new HashMap<Character,Integer>();
  String word = "";

  for(String word : list) {
    Character c = Character.toUpperCase(word.charAt(0));
    if (counts.containsKey(c)) {
      counts.put(c, counts.get(c) + 1);
    }
    else {
      counts.put(c, 1);
    }
  }

  for (Map.Entry<Character, Integer> entry : counts.entrySet()) {
    System.out.println("The number of words begining with " + entry.getKey() + " are: " + entry.getValue());
  }

Or use a Map and AtomicInteger (as per Jarrod Roberson)

public static void  countAlphabeticalWords(List<String> arrayList) throws IOException {
  Map<Character,AtomicInteger> counts = new HashMap<Character,AtomicInteger>();
  String word = "";

  for(String word : list) {
    Character c = Character.toUpperCase(word.charAt(0));
    if (counts.containsKey(c)) {
      counts.get(c).incrementAndGet();
    }
    else {
      counts.put(c, new AtomicInteger(1));
    }
  }

  for (Map.Entry<Character, AtomicInteger> entry : counts.entrySet()) {
    System.out.println("The number of words begining with " + entry.getKey() + " are: " + entry.getValue());
  }

Best Practices

Never do list.get(i), use for(element : list) instead. And never use ArrayList in a signature use the Interface List instead so you can change the implemenation.

Upvotes: 7

Sami N
Sami N

Reputation: 1180

Now, every character can be cast to an integer, representing an ASCII decimal. For example, (int)'a' is 97. 'z''s ASCII decimal is 122. http://www.asciitable.com/

You can create a lookup table for the characters:

int characters = new int[128]

Then in your algorithm's loop use the ASCII decimal as index and increment the value:

word = arrayList.get(i);
characters[word.charAt(0)]++;

In the end, you can print the occurence of the characters:

for (int i = 97; i<=122; i++){
  System.out.println(String.format("The number of words beginning with %s are: %d", (char)i, characters[i]));
}

Upvotes: 0

Related Questions