Search code examples
javaexceptioncollectionsenumshashmap

how to solve exception class java.util.HashMap$Values cannot be cast to class java.util.Enumeration in HashMap


I am getting the error in ClassCastException as below.

java.lang.ClassCastException: class java.util.HashMap$Values
cannot be cast to class java.util.Enumeration
(java.util.HashMap$Values and java.util.Enumeration are in module
java.base of loader 'bootstrap') 
public static void addMemberships(final int key, MembershipData[] members) throws SpiderException
  {
    HashMap duplicates = new HashMap();
    for (int i=0; i<members.length; i++)
    {
      if (duplicates.get(members[i].subjectOfCare) == null) {
        duplicates.put(members[i].subjectOfCare, members[i]);
      }
    }

    members = new MembershipData[duplicates.size()];
    Enumeration elements = (Enumeration) duplicates.values();    //line where error occurs

    for (int i=0; i<members.length; i++){
      members[i] = (MembershipData) elements.nextElement();      
    }

    internalMembershipToolkit.verifyData(key, members);
  }

I tried using Enumeration elements = new IteratorEnumeration(duplicates.keySet().iterator()); but then I get another ClassCastException. Any advice on how to solve this?


Solution

  • Enumeration is an ancient interface that you should almost never need. It has been superseded by the Collection API, introduced in JDK 1.2, back-then in 1998.

    When you use the capabilities of the Collection API, your entire code can be simplified to

    public static void addMemberships(int key,MembershipData[] members) throws SpiderException
    {
        HashMap<Object, MembershipData> duplicates = new HashMap<>();
        for(MembershipData m: members) duplicates.putIfAbsent(m.subjectOfCare, m);
    
        members = duplicates.values().toArray(new MembershipData[0]); 
    
        internalMembershipToolkit.verifyData(key, members);
    }
    

    Note that assigning a new array to the parameter variable members does not alter the caller’s array. You could also pass the new array directly to the verifyData call, like

    internalMembershipToolkit.verifyData(key,
        duplicates.values().toArray(new MembershipData[0]));
    

    More than often, you get even more advantages from the Collection API when eliminating the need to convert from and to an array. E.g. when you change the verifyData to accept a Collection<MembershipData> instead of MembershipData[], you can simply pass the duplicates.values() to the method, without the need to copy it into a new array.