AI Coding Tools Cheat Sheet 2026 — Claude, Cursor, Copilot, and More

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet compares AI coding tools, their features, pricing, and best use cases. Last updated: March 2026 Tool Comparison Tool Type Best For Pricing (Mar 2026) Claude Code CLI agent Multi-file edits, refactoring, debugging $20/mo Pro, $100/$200 Max Cursor IDE (VS Code fork) Day-to-day coding with AI inline $20/mo (Pro) GitHub Copilot IDE extension Autocomplete, inline suggestions Free (limited), $10/mo Pro, $39/mo Pro+ Windsurf IDE (VS Code fork) Chat + agent workflows $15/mo (Pro) ChatGPT Chat Explaining code, brainstorming $20/mo (Plus) Gemini CLI CLI Quick questions, code review Free (1K req/day), Pro/Ultra plans Codex CLI CLI Code review, autonomous tasks OpenAI API pricing Feature Matrix Feature Claude Code Cursor Copilot Windsurf Autocomplete — Yes Yes Yes Chat Yes Yes Yes Yes Multi-file editing Yes Yes Limited Yes Terminal commands Yes Yes (Cmd+K in terminal) — — Agent mode Yes Yes Yes Yes Git integration Yes Yes Yes Yes MCP support Yes Yes Yes Yes Custom rules CLAUDE.md .cursorrules .github/copilot-instructions.md .windsurfrules Context window 200K (up to 1M on Max) 128K 128K 128K Claude Code Shortcuts Command Description /help Show available commands /clear Clear conversation /compact Compress context to save tokens /cost Show token usage and cost /init Create CLAUDE.md project file Esc Cancel current generation Shift+Tab Accept file edit Ctrl+C Exit Claude Code Tips # Run Claude Code claude # Start with a prompt claude "fix the failing tests" # Non-interactive mode claude -p "explain this function" < file.py # Use a specific model claude --model sonnet # or opus, haiku # Continue last conversation claude --continue CLAUDE.md — Project Instructions # CLAUDE.md - Use TypeScript strict mode - Tests: Jest with React Testing Library - Style: Tailwind CSS, no inline styles - Always run tests before committing Place CLAUDE.md in your project root. Claude reads it automatically. ...

March 25, 2026 · 4 min

