October 31, 2022

Supplier Functional Interface Java Examples

In this post we’ll see examples of java.util.function.Supplier functional interface.

Supplier functional interface represents an operation that accepts no argument and supplies a result. In Supplier interface there is one abstract method get() and there is no default or static interface method.

If you are writing a Lambda expression that needs a value returned then that lambda expression can be written as an implementation of Supplier built-in functional interface.

Supplier functional interface examples

1. If you want some random number to be generated, that can be implemented as get() method of Supplier interface.

import java.util.function.Supplier;

public class SupplierExample {
  public static void main(String[] args) {
    Supplier<Double> randomNoGen = () -> Math.random();
    System.out.println(randomNoGen.get());
    System.out.println(randomNoGen.get());
  }
}
Output
0.9507895772946557
0.11609076109430083

In the program statement; Supplier randomNoGen = () -> Math.random(); is the implementation of Supplier as a lambda expression. Since this implementation is an instance of a functional interface so assigned to variable of type Supplier.

When randomNoGen.get() method is called Java can infer from the context, due to “target typing”, where to look for the implementation of get() method.

2. If you want current date at several places in your application, you can implement it as a Supplier.

import java.time.LocalDate;
import java.util.function.Supplier;

public class SupplierExample {
  public static void main(String[] args) {
    Supplier<LocalDate> currDate = () -> LocalDate.now();
    System.out.println(currDate.get());
  }
}

3. Using it as a supplier of class object. If there is a class Employee then you can create objects of this class using Supplier interface.

public class Employee {
  private String name;
  private String dept;
  private int salary;
  Employee(){};
  Employee(String name, String dept, int salary){
    this.name = name;
    this.dept = dept;
    this.salary = salary;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getSalary() {
    return salary;
  }
  public void setSalary(int salary) {
    this.salary = salary;
  }
  public String getDept() {
    return dept;
  }
  public void setDept(String dept) {
    this.dept = dept;
  }
  @Override
  public String toString() {
    // TODO Auto-generated method stub
    return getName() + " " + getDept() + " " + getSalary();
  }
}
public class SupplierExample {
  public static void main(String[] args) {	
    // Invokes no-arg constructor
    Employee emp = getEmpObject(Employee::new);
    System.out.println(emp);
    // Invokes constructor with parameters
    emp = getEmpObject(() -> new Employee("David", "IT", 12000));
    System.out.println(emp);
  }

