-2

So, I created two programs(one with JAVA8) to calculate the total count of uppercase and lowercase characters in given String. After checking the execution time JAVA8 is taking longer execution time than expected. Is there any possible way to optimize any of these code more to reduce execution time and complexity???

Code:

import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Counts
{
public static void main(String arg[])throws Exception
{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int upperCase=0, lowerCase=0;
    String str=br.readLine();
    Long startTimeMemo = System.nanoTime();
    for (int k = 0; k < str.length(); k++) {
// Check for uppercase letters.
if (Character.isUpperCase(str.charAt(k))) upperCase++;
// Check for lowercase letters.
if (Character.isLowerCase(str.charAt(k))) lowerCase++;
}

System.out.printf("%d uppercase letters and %d lowercase letters.",upperCase,lowerCase);
Long stopTimeMemo = System.nanoTime();
    System.out.println("");
    System.out.println("Memoization Time:" + (stopTimeMemo - startTimeMemo));
}
} 

JAVA8 Code:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Count2
{
    public static void main(String arg[])throws Exception
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        Long startTimeMemo = System.nanoTime();
        System.out.println(countUpperCase(str) + " " + countLowerCase(str));    
        Long stopTimeMemo = System.nanoTime();
        System.out.println("");
        System.out.println("Memoization Time:" + (stopTimeMemo - startTimeMemo));
    }
    private static long countUpperCase(String s) {
    return s.codePoints().filter(c-> c>='A' && c<='Z').count();
}

private static long countLowerCase(String s) {
    return s.codePoints().filter(c-> c>='a' && c<='z').count();
}
}
  • 4
    Since this code works, but you just want to optimize it, maybe it would be more fitting to post on https://codereview.stackexchange.com/, as long as you follow the guidelines for posting on there. – Random Davis Jul 06 '21 at 18:05
  • 1
    your second approach would at least not work with german language, since the filter would not get the Umlaute (ÄäÖöÜü) and ß. – juwil Jul 06 '21 at 18:29
  • @juwil what about first approach? Can we optimize to reduce execution time or this is the fastest execution possible? – user12218554 Jul 06 '21 at 18:33
  • 1
    Actually I most times see no point in optimizing this kind of code. If code works (as your first approach seems to do) and is readable/maintainable, I would not bother to care whether it is the highest optimzed way. – juwil Jul 06 '21 at 18:41
  • Both solutions are `O(N)` complexity, and this cannot be improved on. Just saying ... – Stephen C Jul 07 '21 at 10:25

1 Answers1

0

Main difference of the Java 8 version using the Stream API is that the entire string is checked twice for lower case and upper case letters, and two different methods are called, while in for-loop two int counters are merely incremented.

So, the streaming version may be changed to something like this:

int[] counts = {0, 0, 0};
str.codePoints()
   .map(c -> Character.isUpperCase(c) ? 0 : 
             Character.isLowerCase(c) ? 1 : 2)
   .forEach(i -> counts[i]++);

System.out.printf("%d uppercase letters and %d lowercase letters.%n", counts[0], counts[1]);

Regarding the for-loop implementation, the following micro-optimizations are possible although they should be provided by the compiler anyway:

  • calculate string length and get current char once
  • use else to increment lowerCase counter
for (int k = 0, n = str.length(); k < n; k++) {
    char c = str.charAt(k);
    if (Character.isUpperCase(c)) upperCase++;
    else if (Character.isLowerCase(c)) lowerCase++;
}

It may be interesting to read a SO post on the fastest possible way to iterate all the characters in the string

Also, it's highly recommended to review another SO post on correct implementation of micro benchmarks.

Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • Thank you sir. Please confirm that replacing the for loop with a for-each loop and using str.chars() to get the array of characters to iterate over will improve more or it will be same? – user12218554 Jul 07 '21 at 08:32
  • 3
    @user12218554 `str.chars()` does *not* return an array of characters. Besides that, neither the answer nor your question use `str.chars()`, so why should the answerer make a statement about a hypothetical variant which hasn’t been shown anywhere? – Holger Jul 07 '21 at 08:36