Reputation: 2957
The structure is like this:
public interface ItemList{ }
public enum ItemList1 implements ItemList {
Apple,
Orange;
}
public enum ItemList2 implements ItemList {
Banana,
Grapes;
}
and 5 more such enums
The requirement is to use these enums as Keys in a Map, and in those Maps I have put key as:
public Class SomeClass {
private Map<ItemList, OtherObject> objectList;
//other code
}
The ItemList which goes into the map is decided on runtime. And I need to use a sorted Map like TreeMap for other operations. So, the TreeMap is unable to compare the key enums obviously because I have declared them as ItemList supertype.
So, I searched other questions and did something like this so that enums could use their compareTo method:
public interface ItemList<SelfType extends ItemList<SelfType>> extends Comparable<SelfType>{ }
public enum ItemList1 implements ItemList<SelfType> {
//enum values
}
But this doesn't solve the problem. I am still getting the same "ClassCastException" when I tried to retrieve a TreeMap which had my enums as Keys.
Please suggest if I am doing anything wrongly here, or what can be an other way to solve this purpose?
EDIT: Link to the solution which I followed, but it's not working: How to implement an interface with an enum, where the interface extends Comparable?
EDIT 2 Problem identified. Sorry guys. My map was getting populated with different types of enums as keys, when all the keys should belong to same type for sorting to work.
Upvotes: 2
Views: 308
Reputation: 298599
Well, you already found out that it was the actual content of the Map
, not the declaration of the classes that caused the exception, but it’s worth noting that using collections comparing these enum
s is easier than you think.
E.g. TreeMap
doesn’t care whether its declared Generic type has a comparable key or not. If you have class declarations like
public interface ItemList{ }
public enum ItemList1 implements ItemList { Apple, Orange }
public enum ItemList2 implements ItemList { Banana, Grapes }
you can simply use it as
TreeMap<ItemList,Object> tm=new TreeMap<>();
tm.put(ItemList1.Apple, "A");
tm.put(ItemList1.Orange, "O");
System.out.println(tm.get(ItemList1.Apple)+" is for "+ItemList1.Apple);
tm.clear();
tm.put(ItemList2.Banana, "B");
tm.put(ItemList2.Grapes, "G");
System.out.println(tm.get(ItemList2.Banana)+" is for "+ItemList2.Banana);
without problems; it even works if you declare the map as TreeMap<Object,Object>
.
Note that some methods require comparable types when requesting natural order by not specifying a Comparator
, e.g. with the type declarations above,
List<Object> list=Arrays.<Object>asList(ItemList1.Orange,ItemList1.Apple,ItemList1.Orange);
Collections.sort(list);
does not compile, however, you can easily circumvent it by requesting the natural order via a null
Comparator
:
Collections.sort(list, null); // compiles and works
So it’s not necessary to mess around with complicated type declarations like ItemList<SelfType extends ItemList<SelfType>>
in most cases.
Upvotes: 1
Reputation: 198591
It sounds like what you should be doing is having
private Map<? extends ItemList, OtherObject> objectList;
...to indicate objectList
is a specific map of some subtype of ItemList
, and then
objectList = new TreeMap<ItemList1, OtherObject>();
or
objectList = new TreeMap<ItemList2, OtherObject>();
to declare it as some specific type of ItemList
. (You may have to store it temporarily as a Map<ItemListN, OtherObject>
while you populate it, but then you can put it in objectList
.
Upvotes: 0