  public static Employee getEmpObject(Supplier<Employee> sup) {
    return sup.get();
  }
}

Supplier functional interface in JDK

Built-in functional interfaces are used extensively with in the JDK itself. In the Java Stream API there is a method generate() that takes Supplier as an argument.

generate(Supplier<T> s)- Returns an infinite sequential unordered stream where each element is generated by the provided Supplier.

We can use this method to generate a stream of random numbers.

public class SupplierExample {
  public static void main(String[] args) {	
    Stream.generate(()->Math.random()).limit(3).forEach(System.out::println);
  }
}
Output
0.17411307331904347
0.9293020926865666
0.9854950033297908

That's all for the topic Supplier Functional Interface Java Example. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 30, 2022

BiConsumer Functional Interface Java Examples

In this post we’ll see examples of Java BiConsumer functional interface.

BiConsumer functional interface represents an operation that accepts two arguments and returns no result. Abstract method in this functional interface is accept(T t, U u) and there is also one default method andThen(BiConsumer<? super T,? super U> after).

If you are writing a Lambda expression that needs two arguments and doesn’t return a value then that lambda expression can be written as an implementation of BiConsumer built-in functional interface.

BiConsumer functional interface example

1. In the example a Map is created and then entries of the Map are displayed. We’ll use lambda expression that implements the BiConsumer functional interface. Lambda expression you write implements the abstract method of the functional interface so in the case of BiConsumer functional interface, lambda expression is implementing the accept() method.

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class BiConsumerExample {
  public static void main(String[] args) {
    // Implementation
    BiConsumer<String, String> biCons = (K, V) -> 
          System.out.println("Key is- " +K + " Value is- " + V);
    Map<String, String> numMap = new HashMap<String, String>();
    numMap.put("1", "One");
    numMap.put("2", "Two");
    numMap.put("3", "Three");
    numMap.put("4", "Four");
    for(Map.Entry<String, String> entry : numMap.entrySet()) {
      // calling accept method
      biCons.accept(entry.getKey(), entry.getValue());
    }
  }
}
Output
Key is- 1 Value is- One
Key is- 2 Value is- Two
Key is- 3 Value is- Three
Key is- 4 Value is- Four

In the program, statement BiConsumer<String, String> biCons = (K, V) -> System.out.println("Key is- " +K + " Value is- " + V); is the implementation of BiConsumer as a lambda expression. Since it is an instance of a functional interface so assigned to variable of type BiConsumer.

Lambda supports "target typing" which infers the object type from the context in which it is used. When biCons.accept() method is called Java can infer from the context where to look for the implementation of accept() method.

2. Here is another example where add() and multiply() methods are implemented using BiConsumer interface.

public class BiConsumerExample {
  public static void main(String[] args) {
    // Implementation as add method
    BiConsumer<Integer, Integer> biConsAdd = (a, b) -> 
          System.out.println("Sum is- " + (a + b));
    // Implementation as multiplication method
    BiConsumer<Integer, Integer> biConsMul = (a, b) -> 
          System.out.println("Multiplication is- " + (a * b));

    biConsAdd.accept(5, 6);
    biConsMul.accept(5, 6);
  }
}
Output
Sum is- 11
Multiplication is- 30

BiConsumer functional interface andThen() method example

There is also a default method andThen() in BiConsumer interface.

BiConsumer<T,U> andThen(BiConsumer<? super T,? super U> after)- Takes another BiConsumer as argument and returns a composed BiConsumer that performs, in sequence, first the operation of the calling BiConsumer followed by the after operation.

In the previous example addition and multiplication are called in sequence for the same set of arguments. If that is the case then it can use the andThen() method.

public class BiConsumerExample {
  public static void main(String[] args) {
    // Implementation as add method
    BiConsumer<Integer, Integer> biConsAdd = (a, b) -> 
          System.out.println("Sum is- " + (a + b));
    // Implementation as multiplication method
    BiConsumer<Integer, Integer> biConsMul = (a, b) -> 
          System.out.println("Multiplication is- " + (a * b));
    //First add then multiply in sequence			
    biConsAdd.andThen(biConsMul).accept(5, 6);

    //biConsAdd.accept(5, 6);
    //biConsMul.accept(5, 6);
  }
}
Output
Sum is- 11
Multiplication is- 30

BiConsumer functional interface in JDK

These built-in functional interfaces are used extensively with in the JDK itself. One example of BiConsumer functional interface used quite often is when forEach() method is used to iterate a Map. In the Map interface there is a forEach() method that takes BiConsumer as an argument.

forEach(BiConsumer<? super K,? super V> action)- Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.

First example where we iterated a Map can be written more concisely using forEach().

public class BiConsumerExample {
  public static void main(String[] args) {
    Map<String, String> numMap = new HashMap<String, String>();
    numMap.put("1", "One");
    numMap.put("2", "Two");
    numMap.put("3", "Three");
    numMap.put("4", "Four");
    numMap.forEach( (K, V) -> System.out.println("Key is- " + K + " Value is- " + V));
  }
}
Output
Key is- 1 Value is- One
Key is- 2 Value is- Two
Key is- 3 Value is- Three
Key is- 4 Value is- Four

That's all for the topic BiConsumer Functional Interface Java Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 29, 2022

Java Consumer Functional Interface Examples

In this post we’ll see examples of Java Consumer functional interface which is one of the built-in functional interface.

Consumer functional interface represents an operation that accepts a single argument and returns no result. Abstract method in this functional interface is accept(T t) and there is also one default method andThen().

Consumer functional interface example

In the example a List of integer is created and then elements of the List are displayed.

we’ll use lambda expression that implements the Consumer functional interface. Lambda expression you write implements the abstract method of the functional interface so in the case of Consumer functional interface, lambda expression is implementing the accept() method.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {
  public static void main(String[] args) {
    Consumer<Integer> consumer = i -> System.out.println(i);
    List<Integer> numList = Arrays.asList(1, 2, 3, 4);
    for(Integer i : numList) {
      consumer.accept(i);
    }
  }
}
Output
1
2
3
4

Here this statement Consumer<Integer> consumer = i -> System.out.println(i + " "); is the implementation of Consumer as a lambda expression. Since the implementation is an instance of a functional interface so assigned to variable of type Consumer.

Lambda supports "target typing" which infers the object type from the context in which it is used. When consumer.accept() method is called Java can infer from the context where to look for the implementation of accept() method.

Consumer functional interface andThen() method example

There is also a default method andThen() in Consumer interface.

andThen(Consumer<? super T> after)- Takes another Consumer as argument and returns a composed Consumer that performs, in sequence, first the operation of the calling Consumer followed by the after operation.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {
  public static void main(String[] args) {
    // First Consumer
    Consumer<String> consumer = s -> System.out.print("Original String- " + s);
    // Adding another consumer using andThen()
    Consumer<String> consumerAfter = consumer.andThen(s ->  System.out.print(" " + s.toUpperCase() + "\n"));
    List<String> nameList = Arrays.asList("Delhi", "Bangalore", "Hyderabad", "Lucknow");
    for(String str : nameList) {
      consumerAfter.accept(str);
    }
  }
}
Output
Original String- Delhi DELHI
Original String- Bangalore BANGALORE
Original String- Hyderabad HYDERABAD
Original String- Lucknow LUCKNOW

Here first Consumer prints the passed value and second consumer prints the same value in upper case.

andThen() method is called on the instance of the first Consumer and its argument is the second consumer. When the accept() method is called on the instance of the second consumer it calls in sequence initially the first consumer and then second consumer.

Consumer functional interface in JDK

These built-in functional interfaces are used extensively with in the JDK too. One example of Consumer functional interface used quite often is when forEach() method is used to iterate a collection. Method forEach() takes Consumer as argument.

forEach(Consumer<? super E> action)- Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.

The examples shown above can be written more concisely using forEach().
public class ConsumerExample {
  public static void main(String[] args) {
    List<String> nameList = Arrays.asList("Delhi", "Bangalore", "Hyderabad", "Lucknow");
    nameList.forEach( s -> System.out.print(s + " "));
  }
}
Output
Delhi Bangalore Hyderabad Lucknow

That's all for the topic Java Consumer Functional Interface Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 28, 2022

Method Reference in Java

In the post Lambda expression in Java we have already seen how Lambda expression provides an instance of functional interface and implements the abstract method of the functional interface. Though sometimes, a lambda expression is used just to call an existing method. In those cases you can refer to the existing method by name using Method references in Java. Method reference is a compact and more readable lambda expressions for methods that already have a name.

For example consider the following lambda expression-

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.forEach((Integer a) -> System.out.println(a));

Here lambda expression is just calling an existing method which can be done using method reference making the code more readable and concise.

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.forEach(System.out::println);

Method reference also needs a target type

Java method reference can be termed as a special form of lambda expression as method reference also needs a target type context (a compatible functional interface) and it also creates an instance of functional interface just like lambda expression does. Which also means method reference can only be used for a single method.

Where these two differ is lambda expression can also provide implementation for an abstract method where as method reference refers to an existing method.

Java Method reference syntax

As we have already seen in the example a new double colon operator (::) is added in Java to be used with method reference.

Class or object that contains the method is on the left side of the double colon operator and the name of the method in on the right side of the operator.

Kinds of Method References

There are four kinds of method references in Java

Kind Example
Reference to a static method ContainingClass::staticMethodName
Reference to an instance method of a particular object containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName
Reference to a constructor ClassName::new

Static method reference

Following example shows how to use static method reference in Java.

public class MethodRef {
  public static <T> List<T> filter(List<T> myList, Predicate<T> predicate) {
    List<T> filterdList = new ArrayList<T>();
    for(T element: myList) {
      if(predicate.test(element)) {
        filterdList.add(element);
      }
    }
    return filterdList;
  }
  public static boolean isMoreThanValue(int i) {
    return i > 10;
  }
  public static void main(String[] args) {
    List<Integer> myList = Arrays.asList(25, 5, 17, 1, 7, 14, 9, 11);
    System.out.println("Method call as lambda expression");
    List<Integer> filterdList = filter(myList, (i) -> MethodRef.isMoreThanValue(i));
    System.out.println("Filtered elements- " + filterdList);
    System.out.println("Method call using method reference");
    filterdList = filter(myList, MethodRef::isMoreThanValue);
    System.out.println("Filtered elements- " + filterdList);
  }
}
Output
Method call as lambda expression
Filtered elements- [25, 17, 14, 11]
Method call using method reference
Filtered elements- [25, 17, 14, 11]

In the example static method isMoreThanValue() is called using method reference MethodRef::isMoreThanValue.

In the filter method one of the argument is of type Predicate. Predicate is a functional interface which has an abstract method test() which evaluates this predicate on the given argument and return a boolean value (true or false).

Static method isMoreThanValue() is an implementation of the abstract method test() of the Predicate functional interface. When you make a method call filter(myList, MethodRef::isMoreThanValue), Java can infer from the context that isMoreThanValue() is an implementation for Predicate interface.

Method reference to an instance method

In this case you use an object of the class to refer the method rather than using the class name.

public class MethodRef {
  public <T> List<T> filter(List<T> myList, Predicate<T> predicate) {
    List<T> filterdList = new ArrayList<T>();
    for(T element: myList) {
      if(predicate.test(element)) {
        filterdList.add(element);
      }
    }
    return filterdList;
  }
  public boolean isMoreThanValue(int i) {
    return i > 10;
  }
  public static void main(String[] args) {
    List<Integer> myList = Arrays.asList(25, 5, 17, 1, 7, 14, 9, 11);
    MethodRef obj = new MethodRef();
    System.out.println("Method call as lambda expression");
    List<Integer> filterdList = obj.filter(myList, (i) -> obj.isMoreThanValue(i));
    System.out.println("Filtered elements- " + filterdList);
    System.out.println("Method call using method reference");
    filterdList = obj.filter(myList, obj::isMoreThanValue);
    System.out.println("Filtered elements- " + filterdList);
  }
}
Output
Method call as lambda expression
Filtered elements- [25, 17, 14, 11]
Method call using method reference
Filtered elements- [25, 17, 14, 11]

It is the same example as the static method reference only change is now instance of the class is used for method reference. Methods are also not required to be static now.

Reference to an instance method of an arbitrary object of a particular type

In the previous example specific object of the class is used but you may have a scenario in which you want to specify an instance method that can be used with any object of a given class. In that case method reference will have the following form-

ClassName::instanceMethodName

In this case, the first parameter of the functional interface matches the object that has been used to invoke the method and any other parameters are passed to the method.

In the example there a class Person with fields firstName, lastName, age and you need to get the count of Persons with age greater than 50. In this scenario isAgeGreater() method has to be invoked for all the Person objects.

class Person {
  private String firstName;
  private String lastName;
  private int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }
  // This becomes the abstract method (test) implementation
  // of the functional interface
  boolean isAgeGreater(int age) {
    return this.getAge() > age;
  }
}
@FunctionalInterface
interface TestInterface {
  boolean test(Person person, int age);
}
public class MethodRef {
  public static void main(String[] args) {
    List<Person> tempList = createList();
    int count = ageCounter(tempList, Person::isAgeGreater, 50);
    System.out.println("Person count age greater than 50- " + count);
  }

