java 8 lambdas from the nyc java meetup

I really liked the Java 8 Lambda talk from yesterday evening’s meetup so I’m blogging about it.  I like lambdas for the same reasons I like regular expressions – so much power and clarity!   The speaker was Timothy Fagan from Lab 49.  Photos of most of the slides are on the meetup website.  (not sure if you have to be a member of the meetup to view the pictures.)  Ok, here’s what I learned.  There are many blog posts on lambdas better than mine like the “Everything about Java 8” one.  I’m blogging anyway to solidify my understanding.

Where development is up to

  • Feature complete now.
  • General Availability March 2014.
  • Oracle delayed Java 8 date so lambdas would be included

Where we came from

  • Java has always had functors (objects that are classes)
  • Java 1.0 – could create classes to be functors – for example Runnable interface with run method
  • Java 1.1 invented anonymous inner classes  – complexity, performance issues (megamorphic call size or stack?)
Syntax
General case:
  • (paramList) -> expression | { statements}

Special case for single parameter: (Can leave out parens if one param. Need parens if zero params)

  • param -> expr | { stmt }
The return type is expr or return type of stmt.  stmt can return void if no return value
Examples
Uses signatures and return type to match new thread sig. This conforms to Runnable interface – returns void
  • new Thread(() -> System.out.println(“foo”))
Uses type inference to determine types of a and b
  • words.sort ((a,b) -> a.length() – b.length())

Only invokes lambada expression if logger set to right level.  This is a new interface that returns String

  • Logger.finest (()-> f.toString())
Only does expensive call if key not already in map:
  • map.computeIfAbsent(1234444, number-> getObjectFromDB())
Cast tells Java they are strings.  Interesting:  First time in Java you can have an object that will require a cast in order to compile when assigned to object.  May need to cast if ambiguous which constructor it uses

  •  Comparator c = (Comparator<String>) (a,b) -> a.length() – b.length().
General
  • Oracle combed thru java api looking for opportunities to use lambada expressions
  • Currently error messages are confusing. Builds on wildcard confusing messages
  • Can use lambda epressions in code you write if interface with a single method
  • A lambda is like a method that you dont know the name of on the class you are coding
    Foo..lambda$0 – class and method
    foo$$Lambda$1.methodYouCalled – link from your class to lambda – synthetic method – can’t view source
  • @Functional – requires interface has only one interface so can use as lambd
  • Can build own currying. Need to read about it – went over my head
  • Intellij idea community edition already supports lambdas
  • Jdk8.java.net has javadoc
 Scope
  • Lambdas are scoped in “this” scope not an anonymous inner class
  • System.out.println(this) prints current method name. Gives error if try in static method
  • Can refer to local var of param without having to use final keyword unlike anonymous inner classes  Still needs to be effectively final. Cant reassign after lambda expression. Compiler will catch you if you try to assign it.
  • Local vars are “caputred” which requires a new lambda to be created each time. Noncapturing lambda expressions will reuse instances. If not capturing, don’t need to worry about heap/garbage collector.
  • “this” refers to the point of creation of the lambda expression.  Not necessarily the current class (if passed around). Has some characteristics of a closure, but not all characteristics of closures
Limitations
  • Cannot break or continue outside of lamdba expression but can do so within block of statements in lambda
  • Cannot access non effectively final variables
  • Cannot implement abstract classes even single abstract method (SAM) abstract classes. Must use interfaces.
  • Exceptions in a lambda handled as per anonymous inner classes . A pain if functional interface does not throw exception. Would need a try catch to convert it.
Method References
These are all equivalent:
  • names.forEach(s -> sop)
  • names. ForEach(System.out::println) – uses method references – this is println on a specific object (system.out)
  • Static final Consumer PRNT =  System.out::println; names.forEach(PRINT)
