Hackerrank Sparse Arrays in Java 8
Your code uses streams quite neatly and well. The algorithm employed is not necessarily the best, but the logic is reasonably clear.

It's common with streams to use vertical white-space to make the steps in code more readable. For example, the line:


queries.stream().forEach(query -&gt; System.out.println(corpus.stream().filter(p -&gt; p.equals(query)).count()));



could be re-formatted as:

queries.stream()
       .forEach(query -&gt; System.out.println(
              corpus.stream()
                    .filter(p -&gt; p.equals(query))
                    .count()
               ));


Now, while dealing with that stream, it's not really streaming things "right".... The System.out.println is out-of-place. You should be mapping the query in to a count in one step, and then outputting the count in a different step....

queries.stream()
       .mapToInt(query -&gt; corpus.stream()
                    .filter(p -&gt; p.equals(query))
                    .count()
               )
       .forEach(System.out::println);


Now, there are ways to improve that performance still, for example, lots of println statements could be grouped in to just one print...

String output = queries.stream()
       .mapToInt(query -&gt; corpus.stream()
                    .filter(p -&gt; p.equals(query))
                    .count()
               )
        .mapToObj(String::valueOf)
        .collect(Collectors.joining("\n"));
System.out.println(output);


Finally, note that you are doing an \$O(n)\$ operation for each query. You should consider a way of improving that time-cost by front-loading the creation of a Map when loading up the words will improve the performance of querying things.

For example, consider this:


IntStream.range(0, N).forEach(n -&gt; corpus.add(sc.next()));



First up, that inner part n -&gt; corpus.add(sc.next()) is doint a "side-effect" operation that can be avoided. Functional-programming purists try to avoid side-effects in streasm as much as possible. SOmetimes it is unavoidable, but you could easily re-write that line as:

List&lt;String&gt; corpus = IntStream.range(0, N)
      .mapToObj(n -&gt; sc.next())
      .collect(Collectors.toList());


That adds each word to a list. How about doing it this way:

Map&lt;String, List&lt;String&gt;&gt; data = IntStream.range(0, N)
         .mapToObj(i -&gt; sc.next())
         .collect(Collectors.groupingBy(v -&gt; v));


That code takes each input word, and returns a Map keyed by each unique word, and each word's value is a list containing each instance of that word in the source.

Now, you can use the length (size) of the value list to return your data with:

String output = queries.stream()
        .mapToInt(query -&gt; data.get(query).size())
        .mapToObj(String::valueOf)
        .collect(Collectors.joining("\n"));
System.out.println(output);