Finding a value from a List
using closure .find(
) often causes a performance problem in case of:
calling
.find()
closure on theList
having many itemsthe closure
.find()
is called too frequently (e.g. from an LPG line item on a big LPG)
The complexity of searching in a List is O(n). The complexity of searching in a Map is with high probability O(1). Therefore the recommended approach is to convert the List
data to Map
first and use Map.get()
to find the value. You List.find()
should be used only if you know it will not be called many times or on a list with many items.
The Map can use any type object as a key. Therefore is more recommended to use a List as key in case of multiple key fields instead of a concatenated String. Since concatenated String depends on a chosen separator char and that can potentially lead to an error if the character comes in the data one day. Also makes the code worse to read and maintain for the other team members.
Wrong use of .find()
:
def pricingRules = api.findLookupTableValues("PricingRule") def pricingRule = pricingRules.find { record -> record.key1 == "CZ" && record.key2 == "Beef" && record.key3 == "A" }
Correct use of .groupBy()
, but wrong use of concatenated String:
def pricingRules = api.findLookupTableValues("PricingRule", ["key1", "key2", "key3", "attribute1"], null, null) .groupBy { record -> record.key1 + "|" + record.key2 + "|" + record.key3 } def pricingRule = pricingRules["CZ|Beef|A"]
Correct, using .groupBy()
by List:
def pricingRules = api.findLookupTableValues("PricingRule", ["key1", "key2", "key3", "attribute1"], null, null) .groupBy { record -> [record.key1, record.key2, record.key3] } def pricingRule = pricingRules[["CZ", "Beef", "A"]]
Correct, using .collectEntries()
by List:
def pricingRules = api.findLookupTableValues("PricingRule", ["key1", "key2", "key3", "attribute1"], null, null) .collectEntries { record -> [([record.key1, record.key2, record.key3]): record.attribute1] } def margin = pricingRules[["CZ", "Beef", "A"]]