Given n input strings and m query strings, find each query frequency in the list of input strings I'm doing questions on HackerRank to brush up on Java &amp; CS.



Problem

This problem is called Sparse Arrays in HackerRank.


  There is a collection of input strings and a collection of query
  strings. For each query string, determine how many times it occurs in
  the list of input strings.
  
  For example, given input strings = ['ab', 'ab', 'bc'] and queries =
  ['ab', 'abc', 'bc'], result is [2, 1, 0]
  
  Full Question


Solution

static int[] matchingStrings(String[] strings, String[] queries) {
    Map&lt;String, Integer&gt; counter = new HashMap&lt;&gt;();
    for (String current: strings) {
        counter.put(current, counter.getOrDefault(current, 0) + 1);
    }

    int[] result = new int[queries.length];
    for (int i = 0; i &lt; queries.length; i++) {
        result[i] = counter.getOrDefault(queries[i], 0);
    }
    return result;
}


This passes all the test cases. 


Can I do it in a better way? 
Can this be simplified in Java-8, 11 or later?
Can I do it in a better way?


From the time complexity or space complexity your solution is good enough. Your store all your string frequencies beforehand so that to retrieve a frequency by any given string in O(1) time later. Also, it passes all the test cases so it's a good sign too.

Below are a couple of concerns regarding other aspects of your code.

Variable Naming

Your choice of variable names should be improved. For instance, Map&lt;String, Integer&gt; counter doesn't really reflect for what it stands for. I would call it stringFrequencyMap or stringCountMap.  

Also, result sounds too generic here. How about queryResults?

I'll leave it up to you to think about other variable names you have (luckily not many left :) ).

Static method

I guess you've kept this method static as it was like this by default and to avoid creating an instance of your Solution class in the main() method. While it's fine for a small challenge like yours, generally there should be a good reason to add static to your method.

Improvements


  Can this be simplified in Java-8, 11 or later?


Of course, if we just use JAVA 8 then we can take advantage of streams and write a solution as :

static long[] matchingStrings(String[] strings, String[] queries) {
    Map&lt;String, Long&gt; stringCountMap = Arrays.stream(strings).collect(Collectors.groupingBy(Function.identity(), counting()));

    return Arrays.stream(queries).mapToLong(query -&gt; stringCountMap.getOrDefault(query, 0L)).toArray();
}


As you can see, we do this in 2 steps. First, we calculate a frequency map and then calculate an array of results using streams again. Please note that I changed the return type from int[] to long[].

UPDATE

Since there was a question why I've used Map&lt;String, Long&gt; rather than Map&lt;String, Integer&gt; - well, Long can hold bigger numbers. But since it's irrelevant for this problem here's a solution for Map&lt;String, Integer&gt;:

int[] matchingStrings(String[] strings, String[] queries) {
    Map&lt;String, Integer&gt; stringCountMap = Arrays.stream(strings).collect(Collectors.groupingBy(Function.identity(), summingInt(x -&gt; 1)));

    return Arrays.stream(queries).mapToInt(query -&gt; stringCountMap.getOrDefault(query, 0)).toArray();
}