The Suplier interface
The Supplier interface denotes a lambda expression
	that generates an object when invoked. It is commonly used to implement lazy initialisation. This is
	where we want to declare in advance how to create a particular object if and when it is required, rather than having to create
	it up front. The Supplier implementation is the piece of code that determines how to initialise the object in question.
Lambda expressions that can be used as Suppliers
A lambda expression is a Supplier if:
	-  it does not take any parameters;
 
	-  it returns an object.
 
Note the first of the conditions above. In some cases, lazy initialisation may also be performed by a lambda expression that
	is actually strictly speaking a Function because it needs an input value in order to determine what to initialise.
Syntax of a Supplier
Because a Supplier does not have any arguments, its syntax will have a characteristic () to denote the
empty argument list:
Supplier<List> listMaker = () -> new ArrayList();
 
Direct references to no-arg constructors can also be used as Suppliers. To do this, put the class name
	followed by ::new as follows:
Supplier<List> listMaker = ArrayList::new;
 
Common uses of Supplier
As mentioned, a common use of a Supplier is for lazy initialisation. A concrete example of
	this is the ThreadLocal.withInitial() method. In case you have not come across them, a thread local
	variable has an independent value for each thread that references it. Whenever a given thread requests the value,
	it retrieves the value that was last set by that specific thread; other threads can also retrieve their thread-specific
	values at any time. But this leaves the question: what value is returned the first time that a given thread attempts to
	retrieve the value?
We don't generally want the overhead of having to set an initial value in advance for every single thread running on the system,
	without knowing that a particular thread is actually going to want to refer it. (Nor do we want the overhead of having to search
	for all of the thread-local variables to initialise them every time a new thread is started.) And this is where
	ThreadLocal.withInitial() comes to the rescue. We pass in a lambda expression that determines how to create
	the initial value as and when it is required by a particular thread:
ThreadLocal<Calendar> cal =
  ThreadLocal.withInitial(() -> Calendar.getInstance());
 
We could also write:
ThreadLocal<Calendar> cal =
  ThreadLocal.withInitial(Calendar::getInstance);
 
At this point, no calendars have actually been constructed. The very first time a given thread calls cal.get(),
	the Supplier will be invoked, and a new Calendar will be created for that thread. The next time the same
	thread calls cal.get(), that same calendar object will then be returned to it. But no unnecessary objects are
	created if a given thread never actually requires the use of a calendar.
Using Supplier with switchable configuration
Another common use of Supplier is with switchable configuration. In other words, we have particular
	lines of code that we would like to execute if and only if a particular condition is true. For example, we might have
	some lines of debug that we want to log out if debugging mode is enabled. We could write a central logging method
	 such as the following:
public static void debugLog(String msg) {
  if (DEBUG) {
    System.out.println(msg);
  }
}
 
This is functionally sound, but has a minor disadvantage if the logging messages themselves are complex to generate.
Consider this example:
debugLog(String.format("%03d Command: %s", cmdNo, lookupCommand(code)));
 
Here, our code will go to the effort of looking up the
	command and formatting the string even if debug logging is actually turned off!
The Supplier interface provides a solution to this. We can define our logging method as follows:
public static void debugLog(Supplier<String> msg) {
  if (DEBUG) {
    System.out.println(msg.get());
  }
}
 
We would log information like this:
debugLog(() -> String.format("%03d Command: %s", cmdNo, lookupCommand(code)));
 
Now, thanks to lazy initialisation of the log message, the lookup and formatting operation are only performed
	if they are actually required.
   
	  If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants. 
 
	  
	 
     
 
 
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.