Как да накарам enum-ите да използват своя метод compareTo, когато имплементират интерфейс?

Структурата е следната:

public interface ItemList{ }

public enum ItemList1 implements ItemList {

    Apple,
    Orange;
}

public enum ItemList2 implements ItemList {

    Banana,
    Grapes;
}

и още 5 такива изброявания

Изискването е тези изброявания да се използват като ключове в карта и в тези карти съм поставил ключ като:

public Class SomeClass {
private Map<ItemList, OtherObject> objectList;
//other code
}

ItemList, който влиза в картата, се определя по време на изпълнение. И трябва да използвам сортирана карта като TreeMap за други операции. И така, TreeMap не може да сравни ключовите enum-и, очевидно защото съм ги декларирал като супертип ItemList.

И така, потърсих други въпроси и направих нещо подобно, така че enum-ите да могат да използват своя метод compareTo:

public interface ItemList<SelfType extends ItemList<SelfType>> extends Comparable<SelfType>{ }

public enum ItemList1 implements ItemList<SelfType> {
     //enum values
}

Но това не решава проблема. Все още получавам същото „ClassCastException“, когато се опитах да извлека TreeMap, който имаше моите enum като ключове.

Моля, предложете дали правя нещо нередно тук или какъв може да бъде друг начин за разрешаване на тази цел?

РЕДАКТИРАНЕ: Връзка към решението, което последвах, но не работи: Как да имплементирам интерфейс с enum, където интерфейсът разширява Comparable?

РЕДАКТИРАНЕ 2 Установен проблем. Съжалявам момчета. Моята карта се попълваше с различни типове enum като ключове, когато всички ключове трябва да принадлежат към един и същи тип, за да работи сортирането.


person Anmol Gupta    schedule 08.04.2015    source източник
comment
Не разбирам защо картата не може да сортира ключовете. Докато съдържа само екземпляри на ItemList1 или само екземпляри на ItemList2, всичко трябва да работи добре. И от вашето описание изглежда, че е така.   -  person JB Nizet    schedule 08.04.2015
comment
Не можете да поставите константи от две различни enum в един TreeMap като ключове. По принцип не можете да ги сравнявате.   -  person Rohit Jain    schedule 08.04.2015
comment
@JBNizet Да, същото нещо ме притеснява. Проверих го толкова много пъти. Проследих отговора на този въпрос stackoverflow.com/questions/7160980/   -  person Anmol Gupta    schedule 08.04.2015
comment
@RohitJain Картата се попълва само с един тип списък. Но кой enum ще бъде попълнен с това се решава по време на изпълнение.   -  person Anmol Gupta    schedule 08.04.2015
comment
@AnmolGupta Тогава не можете да получите ClassCastException.   -  person Rohit Jain    schedule 08.04.2015
comment
@RohitJain Благодаря, Рохит! Проверих внимателно и да, картата се попълваше с различни типове списък като ключове и следователно изключението.   -  person Anmol Gupta    schedule 08.04.2015


Отговори (2)


Е, вече разбрахте, че действителното съдържание на Map, а не декларацията на класовете е причинило изключението, но си струва да се отбележи, че използването на колекции, сравняващи тези enum, е по-лесно, отколкото си мислите.

напр. TreeMap не се интересува дали неговият деклариран общ тип има сравним ключ или не. Ако имате декларации на класове като

public interface ItemList{ }
public enum ItemList1 implements ItemList { Apple, Orange }
public enum ItemList2 implements ItemList { Banana, Grapes }

можете просто да го използвате като

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);

без проблеми; дори работи, ако декларирате картата като TreeMap<Object,Object>.

Имайте предвид, че някои методи изискват сравними типове, когато заявяват естествен ред, като не посочват Comparator, напр. с декларациите за тип по-горе,

List<Object> list=Arrays.<Object>asList(ItemList1.Orange,ItemList1.Apple,ItemList1.Orange);
Collections.sort(list);

не се компилира, но можете лесно да го заобиколите, като поискате естествения ред чрез null Comparator:

Collections.sort(list, null); // compiles and works

Така че не е необходимо да се забърквате с декларации на сложни типове като ItemList<SelfType extends ItemList<SelfType>> в повечето случаи.

person Holger    schedule 10.04.2015
comment
Благодаря, Холгер, това допълни познанията ми за използването на TreeMap. Само за да съм сигурен, че го разбирам правилно, така че когато нямам конкретен компаратор за ключове на дървовидна карта, той просто ще приеме естествения ред, докато сортира, нали? А за методите, които изискват компараторът да бъде изрично споменат, мога просто да предам null като компаратор за естествен ред, който все още се счита за сортиран ред? Благодаря! - person Anmol Gupta; 13.04.2015
comment
Вярно, неуказването на Comparator винаги предполага естествено подреждане и претоварванията, пропускащи параметъра, обикновено налагат Comparable елементи, докато методите, приемащи Comparator, не го правят. Не мога да говоря за всеки възможен метод, но документацията на Collections.sort и Collections.binarySearch ясно определят поведението за null компаратор. - person Holger; 13.04.2015

Звучи сякаш това, което трябва да правите, е да имате

 private Map<? extends ItemList, OtherObject> objectList;

...за да посочите, че objectList е конкретна карта на някакъв подтип на ItemList, и след това

 objectList = new TreeMap<ItemList1, OtherObject>();

or

 objectList = new TreeMap<ItemList2, OtherObject>();

за да го декларирате като някакъв специфичен тип ItemList. (Може да се наложи да го съхраните временно като Map<ItemListN, OtherObject>, докато го попълвате, но след това можете да го поставите в objectList.

person Louis Wasserman    schedule 08.04.2015
comment
Благодаря Луи за бързия отговор, проблемът беше, че Map се попълни с различни типове enums в даден момент и аз го помолих да сравни ябълки с банани, така че хвърли изключение :) - person Anmol Gupta; 08.04.2015