Using indexOf() To Find Values In An Array

Following my post yesterday on Comparing List And Array Speeds, Andy Matthews suggested I use hidden Java methods to perform an array search, as outlined in this Coldfused? post. Intrigued, I decided to put this new-found method in the pit with my other tests.

Using indexOf() to search through an array

I took out my test code and left only the initialization and original list and array "Find a random value" tests. I then added this bit of code in-between:

<cfloop list="#lengths#" index="length">

    <cftimer type="debug" label="#length# Elements - Find 100 Elements From Array with indexOf()">
        <cfloop from="1" to="100" index="i">
            <cfset result=variables[ "testArray" & length ].indexOf( rand() ) />
        </cfloop>
    </cftimer>

</cfloop>

Most of this is the same than yesterday's tests. However, our approach for finding the value is much different. All we need to do now is use the array's built-in (but hidden!) indexOf() method with the value we're looking for. Much faster to code and much easier to read through than the standard "loop and find" approach. However, does it compare where it really counts?

[30ms] 100 Elements - Find 100 Elements From Array
[601ms] 1000 Elements - Find 100 Elements From Array
[2302ms] 10000 Elements - Find 100 Elements From Array
[10650ms] 50000 Elements - Find 100 Elements From Array

[10ms] 100 Elements - Find 100 Elements From List
[30ms] 1000 Elements - Find 100 Elements From List
[300ms] 10000 Elements - Find 100 Elements From List
[1502ms] 50000 Elements - Find 100 Elements From List

[10ms] 100 Elements - Find 100 Elements From Array with indexOf()
[0ms] 1000 Elements - Find 100 Elements From Array with indexOf()
[0ms] 10000 Elements - Find 100 Elements From Array with indexOf()
[50ms] 50000 Elements - Find 100 Elements From Array with indexOf()

We can see that listFind() is still much faster than looping over an array. However, it doesn't come close to the speed of indexOf()! My dev environment doesn't let me go over 50k elements, but it almost seems like indexOf() isn't even affected by the size of the variable.

In light of this, a new conclusion is reached

It turns out array's are much better than I had originally thought. I used to shy away from them. I didn't like that they had to have a sequential, numeric index. They used to be so much longer to write than lists, too. With Coldfusion 8's new inline array declaration, however, and knowing now that using listToArray() has very little speed impact, I think I'll be seeing much more array usage in my code from now on.

Related Blog Entries

TweetBacks
There are no TweetBacks for this entry.
Comments
marc esher's Gravatar indexOf works great for strings, but I hit problems with arrays of ints, at least on pre-cf8. I tried all manner of javacasting, but the behavior was flaky and depended on the source of the int. for example, if it was simply a[1] = 5, it'd work fine. but if it were using an index from a loop, it didn't.

I only mention this as something to be aware of.
# Posted By marc esher | 8/28/08 8:59 AM
Francois Levesque's Gravatar @Marc,

That's odd... I'm using rand(), so I'm populating my array with floats, but I'd guess it would be the same as integers.

I did forget to mention these tests were run on CF8, though, so that might have something to do with it ;).

Thanks for the input, I might run some more tests later to see if integers have any impact.
# Posted By Francois Levesque | 8/28/08 9:17 AM
marc esher's Gravatar Francois, I whipped this up real quick to demonstrate. This is on CF8:

<cfset a_stuff = ArrayNew(1)>
<cfset a_stuff[1] = "marc">
<cfset a_stuff[2] = "larry">
<cfset a_stuff[3] = "tom">

<cfset a_ints = ArrayNew(1)>
<cfset a_castedints = ArrayNew(1)>
<cfloop from="1" to="10" index="i">
   <cfset arrayAppend(a_ints,i)>
   <cfset arrayAppend(a_castedints,javacast("int",i))>
</cfloop>

<cfset a_rawints = ArrayNew(1)>
<cfset a_rawints[1] = 1>

<cfoutput>
indexOfString: #a_stuff.indexOf("tom")#
<br>
indexOfIntsFromLoop: #a_ints.indexOf(3)#
<br>
indexOfCastedIntsFromLoop: #a_castedints.indexOf(3)#
<br>
indexOfRawInts: #a_rawints.indexOf(1)#
</cfoutput>

You'd expect that the call to a_ints.indexOf(3) would return "2" since the 3rd element in the array is clearly 3. But instead, it returns -1. Same with the castedints array. I tried it with java.lang.Integer, too, but got the same result.

for me, this means "objects are fine, primitives are iffy".

I wonder what Arrays.binarySearch() would turn up.
# Posted By marc esher | 8/28/08 9:58 AM
Justice's Gravatar I blogged about this a while back, and one thing to note is that indexOf is case sensitive, so be sure to match case if the results are not what you expect! =)
# Posted By Justice | 8/28/08 9:58 AM
Francois Levesque's Gravatar @Marc,

That's odd. I tried your test and ran into the same issues. However I tried this:

<cfset a_castedints = ArrayNew(1)>
<cfloop from="1" to="10" index="i">
<cfset arrayAppend(a_castedints,javacast("int",i))>
</cfloop>

<cfoutput>
indexOfCastedIntsFromLoop: #a_castedints.indexOf(javacast("int", 3))#
</cfoutput>

And got it to work as expected... maybe the underlying java method is a little pickier than I thought as to variable casting. Removing the javacast call in the initialization also didn't work.

@Justice,

I remember reading that in the Coldfused? post, but forgot to mention it :P. Thanks!
# Posted By Francois Levesque | 8/28/08 10:38 AM
marc esher's Gravatar that's awesome, because i tried that too and still got -1. nice!
# Posted By marc esher | 8/28/08 10:43 AM
marc esher's Gravatar of course, i just tried it again and i'm getting 2. maybe my page was cached or something. definitely looks like casting on the indexOf call works as expected.
# Posted By marc esher | 8/28/08 10:45 AM
Francois Levesque's Gravatar @Marc,

Happy to see it's working :). We just need to remember to use javacast to make sure we don't spend hours figuring out why our indexOf() calls aren't working, lol.
# Posted By Francois Levesque | 8/28/08 11:10 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.000. Contact Blog Owner