Java8 has introduced Lambda Functions.
Whilst this looks a little overwhelming at first, it is a really useful feature.
Create our Person POJO
Person.java
/** * * @author johndunning */ public class Person { private String name; private Integer age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return String.format("Person[name=%s, age=%d]",name,age); } }
Create an Array of People
People Array
Person p1 = new Person("Jon Doe",21); Person p2 = new Person("Sally Doe",1); Person p3 = new Person("Mark Doe",2); Person p4 = new Person("Jane Doe",19); Person p5 = new Person("Fred Doe",22); Person p6 = new Person("Ian Doe",2); List<Person> people = new ArrayList<Person>(); people.addAll(Arrays.asList(new Person[]{p1,p2,p3,p4,p5,p6}));
Print People
Pre Java8
System.out.println("People"); for(Person p : people) { System.out.format(" + %s\n",p.toString()); } System.out.println();
Java 8
people.forEach( (Person p) -> System.out.println(p));
but we know that p is of type Person because our List is List<Person>
people.forEach( p -> System.out.println(p));
Sorting People
Pre Java8
people.sort(new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getAge().compareTo(p2.getAge()); } });
Using Lambdas
people.sort((Person p1, Person p2) -> { return p1.getAge().compareTo(p2.getAge()); });
but we know that p is of type Person because our List is List<Person>
people.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
Modifying People
Removing People Under 18 Years
System.out.println("\nRemove People with Age < 18"); people.removeIf(p -> p.getAge() < 18); people.forEach(p -> System.out.format(" --- %s\n",p));
Streams
If we want to apply several lambda functions to the same data we stream the data and apply each lamda function in turn.
Sort by Name and Filter Age > 18
people.stream() .filter(p -> p.getAge() > 18 ) .sorted((p1,p2) -> p1.getName().compareTo(p2.getName())) .forEach(p -> System.out.format(" --- %s\n",p));
Generate a Map of Number of People of Each Age
Map<Integer, Long> countByAge; countByAge = people.stream() .map(p -> p.getAge()) .collect(groupingBy(age -> age,counting())); countByAge.forEach((k,v) -> System.out.format(" --- Age: %d, Count: %d\n",k,v));
Sort our countByAge Map by Age
countByAge .entrySet() .stream() .sorted((e1,e2) -> e2.getValue().compareTo(e1.getValue())) .forEach(e -> System.out.format(" --- Count: %d, Age: %d\n",e.getValue(),e.getKey()));
Source Code
Full source code of a number of Lambda examples is below:
package java8examples.lambdas; import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; /** * * @author johndunning */ public class Person { private String name; private Integer age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return String.format("Person[name=%s, age=%d]",name,age); } // public static void printCollection(Collection<Person> people) { System.out.println("People"); for(Person p : people) { System.out.format(" + %s\n",p.toString()); } System.out.println(); } public static void sort1(List<Person> people) { people.sort(new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getAge().compareTo(p2.getAge()); } }); printCollection(people); } public static void sort2(List<Person> people) { people.sort((Person p1, Person p2) -> { return p1.getAge().compareTo(p2.getAge()); }); printCollection(people); } public static void sort3(List<Person> people) { people.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge())); printCollection(people); } public static void main(String[] args) { Person px1 = new Person("Jon Doe",21); Person px2 = new Person("Sally Doe",1); Person px3 = new Person("Mark Doe",2); Person px4 = new Person("Jane Doe",19); Person px5 = new Person("Fred Doe",22); Person px6 = new Person("Ian Doe",2); List<Person> people = new ArrayList<Person>(); people.addAll(Arrays.asList(new Person[]{px1,px2,px3,px4,px5,px6})); printCollection(people); sort1(people); sort2(people); sort3(people); System.out.println("\nSorted By Name"); people.sort((p1,p2) -> p1.getName().compareTo(p2.getName())); people.forEach(p -> System.out.format(" --- %s\n",p)); System.out.println("\nSorted By Age"); people.sort((p1,p2) -> p1.getAge().compareTo(p2.getAge())); people.forEach(p -> System.out.format(" --- %s\n",p)); System.out.println("\nRemove People with Age < 18"); people.removeIf(p -> p.getAge() < 18); people.forEach(p -> System.out.format(" --- %s\n",p)); people.addAll(Arrays.asList(new Person[]{px2,px3,px6})); System.out.println("\nSorted by Name and Filter Age > 18"); people.stream() .filter(p -> p.getAge() > 18 ) .sorted((p1,p2) -> p1.getName().compareTo(p2.getName())) .forEach(p -> System.out.format(" --- %s\n",p)); System.out.println("\nSorted by Name and Filter Age < 18"); people.stream() .filter(p -> p.getAge() < 18 ) .sorted((p1,p2) -> p1.getName().compareTo(p2.getName())) .forEach(p -> System.out.format(" --- %s\n",p)); System.out.println("\nSorted Names of all People >= 18"); people.stream() .filter(p -> p.getAge() > 18) .map(p -> p.getName()) // we now have the name on the stream and not the person .sorted() // sort the stream (i.e. the name .forEach(p -> System.out.format(" --- %s\n",p)); System.out.println("\nNumber of People of each age"); Map<Integer, Long> countByAge; countByAge = people.stream() .map(p -> p.getAge()) .collect(groupingBy(age -> age,counting())); countByAge.forEach((k,v) -> System.out.format(" --- Age: %d, Count: %d\n",k,v)); System.out.println("\nNumber of People of each age sorted by Count"); countByAge = people.stream() .map(p -> p.getAge()) .collect(groupingBy(age -> age,counting())); countByAge .entrySet() .stream() .sorted((e1,e2) -> e2.getValue().compareTo(e1.getValue())) .forEach(e -> System.out.format(" --- Count: %d, Age: %d\n",e.getValue(),e.getKey())); System.out.println("Every .foreach in this file"); Pattern pattern = Pattern.compile(".*forEach.*"); try(BufferedReader br = Files.newBufferedReader(Paths.get("src/java8examples/lambdas/Person.java"))) { br.lines() .map(line -> pattern.matcher(line)) .filter(matcher -> matcher.find()) .map(matcher -> matcher.group(0).trim()) .forEach(s -> System.out.println(s)); } catch(IOException e) { System.out.println(e.getMessage()); } } }