February 24, 2005

Ruby-style iterators in Java

Loop abstraction is probably the most common application of blocks in Ruby. The idea being that the programmer should not have to deal with the iteration code itself and concentrate on what needs to be done at each step, instead. And it's typically a good idea.

This is what a standard pre-Java 5 iteration looks like:

Iterator i = collection.iterator();
while (i.hasNext()) {
     Object obj = i.next();
     ...
}

Or, for iterating over an array:

for (int i = 0; i < array.length; ++i) {
    Object obj = array[i];
    ...
}

These are cleary prone to cause programming errors. Forget to call i.next(), call it twice, use <= instead of <, forget ++, and all goes to hell.

Iterators have gotten significantly better in Java 5 with the introduction of the for each construct, but they are still a long way from Ruby's internal iterators:

for (String str : listOfStrings) {
    ...
}

A little bit of nomenclature here. External iterators are those where the client code controls how the iteration takes place (e.g., the Java way). Internal iterators, on the other hand, abstract that logic and only require the client code to supply the action to perform at each step of the iteration (e.g., the Ruby way).

Take a look at the iterator idiom in Ruby:

array.each { |value|
     ...
}

Much cleaner, and no need for so much boilerplate, don't you think?

In the majority of cases, what a program really needs are internal iterators. From a code reuse perspective, why replicate the same construct over and over? But make no mistake, there are some legitimate cases for where external iterators are necessary, such as when looping over several collections in parallel (try doing that with internal iterators).

Ruby provides a way for externalizing internal iterators. Using the Generator class, an Enumerable object (i.e., that which exposes a method each) can be transformed into an external iterator:

generator = Generator.new [1,2,3,4,5,6,7]

while generator.next?
     puts generator.next
end


Internal iterators in Java

So, how about internal iterators for Java? The first thing we need to look at is how to encapsulate a chunk of code in a form that can be passed around (a la Ruby blocks).

The closest we can get are anonymous inner classes, but it's not even fair to compare them with Ruby blocks. The latter a lot more flexible, without the clunky syntax. Here's an how we could emulate a general-purpose block in Java 5:

interface Block {
     Object call(Object... items);
}

...

void methodThatTakesBlock(Block block)
{
     block.call("hello", "world");
}

...

Block block = new Block() {
     Object call(Object... items) {
         return items[0].toString() + items[1].toString();
     }
}

methodThatTakesBlock(block);

