Java 8 Random Notes


The ultimate Java 8 list

Java 8 Features—The Ultimate Guide


How to back-translate Java 8 lambda- and stream expressions

Sometimes, it's useful to cut through the crap. Highlighted is the basic Java 8 data, in some cases, also the pre-Java 8 construct.

First, list traversal...

String[] PLAYERS = { "Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer",
                "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin del Potro" };

List< String > players =  Arrays.asList( PLAYERS );

// old way of traversing:
for( String player : players )
  System.out.print( player + "; " );

// new way using lamba expression:
players.forEach( ( player ) -> System.out.print( player + "; " ) );

// alternate double-colon operator:
players.forEach( System.out::println );

Anonymous innerclasses...

button.setOnAction( new EventHandler< ActionEvent >()
{
  @Override
  public void handle( ActionEvent event )
  {
    System.out.println( "Hello world!" );
  }
});

// with lambda expression:
new Thread( () -> System.out.println( "Hello world!" ) ).start();

Second example of innerclass...

Runnable race1 = new Runnable()
{
  @Override
  public void run()
  {
    System.out.println( "Hello world!" );
  }
};

// with lambda expression:
Runnable race2 = () -> System.out.println( "Hello world!" );

// run both:
race1.run();
race2.run();

Sorting collections...

String[] PLAYERS = { "Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer",
                "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin del Potro" };

// sort using anonymous innerclass:
Arrays.sort( PLAYERS, new Comparator< String >()
{
  @Override
  public int compare( String s1, String s2 )
  {
    return s1.compareTo( s2 );
  }
});

// sort by name using lambda expression:
Comparator< String > sortByName = ( String s1, String s2 ) -> ( s1.compareTo( s2 ) );

Arrays.sort( PLAYERS, sortByName );
// or:
Arrays.sort( PLAYERS, ( String s1, String s2 ) -> ( s1.compareTo( s2 ) ) );

Using lambda expressions and streams...

public class Person
{
  private String firstName, lastName, job, gender;
  private int salary, age;

  public Person( String firstName, String lastName, String job, String gender, int age, int salary )
  {
    this.firstName = firstName;
    this.lastName  = lastName;
    this.gender    = gender;
    this.age       = age;
    this.job       = job;
    this.salary    = salary;
  }
  ...
}

// later code constructing lists:
List< Person > javaProgrammers = new ArrayList<>()
{
  {
    add( new Person( "Elsdon",  "Jacob",    "Java programmer", "male",   43, 2000 ) );
    add( new Person( "Tamsen",  "Brittany", "Java programmer", "female", 23, 1500 ) );
    add( new Person( "Floyd",   "Donny",    "Java programmer", "male",   33, 1800 ) );
    add( new Person( "Cindy",   "Jonie",    "Java programmer", "female", 32, 1600 ) );
    add( new Person( "Vere",    "Hervey",   "Java programmer", "male",   22, 1200 ) );
    add( new Person( "Maude",   "Jaimie",   "Java programmer", "female", 27, 1900 ) );
    add( new Person( "Shawn",   "Randall",  "Java programmer", "male",   30, 2300 ) );
    add( new Person( "Jayden",  "Corrina",  "Java programmer", "female", 35, 1700 ) );
    add( new Person( "Palmer",  "Dene",     "Java programmer", "male",   33, 2000 ) );
    add( new Person( "Addison", "Pam",      "Java programmer", "female", 34, 1300 ) );
  }
};

List< Person > phpProgrammers = new ArrayList<>()
{
  {
    add( new Person( "Jarrod",   "Pace",     "PHP programmer", "male",   34, 1550 ) );
    add( new Person( "Clarette", "Cicely",   "PHP programmer", "female", 23, 1200 ) );
    add( new Person( "Victor",   "Channing", "PHP programmer", "male",   32, 1600 ) );
    add( new Person( "Tori",     "Sheryl",   "PHP programmer", "female", 21, 1000 ) );
    add( new Person( "Osborne",  "Shad",     "PHP programmer", "male",   32, 1100 ) );
    add( new Person( "Rosalind", "Layla",    "PHP programmer", "female", 25, 1300 ) );
    add( new Person( "Fraser",   "Hewie",    "PHP programmer", "male",   36, 1100 ) );
    add( new Person( "Quinn",    "Tamara",   "PHP programmer", "female", 21, 1000 ) );
    add( new Person( "Alvin",    "Lance",    "PHP programmer", "male",   38, 1600 ) );
    add( new Person( "Yvonne",   "Shari",    "PHP programmer", "female", 40, 1800 ) );
  }
};

And now, iterate those lists...

System.out.println( "Show programmers names:" );

// traditional method:
for( Person programmer : javaProgrammers )
  System.out.printf( programmer.getFirstName() + ", " + programmer.getLastName() +"; " );
for( Person programmer : phpProgrammers )
  System.out.printf( programmer.getFirstName() + ", " + programmer.getLastName() +"; " );

