Java String Tricks: replace vs replaceAll, Integer Caching, BigDecimal Precision
This article explains the differences between replace and replaceAll, how Integer caching affects equality checks, why constructing BigDecimal with double can cause precision loss, the nuances of string concatenation, the distinction between isEmpty and isBlank, when to check for null in MyBatis mapper results, and the correct way to use indexOf in Java.
1. replace vs replaceAll – String.replace replaces all literal occurrences, while String.replaceAll treats the first argument as a regular expression and also replaces all matches. replaceFirst replaces only the first occurrence. Example:
<code>String str = "ACDAB$%^&A*Y";
System.out.println(str.replace('A', 'X'));
System.out.println(str.replace("A", "X"));
System.out.println(str.replaceAll("A", "X"));
System.out.println(str.replaceAll("\\*", "XO"));
System.out.println(str.replaceFirst("A", "-"));
</code>2. Integer caching – Integer.valueOf caches values in the range [-128, 127]; therefore a == b is true for values inside this range but may be false outside it. The cache size can be changed with the JVM option -Djava.lang.Integer.IntegerCache.high=128 . Example output shows the difference for 1, 128, -128, and -129.
<code>Integer a = 1; Integer b = 1; System.out.println(a == b); // true
Integer a = 128; Integer b = 128; System.out.println(a == b); // false (unless cache enlarged)
</code>3. BigDecimal precision – Creating a BigDecimal directly from a double introduces binary floating‑point errors (e.g., new BigDecimal(0.1) is not exactly 0.1). Use the String constructor or BigDecimal.valueOf for exact values.
<code>BigDecimal a = new BigDecimal(0.02);
BigDecimal b = new BigDecimal(0.03);
System.out.println(b.subtract(a)); // 0.009999… (unexpected)
BigDecimal a2 = new BigDecimal("0.02");
BigDecimal b2 = new BigDecimal("0.03");
System.out.println(b2.subtract(a2)); // 0.01
BigDecimal a3 = BigDecimal.valueOf(0.02);
BigDecimal b3 = BigDecimal.valueOf(0.03);
System.out.println(b3.subtract(a3)); // 0.01
</code>4. String concatenation – The + operator is compiled to StringBuilder calls since JDK 5, but explicit use of StringBuilder (or StringBuffer when thread‑safety is required) avoids creating many intermediate objects in large concatenations.
<code>String a = "123";
String b = "456";
String c = a + b; // compiled to StringBuilder
StringBuilder sb = new StringBuilder();
sb.append(a).append(b);
System.out.println(sb);
</code>5. isEmpty vs isBlank – StringUtils.isEmpty returns false for a string containing only spaces, while StringUtils.isBlank returns true. This distinction matters when validating user input.
<code>StringUtils.isEmpty(" "); // false
StringUtils.isBlank(" "); // true
</code>6. Mapper list null check – MyBatis’s DefaultResultSetHandler returns an empty list, not null . Therefore, using CollectionUtils.isNotEmpty(list) is sufficient without an explicit null check.
<code>List<User> list = userMapper.query(search);
if (CollectionUtils.isNotEmpty(list)) {
List<Long> ids = list.stream().map(User::getId).collect(Collectors.toList());
}
</code>7. Correct use of indexOf – indexOf returns 0 for a match at the first character; checking > 0 misses such cases. Use >= 0 or contains instead.
<code>String source = "#ABBXXXOOO*pack";
if (source.indexOf("#") >= 0) {
System.out.println("contains success");
}
</code>Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.