First, you'll notice we're declaring a Block interface. This is needed in order to be able to invoke the "call" method on the block (it would be possible to do via reflection, too, but that's another story).

The use of varargs helps avoid having to declare a block class or method for each possible combination of arguments and return values, but places the burden of extracting the arguments from the array on the implementer of the block.

For what we're trying to achieve here, we're going to stick with non-vararg arguments. In fact, our block only needs one argument, namely, the element that's being iterated over at each step. Here it goes:

interface IterationCallback<E>
{
     void call(E element);
}

interface EnumerableCollection<E>
    extends Collection
{
     void each(IterationCallback<E> callback);
}

class EnumerableArrayList<E>
     extends ArrayList<E>
     implements EnumerableCollection<E>
{

     public void each(IterationCallback<E> callback)
     {
         for (E element : this) {
             callback.call(element);
         }
     }
}

And here's how to use it:

EnumerableCollection<Integer> list = new EnumerableArrayList<Integer>();

list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

list.each(new IterationCallback<Integer>() {
     public void call(Integer element) {
         System.out.println(element);
     }
});

So, it is possible, but nobody said it would be pretty. Better language support would be needed to make internal iterators as developer-friendly as they are in Ruby. And we're not even considering the performance implications. The above code instantiates an extra object compared to using Java's iterator idiom, and requires an extra method call. It could have significant impact if used in the wrong place.

12 Comments:

Blogger Anthony said...

I still think Python beats the pants off of both Ruby and Java:

for item in list:
  print item

March 06, 2005 1:56 AM  
Blogger gavri said...

That works in Ruby too:

for item in list
print item
end

April 29, 2005 1:10 AM  
Blogger Trog said...

Hi great blog i must remember to bokmark you ... I have a horse racing blog myself I also have a new Online Auction to tell you about here auction for income get yourself $35.00 worth of free Advertising auction for income

October 11, 2005 11:41 AM  
Blogger St Louis Cardinals BUFF said...

So many blogs and only 10 numbers to rate them. I'll have to give you a 10 because you have done a good job. Great Job,

Free Access To More Information Aboutbroadcast

October 11, 2005 8:21 PM  
Blogger milf said...

black mold exposureblack mold symptoms of exposurewrought iron garden gatesiron garden gates find them herefine thin hair hairstylessearch hair styles for fine thin hairnight vision binocularsbuy night vision binocularslipitor reactionslipitor allergic reactionsluxury beach resort in the philippines

afordable beach resorts in the philippineshomeopathy for eczema.baby eczema.save big with great mineral makeup bargainsmineral makeup wholesalersprodam iphone Apple prodam iphone prahacect iphone manualmanual for P 168 iphonefero 52 binocularsnight vision Fero 52 binocularsThe best night vision binoculars here

night vision binoculars bargainsfree photo albums computer programsfree software to make photo albumsfree tax formsprintable tax forms for free craftmatic air bedcraftmatic air bed adjustable info hereboyd air bedboyd night air bed lowest pricefind air beds in wisconsinbest air beds in wisconsincloud air beds

best cloud inflatable air bedssealy air beds portableportables air bedsrv luggage racksaluminum made rv luggage racksair bed raisedbest form raised air bedsaircraft support equipmentsbest support equipments for aircraftsbed air informercialsbest informercials bed airmattress sized air beds

bestair bed mattress antique doorknobsantique doorknob identification tipsdvd player troubleshootingtroubleshooting with the dvd playerflat panel television lcd vs plasmaflat panel lcd television versus plasma pic the bestThe causes of economic recessionwhat are the causes of economic recessionadjustable bed air foam The best bed air foam

hoof prints antique equestrian printsantique hoof prints equestrian printsBuy air bedadjustablebuy the best adjustable air bedsair beds canadian storesCanadian stores for air beds

migraine causemigraine treatments floridaflorida headache clinicdrying dessicantair drying dessicantdessicant air dryerpediatric asthmaasthma specialistasthma children specialistcarpet cleaning dallas txcarpet cleaners dallascarpet cleaning dallas

May 18, 2008 2:02 PM  
Blogger nasha said...

Why was there no follow on bankruptcy then? The bailout of AIG FP went to (wow power leveling) hedge funds that bound credit swaps on Lehman failing or others betting on rating (wow power leveling) declines. AIG has drained over 100 billion from the government. Which had to go to (wow power leveling) those who bet on failures and downgrades. Many of whom (power leveling)were hedge funds. I-banks that had offsetting swaps needed the money from the AIG bailout or they would have been caught. Its an (wow powerleveling) insiders game and it takes just a little bit too much time for most people to think (wow gold) through where the AIG 100 billion bailout money went to, hedge funds and players, many of whom hire from the top ranks of DOJ, Fed, Treasury, etc. ZHANG XIAO CHEN

April 19, 2009 10:03 PM  
Blogger Kayla said...

www.crazypurchase.com Web site for the majority of the china wholesalers, and buy products wholesale to provide information and buy wholesale from china information exchange platform dedicated to becoming China Wholesale.

September 24, 2009 9:30 PM  
Blogger Kayla said...

Present-day society, the rapid development of science and technology makes cell phones wholesale is no longer a simple phone communications equipment only. Wholesale cell phones have many features, entertainment, scalability, and so have a good expression of the discount cell phones will be to maximize the effectiveness of multimedia technology.

September 24, 2009 9:31 PM  
Blogger Kayla said...

Cell phones from simple communication became a full-featured entertainment terminal . Can be said that cell phone china new milestone in the industry. This fully demonstrates that, cheap cell phones entertainment has become the most sought after consumer applications and has become the focus of the mobil phones market.

September 24, 2009 9:31 PM  
Blogger Adi said...

Oes Tsetnoc | Mengembalikan Jati Diri Bangsa | Kenali dan Kunjungi Objek Wisata di Pandeglang | Oes tsetnoc | Online Marketing | Electronics Gadgets | etips solution | Travel Guide

October 27, 2009 12:42 AM  
Blogger nike said...

Merry Christmas, my dear friends:
Nike shoes
nike shox torch
Cheap nike shoes
Discount nike shoes
Nike shox r4
nike shox shoes
puma cat
cheap sport shoes
cheap nike shox
cheap nike max
nike tn dollar
nike running shoes
nike air max tn
puma shoes
discount puma shoes
puma mens shoes
puma running shoes
puma shoes
ed hardy clothes
ed hardy shirts
ed hardy jackets
ed hardy hoodies
ed hardy boots
ed hardy polo shirts
ed hardy shoes
ed hardy jeans
ed hardy outerwear
ed hardy long sleeve shirts
ed hardy bags
ed hardy uggr boots
ed hardy handbags
ed hardy love kills slowly shirts
ed hardy love kills slowly shoes
ed hardy love kills slowly boots
ed hardy trousers
ed hardy mens
ed hardy womens
ed hardy t shirts
ed hardy sunglasses
ghd hair straighteners mk4
hair straightners
ghd iv styler hair straightener
ghd hair straightners
cheap ghd hair straighteners

December 14, 2009 5:32 PM  
Blogger uwanna said...

gucci replica handbags
men gucci shoes
Gucci men sneakers
Gucci men moccasins
gucci women sneakers
gucci women boots
Gucci men boots
Gucci
Gucci shop
Gucci bags
Gucci shoes
Replica GUCCI SHOES
wholesale gucci shoes
cheap Gucci handbags
Gucci ON sale
Gucci Belts
Gucci small accessories
Gucci hats & scarves
Gucci wallets
Gucci Handbags
Women Gucci shoes
Men Gucci shoes
discount gucci shoes
cheap Gucci shoes

February 04, 2010 9:48 PM  

Post a Comment

Links to this post:

Create a Link

<< Home