// using streams notation:
javaProgrammers.forEach( ( p ) -> System.out.printf( p.getFirstName() + ", " + p.getLastName() + "; " );
phpProgrammers.forEach( ( p ) -> System.out.printf( p.getFirstName() + ", " + p.getLastName() + "; " );
System.out.println( "Increase salary by 5% to programmers:" );

// traditional method:
for( Person programmer : javaProgrammers )
{
  int salary = programmer.getSalary();
  int bump   = salary / 100 * 5;
	programmer.setSalary( salary + bump );
}

for( Person programmer : phpProgrammers )
{
  int salary = programmer.getSalary();
  int bump   - salary / 100 * 5;
	programmer.setSalary( salary + bump );
}

// using Consumer and forEach() method:
Consumer< Person > giveRaise = e -> e.setSalary( e.getSalary() / 100 * 5 + e.getSalary() );

javaProgrammers.forEach( giveRaise );
phpProgrammers.forEach( giveRaise );
System.out.println( "Show PHP programmers that earn more than $1,400:" )

// traditional:
for( Person programmer : phpProgrammers )
{
  if( programmer.getSalary() > 1400 )
  	System.out.printf( "%s %s; ", programmer.getFirstName(), programmer.getLastName() ) );
}

// using streams and filters:
phpProgrammers.stream()
          .filter( ( p ) -> ( p.getSalary() > 1400 ) )
          .forEach( ( p ) -> System.out.printf( "%s %s; ", p.getFirstName(), p.getLastName() ) );
System.out.println( "Show first 3 Java programmers:" );

// traditional:
int limit = 3;

for( Person programmer : javaProgrammers )
{
  if( limit-- > 0 )
    System.out.printf( "%s %s; ", p.getFirstName(), p.getLastName() ) );
  else
    break;
}

// using limit() method:
javaProgrammers.stream()
           .limit( 3 )
           .forEach( ( p ) -> System.out.printf( "%s %s; ", p.getFirstName(), p.getLastName() ) );
System.out.println( "Show first 3 women Java programmers:" );

// traditional:
int limit = 3;

for( Person programmer : javaProgrammers )
{
  if( programmer.getGender().equals( "female" ) )
  {
    if( limit-- > 0 )
      System.out.printf( "%s %s; ", p.getFirstName(), p.getLastName() ) );
    else
      break;
  }
}

// using Predicate:
Predicate< Person > genderFilter = ( p ) -> ( "female".equals( p.getGender() ) );
javaProgrammers.stream()
           .filter( genderFilter )
           .limit( 3 )
           .forEach( ( p ) -> System.out.printf( "%s %s; ", p.getFirstName(), p.getLastName() ) );
System.out.println( "Get Java programmers first name to String:" );

// traditional:
String firstNames = "";

for( Person programmer : javaProgrammers )
  firstNames += programmer.getFirstName() + " ; ";

firstNames = firstNames.subset( 0, firstNames.length() - 2 );

// Using stream(), map() and collect() methods:
String javaDevelopers = javaProgrammers.stream()
                             .map( Person::getFirstName )
                             .collect( joining(" ; " ) );

System.out.println( "Get Java programmers first name to Set:" );

// traditional:
List< String > firsts = new Set<>();

for( Person programmer : javaProgrammers )
  firsts.add( programmer.getFirstName() );

Set< String > firstNames = new HashSet< String >( firsts );

// Using stream(), collect() and map() methods:
Set< String > javaDevFirstName = javaProgrammers.stream()
                                    .map( Person::getFirstName )
                                    .collect( toSet() );
System.out.println( "Calculate total money spent for paying Java programmers:" );

// traditional way:
int totalSalary = 0;

for( Person programmer : javaProgrammers )
  totalSalary += programmer.getSalary();

// using parallel streams:
int totalSalary = javaProgrammers.parallelStream()
                         .mapToInt( p -> p.getSalary() )
                         .sum();

Methodology for understanding Java 8 method references
  1. Find the class (Person).
  2. Find the method (compareByAge()).
  3. Imply the arguments as passed by the calling method (Arrays.sort() accepts a comparator method taking arguments a, b, o1, o2, etc.)
  4. Note that, in IntelliJ IDEA, there is a decoration that, CTRL-clicked, will take you to the method that the lambda overrides:


Types of Java 8 method references

For example, the reference illustrated just above, of compareByAge() is a static method in the table here.

Reference type In code
to a static method ContainingClass::staticMethodName
to an instance method of an object containingObject::instanceMethodName
to an instance method of an arbitrary object of a particularly type ContainingType::methodName
to a constructor ClassName::new

Java 8 Optional

I'm not super excited about Optional.

I wrote C code for 25 years. I've written Java for more than a decade now. When null is returned, I find that meaningful, and I always have. I'd throw an informative exception (in the first example) if I were writing it today in my own code, but I'm completely down with checking for null. The verbiage of integrating an ontological check instead using Optional brings nothing but more to type to the table as far as I can see. I see this as a solution gone looking for a problem. The assertion that null has somehow been a mistake all these years is futile if not wrong-headed.

This is interesting; the title is very misleading because it's a very good "the emperor has no clothes" analysis: Nothing is better than the Optional type.