  static int ageCounter(List<Person> list, TestInterface ref, int age) {
    int count = 0;
    for(Person person : list) {
      // first param becomes the invoking object
      // other parameters are passed to method
      if(ref.test(person, age))
        count++;
    }
    return count;
  }

  private static List<Person> createList(){
    List<Person> tempList = new ArrayList<Person>();
    tempList.add(new Person("Joe","Root", 28));
    tempList.add(new Person("Mathew","Hayden", 42));
    tempList.add(new Person("Richard","Hadlee", 55));
    tempList.add(new Person("Sunil","Gavaskar", 65));
    tempList.add(new Person("Brian","Lara", 45));     
    return tempList;
  }
}

Constructor reference

You can also reference a constructor which is similar to method reference except that the name of the method is new in this case.

Syntax for the constructor reference is as follows-

classname::new

Constructor reference Java example

In the method copyElements() one of the parameter is of type Supplier which is a functional interface defined in java.util.function package. The functional interface Supplier contains one method get that takes no arguments and returns an object. A new ArrayList instance is passed to Supplier as a constructor reference.

public class MethodRef {
  public static void main(String[] args) {
    List<Integer> myList = Arrays.asList(25, 5, 17, 1, 7, 14, 9, 11);
    List<Integer> tempList = copyElements(myList, ArrayList::new);
    System.out.println("Copied list- " + tempList);
  }

  public static List<Integer> copyElements(List<Integer> sourceList, Supplier<List<Integer>> destList) {      
    List<Integer> list = destList.get();
    for (Integer i : sourceList) {
      list.add(i);
    }
    return list;
  }
}

That's all for the topic Method Reference in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 27, 2022

props.children in React With Examples

In this tutorial we'll try to understand what is children prop (props.children) in React and how to use it.

React children prop Usage

If you have nested components like this

<Parent>
  <Child></Child>
</Parent>

The parent component will receive the content in a prop called children. For the example given above Parent component will receive a children prop set to <Child />

This kind of scenario is common with reusable components where components don't know their children ahead of time. These reusable components can use the special children prop to pass children elements directly into their output.

For example, let us create a Card component which we want to use in several places and whatever content is passed with in the Card component should be rendered.

Card.js

import "./Card.css"
const Card = () => {
  return (
    <div className="card">
    </div>
  )
}
export default Card;

Some styling for the Card component.

Card.css

.card{
  border-radius: 10px;
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.25) ;
  margin: 12px 0px;
}

Now suppose you have a Login component where you want to use this Card component, so you nest the content with in the Card component with the expectation that this content will be rendered within a Card.

import Card from "../UI/Card"

const Login = () => {
  return(
    <Card>
      <label htmlFor="name">Enter User Name</label>
      <input type="text" id="name"></input>
      <label htmlFor="pwd">Enter Password</label>
      <input type="password" id="pwd"></input>
    </Card>
  );
}
export default Login;

But running it won’t give any output. Though in Login component you have content inside a <Card> JSX tag but the Card parent component has no idea about it. It just has an empty <div> tag

<div className="card">
</div>

You have to use children prop in this scenario to pass children elements directly into their output. Here is the updated Card.js file.

import "./Card.css"
const Card = (props) => {
  const styleClasses = "card " + props.className;
  return (
    <div className={styleClasses}>
      {props.children}
    </div>
  )
}

export default Card;

