1

I am using this code:

A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);

I believe that Java is lazy so if aMap.contains(key)) then the createAExpensively() function is never called.

Then, I stumbled onto the Map.getOrDefault() method. If we instead use:

A a = aMap.getOrDefault(key, createAExpensively(key));

is Java still lazy in calling the createAExpensively() function?

It seems that Java will first create the object A and pass it as a method parameter, based on this question, but I'm not totally sure.

If Java is not lazy when using Map.getOrDefault(), what is the point of that method?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
zli
  • 307
  • 1
  • 12

5 Answers5

3

Is Java still lazy in calling the createAExpensively() function? [in .getOrDefault(key, createAExpensively(key))]

Function parameters are evaluated (from left to right) before actually calling the function. So createAExpensively(key) will be evaluated before calling getOrDefault. This behavior is also known as applicative order evaluation strategy.

If Java is not lazy when using Map.getOrDefault(), what is the point of that method?

It's useful when the default value is not expensive to create, for example when it's an already computed value or constant. In that case the Map.getOrDefault(...) call allows a more compact syntax than the ternary operator.

If the default value is expensive to compute, and if you actually want to put the computed value in the map, then as of Java 8, you can use computeIfAbsent:

A a = aMap.computeIfAbsent(key, k -> createAExpensively(k));
janos
  • 120,954
  • 29
  • 226
  • 236
  • `computeIfAbsent` is not the lazy version of `getOrDefault`. The former mutates the map if the key doesn't exist; the latter doesn't. – Helder Pereira Aug 30 '17 at 16:47
  • 1
    @HelderPereira Ouch, good call. Thanks, clarified that point. – janos Aug 30 '17 at 16:52
  • Unfortunately, there isn't a method for it in the `Map` interface. However, we can still work it around with a single call to the map by using `Optional`s: `A a = Optional.ofNullable(aMap.get(key)).orElseGet(() -> createAExpensively(key));`. – Helder Pereira Aug 30 '17 at 17:06
  • @HelderPereira yeah, but I don't think it would be an improvement over the ternary. – janos Aug 30 '17 at 17:07
  • Depends how expensive the calls to the map are. I have a map backed by RocksDB. :D – Helder Pereira Aug 30 '17 at 17:11
2

Java is not lazy at all. You are using conditional operator to check whether aMap.contains(key). If this is true it will never call createAExpensively(key) but aMap.get(key)

Adeel
  • 413
  • 1
  • 7
  • 22
1

It isn't lazy in that case.

The point of the method is that there's lots of times when the default is a constant or something you've already computed anyway. For example, you might use getOrDefault(key, 0) when you're getting some kind of count and absent keys should be counted as zeroes.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

This is called "short-circuit evaluation" rather than lazy evaluation: The JVM is not deferring evaluation of createExpensively(), but rather avoiding it completely if it's not necessary, i.e if the condition holds.

See also the answer to the following question here on StackOverflow:

Java logical operator short-circuiting

einpoklum
  • 118,144
  • 57
  • 340
  • 684
1

It is not lazy at all.

This code

A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);

evaulates to

if (aMap.contains(key)) 
{
  a = aMap.get(key);
}
else 
{
  a = createAExpensively(key);
}
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64