Effective Java Collections

I thought this article, Effective Java Collections, was excellent.  Here is the summary of the article.

  1. Use the isEmpty() method of the collection.
  2. Avoid returning null to mean an empty collection.
  3. Create an empty collection using Collections.empty***() methods.
  4. Iterate through collections using the foreach form when possible.
  5. Use the proper collection, Collection, Map, Set, List.
  6. The left side is always an interface!  (So is the return type of methods.)
  7. If you’re explicitly casting, chances are something is wrong. Use generics.

Interface Members

Because interfaces are static, public and don’t change, by definition any members you declare in them are static, public and final. Therefore you don’t need to qualify such members.

For example:

public interface A {
  String FOO = "foo";
}

is the same as:

public interface A {
  public final static String FOO = "foo";
}

You can read some more about this in the forum Interface member variable by default static?

Covariant Return Types in Java

dolphin's dance on Flickr

(Photo: dolphin’s dance by kalandrakas

This article, Covariant Return Types, from java.sun.com and reprinted in a nicer format by Java Tips, explains well what covariant return types are.

You cannot have two methods in the same class with signatures that only differ by return type. Until the J2SE 5.0 release, it was also true that a class could not override the return type of the methods it inherits from a superclass. In this tip you will learn about a new feature in J2SE 5.0 that allows covariant return types. What this means is that a method in a subclass may return an object whose type is a subclass of the type returned by the method with the same signature in the superclass. This feature removes the need for excessive type checking and casting.

An example is:

public class Shape {
  private Shape shape;
  public Shape getShape() { return shape; }
}

public class Circle extends Shape {
  private Circle circle;
  @Override
  public Circle getShape() { return circle; }
}

Not the best example but a succinct one. 🙂

Static Import

I never liked seeing people put constants in an interface and then implementing that interface in a class so that they can have direct access to those constants. That always seemed wrong to me and now this Sun article, Static Import, verifies my intuition.

In order to get around this, people sometimes put static members into an interface and inherit from that interface. This is a bad idea. In fact, it’s such a bad idea that there’s a name for it: the Constant Interface Antipattern (see Effective Java Item 17). The problem is that a class’s use of the static members of another class is a mere implementation detail. When a class implements an interface, it becomes part of the class’s public API. Implementation details should not leak into public APIs.

The suggested method is to use a static import.

import static java.lang.Math.PI;

However the article suggests using this sparingly.

Only use it when you’d otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from. Importing all of the static members from a class can be particularly harmful to readability; if you need only one or two members, import them individually. Used appropriately, static import can make your program more readable, by removing the boilerplate of repetition of class names.

You can also do static import of methods.

import static com.betweengo.util.CollectionUtils.isEmpty;

However I would never do this, I like knowing where my static methods come from.

Playing with Dates in Java

I always forget how to do these things so I thought I should write it down.

Changing Dates:

Here is an example of getting the date for seven days ago from now.

    Calendar sevenDaysAgo = Calendar.getInstance();
    sevenDaysAgo.add(Calendar.DATE, -7);
    sevenDaysAgo.set(Calendar.HOUR_OF_DAY, 0);
    sevenDaysAgo.set(Calendar.MINUTE, 0);
    sevenDaysAgo.set(Calendar.SECOND, 0);
    sevenDaysAgo.set(Calendar.MILLISECOND, 0);

Formatting Dates:

Here is the simple way to format a date and time.

    DateFormat.getDateTimeInstance().format(sevenDaysAgo.getTime()))

The output is:

    May 21, 2008 12:00:00 AM

Note that according to the JavaDoc, DateFormats are inherently unsafe for multithreaded use. You should not make a call to a static instance of a DateFormat nor share a single instance across thread boundaries without proper synchronization.  The same applies to Calendar.  For more information on this see Sun Bug #6231579 and Sun Bug #6178997.

Creating Dates:

