我有几种类型Objects
,我试图计算。这些对象彼此非常不同,但共同的特征是它们每个都有一个描述它们的Enum
常量。
例如,Day.getDayOfWeek()
成员可能会返回DayOfWeek.THURSDAY
。 Card.getSuit()
可能会返回Suit.SPADE
,Dog.getBreed()
可能会返回枚举常量Breed.LABRADOR
等等。
现在,让我们说我有List<T>
个这些对象(List<Dog>
,List<Card>
等等...),我想根据这些对象计算这些对象他们的枚举状态。单独地,我可以做以下事情:
public int[] getSuitCount(List<Card> cardList, int enumSize) {
int[] array = new int[enumSize];
for (Card card : cardList) {
++array[ card.getSuit().ordinal() ];
}
return array;
}
public int[] getDayCount(List<Day> dayList, int enumSize) {
int[] array = new int[enumSize];
for (Day day : dayList) {
++array[ day.getDayOfWeek().ordinal() ];
}
return array;
}
public int[] getBreedCount(List<Dog> dogList, int enumSize) {
int[] array = new int[enumSize];
for (Dog fido : dogList) {
++array[ fido.getBreed().ordinal() ];
}
return array;
}
虽然这可行,但它非常重复。以下是优选的:
public int[] getEnumCount(List<T> itemList, int enumSize
SomeFunction GENERIC_FUNCTION() ) {
int[] array = new int[enumSize];
for (Class<T> item : itemList) {
++array[ item.GENERIC_FUNCTION().ordinal() ];
}
return array;
}
...唯一的问题是,GENERIC_FUNCTION()
在其调用的每个成员中都有不同的名称。有没有办法表示泛型函数?当我说泛型时,我的意思是,GENERIC_FUNCTION()
是否可以表示getSuit()或getBreed(),因为它们都返回Enum<?>
?
我希望能够将List<Card>
和Card.getSuit()
个参数传递给此函数,并获得正确的计数。我有这种结构的数百个函数,因此在可读性和维护方面这是一个非常不可忽视的优化。
注意:我根本无法编辑任何这些类。我唯一能做的就是使用泛型函数,如果存在这样的话。
答案 0 :(得分:2)
如果您有Java 8编译器,则可以使用lambda表达式方便地执行此操作。
public int[] getEnumCount(List<T> itemList, int enumSize
Function<T, Enum<?>> enumGetterFunction) {
int[] array = new int[enumSize];
for (Class<T> item : itemList) {
++array[ enumGetterFunction.apply(item).ordinal() ];
}
return array;
}
Function
是一个类似于Callable
或Runnable
的接口,但它接受一个参数并返回结果。您可以使用lambda语法(Function
)创建(Dog d) -> d.getBreed()
,这意味着您可以像这样调用getEnumCount
:
int[] counts = getEnumCount(listOfDogs, Breed.values().length, (Dog d) -> d.getBreed());
或甚至更短,使用方法参考(相当于上述):
int[] counts = getEnumCount(listOfDogs, Breed.values().length, Dog::getBreed);
答案 1 :(得分:1)
如果您使用Java 8,则应该能够使用method references。
答案 2 :(得分:1)
没有Java 8(让我们说Java 7),或者只是使用泛型,这是完全可能的。 lambda或委托函数的泛型等效函数是一个函数接口,可以调用一个定义的方法。
首先定义一个功能通用接口,它将为您提供一个通用方法来调用,并且可以为每个具体类型覆盖:
interface GetEnumFromType<S> {
Enum getEnum(S item);
}
现在你在计算方法中调用它:
public static <T> int[] getEnumCount(List<T> itemList, int enumSize,
GetEnumFromType<T> converter) {
int[] array = new int[enumSize];
for (T item : itemList) {
++array[ converter.getEnum(item).ordinal() ];
}
return array;
}
最后你可以通过为每个类型创建一个匿名类来调用它,这个类调用实际的&#34; enum&#34;方法(如果你在很多地方使用它,则为具体类):
int[] suitCounts = getEnumCount(cards, Suits.values().length,
new GetEnumFromType<Card>(){
public Enum getEnum(Card card) { return card.getSuit(); }
});
int[] dayCounts = getEnumCount(days, DayOfWeek.values().length,
new GetEnumFromType<Day>() {
public Enum getEnum(Day day) { return day.getDayOfWeek(); }
});
int[] dogCounts = getEnumCount(dogs, Breeds.values().length,
new GetEnumFromType<Dog>(){
public Enum getEnum(Dog fido) { return fido.getBreed(); }
});