java - 如何使用带有 List 参数的泛型函数

标签 java oop generics arraylist java-8

有些东西是有重量的,所以这是它们的界面,例如:

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

或者更好 - 使用通用父类(super class):

@Nullable
public static Banana pickItemByTheirWeight(List<? extends Banana> originalVideos) {
    // ...
    return randomOneByWeight;
}

关于java - 如何使用带有 List 参数的泛型函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57720293/

相关文章:

java - 对于少量信息,java 文件 i/o 或 derby 哪个更快?

typescript - 后续元素的类型取决于前一个元素的值的元组

c# - 公开非泛型和泛型类的模式

java - 使用基于不兼容的 Servlet API 版本的 Spring Boot 版本会导致问题吗?

java - 如果给出无效响应,请重新运行 main 方法?

java - <C :if/Choose/When> condition to be made as one 的多个实例

java - 将用户数据保存在文本文件或序列化对象中

python - 对象的属性集和它的命名空间有什么区别?

c++ - 如何销毁 OOP 中的静态数据成员?

c# - 通用 T GetByID<K>(K ID_)