Heart containing Coding Chica Java 101

Avoid Reinventing the Wheel! Java Method References

TIP: References Quick List

Table of Contents

  1. Table of Contents
  2. Introduction
  3. Constructor References
  4. Instance Method References
  5. Arbitrary Instance Method Reference
  6. Static Method References
  7. Example Code
  8. Summary

Introduction

When using a Java Stream (or other methods that would accept a lambda expression as an input) if we intend to simply reference already named methods, then we can do so directly, rather than re-defining them as lambda expressions (unnamed methods). This is called a method reference and is indicated with two colons (::) in the instruction. The inputs passed to a method reference, similar to a lambda expression, vary by the context in which the lambda expression or the method reference is invoked. The the case of a method reference, only the explicit parameters are consumed.

Constructor References

A call to a constructor is indicated by <ClassName>::new, for example:

  • Lambda expression: () -> new TreeSet()
  • Method reference: TreeSet::new

Instance Method References

To call a method on a particular object/instance, such as a variable available in the current scope that is defined outside of a stream’s pipeline, we can use a method reference, like: <variableName>::methodName

  • Lambda expression: .forEachOrdered((item) -> stringBuilder.append(item))
  • Method reference: .forEachOrdered(stringBuilder::append)

Arbitrary Instance Method Reference

When a stream provides the needed input parameters, we don’t necessarily care about the names of those ordered input parameters. In this case, we can consume them in order if there is more than one. Here, there is only one input, so that is the arbitrarily named instance upon which we call the toUpperCase method.

  • Lambda expression: .map((item) -> item.toUpperCase())
  • Method reference: .map(String::toUpperCase)

Were we to invoke a method reference when more than one input is available, they would be consumed in-order:

  • Lambda expression: .sorted((a,b) -> a.compareToIgnoreCase(b))
  • Method reference: .sorted(String::compareToIgnoreCase)

In other cases, such as when we provide the collect method a constructor method reference and then arbitrary method references for add and addAll methods, the pipeline is responsible for constructing one ore more lists, adding elements to those lists, and (if necessary) combining those lists into a single List as an output:

    .collect(ArrayList::new,
            ArrayList::add,
            ArrayList::addAll)

Be sure to read the Javadoc for whatever method you are invoking if you are unsure how the method reference(s) will be used.

Static Method References

When referencing a static method, we provide the class name as a prefix to the method name within the method reference. In this example, the input from a stream would be used as the input parameter to that method.

Example Code

An example of using method references in place of lambda expressions for a Java stream pipeline is as follows:

String[] names = {"Sally", "Jane", "Sue", "Rose"};
List<String> allCapsSortedNames = Arrays.stream(names)
        .filter(Objects::nonNull)
        .sorted(String::compareToIgnoreCase)
        .map(String::toUpperCase)
        .collect(ArrayList::new,
                ArrayList::add,
                ArrayList::addAll); 

Summary

Java method references can be used in place of lambda expressions if all the lambda expression will do is call an existing, named method. Method references can be used for constructors, static methods, or instance methods and are intended to aid in the clarity and brevity of the code. How arbitrary method references are consumed may vary by the method consuming the method reference(s) as inputs and the type of the stream (serialized vs. parallel). Be sure to read the Javadoc for the given method consuming those inputs to understand the expectations. Unlike a lambda expression, method references only consume explicit input parameters based upon the context/location where the method reference is invoked. While a lambda expression can also consume implicit input parameters based upon variables available in the surrounding scope where defined, the method reference will not do so. Method references can be used in Java stream pipelines or in stand-alone method calls where a lambda expression would be provided, assuming that the lambda expression that will be consumed is just a call to an existing, named method.

Avoid Reinventing the Wheel! Java Method References

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.