This content originally appeared on HackerNoon and was authored by Nicolas Frankel
\ In this post, I'll explain how to provide a default value when querying an absent key in a hash map in different programming languages.
Java
Let's start with Java, my first professional programming language.
\
In older versions, retrieving a value from a map required using the get()
method:
\
Map map = new HashMap(); //1
Object value = map.get(new Object()); //2
if (value == null) {
value = "default"; //3
}
- Initialize an empty map
- Attempt to retrieve a non-existent key
- Assign a default value if the key is absent
\
With Java 1.8, the Map
interface introduced a more concise way to handle absent keys:
\
var map = new HashMap<Object, String>();
var value = map.getOrDefault(new Object(), "default"); //1
- Retrieve the value with a default in one step
Kotlin
Kotlin provides several approaches to retrieving values from a map:
\
get()
andgetOrDefault()
function just like their Java counterparts.getValue()
throws an exception if the key is missing.getOrElse()
accepts a lambda to provide a default value lazily.
\
val map = mapOf<Any, String>()
val default = map.getOrDefault("absent", "default") //1
val lazyDefault = map.getOrElse("absent") { "default" } //2
- Retrieve the default value
- Lazily evaluate the default value
Python
Python is less forgiving than Java when handling absent keys—it raises a KeyError
:
\
map = {}
value = map['absent'] #1
- Raises a
KeyError
\
To avoid this, Python offers the get()
method:
\
map = {}
value = map.get('absent', 'default') #1
\
Alternatively, Python's collections.defaultdict
allows setting a default for all absent keys:
\
from collections import defaultdict
map = defaultdict(lambda: 'default') #1
value = map['absent']
- Automatically provide a default value for any absent key
Ruby
Ruby's default behavior returns nil
for absent keys:
\
map = {}
value = map['absent']
\
For a default value, use the fetch
method:
\
map = {}
value = map.fetch('absent', 'default') #1
- Provide a default value for the absent key
\ Ruby also supports a more flexible approach with closures:
\
map = {}
value = map.fetch('absent') { |key| key } #1
- Return the queried key instead of a constant
Lua
My experience with Lua is relatively new, having picked it up for Apache APISIX. Let's start with Lua's map syntax:
\
map = {} --1
map["a"] = "A"
map["b"] = "B"
map["c"] = "C"
for k, v in pairs(map) do --2
print(k, v) --3
end
- Initialize a new map
- Iterate over key-value pairs
- Print each key-value pair
\ Fun fact: the syntax for tables is the same as for maps:
\
table = {} --1
table[0] = "zero"
table[1] = "one"
table[2] = "two"
for k,v in ipairs(table) do --2
print(k, v) --3
end
- Initialize a new map
- Loop over the pairs of key values
- Print the following:
1 one
2 two
Lua arrays start at index 0!
\ We can mix and match indices and keys. The syntax is similar, but there's no difference between a table and a map. Indeed, Lua calls the data structure a table:
\
something = {}
something["a"] = "A"
something[1] = "one"
something["b"] = "B"
for k,v in pairs(something) do
print(k, v)
end
\ The result is the following:
\
1 one
a A
b B
I
n Lua, absent keys return nil
by default:
\
map = {}
value = map['absent']
\
To provide a default, Lua uses metatables and the __index
metamethod:
\
Metatables allow us to change the behavior of a table. For instance, using metatables, we can define how Lua computes the expression
a+b
, wherea
andb
are tables. Whenever Lua tries to add two tables, it checks whether either of them has a metatable and whether that metatable has an__add
field. If Lua finds this field, it calls the corresponding value (the so-called metamethod, which should be a function) to compute the sum.
\ Each table in Lua may have its own metatable.
\
As I said earlier, when we access an absent field in a table, the result is nil. This is true, but it is not the whole truth. Such access triggers the interpreter to look for an
__index
metamethod: if there is no such method, as usually happens, then the access results in nil; otherwise, the metamethod will provide the result.\ -- The
__index
Metamethod
\ Here's how to use it:
\
table = {} --1
mt = {} --2
setmetatable(table, mt) --3
mt.__index = function (table, key) --4
return key
end
default = table['absent'] --5
- Create the table
- Create a metatable
- Associate the metatable with the table
- Define the
__index
function to return the absent key - The
__index
function is called because the key is absent
Summary
This post explored how to provide default values when querying absent keys across various programming languages. Here's a quick summary:
| | Scope | Scope | Value | Value | |----|----|----|----|----| | Programming Language | Per call | Per map | Static | Lazy | | Java | ❎ | ❌ | ❎ | ❌ | | Kotlin | ❎ | ❌ | ❎ | ❎ | | Python | ❎ | ❎ | ❌ | ❎ | | Ruby | ❎ | ❌ | ❎ | ❎ | | Lua | ❌ | ❎ | ❎ | ❌ |
\
This content originally appeared on HackerNoon and was authored by Nicolas Frankel
Nicolas Frankel | Sciencx (2024-08-15T14:45:38+00:00) Default Values for Absent Keys: A Cross-Language Guide to Hash Map Querying. Retrieved from https://www.scien.cx/2024/08/15/default-values-for-absent-keys-a-cross-language-guide-to-hash-map-querying/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.