How To Implement Generators In Java

Email this to someoneShare on Google+0Share on Facebook0Tweet about this on Twitter0Share on LinkedIn0Share on Reddit0Share on TumblrDigg thisPin on Pinterest0
.java5 {font-family:monospace;color: #006; border: 1px solid #d0d0d0; background-color: #f0f0f0;} .java5 a:link {color: #000060;} .java5 a:hover {background-color: #f0f000;} .java5 .imp {font-weight: bold; color: red;} .java5 .kw1 {color: #000000; font-weight: bold;} .java5 .kw2 {color: #000000; font-weight: bold;} .java5 .kw3 {color: #006600; font-weight: bold;} .java5 .kw4 {color: #006600; font-weight: bold;} .java5 .kw5 {color: #003399; font-weight: bold;} .java5 .kw6 {color: #003399; font-weight: bold;} .java5 .kw7 {color: #003399; font-weight: bold;} .java5 .kw8 {color: #003399; font-weight: bold;} .java5 .kw9 {color: #003399; font-weight: bold;} .java5 .kw10 {color: #003399; font-weight: bold;} .java5 .kw11 {color: #003399; font-weight: bold;} .java5 .kw12 {color: #003399; font-weight: bold;} .java5 .kw13 {color: #003399; font-weight: bold;} .java5 .kw14 {color: #003399; font-weight: bold;} .java5 .kw15 {color: #003399; font-weight: bold;} .java5 .kw16 {color: #003399; font-weight: bold;} .java5 .kw17 {color: #003399; font-weight: bold;} .java5 .kw18 {color: #003399; font-weight: bold;} .java5 .kw19 {color: #003399; font-weight: bold;} .java5 .kw20 {color: #003399; font-weight: bold;} .java5 .kw21 {color: #003399; font-weight: bold;} .java5 .kw22 {color: #003399; font-weight: bold;} .java5 .kw23 {color: #003399; font-weight: bold;} .java5 .kw24 {color: #003399; font-weight: bold;} .java5 .kw25 {color: #003399; font-weight: bold;} .java5 .kw26 {color: #003399; font-weight: bold;} .java5 .kw27 {color: #003399; font-weight: bold;} .java5 .kw28 {color: #003399; font-weight: bold;} .java5 .kw29 {color: #003399; font-weight: bold;} .java5 .kw30 {color: #003399; font-weight: bold;} .java5 .kw31 {color: #003399; font-weight: bold;} .java5 .kw32 {color: #003399; font-weight: bold;} .java5 .kw33 {color: #003399; font-weight: bold;} .java5 .kw34 {color: #003399; font-weight: bold;} .java5 .kw35 {color: #003399; font-weight: bold;} .java5 .kw36 {color: #003399; font-weight: bold;} .java5 .kw37 {color: #003399; font-weight: bold;} .java5 .kw38 {color: #003399; font-weight: bold;} .java5 .kw39 {color: #003399; font-weight: bold;} .java5 .kw40 {color: #003399; font-weight: bold;} .java5 .kw41 {color: #003399; font-weight: bold;} .java5 .kw42 {color: #003399; font-weight: bold;} .java5 .kw43 {color: #003399; font-weight: bold;} .java5 .kw44 {color: #003399; font-weight: bold;} .java5 .kw45 {color: #003399; font-weight: bold;} .java5 .kw46 {color: #003399; font-weight: bold;} .java5 .kw47 {color: #003399; font-weight: bold;} .java5 .kw48 {color: #003399; font-weight: bold;} .java5 .kw49 {color: #003399; font-weight: bold;} .java5 .kw50 {color: #003399; font-weight: bold;} .java5 .kw51 {color: #003399; font-weight: bold;} .java5 .kw52 {color: #003399; font-weight: bold;} .java5 .kw53 {color: #003399; font-weight: bold;} .java5 .kw54 {color: #003399; font-weight: bold;} .java5 .kw55 {color: #003399; font-weight: bold;} .java5 .kw56 {color: #003399; font-weight: bold;} .java5 .kw57 {color: #003399; font-weight: bold;} .java5 .kw58 {color: #003399; font-weight: bold;} .java5 .kw59 {color: #003399; font-weight: bold;} .java5 .kw60 {color: #003399; font-weight: bold;} .java5 .kw61 {color: #003399; font-weight: bold;} .java5 .kw62 {color: #003399; font-weight: bold;} .java5 .kw63 {color: #003399; font-weight: bold;} .java5 .kw64 {color: #003399; font-weight: bold;} .java5 .kw65 {color: #003399; font-weight: bold;} .java5 .kw66 {color: #003399; font-weight: bold;} .java5 .kw67 {color: #003399; font-weight: bold;} .java5 .kw68 {color: #003399; font-weight: bold;} .java5 .kw69 {color: #003399; font-weight: bold;} .java5 .kw70 {color: #003399; font-weight: bold;} .java5 .kw71 {color: #003399; font-weight: bold;} .java5 .kw72 {color: #003399; font-weight: bold;} .java5 .kw73 {color: #003399; font-weight: bold;} .java5 .kw74 {color: #003399; font-weight: bold;} .java5 .kw75 {color: #003399; font-weight: bold;} .java5 .kw76 {color: #003399; font-weight: bold;} .java5 .kw77 {color: #003399; font-weight: bold;} .java5 .kw78 {color: #003399; font-weight: bold;} .java5 .kw79 {color: #003399; font-weight: bold;} .java5 .kw80 {color: #003399; font-weight: bold;} .java5 .kw81 {color: #003399; font-weight: bold;} .java5 .kw82 {color: #003399; font-weight: bold;} .java5 .kw83 {color: #003399; font-weight: bold;} .java5 .kw84 {color: #003399; font-weight: bold;} .java5 .kw85 {color: #003399; font-weight: bold;} .java5 .kw86 {color: #003399; font-weight: bold;} .java5 .kw87 {color: #003399; font-weight: bold;} .java5 .kw88 {color: #003399; font-weight: bold;} .java5 .kw89 {color: #003399; font-weight: bold;} .java5 .kw90 {color: #003399; font-weight: bold;} .java5 .kw91 {color: #003399; font-weight: bold;} .java5 .kw92 {color: #003399; font-weight: bold;} .java5 .kw93 {color: #003399; font-weight: bold;} .java5 .kw94 {color: #003399; font-weight: bold;} .java5 .kw95 {color: #003399; font-weight: bold;} .java5 .kw96 {color: #003399; font-weight: bold;} .java5 .kw97 {color: #003399; font-weight: bold;} .java5 .kw98 {color: #003399; font-weight: bold;} .java5 .kw99 {color: #003399; font-weight: bold;} .java5 .kw100 {color: #003399; font-weight: bold;} .java5 .kw101 {color: #003399; font-weight: bold;} .java5 .kw102 {color: #003399; font-weight: bold;} .java5 .kw103 {color: #003399; font-weight: bold;} .java5 .kw104 {color: #003399; font-weight: bold;} .java5 .kw105 {color: #003399; font-weight: bold;} .java5 .kw106 {color: #003399; font-weight: bold;} .java5 .kw107 {color: #003399; font-weight: bold;} .java5 .kw108 {color: #003399; font-weight: bold;} .java5 .kw109 {color: #003399; font-weight: bold;} .java5 .kw110 {color: #003399; font-weight: bold;} .java5 .kw111 {color: #003399; font-weight: bold;} .java5 .kw112 {color: #003399; font-weight: bold;} .java5 .kw113 {color: #003399; font-weight: bold;} .java5 .kw114 {color: #003399; font-weight: bold;} .java5 .kw115 {color: #003399; font-weight: bold;} .java5 .kw116 {color: #003399; font-weight: bold;} .java5 .kw117 {color: #003399; font-weight: bold;} .java5 .kw118 {color: #003399; font-weight: bold;} .java5 .kw119 {color: #003399; font-weight: bold;} .java5 .kw120 {color: #003399; font-weight: bold;} .java5 .kw121 {color: #003399; font-weight: bold;} .java5 .kw122 {color: #003399; font-weight: bold;} .java5 .kw123 {color: #003399; font-weight: bold;} .java5 .kw124 {color: #003399; font-weight: bold;} .java5 .kw125 {color: #003399; font-weight: bold;} .java5 .kw126 {color: #003399; font-weight: bold;} .java5 .kw127 {color: #003399; font-weight: bold;} .java5 .kw128 {color: #003399; font-weight: bold;} .java5 .kw129 {color: #003399; font-weight: bold;} .java5 .kw130 {color: #003399; font-weight: bold;} .java5 .kw131 {color: #003399; font-weight: bold;} .java5 .kw132 {color: #003399; font-weight: bold;} .java5 .kw133 {color: #003399; font-weight: bold;} .java5 .kw134 {color: #003399; font-weight: bold;} .java5 .kw135 {color: #003399; font-weight: bold;} .java5 .kw136 {color: #003399; font-weight: bold;} .java5 .kw137 {color: #003399; font-weight: bold;} .java5 .kw138 {color: #003399; font-weight: bold;} .java5 .kw139 {color: #003399; font-weight: bold;} .java5 .kw140 {color: #003399; font-weight: bold;} .java5 .kw141 {color: #003399; font-weight: bold;} .java5 .kw142 {color: #003399; font-weight: bold;} .java5 .kw143 {color: #003399; font-weight: bold;} .java5 .kw144 {color: #003399; font-weight: bold;} .java5 .kw145 {color: #003399; font-weight: bold;} .java5 .kw146 {color: #003399; font-weight: bold;} .java5 .kw147 {color: #003399; font-weight: bold;} .java5 .kw148 {color: #003399; font-weight: bold;} .java5 .kw149 {color: #003399; font-weight: bold;} .java5 .kw150 {color: #003399; font-weight: bold;} .java5 .kw151 {color: #003399; font-weight: bold;} .java5 .kw152 {color: #003399; font-weight: bold;} .java5 .kw153 {color: #003399; font-weight: bold;} .java5 .kw154 {color: #003399; font-weight: bold;} .java5 .kw155 {color: #003399; font-weight: bold;} .java5 .kw156 {color: #003399; font-weight: bold;} .java5 .kw157 {color: #003399; font-weight: bold;} .java5 .kw158 {color: #003399; font-weight: bold;} .java5 .kw159 {color: #003399; font-weight: bold;} .java5 .kw160 {color: #003399; font-weight: bold;} .java5 .kw161 {color: #003399; font-weight: bold;} .java5 .kw162 {color: #003399; font-weight: bold;} .java5 .kw163 {color: #003399; font-weight: bold;} .java5 .kw164 {color: #003399; font-weight: bold;} .java5 .kw165 {color: #003399; font-weight: bold;} .java5 .kw166 {color: #003399; font-weight: bold;} .java5 .co1 {color: #666666; font-style: italic;} .java5 .co2 {color: #006699;} .java5 .co3 {color: #008000; font-style: italic; font-weight: bold;} .java5 .coMULTI {color: #666666; font-style: italic;} .java5 .es0 {color: #000099; font-weight: bold;} .java5 .br0 {color: #009900;} .java5 .sy0 {color: #339933;} .java5 .st0 {color: #0000ff;} .java5 .nu0 {color: #cc66cc;} .java5 .me1 {color: #006633;} .java5 .me2 {color: #006633;} .java5 span.xtra { display:block; } If you've ever used more than one programming language, you've probably found that - as you switch between them - there's usually some feature that you've left behind that you really miss. It could be a particular class, syntactic sugar, or language construct that you just can't do without. When I joined Zoom some 5+ years ago, I went from doing development primarily in Python and C# to doing development primarily in Java. One of the little things I missed from those languages was generators. Generators are a simple but powerful tool for creating iterators. They are written like regular functions but use a "yield" statement whenever they want to return data. Each time next() is called in your for-each loop, control passes to the generator and it resumes right where it left off - its local variables and execution state are automatically saved between calls. The generator returns control back to your loop when it "yields" the next value in the iteration. Using generators - like iterators - can confer some nice performance benefits. This performance boost is the result of the lazy (on-demand) generation of values, which translates to lower memory usage. Furthermore, we do not need to wait until all the elements have been generated before we start to use them. It's important to note that anything that can be done with generators can also be done with iterators. What makes generators so nice & compact is that the iterator(), hasNext() and next() methods are all created automatically for you. This helps make generators easier to write and much clearer than an iterator-based approach. You don't have to write a ton of boilerplate and a mini state machine just to keep track of your progress. By now, you've probably picked up that Java doesn't have generators. Worse still, Java (the language, not the JVM) doesn't have built-in support for continuations - a useful building block for implementing generators (though there are some 3rd-party add-ons like Apache Javaflow that implement them via bytecode manipulation). Fortunately, not all is lost. A bit of Googling turned up an excellent blog post by Jim Blackler who had implemented a Yield/Return framework in Java. After ironing out a few bugs in the framework (and passing those patches back to Jim), we at Zoom adopted it for use in our production environment. Jim's framework is based on a traditional producer/consumer model. In it, two threads effectively do the work of one. Control passes between the "worker" thread (which computes your iteration's values) and the managing thread (which implements the java.util.Iterator logic). Each invocation of "Iterator.next()" causes the worker thread to wake up and compute the next result, which it puts into a Java SynchronousQueue. The worker thread goes back to sleep and the manager thread pops the queue, returning the newly-computed value to your "for" loop. By itself, Jim's framework got us lazy-computation and a more natural programming model than straight Java Iterators, which was a huge improvement. But much like iterators, it required writing a lot of boilerblate code. Writing anything in Java requires writing a lot of boilerplate, but we strive to keep that to a minimum. To solve this, we wrote a really simple "Generator" base class that is easily extensible. It implements the Iterable interface, so you can use Generators wherever you would use a Java 1.5-style "for-each" loop. All it requires is that you implement your business logic inside of a "run()" method, return values via its "yield" method, and it figures out the rest for you. I've included the framework (both Jim's and Zoom's code) for download here, and I've included some illustrative code samples below. In the following examples, you'll see how easy it is to implement Python's numeric range() function and its string-reversing function using generators, just like the core Python library does. You can read up on the Python examples and more on generators here. -Dominic Lachowicz, Director of Core Development
static Iterable<Integer> range(int hi) { return range(0, hi); } static Iterable<Integer> range(int lo, int hi) { return range(lo, hi, 1); } static Iterable<Integer> range(final int lo, final int hi, final int step) { return new Generator<Integer>() { @Override protected void run() { for (int i = lo; i != hi; i += step) { yield(i); } } }; } static Iterable<Character> reverse(final CharSequence string) { return new Generator<Character>() { @Override protected void run() { for (int i : range(string.length() - 1, -1, -1)) { yield(string.charAt(i)); } } }; } static Iterable<Integer> firstn(final int n) { return new Generator<Integer>() { @Override protected void run() { int num = 0; while (num < n) { yield(num); num += 1; } } }; }
Email this to someoneShare on Google+0Share on Facebook0Tweet about this on Twitter0Share on LinkedIn0Share on Reddit0Share on TumblrDigg thisPin on Pinterest0
This entry was posted in Best Practices on by .

About The ZoomInfo Team

ZoomInfo has been a B2B data front-runner for more than a decade. We're constantly engineering technologies to make our business information second to none. ZoomInfo creates just-verified, detailed profiles of 95 million businesspeople and seven million businesses. We make our data available to you through powerful tools for lead generation, prospecting and recruiting.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>