Here is an example of creating a date, the birth date January 1, 1970.

    Calendar birthDate = Calendar.getInstance();
    birthDate.clear();
    birthDate.set(Calendar.YEAR, 1970);
    birthDate.set(Calendar.MONTH, 0);
    birthDate.set(Calendar.DATE, 1);

For further reading please Create a Date object using the Calendar class and of course the JavaDocs for Calendar, Date and DateFormat.

Linked List Interview Questions

  1. Implement Insert and Delete for a Singly Linked List.
    public interface Link<E> {
    	public Link<E> getNext();
    	public void setNext(Link<E> link);
    
    	public Link<E> getPrev();
    	public void setPrev(Link<E> link);
    
    	public E getValue();
    	public void setValue(E value);
    }
    
    public class SingleLink<E> implements Link<E> {
    
    	public SingleLink(E value) { this.value = value; }
    
    	private Link<E> next;
    	private E value;
    
    	public Link<E> getNext() { return next; }
    	public void setNext(Link<E> next) { this.next = next;}
    
    	public Link<E> getPrev() { throw new UnsupportedOperationException(); }
    	public void setPrev(Link<E> prev) { throw new UnsupportedOperationException(); }
    
    	public E getValue() { return value; }
    	public void setValue(E value) { this.value = value;}
    
    	@Override
    	public boolean equals(Object obj) { return this.value.equals(obj); }
    
    	@Override
    	public String toString() { return getValue().toString(); }
    }
    
    public abstract class LinkedList<E> {
    
    	protected abstract Link<E> createHead(E value);
    	protected abstract Link<E> removeHead();
    	protected abstract Link<E> append(Link<E> tail, E value);
    	protected abstract void chain(Link<E> from, Link<E> to);
    	protected abstract void deleteAfterHead(E value);
    	protected abstract boolean isInsert(Link<E> link);
    	protected abstract boolean isEnd(Link<E> link);
    
    	public void insert(E value) {
    
    		if (head == null) {
    			createHead(value);
    			return;
    		}
    
    		Link<E> tmp = head;
    		while (!isInsert(tmp))
    			tmp = tmp.getNext();
    
    		append(tmp, value);
    	}
    
    	public void delete(E value) {
    
    		if (head == null)
    			return;
    
    		if (head.equals(value)) {
    			removeHead();
    			return;
    		}
    
    		deleteAfterHead(value);
    	}
    
    	Link<E> head;
    }
    
    public class SinglyLinkedList<E> extends LinkedList<E> {
    
    	@Override
    	protected Link<E> createHead(E value) {
    		if (value != null) {
    			head = new SingleLink<E>(value);
    		} else {
    			head = null;
    		}
    		return head;
    	}
    
    	@Override
    	protected Link<E> removeHead() {
    		if (isEnd(head.getNext())) {
    			head = null;
    			return null;
    		}
    
    		head = head.getNext();
    		return head;
    	}
    
    	@Override
    	protected Link<E> append(Link<E> tail, E value) {
    		Link<E> link = new SingleLink<E>(value);
    		tail.setNext(link);
    		return link;
    	}
    
    	@Override
    	protected void chain(Link<E> from, Link<E> to) {
    		from.setNext(to);
    	}
    
    	@Override
    	protected void deleteAfterHead(E value) {
    
    		Link<E> tmp = head.getNext();
    		Link<E> prev = head;
    		while (!isEnd(tmp)) {
    			if (tmp.equals(value)) {
    				chain(prev, tmp.getNext());
    				break;
    			}
    			prev = tmp;
    			tmp = tmp.getNext();
    		}
    	}
    
    	@Override
    	protected boolean isInsert(Link<E> link) {
    		return isEnd(link.getNext());
    	}
    
    	@Override
    	protected boolean isEnd(Link<E> link) {
    		return link == null;
    	}
    }
  2. Implement Insert and Delete for a Doubly Linked List.
    public class DoubleLink<E> extends SingleLink<E> {
    
    	public DoubleLink(E value) { super(value); }
    
    	private Link<E> prev;
    
    	@Override
    	public Link<E> getPrev() { return prev; }
    
    	@Override
    	public void setPrev(Link<E> prev) { this.prev = prev; }
    }
    
    public class DoublyLinkedList<E> extends SinglyLinkedList<E> {
    
    	@Override
    	protected Link<E> createHead(E value) {
    		if (value != null) {
    			head = new DoubleLink<E>(value);
    		} else {
    			head = null;
    		}
    		return head;
    	}
    
    	@Override
    	protected Link<E> removeHead() {
    		head = super.removeHead();
    		if (head != null) {
    			head.setPrev(null);
    		}
    
    		return head;
    	}
    
    	@Override
    	protected Link<E> append(Link<E> tail, E value) {
    		Link<E> link = new DoubleLink<E>(value);
    		tail.setNext(link);
    		link.setPrev(tail);
    		return link;
    	}
    
    	@Override
    	protected void chain(Link<E> from, Link<E> to) {
    		from.setNext(to);
    		if (to != null) {
    			to.setPrev(from);
    		}
    	}
    
    	@Override
    	protected void deleteAfterHead(E value) {
    
    		Link<E> tmp = head.getNext();
    		while (!isEnd(tmp)) {
    			if (tmp.equals(value)) {
    				chain(tmp.getPrev(), tmp.getNext());
    				break;
    			}
    			tmp = tmp.getNext();
    		}
    	}
    }
  3. Implement Insert and Delete for a Sorted Linked List.
    public class SortedLinkedList<E> extends SinglyLinkedList<E> {
    
    	@Override
    	public void insert(E value) {
    
    		if (head == null) {
    			createHead(value);
    			return;
    		}
    
    		Link<E> tmp = head;
    		Link<E> prev = null;
    		// XXX: yuck, dynamic casting to Comparable
    		while (!isEnd(tmp) &&
    	Comparable<E>) tmp.getValue()).compareTo(value) < 0) {
    			prev = tmp;
    			tmp = tmp.getNext();
    		}
    
    		Link<E> link = new SingleLink<E>(value);
    		if (prev == null) {
    			link.setNext(head);
    			head = link;
    		} else {
    			prev.setNext(link);
    			link.setNext(tmp);
    		}
    	}
    }
  4. Implement Insert and Delete for a Circular Linked List.
    public class CircularLinkedList<E> extends DoublyLinkedList<E> {
    
    	@Override
    	protected Link<E> createHead(E value) {
    		head = super.createHead(value);
    		if (head != null) {
    			head.setNext(head);
    			head.setPrev(head);
    		}
    		return head;
    	}
    	
    	@Override
    	protected Link<E> removeHead() {
    		if (head.getNext() == head) {
    			head = null;
    			return null;
    		}
    		
    		Link<E> prev = head.getPrev();
    		head = head.getNext();
    		head.setPrev(prev);
    		prev.setNext(head);
    		return head;
    	}		
    
    	@Override
    	protected Link<E> append(Link<E> tail, E value) {
    		Link<E> link = new DoubleLink<E>(value);
    		tail.setNext(link);
    		link.setPrev(tail);
    		link.setNext(head);
    		head.setPrev(link);
    		return link;
    	}
    	
    	@Override
    	protected boolean isEnd(Link link) {
    		return link == head;
    	}
    
    	@Override
    	protected boolean isInsert(Link link) {
    		return link.getNext() == head;
    	}
    }

