Skip to main content

Java 8 - Using Functions as Values


The following is a series of posts about "functional programming in Java" which is the result of my understanding by reading the book "Java 8 in Action: Lambdas, Streams, and Functional-style Programming, by Alan Mycroft and Mario Fusco".
1. Why functional programming?
2. Functional programming in Java 8
3. Java 8 - Using Functions as Values
4. Java 8 - Persistent data structure

In general, the phrase "functional-style programming" means the behavior of functions should be like that of mathematical-style functions - no side effects.

In programmers' point of views, functions may be used like other values: passed as arguments, returned as result, and stored in data structures. That means we can use the :: operator to create a method reference, and lambda expressions to directly express function values. For example:
//method reference
Function<String, Integer> strToInt = Integer::parseInt;

//lambda expression
Comparator<Integer> comparator = (a, b) -> a.compareTo(b);

There are two practical techniques to apply in our codebase.

Higher-order functions

For example:
 Comparator<Apple> c = Comparator.comparing(Apple::getWeight);
Higher-order functions (like Comparator.comparing) that can do at least one of following:
  • Take one or more functions as parameter
  • Return a function as result
Foo: If so, for what? 
Bar: Good question! To compose functions to create a pipeline of operations. It's close to declarative programming.

Currying

A function f of two arguments (x and y, say) is seen instead as a function g of one argument that returns a function also one argument. The value returned by the latter function is the same as the value of the original function, that is, f(x,y) = (g(x))(y).

Brain overload! For example, you want to convert Celsius to Fahrenheit, the formula is f(x) = x *9/5 + 32. Not only this case but we can see the basic pattern of all unit conversion is as follow:
static double converter(double x, double f, double b) {
 return x * f + b;
}
This method is a bit too general. Obviously, we can use it to apply for all unit conversion but it would be tedious and you might accidentally mistyped them. There is an better approach:
static DoubleUnaryOperator curriedConverter(double f, double b){
 return (double x) -> x * f + b;
}
Instead of passing all the arguments x, f and b all at once to the converter method, you only ask for the arguments f and b and return another function, which given an argument x return x*f + b.

Why is it the better approach? This enables you to reuse the convention logic and create different functions with different convention factors:
DoubleUnaryOperator convertCtoF = curriedConverter(9.0/5, 32);
DoubleUnaryOperator convertUSDtoGBP = curriedConverter(0.6, 0);
DoubleUnaryOperator convertKmtoMi = curriedConverter(0.6214, 0);
Instead of three different method for each conversion factor:
static double convertCtoF(double x, double f, double b) {
 return x * f + b;
}

static double convertUSDtoGBP(double x, double f, double b) {
 return x * f + b;
}

static double convertUSDtoGBP(double x, double f, double b) {
 return x * f + b;
}
Foo: If so, for what?
Bar: It helps you modularize functions and reuse code!

Reference

Image result for java 8 in action

[1]. Alan Mycroft and Mario Fusco, Java 8 in Action: Lambdas, Streams, and Functional-style Programming. Part 4. Beyond Java 8.

Comments

Popular posts from this blog

Selenium - Override javascript functions to ignore downloading process

I have got an issue with downloading process on IE 8. This browser blocks my automatic-download functionality on my app so that I could not work with my test case any more after that. In my case, I didn't care about the file is downloaded or not, I just focus on the result after downloading process finished successfully. Therefore, I found a solution to ignore this process so that I can work normally. I use Primefaces, here is the remote command to trigger the download process <p:remoteCommand name="cmdGenerateDocument" actionListener="#{logic.onGenerateDocument}" update="xrflDocumentCreationPanel" oncomplete="clickDownloadButton();"/> The following is my test case: @Test public void shouldUpdateStep6ToWarningIfStep1IsValidAfterFinished(){ MainPage mainPage = new MainPage(); waitForLoading(mainPage.getDriver()); EmployeeDetailPage empDetailPage = new EmployeeDetailPage(); waitForLoading(empDetailPage.getDriver()); e...

Monday vhandit #2

  Introduction to OpenLDAP directory service "A directory is a specialized database specially designed for searching and browsing, in addition to supporting basic lookup and update functions" A directory service can be local, providing a restricted context; or global, providing service to a much broader context. Curlie is a good example of a directory service. LDAP (Lightweight Directory Access Protocol) is a protocol for accessing directory services , specifically X.500-based directory services. OpenLDAP is an open-source implementation of LDAP. Writing system software: code comments I have read Clean Code (by Uncle Bob) and I thought that I should void comments since the code it explains its implementation itself. That is right but not always true. In this post, the author categorized the comments into 9 types. Only "trivial comments" and "backup comments" are the ones that should be avoided. I myself agree with "writing good comments is harder tha...

My must-have apps for daily work

There is no doubt that cool apps can help us be more productive and enjoyable at work. For the time being, I really love the following apps which are used by me almost every day. 1. A personal Kanban In fact, a personal kanban is the most useful app for me. Why does it matter? It is not just a to-do list, but it keeps me motivated every day because it helps me be able to know what my "big picture" is. I usually set up my plans together with a path to reach them.  KanbanFlow  is my preferred tool. KanbanFlow 2. A terminal Needless to say, a terminal is a must-have app for every developer, especially the ones use macOS/Linux. Due to its importance, I love to decorate and enhance it to be super exciting with various tools such as  iTerm ,  oh-my- zsh , and  thefuck . ;) iTerm + oh-my-zsh 3. A documentation "ecosystem" As a developer, I can not remember all things that I have experimented a day. Moreover, a document is really useful for sharing an...

How I did customize "rasa-nlu-trainer" as my own tool

Check out my implementation here Background I wanted to have a tool for human beings to classify intents and extract entities of texts which were obtained from a raw dataset such as Rocket.chat's conversation, Maluuba Frames or  here . Then, the output (labeled texts) could be consumed by an NLU tool such as Rasa NLU. rasa-nlu-trainer was a potential one which I didn't need to build an app from scratch. However, I needed to add more of my own features to fulfill my needs. They were: 1. Loading/displaying raw texts stored by a database such as MongoDB 2. Manually labeling intents and entities for the loaded texts 3. Persisting labeled texts into the database I firstly did look up what rasa-nlu-trainer 's technologies were used in order to see how to implement my mentioned features. At first glance rasa-nlu-trainer was bootstrapped with Create React App. Create React App is a tool to create a React app with no build configuration, as it said. This too...