[ 
https://issues.apache.org/jira/browse/LANG-1795?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Gary D. Gregory resolved LANG-1795.
-----------------------------------
    Resolution: Not A Bug

> 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
>            Priority: Major
>         Attachments: image-2025-11-27-23-29-17-928.png
>
>
> 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. [~ggregory] 
>  
> {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}
> !image-2025-11-27-23-29-17-928.png|width=722,height=145!
> 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)

Reply via email to