DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Redefining Java Object Equality
  • Singleton: 6 Ways To Write and Use in Java Programming
  • Writing DTOs With Java8, Lombok, and Java14+
  • Addressing Memory Issues and Optimizing Code for Efficiency: Glide Case

Trending

  • The Perfection Trap: Rethinking Parkinson's Law for Modern Engineering Teams
  • ITBench, Part 1: Next-Gen Benchmarking for IT Automation Evaluation
  • Driving DevOps With Smart, Scalable Testing
  • How Kubernetes Cluster Sizing Affects Performance and Cost Efficiency in Cloud Deployments
  1. DZone
  2. Coding
  3. Languages
  4. Functional Programming in Java 8 (Part 1): Functions as Objects

Functional Programming in Java 8 (Part 1): Functions as Objects

If functional programming has your attention, let's start with the basics: functions. You can store functions as objects, take them as arguments, return them, and more.

By 
Niklas Wuensche user avatar
Niklas Wuensche
·
Jan. 26, 17 · Tutorial
Likes (47)
Comment
Save
Tweet
Share
84.0K Views

Join the DZone community and get the full member experience.

Join For Free

After you’ve read in Part 0 why functional programming is cool, we will make our first big steps into this topic today. In Java 8, functions became first class. Therefore, you can take functions as arguments of other functions, return functions, and store functions as objects.

Why Should You Store a Function as an Object?

1. Make “Super Private” Functions

As you know, code quality is important. That’s the reason we use private functions to reduce the methods one object of a class has. We don’t want to show the underlying code to others. They just have to work with some public methods on the object. But what if we want to create functions in our class that are visible to just one method and invisible to the rest of the class? With functions as first-class objects, We can store the function in a single object, which can be seen just in this very one method.

2. Upgrade Design Patterns

If you ever worked on a big software project, you know how messy it can become. That’s the reason design patterns were invented. One of the cooler ones is the strategy pattern. I will write a detailed post about it later on, but what it basically does is switch similar algorithms depending on a parameter. For each algorithm, you have to write your own class, which implements a function from an interface. But when you can store functions in an object, you just need one “function object” for each algorithm. That makes the code much clearer and smaller.

3. Create “Higher-Order” Functions

Now comes the fun part. You can use every object as a parameter of a method. So why not call a method with a function argument? Methods that take a function as a parameter or return one are called higher-order functions. Before I can give you an example, we have to learn how to store a function in an object.

Storing a Function in an Object

In Java 8, the java.util.Function<T, R> Interface was introduced. It can store a function that takes one argument and returns an object. The Generic T is the type of the argument, and R is the type of the object you return.

Example: Compute Function

This is a very easy example of a higher-order function. It takes a function and an Integer and computes the given function with the Integer.

Java
 
public static Integer compute(Function<Integer, Integer> function, Integer value) {
    return function.apply(value);
}


Now, we want to use this function to invert an Integer

Java
 
public class AwesomeClass {

    private static Integer invert(Integer value) {
        return -value;
    }

    public static Integer invertTheNumber(){
        Integer toInvert = 5;
        Function<Integer, Integer> invertFunction = AwesomeClass::invert;
        return compute(invertFunction, toInvert);
    }
    
}


There are two interesting lines here. The first one is:

Java
 
return function.apply(value);


The apply method of a Function object just takes an argument and returns the method’s output. In our example, you could also write:

Java
 
return invert(value);


The second interesting line is this one:

Java
 
Function<Integer, Integer> invertFunction = AwesomeClass::invert;


What we use here is a so-called method reference. We make the function invert() to a Function object by using the :: operator. It is one of two ways to store a function in an object. But this code doesn’t make anything easier. You could refactor it like this:

Java
 
public class AwesomeClass {

    private static Integer invert(Integer value) {
        return -value;
    }

    public static Integer invertTheNumber(){
        Integer toInvert = 5;
        return invert(toInvert);
    }
    
}


It doesn’t need a compute function or any fP at all, but it still looks nicer. To make our fP code useful, we have to introduce our second way to store a function in an object. And this is by using anonymous functions, or so-called Lambdas.

How To Work With Lambdas

To work with Lambdas in Java 8, we have to look at a new syntax to handle them properly.

Example: Adding Two Integers

In good old Java 7, you can write a method to add two Integers like this:

Java
 
public Integer add(Integer a, Integer b) {
    return a + b;
}


And this is a Java 8 Lambda, which does exactly the same:

Java
 
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;


That’s pretty straightforward, isn’t it? BiFunction is another Interface in java.util to represent a function with two arguments and one return object. In the brackets of the Lambda, you define the arguments. You don’t have to give them a type. You just have to say how many there are and how each should be called. This is equivalent to

Java
 
(Integer a, Integer b)


In the Java 7 method. Next off, you have the “->” arrow. It is equivalent to the curly brackets and separates the function’s head from its body after the arrow. You can work with the arguments. If you have just one calculation to make, return isn’t necessary because it returns the result of this line. You can also make the function’s body bigger by using curly brackets.

Java
 
BiFunction<Integer, Integer, Integer> add = (a,b) -> {
    Integer result = a + b;
    return result;
};


But most of the time, you just need one line and, therefore, no brackets and no return keyword.

Making the Compute Function Nicer

With that in mind, we can refactor our previous use of the compute function.

Java
 
public class AwesomeClass {

    public static Integer invertTheNumber(){
        Integer toInvert = 5;
        return compute((a) -> -a, toInvert);
    }

}


Now that’s some beautiful code! We can make our invert function to a Lambda. This makes the code nicer than our old fP version and the Java 7 example. We don’t have to create an extra method to invert the Integer; we just have to use a small lambda, which does the work.

You might ask yourself now why we don’t just return -value. And in this case, it would be better. However, if we want to change the function at runtime, our version can be used for this. Thanks to kdm06 for pointing this out.

Java
 
public class AwesomeClass {

    public static Integer changeTheNumber(Function<Integer, Integer> func){
        Integer toChange = 5;
        return compute(func, toChange);
    }

}


Conclusion

That’s it for today! We have made our first big steps towards functional programming in Java 8. First off, we have seen a lot of benefits of fP. After that, we used our first function as an argument in another method by using method references and Lambdas(anonymous functions).

In part 2, we will introduce Optionals and how we can work with them properly.

Thanks for reading, and have a nice day,

Niklas

Object (computer science) Java (programming language) Functional programming

Published at DZone with permission of Niklas Wuensche, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Redefining Java Object Equality
  • Singleton: 6 Ways To Write and Use in Java Programming
  • Writing DTOs With Java8, Lombok, and Java14+
  • Addressing Memory Issues and Optimizing Code for Efficiency: Glide Case

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!