带有选项的Java 8泛型集合

时间:2015-04-24 22:41:34

标签: java generics java-8 optional bounded-wildcard

我有一个相对简单的问题,我正在努力解决。似乎没有直观的方法来做到这一点,或者我在这里遗漏了一些东西。

考虑使用此方法查找主图像,如果不存在,则返回第一张图像 -

public Image findMainImage(Collection<? extends Image> images) {
    if (images == null || images.isEmpty()) return null
    return images.stream()
                 .filter(Image::isMain)
                 .findFirst()
                 .orElse(images.iterator().next())
}

我收到错误 - orElse(capture<? extends Image>) in Optional cannot be applied

任何方向都很棒。

2 个答案:

答案 0 :(得分:7)

解决此问题的一种方法是使用类型参数:

public <I extends Image> I findMainImage(Collection<I> images) {
    if (images == null || images.isEmpty()) return null;
    return images.stream()
                 .filter(Image::isMain)
                 .findFirst()
                 .orElse(images.iterator().next());
}

因为那时(对编译器而言)Optional肯定与images具有相同的类型参数。

如果我们想要,我们可以将其用作capturing helper

public Image findMainImage(Collection<? extends Image> images) {
    return findMainImageHelper( images );
}

private <I extends Image> I findMainImageHelper(Collection<I> images) {
    // ...
}

就个人而言,我只会使用通用版本,因为那时你可以做到例如:

List<ImageSub> list = ...;
ImageSub main = findMainImage( list );

基本上......原因不能编译的原因是为了防止你做这样的事情:

public Image findMainImage(
    Collection<? extends Image> images1,
    Collection<? extends Image> images2
) {
    return images1.stream()
                  .filter(Image::isMain)
                  .findFirst()
                  .orElse(images2.iterator().next());
}

在原始示例中,编译器不需要确定StreamIterator都来自同一对象的事实。引用同一对象的两个单独表达式被捕获到两个不同的类型。

答案 1 :(得分:2)

假设您有List<? extends Number>。您无法将任何号码添加到此列表中,因为它可能是List<Integer>,您尝试添加的号码可能是Float

出于同样的原因,orElse(T t)的方法Optional<T>需要T。由于有问题的OptionalOptional<? extends Image>,因此编译器无法确定images.iterator().next()的类型是否合适。

我通过输入.map(t -> (Image) t)

来编译
return images.stream()
             .filter(Image::isMain)
             .findFirst()
             .map(t -> (Image) t)
             .orElse(images.iterator().next());

事实上,由于某种原因,我无法理解,即使没有演员,它也能奏效。只是使用

.map(t -> t)

似乎使这项工作成功。