Login.js

import Card from "../UI/Card"
import "./Login.css"
const Login = () => {
  return(
    <Card className="card-item">
      <label htmlFor="name">Enter User Name</label>
      <input type="text" className="inp" id="name"></input>
      <label htmlFor="pwd">Enter Password</label>
      <input type="password" className="inp" id="pwd"></input>
    </Card>
  );
}
export default Login;

Login.css

.card-item {
  display: block;
  align-items: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  padding: 0.5rem;
  margin: 1rem 0;
  border-radius: 12px;
  background-color: #A9A9A9;
}

.inp {
  display: block;
  width: 100%;
  padding: 12px 20px;
  margin: 8px 0;
  box-sizing: border-box;
  border: 1px solid #ccc;
  border-radius: 4px;
}

In Card.js as you can see props.children is used to receive the content. One more thing to notice is how CSS classes are used. Using props gives you the flexibility to pass the classes from the child component, giving the flexibility to control the style.

For Card component there is default styling using .card then you can add other classes received from child by using props.className.

const styleClasses = "card " + props.className;

Using with another content

Same reusable component can now be used with other content with out any problem. Suppose there is a Message.js file to render a message with in a card component.

import Card from "../UI/Card";
const Message = () => {
  return(
    <Card>
      <h3>Hello from the component</h3>
    </Card>
  );
}
export default Message;

Now this content inside the <Card> JSX tag will be passed in children prop.

That's all for the topic props.children in React With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 26, 2022

Java Lambda Expressions With Examples

Java Lambda expression is one of the most important addition in Java 8. It is a step towards functional programming in Java programming language. This Java Lambda expression tutorial gives an overview of lambda expressions like what are lambda expressions, how to write one and what are the advantages of using lambda expressions.

Functional interface in Java

Before delving deep into lambda expressions you should know about the functional interfaces in Java.

A functional interface is an interface with only a single abstract method (SAM). There are already many functional interfaces in Java  (though many new ones added in Java 8) like Runnable with its single run() method, Callable with its call() method or Comparator with its compare() method.

To know more about Functional interfaces in Java please refer this post- Functional Interface in Java

Lambda expression in Java

Java lambda expression is an implementation of a functional interface. It is an instance of a functional interface and the lambda expression you write implements the abstract method of the functional interface.

Let’s try to clarify it with an example. Generally when you implement a functional interface most probably you will implement it as an anonymous class. For example if you have to implement a Comparator you will write it as an anonymous class as given below-

List<Integer> myList = Arrays.asList(4, 7, 1, 10, 8, 12);
Collections.sort(myList, new Comparator<Integer>() {
  @Override
  public int compare(Integer o1, Integer o2) {		
    return o2.compareTo(o1);
  }
});

Since Comparator is a functional interface it can also be implemented as a Lambda expression.

Collections.sort(myList, (Integer o1, Integer o2)-> o2.compareTo(o1));

Some important points you should notice here are-

  1. By implementing a functional interface as a lambda expression, code is more compact.
  2. If you see the Collections.sort() method what you have done is written a function- (Integer o1, Integer o2)->o2.compareTo(o1) that represents an instance of a functional interface and it can be passed as a method argument. That is one of the advantages of lambda expression you can pass functionality as an argument to another method.

Arrow operator or Lambda operator

Java lambda expressions introduce a new operator -> knows as Arrow operator in Java. Arrow operator has two parts-

Left side specifies parameters required by the lambda expression which can be empty too if there are no parameters.

Right side is the lambda body which is actually the code of your lambda expression.

So the syntax of Java Lambda expression is as follows-

(type arg1, type arg2, ....) -> lambda body

Type can be inferred from the context in which lambda expression is used so you don’t need to explicitly specify type of the parameters.

(arg1, arg2, ....) -> lambda body

If we consider the lambda expression we have already written-

Lambda expressions in Java examples

Now when you have a good idea of functional interface and how to write a lambda expression let’s see some more examples of Lambda expressions in Java.

1- The simplest lambda expression is one with no parameters and just a return value and it can be written as.

()-> 10;
The above lambda expression is put to use in the following class.
// Functional interface
interface TestInterface{
  int getValue();
}

public class LambdaExample {
  public static void main(String[] args) {
    // assigning to functional interface reference
    TestInterface ref = () -> 10;
    System.out.println("Value- " + ref.getValue());
  }
}
Output
Value- 10

Some important points you should notice here are-

  • Since lambda expression is an instance of functional interface so it can be referred using a functional interface reference as done in this statement- TestInterface ref = () -> 10;
  • Since there are no parameters so left side of the arrow operator is just empty parenthesis.

2- A lambda expression with parameters.

// Functional interface
interface TestInterface{
  String getValue(String str1, String str2);
}

public class LambdaExample {
  public static void main(String[] args) {
    // assigning to functional interface reference
    TestInterface ref = (String str1, String str2) -> str1 + " " + str2;
    System.out.println("Value- " + ref.getValue("Hello", "Lambda"));
  }
}
Output
Value- Hello Lambda

Here we have a lambda expression with two String parameters. You don’t need to specify types of the parameters as that can be inferred from the context it is used, so this is also acceptable-

TestInterface ref = (str1, str2) -> str1 + " " + str2;

Lambda expression as a method argument

In the beginning we have already seen an example where Comparator implementation as a lambda expression is passed as a method argument. This is one of the feature of the lambda expression; to treat functionality as method argument.

If you have a method where argument is a functional interface then you can pass a lambda expression compatible with that functional interface as a method parameter.

In the following Java lambda expression as method argument example there is a method invoke that has a Callable as argument. Since Callable is a functional interface so a lambda expression compatible to it is passed as a parameter while calling invoke method.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class LambdaExample {
  public static void main(String[] args) {
    LambdaExample obj = new LambdaExample();
    try {
      Future<String> f  = obj.invoke(()->"Calling callable");
      System.out.println("Value returned from callable- " + f.get());
    }catch(Exception e) {
      System.out.println("Exception message- " + e.getMessage());
    }      
  }
    
  //Method with Callable(funtional interface) as parameter
  <T> Future<T> invoke(Callable<T> c) throws Exception {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future<T> f =  executor.submit(c);
    executor.shutdown();
    return f;
  }
}
Output
Value returned from callable- Calling callable

Block lambda expressions in Java

What we have seen till now are all single expressions but you can also have lambda expressions having multiple statements known as block lambda expressions.

