Lazy loading in Java programs

  • 2020-04-01 03:58:04
  • OfStack

One way to improve performance when using multiple objects or big data structures is to use lazy loading or assignment. The idea of making time-consuming operations as short as possible was never realized. I've used some examples to illustrate how lazy loading works in Java, giving some Pointers to make it easier in other languages and as part of the core language.

One usage scenario is to use the JTable to display hundreds of domain objects that contain metadata and measure values. Initialize our domain object to hold two types of objects in memory, even if only partial metadata is displayed in the table. Building the table will take a few seconds, but we can live with hundreds of entries again. After doing some analysis, we improved our implementation to look like this:
 


public class DomainObject {
 private final DataParser parser;
 private final Map<String, String> header = new HashMap<>();
 private final List<Data> data = new ArrayList<>();
 
 public DomainObject(DataParser aParser) {
  parser = aParser;
 }
 
 public String getHeaderField(String name) {
  // Here we lazily parse and fill the header map
  if (header.isEmpty()) {
   header.addAll(parser.header());
  }
  return header.get(name);
 }
 public Iterable<Data> getMeasurementValues() {
  // again lazy-load and parse the data
  if (data.isEmpty()) {
   data.addAll(parser.measurements());
  }
  return data;
 }
}

This improvement improved the time items and significantly improved our ability to work with big data items. All data loads occur only when someone wants to see the details of the measurement and double-click on an item.


A Java unboxing that gets deferred assignment in the case of conditional statements
 


// lazy and fast because the expensive operation will only execute when needed
if (aCondition() && expensiveOperation()) { ... }
 
// slow order (still lazy evaluated!)
if (expensiveOperation() && aCondition()) { ... }

Persistence layer frameworks like Hibernate often default to lazy loading because database access is common and data transfer is expensive.

Most of the language functionality is based around the case of lazy assignment and this theoretical functionality is like the first class where all the members are isolated to the greatest extent to reduce the side effects on latency. Scala mixes object-oriented language capabilities and introduces lazy keywords to simplify Java styles, like the following lazy initialization code
 


public class DomainObject(parser: DataParser) {
 // evaluated on first access
 private lazy val header = { parser.header() }
 
 def getHeaderField(name : String) : String = {
  header.get(name).getOrElse("")
 }
 
 // evaluated on first access
 lazy val measurementValues : Iterable[Data] = {
  parser.measurements()
 }
}

conclusion

Lazy loading is not a new revolutionary technology but it is a very useful tool when dealing with big data or slowing down resources. In many of these cases you can use it to improve performance or the user experiences it.

It can reduce the cost of implementing code if the language support is not good (like Java) and other cases where the application will feel more responsive in the case of precompiled preprocessing.


Related articles: