| name | java-kotlin |
| description | Java and Kotlin programming patterns |
| domain | programming-languages |
| version | 1.0.0 |
| tags | ["java","kotlin","jvm","spring","android"] |
| triggers | {"keywords":{"primary":["java","kotlin","jvm","spring","springboot","gradle","maven"],"secondary":["android","hibernate","jpa","stream","coroutine","quarkus"]},"context_boost":["enterprise","backend","microservice","mobile","android"],"context_penalty":["python","javascript","rust","go"],"priority":"high"} |
Java & Kotlin
Overview
Modern Java and Kotlin patterns for JVM development.
Java Modern Features
Records and Sealed Classes (Java 17+)
public record User(
String id,
String email,
String name,
Instant createdAt
) {
public User {
Objects.requireNonNull(id);
Objects.requireNonNull(email);
if (!email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
}
public static User create(String email, String name) {
return new User(UUID.randomUUID().toString(), email, name, Instant.now());
}
}
public sealed interface Shape
permits Circle, Rectangle, Triangle {
double area();
}
public record Circle(double radius) implements Shape {
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public record Rectangle(double width, double height) implements Shape {
@Override
public double area() {
return width * height;
}
}
public final class Triangle implements Shape {
private final double base;
private final double height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double area() {
return 0.5 * base * height;
}
}
Pattern Matching
public String describe(Object obj) {
if (obj instanceof String s) {
return "String of length " + s.length();
} else if (obj instanceof Integer i) {
return "Integer: " + i;
} else if (obj instanceof List<?> list && !list.isEmpty()) {
return "Non-empty list with " + list.size() + " elements";
}
return "Unknown type";
}
public double calculateArea(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> 0.5 * t.base() * t.height();
};
}
public String classify(Shape shape) {
return switch (shape) {
case Circle c when c.radius() > 10 -> "Large circle";
case Circle c -> "Small circle";
case Rectangle r when r.width() == r.height() -> ;
Rectangle r -> ;
-> ;
};
}
Streams and Optionals
import java.util.stream.*;
import java.util.Optional;
public class StreamExamples {
public List<String> processUsers(List<User> users) {
return users.stream()
.filter(u -> u.active())
.map(User::name)
.sorted()
.distinct()
.collect(Collectors.toList());
}
public Map<String, List<User>> groupByDomain(List<User> users) {
return users.stream()
.collect(Collectors.groupingBy(
u -> u.email().substring(u.email().indexOf("@") + 1)
));
}
public DoubleSummaryStatistics getStats(List<Order> orders) {
return orders.stream()
.mapToDouble(Order::total)
.summaryStatistics();
}
public long countLargeFiles(Path directory) throws IOException {
try (Stream<Path> paths = Files.walk(directory)) {
return paths
.parallel()
.filter(Files::isRegularFile)
.filter(p -> {
try {
return Files.size(p) > 1_000_000;
} catch (IOException e) {
return false;
}
})
.count();
}
}
String {
findUser(userId)
.map(User::email)
.filter(email -> !email.isBlank())
.orElse();
}
User {
findUser(userId)
.orElseGet(() -> createUser(userId));
}
}
Kotlin Fundamentals
Data Classes and Null Safety
data class User(
val id: String = UUID.randomUUID().toString(),
val email: String,
val name: String,
val createdAt: Instant = Instant.now()
) {
init {
require(email.contains("@")) { "Invalid email" }
}
}
fun processUser(user: User?) {
val name = user?.name
val displayName = user?.name ?: "Anonymous"
if (user != null) {
println(user.email)
}
user?.let {
sendEmail(it.email)
}
val email = user!!.email
}
fun handleJavaString(javaString: String?) {
val length = javaString?.length ?: 0
}
Extension Functions and Properties
fun String.toSlug(): String =
this.lowercase()
.replace(Regex("[^a-z0-9]+"), "-")
.trim('-')
val String.wordCount: Int
get() = this.split(Regex("\\s+")).size
fun String?.orEmpty(): String = this ?: ""
val slug = "Hello World".toSlug()
val count = "Hello World".wordCount
data class Config(var host: String = "", var port: Int = 0)
val config = Config().apply {
host = "localhost"
port = 8080
}
val result = user.let { it.name.uppercase() }
val processedUser = user.also { log.info("Processing ${it.id}") }
val transformed = with(user) {
"$name <$email>"
}
Coroutines
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
suspend fun fetchUser(id: String): User {
return withContext(Dispatchers.IO) {
api.getUser(id)
}
}
suspend fun fetchAllUsers(ids: List<String>): List<User> = coroutineScope {
ids.map { id ->
async { fetchUser(id) }
}.awaitAll()
}
suspend fun processOrders(orders: List<Order>) = coroutineScope {
orders.forEach { order ->
launch {
processOrder(order)
}
}
}
suspend fun safeFetch(id: String): Result<User> = runCatching {
fetchUser(id)
}
fun fetchUsers(): Flow<User> = flow {
val users = api.getAllUsers()
users.forEach { user ->
emit(user)
delay(100)
}
}
suspend fun processUserFlow() {
fetchUsers()
.filter { it.active }
.map { it.name }
.catch { e -> emit("Error: ") }
.collect { name ->
println(name)
}
}
: () {
_state = MutableStateFlow<UiState>(UiState.Loading)
state: StateFlow<UiState> = _state.asStateFlow()
{
viewModelScope.launch {
_state.value = UiState.Loading
{
user = fetchUser(id)
_state.value = UiState.Success(user)
} (e: Exception) {
_state.value = UiState.Error(e.message ?: )
}
}
}
}
Sealed Classes and When
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val message: String, val cause: Throwable? = null) : Result<Nothing>()
object Loading : Result<Nothing>()
}
fun <T> handleResult(result: Result<T>): String = when (result) {
is Result.Success -> "Success: ${result.data}"
is Result.Error -> "Error: ${result.message}"
Result.Loading -> "Loading..."
}
sealed interface UiEvent {
data class ShowMessage(val message: String) : UiEvent
data class Navigate(val route: String) : UiEvent
object GoBack : UiEvent
}
fun : String = {
value String && value.isEmpty() ->
value String ->
value && value > ->
value ->
->
}
Functional Patterns
inline fun <T> List<T>.customFilter(predicate: (T) -> Boolean): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (predicate(item)) {
result.add(item)
}
}
return result
}
infix fun <A, B, C> ((B) -> C).compose(other: (A) -> B): (A) -> C = { a ->
this(other(a))
}
val double: (Int) -> Int = { it * 2 }
val addOne: (Int) -> Int = { it + 1 }
val doubleThenAddOne = addOne compose double
println(doubleThenAddOne(3))
fun add(a: Int): (Int) -> Int = { b -> a + b }
val add5 = add(5)
println(add5(3))
fun <T, R> ((T) -> R).memoize(): (T) -> R {
val cache = mutableMapOf<T, R>()
{ key ->
cache.getOrPut(key) { (key) }
}
}
fibonacci: () -> = { n: ->
(n <= ) n.toLong()
fibonacci(n - ) + fibonacci(n - )
}.memoize()
DSL Building
class HtmlBuilder {
private val children = mutableListOf<String>()
fun head(block: HeadBuilder.() -> Unit) {
children.add(HeadBuilder().apply(block).build())
}
fun body(block: BodyBuilder.() -> Unit) {
children.add(BodyBuilder().apply(block).build())
}
fun build() = "<html>${children.joinToString("")}</html>"
}
class BodyBuilder {
private val children = mutableListOf<String>()
fun div(classes: String = "", block: BodyBuilder.() -> Unit = {}) {
children.add("<div class=\"$classes\">${BodyBuilder().apply(block).build()}</div>")
}
fun p(text: String) {
children.add("<p>$text</p>")
}
fun build() = children.joinToString("")
}
fun = HtmlBuilder().apply(block).build()
page = html {
body {
div() {
p()
}
}
}
{
{
println()
block()
}
{
println()
block()
}
{
println()
block()
}
}
{
println()
TestContext().apply(block)
}
test() {
given() { }
whenever() { }
then() { }
}
Related Skills
- [[backend]] - Spring Boot development
- [[mobile]] - Android development
- [[testing]] - JUnit, Kotest