In a block lambda expression enclose the block of code with in curly braces and explicitly use return to return a value.

//Functional interface
interface TestInterface{
  String getValue(int i);
}

public class LambdaExample {
  public static void main(String[] args) {
    //block lambda
    TestInterface ref = (int i) -> {
      String s;
      if((i % 2) == 0) {
        s = "Even";
      }else {
        s = "Odd";
      }
      return s;
    };
    
    int num = 5;
    System.out.println(num + " is- " + ref.getValue(num));
  }
}
Output
5 is- Odd

That's all for the topic Java Lambda Expressions With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 25, 2022

Functional Interface in Java

Functional interface in Java is an interface with a single abstract method. Here is a functional interface example in Java.

interface MyFunctionalInterface{
  void calculateInterest(int i);
}

This interface qualifies as a functional interface because there is a single unimplemented method in the interface.

What qualifies as a functional interface

Java 8 onward an interface can have default methods, static methods and Java 9 onward even private methods, so a functional interface can have these methods too but it should have only a single unimplemented method to be qualified as a functional interface.

If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method.

Following interface qualifies as a functional interface even though it contains a default method and a private method as it has a single abstract method.

@FunctionalInterface
interface MyFunctionalInterface{
  void calculateInterest(int i);	
  default void defMethod(){
    commonCode();
    System.out.println("In default method 2");
  }
  private  void commonCode(){
    System.out.println("Executing common code...");
  }
}

Functional interface and Lambda expression

Though there were already interfaces in Java with a single abstract method, like Runnable with its single run() method, Callable with its call() method or Comparator with its compare() method but the term "functional interface" came into fore with the introduction of Lambda expressions in Java 8.

Lambda expression on its own is just a function which needs a target type context to be executed. Since Java is an object oriented language so Lambda expression has to be wrapped with in an object that’s what functional interface provides. Lambda expression specifies the implementation of the abstract method defined by the functional interface and that's how functional interface provides target type for Lambda expression.

Let’s see an example where lambda expression is assigned to a functional interface reference.

//Functional interface
interface MyFunctionalInterface{
  void calculateSimpleInterest(int p, int r, int t);
}
public class LambdaExample {
  public static void main(String[] args) { 
    // lambda assigned to functional interface reference
    MyFunctionalInterface ref = (int p, int r, int t) -> System.out.println("Simple Interest is " + (p*r*t)/100);
    ref.calculateSimpleInterest(10000, 5, 3);
  }
}
Output
Simple Interest is 1500

In the example you can see that the Lambda expression is assigned to MyFunctionalInterface reference. Since target type for lambda expression here is MyFunctionalInterface so an instance of a class is automatically created that implements the functional interface and lambda expression provides implementation of the abstract method declared by the functional interface.

Here is an another example where lambda expression is passed as a method argument. In that case functional interface provides target type as a method parameter.

public class LambdaExample {
  public static void main(String[] args) { 
    new Thread(()->System.out.println("Method argument to Runnable")).start();
  }
}
Output
Method argument to Runnable

Above example is an implementation of Runnable as Lambda expression. As you can see here Thread constructor where Runnable is passed as method parameter is used and Lambda expression implementing the run() method of the Runnable functional interface is passed as method argument. Java run time is able to infer the target type from the context it is used.

@FunctionalInterface annotation in Java

@FunctionalInterface annotation is also added in Java 8 to be used with functional interfaces in Java. By annotating an interface with @FunctionalInterface annotation it is ensured that the interface won’t have more than one abstract method. It is advisable to use it with your functional interface so that no other abstract method is added to the interface even accidentally.

Here is an example of trying to add another abstract method to a functional interface annotated with @FunctionalInterface annotation.

@FunctionalInterface
interface MyFunctionalInterface{
  int calculateSimpleInterest(int p, int r, int t);
  void test(int i);
}

This functional interface gives compile time error “Invalid '@FunctionalInterface' annotation; MyFunctionalInterface is not a functional interface” as there are more than one abstract method.

Pre-packaged Functional interfaces in Java

In the examples shown above we have created our own functional interface but Java comes pre-packaged with many functional interface covering most of the scenarios. A whole new package java.util.function is added in Java 8 containing many functional interfaces to be used off the shelf.

Some of the inbuilt functional interfaces are as follows-

  1. BiConsumer<T,U>- Represents an operation that accepts two input arguments and returns no result.
  2. BiFunction<T,U,R>- Represents a function that accepts two arguments and produces a result.
  3. BinaryOperator<T>- Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  4. Function<T,R>- Represents a function that accepts one argument and produces a result.
  5. Predicate<T>- Represents a predicate (boolean-valued function) of one argument.
  6. Supplier<T>- Represents a supplier of results.
  7. UnaryOperator<T>- Represents an operation on a single operand that produces a result of the same type as its operand.

Check the whole list here- https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/function/package-summary.html

Example using BiFunction functional interface

Since BiFunction functional interface accepts two arguments and returns a result so it can be used where computation using two arguments is required.

public class LambdaExample {
  public static void main(String[] args) { 
    BiFunction<String, String, String> ref = (str1, str2) -> str1+ " " +str2;
    System.out.println("Concatenating Strings- " + ref.apply("Hello", "Lambda"));
  }
}
Output
Concatenating Strings- Hello Lambda

Example using Predicate functional interface

Predicate functional interface in Java has an abstract method test() which evaluates this predicate on the given argument and return true if the input argument matches the predicate, otherwise false.

Suppose you have a List of Integers and you want to get only those elements of the list which are greater than 10 then you can use Predicate functional interface to test if element is greater than 10 or not and return true only if it is greater than 10.

public class LambdaExample {
  public static void main(String[] args) { 
    List<Integer> myList = Arrays.asList(25, 5, 17, 1, 7, 14, 9, 11);
    LambdaExample obj = new LambdaExample();
    // Lambda expression as method arg
    List<Integer> filterdList = obj.filter(myList, (i) -> i>10);
    System.out.println("Filtered elements- " + filterdList);
  }
	
  public <T> List<T> filter(Collection<T> myList, Predicate<T> predicate) {
    List<T> filterdList = new ArrayList<T>();
    for(T element: myList) {
      if(predicate.test(element)) {
        filterdList.add(element);
      }
    }
    return filterdList;
  }
}
Output
Filtered elements- [25, 17, 14, 11]