Python Cheat Sheet 2026 — Syntax, Data Structures, and Common Patterns

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Python syntax from basics to advanced patterns. Try examples at pythontutor.com. Last updated: March 2026 Variables and Types name = "Alex" # str age = 25 # int height = 1.75 # float is_active = True # bool nothing = None # NoneType Type Example Notes int 42 No size limit float 3.14 64-bit decimal str "hello" Immutable bool True, False Capitalized None None Null equivalent list [1, 2, 3] Mutable, ordered tuple (1, 2, 3) Immutable, ordered dict {"a": 1} Key-value pairs set {1, 2, 3} Unique values, unordered Type Conversions int("42") # 42 float("3.14") # 3.14 str(42) # "42" list((1, 2, 3)) # [1, 2, 3] tuple([1, 2, 3]) # (1, 2, 3) set([1, 1, 2]) # {1, 2} bool(0) # False bool("") # False bool([]) # False bool("hello") # True Strings name = "Alex" f"Hello {name}" # f-string: Hello Alex f"Age: {age + 1}" # f-string with expression f"{price:.2f}" # format: 9.99 f"{name!r}" # repr: 'Alex' f"{num:,}" # thousands separator: 1,000,000 f"{value:>10}" # right-align, width 10 f"{value:<10}" # left-align, width 10 # Common methods "hello".upper() # "HELLO" "HELLO".lower() # "hello" "hello world".title() # "Hello World" " hello ".strip() # "hello" "hello world".split() # ["hello", "world"] "hello world".split("o") # ["hell", " w", "rld"] ", ".join(["a", "b", "c"]) # "a, b, c" "hello".replace("l", "r") # "herro" "hello".startswith("he") # True "hello".endswith("lo") # True "hello world".find("world") # 6 (-1 if not found) "hello world".count("l") # 3 "42".isdigit() # True # Multi-line strings text = """ First line Second line """ # Raw strings (no escape processing) path = r"C:\Users\name\folder" Lists nums = [1, 2, 3, 4, 5] # Access nums[0] # 1 (first) nums[-1] # 5 (last) nums[1:3] # [2, 3] (slice) nums[:3] # [1, 2, 3] (first 3) nums[2:] # [3, 4, 5] (from index 2) nums[::2] # [1, 3, 5] (every 2nd) nums[::-1] # [5, 4, 3, 2, 1] (reversed) # Modify nums.append(6) # add to end nums.insert(0, 0) # insert at index nums.extend([7, 8]) # add multiple nums.remove(3) # remove first occurrence nums.pop() # remove and return last nums.pop(0) # remove and return at index nums.sort() # sort in place nums.sort(reverse=True) # sort descending nums.reverse() # reverse in place nums.clear() # remove all # Functions len(nums) # length min(nums) # smallest max(nums) # largest sum(nums) # total sorted(nums) # new sorted list reversed(nums) # reversed iterator Dictionaries user = {"name": "Alex", "age": 25, "city": "Berlin"} # Access user["name"] # "Alex" (KeyError if missing) user.get("name") # "Alex" user.get("phone", "N/A") # "N/A" (default if missing) # Modify user["age"] = 26 # update user["email"] = "alex@mail.com" # add new key del user["city"] # delete key user.pop("age") # remove and return value # Iterate user.keys() # dict_keys(["name", "age", ...]) user.values() # dict_values(["Alex", 25, ...]) user.items() # dict_items([("name", "Alex"), ...]) for key, value in user.items(): print(f"{key}: {value}") # Merge (Python 3.9+) merged = dict1 | dict2 # dict2 values win on conflict Sets and Tuples # Sets — unique values, unordered colors = {"red", "green", "blue"} colors.add("yellow") colors.remove("red") # KeyError if missing colors.discard("red") # no error if missing a | b # union a & b # intersection a - b # difference a ^ b # symmetric difference # Tuples — immutable point = (10, 20) x, y = point # unpacking name, *rest = ("Alex", 25, "Berlin") # name="Alex", rest=[25, "Berlin"] Control Flow # if / elif / else if age < 18: print("minor") elif age < 65: print("adult") else: print("senior") # Ternary status = "adult" if age >= 18 else "minor" # for loop for item in items: print(item) for i in range(5): # 0, 1, 2, 3, 4 for i in range(2, 10): # 2, 3, ..., 9 for i in range(0, 10, 2): # 0, 2, 4, 6, 8 for i, item in enumerate(items): # index + value print(f"{i}: {item}") for a, b in zip(list1, list2): # parallel iteration print(a, b) # while loop while count > 0: count -= 1 # break / continue for item in items: if item == "skip": continue # skip this iteration if item == "stop": break # exit loop Pattern Matching (Python 3.10+) match status_code: case 200: print("OK") case 404: print("Not Found") case 500: print("Server Error") case _: print(f"Unknown: {status_code}") # Match with destructuring match point: case (0, 0): print("Origin") case (x, 0): print(f"On x-axis at {x}") case (0, y): print(f"On y-axis at {y}") case (x, y): print(f"Point at ({x}, {y})") # Match with guards match user: case {"role": "admin", "name": name}: print(f"Admin: {name}") case {"role": "user", "name": name} if name != "blocked": print(f"User: {name}") Comprehensions # List comprehension squares = [x**2 for x in range(10)] evens = [x for x in nums if x % 2 == 0] pairs = [(x, y) for x in range(3) for y in range(3)] # Dict comprehension word_lengths = {word: len(word) for word in words} filtered = {k: v for k, v in data.items() if v > 0} # Set comprehension unique_lengths = {len(word) for word in words} # Generator expression (lazy, memory-efficient) total = sum(x**2 for x in range(1000000)) Functions # Basic function def greet(name): return f"Hello {name}" # Default parameters def greet(name="World"): return f"Hello {name}" # *args and **kwargs def func(*args, **kwargs): print(args) # tuple of positional args print(kwargs) # dict of keyword args # Lambda double = lambda x: x * 2 sorted(users, key=lambda u: u["age"]) # Type hints (Python 3.10+) def greet(name: str) -> str: return f"Hello {name}" def process(items: list[int]) -> dict[str, int]: return {"sum": sum(items), "count": len(items)} Classes class User: def __init__(self, name: str, age: int): self.name = name self.age = age def greet(self) -> str: return f"Hi, I'm {self.name}" def __repr__(self) -> str: return f"User({self.name!r}, {self.age})" user = User("Alex", 25) # Dataclass (Python 3.7+) — auto-generates __init__, __repr__, __eq__ from dataclasses import dataclass @dataclass class User: name: str age: int city: str = "Unknown" # Inheritance class Admin(User): def __init__(self, name, age, level): super().__init__(name, age) self.level = level Error Handling try: result = 10 / 0 except ZeroDivisionError: print("Cannot divide by zero") except (ValueError, TypeError) as e: print(f"Error: {e}") else: print("Success") # runs if no exception finally: print("Always runs") # cleanup # Raise an exception raise ValueError("Invalid input") File I/O # Read entire file with open("file.txt", "r") as f: content = f.read() # Read lines with open("file.txt", "r") as f: lines = f.readlines() # list of lines # or for line in f: print(line.strip()) # Write with open("file.txt", "w") as f: # overwrite f.write("Hello\n") with open("file.txt", "a") as f: # append f.write("More text\n") # JSON import json data = json.loads('{"name": "Alex"}') # parse string text = json.dumps(data, indent=2) # to string with open("data.json", "r") as f: data = json.load(f) # parse file with open("data.json", "w") as f: json.dump(data, f, indent=2) # write file Async / Await import asyncio async def fetch_data(url: str) -> str: # simulate async work await asyncio.sleep(1) return f"Data from {url}" # Run async function async def main(): result = await fetch_data("https://api.example.com") print(result) asyncio.run(main()) # Run tasks in parallel async def main(): results = await asyncio.gather( fetch_data("https://api1.example.com"), fetch_data("https://api2.example.com"), ) print(results) # both complete in ~1 second, not 2 Common Built-in Functions Function Description Example len(x) Length len([1,2,3]) → 3 range(n) Sequence 0..n-1 range(5) → 0,1,2,3,4 enumerate(x) Index + value enumerate(["a","b"]) zip(a, b) Pair elements zip([1,2], ["a","b"]) map(fn, x) Apply function map(str, [1,2,3]) filter(fn, x) Filter elements filter(bool, [0,1,"",2]) any(x) True if any truthy any([False, True]) → True all(x) True if all truthy all([True, True]) → True sorted(x) New sorted list sorted([3,1,2]) → [1,2,3] reversed(x) Reversed iterator list(reversed([1,2,3])) isinstance(x, type) Type check isinstance(42, int) → True type(x) Get type type(42) → <class 'int'> dir(x) List attributes dir([]) help(x) Show docs help(str.split) Virtual Environments python -m venv .venv # create source .venv/bin/activate # activate (macOS/Linux) .venv\Scripts\activate # activate (Windows) pip install requests # install package pip freeze > requirements.txt # save dependencies pip install -r requirements.txt # install from file deactivate # deactivate Common Mistakes Mutable default arguments — def add(item, items=[]) shares the same list across all calls. Use def add(item, items=None) and items = items or [] inside the function. ...

