Alternating String Casing in Java


The challenge

altERnaTIng cAsE <=> ALTerNAtiNG CaSe

Define String.prototype.toAlternatingCase (or a similar function/method such as to_alternating_case/toAlternatingCase/ToAlternatingCase in your selected language; see the initial solution for details) such that each lowercase letter becomes uppercase and each uppercase letter becomes lowercase. For example:

StringUtils.toAlternativeString("hello world") == "HELLO WORLD"
StringUtils.toAlternativeString("HELLO WORLD") == "hello world"
StringUtils.toAlternativeString("hello WORLD") == "HELLO world"
StringUtils.toAlternativeString("HeLLo WoRLD") == "hEllO wOrld"
StringUtils.toAlternativeString("12345") == "12345" // Non-alphabetical characters are unaffected
StringUtils.toAlternativeString("1a2b3c4d5e") == "1A2B3C4D5E"
StringUtils.toAlternativeString("StringUtils.toAlternatingCase") == "sTRINGuTILS.TOaLTERNATINGcASE"

As usual, your function/method should be pure, i.e. it should not mutate the original string.

The solution in Java code

Option 1:

public class StringUtils {
    public static String toAlternativeString(String string) {
        String result = "";
        for (char c : string.toCharArray()) {
            if(Character.isUpperCase(c)) {
                result += Character.toLowerCase(c);
            } else {
                result += Character.toUpperCase(c);
            }
        }
        return result;
    }
}

Option 2:

import static java.lang.Character.*;

public class StringUtils {
    public static String toAlternativeString(String string) {
        return string.chars()
                .map(c -> isUpperCase(c) ? toLowerCase(c) : isLowerCase(c) ? toUpperCase(c) : c)
                .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
                .toString();
    }
}

Option 3:

import java.util.*;

public class StringUtils {
  
  public static String toAlternativeString(String str){
    StringBuilder s = new StringBuilder();
    str.chars()
       .forEach( i -> {
            char c = (char) i;
            s.append( Character.isUpperCase(c) ? Character.toLowerCase(c)
                                               : Character.toUpperCase(c));
    });
    return s.toString();
  }
}

Test cases to validate our solution

import static org.junit.Assert.*;

public class StringUtilsTest {
  private static final String CHARS = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 .,;:!?/";

  @Test
  public void fixedTests() {
    assertEquals("HELLO WORLD", StringUtils.toAlternativeString("hello world"));
    assertEquals("hello world", StringUtils.toAlternativeString("HELLO WORLD"));
    assertEquals("HELLO world", StringUtils.toAlternativeString("hello WORLD"));
    assertEquals("hEllO wOrld", StringUtils.toAlternativeString("HeLLo WoRLD"));
    assertEquals("Hello World", StringUtils.toAlternativeString(StringUtils.toAlternativeString("Hello World")));
    assertEquals("12345", StringUtils.toAlternativeString("12345"));
    assertEquals("1A2B3C4D5E", StringUtils.toAlternativeString("1a2b3c4d5e"));
    assertEquals("sTRINGuTILS.TOaLTERNATINGcASE", StringUtils.toAlternativeString("StringUtils.toAlternatingCase"));
  }
  
  @Test
  public void kataTitleTests() {
    assertEquals("ALTerNAtiNG CaSe", StringUtils.toAlternativeString("altERnaTIng cAsE"));
    assertEquals("altERnaTIng cAsE", StringUtils.toAlternativeString("ALTerNAtiNG CaSe"));
    assertEquals("ALTerNAtiNG CaSe <=> altERnaTIng cAsE", StringUtils.toAlternativeString("altERnaTIng cAsE <=> ALTerNAtiNG CaSe"));
    assertEquals("altERnaTIng cAsE <=> ALTerNAtiNG CaSe", StringUtils.toAlternativeString("ALTerNAtiNG CaSe <=> altERnaTIng cAsE"));
  }
  
  @Test
  public void randomTests() {
    Random random = new Random();
    for (int i = 1; i <= 50; i++) {
      int length = random.nextInt(30) + 1;
      StringBuilder stringBuilder = new StringBuilder(length);
      for (int k = 1; k <= length; k++) stringBuilder.append(CHARS.charAt(random.nextInt(CHARS.length())));
      String testString = stringBuilder.toString();
      assertEquals(solution(testString), StringUtils.toAlternativeString(testString));
    }
  }
  
  private String solution(String string) {
    return string.chars().map(c -> Character.isLowerCase(c) ? Character.toUpperCase(c) : Character.toLowerCase(c)).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
  }
}