In the example lambda expression (i) -> i>10 provides the implementation of the abstract method test() of the Predicate functional interface.

That's all for the topic Functional Interface in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 24, 2022

Built-in Functional Interfaces in Java

Post about Functional Interface in Java gives an overview of functional interfaces and how Lambda expressions can be used to implement functional interfaces. At the same time it doesn’t mean whenever you want to use lambda expression you will have to write your own custom functional interface. In Java there are many built-in functional interfaces which cover many different contexts when used with lambda expressions in Java.

Built-in functional interfaces Java package

In Java there is a package java.util.function that defines many general purpose functional interfaces used by the JDK and used by user code as well.

Functional interfaces in this package can be categorized into five types-

  1. Consumer
  2. Function
  3. Predicate
  4. Supplier
  5. Operators that extend Function

Consumer functional interface

java.util.function.Consumer<T> functional interface represents an operation that accepts a single input argument and returns no result. Definition of the Consumer is as given below which consists of an abstract method accept() and a default method andThen()-

@FunctionalInterface
public interface Consumer<T> {
  void accept(T t);

  default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
  }
}

Here is a list of other pre-defined Consumer functional interfaces sharing the same behavior of consuming the passed value(s) and returning no result.

  • BiConsumer<T,U>- Represents an operation that accepts two input arguments and returns no result.
  • DoubleConsumer- Represents an operation that accepts a single double-valued argument and returns no result.
  • IntConsumer- Represents an operation that accepts a single int-valued argument and returns no result.
  • LongConsumer- Represents an operation that accepts a single long-valued argument and returns no result.
  • ObjDoubleConsumer<T>- Represents an operation that accepts an object-valued and a double-valued argument, and returns no result.
  • ObjIntConsumer<T>- Represents an operation that accepts an object-valued and a int-valued argument, and returns no result.
  • ObjLongConsumer<T>- Represents an operation that accepts an object-valued and a long-valued argument, and returns no result.

See post Java Consumer Functional Interface Examples for examples of Consumer interface and BiConsumer Functional Interface Java Examples for examples of BiConsumer interface

Supplier functional interface

java.util.function.Supplier<T> functional interface represents a function that supplies a result. Supplier interface definition is as given below-

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

Here is a list of pre-defined Supplier functional interfaces sharing the same behavior of supplying a result.

  • BooleanSupplier- Represents a supplier of boolean-valued results.
  • DoubleSupplier- Represents a supplier of double-valued results.
  • IntSupplier- Represents a supplier of int-valued results.
  • LongSupplier- Represents a supplier of long-valued results.

Function functional interface

java.util.function Function<T,R> functional interface represents a function that accepts one argument and produces a result.

Abstract method in this functional interface is apply(Object).

@FunctionalInterface
public interface Function<T, R> {
  R apply(T t);
}

Here is a list of other pre-defined Function functional interfaces sharing the same behavior of accepting argument(s) and producing a result.

  • BiFunction<T,U,R>- Represents a function that accepts two arguments and produces a result.
  • DoubleFunction<R>- Represents a function that accepts a double-valued argument and produces a result.
  • DoubleToIntFunction- Represents a function that accepts a double-valued argument and produces an int-valued result.
  • DoubleToLongFunction- Represents a function that accepts a double-valued argument and produces a long-valued result.
  • IntFunction<R>- Represents a function that accepts an int-valued argument and produces a result.
  • IntToDoubleFunction- Represents a function that accepts an int-valued argument and produces a double-valued result.
  • IntToLongFunction- Represents a function that accepts an int-valued argument and produces a long-valued result.
  • LongFunction<R>- Represents a function that accepts a long-valued argument and produces a result.
  • LongToDoubleFunction- Represents a function that accepts a long-valued argument and produces a double-valued result.
  • LongToIntFunction- Represents a function that accepts a long-valued argument and produces an int-valued result.
  • ToDoubleBiFunction<T,?U>- Represents a function that accepts two arguments and produces a double-valued result.
  • ToDoubleFunction<T>- Represents a function that produces a double-valued result.
  • ToIntBiFunction<T,?U>- Represents a function that accepts two arguments and produces an int-valued result.
  • ToIntFunction<T>- Represents a function that produces an int-valued result.
  • ToLongBiFunction<T,?U>- Represents a function that accepts two arguments and produces a long-valued result.
  • ToLongFunction<T>- Represents a function that produces a long-valued result.

Operator functional interfaces

Function functional interfaces may produce result of the same type as argument or different but there are Operator functional interfaces that always return the value of same type as the passed arguments. Base Operator functional interfaces extend their Function interface counterpart like UnaryOperator extends Function and BinaryOperator extends BiFunction.

  • BinaryOperator<T>- Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  • DoubleBinaryOperator- Represents an operation upon two double-valued operands and producing a double-valued result.
  • DoubleUnaryOperator- Represents an operation on a single double-valued operand that produces a double-valued result.
  • IntBinaryOperator- Represents an operation upon two int-valued operands and producing an int-valued result.
  • IntUnaryOperator- Represents an operation on a single int-valued operand that produces an int-valued result.
  • LongBinaryOperator- Represents an operation upon two long-valued operands and producing a long-valued result.
  • LongUnaryOperator- Represents an operation on a single long-valued operand that produces a long-valued result.
  • UnaryOperator<T>- Represents an operation on a single operand that produces a result of the same type as its operand.

Predicate Functional interface

java.util.function.Predicate<T> functional interface represents a boolean valued function returning either true or false. Abstract method in this functional interface is test(Object).

@FunctionalInterface
public interface Predicate<T> {
  boolean test(T t);
}

Here is a list of pre-defined Predicate functional interfaces sharing the same behavior of accepting argument(s) and producing a boolean result.

  1. BiPredicate<T,?U>- Represents a predicate (boolean-valued function) of two arguments.
  2. DoublePredicate- Represents a predicate (boolean-valued function) of one double-valued argument.
  3. IntPredicate- Represents a predicate (boolean-valued function) of one int-valued argument.
  4. LongPredicate- Represents a predicate (boolean-valued function) of one long-valued argument.

That's all for the topic Built-in Functional Interfaces in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 23, 2022

Variable Scope in Java Lambda Expression

In this post we’ll see what is the scope of a variable with in a lambda expression in Java. This topic is important as it touches one of the concept that’s added in Java 8; Effectively final in Java.

