java - 如何使用带有 List 参数的泛型函数
问题描述
有些东西是有重量的,所以这里是它们的界面,例如:
public interface Banana {
public Double getWeight();
}
// This function is a static function in a public tool class.
@Nullable
public static Banana pickItemByTheirWeight(List<Banana> originalVideos) {
// ...
return randomOneByWeight;
}
现在我想创造有重量的东西,所以:
class Video implements Banana {
@Override
public Double getWeight() {
//....
return weight;
}
}
现在,当我想按重量挑选视频时,例如:
List<Video> videos = new ArrayList<>();
// ...
Video randomOne = pickItemByTheirWeight(videos);
我得到一个编译错误。那么正确的方法是什么?
嘿伙计们,这并不容易。
我试过了
public static <T extends Banana> T pickOneByTheirWeight(List<T> domains) {
// ...
}
public abstract class Banana {
public abstract Double getWeight();
}
而且它仍然无法正常工作,我无法在不强制转换类类型的情况下调用该函数。
* 有人能告诉我为什么 Java 选择不让它正常工作吗???*
在阅读了Java泛型的一些基础知识之后,这里有一个解决方案:
public static <T extends Banana> T pickOneByTheirWeight(List<? extends Banana> domains) {
if (domains.isEmpty()) {
return null;
}
// calculate total weight
Double totalWeight = domains.stream().map(x -> {
Double weight = x.getWeight();
return weight == null ? 0.0 : weight;
}).reduce((first, second) -> {
Double firstWeight = first != null ? first : 0.0;
Double secondWeight = second != null ? second : 0.0;
return firstWeight + secondWeight;
}).get();
// random process
final Double randomSeed = Math.random() * totalWeight;
double currentWeight = 0.0;
for (Banana v: domains) {
Double weight = v.getWeight();
weight = weight == null ? 0.0 : weight;
currentWeight += weight;
if (currentWeight >= randomSeed) {
return (T) v;
}
}
// it'll not reach here indeed.
logger.warn("pickDomainByTheirWeight cannot pick an element from list by their weights.");
return null;
}
但是像这样清除函数,我们可以简单地调用:
List<Video> videos = new ArrayList<>();
// ...
Video p = Utility.pickOneByTheirWeight(videos);
然而,没有更多的外部转换,仍然是函数内部的转换。有更好的主意吗?
解决方案
因为List<Banana>
不是一个List<Video>
。将方法签名更改为:
@Nullable
public static Banana pickItemByTheirWeight(List<Video> originalVideos) {
// ...
return randomOneByWeight;
}
或者更好 - 使用通用超类:
@Nullable
public static Banana pickItemByTheirWeight(List<? extends Banana> originalVideos) {
// ...
return randomOneByWeight;
}
推荐阅读
- sql-server - SQL Server 的 Worktable 逻辑读取仍然是每页 8k 吗?
- c - 是否可以在 doxygen 中提取函数注释并在 markdown 中显示?
- tensorflow - 准确了解预训练模型在 Tensorflow 对象检测 API 上的作用
- sql - Postgresql, sql 命令,用相似字符串连接表,只有字符串“OM:”在开头
- webgl - 不支持 OES_texture_float,但 WebGL2 可用
- python - 如何在 Pygame 中每次初始化新对象以重置游戏
- angular - 在 Angular 中发出 http 请求时,图像闪烁并且页面滚动到顶部 - 内部视频
- http - 为什么“安全”cookie 不安全?
- jdbc - 如何检查增加的连接?
- javascript - 动态输入,v-model 更新 v-for 中的所有值