There's a key difference between a null array and an empty array. This is a test for null.
int arr[] = null;
if (arr == null) {
System.out.println("array is null");
}
"Empty" here has no official meaning. I'm choosing to define empty as having 0 elements:
arr = new int[0];
if (arr.length == 0) {
System.out.println("array is empty");
}
An alternative definition of "empty" is if all the elements are null:
Object arr[] = new Object[10];
boolean empty = true;
for (int i=0; i<arr.length; i++) {
if (arr[i] != null) {
empty = false;
break;
}
}
or
Object arr[] = new Object[10];
boolean empty = true;
for (Object ob : arr) {
if (ob != null) {
empty = false;
break;
}
}
Answer from cletus on Stack OverflowThere's a key difference between a null array and an empty array. This is a test for null.
int arr[] = null;
if (arr == null) {
System.out.println("array is null");
}
"Empty" here has no official meaning. I'm choosing to define empty as having 0 elements:
arr = new int[0];
if (arr.length == 0) {
System.out.println("array is empty");
}
An alternative definition of "empty" is if all the elements are null:
Object arr[] = new Object[10];
boolean empty = true;
for (int i=0; i<arr.length; i++) {
if (arr[i] != null) {
empty = false;
break;
}
}
or
Object arr[] = new Object[10];
boolean empty = true;
for (Object ob : arr) {
if (ob != null) {
empty = false;
break;
}
}
ArrayUtils.isNotEmpty(testArrayName) from the package org.apache.commons.lang3 ensures Array is not null or empty
They're two completely different things. == compares the object reference, if any, contained by a variable. .equals() checks to see if two objects are equal according to their contract for what equality means. It's entirely possible for two distinct object instances to be "equal" according to their contract. And then there's the minor detail that since equals is a method, if you try to invoke it on a null reference, you'll get a NullPointerException.
For instance:
class Foo {
private int data;
Foo(int d) {
this.data = d;
}
@Override
public boolean equals(Object other) {
if (other == null || other.getClass() != this.getClass()) {
return false;
}
return ((Foo)other).data == this.data;
}
/* In a real class, you'd override `hashCode` here as well */
}
Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances
System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition
Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it
System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything
System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null
In addition to the accepted answer (https://stackoverflow.com/a/4501084/6276704):
Since Java 1.7, if you want to compare two Objects which might be null, I recommend this function:
Objects.equals(onePossibleNull, twoPossibleNull)
java.util.Objects
This class consists of static utility methods for operating on objects. These utilities include null-safe or null-tolerant methods for computing the hash code of an object, returning a string for an object, and comparing two objects.
Since: 1.7
When I type
string1 == string2
IntelliJ tells me to switch to equals(), which it says is null-safe.
But is == operator not null-safe?
I tried null == "abc", "abc" == null, null == null, but they consistently gave me right false false true.
What am I missing here?
array1.equals(array2) is the same as array1 == array2, i.e. is it the same array. As @alf points out it's not what most people expect.
Arrays.equals(array1, array2) compares the contents of the arrays.
Similarly array.toString() may not be very useful and you need to use Arrays.toString(array).
It's an infamous problem: .equals() for arrays is badly broken, just don't use it, ever.
That said, it's not "broken" as in "someone has done it in a really wrong way" — it's just doing what's defined and not what's usually expected. So for purists: it's perfectly fine, and that also means, don't use it, ever.
Now the expected behaviour for equals is to compare data. The default behaviour is to compare the identity, as Object does not have any data (for purists: yes it has, but it's not the point); assumption is, if you need equals in subclasses, you'll implement it. In arrays, there's no implementation for you, so you're not supposed to use it.
So the difference is, Arrays.equals(array1, array2) works as you would expect (i.e. compares content), array1.equals(array2) falls back to Object.equals implementation, which in turn compares identity, and thus better replaced by == (for purists: yes I know about null).
Problem is, even Arrays.equals(array1, array2) will bite you hard if elements of array do not implement equals properly. It's a very naive statement, I know, but there's a very important less-than-obvious case: consider a 2D array.
2D array in Java is an array of arrays, and arrays' equals is broken (or useless if you prefer), so Arrays.equals(array1, array2) will not work as you expect on 2D arrays.
public class ArraySet<T> {
private T[] items;
private int size;
public ArraySet() {
items = (T[]) new Object[100];
size = 0;
}
public void add(T value) {
for (int i = 0; i < size; i++) {
if (items[i] == value) {
return;
}
}
items[size + 1] = value;
size ++;
}
public boolean contains(T x) {
for (int i = 0; i < size; i++) {
if (items[i].equals(x)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
ArraySet<String> s = new ArraySet<>();
// test add function
s.add("horse");
System.out.println(s.size);
s.add("fish");
System.out.println(s.size);
// test contains function
System.out.println(s.contains("horse"));
}
}I self create an Arrayset class to store strings with add function and contains function, but the contains function goes wrong. I try to modify my add function but it doesn't works.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.equals(Object)" because "this.items[i]" is null
No you can't remove an element from an array, as in making it shorter. Java arrays are fixed-size. You need to use an ArrayList for that.
If you set an element to null, the array will still have the same size, but with a null reference at that point.
// Let's say a = [0,1,2,3,4] (Integer[])
a[2] = null;
// Now a = [0,1,null,3,4]
Yes, you can set elements in an array to null, but code like a[i].equals(a[i+1]) will fail with a NullPointerException if the array contains nulls, so you just have to be more careful if you know that your array may contain nulls. It also doesn't change the size of the array so you will be wasting memory if you remove large numbers of elements. Fixed size arrays are generally not a good way to store data if you are often adding and removing elements - as you can guess from their name.
No.
An ArrayList can be empty (or with nulls as items) an not be null. It would be considered empty. You can check for am empty ArrayList with:
ArrayList arrList = new ArrayList();
if(arrList.isEmpty())
{
// Do something with the empty list here.
}
Or if you want to create a method that checks for an ArrayList with only nulls:
public static Boolean ContainsAllNulls(ArrayList arrList)
{
if(arrList != null)
{
for(object a : arrList)
if(a != null) return false;
}
return true;
}
arrayList == null if there are no instance of the class ArrayList assigned to the variable arrayList (note the upercase for classes and the lowercase for variables).
If, at anytime, you do arrayList = new ArrayList() then arrayList != null because is pointing to an instance of the class ArrayList
If you want to know if the list is empty, do
if(arrayList != null && !arrayList.isEmpty()) {
//has items here. The fact that has items does not mean that the items are != null.
//You have to check the nullity for every item
}
else {
// either there is no instance of ArrayList in arrayList or the list is empty.
}
If you don't want null items in your list, I'd suggest you to extend the ArrayList class with your own, for example:
public class NotNullArrayList extends ArrayList{
@Override
public boolean add(Object o)
{ if(o==null) throw new IllegalArgumentException("Cannot add null items to the list");
else return super.add(o);
}
}
Or maybe you can extend it to have a method inside your own class that re-defines the concept of "empty List".
public class NullIsEmptyArrayList extends ArrayList{
@Override
public boolean isEmpty()
if(super.isEmpty()) return true;
else{
//Iterate through the items to see if all of them are null.
//You can use any of the algorithms in the other responses. Return true if all are null, false otherwise.
//You can short-circuit to return false when you find the first item not null, so it will improve performance.
}
}
The last two approaches are more Object-Oriented, more elegant and reusable solutions.
Updated with Jeff suggestion IAE instead of NPE.
I generally use a static utility function that I wrote called equalsWithNulls to solve this issue:
Copyclass MyUtils {
public static final boolean equalsWithNulls(Object a, Object b) {
if (a==b) return true;
if ((a==null)||(b==null)) return false;
return a.equals(b);
}
}
Usage:
Copyif (MyUtils.equalsWithNulls(s1,s2)) {
// do stuff
}
Advantages of this approach:
- Wraps up the complexity of the full equality test in a single function call. I think this is much better than embedding a bunch of complex boolean tests in your code each time you do this. It's much less likely to lead to errors as a result.
- Makes your code more descriptive and hence easier to read.
- By explicitly mentioning the nulls in the method name, you convey to the reader that they should remember that one or both of the arguments might be null.
- Does the (a==b) test first (an optimisation which avoids the need to call a.equals(b) in the fairly common case that a and b are non-null but refer to exactly the same object)
You will need to check atleast one is not null before doing equals method -
Copyif(s1 == s2 || (s1!=null && s1.equals(s2))) {
System.out.println("WORKING :)");
}
here s1==s2 will work incase of null==null . But if even one is not null, then you need to check atleast s1 before doing equals.
Update: As edited by @'bernard paulus', if you are using Java 7, you can use java.util.Objects.equals(Object, Object)