What about adding collection functions `.associate...
# stdlib
c
What about adding collection functions
.associateSingle
& family? Inspired by: • `.first`: Takes the first element, ignores others • `.single`: Takes the first element, throws if there are others •
.group
: groups, putting duplicates into a list •
.associate
: groups, ignoring duplicates •
.associateSingle
: groups, same signature as
.associate
, but throws an exception if there are duplicates
Alternatively, make this easier to write in regular code. For example:
Copy code
val foo = list.groupingBy { it.key }
    .eachSingle()
which can be implemented as
Copy code
fun <Key, Value> Grouping<Value, Key>.eachSingle(): Map<Key, Value> {
    return this
        .fold(
            initialValueSelector = { _, element ->
                element
            },
            operation = { key, accumulator, element ->
                throw IllegalArgumentException("""
                Collection contains multiple elements matching key $key:
                 - First element: $accumulator
                 - Second element: $element
            """.trimIndent())
            }
        )
}
v
Taking it's not a very common/popular request, I would suggest going for the third parameter of associate instead: https://youtrack.jetbrains.com/issue/KT-48347/associateBy-with-conflict-resolution
on a side note, I am still not sure if the default behaviour of picking the last element is the right one 🙂 But this ship has sailed anyway
c
My take is that it's not a common request because people don't realize the silent bugs they have due to rare collisions when using associate
👍 2
👍🏻 1
👍🏾 1
I just had a dumb bug because of that :/
v
Yep. But we cannot change
associateBy
(whether it has the right default is a different story), and to use an alternative, one actually has to think whether they don't need the regular
associateBy
anyway
c
True
h
I think a better approach for this would be to have a standard "write-once" map, I've had to implement these several times in my own code, they can be very useful sometimes to assert that each key has only been used once. Then you could just do
.associateByTo(WriteOnceMap()) { ... }
As a side note, I've typically called these write-once maps in my code
Registry
. I have no idea if there's a more 'correct' term for it.