Java Closure Examples

One thing I miss in the current BGGA proposal for closures in Java 7, is a good set of examples. There are some examples, but they don’t cover most situations. Also I feel that more examples might better show the advantages of having closures in Java. Of course, as long as the Java compiler has not been patched to work with closures, this remains “swimming on dry land” (as we say in Holland). Syntax errors will no doubt be abundant, and everything might change with the next version of the proposal. I hope this will still be useful to people wondering why there should be closures in Java in the first place. This is why: it makes your code cleaner and leaner.

So here goes, starting with some simple examples. Each example consists of the closure method usage (which will probably be used most) and the closure method definition (which will mostly be done by library developers).

Select objects from collection

This is an example of how the CollectionUtils utility methods could be rewritten using closures.

public Collection<Book> getPublishedBooks(Collection<Book> books) {
    return select(books, {Book book =>
        book.isPublished()
    });
}

/**
 * Returns the T objects from the source collection for which the
 * given predicate returns true.
 *
 * @param source
 *            a collection of T objects, not null
 * @param predicate
 *            returns true for a given T object that should be
 *            included in the result collection
 * @return a collection of T objects for which the predicate
 *         returns true
 */
public static <T> Collection<T> select(Collection<T> source,
        {T=>Boolean} predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T o : source) {
        if (predicate.invoke(o)) {
            result.add(o);
        }
    }
    return result;
}

Sorting

Sorting lists of objects currently requires an implementation of Comparator (unless the objects’ natural order is to be used). Using a closure could simplify this:

public static void sortByTitle1(Collection<Book> books) {
    sort(books, {Book book1, Book book2 =>
        book1.getTitle().compareTo(book2.getTitle())
    });
}

/**
 * Sorts the given list of T objects, using the block to compare
 * individual elements of the list.
 *
 * @param l
 *            list to be sorted
 * @param block
 *            compares its two arguments for order. Returns a
 *            negative integer, zero, or a positive integer as the
 *            first argument is less than, equal to, or greater
 *            than the second.
 */
