Part of Github Copilot with Kotlin

Kotlin: Capitalize first letter of a string

Sandy LaneSandy Lane

Video: Kotlin: Capitalize first letter of a string by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Kotlin: Capitalize the First Letter of a String

replaceFirstChar { it.uppercase() } is the modern Kotlin idiom. The deprecated capitalize() and the manual s[0].uppercaseChar() + s.substring(1) both work, but the first is cleanest.

A small string-manipulation puzzle that demos how Kotlin's API surface evolves — the "obvious" function (capitalize()) was deprecated in 1.5, and Copilot's suggestions sometimes lag behind.

The Copilot prompt

// Capitalize the first letter of a string
fun capitalizeFirstLetter(input: String): String {

Copilot may suggest:

fun capitalizeFirstLetter(input: String): String {
  if (input.isEmpty()) return input
  return input[0].uppercaseChar() + input.substring(1)
}

fun main() {
  val original = "kotlin"
  println(capitalizeFirstLetter(original))   // "Kotlin"
}

Walkthrough

Three pieces.

1. Empty guard. if (input.isEmpty()) return input — without this, input[0] throws on an empty string.

2. First character uppercase. input[0] returns the first Char. .uppercaseChar() converts it (returns a Char). For ASCII this is fine; Unicode case-folding has subtleties (some characters become two characters in uppercase, like ßSS).

3. Concatenate. + between Char and String (or String and Char) builds the new string. Strings are immutable, so a new string is allocated.

The modern idiom

Kotlin 1.5 introduced replaceFirstChar, which is the cleanest:

fun capitalize(input: String): String =
  input.replaceFirstChar { it.uppercase() }

replaceFirstChar is locale-aware and handles edge cases. The deprecated capitalize() had locale issues (used the system default; could produce iI in English but I with dot above in Turkish).

it.uppercase() returns a String (handles cases like ßSS). For single-char output, use it.uppercaseChar() (returns a Char).

fun capitalize(input: String): String =
  input.replaceFirstChar { it.uppercaseChar() }

Equivalent for ASCII, slightly more efficient (no string allocation for the converted char).

Why was capitalize() deprecated?

String.capitalize() was a JVM-only Kotlin extension. It used the system's default locale, which produced different output on different systems — a major footgun for "I want consistent capitalization."

replaceFirstChar { it.uppercase() } makes the intent explicit. You can pass a Locale:

input.replaceFirstChar { it.uppercase(Locale.ROOT) }

Locale.ROOT is locale-neutral. Use it whenever you want machine-readable, predictable case conversion.

Title case (every word)

For "make every word's first letter uppercase":

fun titleCase(s: String): String =
  s.split(" ").joinToString(" ") { word ->
    word.replaceFirstChar { it.uppercaseChar() }
  }

println(titleCase("hello world from kotlin"))   // "Hello World From Kotlin"

Naive — splits on single space only. Real title-casing is more involved (handle hyphens, apostrophes, articles). For most cases, this is enough.

Sentence case

Sentence case is "first letter of the sentence uppercase, rest lowercase":

fun sentenceCase(s: String): String =
  s.lowercase().replaceFirstChar { it.uppercaseChar() }

println(sentenceCase("HELLO WORLD"))   // "Hello world"

Lowercase everything first, then uppercase the first char.

Edge cases

Empty string. replaceFirstChar is safe — returns the empty string. The manual version needs the explicit guard.

Single-character string. "k".replaceFirstChar { it.uppercaseChar() }"K". No substring(1) needed; it's just empty.

Already capitalized. "Kotlin".replaceFirstChar { ... }"Kotlin" (uppercase of K is still K). Idempotent.

Non-letter first character. "123abc".replaceFirstChar { it.uppercaseChar() }"123abc". Digits don't have an uppercase form; Char.uppercaseChar() returns the same digit.

Locale-specific. "istanbul".replaceFirstChar { it.uppercaseChar() }"Istanbul" (ASCII uppercase). With Turkish locale, it.uppercase(Locale.forLanguageTag("tr")) produces "İstanbul" (capital I with dot).

Useful one-liners

// Normalize: trim, lowercase, capitalize first
fun cleanName(s: String): String =
  s.trim().lowercase().replaceFirstChar { it.uppercaseChar() }

// First word capitalized, rest unchanged
fun capitalizeFirst(s: String): String =
  s.replaceFirstChar { it.uppercaseChar() }

// Make a Map's values title-case
val titledMap = original.mapValues { it.value.replaceFirstChar { c -> c.uppercaseChar() } }

Steering Copilot

If Copilot suggests the deprecated s.capitalize():

// Capitalize the first letter — use replaceFirstChar (capitalize() is deprecated)

Naming the API in the comment usually flips it to the modern path.

If Copilot suggests s[0].toUpperCase():

// In Kotlin 1.5+, prefer Char.uppercaseChar() and String.uppercase() over toUpperCase()

Specifying the version moves Copilot toward the current API.

Common mistakes

Using deprecated capitalize(). Compiler warning, but easy to miss in code review.

Forgetting empty-string guard. s[0] on empty string throws.

Locale assumptions. Default-locale uppercase is non-deterministic across machines.

Mutating a StringBuilder for one-character changes. Overkill. replaceFirstChar is faster and clearer.

Using + for many string concatenations. For one or two, fine. For loops, use StringBuilder or joinToString.

What's next

Episode 6: Jetpack Compose — ViewModel with mutableStateListOf. Manage a list of items in a Compose UI with reactive state.

Recap

replaceFirstChar { it.uppercaseChar() } is the modern Kotlin idiom for capitalizing the first letter. The deprecated capitalize() had locale issues. For empty strings, replaceFirstChar is safe; the manual s[0] + s.substring(1) needs an explicit guard. For predictable case-folding, pass Locale.ROOT. For title-case, split on spaces and replaceFirstChar each word.

Next episode: ViewModel with mutableStateListOf.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.