I Meet the Tao
Tao is as usual sitting under the tree of wisdom.
Last week when the programming lesson on java collection classes was over, he threw a coding challenge at us.
He asked to write a small piece of code to iterate over the collection.
The Problem
Write a program that takes the words in its argument list and prints out any duplicate words, the number of distinct words, and a list of the words with duplicates eliminated.
I approached, with winning smile on my face, and the code snippet on my think pad.
import java.util.*; public class FindDups { public static void main(String args[]) { new FindDups(args); } FindDups(String[] input){ HashSet s = new HashSet(); for (int i=0; i<args.length; i++){ if (!s.add(args[i])){ System.out.println("Duplicate detected:" + args[i]); } } System.out.println(s.size()+" distinct words detected: "+s); } }Out of the program:
% java FindDups i came i saw i left Duplicate detected: i Duplicate detected: i 4 distinct words detected: [came, left, saw, i]Do Small Change, to Make Big Difference.
Tao had a glance at my great piece of code. There was charismatic smile on his face.
I was startled. I knew, I must have done some grave mistake. However, I was eager to learn that fine point of Java programming.
I look forward to Tao to enlighten me.
Then, to my surprise, Tao made a small correction to my code. I could not see much improvement though.
import java.util.*; public class FindDups { public static void main(String args[]) { new FindDups(args); } FindDups(String[] input){ Set s = new HashSet(); for (int i=0; i<args.length; i++){ if (!s.add(args[i])){ System.out.println("Duplicate detected:" + args[i]); } } System.out.println(s.size()+" distinct words detected: "+s); } }I could not hide my quizzical expressions on my face.
Tao continued to don the same charismatic smile.
Then he asked me to ponder over the “small change” and decipher the underlying design principle.
Then he left me.
I stood there wondering about the design principle.
I struggled through out the day to pin point the design principle. But no gain.
Then I wrote down the lines of difference, in hope that I could read between the lines.
HashSet s = new HashSet(); …………… My code Set s = new HashSet(); …………… His codeIt was beautiful full moon night. I kept staring, at my lap top screen.
I do not remember when did I fall asleep.
Early next morning, I hurried myself to Tao.
Tao was not there. But He had left message for me.
HashSet s = new HashSet(); …………… My code Set s = new HashSet(); …………… His codeNow I could see the design principle I was exploring. I got the Aha! Feeling. But I was craving for the Aha! Insight.
What is the rationale behind this design mantra. And how it is making the big difference to my Java code.
I surrendered myself to Tao. Tao showed mercy on me.
I know. When student is ready, Tao appears.
Looking Through the Glass
Note that the code should always refer to the collection by its interface type (Set), rather than by its implementation type (HashSet). This is a strongly recommended programming practice, as it gives you the flexibility to change implementations merely by changing the constructor.
If the variables used to store a collection, or the parameters used to pass it around, are declared to be of the collection's implementation type rather than its interface type, then all such variables and parameters must be changed to change the collection's implementation type.
Furthermore, there's no guarantee that the resulting program will work; if the program uses any non-standard operations that are present in the original implementation type but not the new one, the program will fail.
Referring to collections only by their interface keeps you honest, in the sense that it prevents you from using any non-standard operations.
Small Change in Requirement Should Not Result in Big Change in Code
The implementation type of the Set in the example above is HashSet, which makes no guarantees as to the order of the elements in the Set.
If you want the program to print the word list in alphabetical order, all you have to do is to change the set's implementation type from HashSet to TreeSet.
Making this trivial one-line change causes the command line in the previous example to generate the following output:
% java FindDups i came i saw i left Duplicate word detected: i Duplicate word detected: i 4 distinct words detected: [came, i, left, saw]When I emerged from the fundamentals and looked up, Tao had left me long back.
Tao was not there. But He had left message for me.