Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * In the following ignore the <code>if(Math.random()<0)</code>.
- *
- * This is only to make the code compile since you cannot have useless <code>return</code>
- * statements in Java code, and because it looks conditional to JavaC it shuts up and lets
- * this compile,
- */
- import java.util.List;
- @FunctionalInterface
- interface ItemWriter<T>{
- void write(T t) throws Exception;
- }
- class Scratch {
- public ItemWriter<List<?>> foo(){
- /*
- * This is our original code that makes an anonymous class that implements the ItemWriter
- * interface.
- */
- if(Math.random()<0)
- return new ItemWriter<>() {
- @Override
- public void write( List<?> items) throws Exception {
- for (Object row : items) {
- System.out.println(row.toString());
- }
- }
- };
- /*
- * Because we know from the method signature that the method that the type is ItemWriter,
- * we know that the lambda is an implementation of it's write() method so we don't need
- * to write down the name of the class or it's method name, it's obvious.
- *
- * **IMPORTANT**
- * This only works because ItemWriter is an interface, and that it is an interface with
- * exactly one method. You can enforce that an interface stay that way by adding the
- * annotation @FunctionalInterface. You will hear these interfaces called "S.A.M.s"
- * (aka "SAMs) because they have a "Single Abstract Method".
- *
- * (PS - all methods on an interface are "abstract". You can explicitly write "abstract"
- * on the method declarations, but it doesn't change anything.)
- */
- if(Math.random()<0)
- return (List<?> items) -> {
- for (Object row : items) {
- System.out.println(row.toString());
- }
- };
- /*
- * Because the type is not ambiguous we do not need to specify it as it's obvious from the
- * interface.
- */
- if(Math.random()<0)
- return (items) -> {
- for (Object row : items) {
- System.out.println(row.toString());
- }
- };
- /*
- * Because there is only one argument, we don't need the parentheses, they are obvious.
- */
- if(Math.random()<0)
- return items -> {
- for (Object row : items) {
- System.out.println(row.toString());
- }
- };
- /*
- * We are doing the same thing to ever item on the list. There is a method on list that
- * is available for exactly this use case. When you use this method you know instantly
- * and for sure that every item in the list is being treated the same.
- *
- * It takes a lambda, and applies it to every on the list.
- */
- if(Math.random()<0)
- return items -> {
- items.forEach( row -> {
- System.out.println(row.toString());
- }
- );
- };
- /*
- * For historical reasons, whet they added streams to Java they didn't add them to the
- * classes themselves, but onto a Stream object that comes off of the classes that you
- * access by calling stream().
- *
- * forEach() is the only exception. They added it to the classes themselves because it
- * is the most commonly used so for covenience it's added onto List, Set and a few
- * others directly. But to do a bit more clean up we will need a few more items off of
- * Stream class, so we need to call the stream() method.
- */
- if(Math.random()<0)
- return items -> {
- items.stream().forEach( row -> {
- System.out.println(row.toString());
- }
- );
- };
- /*
- * In the method we have two things going on at the same time that are actually two
- * separate stages: 1) coverting the row to a String, and 2) writing it out to console.
- *
- * Lets separate them, which will make it clearer that the conversion happens first.
- */
- if(Math.random()<0)
- return items -> {
- items.stream()
- .forEach( row -> {
- System.out.println(row.toString());
- });
- };
- /*
- * In the method we have two things going on at the same time that are actually two
- * separate stages: 1) converting the row to a String, and 2) writing it out to console.
- *
- * Let's separate them, which will make it clearer that the conversion happens first.
- */
- if(Math.random()<0)
- return items -> {
- items.stream()
- .forEach( row -> {
- final String rowString = row.toString();
- System.out.println( rowString );
- });
- };
- /*
- * Stream has a method for converting/transforming values; it is called "map()".
- *
- * It takes a lambda and applies it to each item it gets passed to it before
- * it passes it on down the line.
- *
- * Intuitively, it says you are mapping over values from one type to another.
- * This makes code easier to read because when the reader sees map they understand
- * why you are calling the method.
- */
- if(Math.random()<0)
- return items -> {
- items.stream()
- .map( row -> row.toString() )
- .forEach( rowString -> {
- System.out.println( rowString );
- });
- };
- /*
- * If all you are doing in a lambda is taking an object and calling a method on it, then
- * we can use a "method reference" which is a shortcut for exactly this kind of lambda.
- *
- * Just give the name of the class that defined that method originally and then "::" and
- * then the name of the method.
- */
- if(Math.random()<0)
- return items -> {
- items.stream()
- .map( Object::toString )
- .forEach( rowString -> {
- System.out.println( rowString );
- });
- };
- /*
- * Likewise, if all you are doing in a lambda is taking it and passing it to some method, then
- * we can use the same shortcut. If there is ever any ambiguity about what these shortcuts are
- * supposed to do, then the compiler will fail, and you will have to use the more verbose option.
- */
- if(Math.random()<0)
- return items -> {
- items.stream()
- .map( Object::toString )
- .forEach( System.out::println );
- };
- /*
- * There is a minor cleanup here. If there is only one line in a lambda, then we can omit the
- * outer parentheses as they are implied and obvious.
- */
- if(Math.random()<0)
- return items ->
- items.stream()
- .map( Object::toString )
- .forEach( System.out::println )
- ;
- /*
- * The code is now short enough to comfortably fit and read on one line.
- */
- if(Math.random()<0)
- return items -> items.stream().map( Object::toString ).forEach( System.out::println );
- /*
- * This code now reads much cleaner than the original. It says:
- *
- * "This builds a thinger (if I really care I can look it up from the method declaration just
- * on top) that takes some items, converts them to strings, and then prints them out."
- *
- * There is no additional boilerplate to distract you or hide so bit of important code you might miss.
- *
- * The order of events happens exactly in the order you read them, left-to-right.
- */
- if(Math.random()<0)
- return items -> items.stream().map( Object::toString ).forEach( System.out::println );
- /*
- * If we were processing a lot of things we could easily multi-thread this for o easy
- * performance boost by using a ParallelStream instead by calling parallelStream() !
- *
- * Now each stage gets handled in it's own threaded, grabbing the next item while the
- * rest of them continue being processed elsewhere.
- */
- if(Math.random()<0)
- return items -> items.parallelStream().map( Object::toString ).forEach( System.out::println );
- // we need an unconditional return statement to make JavaC happy.
- return null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement