the blog for developers

Response to the critique for my last post and OneElementIterator

I’ve wrote an update to the post where someone suggested in a trackback to use the JDK for an one element iterator.

I got interested in aa OneElementIterator, which optimized – not sure how fast try is – could look like this:

public class OneElementIterator[T] implements Iterator[T] {
  private T element;

  public OneElementIterator(T element) {
    this.element = element;
  }

  public boolean hasNext() {
    return element != null;
  }

  public T next() {
    try {
      return element;
    } finally {
      element = null;
    }
  }

Faster and shorter ideas?

Update: Remove got lost during cut & paste:

  public void remove() {
    // not supported, throw exception
    throw new UnsupportedOperationException("Remove not supported in OneElementIterator");
  }

And as Eugene noted next() should throw NoSuchElementException .

About the author

stephan Stephan Schmidt has been working with internet technologies for the last 20 years. He was head of development, consultant and CTO and is a speaker, author and blog writer. He specializes in organizing and optimizing software development helping companies by increasing productivity with lean software development and agile methodologies. Want to know more? All views are only his own. You can find him on Google +

You can leave a Reply here. Of course, you should follow me on twitter here.

You can share this post!
Do you want to tell others about this article? Use the social bookmark icons to submit this artice to the service of your choice. Thanks.

Leave a reply.

Comments

Much faster to avoid the try (which as you implied, can be quite slow) and instead use a local temporary:

public T next() {
  T e = element;
  element = null;
  return e;
}

It’s not concurrency safe, but then, neither is yours. :-)

stephan

Yes, thought about that, but was intrigued by the beauty of the finally solution. In production I would introduce the e reference though.

But I’m not sure about performance, because there is no Exception being thrown or catched.

According to the Iterator class javadoc, next() method is supposed to throw NoSuchElementException when iteration has no more elements. Also, there is a remove() method, which should throw an UnsupportedOperationException if the remove operation is not supported by Iterator.

stephan

@Eugene: You’re right of course.

The remove got lost with cut&paste (see missing } for class :-)

I’ll add the method.

Erik Mogensen

What if you want to return an iterator that contains a _null_ :-)

And of course you have the while(true) System.out.println(e.next()); which relies on the exception to be thrown. It’s not good code, but it is valid. Violating the javadoc requirement of throwing the exception would put some unlucky user into a tight loop…

I’d go with Collections.singletonList(whatever).iterator(). The less code you write, the fewer bugs you write.

stephan

@Erik: The whole point was not to return null ;-)

“@Eugene: You’re right of course.”

So I added to my version

  public T next() {
    if (!hasNext()) {
      throw new NoSuchElementException("No more elements in OneElementIterator");
    }
    try {
      return element;
    } finally {
      element = null;
    }
  }

“I’d go with Collections.singletonList(whatever).iterator(). The less code you write, the fewer bugs you write.”

Normally I would agree. There are some posts on this topic on this blog, for example the String.reverse issue (JDK versus write-your-own).

In this case, because Option[T] is potentially used a lot, I’d go for an optimization.

Stephan, it seem to me that you created a problem that does not actually exist. Basically, if you are always using iterator, just for the sake of syntactic sugar with the foreach loop, according to my microbenchmark you got yourself about 60% overhead (even with your optimized OneItemIterator class) comparing to simply returning a Null object. It is actually unlikely something like that ever going to be a bottle neck in the real application, but number of iterations and tiny mistakes you made while implementing such simple class is really scare. So, it would have been safer to simply use existing JRE classes.

lqd

Nice :)

I guess we could rename OneElementIterator to Some, extend Option[T] and return this in iterator() to realign with the last post concepts.

stephan

@Eugene: I’m not sure what’s more important, less bugs or performance. You decide. Otherwise I fear there is only Scala left for me.

@lqd: Hmm :-)

If you don’t care about performance, Collections.singleton(value).iterator. :-)

If you want performance and null handling, add a mutable “hasNext” boolean flag to your implementation.

It’s important to mention that, unlike Java style external iterators, the Scala solution based on map and flatMap or the Haskell solution based on bind and “return” (not the same thing as Java style return) require no mutation. E.g., here’s a complete Option monad in Scala – it’s even covariant, which is a pain in the arse in Java

sealed abstract class MyOption[ A] {
def map[B](f:A=>B):MyOption[B] = flatMap(x => MySome(f(x)))
def flatMap[B](f:A=>MyOption[B]):MyOption[B] = this match {
case MySome(x) => f(x)
case _ => MyNone
}
}
case class MySome[ A](value:A) extends MyOption[A]
case object MyNone extends MyOption[Nothing]

println(for {x <- MySome(3);y <- MySome(4);} yield x y)

The Haskell option monad is even tighter with less syntactic noise (although, I know this will get totally borked by word press, I hope something makes it through)

data MyOption a = MySome a | MyNone deriving Show

instance Monad MyOption where
(MySome x) >>= k = k x
MyNone >>= k = MyNone
return = MySome
fail s = MyNone

main = print $ do x <- MySome 3; y <- MySome 4; return (x y)

Leave a Reply

What people wrote somewhere else:

Additional comments powered by BackType

Guide to CodeMonkeyism

Over the last 4 years I wrote many articles on this blog. To make it easier for you to find the relevant ones, I've organized them into topics.

Top 10

6 reasons why my VC funded startup did fail

Go Ahead: Next Generation Java Programming Style

Java Interview questions: Write a String Reverser

The dark side of NoSQL

7 Bad Signs not to Work for a Software Company or Startup

Is Java dead?

Scala vs. Clojure

Never, never, never use String in Java

No future for functional programming in 2008 – Scala, F# and Nu

Clojure vs Scala, Part 2

Java Developer

Is Java Dead?

Go Ahead: Next Generation Java Programming Style

Be careful with magical code

All variables in Java must be final

Never, never, never use String in Java

Bending Java: More readable code with methods that do nothing?

NoSQL Guy

NoSQL: The Dawn of Polyglot Persistence

The dark side of NoSQL

Essential storage tradeoff: Simple Reads vs. Simple Writes

Sharding destroys the goals of your relational database

The unholy legacy of databases

Startup/CTO

Development Dream Teams

6 reasons why my VC funded startup did fail

American vs. European style of Software Development

12 Things to Reduce Your Lead Time and Time to Market

The high cost of overhead when working in parallel

Essential storage tradeoff: Simple Reads vs. Simple Writes

Job Seeker

Another Good (Java) Interview Question

7 Bad Signs not to Work for a Software Company or Startup

Java Interview questions: Write a String Reverser (and use Recursion!)

Java Interview questions: Multiple Inheritance

As a Manager: What I value in developers

Top 10 Tips (+1) to Get a Pay Raise

Agilist

What Developers Need to Know About Agile

5 Practices Better to Change in Your Scrum Implementation

Scrum is not about engineering practices

ScrumMaster and ZenMaster: The joke of certification

What is Trans-Scrum?