Careeroza
String and Collection Performance
Strings
- Use
StringBuilderwhen concatenating in a loop. A singlea + b + cexpression is fine — the compiler optimizes it (invokedynamicstring concat since Java 9). - Use
String.join/Collectors.joiningfor lists. - Precompile regexes:
private static final Pattern EMAIL = Pattern.compile(...);String.matchescompiles every call. - Use
equalsfor comparison, never==.
Example
import java.util.*;
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(64); // pre-size if you know roughly the length
for (int i = 1; i <= 5; i++) sb.append("item").append(i).append(i < 5 ? "," : "");
System.out.println(sb);
System.out.println(String.join(" | ", List.of("Home", "Electronics", "Mobiles")));
String a = "hello", b = new String("hello");
System.out.println("== : " + (a == b) + ", equals: " + a.equals(b) + ", intern ==: " + (a == b.intern()));
}
}Output
item1,item2,item3,item4,item5 Home | Electronics | Mobiles == : false, equals: true, intern ==: true
Choosing Collections
| Need | Best choice | Avoid |
|---|---|---|
| Index access, append | ArrayList (pre-size with new ArrayList<>(n)) | LinkedList (slow get(i), poor cache use) |
| Queue / stack | ArrayDeque | Stack, LinkedList |
| Fast lookup by key | HashMap (pre-size for big maps) | searching a list |
| Sorted keys / ranges | TreeMap (floorKey, subMap) | sorting a list every time |
| Enum keys | EnumMap, EnumSet | HashMap with enum keys |
| Many ints | int[], IntStream | List<Integer> in hot code (boxing) |
Boxing Pitfalls
Example
Integer caches only -128..127, so == works "sometimes". Unboxing a null throws NPE.
import java.util.*;
public class Main {
public static void main(String[] args) {
Integer a = 127, b = 127, c = 128, d = 128;
System.out.println("127 == 127: " + (a == b));
System.out.println("128 == 128: " + (c == d));
System.out.println("128 equals: " + c.equals(d));
Long sum = 0L; // boxed accumulator: creates a new Long on every +=
for (long i = 0; i < 1000; i++) sum += i;
long fast = 0; // primitive: no allocation
for (long i = 0; i < 1000; i++) fast += i;
System.out.println(sum + " " + fast);
Map<String, Integer> stock = new HashMap<>();
try {
int qty = stock.get("missing"); // auto-unboxing null
} catch (NullPointerException e) {
System.out.println("NPE from unboxing null; use getOrDefault: " + stock.getOrDefault("missing", 0));
}
}
}Output
127 == 127: true 128 == 128: false 128 equals: true 499500 499500 NPE from unboxing null; use getOrDefault: 0