Tips & Tricks
A collection of tips and best practices for writing clean, efficient, and easy-to-maintain Java code. These tips cover performance, readability, security, and everyday productivity.
String formatting with String.format() or text blocks is neater than concatenation. Effectively final (Java 8+) allows non-final local variables to be used in a lambda. Method references (::) are shorthand for simple lambdas. Optional (Java 8+) avoids NullPointerException in an elegant way.
Var (Java 10+) enables type inference for local variables. Switch expressions are safer and more compact than switch statements. Records replace boilerplate POJOs. The Streams API enables functional, parallel data processing pipelines.
Productivity Tips:
| Tip | Example |
|---|---|
Use var to cut excessive verbosity |
var list = new ArrayList<String>() |
| Method reference instead of a lambda | list.forEach(System.out::println) |
| Optional for null safety | Optional.ofNullable(obj).orElse(default) |
| Text blocks for multi-line strings | """Hello\nWorld""" |
| Switch expression without fall-through | case "a" -> result = 1; |
| Records for data classes | record Point(int x, int y) {} |
Code Example
import java.util.*;
import java.util.stream.*;
public class TipsDanTrik {
public static void main(String[] args) {
// 1. var (type inference)
var name = "Java"; // String
var numbers = List.of(1, 2, 3); // List<Integer>
var mapa = Map.of("a", 1); // Map<String, Integer>
// 2. Method references
List.of("b", "a", "c").stream()
.sorted()
.forEach(System.out::println);
// 3. Optional for null safety
String input = null;
String result = Optional.ofNullable(input)
.filter(s -> !s.isBlank())
.orElse("Default Value");
System.out.println("Result: " + result);
// 4. Stream pipeline
List<Integer> numbersList = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int evenCount = numbersList.stream()
.filter(a -> a % 2 == 0)
.mapToInt(Integer::intValue)
.sum();
System.out.println("Even count: " + evenCount);
// 5. Collect to Map
Map<String, Integer> wordLengths = List.of("hello", "world", "java")
.stream()
.collect(Collectors.toMap(
s -> s,
String::length
));
System.out.println("Length: " + wordLengths);
// 6. Pattern matching instanceof
Object obj = 42;
if (obj instanceof Integer i && i > 0) {
System.out.println("Integer positif: " + i);
}
// 7. Effectively final for lambda
String prefix = "DEBUG: "; // effectively final
List.of("a", "b").forEach(s ->
System.out.println(prefix + s));
}
}
Code Explanation
- var: reduces verbosity without sacrificing type safety — the compiler determines the type from the expression on the right-hand side.
- Method reference:
System.out::printlnis equivalent tox -> System.out.println(x)— more compact for lambdas that only call a single method. - Optional: avoids repetitive
if (x != null)checks.ofNullable()for input that may be null,filter()for validation,orElse()for a default value. - Stream: the
filter → map → collectpipeline processes data functionally. It can be parallelized with.parallel(). - Effectively final: the
prefixvariable does not need to be declaredfinal— as long as its value is not changed after declaration, it can be used in a lambda.
Everyday Example
A collection of frequently used utility methods:
import java.util.*;
import java.util.stream.*;
public class JavaUtils {
// Check whether a string is empty/null
static boolean isBlank(String s) {
return s == null || s.isBlank();
}
// Format a name: "john smith" → "John Smith"
static String titleCase(String name) {
return Arrays.stream(name.split("\\s+"))
.map(w -> Character.toUpperCase(w.charAt(0)) + w.substring(1).toLowerCase())
.collect(Collectors.joining(" "));
}
// Group a list by a classifier
static <T, K> Map<K, List<T>> groupBy(List<T> list, java.util.function.Function<T, K> fn) {
return list.stream().collect(Collectors.groupingBy(fn));
}
// Retry mechanism
static <T> T retry(int maxAttempt, java.util.concurrent.Callable<T> action) throws Exception {
for (int i = 0; i < maxAttempt; i++) {
try {
return action.call();
} catch (Exception e) {
if (i == maxAttempt - 1) throw e;
Thread.sleep(1000L * (i + 1));
}
}
throw new RuntimeException("Unreachable");
}
public static void main(String[] args) {
System.out.println(titleCase("john smith")); // John Smith
var fruits = List.of("apel", "mangga", "jeruk", "pisang", "mangga");
var grouped = groupBy(fruits, String::length);
System.out.println("By length: " + grouped);
}
}
Summary
Modern Java is far more concise and expressive than older Java versions. Take advantage of var, method references, Optional, Records, and Streams for cleaner code. Always use the latest LTS (Java 21) to get all the latest features. Practice makes perfect — keep refactoring your old code with the new features!