March 22, 2026 · 7 min

SQL Cheat Sheet 2026 — Queries, JOINs, and Performance

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers SQL from basic queries to window functions and performance. Try examples at db-fiddle.com. Last updated: March 2026 SELECT Basics SELECT * FROM users; -- all columns SELECT name, email FROM users; -- specific columns SELECT DISTINCT city FROM users; -- unique values SELECT name AS full_name FROM users; -- column alias SELECT * FROM users LIMIT 10; -- first 10 rows SELECT * FROM users LIMIT 10 OFFSET 20; -- rows 21-30 (pagination) WHERE — Filtering Rows SELECT * FROM users WHERE age > 18; SELECT * FROM users WHERE city = 'Berlin'; SELECT * FROM users WHERE age BETWEEN 18 AND 30; SELECT * FROM users WHERE city IN ('Berlin', 'Munich', 'Hamburg'); SELECT * FROM users WHERE name LIKE 'A%'; -- starts with A SELECT * FROM users WHERE name LIKE '%son'; -- ends with son SELECT * FROM users WHERE name LIKE '%alex%'; -- contains alex SELECT * FROM users WHERE email IS NULL; -- null check SELECT * FROM users WHERE email IS NOT NULL; SELECT * FROM users WHERE age > 18 AND city = 'Berlin'; SELECT * FROM users WHERE age > 65 OR age < 18; SELECT * FROM users WHERE NOT city = 'Berlin'; ORDER BY and LIMIT SELECT * FROM users ORDER BY name; -- ascending (default) SELECT * FROM users ORDER BY age DESC; -- descending SELECT * FROM users ORDER BY city, name; -- multiple columns SELECT * FROM users ORDER BY age DESC LIMIT 5; -- top 5 oldest INSERT, UPDATE, DELETE -- Insert one row INSERT INTO users (name, email, age) VALUES ('Alex', 'alex@example.com', 25); -- Insert multiple rows INSERT INTO users (name, email, age) VALUES ('Sam', 'sam@example.com', 30), ('Jordan', 'jordan@example.com', 22); -- Update UPDATE users SET age = 26 WHERE name = 'Alex'; -- Update multiple columns UPDATE users SET city = 'Munich', age = 27 WHERE id = 1; -- Delete DELETE FROM users WHERE id = 5; -- Delete all rows (use with caution!) DELETE FROM users; -- Faster delete all (resets table) TRUNCATE TABLE users; -- UPSERT — insert or update if exists (PostgreSQL) INSERT INTO users (email, name) VALUES ('alex@example.com', 'Alex') ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name; -- MySQL equivalent INSERT INTO users (email, name) VALUES ('alex@example.com', 'Alex') ON DUPLICATE KEY UPDATE name = VALUES(name); Warning: Always use WHERE with UPDATE and DELETE. Without it, every row is affected. ...

