Collections
Creation
fun <T> listOf(vararg elements: T): List<T>
val names = listOf("Alice", "Bob")
Creates an immutable list; use when the contents won't change.
fun <T> mutableListOf(vararg elements: T): MutableList<T>
val queue = mutableListOf("task1"); queue.add("task2")
Creates a mutable list backed by ArrayList; use when you need add/remove.
fun <T> listOfNotNull(vararg elements: T?): List<T>
val items = listOfNotNull(a, b, null, c) // nulls dropped
Like listOf but silently drops null arguments; useful when building a list from optional values.
fun <T> buildList(builderAction: MutableList<T>.() -> Unit): List<T>
val list = buildList { add(1); if (flag) add(2) }
Builds an immutable list using a mutable builder DSL; ideal for conditional construction.
fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V>
val config = mapOf("host" to "localhost", "port" to "8080")
Creates an immutable map from key-to-value pairs.
fun <K, V> mutableMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V>
val cache = mutableMapOf<String, Int>(); cache["x"] = 1
Creates a mutable LinkedHashMap (preserves insertion order).
fun <K, V> buildMap(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V>
val m = buildMap { put("a", 1); put("b", 2) }
Builds an immutable map using a mutable builder block.
fun <T> setOf(vararg elements: T): Set<T>
val roles = setOf("admin", "user", "admin") // size = 2
Creates an immutable set that automatically deduplicates elements.
fun <T> mutableSetOf(vararg elements: T): MutableSet<T>
val seen = mutableSetOf<String>(); seen.add("a")
Creates a mutable LinkedHashSet (preserves insertion order, deduplicates).
fun <T> buildSet(builderAction: MutableSet<T>.() -> Unit): Set<T>
val allowed = buildSet { add("read"); if (isAdmin) add("write") }
Builds an immutable set using a mutable builder block; parity with buildList/buildMap.
fun <T> arrayOf(vararg elements: T): Array<T>
val arr = arrayOf("a", "b", "c")
Creates a typed Array; prefer listOf for most cases, arrayOf for Java interop.
fun intArrayOf(vararg elements: Int): IntArray [also: longArrayOf, byteArrayOf, doubleArrayOf]
val pixels = intArrayOf(0xFF0000, 0x00FF00)
Creates a primitive int array without boxing; use when performance matters or Java interop requires it.
fun <T> emptyList(): List<T> / emptyMap() / emptySet()
fun getItems(): List<String> = emptyList()
Returns a shared singleton empty collection; prefer over listOf() for default return values.
Transformation
fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
users.map { it.email.lowercase() }
Transforms each element; returns a new list of the same size.
fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R>
rows.mapNotNull { it.toIntOrNull() } // skips non-numeric
Like map but filters out null results in one pass.
fun <T, R> Iterable<T>.mapIndexed(transform: (index: Int, T) -> R): List<R>
items.mapIndexed { i, v -> "$i: $v" }
Like map but also provides the element's index.
fun <T, R> Iterable<T>.mapIndexedNotNull(transform: (Int, T) -> R?): List<R>
lines.mapIndexedNotNull { i, l -> if (l.isNotBlank()) i to l else null }
Combines mapIndexed and filterNotNull in one pass; drops null results.
fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
orders.flatMap { it.items } // flatten list of lists
Maps each element to a collection, then flattens the results into a single list.
fun <T> Iterable<Iterable<T>>.flatten(): List<T>
listOf(listOf(1,2), listOf(3)).flatten() // [1,2,3]
Flattens a collection of collections into a single list; use when you already have nested collections.
fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>>
names.zip(scores) // [("Alice", 95), ("Bob", 87)]
Pairs elements by position; stops at the shorter collection.
fun <T> Iterable<T>.zipWithNext(transform: (T, T) -> R): List<R>
prices.zipWithNext { a, b -> b - a } // price deltas
Pairs each element with the next one; useful for computing consecutive differences.
fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>>
val (keys, vals) = pairs.unzip()
Splits a list of pairs into two separate lists.
fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>
users.associate { it.id to it.name }
Builds a map from elements by transforming each into a key-value pair.
fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K): Map<K, T>
users.associateBy { it.id } // Map<UserId, User>
Builds a map keyed by the selector; the value is the original element.
fun <T, V> Iterable<T>.associateWith(valueSelector: (T) -> V): Map<T, V>
userIds.associateWith { db.find(it) } // Map<Id, User>
Builds a map where the original element is the key and the selector provides the value.
fun <K, V, R> Map<K, V>.mapKeys(transform: (Map.Entry<K,V>) -> R): Map<R, V>
map.mapKeys { it.key.lowercase() } // normalise keys
Returns a new map with keys transformed; values unchanged. Duplicate keys after transform keep last value.
fun <K, V, R> Map<K, V>.mapValues(transform: (Map.Entry<K,V>) -> R): Map<K, R>
scores.mapValues { it.value * 1.1 } // scale all values
Returns a new map with values transformed; keys unchanged.
Filtering
fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
users.filter { it.isActive }
Returns a list of elements matching the predicate.
fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T>
events.filterNot { it.isCancelled }
Returns elements where the predicate is false; cleaner than filter { !it.x }.
fun <T : Any> Iterable<T?>.filterNotNull(): List<T>
results.filterNotNull() // drops nulls, narrows type
Removes nulls and narrows the type to non-nullable.
fun <reified R> Iterable<*>.filterIsInstance(): List<R>
events.filterIsInstance<ClickEvent>()
Keeps only elements of the given type; combines filter and cast safely.
fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>>
val (passed, failed) = students.partition { it.score >= 60 }
Splits into two lists: matching and non-matching, in one pass.
fun <T> Iterable<T>.take(n: Int): List<T>
leaderboard.take(10) // top 10
Returns the first n elements.
fun <T> Iterable<T>.drop(n: Int): List<T>
rows.drop(1) // skip header row
Returns all elements except the first n.
fun <T> Iterable<T>.takeLast(n: Int): List<T> / dropLast(n: Int): List<T>
log.takeLast(100) // last 100 lines
takeLast returns the last n elements; dropLast removes the last n elements.
fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T>
sorted.takeWhile { it.score > 90 } // top scorers
Takes elements from the front while the predicate holds; stops at first failure.
fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T>
log.dropWhile { it.level == DEBUG } // skip debug prefix
Drops elements from the front while the predicate holds; returns the rest.
Aggregation
fun <T, R> Iterable<T>.fold(initial: R, operation: (R, T) -> R): R
nums.fold(0) { acc, n -> acc + n } // sum
Accumulates a value starting from an initial; works on empty collections.
fun <T> Iterable<T>.reduce(operation: (T, T) -> T): T
nums.reduce { acc, n -> acc + n } // throws on empty!
Like fold but uses the first element as the initial value; throws on empty collections.
fun <T, R> Iterable<T>.runningFold(initial: R, operation: (R, T) -> R): List<R>
nums.runningFold(0) { acc, n -> acc + n } // running totals
Like fold but returns a list of all intermediate accumulator values including the initial.
fun <T, R> Iterable<T>.scan(initial: R, operation: (R, T) -> R): List<R>
prices.scan(0.0) { total, p -> total + p }
Alias for runningFold; produces a prefix-sum style list including the initial value.
fun <T> Iterable<T>.runningReduce(operation: (T, T) -> T): List<T>
nums.runningReduce { acc, n -> acc + n } // no initial value
Like runningFold but uses the first element as initial; result list is one shorter than input.
fun <T> Iterable<T>.sumOf(selector: (T) -> Int): Int
orders.sumOf { it.total }
Sums elements by a numeric selector; also available for Long, Double, BigDecimal.
fun <T> Iterable<T>.maxByOrNull(selector: (T) -> Comparable): T?
products.maxByOrNull { it.price }
Returns the element with the largest selector value, or null if the collection is empty.
fun <T> Iterable<T>.minByOrNull(selector: (T) -> Comparable): T?
tasks.minByOrNull { it.priority }
Returns the element with the smallest selector value, or null if empty.
fun <T : Comparable<T>> Iterable<T>.maxOrNull(): T? / minOrNull(): T?
scores.maxOrNull(); temps.minOrNull()
Returns the largest/smallest element directly (no selector); null on empty. Use instead of deprecated max()/min().
fun <T> Iterable<T>.average(): Double
scores.average() // arithmetic mean; NaN on empty
Returns the arithmetic mean; returns NaN if the collection is empty.
fun <T> Iterable<T>.count(predicate: (T) -> Boolean = { true }): Int
users.count { it.isAdmin }
Counts matching elements; without predicate counts all.
fun <T> Iterable<T>.joinToString(separator: String = ", ", ...): String
names.joinToString(separator = ", ", prefix = "[", postfix = "]")
Joins elements into a string with separator, optional prefix/postfix/transform.
Grouping
fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>
employees.groupBy { it.department }
Groups elements by key into a Map; each key maps to a list of matching elements.
fun <T, K> Iterable<T>.groupingBy(keySelector: (T) -> K): Grouping<T, K>
words.groupingBy { it.first() }.eachCount()
Creates a lazy Grouping; chain with eachCount/fold/aggregate for efficient single-pass grouping.
fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
words.groupingBy { it }.eachCount() // word frequency map
Counts elements per group; the most common Grouping terminal.
fun <T, K, R> Grouping<T, K>.fold(initialValue: R, operation: (R, T) -> R): Map<K, R>
sales.groupingBy { it.region }.fold(0.0) { acc, s -> acc + s.amount }
Folds within each group simultaneously in a single pass.
fun <T, K, R> Grouping<T, K>.aggregate(operation: (key, acc: R?, T, Boolean) -> R): Map<K, R>
items.groupingBy { it.type }.aggregate { _, acc, el, first -> if (first) el.value else acc!! + el.value }
Most flexible Grouping terminal; handles first-element initialization explicitly.
Search
fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T?
users.find { it.email == email }
Returns the first matching element or null; alias for firstOrNull.
fun <T> Iterable<T>.findLast(predicate: (T) -> Boolean): T?
log.findLast { it.startsWith("ERROR") }
Returns the last matching element or null.
fun <T> Iterable<T>.first(predicate: (T) -> Boolean = ...): T
users.first { it.isAdmin } // throws if none
Returns the first match; throws NoSuchElementException if not found.
fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T?
users.firstOrNull { it.isAdmin } ?: defaultAdmin()
Returns the first match or null; use with ?: for safe fallbacks.
fun <T> Iterable<T>.last(predicate: (T) -> Boolean = ...): T / lastOrNull(...): T?
events.last { it.type == Click }; events.lastOrNull { it.type == Click }
Returns the last matching element; last throws on empty/no match, lastOrNull returns null.
fun <T> Iterable<T>.single(predicate: (T) -> Boolean): T
configs.single { it.env == "prod" } // throws if 0 or 2+
Returns the one matching element; throws if zero or more than one match.
fun <T> Iterable<T>.singleOrNull(predicate: (T) -> Boolean): T?
results.singleOrNull { it.isPrimary }
Returns the single matching element, or null if zero or more than one match.
fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean
if (users.any { it.isBanned }) blockRequest()
Returns true if at least one element matches.
fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean
val allPaid = invoices.all { it.isPaid }
Returns true only if every element matches; true for empty collections.
fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean
errors.none { it.isCritical }
Returns true if no elements match; cleaner than !any { }.
fun <T> Iterable<T>.contains(element: T): Boolean / indexOf(element: T): Int
items.contains(target); items.indexOf(target) // -1 if absent
contains checks membership; indexOf returns position or -1.
fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int
rows.indexOfFirst { it.startsWith("#") }
Returns the index of the first matching element, or -1.
fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int
tokens.indexOfLast { it == "}" }
Returns the index of the last matching element, or -1.
fun <T> List<T>.getOrNull(index: Int): T? / getOrElse(index: Int, defaultValue: (Int) -> T): T
args.getOrNull(1); args.getOrElse(2) { "default" }
Safe index access; getOrNull returns null, getOrElse calls the lambda for out-of-bounds indices.
fun <T> Collection<T>.random(): T / randomOrNull(): T?
options.random() // throws on empty; options.randomOrNull()
Returns a random element; random throws on empty, randomOrNull returns null.
Ordering
fun <T : Comparable<T>> Iterable<T>.sorted(): List<T>
scores.sorted() // natural ascending
Returns a new sorted list in natural ascending order.
fun <T : Comparable<T>> Iterable<T>.sortedDescending(): List<T>
scores.sortedDescending() // largest first
Sorts in natural descending order; shortcut for sorted().reversed().
fun <T> Iterable<T>.sortedBy(selector: (T) -> Comparable?): List<T>
users.sortedBy { it.lastName }
Sorts by a computed key in ascending order.
fun <T> Iterable<T>.sortedByDescending(selector: (T) -> Comparable?): List<T>
posts.sortedByDescending { it.createdAt }
Sorts by key in descending order; newest-first pattern.
fun <T> Iterable<T>.sortedWith(comparator: Comparator<T>): List<T>
files.sortedWith(compareBy({ it.dir }, { it.name }))
Sorts using a custom Comparator; chain compareBy for multi-key sort.
fun <T> compareBy(vararg selectors: (T) -> Comparable?): Comparator<T>
compareBy<Person>({ it.lastName }, { it.firstName })
Creates a Comparator that compares by multiple keys in order; first key wins unless tied.
fun <T> Iterable<T>.reversed(): List<T>
chronological.reversed() // newest first
Returns a new list in reverse order.
fun <T> Iterable<T>.shuffled(): List<T>
deck.shuffled() // random order
Returns a new list with elements in random order.
Windowing
fun <T> Iterable<T>.windowed(size: Int, step: Int = 1): List<List<T>>
temps.windowed(7) { it.average() } // 7-day rolling avg
Produces sliding windows of a fixed size; step controls how far to advance each time.
fun <T> Iterable<T>.chunked(size: Int): List<List<T>>
ids.chunked(100) { chunk -> db.batchFetch(chunk) }
Splits into non-overlapping chunks of at most size; last chunk may be smaller.
Set Operations
fun <T> Iterable<T>.distinct(): List<T>
tags.distinct() // deduplicate
Returns a list with duplicates removed, preserving first-occurrence order.
fun <T> Iterable<T>.distinctBy(selector: (T) -> Any?): List<T>
users.distinctBy { it.email } // one per email
Deduplicates by a key; keeps first element for each unique key.
infix fun <T> Iterable<T>.intersect(other: Iterable<T>): Set<T>
groupA intersect groupB // common members
Returns elements present in both collections.
infix fun <T> Iterable<T>.union(other: Iterable<T>): Set<T>
setA union setB
Returns all elements from both collections, deduplicated.
infix fun <T> Iterable<T>.subtract(other: Iterable<T>): Set<T>
allUsers subtract bannedUsers
Returns elements in the first collection not present in the second.
Misc / Iteration
fun <T> Iterable<T>.forEach(action: (T) -> Unit)
items.forEach { println(it) }
Iterates over elements for side effects; prefer for-in for simple cases.
fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit)
lines.forEachIndexed { i, line -> println("$i: $line") }
Like forEach but provides the index; useful for printing numbered lists.
fun <T> Iterable<T>.onEach(action: (T) -> Unit): Iterable<T>
pipeline.onEach { logger.log(it) }.filter { it.valid }
Performs a side-effect on each element and returns the collection unchanged; good for logging in chains.
fun <T> Iterable<T>.onEachIndexed(action: (index: Int, T) -> Unit): Iterable<T>
items.onEachIndexed { i, v -> log.debug("$i=$v") }.filter { it.valid }
Like onEach but also provides the index; returns the collection unchanged for chaining.
fun <T> Iterable<T>.toList() / toSet() / toMap() / toMutableList() / toMutableSet() / toSortedSet()
sequence.toList(); readonlyList.toMutableList()
Converts between collection types; always produces a new independent copy.
operator fun <T> Collection<T>.plus(element: T): List<T> / minus(element: T): List<T>
val updated = items + newItem; val filtered = items - toRemove
Returns new lists with element appended or first occurrence removed; originals unchanged.
fun <T> Iterable<T>.withIndex(): Iterable<IndexedValue<T>>
for ((i, v) in list.withIndex()) println("$i: $v")
Wraps each element with its index; destructures cleanly in for loops.
Strings
fun String.trim(): String / trimStart(): String / trimEnd(): String
" hello ".trim(); " hello ".trimStart(); " hello ".trimEnd()
trim removes both sides; trimStart removes leading only; trimEnd removes trailing only.
fun String.trimIndent(): String
val s = """
line1
line2
""".trimIndent()
Removes the common leading whitespace prefix from all lines in a multiline string.
fun String.trimMargin(marginPrefix: String = "|"): String
"""
|SELECT *
|FROM users
""".trimMargin()
Strips leading whitespace and the margin prefix character from each line.
fun String.split(vararg delimiters: String, limit: Int = 0): List<String>
"a,b,c".split(",") // ["a","b","c"]
Splits by delimiters; limit caps the number of parts; last part contains the remainder.
fun String.lines(): List<String>
fileContent.lines().filter { it.isNotBlank() }
Splits by line terminators (\r\n, \n, \r); handles all platforms.
fun String.chunked(size: Int): List<String>
hex.chunked(2) // ["FF", "0A", ...]
Splits a string into chunks of at most size characters; last chunk may be shorter.
fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String
template.replace("{{name}}", userName)
Returns a new string with all occurrences of oldValue replaced.
fun String.replaceFirst(oldValue: String, newValue: String): String
csv.replaceFirst(",", ";") // only first comma
Replaces only the first occurrence of the old value.
fun String.replaceRange(range: IntRange, replacement: String): String
s.replaceRange(0..3, "NEW")
Replaces the substring at the specified index range.
fun String.replaceAfter(delimiter: String, replacement: String): String
"user@old.com".replaceAfter("@", "new.com")
Replaces everything after the first occurrence of delimiter.
fun String.replaceBefore(delimiter: String, replacement: String): String
"old@example.com".replaceBefore("@", "new")
Replaces everything before the first occurrence of delimiter.
fun String.replaceAfterLast(delimiter: String, replacement: String): String
path.replaceAfterLast("/", "newfile.txt")
Replaces everything after the last occurrence of delimiter.
fun String.replaceFirstChar(transform: (Char) -> CharSequence): String
word.replaceFirstChar { it.uppercase() } // capitalize (non-deprecated)
Transforms only the first character; use instead of deprecated capitalize().
fun String.startsWith(prefix: String, ignoreCase: Boolean = false): Boolean
url.startsWith("https")
Checks if the string begins with the given prefix.
fun String.endsWith(suffix: String, ignoreCase: Boolean = false): Boolean
file.endsWith(".kt")
Checks if the string ends with the given suffix.
fun String.contains(other: String, ignoreCase: Boolean = false): Boolean
haystack.contains("needle", ignoreCase = true)
Checks if the string contains the given substring.
fun String.matches(regex: Regex): Boolean
email.matches(Regex("""[\w.]+@[\w.]+"""))
Returns true if the entire string matches the regex (anchored match, not partial).
fun String.padStart(length: Int, padChar: Char = ' '): String
num.toString().padStart(5, '0') // "00042"
Left-pads the string to at least length characters with padChar.
fun String.padEnd(length: Int, padChar: Char = ' '): String
label.padEnd(20, '.') // "Name................"
Right-pads the string to at least length characters with padChar.
fun String.uppercase(): String / lowercase(): String / uppercaseChar() / lowercaseChar()
input.lowercase().trim(); name[0].uppercaseChar() // Char variant
String variants convert the whole string; Char variants convert a single character.
fun String.toInt() / toIntOrNull() / toLong() / toLongOrNull() / toDouble() / toDoubleOrNull() / toFloatOrNull() / toBooleanStrict()
userInput.toIntOrNull() ?: error("not a number"); "true".toBooleanStrict()
Parse string to number/boolean; OrNull variants return null on bad input; toBooleanStrict only accepts "true"/"false".
fun String.toBoolean(): Boolean
"TRUE".toBoolean() // true (case-insensitive); "yes".toBoolean() // false
Returns true only if the string equals "true" (case-insensitive); anything else returns false — unlike toBooleanStrict which throws.
fun String.repeat(n: Int): String
"-".repeat(40) // divider line
Repeats the string n times.
fun String.reversed(): String
"hello".reversed() // "olleh"
Returns the string with characters in reverse order.
fun String.substring(startIndex: Int, endIndex: Int = length): String
s.substring(0, 5) // first 5 chars
Extracts a substring by index range; endIndex is exclusive.
fun String.substringBefore(delimiter: String): String
"user@example.com".substringBefore("@") // "user"
Returns the portion before the first occurrence of delimiter.
fun String.substringAfter(delimiter: String): String
"user@example.com".substringAfter("@") // "example.com"
Returns the portion after the first occurrence of delimiter.
fun String.substringBeforeLast(delimiter: String): String
"/path/to/file.txt".substringBeforeLast(".") // "/path/to/file"
Returns the portion before the last occurrence of delimiter.
fun String.substringAfterLast(delimiter: String): String
"/path/to/file.txt".substringAfterLast("/") // "file.txt"
Returns the portion after the last occurrence; useful for extracting file names from paths.
fun String.removePrefix(prefix: String): String / removeSuffix(suffix: String): String
"#comment".removePrefix("#"); "file.kt".removeSuffix(".kt")
Removes the prefix/suffix if present; returns the string unchanged if not found.
fun String.isEmpty() / isBlank() / isNotEmpty() / isNotBlank(): Boolean
if (input.isBlank()) return error("required")
isEmpty = length 0; isBlank = empty or whitespace only; prefer isBlank for user input validation.
fun String.ifEmpty(defaultValue: () -> String): String
env.ifEmpty { "development" }
Returns the string if not empty, otherwise calls and returns the lambda result.
fun String.ifBlank(defaultValue: () -> String): String
name.ifBlank { "Anonymous" }
Returns the string if not blank, otherwise the lambda result; great for display fallbacks.
"template ${expression}" / String.format(vararg args: Any?)
"Hello, $name! Score: ${score * 100}"; "%.2f".format(price)
String templates (${}) are the idiomatic Kotlin way; format() is useful for printf-style numeric formatting.
Sequences
fun <T> Iterable<T>.asSequence(): Sequence<T>
list.asSequence().filter { }.map { }.first()
Converts a collection to a lazy sequence; intermediate ops don't allocate new lists — use for long chains on large collections.
fun <T> sequenceOf(vararg elements: T): Sequence<T>
sequenceOf(1, 2, 3).map { it * 2 }.toList()
Creates a sequence directly from values; lazy equivalent of listOf followed by asSequence.
fun <T : Any> generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T>
generateSequence(1) { it * 2 }.take(10).toList()
Generates an infinite (or terminating when null is returned) sequence from a seed and a step function.
fun <T> sequence(block: suspend SequenceScope<T>.() -> Unit): Sequence<T>
val fibs = sequence { var a=0; var b=1; while(true) { yield(a); val c=a+b; a=b; b=c } }
Builds a lazy sequence using yield/yieldAll in a coroutine-like builder; perfect for complex iteration logic.
Lazy operators: map / filter / filterNot / filterNotNull / flatMap / mapNotNull / mapIndexed
bigList.asSequence().filter { it.isActive }.map { it.name }.take(10).toList()
All collection operators work lazily on sequences; no intermediate list allocations — chaining many ops is efficient.
Lazy operators: take / drop / takeWhile / dropWhile / zip / zipWithNext / windowed / chunked
seq.windowed(3).map { it.average() }.take(1).first()
Windowing and slicing operators are lazy on sequences; combine with take for efficient short-circuit evaluation.
Lazy operators: distinct / distinctBy / sorted / sortedBy / onEach / constrainOnce
seq.distinct().sortedBy { it.name }.onEach { log(it) }.toList()
distinct/sorted force full iteration internally; use them as late as possible in the chain to preserve laziness.
Terminal ops: toList() / toSet() / first() / firstOrNull() / last() / lastOrNull() / single() / find() / findLast()
seq.filter { it > 0 }.first() // short-circuits immediately
Terminals trigger evaluation; first/find short-circuit so only elements up to the match are processed.
Terminal ops: count() / fold() / reduce() / scan() / runningFold() / sum() / sumOf() / average() / any() / all() / none() / joinToString() / forEach()
seq.filter { it.valid }.sumOf { it.value }
Aggregating terminals consume the full sequence once; they are the only terminals that don't short-circuit.
Scope Functions
fun <T, R> T.let(block: (T) -> R): R
user?.let { sendEmail(it.email) } // null-safe call
Runs block with the object as it; returns block result. Use for null checks, transformations, and scoped variables.
fun <T, R> T.run(block: T.() -> R): R
val result = config.run { host + ":" + port }
Runs block with the object as this; returns block result. Use to compute a value using the object's properties.
fun <T> T.apply(block: T.() -> Unit): T
val btn = Button().apply { text = "OK"; isEnabled = true }
Runs block as this, returns the original object. Classic builder/configuration pattern.
fun <T> T.also(block: (T) -> Unit): T
items.also { log.debug("fetched ${it.size}") }.filter { it.valid }
Runs block with it, returns original object. Use for side-effects (logging, validation) mid-chain.
fun <T, R> with(receiver: T, block: T.() -> R): R
val html = with(builder) { head { }; body { }; build() }
Not an extension; calls block with receiver as this, returns result. Use when operating on an object without extension syntax.
fun <T> T.takeIf(predicate: (T) -> Boolean): T?
input.takeIf { it.isNotBlank() } ?: "default"
Returns the receiver if the predicate holds, null otherwise; clean alternative to if/else chains on a single value.
fun <T> T.takeUnless(predicate: (T) -> Boolean): T?
response.takeUnless { it.isError } ?: handleError(response)
Inverse of takeIf; returns null when the predicate holds.
I/O
fun readLine(): String?
val input = readLine() ?: error("EOF")
Reads one line from stdin; returns null at end of input.
fun File.readText(charset: Charset = UTF_8): String
val content = File("config.json").readText()
Reads entire file content as a string; fine for small files.
fun File.readLines(charset: Charset = UTF_8): List<String>
File("data.csv").readLines().drop(1) // skip header
Reads all lines into a list; closes the file automatically.
fun File.forEachLine(charset: Charset = UTF_8, action: (String) -> Unit)
File("huge.log").forEachLine { process(it) }
Streams lines one at a time without loading the whole file; use for large files.
fun File.useLines(charset: Charset = UTF_8, block: (Sequence<String>) -> T): T
File("large.csv").useLines { lines -> lines.filter { it.startsWith("A") }.toList() }
Provides a lazy Sequence of lines and auto-closes the file when done; best for large files with complex filtering.
fun File.writeText(text: String, charset: Charset = UTF_8)
File("out.txt").writeText(result)
Writes (overwrites) file content as a string.
fun File.appendText(text: String, charset: Charset = UTF_8)
File("app.log").appendText("$timestamp $msg\n")
Appends text to a file without truncating existing content.
fun File.writeBytes(array: ByteArray) / readBytes(): ByteArray
File("img.png").writeBytes(bytes); File("img.png").readBytes()
Binary read/write; readBytes loads entire file into memory — use for small binary files.
fun <T : Closeable, R> T.use(block: (T) -> R): R
FileInputStream("f").use { stream -> stream.read() }
Automatically closes the resource after the block, even on exception; Kotlin's try-with-resources.
fun File.bufferedReader(charset: Charset = UTF_8): BufferedReader
File("big.txt").bufferedReader().use { it.lineSequence().forEach { } }
Returns a buffered reader; pair with use {} for safe resource management.
fun File.bufferedWriter(charset: Charset = UTF_8): BufferedWriter / printWriter(): PrintWriter
File("out.txt").bufferedWriter().use { it.write(line) }
Returns a buffered writer for efficient line-by-line writing; printWriter adds println/printf support.
Kotlin Stdlib — Advanced (Regex · Ranges · Delegates · Math · Result · Collections extras)
Regex
class Regex(pattern: String, options: Set<RegexOption> = emptySet())
val re = Regex("""\d{4}-\d{2}-\d{2}""")
Compiles a regular expression; reuse instances — construction is expensive.
fun Regex.find(input: CharSequence, startIndex: Int = 0): MatchResult?
re.find(text)?.value
Returns the first match or null.
fun Regex.findAll(input: CharSequence): Sequence<MatchResult>
re.findAll(text).map { it.value }.toList()
Returns a lazy sequence of all non-overlapping matches.
fun Regex.matches(input: CharSequence): Boolean / containsMatchIn(input): Boolean
re.matches(entire); re.containsMatchIn(text) // partial match
matches checks the entire string; containsMatchIn checks anywhere in the string.
fun Regex.replace(input: CharSequence, replacement: String): String
Regex("""\s+""").replace(input, " ") // collapse whitespace
Replaces all matches with the replacement string; use $1 for capture group backreferences.
MatchResult.groupValues: List<String>
val m = Regex("""(\d{4})-(\d{2})""").find(s)!!; m.groupValues[1]
List of all captured group values; index 0 is the full match, groups start at 1.
fun Regex.matchEntire(input: CharSequence): MatchResult?
val (year, month, day) = Regex("""(\d{4})-(\d{2})-(\d{2})""").matchEntire(s)!!.destructured
Matches the entire string and returns captured groups; destructured unpacks groups into variables.
Ranges
operator fun Int.rangeTo(to: Int): IntRange [also: until, downTo, step]
for (i in 1..10) { } // inclusive; for (i in 0 until n) { } // exclusive upper
.. is inclusive on both ends; until excludes the upper bound; downTo reverses; step skips elements.
fun <T : Comparable<T>> T.coerceIn(minimumValue: T, maximumValue: T): T
progress.coerceIn(0, 100) // clamp to [0,100]
Clamps the value to the given range; replaces manual min/max chaining.
fun <T : Comparable<T>> T.coerceAtLeast(minimumValue: T): T / coerceAtMost(maximumValue: T): T
x.coerceAtLeast(0) // clamp to ≥ 0; x.coerceAtMost(100) // clamp to ≤ 100
One-sided clamping; use when you only need a minimum or maximum bound.
fun IntRange.random(): Int / randomOrNull(): Int?
(1..6).random() // dice roll
Picks a random value within the range.
Property Delegates
fun <T> lazy(initializer: () -> T): Lazy<T>
val db: Database by lazy { connectDb() }
Computes the value on first access and caches it; thread-safe by default (LazyThreadSafetyMode.SYNCHRONIZED).
fun <T> observable(initialValue: T, onChange: (prop, old, new) -> Unit): ReadWriteProperty<*, T>
var name: String by observable("") { _, old, new -> onNameChange(old, new) }
Calls a callback whenever the property value changes.
fun <T> vetoable(initialValue: T, onChange: (prop, old, new) -> Boolean): ReadWriteProperty<*, T>
var age: Int by vetoable(0) { _, _, new -> new >= 0 }
Like observable but can reject a new value by returning false from the callback.
operator fun <T> Map<String, *>.getValue(thisRef: Any?, property: KProperty<*>): T
val name: String by map; var age: Int by mutableMap
Delegates property reads/writes to a Map; the property name becomes the key.
Type Checks
is / as / as? — smart casts and safe casts
if (x is String) x.length; val s = x as? String ?: return
is smart-casts inside the branch; as throws on failure; as? returns null on failure — always prefer as?.
Math (kotlin.math.*)
abs / ceil / floor / round / sqrt / pow / sign / min / max / PI / E
import kotlin.math.*; sqrt(2.0); abs(-5); 2.0.pow(10); round(3.7)
Standard math functions; import kotlin.math.* to avoid qualification. pow is an extension on Double.
Result / Error Handling
fun <T> runCatching(block: () -> T): Result<T>
val result = runCatching { riskyOp() }
Wraps a block in a Result; never throws — chains instead of try/catch.
fun <T> Result<T>.getOrElse(onFailure: (Throwable) -> T): T
runCatching { parse(s) }.getOrElse { defaultValue }
Returns the value on success, or calls the fallback lambda on failure.
fun <T> Result<T>.getOrDefault(defaultValue: T): T / getOrThrow(): T / getOrNull(): T?
result.getOrNull() ?: fallback(); result.getOrThrow()
getOrNull returns null on failure; getOrDefault uses a static fallback; getOrThrow re-throws.
fun <T, R> Result<T>.map(transform: (T) -> R): Result<R> / mapCatching(transform): Result<R>
runCatching { fetch() }.mapCatching { parse(it) }.getOrThrow()
map transforms the value; mapCatching also catches exceptions in the transform.
fun <T> Result<T>.onSuccess(action: (T) -> Unit): Result<T> / onFailure(action: (Throwable) -> Unit): Result<T>
result.onSuccess { log(it) }.onFailure { reportError(it) }
Side-effect callbacks for success/failure; both return the original Result unchanged for chaining.
fun <T> Result<T>.recover(transform: (Throwable) -> T): Result<T>
result.recover { e -> if (e is NetworkError) cached() else throw e }
Converts a failure to a success value; like catch for a Result chain.
Collections Extras
class IntArray(size: Int) / ByteArray / LongArray / DoubleArray / FloatArray
val buf = ByteArray(1024); val squares = IntArray(10) { it * it }
Primitive arrays with no boxing overhead; prefer over Array<Int> for performance-sensitive numeric code.
fun <T> Array<T>.contentEquals(other: Array<T>): Boolean / contentToString(): String
arr1.contentEquals(arr2); arr.contentToString() // "[1, 2, 3]"
Structural equality and string representation for arrays; regular == and toString() don't work correctly on arrays.
val Array<T>.indices: IntRange / lastIndex: Int
for (i in arr.indices) arr[i] = transform(arr[i])
Convenient range for index-based iteration; safer than 0..arr.size-1 (handles empty arrays).
fun <T> Iterable<T>.withIndex(): Iterable<IndexedValue<T>>
for ((i, v) in list.withIndex()) println("$i: $v")
Wraps each element with its index; destructures cleanly in for loops.
Miscellaneous
fun require(value: Boolean, lazyMessage: () -> Any = ...)
require(age >= 0) { "age must be non-negative, got $age" }
Throws IllegalArgumentException if false; use for parameter validation at function entry.
fun requireNotNull<T : Any>(value: T?, lazyMessage: () -> Any = ...): T
val token = requireNotNull(headers["Authorization"]) { "missing auth" }
Throws IllegalArgumentException if null, else returns the non-null value with smart-cast.
fun check(value: Boolean, lazyMessage: () -> Any = ...)
check(isInitialized) { "call init() first" }
Throws IllegalStateException if false; use for state invariants (not argument validation).
fun checkNotNull<T : Any>(value: T?, lazyMessage: () -> Any = ...): T
val conn = checkNotNull(connection) { "not connected" }
Like requireNotNull but for state checks; throws IllegalStateException.
fun error(message: Any): Nothing
val x = map[key] ?: error("missing key: $key")
Throws IllegalStateException; returns Nothing so it works as an expression after ?:.
fun TODO(reason: String = "..."): Nothing
fun notYetImpl(): String = TODO("implement in next sprint")
Throws NotImplementedError with a message; useful for stubs during development.
fun repeat(times: Int, action: (Int) -> Unit)
repeat(3) { println("attempt $it") }
Executes the block times times, passing the 0-based iteration index.
Coroutines — Builders
fun CoroutineScope.launch(context, start, block: suspend CoroutineScope.() -> Unit): Job
scope.launch { delay(1000); println("done") }
Starts a fire-and-forget coroutine; returns a Job for cancellation/joining.
fun <T> CoroutineScope.async(context, start, block: suspend () -> T): Deferred<T>
val a = async { fetchUser() }; val b = async { fetchPosts() }; a.await() to b.await()
Starts a coroutine that returns a value; concurrent tasks run in parallel until awaited.
fun <T> runBlocking(context, block: suspend CoroutineScope.() -> T): T
fun main() = runBlocking { launch { } }
Bridges blocking and coroutine worlds by blocking the current thread. Use only in main() or tests.
suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R
coroutineScope { val j1 = launch { }; val j2 = launch { } }
Creates a child scope; if any child fails, all siblings are cancelled and the exception propagates.
suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R
supervisorScope { repeat(10) { launch { riskyTask(it) } } }
Like coroutineScope but child failures don't cancel siblings; use for independent parallel tasks.
Context & Dispatchers
suspend fun <T> withContext(context: CoroutineContext, block: suspend () -> T): T
val data = withContext(Dispatchers.IO) { readFile() }
Switches dispatcher for the block and returns the result; the primary way to do blocking I/O in a coroutine.
Dispatchers.IO / Default / Main / Unconfined
withContext(Dispatchers.Default) { heavyCpuWork() }
IO = thread pool for blocking ops (64 threads); Default = CPU thread pool; Main = UI thread; Unconfined = no thread pinning (rare).
suspend fun Deferred<T>.await(): T / Job.join() / awaitAll(vararg deferred) / joinAll()
awaitAll(d1, d2, d3) // concurrent wait for all
await() suspends until a Deferred has a value; awaitAll waits for multiple in parallel.
Timing
suspend fun delay(timeMillis: Long)
delay(1_000) // non-blocking 1s pause
Suspends without blocking the thread; unlike Thread.sleep(), the thread is released to process other coroutines.
suspend fun <T> withTimeout(timeMillis: Long, block: suspend () -> T): T
withTimeout(5_000) { remoteCall() } // throws TimeoutCancellationException
Cancels the block and throws TimeoutCancellationException if it exceeds the timeout.
suspend fun <T> withTimeoutOrNull(timeMillis: Long, block: suspend () -> T): T?
withTimeoutOrNull(3_000) { fetch() } ?: cachedValue()
Like withTimeout but returns null instead of throwing; cleaner for optional operations.
Flow
fun <T> flow(block: suspend FlowCollector<T>.() -> Unit): Flow<T>
val f = flow { for (i in 1..5) { emit(i); delay(100) } }
Creates a cold flow; the block only runs when someone collects it.
fun <T> flowOf(vararg elements: T): Flow<T> / Iterable<T>.asFlow() / (Range).asFlow()
(1..100).asFlow().filter { it % 2 == 0 }.collect { println(it) }
Convenience constructors for flows from known values, iterables, or ranges.
suspend fun <T> Flow<T>.collect(action: suspend (T) -> Unit)
flow.collect { value -> process(value) }
Terminal operator that triggers the flow and processes each emitted value sequentially.
suspend fun <T> Flow<T>.collectLatest(action: suspend (T) -> Unit)
searchQuery.collectLatest { query -> search(query) } // cancels slow search on new input
Like collect but cancels processing of the previous value when a new one arrives.
suspend fun <T> Flow<T>.toList() / toSet() / first() / firstOrNull() / single() / last() / count()
flow.filter { it.valid }.first() // collect only until first match
Terminal operators that materialize flows into collections or single values; first/single short-circuit.
fun <T, R> Flow<T>.map(transform: suspend (T) -> R): Flow<R>
priceFlow.map { it * taxRate }
Transforms each emitted value; same semantics as collection map but lazy and async.
fun <T> Flow<T>.filter(predicate: suspend (T) -> Boolean): Flow<T> / filterNot / filterIsInstance / mapNotNull
eventFlow.filterIsInstance<ClickEvent>().mapNotNull { it.target }
Filtering operators mirror collection equivalents; filterIsInstance narrows the type.
fun <T, R> Flow<T>.transform(transform: suspend FlowCollector<R>.(T) -> Unit): Flow<R>
flow.transform { v -> emit(v); emit(-v) } // emit multiple per input
Most flexible flow operator; can emit zero, one, or multiple values per incoming element.
fun <T> Flow<T>.onEach / onStart / onCompletion / catch
apiFlow.onStart { showSpinner() }.catch { e -> emit(fallback()) }.onCompletion { hideSpinner() }
Lifecycle hooks; catch can emit fallback values — it only catches upstream exceptions.
fun <T> Flow<T>.take(count: Int) / drop(count: Int) / takeWhile / dropWhile / distinctUntilChanged
flow.distinctUntilChanged().take(10) // skip duplicate consecutive values, stop at 10
Windowing and deduplication operators; distinctUntilChanged avoids unnecessary downstream re-processing.
fun <T> Flow<T>.debounce(timeoutMillis: Long): Flow<T>
keystrokes.debounce(300).collect { search(it) } // search-as-you-type
Emits only after the flow has been silent for the timeout period; classic typeahead pattern.
fun <T> Flow<T>.sample(periodMillis: Long): Flow<T>
sensorFlow.sample(100) // emit at most every 100ms
Periodically samples the flow; unlike debounce, emits on a fixed interval rather than waiting for silence.
fun <T1, T2, R> combine(flow1, flow2, transform: (T1, T2) -> R): Flow<R>
combine(userFlow, settingsFlow) { user, settings -> render(user, settings) }
Emits whenever either upstream emits, using the latest value from the other; great for reactive UI state.
fun <T, R> Flow<T>.zip(other: Flow<R>, transform: (T, R) -> ...): Flow<...>
requestFlow.zip(responseFlow) { req, res -> req to res }
Pairs elements by position; stops when either flow ends. Unlike combine, waits for both to emit each time.
fun <T> merge(vararg flows: Flow<T>): Flow<T>
merge(bluetoothEvents, wifiEvents).collect { }
Merges multiple flows into one; emissions from any source appear in the merged flow immediately.
fun <T, R> Flow<T>.flatMapLatest(transform: suspend (T) -> Flow<R>): Flow<R>
searchQuery.flatMapLatest { q -> searchApi(q) }
Cancels the previous inner flow when a new upstream value arrives; the canonical search-as-you-type pattern.
fun <T, R> Flow<T>.flatMapMerge(concurrency: Int = DEFAULT, transform: (T) -> Flow<R>): Flow<R>
ids.asFlow().flatMapMerge(4) { id -> fetchFlow(id) }
Runs inner flows concurrently up to concurrency limit; use for parallel fetching with backpressure.
fun <T, R> Flow<T>.flatMapConcat(transform: (T) -> Flow<R>): Flow<R>
pages.flatMapConcat { page -> fetchItems(page) } // sequential
Maps each value to an inner flow and collects them sequentially one at a time.
fun <T> Flow<T>.launchIn(scope: CoroutineScope): Job
flow.onEach { render(it) }.launchIn(viewModelScope)
Terminal operator that collects the flow in the given scope; equivalent to scope.launch { flow.collect() }.
Channels
class Channel<T>(capacity: Int = RENDEZVOUS)
val ch = Channel<Int>(Channel.BUFFERED); ch.send(1); ch.receive()
Queue for communicating between coroutines; RENDEZVOUS=0 (synchronous handoff), BUFFERED=64, UNLIMITED.
fun <E> CoroutineScope.produce(block: suspend ProducerScope<E>.() -> Unit): ReceiveChannel<E>
val chan = produce { for (i in 1..5) send(i) }
Creates a coroutine-backed producer channel; automatically closes when the block completes.
suspend fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit)
chan.consumeEach { process(it) } // auto-closes and cancels on exception
Iterates and consumes all channel elements; cancels the channel if the block throws.
fun <E> SendChannel<E>.trySend(element: E): ChannelResult<Unit> / ReceiveChannel.tryReceive(): ChannelResult<E>
val result = ch.trySend(event); if (result.isSuccess) { } // non-blocking
Non-suspending channel operations; return a result indicating success or failure rather than suspending.
fun <E> ReceiveChannel<E>.receiveAsFlow(): Flow<E> / consumeAsFlow(): Flow<E>
channel.receiveAsFlow().filter { it.isValid }.collect { }
Adapts a Channel to a Flow; receiveAsFlow allows multiple collectors, consumeAsFlow is for single collector only.
Exception Handling
val handler = CoroutineExceptionHandler { coroutineContext, throwable -> ... }
val scope = CoroutineScope(SupervisorJob() + handler); scope.launch { }
Top-level handler for uncaught exceptions from launch; does NOT catch async/await exceptions — use try/catch around await.
class SupervisorJob() : Job
CoroutineScope(SupervisorJob() + Dispatchers.Default)
A Job where child failures don't cancel the parent or siblings; used in long-lived scopes (ViewModel, Application).
// Always rethrow CancellationException
try { } catch (e: Exception) { if (e is CancellationException) throw e; handle(e) }
CancellationException is how structured concurrency propagates cancellation — swallowing it breaks scope cancellation.
Kotlin Coroutines — Advanced (Hot Flows · Select · Mutex · Semaphore · Job Lifecycle · Buffer · Testing)
Hot Flows
class MutableStateFlow<T>(value: T) : StateFlow<T>
val uiState = MutableStateFlow(UiState.Loading); uiState.value = UiState.Success(data)
Always has a current value; replays the latest to new collectors. The standard ViewModel state pattern.
class MutableSharedFlow<T>(replay: Int = 0) : SharedFlow<T>
val events = MutableSharedFlow<UiEvent>(); events.emit(UiEvent.ShowSnackbar)
Multicast; no stored value by default. Use for one-shot events (toasts, navigation commands).
fun <T> Flow<T>.stateIn(scope, started: SharingStarted, initialValue: T): StateFlow<T>
coldFlow.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initial)
Converts a cold Flow to a hot StateFlow; WhileSubscribed(5000) stops collecting when no subscribers for 5s.
fun <T> Flow<T>.shareIn(scope, started: SharingStarted, replay: Int = 0): SharedFlow<T>
apiFlow.shareIn(scope, SharingStarted.Eagerly, replay = 1)
Converts cold Flow to hot SharedFlow; replay caches the last N emissions for late collectors.
SharingStarted.Eagerly / Lazily / WhileSubscribed(stopTimeoutMillis)
SharingStarted.WhileSubscribed(5_000) // stop 5s after last collector
Controls when the upstream flow starts/stops; WhileSubscribed is best for Android ViewModels.
Callback-to-Flow
fun <T> callbackFlow(block: suspend ProducerScope<T>.() -> Unit): Flow<T>
callbackFlow { val cb = { v: T -> trySend(v) }; api.register(cb); awaitClose { api.unregister(cb) } }
Wraps callback-based APIs into a Flow; awaitClose is mandatory and runs when collection stops.
fun <T> channelFlow(block: suspend ProducerScope<T>.() -> Unit): Flow<T>
channelFlow { launch { send(compute1()) }; launch { send(compute2()) } }
Like callbackFlow but for bridging concurrent coroutine code to Flow; safe to launch child coroutines inside.
Select
suspend fun <R> select(builder: SelectBuilder<R>.() -> Unit): R
select { ch.onReceive { "recv: $it" }; ch.onSend(1) { "sent" }; onTimeout(100) { "timeout" } }
Waits for the first of multiple suspend operations to complete; first-wins race among channels, deferreds, or timeouts.
Synchronization
class Mutex(locked: Boolean = false)
mutex.withLock { sharedState++ } // coroutine-safe exclusive access
Suspending mutual exclusion; withLock acquires and releases automatically. Never use j.u.c.locks in coroutines.
fun Mutex.lock() / unlock() / tryLock(): Boolean / withLock(action): T
if (mutex.tryLock()) try { update() } finally { mutex.unlock() }
tryLock acquires without suspending (returns false if held); always pair manual lock/unlock with try/finally.
class Semaphore(permits: Int, acquiredPermits: Int = 0)
val sem = Semaphore(4); urls.map { async { sem.withPermit { fetch(it) } } }.awaitAll()
Limits concurrent access; withPermit(4) means at most 4 coroutines execute simultaneously.
Job Lifecycle & Cancellation
Job.cancel(cause?) / cancelAndJoin() / isActive / isCompleted / isCancelled
job.cancel(); job.join() // or: job.cancelAndJoin()
cancel signals cancellation; join waits for completion; cancelAndJoin does both atomically.
fun CoroutineScope.ensureActive() / suspend fun yield()
for (item in bigList) { ensureActive(); process(item) }
ensureActive throws CancellationException if cancelled; yield is a suspension point for cooperative cancellation in tight loops.
object NonCancellable : Job
withContext(NonCancellable) { db.rollback() } // runs even if scope is cancelling
Use in finally blocks to perform cleanup even when the surrounding coroutine is being cancelled.
CoroutineStart.LAZY — start the coroutine manually
val job = launch(start = CoroutineStart.LAZY) { }; job.start() // explicit start
LAZY defers execution until start() or join() is called; useful for pre-creating coroutines without running them.
Flow — Buffer & Backpressure
fun <T> Flow<T>.buffer(capacity: Int = BUFFERED): Flow<T>
fastProducer.buffer(100).collect { slowConsumer(it) }
Decouples producer from collector with a buffer; producer can run ahead while collector processes.
fun <T> Flow<T>.conflate(): Flow<T>
sensorFlow.conflate().collect { render(it) } // only latest sensor value
Drops intermediate values if the collector is slow; delivers only the most recent emission.
fun <T> Flow<T>.flowOn(context: CoroutineContext): Flow<T>
flow { emit(readFile()) }.flowOn(Dispatchers.IO).collect { }
Changes the dispatcher for all upstream operators; the collector runs on its own dispatcher unchanged.
fun <T> Flow<T>.retry(retries: Long, predicate: (Throwable) -> Boolean): Flow<T>
apiFlow.retry(3) { e -> e is IOException }
Retries the upstream flow on failure up to retries times; predicate decides which errors are retryable.
fun <T> Flow<T>.retryWhen(predicate: suspend (Throwable, Long) -> Boolean): Flow<T>
apiFlow.retryWhen { e, attempt -> e is IOException && attempt < 3 }
Like retry but provides the attempt count; use for exponential backoff logic.
Testing (kotlinx-coroutines-test)
fun runTest(block: suspend TestScope.() -> Unit)
@Test fun test() = runTest { delay(1_000); assertEquals(1, 1) }
Runs coroutines with virtual time; delay(1000) completes instantly in tests.
TestScope.advanceUntilIdle() / advanceTimeBy(ms) / runCurrent()
launch { delay(5_000); result = 42 }; advanceUntilIdle(); assertEquals(42, result)
Control virtual time; advanceUntilIdle runs all pending coroutines to completion before asserting.
class TestCoroutineDispatcher / UnconfinedTestDispatcher / StandardTestDispatcher
runTest(UnconfinedTestDispatcher()) { /* launch runs eagerly */ }
UnconfinedTestDispatcher runs coroutines eagerly (no need for advanceUntilIdle); StandardTestDispatcher is the default (lazy). Note: TestCoroutineDispatcher is deprecated in coroutines-test 1.6+; prefer StandardTestDispatcher or UnconfinedTestDispatcher.
Android / Platform (reference)
viewModelScope / lifecycleScope / MainScope()
viewModelScope.launch { } // auto-cancelled when ViewModel cleared
viewModelScope cancels on ViewModel.onCleared(); lifecycleScope cancels on Lifecycle DESTROYED; MainScope is manual.
fmt
func fmt.Printf(format string, a ...any) (n int, err error)
fmt.Printf("[%s] %s %s → %d (%v)\n", time.Now().Format(time.RFC3339), method, path, status, elapsed)
Writes formatted output to stdout; the workhorse for quick debugging and CLI programs.
func fmt.Fprintf(w io.Writer, format string, a ...any) (n int, err error)
fmt.Fprintf(w, "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n\r\n", code, http.StatusText(code), len(body))
Writes to any io.Writer — HTTP response writers, files, buffers — the same way as Printf.
func fmt.Sprintf(format string, a ...any) string
key := fmt.Sprintf("user:%d:session:%s", userID, sessionToken) // Redis key
Returns the formatted string rather than writing it; use for building keys, labels, or error messages.
func fmt.Println(a ...any) (n int, err error)
fmt.Println("listening on", addr) // spaces inserted automatically between args
Adds spaces between operands and appends a newline; handy for quick diagnostics when format strings are overkill.
func fmt.Fprintln(w io.Writer, a ...any) (n int, err error)
fmt.Fprintln(os.Stderr, "fatal:", err)
Like Println but to any writer; useful for writing error lines to stderr or a log file.
func fmt.Errorf(format string, a ...any) error
if err := db.QueryRow(q, id).Scan(&u); err != nil {
return nil, fmt.Errorf("fetchUser %d: %w", id, err)
}
Creates an error with context; %w wraps the original so callers can use errors.Is / errors.As.
func fmt.Sscanf(str string, format string, a ...any) (n int, err error)
var major, minor, patch int
fmt.Sscanf(versionStr, "%d.%d.%d", &major, &minor, &patch)
Parses structured text from a string using a scanf-style format; cleaner than splitting and Atoi for fixed layouts.
func fmt.Fscanf(r io.Reader, format string, a ...any) (n int, err error)
var op string; var amount float64
fmt.Fscanf(conn, "%s %f\n", &op, &amount)
Reads and parses formatted tokens from any reader; used for simple text-protocol parsing over a net.Conn or file.
func fmt.Fscan(r io.Reader, a ...any) (n int, err error)
var x, y float64
fmt.Fscan(r, &x, &y) // reads whitespace-separated tokens
Scans whitespace-separated values from a reader without a format string; convenient for space-delimited numeric input.
type fmt.Stringer interface { String() string }
func (s Status) String() string { return statusLabels[s] }
// fmt.Println(job.Status) now prints "pending" instead of "0"
Any type that implements String() is formatted with it by all fmt verbs; eliminates manual %s conversions.
func fmt.Sprint(a ...any) string
label := fmt.Sprint("worker-", workerID) // no format verbs needed
Concatenates args into a string with spaces between non-string adjacent values; use when you have mixed types but no format string.
func fmt.Sprintln(a ...any) string
msg := fmt.Sprintln("connected:", remoteAddr) // trailing \n included
Like Sprint but adds spaces between all args and appends a newline; useful when building lines for a log buffer.
func fmt.Fprint(w io.Writer, a ...any) (n int, err error)
fmt.Fprint(w, chunk) // write a pre-built chunk to an http.ResponseWriter
Writes string representations of args to w with no format string; useful when the value is already a string or Stringer.
strings
type strings.Builder struct{ ... } — WriteString(s string) / String() string / Reset() / Len() int
var b strings.Builder
for _, seg := range pathSegments {
b.WriteByte('/'); b.WriteString(seg)
}
return b.String()
Zero-allocation string builder; prefer over += in loops. Reset() reuses the buffer across calls.
func strings.Contains(s, substr string) bool
if strings.Contains(r.Header.Get("Content-Type"), "application/json") { ... }
Reports whether substr is anywhere in s; use for header/MIME sniffing and log filtering.
func strings.ContainsAny(s, chars string) bool
if strings.ContainsAny(username, "@/\\ ") {
return fmt.Errorf("username contains invalid characters")
}
Returns true if any Unicode code point in chars appears in s; handy for input validation against a forbidden character set.
func strings.HasPrefix(s, prefix string) bool / func strings.HasSuffix(s, suffix string) bool
if strings.HasPrefix(path, "/api/v2/") { handleV2(w, r) }
if strings.HasSuffix(filename, ".pb.go") { continue } // skip generated files
Check if s starts or ends with a given string; essential for routing decisions and file-extension filtering.
func strings.Cut(s, sep string) (before, after string, found bool)
host, port, ok := strings.Cut(addr, ":")
if !ok { return fmt.Errorf("invalid addr %q", addr) }
// "db.prod:5432" → "db.prod", "5432"
Splits around the first sep; cleaner than Index+slicing for host:port, key=value, or scheme://rest splits.
func strings.Fields(s string) []string
args := strings.Fields(cmdLine) // splits on any whitespace, trims leading/trailing
if len(args) == 0 { return fmt.Errorf("empty command") }
Splits on any whitespace and ignores leading/trailing whitespace; prefer over Split(s," ") for user-typed input.
func strings.FieldsFunc(s string, f func(rune) bool) []string
tokens := strings.FieldsFunc(csvLine, func(r rune) bool {
return r == ',' || r == ';'
})
Like Fields but splits wherever f returns true for a rune; useful for multi-delimiter tokenization.
func strings.Join(elems []string, sep string) string
placeholders := strings.Join(make([]string, len(ids)), ", ") // "?, ?, ?"
query := "SELECT * FROM users WHERE id IN (" + placeholders + ")"
Concatenates slice elements with sep between each; the idiomatic way to build comma-separated lists.
func strings.Split(s, sep string) []string
parts := strings.Split(r.URL.Path, "/") // "/api/users/42" → ["", "api", "users", "42"]
Splits at every occurrence of sep; note that a leading sep produces a leading empty string.
func strings.SplitN(s, sep string, n int) []string
kv := strings.SplitN(line, "=", 2) // "KEY=val=with=equals" → ["KEY", "val=with=equals"]
if len(kv) != 2 { continue }
Like Split but stops after n substrings; use n=2 for key=value parsing where values may contain the separator.
func strings.Replace(s, old, new string, n int) string / func strings.ReplaceAll(s, old, new string) string
safe := strings.ReplaceAll(userInput, "'", "''") // escape single quotes for SQL
slug := strings.ReplaceAll(strings.ToLower(title), " ", "-")
Replace replaces first n occurrences (n=-1 means all); ReplaceAll is shorthand for Replace(s,old,new,-1).
func strings.TrimSpace(s string) string
email := strings.TrimSpace(r.FormValue("email")) // strip accidental whitespace from form input
Removes leading and trailing whitespace (space, tab, newline, etc.); always trim before storing or comparing user input.
func strings.TrimPrefix(s, prefix string) string / func strings.TrimSuffix(s, suffix string) string
topic := strings.TrimPrefix(queueName, "events.") // "events.user.created" → "user.created"
base := strings.TrimSuffix(filename, ".tmpl")
Removes a specific prefix or suffix only if present; safer than slicing because it won't panic on short strings.
func strings.Trim(s, cutset string) string / func strings.TrimFunc(s string, f func(rune) bool) string
clean := strings.Trim(raw, "{}[] \t\n") // strip JSON delimiters from partial messages
alpha := strings.TrimFunc(token, func(r rune) bool { return !unicode.IsLetter(r) })
Trim removes any rune in cutset from both ends; TrimFunc removes runes while the predicate holds.
func strings.ToLower(s string) string / func strings.ToUpper(s string) string
row := db.QueryRow("SELECT id FROM users WHERE email = $1", strings.ToLower(email))
header := strings.ToUpper(method) // normalize HTTP verb from config
Case-fold an entire string using Unicode rules; lowercase before DB lookups or map keys so "Admin@Example.COM" matches.
func strings.Map(mapping func(rune) rune, s string) string
sanitized := strings.Map(func(r rune) rune {
if unicode.IsPunct(r) { return -1 } // -1 drops the rune
return unicode.ToLower(r)
}, userText)
Applies mapping to every rune; return -1 to drop a rune. More expressive than ReplaceAll for rune-level transforms.
func strings.EqualFold(s, t string) bool
if !strings.EqualFold(r.Header.Get("Upgrade"), "websocket") {
http.Error(w, "expected Upgrade: websocket", 400)
}
Case-insensitive equality without allocating; preferred over ToLower(a)==ToLower(b) for header and config comparisons.
func strings.Count(s, substr string) int / func strings.Index(s, substr string) int / func strings.LastIndex(s, substr string) int
depth := strings.Count(path, "/") // route depth
dotIdx := strings.LastIndex(filename, ".") // extension boundary
Count reports non-overlapping occurrences; Index / LastIndex return byte offsets (-1 if absent).
func strings.Repeat(s string, count int) string
padding := strings.Repeat("=", termWidth) // CLI separator line
indent := strings.Repeat(" ", nestLevel)
Returns s repeated count times; useful for generating separators, padding, or indentation strings.
func strings.NewReader(s string) *strings.Reader
resp, err := http.Post(url, "application/json", strings.NewReader(jsonPayload))
// strings.NewReader satisfies io.Reader without copying into []byte
Wraps a string as an io.Reader; use to pass an in-memory string to APIs that expect a reader (HTTP bodies, decoders).
strconv
func strconv.Atoi(s string) (int, error) / func strconv.Itoa(i int) string
userID, err := strconv.Atoi(r.PathValue("id"))
if err != nil { http.Error(w, "invalid id", 400); return }
header.Set("X-Request-ID", strconv.Itoa(requestID))
Atoi parses a decimal string to int; Itoa formats an int to string. Both are shortcuts for the common base-10 case.
func strconv.ParseInt(s string, base int, bitSize int) (int64, error)
perms, err := strconv.ParseInt(cfg.Get("file_mode"), 8, 32) // "0644" octal
if err != nil { return fmt.Errorf("parse file_mode: %w", err) }
Parses integers in any base (2–36); use base=0 to auto-detect 0x hex, 0o octal, 0b binary prefixes.
func strconv.ParseFloat(s string, bitSize int) (float64, error)
price, err := strconv.ParseFloat(fields[2], 64)
if err != nil { return fmt.Errorf("row %d price: %w", lineNo, err) }
Parses a floating-point string; bitSize=32 constrains to float32 range. Always check error — user CSV data is unreliable.
func strconv.ParseBool(str string) (bool, error)
debug, err := strconv.ParseBool(os.Getenv("DEBUG"))
if err != nil { debug = false } // "1","t","true","TRUE","T" → true
Accepts "1", "t", "T", "true", "TRUE", "True", "0", "f", "F", "false", "FALSE", "False"; useful for env-var flags.
func strconv.FormatInt(i int64, base int) string / func strconv.FormatFloat(f float64, fmt byte, prec, bitSize int) string
hexColor := "#" + strconv.FormatInt(int64(rgb), 16) // 16711680 → "#ff0000"
latStr := strconv.FormatFloat(coord.Lat, 'f', 6, 64) // "37.774929"
FormatInt converts to any base; FormatFloat's fmt byte controls notation: 'f' fixed, 'e' scientific, 'g' shortest.
func strconv.FormatBool(b bool) string
rec.Set("active", strconv.FormatBool(user.Active)) // writes "true" or "false" to CSV field
Converts bool to "true" or "false"; use instead of fmt.Sprintf("%v") when you only need the bool representation.
func strconv.AppendInt(dst []byte, i int64, base int) []byte
buf = strconv.AppendInt(buf, int64(statusCode), 10) // append without allocating a string
buf = append(buf, ' ')
Appends the string representation of i to dst without allocation; critical in hot paths like request-logging loops.
func strconv.Quote(s string) string / func strconv.Unquote(s string) (string, error)
log.Printf("received key %s", strconv.Quote(key)) // logs "k\x00ey" safely
val, err := strconv.Unquote(jsonStringToken) // strip outer quotes + unescape
Quote wraps a string in double quotes with Go escape sequences (safe for logging untrusted input); Unquote reverses it.
type strconv.NumError struct { Func string; Num string; Err error }
var numErr *strconv.NumError
if errors.As(err, &numErr) && numErr.Err == strconv.ErrRange {
return fmt.Errorf("value %q overflows int64", numErr.Num)
}
Returned by all Parse* functions on failure; Err is ErrRange (overflow) or ErrSyntax (not a valid number).
bytes
type bytes.Buffer — Write(p []byte) / WriteString(s string) / WriteByte(c byte) / Bytes() []byte / String() string / Reset() / Len() int
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil { return err }
w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
w.Write(buf.Bytes())
Growable byte buffer; execute templates into it first to capture length and avoid partial writes on error.
func bytes.NewBuffer(buf []byte) *bytes.Buffer / func bytes.NewBufferString(s string) *bytes.Buffer
buf := bytes.NewBuffer(rawFrame) // wrap received []byte for sequential reading
hdr := make([]byte, 4); buf.Read(hdr)
NewBuffer seeds the buffer with existing data for reading; NewBufferString does the same from a string.
func bytes.Contains(b, subslice []byte) bool / func bytes.HasPrefix(b, prefix []byte) bool / func bytes.HasSuffix(b, suffix []byte) bool
if bytes.HasPrefix(line, []byte("#")) { continue } // skip comment lines without string conversion
if bytes.Contains(body, []byte("</html>")) { parseHTML(body) }
Byte-slice equivalents of strings functions; use when working with []byte from io.ReadAll or net.Conn to avoid allocations.
func bytes.Cut(s, sep []byte) (before, after []byte, found bool)
key, val, ok := bytes.Cut(headerLine, []byte(": "))
if !ok { continue } // malformed header line
Like strings.Cut but for []byte; avoids converting to string when parsing HTTP/2 frame headers or binary protocols.
func bytes.Fields(s []byte) [][]byte
words := bytes.Fields(logLine) // split syslog line on whitespace without string alloc
level := string(words[3]) // convert only what you need
Splits on whitespace, returns sub-slices of the original; avoids the string allocation until you actually need a field as text.
func bytes.Join(s [][]byte, sep []byte) []byte
payload := bytes.Join(chunks, []byte("\r\n")) // reassemble fragmented protocol frames
Concatenates byte slices with sep between each; mirrors strings.Join for binary/protocol work.
func bytes.Split(s, sep []byte) [][]byte
lines := bytes.Split(fileContent, []byte("\n"))
for _, line := range lines { processLine(line) }
Splits byte slice at every sep; sub-slices share the original backing array so no extra allocation per line.
func bytes.Replace(s, old, new []byte, n int) []byte / func bytes.ReplaceAll(s, old, new []byte) []byte
out := bytes.ReplaceAll(tmplBytes, []byte("{{SERVICE}}"), []byte(serviceName))
Substitutes occurrences of old with new in a byte slice; n=-1 or ReplaceAll replaces all occurrences.
func bytes.TrimSpace(s []byte) []byte / func bytes.Trim(s []byte, cutset string) []byte
val := bytes.TrimSpace(scanned) // strip \r\n from network readline
bare := bytes.Trim(token, "\"'") // strip surrounding quotes from config value
TrimSpace removes leading/trailing whitespace; Trim removes any rune in the cutset string from both ends.
func bytes.ToLower(s []byte) []byte / func bytes.ToUpper(s []byte) []byte
if bytes.Equal(bytes.ToLower(method), []byte("get")) { ... } // normalize without string conversion
Returns a new lowercased/uppercased copy of the slice using Unicode rules; avoids round-tripping through string.
func bytes.Equal(a, b []byte) bool
if !bytes.Equal(computedMAC, receivedMAC) {
return fmt.Errorf("HMAC mismatch")
} // note: use hmac.Equal for constant-time comparison in security contexts
Reports whether two byte slices are identical; equivalent to string(a)==string(b) but without allocation.
func bytes.Index(s, sep []byte) int
i := bytes.Index(frame, []byte("\r\n\r\n")) // find end of HTTP header block
if i == -1 { return fmt.Errorf("incomplete header") }
Returns byte index of the first occurrence of sep, or -1; essential for protocol parsing where you scan raw []byte.
func bytes.NewReader(b []byte) *bytes.Reader
dec := json.NewDecoder(bytes.NewReader(cachedBody))
if err := dec.Decode(&result); err != nil { return err }
Wraps a []byte as an io.Reader/io.Seeker; use to feed in-memory bytes to decoders that expect a reader.
regexp
func regexp.Compile(expr string) (*regexp.Regexp, error) / func regexp.MustCompile(str string) *regexp.Regexp
var slugRe = regexp.MustCompile(`^[a-z0-9]+(?:-[a-z0-9]+)*$`) // package-level: compile once
re, err := regexp.Compile(pattern) // user-supplied patterns: handle error
MustCompile panics on bad syntax — safe at package level with literals; use Compile for runtime/user-supplied patterns.
func regexp.MatchString(pattern, s string) (matched bool, err error)
ok, err := regexp.MatchString(`^\d{1,3}(\.\d{1,3}){3}$`, ipStr)
if err != nil || !ok { return fmt.Errorf("invalid IP: %s", ipStr) }
One-shot match without compiling; compiles fresh on each call so only use for ad-hoc validation, not hot paths.
func (*Regexp).FindString(s string) string
token := authRe.FindString(r.Header.Get("Authorization")) // "" if no match
Returns the leftmost match as a string, or "" if none; use when you only need the matched text, not capture groups.
func (*Regexp).Find(b []byte) []byte
match := boundaryRe.Find(frameData) // avoids string conversion for []byte inputs
Like FindString but operates on []byte; the result is a sub-slice of the input, avoiding an extra allocation.
func (*Regexp).FindAllString(s string, n int) []string
emails := emailRe.FindAllString(body, -1) // n=-1 returns all matches
for _, addr := range emails { queue.Enqueue(addr) }
Returns all non-overlapping matches; n limits count (-1 = unlimited). Use when you need every occurrence in a corpus.
func (*Regexp).FindAll(b []byte, n int) [][]byte
tags := tagRe.FindAll(htmlBytes, -1) // sub-slices of htmlBytes, no extra alloc
[]byte variant of FindAllString; sub-slices share the original backing array, efficient for large HTML/binary scanning.
func (*Regexp).FindStringSubmatch(s string) []string
m := semverRe.FindStringSubmatch(tag) // ["v1.2.3", "1", "2", "3"]
if m == nil { return fmt.Errorf("not a semver tag: %s", tag) }
major, _ := strconv.Atoi(m[1])
Returns full match at [0] then capture groups at [1..]; nil if no match. Essential for extracting structured data.
func (*Regexp).FindSubmatch(b []byte) [][]byte
groups := headerRe.FindSubmatch(rawLine) // groups[1] is the header name, groups[2] the value
if groups == nil { continue }
Like FindStringSubmatch but for []byte; sub-slices of the input avoid allocation when parsing binary protocols.
func (*Regexp).ReplaceAllString(src, repl string) string
slug := spaceRe.ReplaceAllString(strings.ToLower(title), "-")
slug = nonAlphaRe.ReplaceAllString(slug, "") // strip punctuation
Replaces all matches with repl; repl can reference groups with $1 or ${name}. Returns a new string.
func (*Regexp).ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
out := placeholderRe.ReplaceAllFunc(tmpl, func(m []byte) []byte {
key := string(m[2 : len(m)-2]) // strip {{ }}
return []byte(vars[key])
})
Replaces each match with the return value of a callback; use when the replacement depends on the match content.
func (*Regexp).ReplaceAll(src, repl []byte) []byte
sanitized := ctrlRe.ReplaceAll(rawBytes, []byte("")) // strip control characters from binary log
[]byte variant of ReplaceAllString; avoids string round-trip when input and output are both []byte.
func (*Regexp).Split(s string, n int) []string
fields := delimRe.Split(record, -1) // split on /\s*,\s*/ — handles CSV with inconsistent spacing
Splits s at each match of the pattern; useful when the delimiter is a pattern rather than a fixed string.
func (*Regexp).SubexpNames() []string
var logRe = regexp.MustCompile(`(?P<ts>\S+) (?P<level>\w+) (?P<msg>.*)`)
names := logRe.SubexpNames() // ["", "ts", "level", "msg"]
m := logRe.FindStringSubmatch(line)
for i, name := range names { if name != "" { fields[name] = m[i] } }
Returns capture group names indexed to match FindStringSubmatch output; enables building a name→value map from a match.
slices
func slices.Contains[S ~[]E, E comparable](s S, v E) bool
slices.Contains(allowedRoles, user.Role)
Reports whether v is in s; requires E to be comparable.
func slices.ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool
slices.ContainsFunc(users, func(u User) bool { return u.Admin })
Reports whether any element in s satisfies f; use when the element type is not comparable or matching logic is complex.
func slices.Index[S ~[]E, E comparable](s S, v E) int
i := slices.Index(headers, "Authorization")
Returns the index of the first occurrence of v, or -1 if not present.
func slices.IndexFunc[S ~[]E, E any](s S, f func(E) bool) int
i := slices.IndexFunc(tasks, func(t Task) bool { return t.ID == targetID })
Returns the index of the first element satisfying f, or -1.
func slices.Equal[S ~[]E, E comparable](s1, s2 S) bool
slices.Equal(got, want) // in table-driven tests
Reports whether two slices are equal element-by-element; nil and empty slices are considered equal to each other.
func slices.EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool
slices.EqualFunc(got, want, func(a, b Event) bool { return a.ID == b.ID })
Reports element-wise equality using a custom comparator; useful when ignoring irrelevant fields like timestamps.
func slices.Sort[S ~[]E, E cmp.Ordered](x S)
slices.Sort(tags) // sorts []string in place
Sorts a slice of ordered values in ascending order in place; not stable.
func slices.SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int)
slices.SortFunc(users, func(a, b User) int { return cmp.Compare(a.Name, b.Name) })
Sorts a slice in place using a comparison function; use cmp.Compare for ordered types.
func slices.SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int)
slices.SortStableFunc(events, func(a, b Event) int { return cmp.Compare(a.Priority, b.Priority) })
Stable sort preserving original order for equal elements; prefer over SortFunc when secondary ordering matters.
func slices.IsSorted[S ~[]E, E cmp.Ordered](x S) bool
slices.IsSorted(ids) // assert invariant in tests
Reports whether x is sorted in ascending order.
func slices.IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool
slices.IsSortedFunc(records, func(a, b Record) int { return a.Timestamp.Compare(b.Timestamp) })
Reports whether x is sorted according to a custom comparator.
func slices.Reverse[S ~[]E, E any](s S)
slices.Reverse(stack) // reverse in place
Reverses the elements of s in place.
func slices.Compact[S ~[]E, E comparable](s S) S
lines = slices.Compact(lines) // remove consecutive duplicate log lines
Removes consecutive duplicate elements (like Unix uniq); combine with Sort to deduplicate entirely.
func slices.CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S
slices.CompactFunc(entries, func(a, b LogEntry) bool { return a.Msg == b.Msg })
Like Compact but uses eq to determine equality; useful when the element type is not comparable.
func slices.Max[S ~[]E, E cmp.Ordered](x S) E
peak := slices.Max(temperatures)
Returns the maximum value in x; panics on empty slice.
func slices.MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E
latest := slices.MaxFunc(commits, func(a, b Commit) int { return a.Time.Compare(b.Time) })
Returns the maximum element using a custom comparator; panics on empty slice.
func slices.Min[S ~[]E, E cmp.Ordered](x S) E
floor := slices.Min(prices)
Returns the minimum value in x; panics on empty slice.
func slices.MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E
oldest := slices.MinFunc(users, func(a, b User) int { return a.CreatedAt.Compare(b.CreatedAt) })
Returns the minimum element using a custom comparator; panics on empty slice.
func slices.BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)
i, found := slices.BinarySearch(sortedIDs, targetID)
Binary search on a sorted slice; returns insertion index and whether target was found.
func slices.BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool)
i, ok := slices.BinarySearchFunc(products, sku, func(p Product, s string) int { return strings.Compare(p.SKU, s) })
Binary search using a custom comparator; target type can differ from element type.
func slices.Collect[E any](seq iter.Seq[E]) []E (Go 1.23)
ids := slices.Collect(maps.Keys(userMap))
Collects all values from an iterator into a new slice (Go 1.23+); the standard way to materialise a range-over-func iterator.
func slices.Concat[S ~[]E, E any](slices ...S) S
all := slices.Concat(required, optional, defaults)
Returns a new slice concatenating all argument slices; cleaner than multiple append calls.
func slices.Clip[S ~[]E, E any](s S) S
results = slices.Clip(results) // trim excess capacity before returning
Returns s with its capacity trimmed to its length; prevents callers from accidentally appending into the backing array.
func slices.Grow[S ~[]E, E any](s S, n int) S
buf = slices.Grow(buf, len(incoming)) // pre-allocate before batch append
Increases the capacity of s by at least n elements; avoids repeated allocations when appending in a loop.
func slices.Delete[S ~[]E, E any](s S, i, j int) S
items = slices.Delete(items, idx, idx+1) // remove one element
Removes elements s[i:j] from s, shifting the tail left; modifies the underlying array.
func slices.DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S
jobs = slices.DeleteFunc(jobs, func(j Job) bool { return j.Status == StatusCancelled })
Removes all elements for which del returns true, in place; replaces the filter-then-copy idiom.
func slices.Insert[S ~[]E, E any](s S, i int, v ...E) S
pipeline = slices.Insert(pipeline, 0, authMiddleware, rateLimiter)
Inserts v at index i, shifting existing elements right; may allocate a new backing array.
func slices.Replace[S ~[]E, E any](s S, i, j int, v ...E) S
tokens = slices.Replace(tokens, start, end, replacement...)
Replaces s[i:j] with v; equivalent to Delete followed by Insert but in one allocation.
maps
func maps.Keys[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K]
ids := slices.Collect(maps.Keys(userIndex))
Returns an iterator over the map's keys (Go 1.23+); wrap with slices.Collect to materialise as a slice.
func maps.Values[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[V]
for cfg := range maps.Values(featureFlags) { cfg.Validate() }
Returns an iterator over the map's values (Go 1.23+); order is undefined, same as ranging over the map directly.
func maps.Clone[Map ~map[K]V, K comparable, V any](m Map) Map
snapshot := maps.Clone(config) // shallow copy before mutation
Returns a shallow copy of m; values are not deep-copied, so pointer/slice values still alias the original.
func maps.Copy[Map1 ~map[K]V, Map2 ~map[K]V, K comparable, V any](dst Map1, src Map2)
maps.Copy(merged, overrides) // overrides wins on key collision
Copies all key-value pairs from src into dst, overwriting existing keys; modifies dst in place.
func maps.DeleteFunc[Map ~map[K]V, K comparable, V any](m Map, del func(K, V) bool)
maps.DeleteFunc(cache, func(k string, v CacheEntry) bool { return v.ExpiresAt.Before(now) })
Deletes all entries for which del returns true; the idiomatic way to prune a map without building a separate delete list.
func maps.Collect[K comparable, V any](seq iter.Seq2[K, V]) map[K]V
lookup := maps.Collect(slices.All(rows))
Collects a key-value iterator into a new map (Go 1.23+); pairs with maps.All or slices.All to build index maps.
func maps.Insert[Map ~map[K]V, K comparable, V any](m Map, seq iter.Seq2[K, V])
maps.Insert(index, slices.All(newItems))
Inserts all key-value pairs from seq into m, overwriting duplicates (Go 1.23+); the mutable counterpart of maps.Collect.
func maps.All[Map ~map[K]V, K comparable, V any](m Map) iter.Seq2[K, V]
for k, v := range maps.All(settings) { applyOverride(k, v) }
Returns an iterator over all key-value pairs (Go 1.23+); useful for passing a map to iterator-accepting functions.
func maps.Equal[Map1, Map2 ~map[K]V, K, V comparable](m1 Map1, m2 Map2) bool
maps.Equal(gotHeaders, wantHeaders) // in HTTP handler tests
Reports whether two maps contain the same key-value pairs; both K and V must be comparable.
sort
func sort.Slice(x any, less func(i, j int) bool)
sort.Slice(events, func(i, j int) bool { return events[i].Time.Before(events[j].Time) })
Sorts a slice in place; not stable — use SliceStable when equal elements must keep original order.
func sort.SliceStable(x any, less func(i, j int) bool)
sort.SliceStable(rows, func(i, j int) bool { return rows[i].Priority > rows[j].Priority })
Stable sort preserving the relative order of equal elements; use when a secondary sort key was applied first.
func sort.SliceIsSorted(x any, less func(i, j int) bool) bool
sort.SliceIsSorted(results, func(i, j int) bool { return results[i].Score > results[j].Score })
Reports whether a slice satisfies the given less function; useful as an assertion in tests.
func sort.Search(n int, f func(int) bool) int
i := sort.Search(len(entries), func(i int) bool { return entries[i].Offset >= target })
Binary search returning the smallest index where f is true; f must be false then true (monotone). Returns n if never true.
func sort.SearchInts(a []int, x int) int
pos := sort.SearchInts(breakpoints, value)
Returns the index to insert x into a sorted []int to keep it sorted; specialisation of sort.Search.
func sort.Strings(x []string)
sort.Strings(tags) // normalise before dedup or binary search
Sorts a []string in ascending order in place; consider slices.Sort for generics-based code.
func sort.Ints(x []int)
sort.Ints(ports) // sort before presenting in UI
Sorts a []int in ascending order in place.
func sort.Float64s(x []float64)
sort.Float64s(latencies) // sort before computing percentiles
Sorts a []float64 in ascending order in place; NaN values sort before other values.
func sort.Reverse(data sort.Interface) sort.Interface
sort.Sort(sort.Reverse(sort.StringSlice(tags)))
Wraps a sort.Interface to sort in descending order; compose with any Interface implementation.
type sort.Interface interface { Len() int; Less(i, j int) bool; Swap(i, j int) }
func (b ByDeadline) Len() int { return len(b) }
func (b ByDeadline) Less(i, j int) bool { return b[i].Deadline.Before(b[j].Deadline) }
func (b ByDeadline) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
Implement Len/Less/Swap on a named slice type to use sort.Sort, sort.Stable, and sort.Reverse.
errors
func errors.New(text string) error
var ErrNotFound = errors.New("record not found")
Creates a new error with a static message; declare as a package-level var so callers can compare with errors.Is.
func errors.Is(err, target error) bool
if errors.Is(err, ErrNotFound) { return http.StatusNotFound }
Checks whether any error in the chain matches target; handles wrapped errors — prefer over direct == comparison.
func errors.As(err error, target any) bool
var pgErr *pgconn.PgError; if errors.As(err, &pgErr) { log.Println(pgErr.Code) }
Finds the first error in the chain matching target's type and assigns it; use instead of type assertion on wrapped errors.
func errors.Unwrap(err error) error
cause := errors.Unwrap(err) // one level; nil if err doesn't implement Unwrap
Returns the directly wrapped error; errors.Is/As are usually preferable for traversing the full chain.
func errors.Join(errs ...error) error
errs = append(errs, validate(field, value))
return errors.Join(errs...)
Combines multiple errors into one; the joined error's Error() concatenates non-nil messages with newlines. errors.Is/As traverse all branches.
io
type io.Reader interface { Read(p []byte) (n int, err error) }
func hashBody(r io.Reader) []byte { h := sha256.New(); io.Copy(h, r); return h.Sum(nil) }
The fundamental streaming-read interface; accept io.Reader in function signatures instead of *os.File or []byte to keep code composable.
type io.Writer interface { Write(p []byte) (n int, err error) }
json.NewEncoder(w).Encode(v) // w is io.Writer — works for http.ResponseWriter, os.File, bytes.Buffer
The fundamental streaming-write interface; accept io.Writer to write to any destination without coupling to a concrete type.
type io.Closer interface { Close() error } / io.ReadCloser / io.WriteCloser
defer resp.Body.Close() // resp.Body is io.ReadCloser
Always defer Close on any io.ReadCloser (HTTP bodies, os.File); failing to close leaks file descriptors and HTTP connections.
type io.ReadWriter interface { io.Reader; io.Writer } / io.Seeker / io.ReadWriteSeeker
var buf bytes.Buffer; io.Copy(&buf, src) // bytes.Buffer satisfies io.ReadWriter
Composed interfaces; bytes.Buffer, os.File, and net.Conn satisfy various combinations — program to the narrowest interface you need.
func io.Copy(dst io.Writer, src io.Reader) (written int64, err error)
n, err := io.Copy(dst, src) // zero-alloc if src implements WriteTo or dst implements ReadFrom
Copies until EOF; uses 32 KB internal buffer by default. Returns bytes written and the first non-EOF error.
func io.CopyN(dst io.Writer, src io.Reader, n int64) (written int64, err error)
_, err = io.CopyN(w, r, 1<<20) // copy at most 1 MiB
Like Copy but stops after n bytes; returns io.EOF if src had fewer bytes than n.
func io.CopyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err error)
buf := make([]byte, 64<<10); io.CopyBuffer(dst, src, buf) // reuse buf across calls
Like Copy but uses the provided buffer; pass a pre-allocated slice to avoid per-call allocations in tight loops.
func io.ReadAll(r io.Reader) ([]byte, error)
body, err := io.ReadAll(resp.Body)
Reads until EOF or error; don't use on untrusted network streams without a LimitReader — a malicious peer can exhaust memory.
func io.WriteString(w io.Writer, s string) (n int, err error)
io.WriteString(w, "Content-Type: application/json\r\n")
Writes a string to w without converting to []byte if w implements io.StringWriter; otherwise falls back to Write([]byte(s)).
func io.Pipe() (*io.PipeReader, *io.PipeWriter)
pr, pw := io.Pipe(); go json.NewEncoder(pw).Encode(v); io.Copy(dst, pr)
Synchronous, in-memory pipe connecting a Writer to a Reader with no buffering; use when you need to stream encode/compress without staging a []byte.
func io.LimitReader(r io.Reader, n int64) io.Reader
safe := io.LimitReader(resp.Body, 10<<20); io.ReadAll(safe) // cap at 10 MiB
Wraps r to return EOF after n bytes; essential safety guard before ReadAll on network responses or uploaded files.
func io.MultiReader(readers ...io.Reader) io.Reader
body := io.MultiReader(strings.NewReader(header), f, strings.NewReader(footer))
Concatenates multiple readers into one; reads drain them in order — useful for prepending headers to a file stream without copying.
func io.MultiWriter(writers ...io.Writer) io.Writer
mw := io.MultiWriter(os.Stdout, logFile); fmt.Fprintln(mw, "server started")
Fans out writes to all writers simultaneously; write fails if any writer fails, so combine with a resilient writer if some destinations are optional.
func io.TeeReader(r io.Reader, w io.Writer) io.Reader
body := io.TeeReader(resp.Body, &buf); json.NewDecoder(body).Decode(&v) // buf has raw bytes
Returns a Reader that writes everything it reads into w; use to log or hash a stream while consuming it.
var io.Discard io.Writer
io.Copy(io.Discard, resp.Body) // drain body so connection can be reused
A writer that discards all data; drain HTTP response bodies you don't need so the underlying TCP connection returns to the pool.
func io.NopCloser(r io.Reader) io.ReadCloser
req.Body = io.NopCloser(strings.NewReader(payload)) // no-op Close()
Wraps a Reader with a no-op Close method to satisfy interfaces expecting io.ReadCloser; commonly used when building synthetic http.Request bodies in tests.
var io.EOF = errors.New("EOF")
if err == io.EOF { return } // normal end-of-stream, not an error
The sentinel value Read returns when the stream is cleanly exhausted; never wrap or discard it — check with == not errors.Is.
func io.ReadFull(r io.Reader, buf []byte) (n int, err error)
_, err = io.ReadFull(conn, header[:8]) // exactly 8 bytes or error
Reads exactly len(buf) bytes; returns ErrUnexpectedEOF if the stream ends before the buffer is full — use for binary protocol framing.
func io.ReadAtLeast(r io.Reader, buf []byte, min int) (n int, err error)
n, err = io.ReadAtLeast(r, buf, 1) // at least 1 byte, up to len(buf)
Like ReadFull but accepts a minimum count less than len(buf); useful when you need some data but can work with a partial buffer fill.
io/fs
type fs.FS interface { Open(name string) (fs.File, error) }
func loadTemplates(fsys fs.FS) { tmpl.ParseFS(fsys, "templates/*.html") }
The root abstraction for any file tree — OS directory, zip archive, or embed.FS; accept fs.FS in function parameters to make code testable with fstest.MapFS.
type fs.ReadFileFS interface { fs.FS; ReadFile(name string) ([]byte, error) }
if rfs, ok := fsys.(fs.ReadFileFS); ok { data, _ = rfs.ReadFile("config.yaml") }
Optional FS extension for efficient whole-file reads; embed.FS and os.DirFS implement it — fs.ReadFile falls back to Open+Read if absent.
type fs.StatFS interface { fs.FS; Stat(name string) (fs.FileInfo, error) }
if sfs, ok := fsys.(fs.StatFS); ok { info, _ = sfs.Stat("assets/logo.svg") }
Optional FS extension for metadata without opening; use a type assertion before calling to avoid the Open+Stat round-trip on implementations that support it natively.
func fs.WalkDir(fsys fs.FS, root string, fn fs.WalkDirFunc) error
fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error {
if err != nil { return err }; if !d.IsDir() { index(p) }; return nil })
Walks the tree rooted at root in lexical order; return fs.SkipDir from the callback to skip a directory, return fs.SkipAll to stop the entire walk.
func fs.ReadFile(fsys fs.FS, name string) ([]byte, error)
data, err := fs.ReadFile(fsys, "migrations/001_init.sql")
Reads an entire file from any fs.FS; delegates to ReadFileFS.ReadFile if available, otherwise falls back to Open+Read+Close.
func fs.Glob(fsys fs.FS, pattern string) (matches []string, err error)
htmlFiles, _ := fs.Glob(fsys, "templates/*.html")
Returns paths matching the shell pattern within the FS; same syntax as filepath.Match — useful for discovering embedded assets at startup.
type fs.DirEntry interface { Name() string; IsDir() bool; Type() FileMode; Info() (FileInfo, error) }
entries, _ := fs.ReadDir(fsys, "migrations"); for _, e := range entries { fmt.Println(e.Name()) }
Lightweight directory entry; call Info() only when you need full FileInfo — avoids a stat syscall on implementations that cache basic metadata.
func fs.Sub(fsys fs.FS, dir string) (fs.FS, error)
staticFS, _ := fs.Sub(assets, "static"); http.Handle("/static/", http.FileServer(http.FS(staticFS)))
Returns a new FS rooted at dir within fsys; use to expose a subdirectory of embed.FS to http.FileServer without revealing the full tree.
func fs.ReadDir(fsys fs.FS, name string) ([]fs.DirEntry, error)
entries, err := fs.ReadDir(fsys, "migrations") // sorted by name
Returns sorted directory entries; simpler than WalkDir when you only need one directory level without recursion.
os
func os.Open(name string) (*os.File, error)
f, err := os.Open("access.log"); if err != nil { return err }; defer f.Close()
Opens a file read-only; always defer Close immediately after checking the error, not inside the if block, so the defer runs on all code paths.
func os.Create(name string) (*os.File, error)
f, err := os.Create("report.json"); if err != nil { return err }; defer f.Close()
Creates or truncates a file for writing with mode 0666 (before umask); use OpenFile for append, exclusive create, or custom permissions.
func os.OpenFile(name string, flag int, perm os.FileMode) (*os.File, error)
f, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
General-purpose open with explicit flags: O_RDONLY, O_WRONLY, O_RDWR combined with O_CREATE, O_APPEND, O_EXCL, O_TRUNC.
func os.ReadFile(name string) ([]byte, error)
data, err := os.ReadFile("config.yaml"); if err != nil { return fmt.Errorf("read config: %w", err) }
Reads a whole file into memory in one call; use for config files and small assets, not streaming large files.
func os.WriteFile(name string, data []byte, perm os.FileMode) error
err := os.WriteFile("state.json", buf.Bytes(), 0600)
Atomically creates or replaces a file; for safe atomic writes, write to a temp file and rename — WriteFile itself is not crash-safe.
func os.MkdirAll(path string, perm os.FileMode) error
err := os.MkdirAll(filepath.Join(cacheDir, "thumbnails"), 0755)
Creates a directory and all missing parents; does not error if the path already exists — use instead of Mkdir for setup code.
func os.Remove(name string) error / func os.RemoveAll(path string) error
os.Remove("upload.tmp"); os.RemoveAll(filepath.Join(workDir, jobID))
Remove deletes one file or empty directory; RemoveAll recursively deletes a tree and returns nil if path doesn't exist.
func os.Stat(name string) (os.FileInfo, error) / func os.Lstat(name string) (os.FileInfo, error)
info, err := os.Stat("data.db"); if os.IsNotExist(err) { /* create */ }
Stat follows symlinks; Lstat returns info about the symlink itself. Use errors.Is(err, fs.ErrNotExist) for portable not-found checks.
func os.Getenv(key string) string / func os.LookupEnv(key string) (string, bool)
dsn, ok := os.LookupEnv("DATABASE_URL"); if !ok { return fmt.Errorf("DATABASE_URL not set") }
Prefer LookupEnv over Getenv when an empty string is a valid value and you need to distinguish "unset" from "empty".
func os.Setenv(key, value string) error
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credPath)
Sets an environment variable for the current process; changes are visible to child processes started after the call.
func os.Exit(code int)
if err := run(); err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
Terminates the process immediately — deferred functions do NOT run. Only call from main(); use log.Fatal in tests or defer-heavy code.
var os.Args []string / os.Stdin *os.File / os.Stdout *os.File / os.Stderr *os.File
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "[--port PORT]")
os.Args[0] is the program name; os.Stdin/Stdout/Stderr are pre-opened *os.File values implementing io.Reader/Writer.
func os.Rename(oldpath, newpath string) error
err := os.Rename(tmpPath, "config.yaml") // atomic replace on same filesystem
Atomic file replace on the same filesystem; the standard pattern for safe writes is WriteFile→tmpfile, Rename→target, Remove→tmp on error.
func os.CreateTemp(dir, pattern string) (*os.File, error)
tmp, err := os.CreateTemp("", "upload-*.bin"); defer os.Remove(tmp.Name())
Creates a uniquely named temp file; pass "" for dir to use os.TempDir(). Always defer Remove(tmp.Name()) for cleanup.
*os.File methods: Read / Write / Close / Seek / ReadAt / WriteAt
f.Seek(0, io.SeekStart); io.Copy(w, f) // rewind after writing, then serve
*os.File implements io.Reader, io.Writer, io.Seeker, io.ReaderAt, io.WriterAt; Seek(0, io.SeekStart) rewinds to the beginning.
os/exec
func exec.Command(name string, arg ...string) *exec.Cmd
out, err := exec.Command("git", "log", "--oneline", "-10").Output()
Creates a Cmd; name is looked up via PATH. In server code always use CommandContext so the subprocess is killed when the request is cancelled.
func exec.CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd
out, err := exec.CommandContext(ctx, "git", "rev-parse", "HEAD").Output()
Like Command but kills the process when ctx is cancelled; always prefer over Command in server code.
func (*exec.Cmd) Output() ([]byte, error) / CombinedOutput() ([]byte, error)
out, err := exec.CommandContext(ctx, "ffprobe", "-i", path).CombinedOutput()
Output returns stdout only; CombinedOutput merges stdout and stderr — useful when the tool writes diagnostics to stderr that you need on error.
func (*exec.Cmd) Run() error / Start() error + Wait() error
cmd := exec.CommandContext(ctx, "ffmpeg", args...); cmd.Stdout = w; cmd.Start(); defer cmd.Wait()
Run = Start + Wait in one call; use Start/Wait separately when you need to stream output or interact with the process while it runs.
Cmd.Stdin io.Reader / Cmd.Stdout io.Writer / Cmd.Stderr io.Writer
cmd.Stdin = strings.NewReader(input); cmd.Stdout = &outBuf; cmd.Stderr = os.Stderr
Wire subprocess I/O to any io.Reader/Writer; set Stderr=os.Stderr during development to see tool errors, then capture it in production.
func exec.LookPath(file string) (string, error)
ffmpegPath, err := exec.LookPath("ffmpeg"); if err != nil { return fmt.Errorf("ffmpeg not found: %w", err) }
Searches PATH for an executable; call at startup to fail fast if required tools are missing rather than discovering it at request time.
type exec.ExitError struct { *os.ProcessState; Stderr []byte }
var exitErr *exec.ExitError; if errors.As(err, &exitErr) { log.Printf("exit %d: %s", exitErr.ExitCode(), exitErr.Stderr) }
Returned by Run/Output/Wait when the command exits non-zero; ExitCode() gives the status, Stderr field has captured stderr when using Output().
bufio
func bufio.NewReader(rd io.Reader) *bufio.Reader
r := bufio.NewReader(conn) // 4096-byte buffer by default
Wraps a Reader with a buffer; reduces syscall count when reading many small chunks from a net.Conn or os.File.
func bufio.NewWriter(w io.Writer) *bufio.Writer
bw := bufio.NewWriter(conn); fmt.Fprintln(bw, "HTTP/1.1 200 OK"); bw.Flush()
Wraps a Writer with a buffer; always call Flush() when done — unflushed data is silently lost if you forget.
type bufio.Scanner — Scan() bool, Text() string, Err() error, Split(SplitFunc)
sc := bufio.NewScanner(f); for sc.Scan() { process(sc.Text()) }; return sc.Err()
Line-by-line file reader; always check Err() after the loop — Scan returning false doesn't mean no error.
func bufio.NewScanner(r io.Reader) *bufio.Scanner
sc := bufio.NewScanner(f); sc.Buffer(make([]byte, 1<<20), 1<<20) // 1 MiB lines
Default buffer is 64 KiB; call Buffer() before the first Scan() to handle longer lines — otherwise Scan returns false with ErrTooLong.
var bufio.ScanLines / bufio.ScanWords / bufio.ScanRunes / bufio.ScanBytes SplitFunc
sc.Split(bufio.ScanWords); for sc.Scan() { words = append(words, sc.Text()) }
Built-in split functions; pass to Scanner.Split() before the loop. ScanLines strips the newline; ScanWords splits on whitespace.
func (*bufio.Reader) ReadString(delim byte) (string, error)
line, err := r.ReadString('\n') // includes the delimiter
Reads until the delimiter (inclusive); returns the partial string AND an error if EOF is hit before the delimiter — handle both.
func (*bufio.Reader) ReadLine() (line []byte, isPrefix bool, err error)
for { l, more, err := r.ReadLine(); buf = append(buf, l...); if !more { break } }
Low-level line reader; isPrefix is true if the line exceeded the buffer — loop to collect all parts. Prefer Scanner.Scan for typical use.
func (*bufio.Writer) Flush() error / WriteString(s string) (int, error)
bw.WriteString(line); bw.WriteByte('\n'); if done { bw.Flush() }
WriteString avoids a string→[]byte allocation; Flush must be called explicitly — bufio.Writer does not flush on Close or GC.
type bufio.ReadWriter struct { *Reader; *Writer }
rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
Combines a buffered Reader and Writer over the same underlying connection; used when a protocol requires both buffered reads and writes (e.g. HTTP/1.1 hijack).
path/filepath
func filepath.Join(elem ...string) string
cfgPath := filepath.Join(os.UserHomeDir(), ".config", "app", "config.yaml")
Joins path elements with the OS separator and cleans the result; handles empty elements and double slashes — never concatenate paths with string +.
func filepath.Base(path string) string / filepath.Dir(path string) string
dir, file := filepath.Dir(p), filepath.Base(p) // "/var/log/app.log" → "/var/log", "app.log"
Base returns the last element; Dir returns everything before the last separator. Both handle trailing slashes consistently.
func filepath.Ext(path string) string
ext := filepath.Ext("avatar.jpg") // ".jpg"
Returns the file extension including the leading dot; returns "" for paths with no dot in the final element.
func filepath.Abs(path string) (string, error)
abs, err := filepath.Abs(flagDataDir) // resolve relative CLI flag to absolute
Returns the absolute path by joining with the working directory; call early in main() on user-provided paths so the rest of the code sees consistent absolute paths.
func filepath.Rel(basepath, targpath string) (string, error)
rel, err := filepath.Rel(root, fullPath) // "/app", "/app/static/x.css" → "static/x.css"
Returns a relative path from base to target; errors if the paths can't be made relative (different Windows volumes).
func filepath.Clean(path string) string
if !strings.HasPrefix(filepath.Clean(p), root) { return fmt.Errorf("path traversal") }
Lexically cleans a path by resolving . and ..; apply before checking that a user-supplied path stays within a root directory.
func filepath.IsAbs(path string) bool
if !filepath.IsAbs(p) { p = filepath.Join(workDir, p) }
Reports whether the path is absolute; use to normalize user input that could be either relative or absolute.
func filepath.WalkDir(root string, fn fs.WalkDirFunc) error
filepath.WalkDir("./migrations", func(p string, d fs.DirEntry, err error) error {
if filepath.Ext(p) == ".sql" { files = append(files, p) }; return nil })
Walks the OS directory tree; prefer over the older filepath.Walk which calls Lstat on every entry — WalkDir is faster because DirEntry avoids extra syscalls.
func filepath.Glob(pattern string) (matches []string, err error)
configs, _ := filepath.Glob("/etc/myapp/*.conf")
Returns filesystem paths matching the shell pattern; does not recurse — use WalkDir for deep searches.
func filepath.Match(pattern, name string) (matched bool, err error)
ok, _ := filepath.Match("*.log", filepath.Base(p))
Shell-style pattern matching for a single path element; supports *, ?, [range] but not **. Use in WalkDir callbacks to filter files.
func filepath.FromSlash(path string) string / filepath.ToSlash(path string) string
osPath := filepath.FromSlash("static/css/main.css") // forward→OS separator
Convert between forward-slash paths (URLs, embed.FS) and OS paths; necessary on Windows where the separator is backslash.
func filepath.EvalSymlinks(path string) (string, error)
real, err := filepath.EvalSymlinks(p) // resolve symlinks before security checks
Resolves all symlinks and returns the canonical path; call before checking that a path is within a safe root to prevent symlink traversal attacks.
embed
//go:embed <path> → var content string / var data []byte
//go:embed schema.sql
var schema string // populated at compile time
Embeds a single file as a string or []byte; the directive must appear on the line immediately before the var declaration with no blank lines between.
//go:embed <pattern> → var assets embed.FS
//go:embed static/* templates
var assets embed.FS; http.Handle("/static/", http.FileServer(http.FS(assets)))
Embeds a directory tree into the binary at compile time; serve it directly via http.FS without extracting.
embed.FS.Open(name string) / ReadFile(name string) / ReadDir(name string)
data, err := assets.ReadFile("templates/index.html")
entries, _ := assets.ReadDir("migrations"); for _, e := range entries { /* run migration */ }
embed.FS implements fs.FS, fs.ReadFileFS, and fs.ReadDirFS; paths always use forward slashes regardless of OS.
Serving embedded files over HTTP via http.FS + fs.Sub
sub, _ := fs.Sub(assets, "static")
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(sub))))
Use fs.Sub to expose only a subdirectory; http.FS wraps any fs.FS into an http.FileSystem so the standard file server serves embedded assets with correct MIME types.
time
func time.Now() time.Time
start := time.Now(); // capture before the operation
Returns the current local time; use as a snapshot before work you want to measure or log.
func time.Since(t time.Time) time.Duration
elapsed := time.Since(start); slog.Info("request", "dur", elapsed)
Shorthand for time.Now().Sub(t); use to measure elapsed time since a recorded timestamp.
func time.Until(t time.Time) time.Duration
if time.Until(cert.NotAfter()) < 30*time.Hour*24 { renewCert() }
Shorthand for t.Sub(time.Now()); negative when t is in the past. Handy for deadline/expiry checks.
func time.Parse(layout, value string) (time.Time, error)
t, err := time.Parse("2006-01-02", r.FormValue("date")) // reference time is Mon Jan 2 15:04:05 MST 2006
Parses a time string using Go's reference time as the layout; the magic numbers 2006/01/02/15/04/05 encode year/month/day/hour/min/sec.
func (t time.Time) Format(layout string) string
ts := t.Format("2006-01-02T15:04:05Z07:00") // RFC 3339
Formats t using Go's reference-time layout; "2006-01-02T15:04:05Z07:00" is RFC 3339 (ISO 8601 with timezone offset).
const time.Second, time.Minute, time.Hour, time.Millisecond time.Duration
http.DefaultClient.Timeout = 10 * time.Second
Pre-defined Duration constants; multiply by an integer literal to get any duration (e.g. 500*time.Millisecond for half a second).
func (t time.Time) Add(d time.Duration) time.Time
expiry := time.Now().Add(24 * time.Hour) // token valid for one day
Returns a new Time offset by d; negative d moves backward. Use for computing deadlines or expiry timestamps.
func (t time.Time) Sub(u time.Time) time.Duration
age := time.Now().Sub(user.CreatedAt); // how long the account has existed
Returns the Duration t-u; positive when t is after u. Use when you need elapsed time between two known timestamps.
func time.Sleep(d time.Duration)
time.Sleep(500 * time.Millisecond) // back-off before retry
Pauses the current goroutine for at least d; for cancellable sleeps prefer select with time.After and a ctx.Done() case.
func time.After(d time.Duration) <-chan time.Time
select { case res := <-ch: process(res); case <-time.After(2 * time.Second): log.Println("timeout") }
Returns a channel that receives the current time after d; leaks the timer if the channel is never received — prefer time.NewTimer when you need to stop early.
func time.NewTimer(d time.Duration) *time.Timer
timer := time.NewTimer(5 * time.Second); defer timer.Stop()
Creates a timer that fires once after d; always call Stop() when done to release resources, especially in long-running goroutines.
func (t *time.Timer) Stop() bool; func (t *time.Timer) Reset(d time.Duration) bool
if !timer.Stop() { <-timer.C }; timer.Reset(10 * time.Second)
Stop prevents the timer from firing (drain C if it returns false); Reset reschedules — always Stop and drain before Reset per Go docs.
func time.NewTicker(d time.Duration) *time.Ticker
tick := time.NewTicker(1 * time.Minute); defer tick.Stop(); for range tick.C { flushMetrics() }
Sends the current time on its channel at every interval d; always defer Stop() to avoid goroutine and channel leaks.
func time.AfterFunc(d time.Duration, f func()) *time.Timer
time.AfterFunc(30*time.Second, func() { cache.Evict(key) })
Calls f in a new goroutine after d; returns a Timer whose Stop can cancel f if it hasn't fired yet.
func (t time.Time) Truncate(d time.Duration) time.Time; func (t time.Time) Round(d time.Duration) time.Time
hour := time.Now().Truncate(time.Hour); rounded := t.Round(time.Minute)
Truncate strips the sub-d remainder (floor); Round goes to the nearest multiple of d. Both operate relative to the zero time, not midnight.
func (t time.Time) Unix() int64; func (t time.Time) UnixMilli() int64; func time.UnixMilli(msec int64) time.Time
ms := time.Now().UnixMilli(); t := time.UnixMilli(ms) // round-trip
Unix/UnixMilli convert a Time to an integer epoch; time.UnixMilli converts back. Use UnixMilli for JavaScript interop (JS Date.now() is milliseconds).
func time.LoadLocation(name string) (*time.Location, error); var time.UTC, time.Local *time.Location
loc, err := time.LoadLocation("America/New_York"); t := time.Now().In(loc)
LoadLocation parses an IANA timezone name (requires tzdata); time.UTC and time.Local are pre-defined sentinels for UTC and the process's local zone.
func (t time.Time) IsZero() bool; func (t time.Time) Before(u time.Time) bool; func (t time.Time) After(u time.Time) bool
if t.IsZero() { return errors.New("timestamp not set") }; ok := t.Before(deadline)
IsZero checks if t is the zero value (Jan 1 year 1); Before/After compare two times and are nil-safe alternatives to t.Sub(u) sign checks.
context
func context.Background() context.Context; func context.TODO() context.Context
ctx := context.Background() // top-level; use TODO when unsure which parent to use
Background is the root context for main, tests, and incoming request handlers; TODO signals a placeholder where the correct context is not yet determined.
func context.WithCancel(parent context.Context) (context.Context, context.CancelFunc)
ctx, cancel := context.WithCancel(r.Context()); defer cancel(); go worker(ctx)
Returns a child context and a cancel function; calling cancel propagates cancellation to all children. Always defer cancel to prevent goroutine leaks.
func context.WithCancelCause(parent context.Context) (context.Context, context.CancelCauseFunc)
ctx, cancel := context.WithCancelCause(parent); cancel(io.ErrUnexpectedEOF); err := context.Cause(ctx)
Like WithCancel but the cancel func accepts an error that is retrievable via context.Cause; useful for propagating the root cause through a tree of goroutines.
func context.WithTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second); defer cancel()
Returns a context that cancels after the timeout; always defer cancel() immediately to avoid leaking resources.
func context.WithDeadline(parent context.Context, d time.Time) (context.Context, context.CancelFunc)
dl := time.Now().Add(10 * time.Second); ctx, cancel := context.WithDeadline(r.Context(), dl); defer cancel()
Like WithTimeout but takes an absolute deadline; use when you have a wall-clock cutoff (e.g. end of a business window) rather than a duration.
func context.WithValue(parent context.Context, key, val any) context.Context
type ctxKey struct{}; ctx := context.WithValue(r.Context(), ctxKey{}, userID)
Attaches a key-value pair to a context; use an unexported struct type as the key to prevent collisions between packages.
func (ctx context.Context) Done() <-chan struct{}; func (ctx context.Context) Err() error
select { case <-ctx.Done(): return ctx.Err() // Canceled or DeadlineExceeded; case res := <-ch: return process(res) }
Done returns a channel closed when the context is cancelled; Err returns context.Canceled or context.DeadlineExceeded. Use both in select loops to honour cancellation.
func context.Cause(c context.Context) error
if err := context.Cause(ctx); err != nil { slog.Error("cancelled", "cause", err) }
Returns the cause passed to WithCancelCause, or ctx.Err() for ordinary contexts (Go 1.20+); lets you distinguish application-level cancellation reasons.
func (ctx context.Context) Value(key any) any
type ctxKey struct{}; uid, ok := ctx.Value(ctxKey{}).(string)
Retrieves a value stored with WithValue; always type-assert the result and check ok. Only store request-scoped data (trace IDs, auth info), not optional function parameters.
func context.AfterFunc(ctx context.Context, f func()) (stop func() bool)
stop := context.AfterFunc(ctx, func() { conn.Close() }); defer stop()
Schedules f to run in a new goroutine after ctx is done (Go 1.21); stop() cancels the callback if the context hasn't fired yet — useful for cleanup on cancellation.
sync
type sync.Mutex — Lock(), Unlock(), TryLock() bool
mu.Lock(); defer mu.Unlock(); cache[key] = value
Mutual exclusion lock; always defer Unlock immediately after Lock to prevent deadlock on panic.
type sync.RWMutex — RLock(), RUnlock(), Lock(), Unlock(), TryLock() bool, TryRLock() bool
mu.RLock(); defer mu.RUnlock(); return cache[key] // multiple readers OK
Reader/writer mutex; multiple goroutines can RLock simultaneously, but Lock is exclusive — ideal for read-heavy caches.
type sync.WaitGroup — Add(delta int), Done(), Wait()
var wg sync.WaitGroup; for _, url := range urls { wg.Add(1); go func() { defer wg.Done(); fetch(url) }() }; wg.Wait()
Waits for a collection of goroutines to finish; Add before launching, Done deferred inside the goroutine, Wait to block.
type sync.Once — Do(f func())
var once sync.Once; once.Do(func() { db = openDB() }) // runs exactly once
Guarantees f is executed at most once across all goroutines — classic lazy singleton initialisation.
func sync.OnceFunc(f func()) func() (Go 1.21)
loadConfig := sync.OnceFunc(func() { cfg = parseFile("config.yaml") }); loadConfig(); loadConfig()
Returns a function that calls f only on the first invocation; panics in f are re-panicked on every subsequent call, unlike Once.Do.
func sync.OnceValue[T any](f func() T) func() T (Go 1.21)
getConn := sync.OnceValue(func() *sql.DB { return mustOpen(dsn) }); db := getConn()
Like OnceFunc but the wrapped function returns a value — every call returns the same cached result without a mutex.
type sync.Map — Load(key any) (any, bool), Store(key, value any), LoadOrStore, Delete, Range, Swap, CompareAndSwap
m.Store("hits", 0); v, ok := m.Load("hits"); m.Range(func(k, v any) bool { fmt.Println(k, v); return true })
Concurrent map safe for goroutine use without extra locking; best when keys are written once and read many times (e.g. caches, registries).
sync.Map — LoadOrStore(key, value any) (actual any, loaded bool)
actual, loaded := m.LoadOrStore(id, newConn()); if loaded { newConn().Close() }
Atomically loads an existing value or stores and returns a new one; loaded is false when the value was freshly stored.
type sync.Pool — Get() any, Put(x any)
var bufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }}; b := bufPool.Get().(*bytes.Buffer); b.Reset(); defer bufPool.Put(b)
Reusable free-list for temporary objects; reduces GC pressure — must Reset before reuse as GC may evict pooled items any time.
type sync.Cond — Wait(), Signal(), Broadcast(); sync.NewCond(l sync.Locker) *Cond
cond := sync.NewCond(&mu); mu.Lock(); for !ready { cond.Wait() }; mu.Unlock(); // producer: cond.Broadcast()
Condition variable for goroutines waiting on a shared condition; Wait atomically releases the lock and suspends until Signal or Broadcast.
sync/atomic
type atomic.Int64 — Load() int64, Store(v int64), Add(delta int64) int64, Swap(new int64) int64, CompareAndSwap(old, new int64) bool
var reqs atomic.Int64; reqs.Add(1) // safe from multiple goroutines
Lock-free counter; prefer typed atomics (Int64, Bool) over the old Add/Load functions for type safety.
type atomic.Int32 — Load() int32, Store(v int32), Add(delta int32) int32, Swap, CompareAndSwap
var activeConns atomic.Int32; activeConns.Add(1); defer activeConns.Add(-1)
Typed 32-bit signed atomic integer; same API as Int64 but uses half the memory — useful when the counter fits in 32 bits.
type atomic.Uint32 — Load() uint32, Store(v uint32), Add(delta uint32) uint32, Swap, CompareAndSwap
var seq atomic.Uint32; id := seq.Add(1) // monotonic request ID
Unsigned 32-bit atomic; wraps around at 2^32 — good for sequence numbers that never go negative.
type atomic.Uint64 — Load() uint64, Store(v uint64), Add(delta uint64) uint64, Swap, CompareAndSwap
var bytesWritten atomic.Uint64; bytesWritten.Add(uint64(len(buf)))
Unsigned 64-bit atomic; covers byte counts and timestamps beyond int64 range without wrapping to negative.
type atomic.Bool — Load() bool, Store(v bool), Swap(new bool) bool, CompareAndSwap(old, new bool) bool
var shutdownFlag atomic.Bool; shutdownFlag.Store(true); if shutdownFlag.Load() { return }
Atomic boolean flag — cleaner than an int32 used as a bool; zero value is false, safe to use without initialisation.
type atomic.Uintptr — Load() uintptr, Store(v uintptr), Add(delta uintptr) uintptr, Swap, CompareAndSwap
var epoch atomic.Uintptr; epoch.Add(1) // generation counter for invalidation
Atomic uintptr; typically used to store raw pointer-sized integers or cache-generation counters without full Pointer[T] overhead.
type atomic.Pointer[T any] — Load() *T, Store(v *T), Swap(new *T) *T, CompareAndSwap(old, new *T) bool
var cfg atomic.Pointer[Config]; cfg.Store(&newCfg); cur := cfg.Load() // hot-swap config
Type-safe atomic pointer — store a newly allocated value to atomically publish it to all readers without locks (copy-on-write pattern).
type atomic.Value — Load() any, Store(v any), Swap(new any) any, CompareAndSwap(old, new any) bool
var routes atomic.Value; routes.Store(newRouteTable); tbl := routes.Load().(RouteTable)
Atomic container for any value; Store panics if the concrete type changes between calls — use Pointer[T] for type safety in new code.
math
func math.Abs(x float64) float64 — math.Ceil, math.Floor, math.Round
math.Abs(-3.7) // 3.7; math.Ceil(1.2) // 2; math.Floor(1.9) // 1; math.Round(1.5) // 2
Basic rounding/absolute-value helpers; Round uses round-half-away-from-zero, unlike banker's rounding.
func math.Sqrt(x float64) float64 — math.Pow(x, y float64) float64 — math.Exp(x float64) float64
dist := math.Sqrt(dx*dx + dy*dy); prob := math.Exp(-cost / temp) // simulated annealing
Sqrt is faster than Pow(x, 0.5); Exp(x) computes e^x and is the inverse of Log — common in probability and physics simulations.
func math.Log(x float64) float64 — math.Log2(x float64) float64 — math.Log10(x float64) float64
bits := int(math.Log2(float64(n))) + 1 // number of bits needed; math.Log10(1000) // 3
Log is natural (base e); Log2 and Log10 are exact for powers of 2/10; use Log(x)/Log(b) for arbitrary base b.
func math.Min(x, y float64) float64 — math.Max(x, y float64) float64
clamp := math.Min(math.Max(val, lo), hi) // clamp val to [lo, hi]
Float64 min/max; note Go 1.21+ adds builtin min/max for ordered types — prefer builtins for integers, math.Min/Max for floats with NaN handling.
func math.Inf(sign int) float64 — math.IsInf(f float64, sign int) bool — math.IsNaN(f float64) bool
if math.IsNaN(v) || math.IsInf(v, 0) { return fmt.Errorf("invalid sensor reading: %v", v) }
math.Inf(1) is +Inf, math.Inf(-1) is -Inf; IsInf(f, 0) checks either sign — always validate float inputs from external sources.
const math.Pi — const math.E — const math.Phi — const math.Sqrt2
circumference := 2 * math.Pi * radius; area := math.Pi * radius * radius
High-precision float64 constants (Pi has 20+ decimal digits of precision); use math.Pi rather than defining your own 3.14159…
func math.Sin(x float64) float64 — math.Cos — math.Tan — math.Atan2(y, x float64) float64
angle := math.Atan2(dy, dx) // heading in radians; x := r * math.Cos(angle); y := r * math.Sin(angle)
Atan2 handles all quadrants correctly (unlike Atan) — use it to convert Cartesian to polar coordinates.
math/rand/v2
func rand.IntN(n int) int — rand.Float64() float64 — rand.N[T intType](n T) T (Go 1.22)
i := rand.IntN(100) // [0,100); f := rand.Float64() // [0.0,1.0); d := rand.N(time.Second) // random duration
Package-level functions use a global PCG source; math/rand/v2 is not seeded with 1 at startup — safe for random output without manual seeding.
func rand.New(src rand.Source) *rand.Rand — rand.NewPCG(seed1, seed2 uint64) *rand.PCG
rng := rand.New(rand.NewPCG(42, 0)); rng.IntN(1000) // deterministic sequence
Create a seeded Rand for reproducible tests or simulations; PCG is the default source in v2 — faster and higher quality than the old LCG.
func (*rand.Rand) Shuffle(n int, swap func(i, j int))
rng.Shuffle(len(deck), func(i, j int) { deck[i], deck[j] = deck[j], deck[i] })
Fisher-Yates shuffle in O(n); the swap callback pattern works for any slice type without reflection.
net
func net.Dial(network, address string) (net.Conn, error)
conn, err := net.Dial("tcp", "api.example.com:443"); if err != nil { return err }; defer conn.Close()
Opens a TCP connection; use "udp" for UDP or "unix" for Unix domain sockets. Returns an io.ReadWriteCloser.
func net.DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
conn, err := net.DialTimeout("tcp", "db.internal:5432", 5*time.Second)
Like Dial but aborts if the connection is not established within the timeout — essential for avoiding indefinite hangs.
func net.Listen(network, address string) (net.Listener, error)
ln, err := net.Listen("tcp", ":8080"); if err != nil { log.Fatal(err) }
Binds a local port and returns a Listener; call Accept in a loop to handle incoming connections.
func (l net.Listener) Accept() (net.Conn, error)
for { conn, err := ln.Accept(); if err != nil { return }; go handleConn(conn) }
Blocks until a new connection arrives; spawn a goroutine per connection to avoid blocking the accept loop.
func (c net.Conn) SetDeadline(t time.Time) error
conn.SetDeadline(time.Now().Add(10 * time.Second))
Sets both read and write deadlines; call SetReadDeadline / SetWriteDeadline to control them independently.
func (c net.Conn) Read(b []byte) (n int, err error) / Write(b []byte) (n int, err error)
n, err := conn.Write([]byte("PING\n")); buf := make([]byte, 512); n, err = conn.Read(buf)
Implement io.Reader/Writer; partial reads are normal — wrap with bufio.Scanner or io.ReadFull for framing.
func net.ResolveTCPAddr(network, address string) (*net.TCPAddr, error)
addr, err := net.ResolveTCPAddr("tcp", "localhost:8080")
Resolves a host:port string to a structured TCPAddr with IP, Port, and Zone fields.
func net.LookupHost(host string) (addrs []string, err error)
addrs, err := net.LookupHost("example.com") // ["93.184.216.34"]
DNS A/AAAA lookup returning string addresses; use LookupIP to get net.IP values instead.
func net.LookupMX(name string) ([]*net.MX, error)
records, err := net.LookupMX("gmail.com"); for _, mx := range records { fmt.Println(mx.Host, mx.Pref) }
Returns MX records sorted by preference; useful for validating email domains before sending.
func net.ParseIP(s string) net.IP
ip := net.ParseIP("192.168.1.1"); if ip == nil { return errors.New("invalid IP") }
Parses IPv4 or IPv6 address strings; returns nil for invalid input — always check before using.
func (*net.IPNet) Contains(ip net.IP) bool — from net.ParseCIDR
_, network, _ := net.ParseCIDR("10.0.0.0/8"); ok := network.Contains(net.ParseIP("10.1.2.3"))
ParseCIDR returns both the host IP and the network; use Contains to check if an IP belongs to a subnet.
net/http
func http.Get(url string) (*http.Response, error)
resp, err := http.Get("https://api.example.com/data"); if err != nil { return err }; defer resp.Body.Close()
Quick GET via DefaultClient — always close Body to release the connection back to the pool.
func http.Post(url, contentType string, body io.Reader) (*http.Response, error)
resp, err := http.Post("https://api.example.com/submit", "application/json", bytes.NewReader(payload))
Convenience POST via DefaultClient; prefer NewRequestWithContext for production to attach timeouts and auth headers.
func http.Head(url string) (*http.Response, error)
resp, err := http.Head("https://cdn.example.com/file.zip"); size := resp.Header.Get("Content-Length")
Fetches only headers — useful for checking file size or ETag before downloading large resources.
func http.NewRequest(method, url string, body io.Reader) (*http.Request, error)
req, _ := http.NewRequest(http.MethodDelete, "https://api.example.com/item/42", nil)
Creates a Request without a context; prefer NewRequestWithContext in any production code that should be cancellable.
func http.NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error)
req, _ := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(payload)); req.Header.Set("Authorization", "Bearer "+token)
Always use the Context variant in production — it enables timeout, cancellation, and tracing propagation.
http.Client{Timeout: time.Duration} — Do / Get / Post
client := &http.Client{Timeout: 10 * time.Second}; resp, err := client.Do(req)
Always set a Timeout on your Client — DefaultClient has none, so a slow server will hang your goroutine forever.
http.DefaultClient *http.Client
// http.Get, Post, Head use DefaultClient — fine for scripts, not for servers
DefaultClient has no timeout and a shared Transport; create a custom Client in long-running services.
http.Transport — RoundTrip, MaxIdleConns, IdleConnTimeout, TLSClientConfig
tr := &http.Transport{MaxIdleConnsPerHost: 20, IdleConnTimeout: 90 * time.Second}; client := &http.Client{Transport: tr}
Tune the connection pool for high-throughput services; a shared Transport reuses TCP connections across requests.
func http.Handle(pattern string, handler http.Handler)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
Registers on DefaultServeMux; prefer an explicit ServeMux to avoid global state collisions in tests and libraries.
func http.HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
Adapts a plain function to http.Handler via http.HandlerFunc; registers on DefaultServeMux.
func http.NewServeMux() *http.ServeMux — Handle / HandleFunc
mux := http.NewServeMux(); mux.HandleFunc("GET /users/{id}", getUser); mux.HandleFunc("POST /users", createUser)
Go 1.22+ supports method+pattern routing ("GET /path/{id}") and PathValue extraction directly on ServeMux.
func http.ListenAndServe(addr string, handler http.Handler) error
if err := http.ListenAndServe(":8080", mux); err != nil { log.Fatal(err) }
Starts an HTTP server; blocks until error — use http.Server with Shutdown for graceful shutdown in production.
func http.ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler) error
http.ListenAndServeTLS(":443", "cert.pem", "key.pem", mux)
Serves HTTPS; provide Let's Encrypt certs via golang.org/x/crypto/acme/autocert for automatic renewal.
http.Request — Method / URL / Header / Body / Context / FormValue / PathValue
id := r.PathValue("id"); auth := r.Header.Get("Authorization"); q := r.URL.Query().Get("limit")
PathValue (Go 1.22) extracts named segments from the mux pattern; FormValue parses both query params and POST body.
http.ResponseWriter — Header() / Write([]byte) / WriteHeader(statusCode int)
w.Header().Set("Content-Type", "application/json"); w.WriteHeader(http.StatusCreated); json.NewEncoder(w).Encode(resp)
Set headers before calling WriteHeader or Write — once either is called, headers are sent and cannot be changed.
func http.Error(w http.ResponseWriter, error string, code int)
http.Error(w, "not found", http.StatusNotFound)
Writes a plain-text error response with the given status code; sets Content-Type to text/plain automatically.
HTTP status constants — http.StatusOK / StatusCreated / StatusNoContent / StatusBadRequest / StatusUnauthorized / StatusForbidden / StatusNotFound / StatusInternalServerError
w.WriteHeader(http.StatusUnprocessableEntity) // 422
Named constants from RFC 9110 — use them instead of bare integers to make intent clear and searchable.
func http.FileServer(root http.FileSystem) http.Handler / func http.StripPrefix(prefix string, h http.Handler) http.Handler
mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("./dist"))))
StripPrefix removes the URL prefix before FileServer sees the path — required when the mount point isn't the root.
http.Cookie / func http.SetCookie(w http.ResponseWriter, cookie *http.Cookie)
http.SetCookie(w, &http.Cookie{Name: "session", Value: token, HttpOnly: true, Secure: true, SameSite: http.SameSiteLaxMode})
Always set HttpOnly and Secure for session cookies; SameSite: Lax blocks most CSRF without breaking navigation.
func http.MaxBytesReader(w http.ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser
r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // 1 MiB limit
Wraps the request body with a size limit; returns an error if the client sends more, preventing memory exhaustion.
net/http/httptest
func httptest.NewRecorder() *httptest.ResponseRecorder — Body *bytes.Buffer, Code int, Result() *http.Response
w := httptest.NewRecorder(); MyHandler(w, httptest.NewRequest("GET", "/healthz", nil)); if w.Code != http.StatusOK { t.Fail() }
In-memory ResponseWriter for unit testing HTTP handlers; inspect Code and Body without a real server.
func httptest.NewServer(handler http.Handler) *httptest.Server — URL string, Client *http.Client, Close()
ts := httptest.NewServer(mux); defer ts.Close(); resp, _ := ts.Client().Get(ts.URL + "/users/1")
Starts a real HTTP server on a random localhost port; use ts.Client() to get a pre-configured client that talks to it.
func httptest.NewTLSServer(handler http.Handler) *httptest.Server
ts := httptest.NewTLSServer(mux); defer ts.Close(); resp, _ := ts.Client().Get(ts.URL + "/secure")
Like NewServer but serves HTTPS with a self-signed cert; ts.Client() is pre-configured to trust it.
func httptest.NewUnstartedServer(handler http.Handler) *httptest.Server — Start() / StartTLS()
ts := httptest.NewUnstartedServer(mux); ts.Config.ReadTimeout = 5 * time.Second; ts.Start()
Lets you customise Server fields (timeouts, TLS config) before starting — needed when testing timeout-sensitive handlers.
net/url
func url.Parse(rawurl string) (*url.URL, error)
u, err := url.Parse("https://api.example.com/v1/users?limit=10#results")
Parses any URL reference (absolute or relative); use ParseRequestURI when you need to reject relative URLs.
url.URL — Scheme / Host / Path / RawQuery / Fragment / String()
u.Scheme = "https"; u.Host = "api.example.com"; u.Path = "/v2/users"; fmt.Println(u.String())
URL is a mutable struct — modify fields then call String() to reconstruct; use RawQuery for pre-encoded query strings.
func (u *url.URL) Query() url.Values
vals := u.Query(); vals.Set("page", "2"); u.RawQuery = vals.Encode()
Parses RawQuery into a Values map; mutate, then re-assign Encode() result back to RawQuery.
url.Values — Get / Set / Add / Del / Encode
v := url.Values{}; v.Set("q", "golang"); v.Add("tag", "net"); v.Add("tag", "http"); req.URL.RawQuery = v.Encode()
Values is map[string][]string; Add appends to a key's slice, Set replaces it — Encode produces percent-encoded output.
func url.ParseQuery(query string) (url.Values, error)
vals, err := url.ParseQuery(r.URL.RawQuery); limit := vals.Get("limit")
Decodes a query string into Values; equivalent to url.Parse then .Query(), but useful when you already have the raw string.
func url.QueryEscape(s string) string / func url.QueryUnescape(s string) (string, error)
encoded := url.QueryEscape("hello world & more") // "hello+world+%26+more"
QueryEscape encodes spaces as '+' (application/x-www-form-urlencoded); use PathEscape for URL path segments instead.
func url.JoinPath(base string, elem ...string) (string, error)
u, _ := url.JoinPath("https://api.example.com/", "v1", "users", id) // safe path joining
Added in Go 1.19; joins path segments safely, escaping each element — prevents directory traversal bugs from string concat.
encoding/json
func json.Marshal(v any) ([]byte, error)
b, err := json.Marshal(resp); w.Header().Set("Content-Type", "application/json"); w.Write(b)
Encodes v to JSON bytes; returns error for unserializable types (channels, functions, cyclic structs).
func json.Unmarshal(data []byte, v any) error
var order Order; if err := json.Unmarshal(body, &order); err != nil { http.Error(w, err.Error(), http.StatusBadRequest); return }
Decodes JSON bytes into v; numbers decode as float64 unless the target field is typed otherwise. Always pass a pointer.
func json.MarshalIndent(v any, prefix, indent string) ([]byte, error)
b, _ := json.MarshalIndent(cfg, "", " "); os.WriteFile("config.json", b, 0644)
Same as Marshal but pretty-prints with indentation; handy for writing human-readable config files or debug dumps.
func json.NewEncoder(w io.Writer) *json.Encoder — Encode(v any) error
enc := json.NewEncoder(w); enc.SetIndent("", " "); if err := enc.Encode(payload); err != nil { log.Fatal(err) }
Writes JSON directly to a writer without buffering the full byte slice — preferred for HTTP response bodies and large structs.
func json.NewDecoder(r io.Reader) *json.Decoder — Decode(v any) error, DisallowUnknownFields()
dec := json.NewDecoder(r.Body); dec.DisallowUnknownFields(); if err := dec.Decode(&req); err != nil { }
Streams JSON from a reader; DisallowUnknownFields rejects payloads with keys not in the struct — use in APIs to catch client bugs early.
json.RawMessage (type RawMessage []byte)
type Event struct { Type string; Payload json.RawMessage }; var e Event; json.Unmarshal(data, &e); json.Unmarshal(e.Payload, &specific)
Defers decoding of a JSON subtree; useful for polymorphic events where you decode the envelope first, then the payload based on Type.
json.Number (type Number string) — Int64() (int64, error), Float64() (float64, error), String() string
dec := json.NewDecoder(r); dec.UseNumber(); var m map[string]any; dec.Decode(&m); id, _ := m["id"].(json.Number).Int64()
Preserves large integers without float64 precision loss; call Decoder.UseNumber() so numeric values decode as json.Number instead of float64.
Struct tags: json:"name" / json:"name,omitempty" / json:"-" / json:"name,string"
type User struct {
ID int64 `json:"id,string"` // encode int as JSON string
Email string `json:"email"`
Password string `json:"-"` // never marshaled
Bio string `json:"bio,omitempty"`
}
Tags control field names and marshaling behavior; omitempty skips zero values; "-" excludes the field entirely; "string" coerces the value to a JSON string.
interface json.Marshaler — MarshalJSON() ([]byte, error)
func (d Date) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Time.Format("2006-01-02"))
}
Implement MarshalJSON on a type to customize its JSON representation — used for time.Time formatting, enum strings, or redacted fields.
interface json.Unmarshaler — UnmarshalJSON([]byte) error
func (d *Date) UnmarshalJSON(b []byte) error {
var s string; json.Unmarshal(b, &s); d.Time, _ = time.Parse("2006-01-02", s); return nil
}
Implement UnmarshalJSON to parse non-standard JSON formats into your type — the raw bytes include surrounding quotes for strings.
func json.Valid(data []byte) bool
if !json.Valid(body) { http.Error(w, "invalid JSON", http.StatusBadRequest); return }
Reports whether data is valid JSON without unmarshaling it — cheap pre-validation before storing raw bytes or forwarding to another service.
Decoder.Token() (json.Token, error) — streaming token-by-token parse
dec := json.NewDecoder(r); for dec.More() { t, _ := dec.Token(); /* handle Delim, string, float64, bool, nil */ }
Reads JSON one token at a time (delimiters, strings, numbers, booleans); use for streaming large arrays without loading the whole document.
encoding/xml
func xml.Marshal(v any) ([]byte, error)
b, err := xml.Marshal(invoice); if err != nil { return err }; w.Write([]byte(xml.Header)); w.Write(b)
Encodes v to XML; prepend xml.Header ("<?xml version=…?>\n") for well-formed documents. Uses XMLName field or type name as root element.
func xml.Unmarshal(data []byte, v any) error
var inv Invoice; if err := xml.Unmarshal(body, &inv); err != nil { return fmt.Errorf("parse invoice: %w", err) }
Decodes XML into v; struct fields are matched by their xml tag name; unknown elements are silently ignored by default.
func xml.MarshalIndent(v any, prefix, indent string) ([]byte, error)
b, _ := xml.MarshalIndent(catalog, "", "\t"); os.WriteFile("catalog.xml", b, 0644)
Same as Marshal but formats the output with indentation — useful for writing human-readable XML config or fixture files.
func xml.NewEncoder(w io.Writer) *xml.Encoder — Encode(v any) error, EncodeToken(t xml.Token) error, Flush() error
enc := xml.NewEncoder(w); enc.Indent("", " "); enc.Encode(item); enc.Flush()
Streams XML to a writer; call Flush() to ensure buffered tokens are written — essential when writing to a network connection.
Encoder.EncodeToken(t xml.Token) error — StartElement, EndElement, CharData, Comment, ProcInst
enc.EncodeToken(xml.StartElement{Name: xml.Name{Local: "price"}}); enc.EncodeToken(xml.CharData("19.99")); enc.EncodeToken(xml.EndElement{Name: xml.Name{Local: "price"}})
Writes individual XML tokens for fine-grained control — use when building XML documents with dynamic structure not expressible via struct tags.
func xml.NewDecoder(r io.Reader) *xml.Decoder — Decode(v any) error, Token() (xml.Token, error), RawToken() (xml.Token, error)
dec := xml.NewDecoder(resp.Body); for { t, err := dec.Token(); if err == io.EOF { break }; /* process StartElement, CharData … */ }
Streams XML parsing; Token resolves entities and handles namespaces, RawToken skips entity expansion — use for large feeds where loading the whole doc is impractical.
Struct tags: xml:"name" / xml:"name,attr" / xml:",chardata" / xml:",omitempty" / xml:",innerxml"
type Product struct {
XMLName xml.Name `xml:"product"`
SKU string `xml:"sku,attr"` // <product sku="…">
Name string `xml:"name"`
Price float64 `xml:"price,omitempty"`
RawSpec string `xml:",innerxml"` // raw inner XML preserved
}
Tags control element names, attributes, and character data; ",attr" maps to an XML attribute; ",chardata" captures text content; ",innerxml" preserves raw XML subtrees.
xml:",chardata" — capture element text content
type Description struct {
Lang string `xml:"lang,attr"`
Text string `xml:",chardata"`
}
// <description lang="en">Great product</description>
The ",chardata" tag captures the text node inside an element into the field; combine with ",attr" tags on sibling fields to also capture attributes.
encoding/csv
func csv.NewReader(r io.Reader) *csv.Reader — Read() ([]string, error), ReadAll() ([][]string, error)
f, _ := os.Open("prices.csv"); defer f.Close(); r := csv.NewReader(f); r.TrimLeadingSpace = true; records, err := r.ReadAll()
Parses CSV from any Reader; ReadAll loads the entire file into memory; for large price catalogs iterate with Read() in a loop to process row by row.
Reader.FieldsPerRecord int — 0=infer from first row, -1=allow variable, N=require exactly N
r := csv.NewReader(f); r.FieldsPerRecord = -1; for { row, err := r.Read(); if err == io.EOF { break }; processRow(row) }
Set to -1 to tolerate rows with varying column counts (common in legacy exports); set to a positive N to enforce schema and get an error on malformed rows.
Reader.LazyQuotes bool / Reader.TrimLeadingSpace bool / Reader.Comment rune
r := csv.NewReader(f); r.LazyQuotes = true; r.TrimLeadingSpace = true; r.Comment = '#'
LazyQuotes accepts bare quotes inside unquoted fields (fixes many real-world dirty CSVs); Comment skips lines beginning with that rune (e.g., metadata headers).
func csv.NewWriter(w io.Writer) *csv.Writer — Write(record []string) error, WriteAll(records [][]string) error, Flush(), Error() error
w := csv.NewWriter(os.Stdout); w.WriteAll(rows); if err := w.Error(); err != nil { return err }
Writes CSV; WriteAll flushes automatically; always check Error() after Flush/WriteAll since Write buffers and errors surface only then.
Writer.Comma rune / Writer.UseCRLF bool
w := csv.NewWriter(f); w.Comma = ';'; w.UseCRLF = true; w.WriteAll(rows); w.Flush()
Comma defaults to ','; change to ';' or '\t' for TSV and European locale exports; UseCRLF=true for Windows-compatible line endings required by Excel.
csv streaming write — per-row Write + Flush
w := csv.NewWriter(gzipWriter); for _, order := range orders { w.Write([]string{order.ID, order.SKU, fmt.Sprint(order.Qty)}); }; w.Flush(); if err := w.Error(); err != nil { return err }
Use Write in a loop for large exports (streaming to gzip, S3, etc.) to avoid holding all rows in memory; a single Flush at the end flushes the buffer.
csv skip header row — Read once before loop
r := csv.NewReader(f); header, _ := r.Read(); _ = header; for { row, err := r.Read(); if err == io.EOF { break }; /* row[0]=SKU, row[1]=price */ }
There is no built-in skip-header option; call Read() once before the loop to consume the header row, then iterate the remaining data rows.
runtime
func runtime.NumCPU() int
workers := runtime.NumCPU() * 2; sem := make(chan struct{}, workers)
Returns the number of logical CPUs available to the process; multiply by 2–4 to size worker pools or buffered semaphore channels.
func runtime.GOMAXPROCS(n int) int
prev := runtime.GOMAXPROCS(runtime.NumCPU()) // returns old value; 0 = query without changing
Sets the maximum number of OS threads that can execute Go code simultaneously; defaults to NumCPU since Go 1.5; call with 0 to query the current value.
func runtime.Gosched()
for !atomic.CompareAndSwapInt32(&ready, 0, 1) { runtime.Gosched() } // yield in spin-wait
Yields the processor, allowing other goroutines to run; use in tight spin-loops to avoid starving the scheduler on GOMAXPROCS=1 or CPU-bound goroutines.
func runtime.GC()
b.ResetTimer(); runtime.GC() // force GC before benchmark iteration to get clean heap baseline
Forces an immediate garbage collection; useful in benchmarks or tests to isolate heap effects; not needed in production code — the runtime GC is self-tuning.
runtime.GOOS string / runtime.GOARCH string
if runtime.GOOS == "windows" { sep = '\\' }; if runtime.GOARCH == "arm64" { /* Apple Silicon path */ }
Package-level string constants set at compile time; use instead of os.Getenv("GOOS") for zero-cost platform detection in library code.
func runtime.Caller(skip int) (pc uintptr, file string, line int, ok bool)
_, file, line, _ := runtime.Caller(1); fmt.Printf("%s:%d", filepath.Base(file), line) // caller of this func
Returns program counter, source file, and line number of the call stack at the given skip depth; skip=0 is Caller itself, skip=1 is the function that called Caller.
func runtime.Callers(skip int, pcs []uintptr) int
pcs := make([]uintptr, 32); n := runtime.Callers(2, pcs); frames := runtime.CallersFrames(pcs[:n])
Fills pcs with return program counters of the call stack; pass the slice to runtime.CallersFrames to get File/Line/Function for each frame — cheaper than Stack for structured use.
func runtime.FuncForPC(pc uintptr) *runtime.Func
pc, _, _, _ := runtime.Caller(1); fn := runtime.FuncForPC(pc); fmt.Println(fn.Name()) // e.g. "main.handleRequest"
Returns the *Func describing the function containing the given PC; call .Name() for the fully qualified function name, .FileLine(pc) for source location.
func runtime.Stack(buf []byte, all bool) int
buf := make([]byte, 64<<10); n := runtime.Stack(buf, false); log.Printf("goroutine stack:\n%s", buf[:n])
Writes goroutine stack trace(s) into buf and returns the byte count; all=false captures only the current goroutine, all=true captures every goroutine — useful in panic handlers.
func runtime.ReadMemStats(m *runtime.MemStats)
var m runtime.MemStats; runtime.ReadMemStats(&m); fmt.Printf("alloc=%d MB numGC=%d", m.Alloc>>20, m.NumGC)
Populates MemStats with current heap/GC metrics; stops the world briefly — avoid in tight loops; useful in health-check endpoints or profiling scripts to expose live memory figures.
log/slog
func slog.Info(msg string, args ...any)
slog.Info("request completed", "user_id", userID, "latency_ms", latency.Milliseconds())
Logs at Info level using the default logger; alternating key/value pairs become structured fields; no allocation for disabled levels (zerolog-style fast path since Go 1.21).
func slog.Error(msg string, args ...any)
slog.Error("db query failed", "request_id", reqID, "err", err)
Logs at Error level; pass the error as the "err" key — slog formats it via its Error() string; use instead of log.Printf so structured handlers can index the error field.
func slog.Debug(msg string, args ...any) / func slog.Warn(msg string, args ...any)
slog.Debug("cache miss", "key", key); slog.Warn("quota near limit", "used_pct", pct)
Debug is a no-op when the handler level is Info or above — zero allocation; Warn sits between Info and Error for non-fatal anomalies that need monitoring attention.
func slog.Log(ctx context.Context, level slog.Level, msg string, args ...any)
slog.Log(ctx, slog.LevelInfo+2, "audit", "actor", actor, "action", action) // custom level between Info and Warn
Logs at an arbitrary Level, including custom numeric levels; the ctx is passed to the handler so it can extract trace-IDs or deadlines from context values.
func slog.With(args ...any) *slog.Logger
logger := slog.With("service", "payments", "env", os.Getenv("ENV")); logger.Info("started")
Returns a new Logger derived from the default logger with the given attributes pre-attached to every subsequent log line — ideal for request-scoped or service-level fields.
func (*slog.Logger) WithGroup(name string) *slog.Logger
reqLog := slog.Default().WithGroup("request"); reqLog.Info("handled", "method", r.Method, "path", r.URL.Path) // JSON: {"request":{"method":"GET","path":"/"}}
Nests subsequent fields under the given group name in the output; in JSON handlers this produces a nested object, in text handlers it prefixes keys with "group.".
func slog.New(h slog.Handler) *slog.Logger
logger := slog.New(slog.NewJSONHandler(os.Stderr, nil)); logger.Info("ready", "pid", os.Getpid())
Creates a Logger wrapping any slog.Handler; use to swap handlers in tests (e.g. slogtest.NewTestHandler) without changing call sites that use the logger.
func slog.NewJSONHandler(w io.Writer, opts *slog.HandlerOptions) *slog.JSONHandler
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})); slog.SetDefault(logger)
Creates a structured JSON logger; call SetDefault so top-level slog.Info/Error use it throughout the program.
func slog.NewTextHandler(w io.Writer, opts *slog.HandlerOptions) *slog.TextHandler
h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug, AddSource: true}); slog.SetDefault(slog.New(h))
Outputs logfmt-style key=value lines; AddSource=true appends file:line to every record — useful during local development when JSON is hard to scan quickly.
slog.HandlerOptions{Level slog.Leveler, AddSource bool, ReplaceAttr func(groups []string, a slog.Attr) slog.Attr}
opts := &slog.HandlerOptions{Level: slog.LevelDebug, AddSource: true, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { if a.Key == slog.TimeKey { a.Key = "ts" }; return a }}
ReplaceAttr lets you rename, redact, or drop fields globally — rename "time" to "ts" for Elasticsearch, scrub "password" values, or drop the source key in prod builds.
slog.LevelDebug / slog.LevelInfo / slog.LevelWarn / slog.LevelError
minLevel := slog.LevelInfo; if os.Getenv("DEBUG") == "1" { minLevel = slog.LevelDebug }; slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: minLevel})))
Predefined Level constants (int values -4/0/4/8); compare or combine arithmetically to define custom levels between them (e.g. LevelInfo+2 for a "notice" level).
func slog.String(key, value string) slog.Attr / slog.Int / slog.Bool / slog.Duration / slog.Any
slog.Info("signup", slog.String("user_id", uid), slog.Int("plan", planID), slog.Duration("latency", d))
Typed Attr constructors avoid reflection — prefer over bare key/value pairs in hot paths where the allocator matters; slog.Any handles arbitrary values via fmt.Stringer or json.Marshaler.
func slog.Group(key string, args ...any) slog.Attr
slog.Info("request", slog.Group("http", "method", r.Method, "status", code, "bytes", written)) // JSON: {"http":{"method":"GET","status":200}}
Creates a nested attribute group inline at the call site; equivalent to WithGroup but scoped to a single log line rather than all subsequent calls on the logger.
func slog.SetDefault(l *slog.Logger)
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))); slog.Info("server starting", "addr", addr) // also redirects log.Printf output
Replaces the package-level default logger; also bridges the old log package so log.Printf output is routed through the new structured handler — migrate incrementally.
type slog.LogValuer interface { LogValue() slog.Value }
type Secret struct{ v string }; func (s Secret) LogValue() slog.Value { return slog.StringValue("[REDACTED]") }; slog.Info("auth", "token", Secret{tok})
Implement LogValuer on sensitive types so they always log as "[REDACTED]" regardless of call site — safer than relying on every caller to remember to redact.
testing
func (t *testing.T) Run(name string, f func(t *testing.T)) bool
for _, tc := range []struct{ in string; want int }{{"abc", 3}, {"", 0}}{ tc := tc; t.Run(tc.in, func(t *testing.T) { if got := Len(tc.in); got != tc.want { t.Errorf("got %d", got) } }) }
Runs a subtest; each subtest appears as TestFoo/name in output and can be run individually with -run; capture tc := tc before the closure when parallelising to avoid the loop-variable capture bug.
func (t *testing.T) Helper()
func assertEqual(t *testing.T, got, want int) { t.Helper(); if got != want { t.Errorf("got %d want %d", got, want) } }
Marks the calling function as a test helper so that t.Errorf reports the caller's file/line, not the helper's — every assertion helper should call t.Helper() as its first statement.
func (t *testing.T) Parallel()
t.Run("heavy", func(t *testing.T) { t.Parallel(); /* runs concurrently with other Parallel subtests */ })
Signals that this test can run in parallel with other parallel tests; the test pauses until its parent test function returns, then resumes alongside other parallel subtests — speeds up I/O-bound test suites.
func (t *testing.T) Cleanup(f func())
db := openTestDB(t); t.Cleanup(func() { db.Close() }) // runs after test and all subtests
Registers a cleanup function that runs when the test and all its subtests finish; prefer over defer for shared resources because it runs even if the test calls t.FailNow or t.Skip.
func (t *testing.T) Errorf(format string, args ...any) / func (t *testing.T) Fatalf(format string, args ...any)
if got != want { t.Errorf("Parse(%q) = %v, want %v", input, got, want) } // Fatalf calls FailNow — stops the test immediately
Errorf marks the test failed and continues; Fatalf marks failed and calls runtime.Goexit() to stop the goroutine immediately — use Fatalf when subsequent code would panic on bad state.
func (t *testing.T) FailNow()
if err != nil { t.Logf("setup failed: %v", err); t.FailNow() } // same as Fatalf without a message
Marks the test as failed and stops execution by calling runtime.Goexit(); unlike os.Exit it still runs Cleanup and defer functions registered on the test goroutine.
func (t *testing.T) Logf(format string, args ...any)
t.Logf("response body: %s", body) // only printed when test fails or -v flag is set
Appends a formatted message to the test's log output; the message is only shown on failure or with -v — use freely for diagnostic context without noisy CI output on passing runs.
func (t *testing.T) Skip(args ...any) / func (t *testing.T) Skipf(format string, args ...any)
if os.Getenv("INTEGRATION") == "" { t.Skip("set INTEGRATION=1 to run") }; if testing.Short() { t.Skipf("skipping %s in short mode", t.Name()) }
Marks the test as skipped and stops execution; the skip reason appears in test output; use to guard integration tests or slow tests that shouldn't run in CI fast mode.
func (b *testing.B) N int / b.ResetTimer() / b.ReportAllocs() / b.RunParallel(body func(*testing.PB))
func BenchmarkEncode(b *testing.B) { b.ReportAllocs(); b.ResetTimer(); for i := 0; i < b.N; i++ { encode(payload) } }
B.N is auto-tuned by the framework; ResetTimer excludes setup time; ReportAllocs prints allocs/op and B/op columns; RunParallel measures throughput across GOMAXPROCS goroutines.
func (b *testing.B) RunParallel(body func(*testing.PB))
b.RunParallel(func(pb *testing.PB) { for pb.Next() { encode(payload) } }) // measures lock contention under parallel load
Runs the body in parallel across GOMAXPROCS goroutines; use to benchmark concurrent-safe functions or measure lock contention; pb.Next() replaces the b.N loop inside the body.
func testing.Short() bool
if testing.Short() { t.Skip("skipping integration test in -short mode") }
Returns true when the test binary was invoked with -test.short; convention is that -short skips slow tests — use in CI pipelines to run a fast subset before a full nightly suite.
func testing.TestMain(m *testing.M)
func TestMain(m *testing.M) { setupDB(); code := m.Run(); teardownDB(); os.Exit(code) }
Replaces the default test runner; m.Run() executes all tests and returns the exit code; use for global test fixtures (database migrations, Docker containers) that are too expensive to repeat per test.
Language Features
record Point(double x, double y) { } (Java 16+)
record OrderLine(String sku, int qty, BigDecimal unitPrice) {}
// Generated: sku(), qty(), unitPrice(), equals, hashCode, toString
OrderLine line = new OrderLine("SKU-42", 3, BigDecimal.valueOf(9.99));
System.out.println(line.sku() + " × " + line.qty());
Immutable data carrier; generates accessors, equals, hashCode, and toString — replaces boilerplate POJOs for DTOs, value objects, and domain events.
record — compact constructor (Java 16+)
record EmailAddress(String value) {
// compact constructor — params already assigned; only validate/normalize
EmailAddress {
value = value.strip().toLowerCase();
if (!value.contains("@"))
throw new IllegalArgumentException("Invalid email: " + value);
}
}
Compact constructors run before the auto-generated field assignment; ideal for validation and normalization without repeating parameter names.
sealed interface … permits (Java 17+)
sealed interface Result<T> permits Ok, Err {}
record Ok<T>(T value) implements Result<T> {}
record Err<T>(String msg) implements Result<T> {}
Result<User> load(long id) {
return repo.find(id).map(Ok::new).orElse(new Err("Not found"));
}
Sealed types restrict which classes may implement an interface; combined with records they produce exhaustive, algebraic-style sum types the compiler can verify.
instanceof pattern matching (Java 16+)
void describe(Object obj) {
if (obj instanceof String s && s.length() > 10)
System.out.println("Long string: " + s.toUpperCase());
else if (obj instanceof Integer n && n < 0)
System.out.println("Negative int: " + n);
else if (obj instanceof List<?> list)
System.out.println("List size: " + list.size());
}
Pattern-matching instanceof binds the cast variable inline; the && guard is evaluated only when the pattern matches, eliminating redundant casts.
Pattern matching switch — type patterns (Java 21+)
sealed interface Shape permits Circle, Rect, Triangle {}
record Circle(double r) implements Shape {}
record Rect(double w, double h) implements Shape {}
record Triangle(double b, double h) implements Shape {}
double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.r() * c.r();
case Rect r -> r.w() * r.h();
case Triangle t -> 0.5 * t.b() * t.h();
}; // exhaustive — no default needed
}
Switch over a sealed hierarchy is exhaustive; the compiler rejects missing cases, giving you type-safe dispatch without casting.
Record patterns in switch — destructuring (Java 21+)
String format(Result<String> result) {
return switch (result) {
case Ok(var v) -> "Success: " + v;
case Err(var m) -> "Error: " + m;
};
}
// Nested destructuring
record Point(int x, int y) {}
record Line(Point from, Point to) {}
String describe(Line l) {
return switch (l) {
case Line(Point(var x1, var y1), Point(var x2, var y2))
-> "("+x1+","+y1+") → ("+x2+","+y2+")";
};
}
Record patterns deconstruct record components inline inside switch — including nested records — without explicit accessor calls.
Text blocks — """…""" (Java 15+)
String sql = """
SELECT u.id, u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE u.active = true
AND o.total > :minTotal
ORDER BY o.total DESC
""";
String json = """
{
"event": "order.placed",
"orderId": %d,
"amount": %.2f
}
""".formatted(orderId, amount);
Text blocks preserve indentation via a common-whitespace stripping algorithm; the closing """ determines the indent baseline, eliminating \n and concat noise.
var — local variable type inference (Java 10+)
var users = new ArrayList<User>(); // ArrayList<User>
var map = Map.of("a", 1, "b", 2); // Map<String, Integer>
var entries = map.entrySet(); // Set<Map.Entry<String,Integer>>
try (var conn = DataSource.getConnection()) { // Connection — works in try-with-resources
var stmt = conn.prepareStatement(sql);
var rs = stmt.executeQuery();
}
var reduces verbosity for obvious right-hand sides; the inferred type is still static — use it where the type is clear from context, avoid it where it obscures intent.
Switch expressions — arrow cases & yield (Java 14+)
int fee = switch (tier) {
case FREE -> 0;
case BASIC, STANDARD -> 500;
case PRO -> 1_200;
case ENTERPRISE -> {
int base = lookupContractBase(account);
yield base + 3_000; // yield required in block arms
}
};
// Multiple labels collapse duplicate logic
String category = switch (statusCode) {
case 200, 201, 204 -> "success";
case 400, 422 -> "client-error";
default -> "other";
};
Switch expressions are statements that return a value; arrow cases don't fall through, and yield exits a block arm — no break needed.
@FunctionalInterface — custom SAM + lambda (Java 8+)
@FunctionalInterface
interface Validator<T> {
List<String> validate(T value);
default Validator<T> andThen(Validator<T> next) {
return v -> {
var errors = new ArrayList<>(this.validate(v));
errors.addAll(next.validate(v));
return errors;
};
}
}
Validator<String> notBlank = s ->
s.isBlank() ? List.of("must not be blank") : List.of();
Validator<String> maxLen = s ->
s.length() > 255 ? List.of("max 255 chars") : List.of();
Validator<String> emailVal = notBlank.andThen(maxLen);
@FunctionalInterface enforces exactly one abstract method; lambdas implement it without anonymous class boilerplate, and default methods add composability.
Unnamed patterns _ (Java 22+)
// Unnamed pattern variable in switch — ignore components you don't need
String label(Result<?> r) {
return switch (r) {
case Ok(var v) -> "ok:" + v;
case Err(_) -> "error"; // _ discards the msg component
};
}
// Unnamed catch variable — acknowledge exception without naming it
try {
return Integer.parseInt(input);
} catch (NumberFormatException _) {
return 0; // _ suppresses "variable unused" warning
}
The unnamed pattern _ signals intentional discard of a bound variable; eliminates IDE warnings about unused names in catch blocks and switch destructuring.
instanceof pattern with guard (Java 21+)
sealed interface Event permits Login, Purchase, Refund {}
record Login(String userId, boolean mfa) implements Event {}
record Purchase(String userId, BigDecimal amount) implements Event {}
record Refund(String userId, BigDecimal amount) implements Event {}
String audit(Event e) {
return switch (e) {
case Login l when !l.mfa() -> "⚠ MFA bypass: " + l.userId();
case Login l -> "login: " + l.userId();
case Purchase p when p.amount().compareTo(THRESHOLD) > 0
-> "high-value: $" + p.amount();
case Purchase p -> "purchase: $" + p.amount();
case Refund r -> "refund: $" + r.amount();
};
}
when guards refine a type pattern with a boolean predicate; more specific guarded cases must appear before broader ones of the same type, or the compiler rejects the switch.
java.lang
String
String.length() → int | String.charAt(int index) → char | String.isEmpty() → boolean
String s = "hello";
s.length(); // 5
s.charAt(1); // 'e'
"".isEmpty(); // true
Fundamental accessors: length() returns the number of UTF-16 code units; charAt(i) returns the char at index i (throws IndexOutOfBoundsException if out of range); isEmpty() is equivalent to length() == 0.
String.substring(int beginIndex, int endIndex) → String | String.indexOf(String str) → int | String.lastIndexOf(String str) → int
String s = "hello world";
s.substring(6); // "world"
s.substring(0, 5); // "hello"
s.indexOf("o"); // 4
s.lastIndexOf("o"); // 7
substring(begin, end) returns chars from begin (inclusive) to end (exclusive); indexOf returns first occurrence index or -1; lastIndexOf returns the last occurrence.
String.contains(CharSequence s) → boolean | String.startsWith(String prefix) → boolean | String.endsWith(String suffix) → boolean
String url = "https://example.com/api";
url.startsWith("https"); // true
url.endsWith("/api"); // true
url.contains("example"); // true
Membership tests that read naturally left-to-right; all return false rather than throwing on null argument (contains throws NullPointerException on null).
String.replace(char oldChar, char newChar) → String | String.replaceAll(String regex, String replacement) → String | String.replaceFirst(String regex, String replacement) → String
"a.b.c".replace('.', '-'); // "a-b-c"
"foo123bar456".replaceAll("\\d+", "#"); // "foo#bar#"
"foo123bar456".replaceFirst("\\d+", "#");// "foo#bar456"
replace(char,char) and replace(CharSequence,CharSequence) use literal matching; replaceAll/replaceFirst use regex — remember to escape regex metacharacters like ..
String.strip() → String | String.stripLeading() → String | String.stripTrailing() → String | String.isBlank() → boolean (Java 11+)
String s = " hello ";
s.strip(); // "hello" — Unicode-aware (vs trim())
s.stripLeading(); // "hello "
s.stripTrailing(); // " hello"
" \t\n".isBlank(); // true
Java 11+ Unicode-aware whitespace handling; prefer strip() over the legacy trim() which only handles ASCII control chars ≤ U+0020. isBlank() is true when empty or all whitespace.
String.lines() → Stream<String> (Java 11+)
long count = "line1\nline2\nline3"
.lines()
.filter(l -> l.contains("line"))
.count(); // 3
Splits on \n, \r, or \r\n and returns a lazy Stream<String>; trailing empty strings are not included — useful for processing multi-line text without pre-splitting.
String.repeat(int count) → String (Java 11+)
"ab".repeat(3); // "ababab"
"-".repeat(40); // "----------------------------------------"
Returns a new string that is this string repeated count times; throws IllegalArgumentException if count is negative. Replaces the common Stream.generate/StringBuilder workarounds.
String.formatted(Object... args) → String (Java 15+)
var msg = "User %s (id=%d) logged in from %s"
.formatted(name, id, ip);
Instance-method shorthand for String.format(this, args); reads left-to-right without the static prefix. Supports the same format specifiers as printf: %s, %d, %f, %n, etc.
String.split(String regex) → String[] | String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements) → String
String[] parts = "a,b,c".split(","); // ["a","b","c"]
String joined = String.join(", ", List.of("x", "y", "z"));
// "x, y, z"
split(regex) uses a regex and trims trailing empty strings by default; pass -1 as limit to keep them. String.join is the inverse — delegates to StringJoiner internally.
String.toUpperCase() → String | String.toLowerCase() → String | String.toCharArray() → char[] | String.chars() → IntStream
"hello".toUpperCase(); // "HELLO"
"HELLO".toLowerCase(); // "hello"
char[] arr = "abc".toCharArray();
long vowels = "hello".chars()
.filter(c -> "aeiou".indexOf(c) >= 0)
.count(); // 2
toUpperCase()/toLowerCase() are locale-sensitive — use the overload with explicit Locale for locale-safe code. chars() returns UTF-16 code units as IntStream, useful for stream processing.
String.valueOf(Object obj) → String | String.format(String format, Object... args) → String | String.intern() → String
String.valueOf(42); // "42"
String.valueOf(null); // "null" (no NPE)
String.format("%.2f", 3.14159); // "3.14"
String s = new String("hello").intern(); // canonical instance
valueOf(Object) calls toString() but safely returns "null" for null references. intern() returns the canonical string pool reference — useful when memory matters but rarely needed in modern code.
StringBuilder
StringBuilder.append(Object obj) → StringBuilder (chaining)
String result = new StringBuilder()
.append("Hello")
.append(", ")
.append(name)
.append("!")
.toString();
append accepts any type (calls String.valueOf internally) and returns this for chaining. Prefer StringBuilder over + in loops to avoid O(n²) string allocation.
StringBuilder.insert(int offset, String str) → StringBuilder | StringBuilder.delete(int start, int end) → StringBuilder | StringBuilder.deleteCharAt(int index) → StringBuilder
var sb = new StringBuilder("hello world");
sb.insert(5, ","); // "hello, world"
sb.delete(5, 6); // "hello world"
sb.deleteCharAt(4); // "hell world"
insert shifts existing chars right; delete(start, end) removes chars from start (inclusive) to end (exclusive); deleteCharAt removes a single char by index.
StringBuilder.reverse() → StringBuilder
var sb = new StringBuilder("racecar");
boolean isPalindrome = sb.toString()
.equals(sb.reverse().toString()); // true
Reverses the character sequence in-place (handles surrogate pairs correctly) and returns this. Common palindrome check idiom.
StringBuilder.replace(int start, int end, String str) → StringBuilder | StringBuilder.indexOf(String str) → int | StringBuilder.length() → int | StringBuilder.charAt(int index) → char
var sb = new StringBuilder("hello world");
sb.replace(6, 11, "Java"); // "hello Java"
sb.indexOf("Java"); // 6
sb.length(); // 10
sb.charAt(0); // 'h'
replace(start, end, str) removes the range and inserts the new string, which may be shorter or longer. Mutation methods all return this for chaining.
StringBuilder.toString() → String | StringBuilder(int capacity) constructor
var sb = new StringBuilder(256); // pre-allocate for performance
for (int i = 0; i < items.size(); i++) {
if (i > 0) sb.append(", ");
sb.append(items.get(i));
}
String csv = sb.toString();
Specifying initial capacity avoids internal array resizing (default 16 chars). Call toString() once at the end — it creates a new String backed by a copy of the internal array.
Math
Math.abs(T n) | Math.min(T a, T b) | Math.max(T a, T b)
Math.abs(-7); // 7
Math.min(3, 5); // 3
Math.max(3, 5); // 5
Math.abs(Integer.MIN_VALUE); // still MIN_VALUE! (overflow)
Overloaded for int, long, float, double. Watch for the Math.abs(Integer.MIN_VALUE) trap — the result overflows and returns MIN_VALUE itself; use Math.absExact (Java 15+) to get an exception instead.
Math.pow(double a, double b) → double | Math.sqrt(double a) → double | Math.cbrt(double a) → double
Math.pow(2, 10); // 1024.0
Math.sqrt(144); // 12.0
Math.cbrt(27); // 3.0
All return double. pow is general but slow for integer exponents — use multiplication for small fixed exponents. cbrt handles negative inputs correctly (returns negative result), unlike pow(x, 1.0/3).
Math.floor(double a) → double | Math.ceil(double a) → double | Math.round(double a) → long
Math.floor(2.9); // 2.0
Math.ceil(2.1); // 3.0
Math.round(2.5); // 3 (half-up rounding)
Math.round(-2.5); // -2 (not -3)
floor/ceil return double while round returns long. Java uses half-up rounding (not banker's rounding); BigDecimal offers configurable rounding modes for financial calculations.
Math.log(double a) → double | Math.log10(double a) → double | Math.exp(double a) → double | Math.PI | Math.E
Math.log(Math.E); // 1.0 (natural log)
Math.log10(1000); // 3.0
Math.exp(1); // 2.718... (e^1)
Math.PI; // 3.141592653589793
Math.E; // 2.718281828459045
log is natural logarithm (base e); log10 is base 10. These are native methods in the JVM and typically hardware-accelerated. Math.PI and Math.E are static final double constants.
Math.clamp(long value, long min, long max) → long (Java 21+)
Math.clamp(150, 0, 100); // 100
Math.clamp(-5, 0, 100); // 0
Math.clamp(50, 0, 100); // 50
// also overloaded for int, double, float
Added in Java 21 — constrains a value within [min, max]. Replaces the common Math.min(max, Math.max(min, value)) idiom. Overloaded for int, long, float, and double.
Math.random() → double | Math.signum(double d) → double | Math.hypot(double x, double y) → double
Math.random(); // [0.0, 1.0)
int dice = (int)(Math.random() * 6) + 1; // 1-6
Math.signum(-3.5); // -1.0
Math.hypot(3, 4); // 5.0 (Pythagorean)
Math.random() is thread-safe but contended — prefer ThreadLocalRandom.current().nextInt() in multi-threaded code. hypot avoids intermediate overflow that direct sqrt(x²+y²) can suffer.
System / Runtime
System.currentTimeMillis() → long | System.nanoTime() → long
long start = System.nanoTime();
doWork();
long elapsedMs = (System.nanoTime() - start) / 1_000_000;
long epochMs = System.currentTimeMillis(); // wall clock
Use nanoTime() for elapsed-time measurements (monotonic, not affected by clock adjustments); use currentTimeMillis() for wall-clock timestamps. Never use currentTimeMillis() for benchmarking.
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 1, dest, 0, 3);
// dest = [2, 3, 4, 0, 0]
Native method — the fastest way to bulk-copy array elements. Works correctly for overlapping src/dest ranges (same array). For object arrays, copies references (shallow copy); array must be compatible type.
System.getenv(String name) → String | System.lineSeparator() → String | System.getProperty(String key) → String
String home = System.getenv("HOME"); // "/home/user"
String sep = System.lineSeparator(); // "\n" on Linux, "\r\n" on Windows
String java = System.getProperty("java.version");
getenv reads OS environment variables; returns null if not set. lineSeparator() is platform-appropriate — use it instead of hardcoding \n for file output. getProperty reads JVM system properties.
System.exit(int status) | System.gc()
System.gc(); // hint to JVM — not guaranteed to run
System.exit(0); // success; non-zero = error
System.exit(1); // conventional error exit code
exit() terminates the JVM after running shutdown hooks — avoid calling it inside library code. gc() is a hint only; the JVM may ignore it. In production, let the GC manage memory automatically.
Runtime.getRuntime().availableProcessors() → int | maxMemory() → long | totalMemory() → long | freeMemory() → long
Runtime rt = Runtime.getRuntime();
rt.availableProcessors(); // logical CPU count
rt.maxMemory() / 1024 / 1024; // max heap MB (-Xmx)
rt.totalMemory()/ 1024 / 1024; // current heap MB
rt.freeMemory() / 1024 / 1024; // free within current heap
availableProcessors() is commonly used to size thread pools (e.g., Executors.newFixedThreadPool). maxMemory() reflects -Xmx; the used memory is approximately totalMemory() - freeMemory().
Thread
Thread.ofVirtual().name(String prefix, long start).start(Runnable) → Thread (Java 21+)
var t = Thread.ofVirtual()
.name("worker-", 0)
.start(() -> handleRequest(req));
// virtual threads are cheap — millions can exist simultaneously
Creates and starts a named virtual thread; virtual threads are lightweight JVM-managed fibers, not OS threads — ideal for blocking I/O tasks at high concurrency. The name suffix auto-increments per thread created from this builder.
Thread.startVirtualThread(Runnable task) → Thread (Java 21+)
Thread t = Thread.startVirtualThread(() -> {
String body = httpClient.send(req).body();
process(body);
});
Convenience factory — equivalent to Thread.ofVirtual().start(task). Use when you need a quick fire-and-forget virtual thread without a custom name or factory configuration.
Thread.sleep(long millis) throws InterruptedException | Thread.sleep(Duration duration) (Java 19+)
try {
Thread.sleep(500); // 500 ms
Thread.sleep(Duration.ofSeconds(2)); // Java 19+
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // restore flag
}
Always restore the interrupted status when catching InterruptedException in non-top-level code — swallowing it silently prevents cooperative cancellation from working up the call stack.
Thread.currentThread() → Thread | Thread.getName() → String | Thread.isVirtual() → boolean (Java 21+)
Thread t = Thread.currentThread();
t.getName(); // e.g. "main" or "worker-0"
t.isVirtual(); // false for platform threads
t.threadId(); // unique long ID (Java 19+, replaces getId())
currentThread() is frequently used to access thread-local context, restore interrupted status, or log thread identity. isVirtual() lets code branch on thread type when mixing virtual and platform threads.
Thread.interrupt() | Thread.isInterrupted() → boolean | Thread.interrupted() → boolean (static)
// Requester side:
workerThread.interrupt();
// Worker side:
while (!Thread.interrupted()) { // clears the flag
doWork();
}
// or: while (!thread.isInterrupted()) — does NOT clear flag
interrupt() sets the interrupted flag and unblocks blocking calls (sleep/wait/IO) with InterruptedException. Thread.interrupted() (static) checks AND clears the flag; isInterrupted() (instance) only checks.
Wrapper Types
Integer.parseInt(String s) → int | Integer.parseInt(String s, int radix) → int | Integer.valueOf(int i) → Integer
Integer.parseInt("42"); // 42
Integer.parseInt("ff", 16); // 255
Integer.parseInt("1010", 2); // 10 (binary)
Integer.valueOf(42); // Integer (cached -128..127)
parseInt returns a primitive int; valueOf returns an Integer object (uses cache for -128 to 127). Both throw NumberFormatException on invalid input. Use parseInt when a primitive is sufficient.
Integer.toBinaryString(int i) → String | Integer.toHexString(int i) → String | Integer.toOctalString(int i) → String
Integer.toBinaryString(10); // "1010"
Integer.toHexString(255); // "ff"
Integer.toOctalString(8); // "10"
// No "0x" prefix — add manually if needed
Produces unsigned representations (negative ints appear as large unsigned values in binary/hex). For zero-padded hex, use "%08x".formatted(n) or HexFormat (Java 17+) for byte arrays.
Integer.compare(int x, int y) → int | Integer.MAX_VALUE | Integer.MIN_VALUE
Integer.compare(3, 5); // negative (3 < 5)
Integer.compare(5, 5); // 0
Integer.MAX_VALUE; // 2147483647 (2^31 - 1)
Integer.MIN_VALUE; // -2147483648 (-2^31)
list.sort(Integer::compare); // safe comparator
Use Integer.compare(x, y) as a comparator instead of x - y — subtraction overflows for extreme values (e.g., MIN_VALUE - 1). Integer.sum, Integer.max, Integer.min are also useful method references.
Double.parseDouble(String s) → double | Double.isNaN(double v) → boolean | Double.isInfinite(double v) → boolean
Double.parseDouble("3.14"); // 3.14
double nan = 0.0 / 0.0;
Double.isNaN(nan); // true (nan != nan is also true)
Double.isInfinite(1.0 / 0.0);// true
Double.MAX_VALUE; // ~1.8e308
Always use Double.isNaN() to check for NaN — x == Double.NaN is always false by IEEE 754 spec. Double.isFinite(v) (Java 8+) is the inverse of isNaN || isInfinite.
Boolean.parseBoolean(String s) → boolean
Boolean.parseBoolean("true"); // true
Boolean.parseBoolean("TRUE"); // true (case-insensitive)
Boolean.parseBoolean("yes"); // false (only "true" is true)
Boolean.parseBoolean(null); // false (no NPE)
Returns true only when the string equals "true" (case-insensitive); everything else — including null, "yes", "1", "on" — returns false without throwing. Safe to use directly with System.getenv.
Autoboxing cache caveat: Integer == comparison
Integer a = 127, b = 127;
a == b; // true — same cached instance
Integer c = 128, d = 128;
c == d; // false — different heap objects
c.equals(d); // true — always use equals() for value comparison
The JVM caches Integer instances for values -128 to 127 (configurable via -XX:AutoBoxCacheMax). Using == on boxed types compares references — always use .equals() or unbox first for value equality.
java.util
List
static <E> List<E> List.of(E... elements) → unmodifiable List
var roles = List.of("admin", "editor", "viewer"); // null-hostile, fixed size
Creates an unmodifiable list; throws NullPointerException on null elements and UnsupportedOperationException on mutation — use ArrayList for mutable lists.
static <E> List<E> List.copyOf(Collection<? extends E> coll) → unmodifiable copy
List<String> snapshot = List.copyOf(mutableList); // safe, immutable view
Copies the collection into an unmodifiable list; null elements cause NullPointerException. Useful for defensive copies at API boundaries.
new ArrayList<>() — mutable list; add / addAll / get / set / remove
List<String> names = new ArrayList<>();
names.add("Alice");
names.addAll(List.of("Bob", "Carol"));
names.set(0, "Alicia");
names.remove(1); // removes "Bob"
ArrayList is the go-to mutable list; backed by an array with amortized O(1) add at end. remove(int) removes by index, remove(Object) removes by value.
void List.sort(Comparator<? super E> c) — in-place sort
names.sort(Comparator.naturalOrder());
names.sort(Comparator.comparing(String::length).reversed()); // longest first
Sorts the list in-place using a TimSort; pass null to use natural ordering (elements must be Comparable). More readable than Collections.sort for method-chained comparators.
List<E> list.subList(int fromIndex, int toIndex) — view
List<String> page = names.subList(0, 10); // first 10 elements
page.clear(); // removes first 10 from backing list
Returns a live view backed by the original list — mutations to the subList (clear, set, etc.) reflect in the backing list. Useful for pagination and bulk removal.
boolean list.contains(Object o) / int indexOf(Object o) / int size() / boolean isEmpty()
if (!names.isEmpty() && names.contains("Alice")) {
int pos = names.indexOf("Alice"); // first occurrence, -1 if absent
System.out.println(names.size() + " elements, Alice at " + pos);
}
Linear-time O(n) operations — use a HashSet for O(1) membership tests when the list is large.
Stream<E> list.stream() / Iterator<E> list.iterator()
names.stream()
.filter(s -> s.startsWith("A"))
.forEach(System.out::println);
Iterator<String> it = names.iterator();
while (it.hasNext()) { if (it.next().isBlank()) it.remove(); }
stream() feeds the Stream API; iterator() is the safe way to remove elements during iteration (ConcurrentModificationException if you mutate via the list directly).
Set
static <E> Set<E> Set.of(E... elements) — unmodifiable, no nulls, no duplicates
var perms = Set.of("READ", "WRITE", "EXEC"); // iteration order not guaranteed
Creates an unmodifiable set; duplicate elements or null cause exceptions at construction time. Iteration order is deliberately randomised per JVM invocation to discourage order dependence.
new HashSet<>(Collection<? extends E>) — mutable, O(1) ops, no order
Set<String> unique = new HashSet<>(rawList); // deduplicate in one line
unique.add("extra");
unique.remove("READ");
boolean has = unique.contains("WRITE");
HashSet gives O(1) average for add/remove/contains. Passing a collection to the constructor is the idiom for de-duplication — far faster than iterating manually.
new TreeSet<>(Comparator<? super E>) — sorted, NavigableSet
NavigableSet<String> sorted = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
sorted.add("banana"); sorted.add("Apple"); sorted.add("cherry");
String first = sorted.first(); // "Apple" (case-insensitive)
TreeSet maintains elements in comparator (or natural) order with O(log n) ops. Also exposes floor/ceiling/headSet/tailSet for range queries.
new LinkedHashSet<>() — insertion-ordered, no duplicates
Set<String> ordered = new LinkedHashSet<>();
ordered.add("first"); ordered.add("second"); ordered.add("first");
// iteration: "first", "second" — duplicate silently ignored
Combines HashSet O(1) ops with predictable insertion-order iteration — useful when output order matters (e.g. preserving user-supplied tag order with deduplication).
static <E> Set<E> Set.copyOf(Collection<? extends E> coll) — unmodifiable copy
Set<String> snap = Set.copyOf(mutableSet); // null elements → NPE
Produces an unmodifiable set from any collection; duplicates are collapsed. Complement to List.copyOf for defensive copies of set-valued fields.
Map
static <K,V> Map<K,V> Map.of(K k1, V v1, ...) — unmodifiable, up to 10 pairs
var codes = Map.of("OK", 200, "NOT_FOUND", 404, "ERROR", 500);
// no nulls, no duplicate keys, iteration order not guaranteed
Compact literal for small maps; limited to 10 pairs by overloaded methods — use Map.ofEntries for larger maps. Null keys/values or duplicate keys throw at construction time.
Map.entry(K, V) + Map.ofEntries(Map.Entry...) — unmodifiable, unlimited pairs
var map = Map.ofEntries(
Map.entry("alpha", 1),
Map.entry("beta", 2),
Map.entry("gamma", 3)
);
Use when you need more than 10 pairs in an unmodifiable map. Map.entry() is the null-hostile factory; import static for cleaner syntax.
new HashMap<>() — get / put / remove / containsKey / size
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 42);
int s = scores.getOrDefault("Bob", 0);
scores.remove("Alice");
boolean has = scores.containsKey("Carol");
HashMap is the workhorse: O(1) average for all ops. get() returns null for missing keys — prefer getOrDefault to avoid null checks.
new LinkedHashMap<>() — insertion-order map
Map<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true);
// accessOrder=true → eviction hook for simple LRU caches
Preserves insertion order (or access order when constructed with accessOrder=true). Override removeEldestEntry to build a bounded LRU cache with minimal code.
new TreeMap<>() — sorted by key, NavigableMap
NavigableMap<String, Integer> tm = new TreeMap<>();
tm.put("b", 2); tm.put("a", 1); tm.put("c", 3);
Map<String, Integer> sub = tm.subMap("a", "c"); // ["a".."b"]
O(log n) ops; keys iterated in natural order. Exposes firstKey/lastKey/floorKey/ceilingKey/headMap/tailMap — invaluable for range queries on ordered data.
V map.getOrDefault(Object key, V defaultValue) — safe get
int count = wordCount.getOrDefault(word, 0); // never returns null
Returns the mapped value or defaultValue if the key is absent — eliminates null checks and is clearer than a ternary with containsKey.
V map.putIfAbsent(K key, V value) — conditional put
cache.putIfAbsent(key, expensiveCompute(key));
// returns existing value if present, null if newly inserted
Atomically inserts only when the key is absent. Note: the value expression is always evaluated — use computeIfAbsent when value construction is expensive.
V map.computeIfAbsent(K key, Function<K,V> mappingFn) — lazy populate
Map<String, List<String>> groups = new HashMap<>();
groups.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
// one-liner to group into lists — creates bucket only when needed
Invokes mappingFn only when the key is absent and stores its result; returns the (existing or newly computed) value. The idiomatic way to build map-of-lists.
V Map.merge(K key, V value, BiFunction<V,V,V> remappingFn)
wordCount.merge(word, 1, Integer::sum);
// if absent: put 1; if present: add 1 — the idiomatic frequency counter
If the key is absent, stores value; otherwise applies the remapping function to the old and new values — cleaner than getOrDefault + put for accumulators.
map.forEach((k,v) -> ...) / entrySet() / keySet() / values()
scores.forEach((name, score) -> System.out.println(name + ": " + score));
for (Map.Entry<String, Integer> e : scores.entrySet())
process(e.getKey(), e.getValue());
forEach is the concise iteration form; entrySet() exposes both key and value without double-lookups; keySet()/values() when you need only one side.
static <K,V> Map<K,V> Map.copyOf(Map<? extends K, ? extends V> map) — unmodifiable copy
Map<String, Integer> snap = Map.copyOf(mutableMap); // null keys/values → NPE
Produces an unmodifiable snapshot; any nulls or subsequent mutations to the source map do not affect the copy.
SequencedCollection (Java 21+)
E list.getFirst() / E list.getLast() — replaces get(0) / get(size-1)
String head = names.getFirst(); // NoSuchElementException if empty
String tail = names.getLast();
Introduced in Java 21 via SequencedCollection; cleaner than get(0) and eliminates the error-prone get(size()-1) idiom. Also available on Deque and LinkedHashSet/LinkedHashMap views.
list.addFirst(E) / addLast(E) / removeFirst() / removeLast()
LinkedList<String> deq = new LinkedList<>(List.of("b", "c"));
deq.addFirst("a"); // [a, b, c]
deq.removeLast(); // [a, b]
SequencedCollection mutations; on ArrayList these are O(n) head operations — prefer ArrayDeque when you need efficient both-ends access.
SequencedCollection<E> list.reversed() — reversed view (Java 21+)
for (String s : names.reversed()) System.out.println(s);
// also: names.reversed().stream().map(...)
Returns a live reversed view — no copy made. Mutations via the view reflect in the original. Works on List, Deque, LinkedHashSet, and LinkedHashMap's sequenced views.
Queue / Deque
new ArrayDeque<>() as stack — push / pop / peek
Deque<String> stack = new ArrayDeque<>();
stack.push("a"); stack.push("b");
String top = stack.peek(); // "b", no remove
String popped = stack.pop(); // "b", throws if empty
ArrayDeque is faster than Stack (no synchronization) and Deque is preferred over Stack by the Java docs. push/pop operate on the head (LIFO).
new ArrayDeque<>() as queue — offer / poll / peek / isEmpty
Queue<String> q = new ArrayDeque<>();
q.offer("first"); q.offer("second");
String head = q.poll(); // "first", returns null if empty (vs remove() throws)
while (!q.isEmpty()) process(q.poll());
offer/poll are the null-returning queue methods (safe); add/remove throw on failure. ArrayDeque outperforms LinkedList for queue workloads.
new PriorityQueue<>(Comparator<? super E>) — offer / poll / peek
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
minHeap.offer(5); minHeap.offer(1); minHeap.offer(3);
int smallest = minHeap.poll(); // 1 — O(log n)
Min-heap by default; poll() always removes the smallest (by natural order or comparator). O(log n) offer/poll, O(1) peek. Does not support O(1) contains; iterator order is not sorted.
BlockingQueue — LinkedBlockingQueue, ArrayBlockingQueue (see java.util.concurrent)
BlockingQueue<Task> bq = new LinkedBlockingQueue<>(1000);
producer: bq.put(task); // blocks when full
consumer: Task t = bq.take(); // blocks when empty
Thread-safe bounded queue for producer-consumer patterns; put/take block, offer/poll accept a timeout. Prefer over hand-rolled wait/notify. Lives in java.util.concurrent.
Collections utilities
Collections.sort(List<T>) / Collections.sort(List<T>, Comparator<T>)
Collections.sort(words); // natural order, must implement Comparable
Collections.sort(words, String.CASE_INSENSITIVE_ORDER);
Stable TimSort; modifies the list in place. Prefer list.sort(comparator) for a more fluent style — both delegate to the same algorithm.
Collections.shuffle(List<?>) / Collections.reverse(List<?>)
Collections.shuffle(deck); // random order
Collections.shuffle(deck, new Random(42L)); // seeded
Collections.reverse(list); // in-place reversal
shuffle uses a default ThreadLocalRandom; pass a seeded Random for reproducible results (testing). reverse is O(n) in-place — useful before iterating in reverse order once.
Collections.unmodifiableList(List) / unmodifiableMap(Map) / unmodifiableSet(Set)
List<String> safe = Collections.unmodifiableList(mutableList);
// safe throws UnsupportedOperationException on mutation
// mutations to mutableList ARE visible through safe — it's a live view
Returns a live unmodifiable view — not a copy. Prefer List.copyOf for a true defensive copy that cannot be mutated through the original reference.
Collections.synchronizedList(List<T>) — thread-safe wrapper
List<String> synced = Collections.synchronizedList(new ArrayList<>());
synchronized (synced) { // must lock externally when iterating
for (String s : synced) process(s);
}
Each individual method is synchronized, but compound operations (iterate + remove) require external locking. Consider CopyOnWriteArrayList for read-heavy concurrent access instead.
Collections.frequency(Collection<?>, Object) / disjoint(Collection<?>, Collection<?>)
int count = Collections.frequency(words, "hello"); // O(n)
boolean noCommon = Collections.disjoint(setA, setB); // true if no shared elements
frequency counts occurrences via equals; disjoint is O(n) but optimised when one argument is a Set (O(1) contains). Both accept any Collection type.
Collections.min(Collection, Comparator) / max / nCopies(int, T) / singletonList(T)
String shortest = Collections.min(words, Comparator.comparing(String::length));
List<Integer> zeros = Collections.nCopies(10, 0); // immutable, size 10
List<String> one = Collections.singletonList("only"); // immutable, size 1
min/max are linear scans; nCopies is memory-efficient (stores one element + count); singletonList is a lightweight immutable single-element list — prefer List.of("only") in modern code.
Arrays utilities
Arrays.sort(int[]) / Arrays.sort(T[], Comparator<T>)
int[] nums = {5, 2, 8, 1};
Arrays.sort(nums); // [1, 2, 5, 8]
String[] words = {"banana", "apple", "cherry"};
Arrays.sort(words, Comparator.reverseOrder()); // [cherry, banana, apple]
Primitives use dual-pivot quicksort O(n log n); object arrays use stable TimSort. To sort primitives in reverse order, box to Integer[] or use a stream.
int Arrays.binarySearch(int[] a, int key) — requires sorted input
Arrays.sort(nums);
int idx = Arrays.binarySearch(nums, 5); // ≥0 if found, negative if absent
int insertionPoint = ~Arrays.binarySearch(nums, 6); // bitwise NOT of negative result
O(log n); array must be sorted first. A negative return value encodes the insertion point as -(insertionPoint)-1 — bitwise NOT (~) decodes it.
T[] Arrays.copyOf(T[] original, int newLength) / copyOfRange(T[], int, int)
int[] doubled = Arrays.copyOf(nums, nums.length * 2); // pads with 0s
int[] slice = Arrays.copyOfRange(nums, 1, 4); // [1..3] exclusive end
copyOf truncates or pads with zeros/nulls; copyOfRange supports out-of-bounds toIndex (pads). Both return a new array — the original is unaffected.
void Arrays.fill(int[] a, int val) / fill(T[], int, int, T)
int[] board = new int[9];
Arrays.fill(board, -1); // [-1,-1,-1,-1,-1,-1,-1,-1,-1]
Arrays.fill(board, 3, 6, 0); // indices 3-5 → 0
Assigns a single value to every element (or a range). Faster and clearer than a loop for initialization. Does not deep-fill — each cell of an Object[] still holds the same reference.
List<T> Arrays.asList(T... a) — fixed-size list backed by the array
List<String> fixed = Arrays.asList("x", "y", "z");
fixed.set(0, "X"); // OK — mutates backing array
fixed.add("w"); // UnsupportedOperationException — fixed size
The returned list allows set/sort but not structural changes (add/remove). Wrap in new ArrayList<>(Arrays.asList(...)) for a fully mutable copy. Prefer List.of for truly immutable literals.
Stream<T> Arrays.stream(T[]) / stream(int[])
int sum = Arrays.stream(nums).sum();
String[] upper = Arrays.stream(words)
.map(String::toUpperCase)
.toArray(String[]::new);
Bridges arrays into the Stream API; int[]/long[]/double[] produce IntStream/LongStream/DoubleStream with sum/average/min/max. More expressive than index-based loops for transformations.
boolean Arrays.equals(int[], int[]) / deepEquals(Object[], Object[]) / toString / deepToString
boolean same = Arrays.equals(a, b); // element-wise, 1D only
boolean deep = Arrays.deepEquals(matrix1, matrix2); // nested arrays
System.out.println(Arrays.toString(nums)); // "[1, 2, 5, 8]"
System.out.println(Arrays.deepToString(grid)); // "[[1, 2], [3, 4]]"
== on arrays compares references; Arrays.equals does element-wise comparison. deepEquals recurses into nested arrays. toString/deepToString are essential for debugging arrays (avoid the default Object@hex output).
Objects utilities
T Objects.requireNonNull(T obj, String message) — null guard
public UserService(UserRepository repo) {
this.repo = Objects.requireNonNull(repo, "repo must not be null");
}
Throws NullPointerException with the given message if obj is null; otherwise returns obj. The canonical null-guard idiom for constructors and method preambles — fail fast at the boundary.
T Objects.requireNonNullElse(T obj, T defaultObj) — null coalesce
String label = Objects.requireNonNullElse(config.label(), "default");
// defaultObj itself must not be null
Returns obj if non-null, defaultObj otherwise; both arguments must be non-null (unlike getOrDefault which has no such constraint). Cleaner than a ternary null-check.
boolean Objects.isNull(Object obj) / nonNull(Object obj)
list.stream().filter(Objects::nonNull).toList(); // drop nulls
list.stream().filter(Objects::isNull).count(); // count nulls
Primarily useful as method references in streams; isNull/nonNull are equivalent to == null / != null but compose cleanly with filter/removeIf.
String Objects.toString(Object o, String nullDefault) — null-safe toString
String s = Objects.toString(maybeNull, "N/A"); // never null
Returns o.toString() if o is non-null, otherwise nullDefault. Avoids NullPointerException in logging/display code without an explicit null check.
boolean Objects.equals(Object a, Object b) — null-safe equality
Objects.equals(a, b); // true if both null, false if one null, a.equals(b) otherwise
The standard null-safe equals — eliminates the pattern a != null && a.equals(b). Use in equals() overrides to handle null fields without extra guards.
int Objects.hash(Object... values) — multi-field hashCode
@Override public int hashCode() {
return Objects.hash(firstName, lastName, email);
}
Combines multiple fields into a hash code via Arrays.hashCode; slightly slower than hand-rolled due to varargs array creation — use for clarity, not hot-path code.
int Objects.checkIndex(int index, int length) — bounds check (Java 9+)
Objects.checkIndex(i, array.length); // throws IndexOutOfBoundsException if i < 0 || i ≥ length
Validates that index is within [0, length) and returns the index on success — useful in custom data structures to enforce bounds with a standard exception message.
Optional
Optional.of(T) / Optional.ofNullable(T) / Optional.empty()
Optional<String> a = Optional.of("hello"); // NPE if null
Optional<String> b = Optional.ofNullable(maybeNull); // safe
Optional<String> c = Optional.empty(); // no value
Optional is a value type for method return values — not a field type or parameter type. of() is for known non-null values; ofNullable bridges nullable APIs into Optional chains.
boolean optional.isPresent() / isEmpty() (Java 11+)
if (opt.isPresent()) doSomething(opt.get());
if (opt.isEmpty()) handleMissing(); // Java 11+, cleaner than !isPresent()
isEmpty() was added in Java 11 to avoid the double-negation of !isPresent(). Prefer ifPresent(consumer) or map/orElse over isPresent()+get() to stay functional.
T optional.get() — unsafe; use sparingly
String val = opt.get(); // NoSuchElementException if empty — only call after isPresent()
Throws NoSuchElementException when empty. Treat get() as a code smell — if you find yourself calling isPresent() then get(), refactor to orElse/orElseGet/ifPresent.
T optional.orElse(T) / orElseGet(Supplier<T>) / orElseThrow(Supplier<Throwable>)
String s1 = opt.orElse("default"); // always evaluates default
String s2 = opt.orElseGet(() -> computeDefault()); // lazy
String s3 = opt.orElseThrow(() -> new IllegalStateException("missing"));
orElse evaluates its argument eagerly — use orElseGet when the default is expensive to construct. orElseThrow is the preferred way to propagate a domain error when absence is invalid.
Optional<T> Optional.ofNullable(T) / .map(Function) / .orElse(T) / .orElseGet(Supplier)
var city = Optional.ofNullable(user.address())
.map(Address::city)
.orElse("Unknown");
ofNullable wraps a potentially-null value; chain map/flatMap for transformations, orElse/orElseGet for extraction with a default — avoids null checks in pipelines.
void optional.ifPresent(Consumer<T>) / ifPresentOrElse(Consumer<T>, Runnable) (Java 9+)
opt.ifPresent(val -> System.out.println(val));
opt.ifPresentOrElse(
val -> save(val),
() -> System.out.println("nothing to save")
);
ifPresent runs the consumer only when a value exists; ifPresentOrElse (Java 9) handles both branches — cleaner than if/else around isPresent() for side-effect-only paths.
Stream<T> optional.stream() — 0 or 1 element stream (Java 9+)
List<String> values = optionals.stream()
.flatMap(Optional::stream) // flatten Optional<T> into present values
.toList();
Produces a single-element stream if present, empty stream otherwise. The key use case is flatMap(Optional::stream) to filter-and-unwrap a stream of Optionals in one step.
Optional<T> optional.or(Supplier<Optional<T>>) — fallback optional (Java 9+)
Optional<User> user = findInCache(id)
.or(() -> findInDatabase(id))
.or(() -> findInRemote(id));
Returns this Optional if present, otherwise returns the supplier's Optional — enables lazy fallback chains without unwrapping intermediate values. Complement to orElseGet for Optional-returning lookup layers.
java.util.stream
Stream — Creation
Collection.stream() / Collection.parallelStream() → Stream<E>
List<String> names = List.of("Alice", "Bob", "Carol");
long count = names.stream().filter(n -> n.startsWith("A")).count();
long parCount = names.parallelStream().filter(n -> n.startsWith("A")).count();
Every Collection exposes stream() for sequential processing and parallelStream() for fork-join parallel processing; prefer parallelStream() only for CPU-bound work on large data sets.
Stream.of(T... values) / Stream.generate(Supplier<T>) / Stream.iterate(T seed, UnaryOperator<T> f)
Stream.of("a", "b", "c").forEach(System.out::println);
Stream<Double> randoms = Stream.generate(Math::random).limit(5);
Stream<Integer> powers = Stream.iterate(1, n -> n * 2).limit(10); // 1,2,4,8,…
// Java 9+ iterate with hasNext predicate:
Stream<Integer> upTo100 = Stream.iterate(1, n -> n <= 100, n -> n * 2);
Stream.of creates a finite stream from varargs; generate produces an infinite lazy stream from a Supplier; iterate produces an infinite (or bounded with Java 9 predicate form) sequential stream.
Arrays.stream(T[] array) / Arrays.stream(T[], int fromIndex, int toIndex) → Stream<T>
String[] arr = {"x", "y", "z"};
Stream<String> s = Arrays.stream(arr);
IntStream ints = Arrays.stream(new int[]{1, 2, 3}); // returns IntStream for primitives
Stream<String> slice = Arrays.stream(arr, 0, 2); // "x", "y"
Bridges arrays to the Stream API; automatically returns a primitive stream (IntStream, LongStream, DoubleStream) for primitive array types, avoiding boxing overhead.
Stream.empty() → Stream<T> / Stream.concat(Stream<A>, Stream<B>) → Stream<T>
Stream<String> none = Stream.empty(); // useful as a null-safe return value
Stream<String> merged = Stream.concat(
list1.stream(),
list2.stream()
); // lazy; does not copy elements
Stream.empty() is useful as a safe no-op return instead of null; Stream.concat lazily concatenates two streams without materialising either — prefer it over flatMap for exactly two sources.
Stream — Intermediate Operations
filter(Predicate<T> predicate) → Stream<T>
var seniors = employees.stream()
.filter(e -> e.yearsOfService() >= 10 && e.isFullTime())
.toList();
Keeps only elements matching the predicate; lazy — the predicate is not evaluated until a terminal operation pulls elements. Chain multiple filters or compose predicates with Predicate.and().
map(Function<T,R>) → Stream<R> / mapToInt(ToIntFunction) → IntStream / mapToLong / mapToDouble
List<String> upper = names.stream()
.map(String::toUpperCase)
.toList();
int totalAge = users.stream()
.mapToInt(User::age)
.sum(); // no boxing — stays as IntStream
map transforms each element; mapToInt/mapToLong/mapToDouble produce primitive streams, eliminating boxing and unlocking numeric aggregates like sum(), average(), min(), max().
flatMap(Function<T, Stream<R>>) → Stream<R> — flatten one level of nesting
List<List<String>> nested = List.of(List.of("a", "b"), List.of("c"));
List<String> flat = nested.stream()
.flatMap(Collection::stream)
.toList(); // ["a", "b", "c"]
// splitting sentences into words:
List<String> words = sentences.stream()
.flatMap(s -> Arrays.stream(s.split("\\s+")))
.toList();
Maps each element to a stream and merges the resulting streams into one; the standard way to flatten nested collections or expand one element into many.
distinct() → Stream<T> / sorted() → Stream<T> / sorted(Comparator<T>) → Stream<T>
List<Integer> unique = nums.stream().distinct().toList(); // uses equals/hashCode
List<String> alpha = names.stream().sorted().toList(); // natural order
List<Employee> bySalaryDesc = employees.stream()
.sorted(Comparator.comparingDouble(Employee::salary).reversed())
.toList();
distinct() deduplicates via equals/hashCode; sorted() requires elements to be Comparable or a Comparator to be supplied. Both are stateful operations that may buffer the entire stream.
peek(Consumer<T> action) → Stream<T> — inspect elements without consuming the stream
var result = orders.stream()
.filter(Order::isPending)
.peek(o -> System.out.println("Processing: " + o.id())) // debug
.map(Order::process)
.toList();
peek is intended for debugging — it applies a Consumer to each element as it flows through the pipeline without changing the element. Do not use it for side effects in production logic.
limit(long maxSize) → Stream<T> / skip(long n) → Stream<T>
List<Product> topFive = products.stream()
.sorted(Comparator.comparingInt(Product::rating).reversed())
.limit(5)
.toList();
List<Product> page2 = products.stream().skip(20).limit(10).toList(); // offset pagination
limit short-circuits the stream after maxSize elements; skip discards the first n elements. Together they implement offset-based pagination, though cursor-based is preferred for large datasets.
takeWhile(Predicate) → Stream<T> (Java 9+) / dropWhile(Predicate) → Stream<T> (Java 9+)
// takeWhile: stop as soon as predicate is false
List<Integer> head = Stream.of(1, 3, 5, 6, 7).takeWhile(n -> n % 2 != 0).toList(); // [1,3,5]
// dropWhile: skip until predicate is false, then pass everything
List<Integer> tail = Stream.of(1, 3, 5, 6, 7).dropWhile(n -> n % 2 != 0).toList(); // [6,7]
Both operate on ordered streams based on element position, not arbitrary filtering. takeWhile is the streaming analogue of breaking out of a sorted loop early; dropWhile skips an ordered prefix.
mapMulti(BiConsumer<T, Consumer<R>>) → Stream<R> (Java 16+) — selective expansion
// More efficient than flatMap when output is 0–few elements per input
List<String> result = items.stream()
.<String>mapMulti((item, downstream) -> {
if (item.isEnabled()) {
downstream.accept(item.name());
downstream.accept(item.alias());
}
})
.toList();
mapMulti avoids creating an intermediate Stream per element (unlike flatMap), making it more efficient when each element expands into zero to a handful of outputs. Push results directly to the downstream Consumer.
Stream — Terminal Operations
collect(Collector<T,A,R> collector) → R — general mutable reduction
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
String joined = stream.collect(Collectors.joining(", ", "[", "]"));
Map<String,User> byId = users.stream()
.collect(Collectors.toMap(User::id, u -> u));
The universal terminal operation for accumulating stream elements into a container; delegates the accumulation strategy to a Collector — use factory methods in Collectors for common cases.
forEach(Consumer<T>) / forEachOrdered(Consumer<T>) — consume all elements
names.stream().forEach(System.out::println); // order undefined on parallel streams
names.parallelStream().forEachOrdered(System.out::println); // encounter order preserved
forEach is unordered on parallel streams for better throughput; forEachOrdered preserves encounter order at the cost of reduced parallelism. Prefer collect over forEach for building collections.
count() → long / findFirst() → Optional<T> / findAny() → Optional<T>
long active = users.stream().filter(User::isActive).count();
Optional<User> first = users.stream().filter(User::isAdmin).findFirst();
Optional<User> any = users.parallelStream().filter(User::isAdmin).findAny(); // faster
count() is a terminal reduction returning the element count; findFirst() respects encounter order; findAny() may return any matching element and is optimised for parallel streams to return without coordination.
anyMatch(Predicate) / allMatch(Predicate) / noneMatch(Predicate) → boolean — short-circuit checks
boolean hasAdmin = users.stream().anyMatch(User::isAdmin);
boolean allActive = users.stream().allMatch(User::isActive);
boolean noBanned = users.stream().noneMatch(User::isBanned);
All three short-circuit — they stop processing as soon as the result is determined. anyMatch returns true on first match; allMatch returns false on first non-match; noneMatch returns false on first match.
reduce(T identity, BinaryOperator<T>) → T / reduce(BinaryOperator<T>) → Optional<T>
int sum = Stream.of(1, 2, 3).reduce(0, Integer::sum); // 6
Optional<String> longest = words.stream()
.reduce((a, b) -> a.length() >= b.length() ? a : b);
reduce folds elements using an associative combiner; the identity form always returns a value, making it safe without Optional. Prefer mapToInt().sum() over reduce for numeric sums to avoid boxing.
toList() → unmodifiable List<T> (Java 16+)
var activeIds = users.stream()
.filter(User::isActive)
.map(User::id)
.toList(); // shorter than .collect(Collectors.toUnmodifiableList())
Terminal shorthand returning an unmodifiable List; preferred over Collectors.toList() since Java 16. Throws UnsupportedOperationException on mutation attempts, making intent explicit.
min(Comparator<T>) → Optional<T> / max(Comparator<T>) → Optional<T>
Optional<Employee> lowest = employees.stream().min(Comparator.comparingDouble(Employee::salary));
Optional<Employee> highest = employees.stream().max(Comparator.comparingDouble(Employee::salary));
Convenience terminals that wrap reduce under the hood; return Optional.empty() for empty streams. Equivalent to sorted(comparator).findFirst() but without materialising a sorted stream.
toArray() → Object[] / toArray(IntFunction<T[]> generator) → T[]
Object[] raw = stream.toArray();
String[] typed = names.stream().toArray(String[]::new); // type-safe
Employee[] sorted = employees.stream()
.sorted(Comparator.comparing(Employee::name))
.toArray(Employee[]::new);
toArray() without arguments returns an untyped Object[]; pass a constructor reference (Type[]::new) to get a typed array. Useful when an API requires an array rather than a List.
IntStream / LongStream
IntStream.range(int start, int end) / IntStream.rangeClosed(int start, int end) → IntStream
// range: [start, end) — end exclusive
IntStream.range(0, 5).forEach(System.out::println); // 0 1 2 3 4
// rangeClosed: [start, end] — end inclusive
int sumTo10 = IntStream.rangeClosed(1, 10).sum(); // 55
// index-based loop replacement:
IntStream.range(0, list.size()).forEach(i -> process(i, list.get(i)));
Replaces index-based for-loops with a functional style; range excludes the end, rangeClosed includes it (matching mathematical interval notation). Analogous methods exist on LongStream.
IntStream.sum() → int / average() → OptionalDouble / min() → OptionalInt / max() → OptionalInt / summaryStatistics() → IntSummaryStatistics
int total = employees.stream().mapToInt(Employee::salary).sum();
OptionalDouble avg = employees.stream().mapToInt(Employee::salary).average();
IntSummaryStatistics stats = employees.stream()
.mapToInt(Employee::salary)
.summaryStatistics(); // count, sum, min, max, average in one pass
Primitive streams provide numeric aggregates without boxing; summaryStatistics() computes all five statistics in a single pass — use it when you need more than one aggregate to avoid multiple stream traversals.
IntStream.boxed() → Stream<Integer> / IntStream.mapToObj(IntFunction<R>) → Stream<R>
List<Integer> boxed = IntStream.range(1, 6).boxed().toList(); // [1,2,3,4,5]
List<String> labels = IntStream.range(1, 4)
.mapToObj(i -> "Item-" + i)
.toList(); // ["Item-1", "Item-2", "Item-3"]
boxed() is shorthand for mapToObj(Integer::valueOf); use mapToObj when you need to produce a non-wrapper type from each int, such as building strings or domain objects indexed by position.
LongStream.range(long start, long end) / LongStream.rangeClosed(long start, long end)
long billionSum = LongStream.rangeClosed(1L, 1_000_000L).sum(); // overflow-safe
// Parallel reduction over large range:
long count = LongStream.range(0L, 1_000_000_000L)
.parallel()
.filter(n -> n % 2 == 0)
.count();
LongStream handles ranges too large for int arithmetic without overflow; parallel() on a LongStream splits the range across available CPU cores using the fork-join pool.
Collectors
Collectors.toList() / toUnmodifiableList() / toSet() / toUnmodifiableSet()
List<String> mutable = stream.collect(Collectors.toList()); // mutable ArrayList
List<String> immutable = stream.collect(Collectors.toUnmodifiableList()); // unmodifiable
// Prefer stream.toList() (Java 16+) over toUnmodifiableList() for brevity
Set<String> unique = stream.collect(Collectors.toSet()); // HashSet, order undefined
toList() returns a mutable ArrayList; toUnmodifiableList() returns a snapshot that rejects mutations. Prefer the Java 16 stream.toList() terminal for unmodifiable results. toSet() deduplicates via equals/hashCode.
Collectors.toMap(keyMapper, valueMapper) / toMap(keyMapper, valueMapper, mergeFunction) / toUnmodifiableMap
Map<String, User> byId = users.stream()
.collect(Collectors.toMap(User::id, u -> u)); // throws on duplicate key
Map<String, Long> wordCount = words.stream()
.collect(Collectors.toMap(w -> w, w -> 1L, Long::sum)); // merge on duplicate
Two-arg toMap throws IllegalStateException on duplicate keys — always supply a merge function when duplicates are possible. The merge function receives (existing, incoming) and returns the resolved value.
Collectors.groupingBy(Function classifier) / groupingBy(Function, Collector downstream)
Map<Department, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::department));
Map<Department, Long> counts = employees.stream()
.collect(Collectors.groupingBy(Employee::department, Collectors.counting()));
Groups elements by a classifier into Map<K,List<V>>; the downstream collector transforms grouped values — counting, averaging, joining, toList, etc.
Collectors.partitioningBy(Predicate<T>) → Map<Boolean, List<T>>
Map<Boolean, List<User>> parts = users.stream()
.collect(Collectors.partitioningBy(User::isActive));
List<User> active = parts.get(true);
List<User> inactive = parts.get(false);
Specialised groupingBy that always produces a two-entry map keyed on true/false; more readable than a generic groupingBy with a boolean classifier and always has both keys present.
Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) → String
String csv = names.stream().collect(Collectors.joining(", "));
String json = names.stream().collect(Collectors.joining("\", \"", "[\"", "\"]"));
String sql = ids.stream().map(Object::toString)
.collect(Collectors.joining(", ", "(", ")")); // (1, 2, 3) for IN clause
Concatenates stream elements (must be CharSequence) with a delimiter and optional wrapping prefix/suffix; more efficient than repeated string concatenation in a loop.
Collectors.counting() → Collector<T,?,Long> / summarizingInt(ToIntFunction) → IntSummaryStatistics
Map<String, Long> freq = words.stream()
.collect(Collectors.groupingBy(w -> w, Collectors.counting()));
IntSummaryStatistics stats = orders.stream()
.collect(Collectors.summarizingInt(Order::quantity));
// stats.getSum(), .getAverage(), .getMin(), .getMax(), .getCount()
counting() is the canonical downstream collector for frequency maps; summarizingInt/Long/Double computes all five statistics in one collect pass — useful when you need count + sum + average together.
Collectors.teeing(Collector c1, Collector c2, BiFunction merger) → Collector (Java 12+)
// Compute min and max in a single stream pass
var minMax = numbers.stream().collect(
Collectors.teeing(
Collectors.minBy(Comparator.naturalOrder()),
Collectors.maxBy(Comparator.naturalOrder()),
(Optional<Integer> min, Optional<Integer> max) -> Map.of("min", min.orElseThrow(), "max", max.orElseThrow())
));
teeing feeds each element into two independent collectors simultaneously, then merges the two results with a BiFunction — eliminates the need to traverse the stream twice for two independent aggregates.
java.util.function
Function<T,R>: apply(T) → R / andThen(Function) / compose(Function) / Function.identity()
Function<String, Integer> len = String::length;
Function<String, String> upper = String::toUpperCase;
Function<String, Integer> upperLen = upper.andThen(len); // upper first, then len
Function<String, Integer> same = len.compose(upper); // identical result
Function<User, User> id = Function.identity(); // u -> u, useful as a no-op mapper
andThen applies this function first then the next; compose applies the argument first then this — they are inverses of each other. Function.identity() avoids a lambda for u -> u situations.
Predicate<T>: test(T) / negate() / and(Predicate) / or(Predicate) / Predicate.not(Predicate) (Java 11+)
Predicate<User> active = User::isActive;
Predicate<User> admin = u -> u.role() == Role.ADMIN;
Predicate<User> blocked = Predicate.not(User::isActive);
var result = users.stream().filter(active.and(admin)).toList();
Compose predicates with and/or/negate instead of nesting &&; Predicate.not() wraps a method reference into a negating predicate.
Consumer<T>: accept(T) / andThen(Consumer<T>) — chaining side-effect operations
Consumer<Order> log = o -> System.out.println("Processing: " + o.id());
Consumer<Order> audit = o -> auditService.record(o);
Consumer<Order> pipeline = log.andThen(audit);
orders.forEach(pipeline); // log then audit for each order
Consumer encapsulates a single side-effect action; andThen chains consumers sequentially. Useful for composing logging, auditing, or notification steps without nested lambdas.
Supplier<T>: get() → T — deferred / lazy evaluation
Supplier<List<User>> lazyUsers = () -> userRepo.findAll(); // DB call deferred
// Optional.orElseGet with Supplier — only calls supplier if Optional is empty:
User u = findUser(id).orElseGet(() -> userRepo.findDefault());
// Logger example — avoid string concat when log level is off:
logger.debug(() -> "State: " + expensive.compute()); // Supplier-based overload
Supplier delays computation until get() is called; particularly valuable with Optional.orElseGet to avoid evaluating a fallback eagerly, and with logging APIs to skip string concatenation when the level is disabled.
BiFunction<T,U,R>: apply(T,U) / UnaryOperator<T> extends Function<T,T> / BinaryOperator<T> extends BiFunction<T,T,T>
BiFunction<String, Integer, String> repeat = (s, n) -> s.repeat(n);
String dashes = repeat.apply("-", 10); // "----------"
UnaryOperator<String> trim = String::strip; // Function specialisation
BinaryOperator<Integer> max = Integer::max; // used in reduce
int biggest = Stream.of(3,1,4,1,5).reduce(Integer::max).orElseThrow();
BiFunction takes two arguments; UnaryOperator is a Function where input and output types match — used in Stream.iterate and List.replaceAll; BinaryOperator is the BiFunction variant used in reduce and merge functions.
Primitive specializations: IntFunction<R> / ToIntFunction<T> / IntUnaryOperator / IntBinaryOperator / IntConsumer / IntSupplier / IntPredicate
IntUnaryOperator doubler = n -> n * 2;
int[] doubled = IntStream.range(1, 6).map(doubler).toArray(); // [2,4,6,8,10]
ToIntFunction<String> strLen = String::length;
int[] lengths = words.stream().mapToInt(strLen).toArray();
// Naming pattern: [To][Type]Function — avoids boxing in hot paths
Primitive functional interfaces eliminate autoboxing; follow the naming pattern — ToIntFunction converts T→int, IntFunction converts int→R, IntUnaryOperator maps int→int. Analogous Long/Double variants exist for each shape.
java.time
LocalDate / LocalTime / LocalDateTime
static LocalDate LocalDate.now() / of(int year, int month, int dayOfMonth) / of(int year, Month, int day)
var today = LocalDate.now();
var xmas2025 = LocalDate.of(2025, 12, 25);
var piDay = LocalDate.of(2025, Month.MARCH, 14);
Factory methods to create a date without time or timezone; of() validates the fields eagerly and throws DateTimeException for invalid combinations like Feb 30.
static LocalDate LocalDate.parse(CharSequence text) / parse(CharSequence, DateTimeFormatter)
var dob = LocalDate.parse(req.getParameter("dob"), DateTimeFormatter.ofPattern("dd/MM/yyyy"));
var age = Period.between(dob, LocalDate.now()).getYears();
Parses a date string with an explicit formatter; always specify the formatter for user-supplied input to handle locale differences.
LocalDate plusDays(long) / plusMonths(long) / plusYears(long) / minusDays(long) / minusMonths(long)
var due = LocalDate.now().plusDays(30);
var lastMonth = LocalDate.now().minusMonths(1).withDayOfMonth(1);
All arithmetic returns a new immutable instance; chain calls freely — LocalDate is thread-safe and value-based.
boolean isBefore(LocalDate) / isAfter(LocalDate) / isEqual(LocalDate)
if (deadline.isBefore(LocalDate.now())) {
sendOverdueNotice(task);
}
Prefer isBefore/isAfter over compareTo for readable date comparisons; isEqual is equivalent to equals() for LocalDate.
DayOfWeek getDayOfWeek() / int getDayOfMonth() / Month getMonth() / int getYear() / int lengthOfMonth()
var d = LocalDate.now();
String label = d.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US)
+ ", " + d.getMonth() + " " + d.getDayOfMonth(); // "Sunday, MARCH 22"
Field accessors; getDayOfWeek() returns a DayOfWeek enum so you can switch on it; lengthOfMonth() accounts for leap years automatically.
LocalDate withDayOfMonth(int) / withMonth(int) / withYear(int)
var firstOfMonth = LocalDate.now().withDayOfMonth(1);
var lastOfMonth = firstOfMonth.withDayOfMonth(firstOfMonth.lengthOfMonth());
Returns a copy with the specified field changed; useful for computing month boundaries without manual calendar arithmetic.
LocalDateTime atStartOfDay() / ZonedDateTime atStartOfDay(ZoneId zone)
var startUTC = LocalDate.now().atStartOfDay(ZoneId.of("UTC"));
var epochMs = startUTC.toInstant().toEpochMilli();
Converts a date to a timezone-aware start-of-day; use the ZoneId overload when building UTC timestamps for database queries.
static LocalTime LocalTime.now() / of(int hour, int minute) / of(int hour, int minute, int second) / parse(CharSequence)
var now = LocalTime.now();
var noon = LocalTime.of(12, 0);
var cutoff = LocalTime.parse("17:30");
boolean late = now.isAfter(cutoff);
LocalTime has no date or timezone; use it for recurring daily rules like business hours or cron-style schedules.
LocalTime plusHours(long) / plusMinutes(long) / isBefore(LocalTime) / isAfter(LocalTime)
var sessionEnd = LocalTime.now().plusMinutes(45);
if (sessionEnd.isAfter(LocalTime.of(22, 0))) {
warnLateMeeting();
}
Time arithmetic wraps midnight silently — plusHours(3) on 23:00 returns 02:00; if crossing midnight matters, use LocalDateTime instead.
static LocalDateTime LocalDateTime.now() / of(LocalDate, LocalTime) / atZone(ZoneId) → ZonedDateTime
var meeting = LocalDateTime.of(LocalDate.of(2025, 9, 15), LocalTime.of(14, 30));
var zoned = meeting.atZone(ZoneId.of("America/New_York"));
var utc = zoned.withZoneSameInstant(ZoneId.of("UTC"));
LocalDateTime has no timezone — it's just a date-time wall clock value; attach a ZoneId via atZone() before doing any cross-timezone math.
LocalDate LocalDateTime.toLocalDate() / LocalTime toLocalTime() / static LocalDateTime parse(CharSequence, DateTimeFormatter)
var fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
var ldt = LocalDateTime.parse("2025-09-15 14:30", fmt);
var date = ldt.toLocalDate(); // 2025-09-15
Decompose a LocalDateTime into its date or time parts; parse() with a formatter handles non-ISO formats like database DATETIME strings.
ZonedDateTime / Instant
static ZonedDateTime ZonedDateTime.now() / now(ZoneId) / of(LocalDateTime, ZoneId)
var berlin = ZonedDateTime.now(ZoneId.of("Europe/Berlin"));
var tokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
boolean same = berlin.toInstant().equals(tokyo.toInstant()); // true if captured simultaneously
Always pass an explicit ZoneId to now() in server code — the default ZoneId.systemDefault() may differ between dev and prod environments.
ZonedDateTime withZoneSameInstant(ZoneId zone) — convert the same moment to another timezone
var ny = ZonedDateTime.now(ZoneId.of("America/New_York"));
var london = ny.withZoneSameInstant(ZoneId.of("Europe/London"));
var display = london.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
withZoneSameInstant preserves the underlying Instant (same point in time); withZoneSameLocal keeps the clock value but shifts the timezone, changing the instant.
Instant ZonedDateTime.toInstant() / LocalDateTime toLocalDateTime()
var zdt = ZonedDateTime.now(ZoneId.of("UTC"));
var instant = zdt.toInstant(); // store in DB as epoch
var back = instant.atZone(ZoneId.of("UTC")).toLocalDateTime();
Convert to Instant for storage or comparison, back to ZonedDateTime for display; round-trip is lossless when the same ZoneId is used.
static Instant Instant.now() / ofEpochMilli(long) / ofEpochSecond(long) / toEpochMilli() → long
var start = Instant.now();
doWork();
var elapsed = Duration.between(start, Instant.now()).toMillis();
Instant represents a point on the UTC timeline; use for timestamps in databases and APIs — never LocalDateTime for wall-clock comparisons across timezones.
Instant plus(Duration) / minus(Duration) / isBefore(Instant) / isAfter(Instant)
var expiry = Instant.now().plus(Duration.ofHours(24));
if (Instant.now().isAfter(expiry)) {
revokeToken(token);
}
Duration-based arithmetic on Instant is the correct way to express "24 hours from now" independent of daylight saving time changes.
Duration / Period
static Duration Duration.between(Temporal start, Temporal end) / of(long amount, ChronoUnit)
var d1 = Duration.between(startInstant, endInstant);
var d2 = Duration.of(5, ChronoUnit.MINUTES);
var d3 = Duration.ofSeconds(90); // 1m 30s
Duration models a time-based amount (seconds + nanos); use it for elapsed time and timeouts — not calendar months, which vary in length.
long toMillis() / toSeconds() / toMinutes() / toHours() / boolean isNegative() / Duration abs()
var lag = Duration.between(expected, actual);
if (lag.abs().toMillis() > 500) {
log.warn("Clock skew {} ms", lag.toMillis());
}
toXxx() methods truncate — toMinutes() on a 90-second duration returns 1, not 1.5; use abs() before threshold comparisons when sign is uncertain.
Duration plus(Duration) / minus(Duration) / multipliedBy(long) / dividedBy(long)
var timeout = Duration.ofSeconds(30).multipliedBy(3); // 90 s
var budget = totalBudget.dividedBy(4); // quarter of total
Duration arithmetic is immutable; multipliedBy and dividedBy operate on the total nanosecond value, so precision is preserved.
static Period Period.between(LocalDate startInclusive, LocalDate endExclusive) / of(int years, int months, int days)
var dob = LocalDate.of(1990, 6, 15);
var p = Period.between(dob, LocalDate.now());
String age = p.getYears() + "y " + p.getMonths() + "m " + p.getDays() + "d";
Period is calendar-based (years/months/days) — unlike Duration, it handles variable month lengths and leap years; use it for age and anniversary calculations.
DateTimeFormatter
static DateTimeFormatter DateTimeFormatter.ofPattern(String) / ofPattern(String, Locale)
var fmt = DateTimeFormatter.ofPattern("dd MMM yyyy", Locale.ENGLISH);
String s = LocalDate.now().format(fmt); // "22 Mar 2026"
var d = LocalDate.parse("22 Mar 2026", fmt);
Always pass a Locale to ofPattern when the pattern contains month/day names (MMM, EEEE) — without it the JVM default locale is used, causing locale-dependent failures.
DateTimeFormatter ISO_LOCAL_DATE / ISO_LOCAL_DATE_TIME / ISO_INSTANT / ISO_OFFSET_DATE_TIME (constants)
// ISO_INSTANT → "2026-03-22T14:30:00Z" (always UTC, ideal for APIs)
String ts = Instant.now().toString(); // calls ISO_INSTANT implicitly
// ISO_OFFSET_DATE_TIME → "2026-03-22T14:30:00+01:00"
String s = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
Prefer built-in ISO formatters for inter-system data exchange; ISO_INSTANT is the safest choice for JSON timestamps as it is unambiguous and parseable by all languages.
String formatter.format(TemporalAccessor) / TemporalAccessor formatter.parse(CharSequence)
var fmt = DateTimeFormatter.ofPattern("yyyyMMdd").withZone(ZoneOffset.UTC);
String s = fmt.format(Instant.now()); // "20260322"
var inst = Instant.from(fmt.parse("20260322"));
withZone() is required when formatting an Instant because Instant has no timezone; withLocale() overrides the locale for display names.
ZoneId / ZoneOffset
static ZoneId ZoneId.of(String zoneId) / ZoneId.systemDefault() / ZoneId.getAvailableZoneIds()
var tz = ZoneId.of("America/Los_Angeles");
var sysZone = ZoneId.systemDefault();
// List all IANA zones:
ZoneId.getAvailableZoneIds().stream().sorted().forEach(System.out::println);
Always use IANA zone IDs like "Europe/Berlin" — never three-letter abbreviations like "EST" which are ambiguous and may map to different offsets on different JVM versions.
ZoneOffset ZoneOffset.UTC / ZoneOffset.of(String offsetId) / ZoneOffset.ofHours(int)
var utc = ZoneOffset.UTC; // +00:00
var ist = ZoneOffset.of("+05:30"); // India Standard Time
var odt = OffsetDateTime.now(ist);
String s = odt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
ZoneOffset is a fixed offset with no DST rules; use it when you know the exact UTC offset (e.g. from an API response header) rather than a geographic zone.
java.io
java.io — legacy I/O
int InputStream.read() / byte[] readAllBytes() (Java 9+) / long transferTo(OutputStream) (Java 9+)
try (var in = MyClass.class.getResourceAsStream("/data.bin")) {
byte[] bytes = in.readAllBytes(); // Java 9+, loads fully into memory
}
readAllBytes() is convenient for small classpath resources; avoid it for large files — use transferTo() or NIO Files.copy() to stream without buffering the whole file.
InputStream.transferTo(OutputStream out) → long (Java 9+)
try (var in = new FileInputStream(src);
var out = new FileOutputStream(dst)) {
var bytes = in.transferTo(out); // returns byte count
}
Copies all bytes from this stream to out; prefer Files.copy() for file paths, but transferTo is useful when you already hold stream references.
void OutputStream.write(byte[]) / write(byte[], int off, int len) / flush() / close()
try (var out = new FileOutputStream("report.bin", true)) { // append=true
out.write(payload);
out.flush();
}
Always use try-with-resources so close() is called even on exception; the boolean append flag in FileOutputStream(File, boolean) prevents overwriting existing content.
InputStreamReader(InputStream in, Charset cs) / OutputStreamWriter(OutputStream out, Charset cs)
try (var rdr = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);
var buf = new BufferedReader(rdr)) {
String line = buf.readLine();
}
Always specify the charset explicitly — the single-arg constructor uses the platform default which differs between Windows and Linux; StandardCharsets.UTF_8 is a constant, not a string lookup.
BufferedReader(Reader) — readLine() → String / Stream<String> lines() / try-with-resources
try (var br = new BufferedReader(new FileReader("log.txt", StandardCharsets.UTF_8))) {
br.lines()
.filter(l -> l.contains("ERROR"))
.forEach(System.out::println);
}
lines() returns a lazy Stream backed by readLine(); the stream is closed when the BufferedReader is closed, so always wrap in try-with-resources.
BufferedWriter(Writer) / PrintWriter(Writer, boolean autoFlush) — println / printf / flush
try (var pw = new PrintWriter(new BufferedWriter(new FileWriter("out.txt", StandardCharsets.UTF_8)), false)) {
pw.printf("%-10s %5.2f%n", name, price);
pw.flush();
}
PrintWriter adds printf/println on top of any Writer; set autoFlush=false for file writes and call flush() explicitly to avoid flushing on every println.
StringWriter — in-memory write / toString() / StringReader(String) — wrap String as Reader
var sw = new StringWriter();
new PrintWriter(sw).printf("Hello %s", name);
String result = sw.toString();
var sr = new StringReader(result); // back to Reader
StringWriter is useful for capturing output from APIs that write to a Writer (e.g. XML serializers, template engines) without touching the filesystem.
ByteArrayOutputStream — write(byte[]) / toByteArray() → byte[] / toString(Charset)
var baos = new ByteArrayOutputStream();
gzip(inputStream, baos); // write compressed bytes
byte[] compressed = baos.toByteArray();
String debug = baos.toString(StandardCharsets.UTF_8);
ByteArrayOutputStream buffers all written bytes in an auto-growing internal array; toByteArray() returns a copy, so subsequent writes don't affect it.
DataOutputStream — writeInt(int) / writeLong(long) / writeUTF(String) / DataInputStream — readInt() / readUTF()
try (var dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.bin")))) {
dos.writeInt(42);
dos.writeUTF("hello"); // 2-byte length prefix + UTF-8 bytes
}
DataOutputStream/DataInputStream are matched pairs for portable binary formats; writeUTF uses a modified UTF-8 encoding, not standard UTF-8, so don't mix with other parsers.
FileInputStream(File) / FileInputStream(String) — basic byte-level file reading with try-with-resources
try (var fis = new FileInputStream("image.png");
var buf = new BufferedInputStream(fis)) {
byte[] header = buf.readNBytes(8); // read exactly 8 bytes (Java 11+)
}
Wrap FileInputStream in BufferedInputStream to reduce system calls; prefer Files.newInputStream(Path) for new code as it works with NIO path abstractions.
java.nio.file
Path
static Path Path.of(String first, String... more) / Paths.get(String first, String... more)
var config = Path.of("config", "app.properties"); // config/app.properties
var abs = Path.of("/etc/hosts");
var fromUri = Path.of(URI.create("file:///tmp/data.json"));
Path.of() (Java 11+) is the preferred factory; Paths.get() is the older equivalent — both return the same implementation. The varargs overload assembles path segments with the OS separator.
Path resolve(String) / Path resolve(Path) / Path resolveSibling(String)
var base = Path.of("uploads");
var file = base.resolve("2026/report.pdf"); // uploads/2026/report.pdf
var sibling = file.resolveSibling("report.txt"); // uploads/2026/report.txt
resolve() appends a relative path to this path; if the argument is absolute it replaces this path entirely, so validate untrusted input to prevent path-traversal attacks.
Path relativize(Path) / Path normalize() / Path toAbsolutePath() / Path toRealPath()
var base = Path.of("/app");
var full = Path.of("/app/data/../logs/app.log");
var rel = base.relativize(full.normalize()); // logs/app.log
normalize() collapses ".." and "." segments; relativize() computes the relative path between two paths — both paths must be absolute or both relative, otherwise it throws.
Path getParent() / Path getFileName() / Path getRoot() / int getNameCount() / Path getName(int index)
var p = Path.of("/var/log/app/server.log");
String name = p.getFileName().toString(); // "server.log"
Path parent = p.getParent(); // /var/log/app
int count = p.getNameCount(); // 4
getFileName() returns the last element as a Path (not a String), and getParent() returns null for root paths; check for null before chaining.
File toFile() / Path toString() / boolean startsWith(Path) / boolean endsWith(Path)
var p = Path.of("uploads/img/photo.jpg");
boolean safe = !p.toAbsolutePath().startsWith(Path.of("/uploads").toAbsolutePath());
File f = p.toFile(); // legacy interop
startsWith/endsWith compare path elements, not string prefixes — "/foo/bar".startsWith("/foo/b") is false; use them for safe path-traversal validation.
Files
static String Files.readString(Path path) / readString(Path, Charset) (Java 11+)
var config = Files.readString(Path.of("config/app.properties"));
var latin = Files.readString(Path.of("legacy.txt"), StandardCharsets.ISO_8859_1);
Reads an entire file as a UTF-8 string in one call; use for config files and small assets, not streaming multi-GB files.
static Path Files.writeString(Path, CharSequence, OpenOption...) (Java 11+)
Files.writeString(Path.of("output.json"), json);
Files.writeString(Path.of("log.txt"), entry + "\n", StandardOpenOption.APPEND, StandardOpenOption.CREATE);
Atomic single-call write; defaults to CREATE, TRUNCATE_EXISTING, WRITE — pass StandardOpenOption.APPEND to append without overwriting.
static byte[] Files.readAllBytes(Path) / static Path Files.write(Path, byte[], OpenOption...)
byte[] img = Files.readAllBytes(Path.of("avatar.png"));
Files.write(Path.of("copy.png"), img);
Use for binary data or when you need the raw byte array; readAllBytes() buffers the whole file so it's inappropriate for files larger than available heap.
static Path Files.copy(Path source, Path target, CopyOption...) / Files.move(Path, Path, CopyOption...)
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
Files.move(tmp, dst, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
Without REPLACE_EXISTING, copy/move throw if the target exists; ATOMIC_MOVE is OS-dependent — it works on most POSIX systems but may fall back to a non-atomic copy on Windows.
static boolean Files.delete(Path) / deleteIfExists(Path) → boolean
Files.delete(tmp); // throws NoSuchFileException if missing
boolean deleted = Files.deleteIfExists(tmp); // returns false if not found
delete() throws on missing file; deleteIfExists() is idempotent and safe for cleanup code; neither deletes non-empty directories — use walkFileTree for recursive delete.
static boolean Files.exists(Path) / isDirectory(Path) / isRegularFile(Path) / long size(Path)
if (Files.isRegularFile(p) && Files.size(p) < 10_000_000) {
process(Files.readAllBytes(p));
}
These checks are not atomic with subsequent operations — TOCTOU race is possible; use them for diagnostic logging rather than security-critical access control.
static Path Files.createDirectories(Path) / createTempFile(String prefix, String suffix)
Files.createDirectories(Path.of("out/reports/2026")); // mkdir -p equivalent
var tmp = Files.createTempFile("upload-", ".tmp"); // OS temp dir
tmp.toFile().deleteOnExit();
createDirectories() is idempotent — it succeeds even if the directory already exists; createTempFile generates a unique name, but you must delete it yourself unless deleteOnExit() is called.
static Stream<Path> Files.list(Path dir) — immediate children only (not recursive)
try (var stream = Files.list(Path.of("uploads"))) {
stream.filter(Files::isRegularFile)
.map(Path::getFileName)
.forEach(System.out::println);
}
Returns a lazy stream backed by an open directory handle — always close it (try-with-resources); order is filesystem-defined, not alphabetical.
static Stream<Path> Files.walk(Path start, FileVisitOption...) (Java 8+) — recursive depth-first
try (var stream = Files.walk(Path.of("src"))) {
stream.filter(p -> p.toString().endsWith(".java"))
.forEach(System.out::println);
}
Lazy depth-first walk returning Stream<Path>; must be closed (try-with-resources) to release directory handle.
static Stream<String> Files.lines(Path) / lines(Path, Charset) — lazy line reading
try (var lines = Files.lines(Path.of("access.log"))) {
long errors = lines.filter(l -> l.contains("ERROR")).count();
}
Lines are read lazily — suitable for large files that don't fit in memory; close the stream to release the file handle, or use Files.readAllLines() when you want a List and the file is small.
static BufferedReader Files.newBufferedReader(Path) / BufferedWriter newBufferedWriter(Path, OpenOption...)
try (var r = Files.newBufferedReader(Path.of("input.csv"));
var w = Files.newBufferedWriter(Path.of("output.csv"))) {
String line;
while ((line = r.readLine()) != null) {
w.write(transform(line)); w.newLine();
}
}
NIO-backed buffered I/O with explicit charset defaulting to UTF-8; prefer over new FileReader/FileWriter which use the platform default charset.
StandardOpenOption / FileVisitor
StandardOpenOption: CREATE / CREATE_NEW / APPEND / TRUNCATE_EXISTING / READ / WRITE / SYNC / DSYNC
Files.writeString(log, entry, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
try (var ch = FileChannel.open(p, StandardOpenOption.READ, StandardOpenOption.WRITE)) { ... }
CREATE opens or creates; CREATE_NEW fails if file exists; APPEND seeks to end before each write; SYNC flushes both data and metadata to storage on every write (use DSYNC for data-only).
static Path Files.walkFileTree(Path, FileVisitor<Path>) with SimpleFileVisitor<Path>
Files.walkFileTree(Path.of("build"), new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
Files.delete(f);
return FileVisitResult.CONTINUE;
}
public FileVisitResult postVisitDirectory(Path d, IOException e) throws IOException {
Files.delete(d);
return FileVisitResult.CONTINUE;
}
});
SimpleFileVisitor provides no-op defaults for all callbacks; override only what you need. postVisitDirectory fires after all children, making it the right place for recursive directory deletion.
java.util.concurrent
Virtual Threads (Java 21+)
Thread.ofVirtual().name(String, long).start(Runnable) → Thread (Java 21+)
var t = Thread.ofVirtual().name("worker-", 0).start(() -> handleRequest(req));
Creates and starts a named virtual thread; virtual threads are lightweight JVM-managed fibers — ideal for blocking I/O at high concurrency.
static Thread Thread.startVirtualThread(Runnable) (Java 21+)
Thread t = Thread.startVirtualThread(() -> process(item));
Quickest way to create and immediately start a virtual thread; equivalent to Thread.ofVirtual().start(task) but in one call.
static ExecutorService Executors.newVirtualThreadPerTaskExecutor() (Java 21+)
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
for (var url : urls) exec.submit(() -> fetch(url));
} // auto-closes: waits for all tasks, then shuts down
Creates a new virtual thread per submitted task; ExecutorService is AutoCloseable in Java 19+ so try-with-resources replaces shutdown/awaitTermination.
StructuredTaskScope (preview / Java 21+)
StructuredTaskScope.ShutdownOnFailure — fork(Callable), join(), throwIfFailed() (preview / Java 21+)
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var user = scope.fork(() -> userRepo.findById(id));
var orders = scope.fork(() -> orderRepo.findByUser(id));
scope.join().throwIfFailed();
return new Dashboard(user.get(), orders.get());
}
Structured concurrency: fan out subtasks, wait for all, cancel remaining if any fails — scope lifetime matches the block. Preview API, expected stable in Java 26.
StructuredTaskScope.ShutdownOnSuccess — fork(Callable), join(), result() (preview / Java 21+)
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
scope.fork(() -> queryPrimary(key));
scope.fork(() -> queryReplica(key));
scope.join();
return scope.result(); // fastest winner
}
First-to-succeed pattern: as soon as one subtask completes successfully the scope cancels remaining tasks and result() returns the winning value.
ExecutorService
static ExecutorService Executors.newFixedThreadPool(int) / newCachedThreadPool() / newSingleThreadExecutor()
ExecutorService fixed = Executors.newFixedThreadPool(8);
ExecutorService cached = Executors.newCachedThreadPool();
ExecutorService single = Executors.newSingleThreadExecutor();
Fixed: bounded pool, good for CPU-bound tasks. Cached: creates threads on demand, reuses idle ones — good for short I/O bursts. Single: serializes all tasks.
static ScheduledExecutorService Executors.newScheduledThreadPool(int)
ScheduledExecutorService sched = Executors.newScheduledThreadPool(2);
sched.scheduleAtFixedRate(() -> poll(), 0, 5, TimeUnit.SECONDS);
sched.schedule(() -> expire(key), 30, TimeUnit.SECONDS);
Schedules tasks with a fixed delay or fixed rate; scheduleAtFixedRate fires regardless of previous run completion, scheduleWithFixedDelay waits for completion first.
Future<T> executor.submit(Callable<T>) / Future<?> executor.submit(Runnable)
Future<String> f = executor.submit(() -> loadData());
String result = f.get(5, TimeUnit.SECONDS); // blocks up to 5 s
Submits a task for async execution; submit(Callable) captures a return value, submit(Runnable) returns Future<?> whose get() returns null on success.
List<Future<T>> executor.invokeAll(Collection<Callable<T>>) / T executor.invokeAny(Collection<Callable<T>>)
List<Future<Result>> futures = executor.invokeAll(tasks); // all done
Result first = executor.invokeAny(tasks); // fastest wins
invokeAll blocks until every task completes; invokeAny blocks until the first succeeds and cancels the rest — useful for redundant calls to multiple endpoints.
executor.shutdown() / shutdownNow() / awaitTermination(long, TimeUnit) / Future.get() / cancel(boolean)
executor.shutdown(); // no new tasks; existing finish
if (!executor.awaitTermination(10, TimeUnit.SECONDS))
executor.shutdownNow(); // interrupt running tasks
future.cancel(true); // mayInterruptIfRunning
Graceful shutdown pattern: stop accepting tasks, wait for completion, force-interrupt if timeout exceeded; cancel(true) sends interrupt to running thread.
CompletableFuture
CompletableFuture.supplyAsync(Supplier, Executor).thenApply(Function).exceptionally(Function<Throwable,T>)
var future = CompletableFuture
.supplyAsync(() -> api.fetchUser(id), executor)
.thenApply(User::toDto)
.exceptionally(ex -> UserDto.unknown());
Async pipeline: supplyAsync runs on a thread pool, thenApply transforms the result on completion, exceptionally provides a fallback — all non-blocking.
CompletableFuture.runAsync(Runnable) — fire-and-forget
CompletableFuture.runAsync(() -> audit.log(event), executor)
.whenComplete((v, ex) -> {
if (ex != null) log.error("audit failed", ex);
});
Runs a Runnable asynchronously with no return value; whenComplete observes completion or failure without altering the result — useful for side-effects like logging.
CF.thenAccept(Consumer) / thenRun(Runnable) — consume result without chaining
cf.thenAccept(data -> cache.put(key, data))
.thenRun(() -> metrics.increment("cache.fill"));
thenAccept receives the result but returns CompletableFuture<Void>; thenRun ignores the result and just runs an action — chain side-effects without transforming data.
CF.thenCompose(Function<T, CompletableFuture<U>>) — flatMap for async steps
CompletableFuture<Order> result =
CompletableFuture.supplyAsync(() -> userRepo.find(id))
.thenCompose(user -> orderRepo.findByUserAsync(user));
Chains dependent async calls without nesting: the function returns a new CompletableFuture, and thenCompose flattens it — avoids CompletableFuture<CompletableFuture<T>>.
CF.thenCombine(CompletableFuture<U>, BiFunction<T,U,V>) — combine two independent futures
var profile = CompletableFuture.supplyAsync(() -> fetchProfile(id));
var prefs = CompletableFuture.supplyAsync(() -> fetchPrefs(id));
var page = profile.thenCombine(prefs, (Profile p, Prefs r) -> new Page(p, r));
Runs two futures in parallel then merges their results with a BiFunction once both complete — the canonical pattern for parallel fan-out then merge.
CF.handle(BiFunction<T, Throwable, U>) — handle both result and exception
CompletableFuture<String> safe = cf.handle((result, ex) -> {
if (ex != null) return "fallback";
return result.toUpperCase();
});
Like exceptionally but always invoked — receives (result, null) on success or (null, throwable) on failure; can both recover from errors and transform the happy path.
CompletableFuture.allOf(CF...) / anyOf(CF...) → CompletableFuture<Void>
CompletableFuture<Void> all = CompletableFuture.allOf(cf1, cf2, cf3);
all.join(); // blocks until all done
Object first = CompletableFuture.anyOf(cf1, cf2, cf3).join();
allOf completes when all futures complete (fails if any fails); anyOf completes with the result of the first to finish — use for barrier synchronization or racing.
CF.join() / get() / complete(T) / completeExceptionally(Throwable)
CompletableFuture<String> cf = new CompletableFuture<>();
String val = cf.join(); // unchecked, unlike get()
cf.complete("done"); // resolve manually
cf.completeExceptionally(new RuntimeException("oops"));
join() blocks like get() but throws unchecked CompletionException; complete()/completeExceptionally() let you resolve a CF from outside — useful for bridging callbacks to futures.
Synchronizers
CountDownLatch(int count) — await() / countDown() — fan-in pattern
var latch = new CountDownLatch(3);
List.of("a", "b", "c").forEach(s ->
executor.submit(() -> { process(s); latch.countDown(); }));
latch.await(); // blocks until count reaches 0
One-shot barrier: count reaches zero when all workers call countDown(), then await() unblocks — not reusable; use CyclicBarrier for repeating rendezvous.
CyclicBarrier(int parties, Runnable barrierAction) — await() — reusable rendezvous
var barrier = new CyclicBarrier(4, () -> mergeResults());
for (int i = 0; i < 4; i++) executor.submit(() -> {
computePartition(); barrier.await(); // meet every round
});
All parties call await(); when the last arrives, the optional barrierAction runs, then all are released — resets automatically for the next round unlike CountDownLatch.
Semaphore(int permits) — acquire() / release() / tryAcquire(long, TimeUnit)
var sem = new Semaphore(10); // max 10 concurrent
sem.acquire();
try { callExternalApi(); }
finally { sem.release(); }
Limits concurrent access to a resource; tryAcquire(timeout, unit) avoids indefinite blocking — use for rate limiting, connection pool guards, or bounded parallelism.
ReentrantLock — lock() / unlock() / tryLock() / newCondition()
var lock = new ReentrantLock();
lock.lock();
try { criticalSection(); }
finally { lock.unlock(); }
if (lock.tryLock(100, TimeUnit.MILLISECONDS)) { // timed attempt
Explicit lock with try/finally discipline; tryLock avoids deadlock by failing fast; newCondition() gives Condition.await()/signal() for producer-consumer coordination.
ReentrantReadWriteLock — readLock().lock() / writeLock().lock()
var rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock(); // many readers concurrently
try { return cache.get(key); } finally { rwLock.readLock().unlock(); }
rwLock.writeLock().lock(); // exclusive
Multiple readers run concurrently; a writer gets exclusive access — ideal for read-heavy caches where writes are rare and you want to avoid serializing reads.
Concurrent Collections
ConcurrentHashMap — putIfAbsent / computeIfAbsent / merge / forEach(parallelismThreshold, BiConsumer)
ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<>();
map.computeIfAbsent(key, k -> new ArrayList<>()).add(val);
map.merge(word, 1, Integer::sum); // word-count pattern
map.forEach(1000, (k, v) -> process(k, v)); // parallel if >1000 entries
Lock-striped hash map safe for concurrent reads and writes; computeIfAbsent is atomic; forEach with parallelismThreshold uses ForkJoinPool for bulk operations.
CopyOnWriteArrayList — thread-safe iteration while writers modify
CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<>();
listeners.add(l); // creates snapshot copy
for (var l : listeners) l.onEvent(e); // safe: iterates original
Every mutation copies the underlying array; iterators see a stable snapshot and never throw ConcurrentModificationException — best when reads vastly outnumber writes.
LinkedBlockingQueue(int capacity) — put(E) / take() / offer(E, long, TimeUnit) / poll(long, TimeUnit)
BlockingQueue<Task> queue = new LinkedBlockingQueue<>(100);
queue.put(task); // blocks if full
Task t = queue.take(); // blocks if empty
boolean ok = queue.offer(task, 500, TimeUnit.MILLISECONDS);
Bounded FIFO blocking queue for producer-consumer pipelines; put/take block indefinitely, offer/poll with timeout return false/null instead of blocking forever.
Atomic Types
AtomicInteger — get() / set(int) / getAndIncrement() / incrementAndGet() / getAndAdd(int) / compareAndSet(int, int)
var counter = new AtomicInteger(0);
int next = counter.incrementAndGet(); // ++counter, lock-free
boolean swapped = counter.compareAndSet(5, 10); // CAS: 5→10 if current==5
Lock-free thread-safe integer; compareAndSet is the building block for non-blocking algorithms — prefer AtomicInteger over synchronized int for counters and flags.
AtomicLong — incrementAndGet() / addAndGet(long) / compareAndSet(long, long)
var totalBytes = new AtomicLong(0L);
totalBytes.addAndGet(bytesRead); // atomic +=
long snapshot = totalBytes.get();
Same as AtomicInteger but 64-bit; addAndGet returns the updated value; use LongAdder instead when update contention is very high and you only need the final sum.
AtomicReference<T> — get() / set(T) / compareAndSet(T, T) / getAndSet(T)
var ref = new AtomicReference<Config>(initialConfig);
Config old, updated;
do {
old = ref.get();
updated = old.withTimeout(newTimeout);
} while (!ref.compareAndSet(old, updated)); // CAS loop
Lock-free atomic reference swap; the CAS loop retries if another thread raced ahead — use for publishing immutable snapshots like config objects without locking.
AtomicBoolean — get() / set(boolean) / compareAndSet(boolean, boolean)
var initialized = new AtomicBoolean(false);
if (initialized.compareAndSet(false, true)) {
init(); // runs exactly once across threads
}
Atomic flag; compareAndSet(false, true) returns true only for the one thread that wins the race — classic idiom for one-time initialization or run-once guards.
java.net.http
HttpClient.newHttpClient() → HttpClient (Java 11+)
var client = HttpClient.newHttpClient();
// default: HTTP/2 preferred, no timeout, no redirect following
Convenience factory for a default client; thread-safe and suitable for reuse across all requests in an application — create once, share globally.
HttpClient.newBuilder().connectTimeout(Duration).followRedirects(Redirect).build() (Java 11+)
var client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
The HttpClient is thread-safe and should be reused across requests; NORMAL follows redirects except from HTTPS to HTTP.
HttpClient.Redirect.NORMAL / ALWAYS / NEVER
HttpClient.Redirect.NORMAL // follows except HTTPS→HTTP downgrades
HttpClient.Redirect.ALWAYS // follows all redirects including HTTPS→HTTP
HttpClient.Redirect.NEVER // default — no automatic redirect following
Redirect policy passed to newBuilder().followRedirects(); NORMAL is the safe default for most applications — ALWAYS only if you trust all endpoints.
HttpRequest.newBuilder(URI).GET().timeout(Duration).header(String, String).build()
var req = HttpRequest.newBuilder(URI.create("https://api.example.com/data"))
.GET()
.header("Accept", "application/json")
.header("Authorization", "Bearer " + token)
.timeout(Duration.ofSeconds(30))
.build();
HttpRequest is immutable once built; per-request timeout overrides client-level connect timeout — set both to bound worst-case latency.
HttpRequest.newBuilder(URI).POST(BodyPublisher).header(String, String).timeout(Duration).build()
var req = HttpRequest.newBuilder(URI.create(endpoint))
.POST(HttpRequest.BodyPublishers.ofString(json))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + token)
.timeout(Duration.ofSeconds(30))
.build();
Builds an immutable request; set timeout per-request so long-running endpoints don't block the shared client.
HttpRequest.BodyPublishers.ofString(String) / ofFile(Path) / ofByteArray(byte[]) / noBody()
HttpRequest.BodyPublishers.ofString(json) // UTF-8 string body
HttpRequest.BodyPublishers.ofFile(Path.of("upload.bin")) // stream file
HttpRequest.BodyPublishers.ofByteArray(bytes) // raw bytes
HttpRequest.BodyPublishers.noBody() // DELETE / GET
BodyPublishers are the source-side complement to BodyHandlers; noBody() is required for methods like DELETE that send no payload.
HttpRequest.newBuilder(URI).PUT(BodyPublisher).build() / .DELETE().build()
var put = HttpRequest.newBuilder(URI.create(url))
.PUT(HttpRequest.BodyPublishers.ofString(json))
.header("Content-Type", "application/json").build();
var del = HttpRequest.newBuilder(URI.create(url))
.DELETE().build();
PUT replaces the resource; DELETE removes it — both use the same builder pattern as GET/POST with the method call swapped.
HttpClient.send(HttpRequest, BodyHandler<T>) → HttpResponse<T> (synchronous)
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() == 200) {
process(resp.body());
}
Blocking call — throws IOException and InterruptedException; suitable for scripts or when the calling thread is already async (e.g., virtual thread).
HttpClient.sendAsync(HttpRequest, BodyHandler<T>) → CompletableFuture<HttpResponse<T>>
client.sendAsync(req, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(json -> process(json))
.exceptionally(ex -> { log.error("fetch failed", ex); return null; });
Non-blocking HTTP; returns a CompletableFuture — compose with thenApply/exceptionally for the full async pipeline without blocking threads.
HttpResponse.statusCode() / body() / headers() / uri()
int status = resp.statusCode(); // e.g. 200, 404, 500
String body = resp.body(); // decoded per BodyHandler
String ct = resp.headers().firstValue("content-type").orElse("");
URI finalUri = resp.uri(); // may differ from request URI after redirects
uri() returns the final URI after redirects — always check statusCode() before consuming body(); 2xx means success, not correctness.
HttpResponse.BodyHandlers.ofString() / ofFile(Path) / ofByteArray() / ofInputStream() / discarding()
HttpResponse.BodyHandlers.ofString() // decode as UTF-8 String
HttpResponse.BodyHandlers.ofFile(Path.of("out.bin")) // write directly to file
HttpResponse.BodyHandlers.ofByteArray() // raw byte[]
HttpResponse.BodyHandlers.ofInputStream() // stream large responses
HttpResponse.BodyHandlers.discarding() // fire-and-forget
Choose the handler to match consumption: ofInputStream() for large payloads to avoid buffering the entire body; discarding() when only status code matters.
HttpResponse.headers().firstValue(String) / allValues(String) / map()
HttpHeaders headers = resp.headers();
String type = headers.firstValue("content-type").orElse("");
List<String> cookies = headers.allValues("set-cookie");
Map<String, List<String>> all = headers.map();
Header names are case-insensitive per HTTP spec; allValues handles multi-value headers like Set-Cookie that appear multiple times.
HttpClient.newWebSocketBuilder().buildAsync(URI, WebSocket.Listener) → CompletableFuture<WebSocket>
client.newWebSocketBuilder()
.buildAsync(URI.create("wss://echo.example.com"), new WebSocket.Listener() {
public CompletionStage<?> onText(WebSocket ws, CharSequence data, boolean last) {
handle(data); ws.request(1); return null;
}
})
.thenAccept(ws -> ws.sendText("hello", true));
WebSocket uses a flow-control model: call ws.request(n) in each listener callback to receive n more messages — forgetting request(1) silently stops delivery.
java.util.regex
static Pattern Pattern.compile(String regex) / compile(String regex, int flags)
private static final Pattern EMAIL =
Pattern.compile("^[\\w.+-]+@[\\w-]+\\.[\\w.]+$", Pattern.CASE_INSENSITIVE);
// compile once at class load; Matcher is created per use via EMAIL.matcher(input)
Pattern is thread-safe; Matcher is not — create a new Matcher per thread/request with pattern.matcher(input). Compile once, match many.
Pattern flags: CASE_INSENSITIVE / MULTILINE / DOTALL / UNICODE_CASE
Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
Pattern.compile(regex, Pattern.MULTILINE); // ^ and $ match line boundaries
Pattern.compile(regex, Pattern.DOTALL); // . matches \n too
// or inline: (?i) (?m) (?s) inside the regex string
MULTILINE makes ^ and $ match line boundaries instead of string start/end; DOTALL makes . match newlines — combine flags with bitwise OR.
static boolean Pattern.matches(String regex, CharSequence input)
boolean ok = Pattern.matches("\\d{4}-\\d{2}-\\d{2}", input);
// equivalent to Pattern.compile(regex).matcher(input).matches()
// recompiles every call — use only for one-shot checks
Convenience one-liner for full-string match; recompiles the pattern on each call — cache a Pattern.compile() result if called in a loop or hot path.
static String Pattern.quote(String s)
String escaped = Pattern.quote(userInput); // wraps in \Q...\E
Pattern p = Pattern.compile(escaped + "\\s+");
// safe: userInput may contain . * + ? ( ) [ ] { } ^ $ | \
Essential when embedding user-supplied strings in a regex — prevents regex injection by wrapping the literal in \Q...\E so all metacharacters are treated as literals.
Pattern.matcher(CharSequence) → Matcher
Matcher m = EMAIL.matcher(input); // create per call — not thread-safe
boolean valid = m.matches(); // full-string match
boolean found = m.find(); // scan for next occurrence
boolean prefix = m.lookingAt(); // match at start only
matches() requires the pattern to span the entire input; find() scans forward and can be called repeatedly in a loop to iterate all matches.
Matcher.find() → boolean / group(String name) → String / replaceAll(Function<MatchResult,String>) (Java 9+)
var m = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})").matcher(text);
while (m.find()) { process(m.group("year"), m.group("month"), m.group("day")); }
find() scans for the next match (unlike matches() which requires full-string); named groups make extraction self-documenting.
Matcher.group() / group(int n) / groupCount() / start() / end()
Matcher m = Pattern.compile("(\\d+)-(\\w+)").matcher("42-hello");
if (m.matches()) {
m.group(); // "42-hello" — full match (group 0)
m.group(1); // "42"
m.group(2); // "hello"
m.start(1); m.end(1); // span of group 1 in input
}
Group 0 is always the full match; numbered groups are 1-based and counted by opening parenthesis left to right; groupCount() returns number of capturing groups.
Matcher.replaceAll(String replacement) / replaceFirst(String) / replaceAll(Function<MatchResult,String>) (Java 9+)
String masked = Pattern.compile("\\d{4}").matcher(text).replaceAll("****");
// Java 9+: functional replacement with access to each MatchResult
String upper = Pattern.compile("\\b\\w").matcher(text)
.replaceAll(mr -> mr.group().toUpperCase());
The Function overload (Java 9+) enables dynamic replacements without constructing a replacement string — use it for title-casing, redaction, or transformations.
Matcher.reset(CharSequence newInput) → Matcher
Matcher m = pattern.matcher(""); // allocate once
for (String line : lines) {
if (m.reset(line).find()) { // reuse, avoid allocation
handle(m.group());
}
}
reset() avoids creating a new Matcher object per iteration — significant in tight loops; returns the Matcher itself so it can be chained with find() or matches().
String.matches(String regex) / replaceAll(String regex, String) / split(String regex, int limit)
"hello123".matches("[a-z]+\\d+") // true — full match, recompiles
"foo bar baz".replaceAll("\\s+", "-") // "foo-bar-baz"
"a,b,,c".split(",") // ["a","b","","c"] — trailing empty dropped
"a,b,,c".split(",", -1) // keeps all trailing empty strings
String convenience methods recompile the regex every call — extract to a static Pattern field for any hot path; split(-1) preserves trailing empty tokens.