Data Structures Interview Questions

  1. Find the largest int value in an int array (try to not use native functionality like “max()”)
    	public static int max(int [] array) {
    		int max = Integer.MIN_VALUE;
    		for (int ii = 0; ii < array.length; ii++) {
    			if (array[ii] > max)
    				max = array[ii];
    			if (max == Integer.MAX_VALUE)
    				break;
    		}
    		return max;
    	}
  2. What’s the difference between a stack and a queue?
     
    Stacks are LIFO, i.e. last in, first out. You push things on top of the stack and pop them off the stack.
    Queues are FIFO, i.e. first in, first out. You push things in one side, pop them off the other.
     
  3. Write a function to reverse a string (try to not use native functionality like strrev() or text[::-1])
             char * strrev(char * str) {
               int ii = 0, jj = strlen(str) - 1;
               char tmp;
               while (ii < jj) {
                 tmp = str[ii];
                 str[ii++] = str[jj];
                 str[jj--] = tmp;
               }
               return str;
             }
  4. Write a function that determines if two strings are anagrams. From wikipedia: an anagram is “the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once.” (“abc” “bac” “cba” are anagrams, “abc” and “bba” are not)
  5. /**
     * Returns 1 if it's an anagram, 0 otherwise.
     */
    int anagram(char * str1, char * str2) {
    
      // quick check
      if (strlen(str1) != strlen(str2)) {
        return 0;
      }
    
      // copy str2 to our tmp
      char * tmp = malloc(strlen(str2) + 1);
      strcpy(tmp, str2);
    
      int ii = 0;
      while (str1[ii] != 0) {
        char * ch = strchr (tmp, str1[ii]);
    
        // if not found return -1 to indicate not an anagram
        if (ch == 0)
          return 0;
    
        // remove this found letter from second string
        ch[0] = 0;
        if (ch == tmp) {
          tmp = ch + 1;
        } else if (*(ch+1) != 0) {
          tmp = strcat(tmp, ch+1);
    	}
    
        // go to next character
        ii++;
      }
    
      return 1;
    }