Java lambda expression variable scope

Lambda expression in Java doesn’t have a scope of its own, it has the same scope as its enclosing scope. It results in an error if a variable is defined with in a lambda expression that has the same name as a variable in its enclosing scope.

For example-

String s1 = "Lambda";
// Error
Comparator<String> comp = (s1, s2) -> s1.length() - s2.length();

This lambda expression implements the compare() method of the Comparator functional interface but that will result in an error as the parameter used with in the lambda expression has the same name as the local variable s1 already defined. Thus this statement results in compile time error “Lambda expression's parameter s1 cannot redeclare another local variable defined in an enclosing scope”.

Accessing enclosing scope variable in Lambda expression

Since lambda expression does not introduce a new level of scoping you can directly access fields, methods, and local variables of the enclosing scope. However there is a restriction how variables from enclosing scope can be used. Like local and anonymous classes, a lambda expression can only access local variables and parameters of the enclosing scope that are final or effectively final.

An effectively final variable in Java is a variable whose value can't be modified once it is assigned. So any enclosing scope variable can either be declared as final or it is by default effectively final and it can’t be modified in lambda expression or in an inner class. Actually before Java 8 it was mandatory to define such a field (which is used in inner class) as final, Java 8 onward it is relaxed a bit and there is no need to explicitly declare such fields as final.

@FunctionalInterface
interface TestInterface{
  int calculate(int i, int j);
}
public class LambdaExample {
  public static void main(String[] args) { 
    int num = 7;
    TestInterface ref = (x, y) -> {
      // Modifying value of enclosing scope field
      num = x + y;
      return num;
    };
  }
}

In the above example with in the lambda expression block there is an attempt to modify the value of a variable from an enclosing scope that results in an error “Local variable num defined in an enclosing scope must be final or effectively final”.

Why effectively final

Now the question arises why such restriction for an enclosing scope variable. A lambda expression that uses the variables from the enclosing scope captures the values of such variables. Since lambda expression in Java is an instance of a functional interface so the fields of the enclosing scope used in such an instance captures the values of those fields and use it. It is important to maintain the state of such fields so that those are not modified that’s why this restriction of "effectively final".

Using this and super keyword in lambda expression

Since lambda expressions don’t introduce a new scope so using this keyword and super keyword with in a lambda refers to the same object that has invoked the method where the lambda expression resides.

@FunctionalInterface
interface TestInterface{
  int calculate(int i, int j);
}

class Test {
  public void showValue(String str) {
    System.out.println("Value is- " + str);
  }
}
public class LambdaExample extends Test{
  public static void main(String[] args) { 
    LambdaExample obj = new LambdaExample();
    obj.getResult();
  }
	
  public void getResult(){
    TestInterface ref = (x, y) -> {
      // Modifying value of enclosing scope field
      System.out.println("ToString- " + this.toString());
      super.showValue("Calling from Lambda");
      return x+y;
    };
    System.out.println("Result is- " + ref.calculate(8, 6));
  }
}
Output
ToString- com.knpcode.LambdaExample@66133adc
Value is- Calling from Lambda
Result is- 14

In the example, LambdaExample class extends class Test and has a method getResult() where we have a lambda expression. As you can see that lambda expression has access to the this and super. Calling this.toString() from the lambda prints an instance of LambdaExample not of TestInterface.

That's all for the topic Variable Scope in Java Lambda Expression. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 22, 2022

Exception Handling With Java Lambda Expressions

In this post we’ll see exception handling with lambda expressions in Java. A lambda expression can throw an exception but that should be compatible with the exceptions specified in the throws clauses of the abstract method of the functional interface.

If a lambda expression body throws a checked exception, the throws clause of the functional interface method must declare the same exception type or its supertype.

Checked exception in lambda expression

In the example abstract method calculate of the functional interface MyFunctionalInterface doesn't have a throws clause but lambda body throws an exception. In such case a compiler error message "Unhandled exception type Exception" is generated.

Exception handling in lambda expression

If you specify the same exception in the functional interface method then the error is resolved but then you do need to handle it while calling the method.

@FunctionalInterface
interface MyFunctionalInterface{
  int calculate(int i, int j) throws Exception;
}
public class LambdaException {
  public static void main(String[] args) {
    MyFunctionalInterface ref = (x, y) -> {
      int num = x * y;
      throw new Exception();
      //return num;
    };
    try {
      System.out.println("Result is " + ref.calculate(8, 5));
    }catch(Exception e) {
      System.out.println("Exception while calculating " + e.getMessage());
    }
  }
}

Unchecked exception in lambda expression

In case of unchecked exception there is no such restriction that it should be specified in the abstract method of the functional interface.

In the example abstract method calculate of the functional interface MyFunctionalInterface doesn't have a throws clause but lambda body throws a runtime exception.

@FunctionalInterface
interface MyFunctionalInterface{
  int calculate(int i, int j);
}
public class LambdaException {
  public static void main(String[] args){
    MyFunctionalInterface ref = (x, y) -> {
      try {
        int num = x/y;
        return num;
      }catch(ArithmeticException e) {
        System.out.println("Exception while calculating- " + e.getMessage());
        throw new RuntimeException(e);
      }
    };

    System.out.println("Result is " + ref.calculate(8, 0));		
  }
}

Wrapping lambda to handle exceptions

Many people like to keep lambda expression code concise and clutter free with no try catch blocks.

In that case you can create a wrapper class wrapping your lambda and then calling it.

@FunctionalInterface
interface MyFunctionalInterface{
  int calculate(int i, int j);
}
public class LambdaException {
  // Lambda wrapper
  static MyFunctionalInterface lambdaWrapper(MyFunctionalInterface ref) {
    return (x, y) -> {
      try {
        ref.calculate(x, y);
      }catch(ArithmeticException e) {
        System.out.println("Exception while calculating- " + e.getMessage());
      }
      return -1;
    };
  }

  public static void main(String[] args){
    // calling lambda wrapp
    MyFunctionalInterface ref = lambdaWrapper((x,y)->x/y);
    System.out.println("Result is " + ref.calculate(8, 0));	
  }
}
Output
Exception while calculating- / by zero
Result is -1
Reference: https://www.oracle.com/technetwork/articles/java/lambda-1984522.html

That's all for the topic Exception Handling With Java Lambda Expressions. If something is missing or you have something to share about the topic please write a comment.