March 21, 2026 · 8 min

Docker Cheat Sheet 2026 — Commands, Dockerfile, and Compose

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Docker CLI commands, Dockerfile instructions, Docker Compose, volumes, networking, and production tips. Last updated: March 2026 How Docker Works ┌──────────────┐ docker build ┌──────────┐ docker run ┌────────────┐ │ Dockerfile │ ───────────────► │ Image │ ─────────────► │ Container │ │ (recipe) │ │ (template)│ │ (running) │ └──────────────┘ └──────────┘ └────────────┘ │ docker push │ ┌────▼───────┐ │ Registry │ │ (Docker Hub)│ └────────────┘ Container Commands Command Description docker run <image> Create and start a container docker run -d <image> Run in background (detached) docker run -it <image> bash Run interactively with shell (sh for Alpine) docker run -p 8080:80 <image> Map host port 8080 to container port 80 docker run --name myapp <image> Run with a custom name docker run --rm <image> Automatically remove container when it stops docker run -e KEY=value <image> Set environment variable docker run -v /host:/container <image> Mount a volume docker ps List running containers docker ps -a List all containers (including stopped) docker stop <container> Stop a running container docker start <container> Start a stopped container docker restart <container> Restart a container docker rm <container> Remove a stopped container docker rm -f <container> Force remove (even if running) docker exec -it <container> bash Open a shell inside a running container docker logs <container> View container logs docker logs -f <container> Follow logs in real-time docker inspect <container> Show detailed container info (JSON) docker stats Live resource usage for all containers docker cp <container>:/path ./local Copy file from container to host docker cp ./local <container>:/path Copy file from host to container docker container prune Remove all stopped containers docker kill <container> Force stop a container (SIGKILL) Image Commands Command Description docker images List all local images docker pull <image> Download an image from registry docker push <image> Upload an image to registry docker build -t myapp . Build image from Dockerfile in current dir docker build -t myapp:v1 . Build with a tag/version docker tag <image> <new-tag> Add a tag to an image docker rmi <image> Remove an image docker image prune Remove unused (dangling) images docker system prune -a Remove all unused images, containers, networks (not volumes) docker system prune -a --volumes Remove everything including volumes docker history <image> Show image layers and sizes docker login Log in to Docker Hub (required before push) docker logout Log out from registry docker save -o image.tar <image> Export image to tar file docker load -i image.tar Import image from tar file Dockerfile Reference # Base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy dependency files first (for caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --production # Copy application code COPY . . # Expose a port (documentation only) EXPOSE 3000 # Default command when container starts CMD ["node", "server.js"] Dockerfile Instructions Instruction Description FROM <image> Base image (required, must be first) WORKDIR /app Set working directory for subsequent commands COPY <src> <dest> Copy files from host to image ADD <src> <dest> Like COPY but can extract tar and fetch URLs RUN <command> Execute command during build (creates a layer) ENV KEY=value Set environment variable ARG KEY=value Build-time variable (not available at runtime) EXPOSE <port> Document which port the app listens on CMD ["executable", "arg"] Default command (can be overridden) ENTRYPOINT ["executable"] Fixed command (CMD becomes arguments) VOLUME /data Create a mount point for persistent data USER <username> Switch to non-root user `HEALTHCHECK CMD curl -f http://localhost/ CMD vs ENTRYPOINT # CMD — default command, can be overridden CMD ["python", "app.py"] # docker run myapp → runs python app.py # docker run myapp bash → runs bash (overrides CMD) # ENTRYPOINT — fixed command, CMD becomes arguments ENTRYPOINT ["python"] CMD ["app.py"] # docker run myapp → runs python app.py # docker run myapp test.py → runs python test.py Multi-Stage Build # Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production (smaller image) FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] Multi-stage builds produce smaller images — the final image only contains the production output, not the build tools. ...

