Playing with Lambda Functions
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
[code language=”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);
}
}
[/code]
Create an Array of People
People Array
[code language=”java”]
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}));
[/code]
Print People
Pre Java8
[code language=”java”]
System.out.println("People");
for(Person p : people)
{
System.out.format(" + %s\n",p.toString());
}
System.out.println();
[/code]
Java 8
[code language=”java”]
people.forEach( (Person p) -> System.out.println(p));
[/code]
but we know that p is of type Person because our List is List<Person>
[code language=”java”]
people.forEach( p -> System.out.println(p));
[/code]
Sorting People
Pre Java8
[code language=”java”]
people.sort(new Comparator<Person>()
{
@Override
public int compare(Person p1, Person p2)
{
return p1.getAge().compareTo(p2.getAge());
}
});
[/code]
Using Lambdas
[code language=”java”]
people.sort((Person p1, Person p2) -> {
return p1.getAge().compareTo(p2.getAge());
});
[/code]
but we know that p is of type Person because our List is List<Person>
[code language=”java”]
people.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
[/code]
Modifying People
Removing People Under 18 Years
[code language=”java”]
System.out.println("\nRemove People with Age < 18");
people.removeIf(p -> p.getAge() < 18);
people.forEach(p -> System.out.format(" — %s\n",p));
[/code]
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
[code language=”java”]
people.stream()
.filter(p -> p.getAge() > 18 )
.sorted((p1,p2) -> p1.getName().compareTo(p2.getName()))
.forEach(p -> System.out.format(" — %s\n",p));
[/code]
Generate a Map of Number of People of Each Age
[code language=”java”]
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));
[/code]
Sort our countByAge Map by Age
[code language=”java”]
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()));
[/code]
Source Code
Full source code of a number of Lambda examples is below:
[code language=”java”]
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());
}
}
}
[/code]