You may also like

October 21, 2022

Function Functional Interface Java Examples

In this post we’ll see examples of java.util.function.Function functional interface.

Function functional interface represents an operation that accepts one argument and produces a result. Abstract method in this functional interface is-

R apply(T t)- Here T is the type of the argument passed to the method and it returns a value of type R.

If you are writing a Lambda expression that takes single argument of one type and returns a value of another type (or even same type) then that lambda expression can be written as an implementation of Function built-in functional interface.

Apart from the apply() abstract method Function() interface has following default and static methods.

  • andThen(Function<? super R, ? extends V> after)- It is a default method which takes another Function as argument and returns a composed Function that performs, in sequence, first the operation of the calling Function followed by the after operation.
  • compose(Function<? super V, ? extends T> before)- It is a default method in Function interface which takes another Function as argument and returns a composed Function that performs, in sequence, first the before operation then the operation of the calling Function.
  • identity()- It is a static method that returns a function which returns its input argument.

Function interface apply() method example

1. Writing a function that returns the length of the passed string.

public class FunctionExample {
  public static void main(String[] args) {
    Function<String, Integer> function = (s) -> s.length();
    System.out.println("Length- " + function.apply("Test"));
    System.out.println("Length- " + function.apply("Retrospective"));
  }
}
Output
Length- 4
Length- 13

In the example statement- Function<String, Integer> function = (s) -> s.length(); is the implementation of Function interface as a lambda expression.

When function.apply() method is called Java can infer from the context that lambda expression is the implementation of apply() method.

2. Finding factorial of a number as a lambda expression can be implemented as an instance of Function interface where input argument is an Integer and return value is of type Double.

import java.util.function.Function;

public class FunctionExample {
  public static void main(String[] args) {
    double result = factorial(10);
    System.out.println("Factorial- " + result);

  }

  public static double factorial(int n) {
    Function<Integer, Double> function =  x -> (x == 0) ? 1 : x * factorial(x - 1);
    return function.apply(n);
  }
}
Output
Factorial- 3628800.0

3. In this Function interface Java example a List of Employees is mapped to a list of names.

public class Employee {
  private String name;
  private String dept;
  private int salary;

  Employee(String name, String dept, int salary){
    this.name = name;
    this.dept = dept;
    this.salary = salary;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getSalary() {
    return salary;
  }
  public void setSalary(int salary) {
    this.salary = salary;
  }
  public String getDept() {
    return dept;
  }
  public void setDept(String dept) {
    this.dept = dept;
  }
}
public class FunctionExample {
  public static void main(String[] args) {
    List<Employee> employeeList = new ArrayList<>(); 

    employeeList.add(new Employee("Jack", "Finance", 5500)); 
    employeeList.add(new Employee("Lisa", "Finance", 5600)); 
    employeeList.add(new Employee("Scott", "Finance", 7000));
    employeeList.add(new Employee("Nikita", "IT", 4500));
    employeeList.add(new Employee("Tony", "IT", 8000));
    
    List<String> nameList = mapTo(employeeList, (e)->e.getName());
    nameList.forEach(System.out::println);
  }

  public static List<String> mapTo(List<Employee> empList, Function<Employee, String>mapper){
    List<String> nameList = new ArrayList<>();
    for(Employee emp : empList) {
      nameList.add(mapper.apply(emp));
    }
    return nameList;
  }
}
Output
Jack
Lisa
Scott
Nikita
Tony

In the example implementation of the Function is passed as the method argument-

mapTo(employeeList, (e)->e.getName());

Function functional interface andThen() method example

In the example there will be two Function interfaces, on the first Function, andThen() is called with second Function as an argument. Now, when apply() method is called on the second Function interface, it first executes the first Function implementation and then the second one.

We’ll use the previous example of Employee list, in first function interface we’ll get the salary of the Employee and then in the second function increase it by 10%.

public class FunctionExample {
  public static void main(String[] args) {
    int fin, it;
    List<Employee> employeeList = new ArrayList<>(); 
    employeeList.add(new Employee("Jack", "Finance", 5500)); 
    employeeList.add(new Employee("Lisa", "Finance", 5600)); 
    employeeList.add(new Employee("Scott", "Finance", 7000));
    employeeList.add(new Employee("Nikita", "IT", 4500));
    employeeList.add(new Employee("Tony", "IT", 8000));
    Function<Employee, Integer> function = (e)->e.getSalary();
    Function<Integer, Integer> functionAnother =  (Integer i)-> i + ((i * 10)/100);
    List<Integer> salaryList = mapTo(employeeList, function.andThen(functionAnother));
    salaryList.forEach(System.out::println);
  }

  public static List<Integer> mapTo(List<Employee> empList, Function<Employee, Integer>mapper){
    List<Integer> salaryList = new ArrayList<>();
    for(Employee emp : empList) {
      salaryList.add(mapper.apply(emp));
    }
    return salaryList;
  }
}
Output
6050
6160
7700
4950
8800

Function functional interface compose() method example

compose() is reverse of andThen() first the Second Function interface implementation is called then the first one.

In the previous andThen() example if compose method is called on the second function and as argument first function interface is passed we’ll have the same result as the previous example.

List<Integer> salaryList = mapTo(employeeList, functionAnother.compose(function));

Function functional interface in JDK

These built-in functional interfaces are used extensively with in the JDK itself. A very good example of usage of Function interface is map() method of Stream interface in Java Stream API.

map(Function<? superT,? extends R>mapper)- Returns a stream consisting of the results of applying the given function to the elements of this stream.

The example where we mapped Employee object list to a List of employee names, can be written using map() method of Stream.

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionExample {
  public static void main(String[] args) {
    int fin, it;
    List<Employee> employeeList = new ArrayList<>(); 
    employeeList.add(new Employee("Jack", "Finance", 5500)); 
    employeeList.add(new Employee("Lisa", "Finance", 5600)); 
    employeeList.add(new Employee("Scott", "Finance", 7000));
    employeeList.add(new Employee("Nikita", "IT", 4500));
    employeeList.add(new Employee("Tony", "IT", 8000));
    // map to name and then collect to a list
    List<String> nameList = employeeList.stream().map((e)->e.getName()).collect(Collectors.toList());
    nameList.forEach(System.out::println);
  }
}
Output
Jack
Lisa
Scott
Nikita
Tony

That's all for the topic Function Functional Interface Java Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like