March 19, 2026 · 6 min

Jetpack Compose Cheat Sheet 2026 — Every Component and Modifier

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Jetpack Compose components, modifiers, state, navigation, and common patterns. Last updated: April 2026 Core Composables Composable Usage Text("Hello") Display text Text("Bold", fontWeight = FontWeight.Bold) Styled text Button(onClick = { }) { Text("Click") } Clickable button OutlinedButton(onClick = { }) { Text("Outlined") } Outlined variant TextButton(onClick = { }) { Text("Text") } Text-only button IconButton(onClick = { }) { Icon(...) } Icon button TextField(value, onValueChange = { }) Text input field OutlinedTextField(value, onValueChange = { }) Outlined text input Image(painter, contentDescription) Display an image Icon(Icons.Default.Home, contentDescription) Material icon Checkbox(checked, onCheckedChange) Checkbox Switch(checked, onCheckedChange) Toggle switch RadioButton(selected, onClick) Radio button Slider(value, onValueChange) Slider CircularProgressIndicator() Loading spinner LinearProgressIndicator(progress) Progress bar HorizontalDivider() Horizontal divider line (replaces deprecated Divider()) Spacer(modifier = Modifier.height(16.dp)) Empty space Layouts // Column — vertical stack Column { Text("First") Text("Second") } // Row — horizontal stack Row { Text("Left") Spacer(Modifier.weight(1f)) Text("Right") } // Box — stack on top of each other Box { Image(...) // background Text("Overlay") // on top } // LazyColumn — scrollable vertical list (RecyclerView replacement) LazyColumn { items(list) { item -> Text(item.name) } } // LazyRow — scrollable horizontal list LazyRow { items(list) { item -> Card { Text(item.name) } } } // LazyVerticalGrid — grid layout LazyVerticalGrid(columns = GridCells.Fixed(2)) { items(list) { item -> Card { Text(item.name) } } } Common Modifiers Modifiers change the appearance and behavior of composables. Order matters — modifiers are applied top to bottom. ...

March 18, 2026 · 6 min

Git Commands Cheat Sheet 2026 — Every Command You Need

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Git commands from basics to advanced workflows. Last updated: April 2026 Setup and Config Command Description git config --global user.name "Alex" Set your name (shown in commits) git config --global user.email "alex@example.com" Set your email git config --global init.defaultBranch main Set default branch name git config --list Show all config settings git init Create a new repository git clone <url> Clone a remote repository git clone <url> <folder> Clone into a specific folder Basic Workflow Command Description git status Show changed, staged, and untracked files git add <file> Stage a file for commit git add . Stage all changes git add -p Stage changes interactively (hunk by hunk) git commit -m "message" Commit staged changes git commit -am "message" Stage tracked files and commit (does NOT stage untracked files) git commit --amend Modify the last commit (add files or fix message) git diff Show unstaged changes git diff --staged Show staged changes (ready to commit) git diff HEAD Show all changes (staged + unstaged) Working Directory → git add → Staging Area → git commit → Repository Viewing History Command Description git log Show commit history git log --oneline One line per commit git log --oneline --graph --all Visual branch graph git log -5 Show last 5 commits git log --author="Alex" Filter by author git log --since="2026-01-01" Commits after a date git log -- <file> History of a specific file git show <commit> Show details of a commit git blame <file> Show who changed each line Branching Command Description git branch List local branches git branch -a List all branches (local + remote) git branch <name> Create a new branch git branch -d <name> Delete a branch (safe — won’t delete unmerged) git branch -D <name> Force delete a branch git branch -m <old> <new> Rename a branch git switch <name> Switch to a branch git switch -c <name> Create and switch to a new branch git checkout <name> Switch to a branch (older syntax) git checkout -b <name> Create and switch (older syntax) Branch Workflow (ASCII Diagram) main: A --- B --- C --- F (merge commit) \ / feature: D --- E - Merging Command Description git merge <branch> Merge branch into current branch git merge --no-ff <branch> Force a merge commit (no fast-forward) git merge --squash <branch> Merge all commits as one (does not auto-commit) git merge --abort Cancel a merge in progress Resolving Conflicts When Git cannot auto-merge, it marks conflicts in the file: ...

