Lazy

Lazy evaluation (called short-circuit evaluation in compiled languages) is a strategy some programming languages use to save work for the last minute or avoid unnecessary work altogether. For example, suppose we had a conditional like this:

if (itIsFriday && itIsRaining) { System.out.println("board games at my place!"); }

Suppose itIsFriday was false. Because Java short-circuits evaluation, it wouldn't bother checking the value of itIsRaining—it knows that either way the result of our && will be false, so we won't print the invitation to board game night.

We can use this to our advantage. For example, suppose we have a check like this:

if (friends.get("Becky").isFreeThisFriday()) { inviteToBoardGameNight(friends.get("Becky")); }

What happens if 'Becky' isn't in our friends hash map? In Java, we'll get a NullPointerException (Python would similarly raise a KeyError, but Ruby and JavaScript would just give us a null object).

Instead, we could first confirm that 'Becky' and I are still on good terms:

if (friends.containsKey("Becky") && friends.get("Becky").isFreeThisFriday()) { inviteToBoardGameNight(friends.get("Becky")); }

This way, if 'Becky' isn't in friends, Java will skip the second check about Becky being free and avoid throwing the NullPointerException!

This is all hypothetical, of course. It's not like things with Becky are weird or anything. We're totally cool. She's still in my friends hash map for sure and I hope I'm still in hers and Becky if you're reading this I just want you to know you're still in my friends hash map.

We can also take a lazy approach in system design. For example, suppose we had a class for tracking temperatures:

import java.util.ArrayList; import java.util.List; class TempTracker { private List<Integer> recordedTemps = new ArrayList<>(); public void record(int temp) { recordedTemps.add(temp); } }

Suppose we wanted to add a feature for getting the the highest temperature we've seen so far. We could "eagerly" keep the max up to date whenever we insert a new temperature:

import java.util.ArrayList; import java.util.List; class TempTrackerEager { private List<Integer> recordedTemps = new ArrayList<>(); private int maxTemp = Integer.MIN_VALUE; public void record(int temp) { recordedTemps.add(temp); if (temp > maxTemp) { maxTemp = temp; } } public int getMax() { return maxTemp; } }

Or we could lazily (or "just in time") calculate the max whenever it's requested:

import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; class TempTrackerLazy { private List<Integer> recordedTemps = new ArrayList<>(); public void record(int temp) { recordedTemps.add(temp); } public int getMax() throws NoSuchElementException { int maxTemp = 0; try { maxTemp = Collections.max(recordedTemps); } catch (ClassCastException ex) { // will never get here } return maxTemp; } }

The best choice depends on how often you expect to run getMax!

Becky, I haven't hosted another board game night since the incident. I know we both said things we didn't really mean and anyway Becky just if you're reading this please know that I've been cake free for 3 whole days now and it's hard but I'm doing it for you PLEASE Becky. Please.

What's next?

If you're ready to start applying these concepts to some problems, check out our mock coding interview questions.

They mimic a real interview by offering hints when you're stuck or you're missing an optimization.

Try some questions now

. . .