Consumer has apply method of type T. So it can infer to pass forEach param to println. Can be more complex. Can have Printstream::println in which case must pass object to call println on as well.
Chaining with Streams
Stream.of(a,b,c).peek(a->sop)anyMatch(a->a.equals(r))
  • Peek doesn’t alter state. Can insert any where in chain to debug what is going on in stream
  • AnyMatch checks if any are true.    (The presenter wasn’t sure off the top of his head if it is a short circuit operator.  I just checked; it is)
  • AnyMatch lambda must create each time called because r is a variable so caputring. Peek lambda only created once. Don’t know if performance hit enough to worry about but suspect not. And even if a problem now just in time compiler will probably optimize it by ship date
Stream is a one time provider of values. May create lazily on demand. Permits for infinite streams – don’t try to count on one of those!  Examples:
  • Arrays.stream()
  • BufferedReader.lines()
  • IntStrem.range(0,100)
  • IntStream.ints().limit(100)
  • Random.ints() – infinite stream
  • ZipFile.stream()
Methods on Stream
Intermediate – defers execution.  Does not execute until need to.  That way can optimize if don’t need all values
  • Map , reduce, flatmap, mapTo
  • Filter, substream, limit, sorted, distinct (substream means skip first x)
  • Peek, parallel
Terminal – must be at end of chain
  • ForEach, count, min, max, sum (only on numeric streams)
  • AllMatch, anyMatch, noneMatch
  • FindFirst, findAny
  • Collect – collect data from stream and return something that isn’T a stream such as map of lists, min, collection or join strings with delimiter
java.util.function package
  • Function<T,R>  t input, r output
  • Predicate <T> – t input, boolean output
  • Consumer <T> a t input no output
  • Supplier <T> – no input, t output
  • BinaryOperator<T> – take two T’s an inout and returns one as output
and many more
Options
  • Optional<Long> o -returns an object that may or may not hold a long
  • o.get() to actually get the long
  • Throws exception if no value
  • o.ifPresent to check if there
  • o.orElse(a) – returns from get or hard coded value if not
Use carefully
New patterns
  • Try to pass streams around   Don’t need to keep converting to list.  Limitations on streams are not being able to go backwards and forwards and that can’t serialize.
  • Can now put static methos on interface
    comparator.comparing(lambda). ThenComparing(Comaprator.naturalOrder())

Multi core

B -> b.parallel().count() – can take advantage of multiple cores – can chop up work – uses work stealing – breaks up into smaller pieces so caget work from busy neighbors

Creating a UML diagram with Eclipse Papyrus

Yesterday, I upgraded my Eclipse to Kepler. I needed to create a UML class diagram and decided to try out Papyrus – an Eclipse incubator project.  It wasn’t as straightforward as I expected so blogging about what to do and what not to do.  Class_Diagram

I think this project needs more documentation (and a few more features) before using it seriously.  Luckily, my diagram was trivial.  In fact, it was so trivial, I decided to switch to PowerPoint (or in my clas – Open Office Drawing)

Regardless, here’s what I learned before giving up on it.

Creating a diagram

  1. File > New > Papyrus Project
  2. Enter project name
  3. Click NEXT (Do not click Finish.  I was unable to use papyrus > new diagram > create new class diagram when I didn’t create one right away)
  4. UML
  5. Click next
  6. Enter diagram name and click “UML Class Diagram”
  7. Click finish