March 17, 2026 · 6 min

Kotlin Cheat Sheet 2026 — Quick Reference Guide

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Kotlin syntax from basics to coroutines. Try examples live at play.kotlinlang.org. Last updated: April 2026 Variables Syntax Description val name = "Alex" Immutable (read-only) — cannot reassign var count = 0 Mutable — can reassign val age: Int = 25 Explicit type annotation const val PI = 3.14 Compile-time constant (top-level or object only) val name = "Alex" // type inferred as String var score = 0 // type inferred as Int score = 10 // OK — var can be reassigned // name = "Sam" // ERROR — val cannot be reassigned Basic Types Type Example Notes Int 42 32-bit integer Long 42L 64-bit integer Double 3.14 64-bit decimal Float 3.14f 32-bit decimal Boolean true, false String "hello" Immutable Char 'A' Single character Type Conversions val x: Int = 42 val d: Double = x.toDouble() // 42.0 val s: String = x.toString() // "42" val i: Int = "123".toInt() // 123 val safe: Int? = "abc".toIntOrNull() // null Null Safety Syntax Description String? Nullable type — can hold null name?.length Safe call — returns null if name is null name ?: "default" Elvis operator — use default if null name!! Not-null assertion — throws if null (avoid this) name?.let { ... } Execute block only if not null val name: String? = null val len = name?.length // null (no crash) val safe = name ?: "Unknown" // "Unknown" // val crash = name!!.length // throws NullPointerException String Templates val name = "Alex" println("Hello $name") // Hello Alex println("Length: ${name.length}") // Length: 4 println("Sum: ${2 + 3}") // Sum: 5 Functions // Regular function fun greet(name: String): String { return "Hello $name" } // Single-expression function fun greet(name: String) = "Hello $name" // Default parameters fun greet(name: String = "World") = "Hello $name" // Named arguments greet(name = "Alex") // Unit return type (void equivalent) fun log(message: String) { println(message) } Control Flow if / else (is an expression) val max = if (a > b) a else b when (replaces switch) when (x) { 1 -> println("one") 2, 3 -> println("two or three") in 4..10 -> println("between 4 and 10") is String -> println("it is a string") else -> println("something else") } // Guard conditions in when (Kotlin 2.2+) when (val result = fetchData()) { is Result.Success if result.data.isNotEmpty() -> show(result.data) is Result.Success -> showEmpty() is Result.Error -> showError(result.message) } // when as expression val label = when { score >= 90 -> "A" score >= 80 -> "B" else -> "C" } Loops for (i in 1..5) { } // 1, 2, 3, 4, 5 for (i in 1 until 5) { } // 1, 2, 3, 4 (or 1..<5) for (i in 1..<5) { } // 1, 2, 3, 4 (open-ended range, Kotlin 1.8+) for (i in 5 downTo 1) { } // 5, 4, 3, 2, 1 for (i in 0..10 step 2) { } // 0, 2, 4, 6, 8, 10 for (item in list) { } // iterate a collection list.forEachIndexed { index, item -> } Collections Type Create Mutable Version List listOf(1, 2, 3) mutableListOf(1, 2, 3) Set setOf(1, 2, 3) mutableSetOf(1, 2, 3) Map mapOf("a" to 1) mutableMapOf("a" to 1) Common Operations val numbers = listOf(1, 2, 3, 4, 5) numbers.filter { it > 2 } // [3, 4, 5] numbers.map { it * 2 } // [2, 4, 6, 8, 10] numbers.first() // 1 numbers.last() // 5 numbers.firstOrNull { it > 10 } // null numbers.any { it > 3 } // true numbers.all { it > 0 } // true numbers.count { it % 2 == 0 } // 2 numbers.sum() // 15 numbers.sorted() // [1, 2, 3, 4, 5] numbers.reversed() // [5, 4, 3, 2, 1] numbers.distinct() // remove duplicates numbers.take(3) // [1, 2, 3] numbers.drop(2) // [3, 4, 5] numbers.groupBy { it % 2 } // {1=[1,3,5], 0=[2,4]} numbers.associate { it to it * it } // {1=1, 2=4, 3=9, ...} numbers.flatMap { listOf(it, it * 10) } // [1,10,2,20,...] Map Operations val map = mapOf("a" to 1, "b" to 2) map["a"] // 1 map.getOrDefault("c", 0) // 0 map.keys // [a, b] map.values // [1, 2] map.entries // [a=1, b=2] map + ("c" to 3) // new map with c added Lambdas val double = { x: Int -> x * 2 } double(5) // 10 // Single parameter uses "it" val numbers = listOf(1, 2, 3) numbers.filter { it > 1 } // Trailing lambda numbers.fold(0) { acc, n -> acc + n } Classes // Data class — equals, hashCode, toString, copy generated data class User(val name: String, val age: Int) val user = User("Alex", 25) val copy = user.copy(age = 26) // Enum class enum class Color { RED, GREEN, BLUE } // Sealed class — restricted hierarchy sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() data object Loading : Result() } // Object — singleton object Database { fun connect() { } } // Companion object — static-like members class MyClass { companion object { fun create(): MyClass = MyClass() } } Extension Functions fun String.addExclamation() = "$this!" "Hello".addExclamation() // "Hello!" fun List<Int>.secondOrNull(): Int? = if (size >= 2) this[1] else null Scope Functions Function Object ref Return Use case let it Lambda result Null checks, transformations run this Lambda result Object config + compute result with this Lambda result Group calls on an object apply this Object itself Object configuration also it Object itself Side effects (logging, validation) // let — execute block if not null val length = name?.let { it.length } // apply — configure a builder/mutable object val paint = Paint().apply { color = Color.RED strokeWidth = 4f } // also — side effects val list = mutableListOf(1, 2).also { println("Before: $it") } // run — compute a result val result = service.run { connect() fetchData() } // with — group calls val info = with(user) { "$name is $age years old" } Coroutines Basics // Launch — fire and forget scope.launch { val data = fetchData() // suspend function updateUi(data) } // Async — returns a Deferred (future) val deferred = async { fetchData() } val result = deferred.await() // Parallel execution coroutineScope { val a = async { fetchA() } val b = async { fetchB() } println("${a.await()} ${b.await()}") } // Switch context withContext(Dispatchers.IO) { // Run on background thread readFile() } // Flow — reactive stream fun numbers(): Flow<Int> = flow { for (i in 1..3) { delay(100) emit(i) } } // collect is a suspend function — must be called inside a coroutine scope.launch { numbers().collect { println(it) } } Dispatcher Use case Dispatchers.Main UI updates Dispatchers.IO Network, database, file I/O Dispatchers.Default CPU-heavy computation Smart Casts // Kotlin auto-casts after a type check — no explicit cast needed fun printLength(x: Any) { if (x is String) { println(x.length) // x is auto-cast to String } } // Works with when too when (result) { is Result.Success -> println(result.data) is Result.Error -> println(result.message) } Value Classes // Wraps a value with zero runtime overhead (no extra object allocation) @JvmInline value class Email(val address: String) val email = Email("alex@example.com") // At runtime, this is just a String — no wrapper object Multi-line Strings val json = """ { "name": "Alex", "age": 25 } """.trimIndent() val sql = """ SELECT * FROM users WHERE age > 18 ORDER BY name """.trimIndent() Common Patterns Safe casting val x: Any = "hello" val s: String? = x as? String // "hello" val i: Int? = x as? Int // null (no crash) Destructuring val (name, age) = User("Alex", 25) val (key, value) = mapEntry takeIf / takeUnless val positiveNumber = number.takeIf { it > 0 } // number or null val nonBlank = name.takeUnless { it.isBlank() } // name or null // Chain with Elvis val port = config.getPort().takeIf { it in 1..65535 } ?: 8080 Lazy initialization val heavy: String by lazy { println("Computed!") "result" } Common Mistakes Mutable vs immutable collections — listOf() returns a read-only List. Use mutableListOf() if you need add() or remove(). Casting a List to MutableList is unsafe. ...

March 16, 2026 · 7 min