Computing Basics Interview Questions

  1. Use recursion to write a function that determines the length of a string
    int strlen(char * str) {
      if (str[0] == 0)
        return 0;
      return 1 + strlen(str + 1);
    }
  2. What’s the number after F in hexadecimal?0x10
  3. Bitwise: what is 7 | 1? 7 & 1? ~7?

    7 (0111). 1 (0001). -8 (1000).

  4. Write a script that prints the numbers from 1 to 100. But for multiples of four print “Four” instead of the number and for the multiples of seven print “Seven”. For numbers which are multiples of both four and seven print “FourSeven”.
    for (int ii = 1; ii <= 100; ii++) {
    	boolean isMultipleOfFour = (ii % 4 == 0);
    	boolean isMultipleOfSeven = (ii % 7 == 0);
    	if (isMultipleOfFour && isMultipleOfSeven)
    		System.out.println("FourSeven");
     	else if (isMultipleOfFour)
    		System.out.println("Four");
     	else if (isMultipleOfSeven)
     		System.out.println("Seven");
    	else
    		System.out.println(ii);
    }

ATG Consulting Interview

Today I had the most detailed but at same time most interesting ATG consulting interview yet. Here are the questions I was asked with answers when appropriate in italics.

  1. Which versions of ATG have you worked with?
  2. What parts of ATG’s stack have you worked with?
  3. How do you compare ATG with Ruby on Rails?
  4. What is Nucleus?
  5. What is the ATG Repository?
  6. When creating form handlers typically what ATG base class do you extend? GenericFormHandler.java
  7. When creating droplets what ATG base class do you extend? DynamoServlet.java
  8. What form handlers and methods do you use during checkout? ShoppingCartFormHandler, numerous handlers like handleMoveToConfirm, etc.
  9. What does a user typically see during checkout? Add to shopping cart, login, billing and shipping address, payment, confirm, confirmation, email confirmation, shipped email.
  10. How do you compare strings in Java? If String a = “hello” and String b= “hello” what is a == b? True, a and b both reference the same constant string.

In another interview I was asked these questions.

  1. What is HTTP? How does it work?
  2. If HTTP is stateless then how does a web application maintain state.