It's been forever since I've written anything here. I know, I'm such a slacker and I have no excuse. But after discovering the ColdFusion solution I'm about to share, I knew I had to write about it.

Yesterday as quick test I attempted to create a solution for the following: Given 2 lists of names, create a 3rd, sorted list that contains ONLY those names that appear in both lists.

Pretty straightfoward, right? Before I show my first attempt I think it is important to understand that I always strive to answer "yes" to 3 questions when creating a solution:

  1. Does the solution accomplish the goal?
  2. Is the code easy to read/understand?
  3. Is the code performant?

My straightforward solution became:

view plain print about
1friends = "Chris,Ashley,Joe,Mike,Ritch,Jennifer";
2family = "Ashley,Jennifer,Nancy,Mae";
3framily = "";
4for( name in friends ){
5    if( findNoCase( name, family ) ){
6        framily = listAppend( framily, name );
7    }
9framily = listSort( framily, "textnocase" );

In essence, loop through all the names in list "one". If the name also appears in list "two", add it to "common". If one of the lists was shorter (as "two" is)

I think my solution checks all those boxes. But looking at it I just knew there was a better approach. I played around with map but it didn't feel better, just more difficult to read. Then I unearthed array.retainAll(). As a ColdFusion developer I had never heard of it. It's not a method included in the documentation at CFDocs Array Functions.

Dear reader, retainAll() is a JAVA method, called in the format array1.retainAll(array2), that retains only common array elements of array1 and array2. Exactly what I wanted to do!

I changed my code to:

view plain print about
1friends = "Chris,Ashley,Joe,Mike,Ritch,Jennifer";
2family = "Ashley,Jennifer,Nancy,Mae";
3framily = listToArray( friends );
4framily.retainAll( listToArray( family ) );
5framily = listSort( arrayToList( framily ), "textnocase" );

This code accomplishes the goal and is mostly easy to understand. 2 of my 3 requirements for an acceptable solution.The use of retainAll() may not be clear for any CF developer with no java experience (like myself). But this can be mitigated by adding a comment, so I don't consider it a bad thing.

But how about the third question? How does it perform? Better than the original!

The average run-time over 10,000,000 iterations: Loop-based solution: 0.006364ms RetainAll-based solution: 0.0044926ms

It would be premature optimization to choose the retainAll-based solution based solely on the runt-time numbers, though. At that speed, the difference is really negligible. For me, the retainAll-based solution is the better choice because the code is more concise and easier to debug/maintain.