Adding a class

  1. Switch to the Papyrus Perspective
  2. Drag a “Class” node from the palette view at right
  3. Click the “Class 1” name once and then type the name of your class.  (Do not double click the class box as it opens a hyberlink view.  Do not click the class box and expect to type in it
  4. Drag an ‘Operation” node from the palette at right onto your class
  5. Click “Operation 1” and type the name of your method (Do not add an operation to the model explorer view at left as it will not show up in the diagram)

Preferences

In the Eclipse preferences, you can set a number of view preferences.  They are extremely granular.  For example, I wanted to hide the fourth “section” of the UML diagram showing just class name, attributes and operations.  To do this, I had to:

  1. Preferences > Papyrus > Diagrams > PapyrusUMLClassDiagram > Class Node
  2. Uncheck “show compartment” in NestedClassifierComponent section
  3. Preferences > Papyrus > Diagrams > PapyrusUMLClassDiagram > Interface Node
  4. Uncheck “show compartment” in NestedClassifierComponent section
  5. Delete my diagram and create a new one as I could not figure out how to get preferences to take effect on an existing diagram.

What still puzzles me

There has to be a way to refresh the graphical view to sync with the model explorer and update based on workspace preferences.

eclipse kepler (4.3) on a mac

Getting started

When going to the Eclipse site, I was greeted with a cool book looking page about Kepler.  Who Kepler is, what’s new, the link to download, etc.  kepler-book

Choosing a package

Eclipse has a nice chart comparing the features in each edition.  I’m excited to see git and maven got promoted to the Java EE edition.  In fact the Java EE edition is *almost* a superset of the Java edition now.  The download is 50MB bigger than last time.  And since Verizon wired the basement for FIOS but not any individual apartments yet, this means 30-45 minute download.  Now that I have the file eclipse-jee-kepler-R-macosx-cocoa-x86_64.tar, I can start.

Installing on A Mac was a small adventure

I did the usual of untarring and copying the eclipse folder into Applications.  I got an error: “Eclipse” is damaged and can’t be opened.  You should move it to the Trash.

I found a command here to get Gatekeeper to allow it:  xattr -d com.apple.quarantine /Applications/eclipse/Eclipse.app

Then I got: Failed to load the JNI shared library /Library/java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/bin/../jre/lib/client/libjvm.dylib

I was on Java 7 update 17.  I updated to update 25, but that didn’t help.  I then tried using a launch startup script per the bug report.  Note that I needed to change two bolded lines to point to my install location.

#!/bin/bash
/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/bin/java \
-Djava.library.path=<strong>/Applications/eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.200.v20130521-0416/eclipse_1507.so</strong> \
-Xms512m \
-Xmx2048m \
-Xdock:icon=../Resources/Eclipse.icns \
-XstartOnFirstThread \
-Dorg.eclipse.swt.internal.carbon.smallFonts \
-XX:MaxPermSize=256m \
-jar /Applications/eclipse/plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar \
-os macosx \
-ws cocoa \
-arch x86_64 \
-showsplash \
-name Eclipse \
--launcher.appendVmargs \
-debug

It sounds like this will be fixed in Kepler SR  1.  In the meantime I renamed my script to end in .command so I can open it via the applications finder window (nice tip)

First Impressions

Since some of the plugins I was using are now built in and others I don’t use anymore (that I installed over the past year), I decided not to import my plugins from a previous installation and start anew.  It’s easy enough to install from the marketplace.

The significant plugins I use:

Plugin Purpose
Mongrel Tomcat integration supporting Tomcat 7.  (The version of Sysdeo I was using seems to have had that too but at least Mongrel looks more active.) Used the Sysdeo source code and forked it since Sysdeo isn’t getting updates anymore.
Ecl Emma Code coverage
PMD and FindBugs Static analysis
Subversive To access Subversion repositories
Groovy/Grails Tool Suite Groovy project/editor and console
Eclipse Memory Analyzer For finding memory leaks – must use update site rather than marketplace
Freemarker IDE Freemarker syntax highlighting and macro assistance.  Note that it is listed under the JBoss Tool Project.
Papyrus UML editor – under install new software > kepler > papyrus  (I don’t recommend Papyrus at this time.)
Python Python plugin/perspective

What excites me

  1. Mylyn connector improvements (for code review)
  2. Remove type arguments after content assist – this happened just often enjoy to be annoying
  3. IDE support for JUnit Assumptions

What frustrates me

  1. The mess about Mac support for Kepler.  It’s annoying launching from the command line (or even a command).