[英]Java: What is an alternative to using generics in this design?
I'm working on an open-source Java library that will allow one to compute certain quantities, such as Gini index, of an attribute that takes on a finite number of values. 我正在开发一个开放源Java库,该库将允许人们计算具有一定数量值的属性的某些数量,例如Gini索引。 (Formally, it computes the Gini index of the discrete distribution associated with the attribute
A
, but this is not relevant here.) (从形式上讲,它计算与属性
A
关联的离散分布的基尼系数,但这与此处无关。)
For example, one will be able to do the following 例如,一个人将能够执行以下操作
String[] namesArray = {"primary_school", "high_school", "university"};
Calculator<String> calc =new Calculator<String>(namesArray);
// p.getEducationLevel() returns `"primary_school"`, `"high_school"`, or `"university"`.
for (Person p : peopleCollection) {
calc.increment(p.getEducationLevel());
}
// e.g. the Gini index of the distribution
double currentStat = calc.getCurrentValue();
The idea is to allow users of the library to use their own type to refer to attribute values; 这个想法是允许库的用户使用他们自己的类型来引用属性值。 in this case, I am using strings (eg
"primary_school"
). 在这种情况下,我正在使用字符串(例如
"primary_school"
)。 But I might want to use integers or even my own type AttributeValue
. 但是我可能要使用整数,甚至是我自己的
AttributeValue
类型。
I solve this by defining 我通过定义解决
public class Calculator<T> {
/* ... */
}
However, using generics causes some problems in the implementation: for example, if I want to maintain a collection of pairs of type (T, double)
, I have to do nasty type casts: 但是,使用泛型会在实现过程中引起一些问题:例如,如果我想维护类型对
(T, double)
的集合,则必须进行讨厌的类型转换:
public class Calculator<T>
/* ... */
private Queue<StreamElement<T>> slidingWindow;
/* ... */
class StreamElement<T> {
private T label;
private double value;
StreamElement(T label, double value) {
this.label = label;
this.value = value;
}
public T getLabel() {
return label;
}
public double getValue() {
return value;
}
}
/* ... */
slidingWindow.add(new StreamElement<T>(label, value));
if (slidingWindow.size() > windowSize) {
StreamElement lastElement = slidingWindow.remove();
// XXX: Nasty type cast
decrement((T)lastElement.getLabel(), lastElement.getValue());
}
/* ... */
}
Here is the warning produced by javac
: 这是
javac
产生的警告:
Calculator.java:163: warning: [unchecked] unchecked cast
decrement((T)lastElement.getLabel(), lastElement.getValue());
^
required: T
found: Object
where T is a type-variable:
T extends Object declared in class Calculator
1 warning
Update. 更新。 If I do not do the type cast, I get
如果我不进行类型转换,我会得到
Calculator.java:163: error: no suitable method found for decrement(Object,double)
decrement(lastElement.getLabel(), lastElement.getValue());
^
method Calculator.decrement(T) is not applicable
(actual and formal argument lists differ in length)
method Calculator.decrement(T,double) is not applicable
(actual argument Object cannot be converted to T by method invocation conversion)
where T is a type-variable:
T extends Object declared in class Calculator
1 error
Questions: 问题:
Label
which user could extend to MyLabel
and then use MyLabel
for attribute values? MyLabel
然后使用MyLabel
作为属性值的Label
类吗? This means that Calculator
would no longer be a generic type; Calculator
将不再是通用类型; in the implementation we'd have class StreamElement { Label label; /* ... */ }
class StreamElement { Label label; /* ... */ }
class StreamElement { Label label; /* ... */ }
et cetera. class StreamElement { Label label; /* ... */ }
等。 I think you just made some mistake. 我认为您刚刚犯了一些错误。
This is the correct implementation: 这是正确的实现:
/* ... */
slidingWindow.add(new StreamElement<T>(label, value));
if (slidingWindow.size() > windowSize) {
// Don't forget the generic argument at StreamElement
StreamElement<T> lastElement = slidingWindow.remove();
decrement(lastElement.getLabel(), lastElement.getValue());
}
/* ... */
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.