You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Zhongxin Yan (Jira)" <ji...@apache.org> on 2025/11/27 14:44:00 UTC
[jira] [Created] (LANG-1795) EnumUtils.getEnumMap throw IllegalStateException when keyFunction produces duplicate keys
Zhongxin Yan created LANG-1795:
----------------------------------
Summary: EnumUtils.getEnumMap throw IllegalStateException when keyFunction produces duplicate keys
Key: LANG-1795
URL: https://issues.apache.org/jira/browse/LANG-1795
Project: Commons Lang
Issue Type: Bug
Components: lang.*
Affects Versions: 3.20.0
Reporter: Zhongxin Yan
EnumUtils.getEnumMap(...) currently collect enum values using Collectors.toMap(...) without a merge function.Because the default Collectors.toMap requires the key to be {*}unique{*}, these methods will throw an IllegalStateException if the provided keyFunction produces duplicate keys.
{code:java}
// code placeholder
Example:
class EnumUtilsDuplicateKeyTest {
enum Color {
RED, ROSE
}
@Test
void testGetEnumMapThrowsOnDuplicateKey() {
assertThrows(IllegalStateException.class, () -> {
EnumUtils.getEnumMap(Color.class, c -> c.name().substring(0, 1));
});
}
} {code}
Why this happens
* EnumUtils.getEnumMap(enumClass, keyFunction)constructs a Stream<E> of enum constants (via stream(enumClass)), and then collect(...)s them into a Map using Collectors.toMap.
* The call pattern used is the two-argument Collectors.toMap(keyMapper, valueMapper)(i.e. Collectors.toMap(keyFunction::apply, Function.identity())). This toMap overload {*}requires keys to be unique{*}. Internally, on encountering a duplicate key it throws: “java.lang.IllegalStateException: Duplicate key <theKey>”
* A caller-supplied keyFunction might easily produce duplicate keys — common examples:
# keyFunction = e -> e.name().toLowerCase() — different-cased enum constants become identical keys.
# keyFunction = e -> e.name().substring(0, 1) — multiple names starting with same letter collide.
There are multiple reasonable behaviors when keys collide (keep first, keep last, throw a clearer exception, or return a multi-valued map). The current implementation chooses an implicit and undocumented behavior (throw) by delegating to {{Collectors.toMap}} two-arg overload.
*Proposed fix*
Change the collection step to supply a merge function. A compatible, conservative default is to *preserve the first-seen value*
--
This message was sent by Atlassian Jira
(v8.20.10#820010)