1. Underscore in Numeric Literals
You have to write dozen of numbers to present a number of millions, billions and even more. You always must count it again and again to make sure the number is correct. Actually, you could place some underscore inside the number to make it clear, like you use comma in real life.
long noUnderscore = 100000000000l;
long withUnderscore = 100_000_000_000l;
Refer: Underscores in Numeric Literals
2. Pattern.asPredicate
When use java.util.regex.Pattern with Stream API, I feel uncomfortable when I have to create a Matcher, and then use that matcher to test whether my text is matched the pattern.
var validEmails = emails.stream()
.filter(email -> EMAIL_REGEX.matcher(email).find())
.collect(Collectors.toList());
I have no idea why Java make it so complex for such a simple thing. Anyway, Java provides a way to shorten the code and make it more clear. That’s Pattern.asPredicate
var validEmails = emails.stream()
.filter(EMAIL_REGEX.asPredicate())
.collect(Collectors.toList());
Refer: Oracle docs Pattern.html#asPredicate
3. Named RegEx Capturing Group
When I need extract multiple information in texts with single Pattern. I have to use java.util.regex.Matcher#group and I usually pass the index of a capturing group in its pattern. The indexes always confuse me. So, you should place a named group to easily extract it by name, like this:
var p = Pattern.compile(
"^Today is (?<month>\\\\w+) (?<day>\\\\d+), (?<year>\\\\d+)"
);
var m = p.matcher("Today is August 4, 2026");
System.out.println(m.group("month"));
System.out.println(m.group("day"));
System.out.println(m.group("year"));
Refer: Oracle docs Pattern.html#special
4. Arrays.asList
Need to create a List inline. The fastest way is use Arrays.asList
var numbers = Arrays.asList(1, 2, 3);
var singletonList = Arrays.asList("Just me");
Beware: the list is returned is a fixed-size (but mutable) list.
Refer: Oracle docs Collections.html#singleton(T)
5. Collections.singleton*
Do you know an ArrayList, a HashSet or a HashMap instance wastes plenty of memory even when you just need to store a single item. They need an array to store data, and int value to store real size and a HashMap (lol)
If you need a collection to store the single item, you should use:
- Collections.singleton to create a Set
- Collections.singletonList to create a List
- Collections.singletonMap to create a Map
var singletonSet = Collections.singleton(1);
var singletonList = Collections.singletonList(1);
var singletonMap = Collections.singletonMap("version", 1);
It’s a simple but very effective.
Refer: Oracle docs Collections#singleton)
6. Collections.empty*
Stop returning null value as a collection, return an empty collection instead.
public static List<String> getValidEmails(Collection<String> email) {
if (email == null) {
return Collections.emptyList();
}
...
}
We have
- emptyList
- emptyMap
- emptySet
- emptyIterator
And more, use them.
Refer: Oracle docs Collections emptyList)
7. Objects equality check
String gameA = "The Legend of Zelda: Breath of the Wild";
String gameB = "Monster Hunter Rise";
System.out.println(gameA.equals(gameB));
Am I seriously? Why don’t I use equals method to solve a simple thing. Well, what happened if either gameA or gameB is null? I would get an NullPointerException if I have a bad luck.
String gameA = null;
String gameB = "Monster Hunter Rise";
System.out.println(gameA.equals(gameB));
// => Exception in thread "main" java.lang.NullPointerException
I can avoid it by using Objects.equals, it does work no matter either gameA or gameB is null.
String gameA = null;
String gameB = "Monster Hunter Rise";
System.out.println(Objects.equals(gameA, gameB));
Refer: Oracle docs Objects
8. List.of, Set.of and Map.of (since 9)
Do you prefer Functional Programming, and love immutable objects? Creating a immutable collection class by yourself could be challenging. Well, Java provides Unmodifiable Lists, Unmodifiable Sets, Unmodifiable Maps which basically are immutable classes.
For example, Unmodifiable Lists have some characteristics:
- They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List's contents to appear to change.
- They disallow null elements. Attempts to create them with null elements result in NullPointerException.
- They are serializable if all elements are serializable.
- The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
- They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.
- They are serialized as specified on the Serialized Form page.
Refer: Oracle docs List unmodifiable
To create an unmodifiable lists, use can use List.of
static List of()
static List of(E e1)
static List of(E… elements)
static List of(E e1, E e2)
static List of(E e1, E e2, E e3)
…
It sounds like Arrays.asList, but instead of a mutable list, List.of creates an immutable list and it doesn’t accept null values.
9. Comparator and null
In the past, I didn’t noticed that Comparator don’t work with null value by default.
For example, the code will throw a NullPointerException
var list = Arrays.asList(1, null, -1, null, 2);
list.sort(Comparator.naturalOrder());
// ==> Exception in thread "main" java.lang.NullPointerException
I used to code like this
var list = Arrays.asList(1, null, -1, null, 2);
list.sort((a, b) -> {
if (a == null) {
return b == null ? 0 : -1;
}
if (b == null) {
return a == null ? 0 : 1;
}
return a.compareTo(b);
});
Luckily, there are two simple methods resolve my problem. They are Comparator.nullsFirst and Comparator.nullsLast
var list = Arrays.asList(1, null, -1, null, 2);
list.sort(Comparator.nullsFirst(Comparator.naturalOrder()));
// [null, null, -1, 1, 2]
10. Predicate::not (since 11)
Stream API is good, filter is great and Predicate is awesome, but have you ever written something like that:
games.stream()
.filter(game -> !Strings.isNullOrEmpty(game))
.collect(Collectors.toList());
Fortunately, Java 11 save you from that ugly code by Predicate.not
games.stream()
.filter(Predicate.not(Strings::isNullOrEmpty))
.collect(Collectors.toList());