Complex Bag Sum In Java

Extracted from BagSumInManyProgrammingLanguages

A proposed JavaLanguage solution:

 public class BagSum{
public static void main(String[] tokens){
//  Create a new sorted Map, defaulting each entry to a new counter.
final AMap output = new Map(new TreeMap(), new NullFunctor(){
public Object result(){
return new int[]{ 0 };  
}
});

// For each token, grab the counter and increment it. new List(tokens).forEach(new UnaryClosure(){ public void perform(Object token){ ((int[]) output.at(token).get())[0]++; } }};

// For each count, display the token followed by the count. output.forEach(new UnaryClosure(){ public void perform(Object aTokenCount){ AMapElement tokenCount = (AMapElement) aTokenCount; System.out.println(tokenCount.key() + " " + ((int[]) tokenCount.get())[0]); } }); } }
So. Much. BoilerPlate. Code.

Seriously, the top of each class that I've used above has a comment "Reason #[foo] why I wish java was Lisp". And then there's the int array trick (Integer is not mutable, and 'int' isn't an object). And all the silly casts (which should go away with java1.5). And the verbosity of the blocks.

It's really a one liner, plus overhead :)

-- WilliamUnderwood

Interesting Java usage style. Where are the AMap, NullFunctor? and UnaryClosure? classes? And how did the List class (java.util.List???) get a 'forEach' method? I don't see 'forEach' anywhere in the Java 1.4 or 1.5 APIs. -- anon

But isn't library use cheating anyway? --ATS

And I'd think that using non-standard libraries would be cheating. If it was super-easy with "Java plus LibraryX," and LibraryX is well known and widely distributed (like Spring, for example), I'd be interested in seeing it. (But I wouldn't accept it as an official "JavaLanguage" example.) -- JeffGrigg

Does the example above use JavaGenericLibrary or JavaAlgorithmLibrary, or maybe the ApacheCommonsFunctor library?

I particularly wonder about AMap. And it's functor argument. Is that part of a widely available third party library? -- anon


A working complex JavaLanguage solution, without 3rd party libraries:

 import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;

public class BagSum? { public static void main(final String[] tokens){ // Create a new sorted Map, defaulting each entry to a new counter. final AMap output = new AMap(new TreeMap(), new NullFunctor?() { public Object result() { return new int[] { 0 }; } });

// For each token, grab the counter and increment it. (new ListOfArray?(tokens)).forEach(new UnaryClosure?() { public void perform(final Object token) { ((int[]) output.get(token))[0]++; } });

// For each count, display the token followed by the count. output.forEachKey(new UnaryClosure?() { public void perform(final Object key) { final int count = ((int[]) output.get(key))[0]; System.out.println(key + " " + count); } }); }

private static abstract class UnaryClosure? { public abstract void perform(final Object token); } private static abstract class Functor { public abstract Object result(); } private static class NullFunctor? extends Functor { public Object result() { return null; } }

private static class AMap /* 11 additional methods needed to do... implements Map */ { final Map map; final Functor undefinedEntryDefault; public AMap(final Map map, final Functor undefinedEntryDefault) { this.map = map; this.undefinedEntryDefault = undefinedEntryDefault; } public Object get(final Object key) { if (!this.map.containsKey(key)) { final Object value = this.undefinedEntryDefault.result(); this.map.put(key, value); } return this.map.get(key); } public void forEachKey(final UnaryClosure? unaryClosure) { for (final Iterator keyIterator = this.map.keySet().iterator(); keyIterator.hasNext();) { final Object key = (Object) keyIterator.next(); unaryClosure.perform(key); } } } private static class ListOfArray? /* 22 additional methods needed to do... implements java.util.List */ { final String[] listElements; public ListOfArray?(final String[] listElements) { this.listElements = listElements; } public void forEach(final UnaryClosure? unaryClosure) { for (int arrayIndex = 0; arrayIndex < this.listElements.length; ++arrayIndex) { final String element = this.listElements[arrayIndex]; unaryClosure.perform(element); } } } }


Consider the ApacheCommonsFunctor project, if you like the Closure, Functor and forEach syntax above.

Or write your own, there's nothing terribly complicated here, and the experience may even be worthwhile.


CategoryJava


EditText of this page (last edited June 8, 2006) or FindPage with title or text search