I have an array
of boolean
entries:
boolean[] myBooleanArray = new boolean[24];
Currently i check if it contains
Just iterate through array
for(boolean value: myBooleanArray){
if(value){ return true;}
}
return false;
According to this previous question iterating over an array is mostly the same using enhanced for or normal for because both use array accesses . So just iterate over your array:
public boolean containsTrue(boolean[] array){
for(boolean val : array){
if(val)
return true;
}
return false;
}
If you are using the Guava library (which has a lot of useful stuff):
Booleans.contains(myBooleanArray, true);
(JavaDoc)
The documentation of this method also describes another way. You can replace a boolean[]
with a BitSet
(should be more memory efficient) and call !bitSet.isEmpty()
to check whether at least one bit is true.
Generally speaking, if you have an array (or List
) of anything, the fastest/onlyest way to look for an item in it is to iterate over the array until you find what you're looking for. That's one of the limitations of arrays/List
s.
For an array of 24 elements, I wouldn't worry about this anyway. If you had millions of items and expected very few true
s (or possibly none), then it could make sense to encapsulate the data in a class:
public class BooleanArray
{
boolean[] arr = new boolean[SIZE]; // or get size from a constructor
boolean anyTrue = false;
boolean get(int index) {
return arr[index];
}
boolean set(int index, boolean value) {
arr[index] = value;
anyTrue |= value;
}
boolean containsAnyTrues() {
return anyTrue;
}
}
To reiterate, I don't suggest this for your array of 24 elements. I mean it more of an example that your data structure should support the expected use case. If the expected use case is "lots of elements, very sparse true
s, need to find out if there are any true
s" then your concern for the fastest way is more relevant, and a data structure like the one above would be useful.
If you are not bound to an Array of boolean, you should give a look to the class java.util.BitSet. Despite the name, it is more array-like than set-like.
The method BitSet.isEmpty is answering your question if there is any true
in the "Array", and it is implemented as:
public boolean isEmpty()
{
return wordsInUse == 0;
}
I doubt that you can get a faster check …
But the price has to be paid elsewhere: setting/unsetting a value might be more expensive as for a mere boolean []
.
If you know the size of the array, and the array is large. Eg. 24 is pretty small so it would be hard to improve. Arrays.mismatch seems to be a bit quicker.
import java.util.Arrays;
import java.util.Random;
public class BenchMark{
final static int N = Short.MAX_VALUE;
static boolean[] base = new boolean[N];
static boolean any1(boolean[] test){
return Arrays.mismatch(base, test)==-1;
}
static boolean any2(boolean[] test){
for(boolean b: test)
if(b) return true;
return false;
}
public static void main(String[] args){
boolean[] test = new boolean[N];
Random r = new Random(1);
int last = 0;
long start = System.nanoTime();
int p = 0;
for(int i = 0; i<100000; i++){
test[last] = false;
int s = r.nextInt(2);
if(s == 0){
last = r.nextInt(test.length);
test[last] = true;
}
if(any2(test)){
p++;
}
}
System.out.println( ( p + " in " + (System.nanoTime() - start ) / 1e9 ) + " seconds");
}
}
I didn't setup a proper benchmark, but the output from this shows any1
to be about 4-5 times faster than any2
, the standard loop technique.
To understand why, looking in the jdk source code. We find vectorizedMismatch which appears to be using the unsafe class to cast the values to a long and comparing the long values.