public static <T> void sort(List<T> l,
        final {T, T=>Number} block) {
    Collections.sort(l, new Comparator<T>() {
        public int compare(T arg0, T arg1) {
            return block.invoke(arg0, arg1);
        }
    }
}

Sorting (2)

But why stop there? If most of the sorting you do only uses one attribute, then why not define a method with a block that only returns that attribute?

public static void sortByTitle2(Collection books) {
    sort(books, {Book book =>
        book.getTitle()
    });
}

/**
 * Sorts the given list of T objects, using the block to compare
 * individual elements of the list.
 *
 * @param l
 *            list to be sorted
 * @param block
 *            returns the value of a property of the given T object
 *            that should be used for sorting
 */
public static <T> void sort(List<T> l,
        {T=>Comparable} block) {
    sort(T o1, T o2 : l) {
        block.invoke(o1).compareTo(block.invoke(o2));
    }
}

Iterating over maps

This example demonstrates iterating over map entries. The closure receives each entry’s key and value in one go, and can process them as required.

public static void printMap(Map<String,Book> m) {
    forEach(m, {String key, Book book =>
        System.out.println(key + " = " + book);
    });
}

/**
 * Iterates over entries from the given map, passing each entry's key
 * and value to the given block.
 *
 * @param m
 *            map to be iterated over
 * @param block
 *            processes key/value pairs from the map
 */
public static <T,U> void forEach(Map<T,U> m,
        {T, U=> } block) {
    for (Iterator<T> it = m.keySet().iterator(); it.hasNext(); ) {
        T key = it.next();
        block.invoke(key, m.get(key));
    }
}

06-02-07 UPDATE fixed syntax error and syntax highlighting.

08-02-07 UPDATE following up on Neal’s comments, I have replaced the cleaner-looking (but in this case incorrect) control invocation syntax with the standard syntax. I still think it’s confusing to have this alternative syntax that can only be used in some cases; but perhaps there’s a logic explanation for this? At least I hope to get the “approved” stamp this time. It goes to show that it’s a good idea to have some (correct) real-world code examples.

2007-02-05. 17 responses.

Comments

  1. Ugh! Ugly syntax.

  2. I wrote up a series of 5 ‘use cases’ on my blog – http://www.jroller.com/page/scolebourne?entry=closures_use_cases_looping. They are a bit more discussion based than your examples

    BTW, Sorting (1) isn’t quite right – you fell into the last-line-no-semicolon trap

  3. Why u sai it is ugly ????
    What is ur reason ????
    If u do something without reason, I can also call u fool without giving any reason.

    Welcome to the Java World, No-brainer

  4. I see ugly and I say it is ugly. That’s why. No other reason. Aesthetics and ease of reading.

  5. @Stephen: thanks for spotting the error, I fixed it. I’m not a fan of the missing semicolon; on the other hand, you’ll probably get used to it fast enough.

    I did read your usecase posts. These examples are merely meant as an illustration to the proposal, not to discuss it.

  6. The control invocation is a statement form, not an expression, and the controlled statement is a statement, not an expression. I think none of your examples is syntactically correct.

  7. [...] syntax for generics, it’s not too far off from C++’s it seems. But I went to look at these examples of how the new closures feature would look and I was lost. Apparently, Java has changed a lot since I last used it in college — a mere [...]

  8. Also, you can’t use wildcards as function argument types.

  9. @Neal: hmm… yes, I see… But why this limitation on the control invocation syntax? That means that for closures resulting in an expression, I’d have to write, for example:

        Collection publishedBooks = select(books, {Book book =>
            book.isPublished()
        });
    

    …and for closures that do not need to result in an expression, I could choose between the standard and the control invocation form? Isn’t that confusing? If you get used to the control invocation syntax, wouldn’t you want to use it in all cases?

  10. If the precise same syntax is an expression and also a statement, then an extra semicolon would be needed to end the statement. That sort of undermines the point of the control invocation syntax.

  11. I have put a comparison of different inner class/closure proposals at:

    http://www.artima.com/weblogs/viewpost.jsp?thread=202004

  12. What I think is a shame about the Java closure examples you can usually find on the Net is that they are too obvious. Almost all of them can be solved with mere inner classes with a bit of verbosity. The five examples on this page fall into this. Of course, people need them to understand the basics, for it’s not enough to understand the real power of closures.

    In my opinion, one thing that really makes the BGGA closures powerful is the change of semantics for return, break, etc. It allows easy-to-write iteration using recursive algorithms, for instance: imagine you have a tree-based structure and you want to iterate through nodes or leaves of the tree. Today you have but one choice: to write an Iterator class, which un-recursifies the iteration. About 100-300 lines of code (!), which are quite tricky and hard to make bug-free.

    With the BGGA closures, you just need to write your recursive algorithm (which is usually much simpler and shorter: down to 15-20 lines for classic tree-based algorithms?), and invoke the argument closure at every step of the iteration. If the closure decides to stop the iteration after the first or the second step, it’s very easy to do it, no matter the recursion depth: the recursive algorithm doesn’t have to be rewritten for that.

    The best example I found on this matter is Neal Gaffer’s one on his blog: http://gafter.blogspot.com/2007/03/closures-for-organizing-your-code.html

  13. Just a nit: Instead of putting these methods in CollectionUtils or Collections, I would hope that Sun and other API vendors would implement them as instance methods in the Collection API implementations. Better OO, better API.

    Only the syntax, and it’s ugliness — it’s ugly because you don’t understand it at a glance. Once you’re used to the syntax, and you can grok the intent of the code at a glance, it may not stick out as ugly. A certain amount of syntactic decoration is necessary to fit it into a language that wasn’t originally designed for it, in order to make it forward-compatible.

  14. [...] to discuss only the most complex examples from the BGGA proposal. He “forgot” to show some examples of how closures might actually make life (and coding) a lot easier. Which one do you think is [...]

  15. [...] Danny’s Blog ->Java Closure Examples [...]

  16. Please,dont propose new java language features anymore.let the groovy solves all dynamic syntax as java superset.

  17. [...] Colebourne’s WebblogWill Closures Make Java Less Verbose? by Bruce EckelJava Closures TutorialJava Closure ExamplesClosures for the Java Programming Language (aka [...]