
How to do it...
The int compare(T a, T b, Comparator<T> c) method uses the provided comparator for comparing the two objects:
- Returns 0 when the objects are equal
- Returns a negative number when the first object is smaller than the second one
- Returns a positive number otherwise
The non-zero return value of the int compare(T a, T b, Comparator<T> c) method depends on the implementation. In the case of String, smaller and bigger are defined according to their ordering position (smaller is placed in front of bigger in the ordered list), and the returned value is the difference between the positions of the first and the second parameter in the list, ordered according to the provided comparator:
int res =
Objects.compare("a", "c", Comparator.naturalOrder());
System.out.println(res); //prints: -2
res = Objects.compare("a", "a", Comparator.naturalOrder());
System.out.println(res); //prints: 0
res = Objects.compare("c", "a", Comparator.naturalOrder());
System.out.println(res); //prints: 2
res = Objects.compare("c", "a", Comparator.reverseOrder());
System.out.println(res); //prints: -2
The Integer values, on the other hand, return just -1 or 1 when the values are not equal:
res = Objects.compare(3, 5, Comparator.naturalOrder());
System.out.println(res); //prints: -1
res = Objects.compare(3, 3, Comparator.naturalOrder());
System.out.println(res); //prints: 0
res = Objects.compare(5, 3, Comparator.naturalOrder());
System.out.println(res); //prints: 1
res = Objects.compare(5, 3, Comparator.reverseOrder());
System.out.println(res); //prints: -1
res = Objects.compare("5", "3", Comparator.reverseOrder());
System.out.println(res); //prints: -2
Please notice how, in the last line in the preceding code block, the result changes when we compare numbers as String literals.
When both objects are null, the compare() method considers them equal:
res = Objects.compare(null,null,Comparator.naturalOrder());
System.out.println(res); //prints: 0
But it throws NullPointerException when only one of the objects is null:
//Objects.compare(null, "c", Comparator.naturalOrder());
//Objects.compare("a", null, Comparator.naturalOrder());
If you need to compare an object with null, you are better off using org.apache.commons.lang3.ObjectUtils.compare(T o1, T o2).
- The toString(Object obj) method is helpful when an obj object reference is the null value:
- String toString(Object obj): Returns the result of calling toString() on the first parameter when it is not null and null when the first parameter value is null
- String toString(Object obj, String nullDefault): Returns the result of calling toString() on the first parameter when it is not null and the second parameter value, nullDefault, when the first parameter value is null
The usage of the toString(Object obj) method is straightforward:
System.out.println(Objects.toString("a")); //prints: a
System.out.println(Objects.toString(null)); //prints: null
System.out.println(Objects.toString("a", "b")); //prints: a
System.out.println(Objects.toString(null, "b"));//prints: b
- The checkIndex() overloaded method checks whether the index and the length of a collection or an array are compatible:
- int checkIndex(int index, int length): Throws IndexOutOfBoundsException if the provided index is bigger than length - 1, for example:
List<Integer> list = List.of(1, 2);
try {
Objects.checkIndex(3, list.size());
} catch (IndexOutOfBoundsException ex){
System.out.println(ex.getMessage());
//prints: Index 3 out-of-bounds for length 2
}
-
- int checkFromIndexSize(int fromIndex, int size, int length): Throws IndexOutOfBoundsException if the provided index + size is bigger than length - 1, for example:
List<Integer> list = List.of(1, 2);
try {
Objects.checkFromIndexSize(1, 3, list.size());
} catch (IndexOutOfBoundsException ex){
System.out.println(ex.getMessage());
//prints:Range [1, 1 + 3) out-of-bounds for length 2
}
-
- int checkFromToIndex(int fromIndex, int toIndex, int length): Throws IndexOutOfBoundsException if the provided fromIndex is bigger than toIndex, or toIndex is bigger than length - 1, for example:
List<Integer> list = List.of(1, 2);
try {
Objects.checkFromToIndex(1, 3, list.size());
} catch (IndexOutOfBoundsException ex){
System.out.println(ex.getMessage());
//prints:Range [1, 3) out-of-bounds for length 2
}
- The five methods of the requireNonNull() group check the value of the first parameter, obj. If the value is null, they either throw NullPointerException or return the provided default value:
- T requireNonNull(T obj): Throws NullPointerException without a message if the parameter is null, for example:
String obj = null;
try {
Objects.requireNonNull(obj);
} catch (NullPointerException ex){
System.out.println(ex.getMessage());//prints: null
}
-
- T requireNonNull(T obj, String message): Throws NullPointerException with the provided message if the first parameter is null, for example:
String obj = null;
try {
Objects.requireNonNull(obj,
"Parameter 'obj' is null");
} catch (NullPointerException ex){
System.out.println(ex.getMessage());
//prints: Parameter 'obj' is null
}
-
- T requireNonNull(T obj, Supplier<String> messageSupplier): If the first parameter is null, returns the message generated the provided function or, if the generated message or the function itself is null, throws NullPointerException, for example:
String obj = null;
Supplier<String> supplier = () -> "Message";
try {
Objects.requireNonNull(obj, supplier);
} catch (NullPointerException ex){
System.out.println(ex.getMessage());
//prints: Message
}
-
- T requireNonNullElse(T obj, T defaultObj): Returns the first parameter (if it is non-null), the second parameter (if it is non-null), throws NullPointerException (if both parameters is null), for example:
String object = null;
System.out.println(Objects
.requireNonNullElse(obj, "Default value"));
//prints: Default value
-
- T requireNonNullElseGet(T obj, Supplier<T> supplier): Returns the first parameter (if it is non-null), the object produced by the provided supplier function (if it is non-null and supplier.get() is non-null), throws NullPointerException (if both parameters are null or the first parameter and supplier.get() are null), for example:
Integer obj = null;
Supplier<Integer> supplier = () -> 42;
try {
System.out.println(Objects
.requireNonNullElseGet(obj, supplier));
} catch (NullPointerException ex){
System.out.println(ex.getMessage()); //prints: 42
}
- The hash() or hashCode() method is typically used to override the default hashCode() implementation:
- int hashCode(Object value): Calculates a hash value for a single object, for example:
System.out.println(Objects.hashCode(null));
//prints: 0
System.out.println(Objects.hashCode("abc"));
//prints: 96354
- int hash(Object... values): Calculates a hash value for an array of objects, for example:
System.out.println(Objects.hash(null)); //prints: 0
System.out.println(Objects.hash("abc"));
//prints: 96385
String[] arr = {"abc"};
System.out.println(Objects.hash(arr));
//prints: 96385
Object[] objs = {"a", 42, "c"};
System.out.println(Objects.hash(objs));
//prints: 124409
System.out.println(Objects.hash("a", 42, "c"));
//prints: 124409
Please note that the hashCode(Object value) method returns a different hash value (96354) than the Objects.hash(Object... values) method (96385), even though they calculate the hash value for the same single object.
- The isNull() and nonNull() methods are just wrappers around Boolean expressions:
- boolean isNull(Object obj): Returns the same value as obj == null, for example:
String obj = null;
System.out.println(obj == null); //prints: true
System.out.println(Objects.isNull(obj));
//prints: true
obj = "";
System.out.println(obj == null); //prints: false
System.out.println(Objects.isNull(obj));
//prints: false
-
- boolean nonNull(Object obj): Returns the same value as obj != null, for example:
String obj = null;
System.out.println(obj != null); //prints: false
System.out.println(Objects.nonNull(obj));
//prints: false
obj = "";
System.out.println(obj != null); //prints: true
System.out.println(Objects.nonNull(obj));
//prints: true
- The equals() and deepEquals() methods allow us to compare two objects by their state:
- boolean equals(Object a, Object b): Compares two objects using the equals(Object) method and handles the case when one of them or both are null, for example:
String o1 = "o";
String o2 = "o";
System.out.println(Objects.equals(o1, o2));
//prints: true
System.out.println(Objects.equals(null, null));
//prints: true
Integer[] ints1 = {1,2,3};
Integer[] ints2 = {1,2,3};
System.out.println(Objects.equals(ints1, ints2));
//prints: false
In the preceding example, Objects.equals(ints1, ints2) returns false because arrays cannot override the equals() method of the Object class and are compared by references, not by value.
-
- boolean deepEquals(Object a, Object b): Compares two arrays by the value of their elements, for example:
String o1 = "o";
String o2 = "o";
System.out.println(Objects.deepEquals(o1, o2));
//prints: true
System.out.println(Objects.deepEquals(null, null));
//prints: true
Integer[] ints1 = {1,2,3};
Integer[] ints2 = {1,2,3};
System.out.println(Objects.deepEquals(ints1,ints2));
//prints: true
Integer[][] iints1 = {{1,2,3},{1,2,3}};
Integer[][] iints2 = {{1,2,3},{1,2,3}};
System.out.println(Objects.
deepEquals(iints1, iints2)); //prints: true
As you can see, the deepEquals() method returns true when the corresponding values of the arrays are equal. But if the arrays have different values or a different order of the same values, the method returns false:
Integer[][] iints1 = {{1,2,3},{1,2,3}};
Integer[][] iints2 = {{1,2,3},{1,3,2}};
System.out.println(Objects.
deepEquals(iints1, iints2)); //prints: false