Understand the functional style

The functional style of programming was introduced in Java 8. It's quite different from previous forms of Java programming, and the syntax seems strange when you first see it.

If you've never used functional programming in Java before, you should:

After a few days, functional programming will seem natural.

The basic concepts are:

To understand the spirit of functional programming, you need to know that it works best with what you might call pure functions:

It's also useful to note that, in comparison with regular programming, functional programming:

Example

Here's a quick example of what functional programming looks like in Java.

//these methods are commonly used with streams
import static java.util.stream.Collectors.*;

import java.util.Collection;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.stream.Stream;

/**
 Example run:

  Lightest unstable element:
   Technetium
  Heavier than gold:
   [Pb, Pu, Fm]
  Heavier than gold and unstable:
   [Pu, Fm]
  Sum of protons, all elements heavier than gold:
   276
  Done.
*/
public final class PeriodicTable {
  
  public static void main(String... args) {
    PeriodicTable pt = new PeriodicTable();
    
    //hard-coded to one specific policy
    pt.findLightestUnstableElement();
    
    //here, can pass in different predicates to filter by
    Predicate<Atom> heavierThanGold = atom -> atom.numProtons > Atom.Au.numProtons;
    log("Heavier than gold:", " " + pt.filter(heavierThanGold));

    Predicate<Atom> heavierThanGoldUnstable = (
        atom -> atom.numProtons > Atom.Au.numProtons && 
        atom.isAlwaysUnstable
    );
    log("Heavier than gold and unstable:", " " + pt.filter(heavierThanGoldUnstable));
    
    //here, pass a predicate and a way of reducing an Atom to an int
    //(this is contrived; but you get the idea)
    ToIntFunction<Atom> sumProtons = atom -> atom.numProtons; 
    log(
      "Sum of protons, all elements heavier than gold:", 
      " " + pt.filterAndSum(heavierThanGold, sumProtons), "Done."
    );
  }

  /**
   Find the lightest Atom that's always unstable.
   A very specific policy! Not a flexible method.
  */
  void findLightestUnstableElement(){
    Optional<Atom> answer = Stream.of(Atom.values())
      .filter(Atom::isAlwaysUnstable)
      .max((a,b) -> b.numProtons.compareTo(a.numProtons))
    ;
    answer.ifPresent(atom -> log("Lightest unstable element:", " " + atom.getName()));
  }
  
  /** Filter the Atoms somehow, and return them in a Collection. */
  Collection<Atom> filter(Predicate<Atom> predicate){
    return Stream.of(Atom.values())
      .filter(predicate)
      .collect(toList()) //static import of Collectors!
    ;
  }
  
  /** 
   Filter the Atoms somehow, and summarize by turning each Atom into 
   an int of some sort, and then summing the int's. 
  */
  int filterAndSum(Predicate<Atom> predicate, ToIntFunction<Atom> summarizer){
    int result = Stream.of(Atom.values())
      .filter(predicate)
      .collect(summingInt(summarizer)) //static import of Collectors!
    ;
    return result;
  }

  /**
   Some data from the periodic table of the elements (incomplete!). 
  */
  enum Atom {
    H("Hydrogen", 1, false),
    Tc("Technetium", 43, true),
    Au("Gold", 79, false),
    Pb("Lead", 82, false),
    Pu("Plutonium", 94, true),
    Fm("Fermium", 100, true);
    private Atom(String name, Integer numProtons, Boolean isAlwaysUnstable){
      this.name = name;
      this.numProtons = numProtons;
      this.isAlwaysUnstable = isAlwaysUnstable;
    }
    Boolean isAlwaysUnstable() { return isAlwaysUnstable; }
    String getName() { return name;  }
    Integer getNumProtons() { return numProtons; }
    private String name;
    private Integer numProtons;
    private Boolean isAlwaysUnstable;
  }
  
  private static void log(Object... msgs){
    Stream.of(msgs).forEach(System.out::println);
  }
} 

See Also :
Beware forEach terminals