带有选项的Java 8泛型集合

san*_*anz 5 java generics optional java-8 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())
}
Run Code Online (Sandbox Code Playgroud)

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

任何方向都会很棒.

Rad*_*def 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());
}
Run Code Online (Sandbox Code Playgroud)

因为那时(对编译器)Optional肯定有相同的类型参数images.

如果我们想要,我们可以将其用作捕获助手:

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

private <I extends Image> I findMainImageHelper(Collection<I> images) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

List<ImageSub> list = ...;
ImageSub main = findMainImage( list );
Run Code Online (Sandbox Code Playgroud)

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

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

而在最初的例子,编译器并不需要确定的事实,都StreamIterator来自同一个对象.引用同一对象的两个单独表达式被捕获到两个不同的类型.