Skip to content

Artemas-Muzanenhamo/java-functional-programming

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java Functional Programming

Foundation of the Java Stream API

foundation-java-stream-api

Functional Interfaces

  • A Lambda Expression implements a Functional Interface.
  • A Lambda Expression is not another way to write instances of anonymous classes.

What is a Functional Interface?

  • An interface.
  • Has only one abstract method.
  • Default and static methods do not count.
  • Methods from Object Class do not count. I.e. hashcode(), equals(), toString().
  • May have one abstract methods.
  • May have as many default methods
  • May have as many static methods
  • May have methods from the Object Class.
  • May be annotated with the @FunctionalInterface annotation.
    • This just tells the compiler to help me determine if the interface is a functional interface or not.
    • If not, it will throw a compiler error.

Writing Suppliers, Consumers, Predicates and Functions

Supplier Interface

public interface Supplier<T> {
    T get();
}
  • The above is a functional interface.
  • A Supplier does not take any kind of object and produces any kind of object as long as it matches the T type you define when you define the supplier.
  • The above can be implemented as follows:
public class SupplierExample {
    public String getGreeting() {
        Supplier<String> supplier = () -> "Hello Artemas";
        return supplier.get();
    }
}

Consumer Interface

public interface Consumer<T> {
    void accept(T t);
}
  • A consumer, consumes any kind of object which is defined on the parameter.
  • Has a single method called accept(T t) that takes any kind of object and that does not produce or return anything.
  • The above can be implemented as:
public class ConsumerExample {
    public void printValue(String name) {
        Consumer<String> nameConsumer = System.out::println;
        nameConsumer.accept(name);
    }
}

Predicate Interface

public interface Predicate<T> {
    boolean test(T t);
}
  • A Predicate will take some object T and perform a test with it to produce a boolean value true or false.
  • Used in the filtering operations in the Stream API.
  • The above can be implemented as the following lambda:
public class PredicateExample {
    public List<String> stringNotStartingWithLetterT(List<String> strings) {
        Predicate<String> filter = (String someString) -> someString.startsWith("t");
        strings.removeIf(filter);

        return strings;
    }
}

Function Interface

public interface Function<T, R> {
    R apply(T t);
}
  • Like the Predicate which returns a boolean value, a Function will take in any type of object and return another type of object.
  • Used in the map() operation in the Stream API.
  • The above can be implemented as:
public class FunctionExample {
    public List<String> getNames(List<User> users) {
        Function<User, String> userNames = User::getName;
        return users.stream()
                .map(userNames)
                .collect(toList());
    }
}

Invoking a Lambda Expression on Objects and Primitive Types

How fast Are Lambda Expressions?

  • What you can put in a lambda, can be returned also in an instance of an anonymous class.
  • Lambda expressions are compiled using specific byte code instructions called invokedynamic introduced in Java 7.
  • Ta make lambdas even faster, you want to avoid autoboxing on lambdas (converting int to INT and auto-unboxing which is converting INT to int).

Introducing the Specialized Interfaces

  • The java.util package has interfaces that are tailored to with primitive types instead of wrapping types.
  • E.g. you have the IntPredicate that takes an int and returns a boolean.

IntSupplier Interface

@FunctionalInterface
public interface IntSupplier {
    int getAsInt();
}
  • This can be implemented as follows:
public class IntSupplierExample {
    public int getValue() {
        IntSupplier supplier = () -> 10;
        return supplier.getAsInt();
    }
}

DoubleToIntFunction

@FunctionalInterface
public interface DoubleToIntFunction {
    int applyAsInt(double value);
}
  • This can be implemented as follow:
public class DoubleToIntFunctionExample {
    public int getIntValueBy(double input) {
        DoubleToIntFunction intFunction = value -> (int) value * 2;
        return intFunction.applyAsInt(input);
    }
}

Releases

No releases published

Packages

No packages published

Languages