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