Detect non-null reference in an array
I just asked a similar question, but then I realized I actually need something else. Since that question already has two answers, I do not want 开发者_如何学Goto edit my question. So here is what I actually need:
I want to detect whether a subrange of an array contains null references only. Somehow like this:
public static <T> boolean nullReferencesOnly
(T[] array, int fromInclusive, int toExclusive)
{
for (int i = fromInclusive; i < toExclusive; ++i)
{
if (array[i] != null) return false;
}
return true;
}
Is there a method like this in the Java library so I don't have to manually loop over the array?
Collections.frequency(Arrays.asList(array), null) == array.length
For a range, SLaks has already suggested .subList(from, to)
in his answer.
You could use a functional programming library like Guava (http://code.google.com/p/guava-libraries/). You could do something like this:
import com.google.common.base.Predicate;
public class NotNull implements Predicate
{
@Override
public boolean apply(String arg0)
{
return arg0 != null;
}
}
And a test driver to see how it's used:
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Iterables;
public class Driver
{
@Test
public void testNotNull()
{
List l = Arrays.asList(new String[] {null, null, null});
String s = Iterables.find(l, new NotNull(), null);
assertNull(s);
}
@Test
public void testNotNull2()
{
List l = Arrays.asList(new String[] {null, "1", null});
String s = Iterables.find(l, new NotNull(), null);
assertNotNull(s);
}
}
With this, you just call Iterables.find() and see if it can find anything that isn't null. As long as it returns nothing (null), you know that there wasn't anything in the list that wasn't null.
I think that the best solution is to take the code you have already got, change the array type to Object[]
and put the method it into a "helper" class.
- AFAIK, there is no method in the standard Java libraries that does what you want directly.
- AFAIK, there is no method in Apache Commons or Google Collections / Guava that does what you want directly.
- Solutions involving
Collection.contains
will fail because that method is based onequals
and will give an NPE if you test fornull
. - Solutions involving generic
frequency
methods don't short-circuit when they find anull
. - Solutions involving applying
Predicate
objects are expensive, and take more code than your solution.
Your solution is easy to read, and more efficient than any of the proposed alternatives. The fact that it involves an explicit loop should not concern you. After all, this is Java code you are writing ... not a FP language.
Aside - if the problem had been to test for the presence of a null
element (rather than a non-null
element) then one alternative would be org.springframework.util.Assert.noNullElements
.
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/util/Assert.html#noNullElements(java.lang.Object[]))
However, this throws an exception rather than returning true
or false
, and this is likely to make it a poor solution ... unless you were intending to throw an exception anyway.
Well, not exactly efficient, but you could use a Set to help out, like in this example:
String[] test = {null, null, null, null};
Set<String> set = new HashSet<String>(Arrays.asList(test));
System.out.println(set.size() == 0 || (set.size() == 1 && set.contains(null)));
This way, if it is all null, it will only have one element and that one element will be null.
If you need just a range, you could use subList on Arrays.asList(test)
.
Not efficient, but uses classes you can find in core Java library.
Hope this helps.
Using Java 8 (or beyond) is straight forward and uses short-circuiting; meaning it returns immediately as soon as it detects a not null element:
public static boolean hasAtLeastOneElementNotNull(final Object[] array) {
return Arrays.stream(array)
.anyMatch(Objects::nonNull);
}
From the documentation for 'anyMatch':
Returns whether any elements of this stream match the provided predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then false is returned and the predicate is not evaluated. This is a short-circuiting terminal operation.
精彩评论