带有可选项的Java 8通用集合

带有可选项的Java 8通用集合,java,generics,java-8,optional,bounded-wildcard,Java,Generics,Java 8,Optional,Bounded Wildcard,我有一个看起来相对简单的问题,我正在努力解决。似乎没有一个直观的方法来做到这一点,或者,我在这里遗漏了一些东西 考虑使用此方法查找主映像,如果不存在主映像,则返回第一个映像- public Image findMainImage(Collection<? extends Image> images) { if (images == null || images.isEmpty()) return null return images.stream()

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

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

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())
}

public Image findMainImage(Collection假设您有一个
列表修复它的一种方法是使用类型参数:

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());
}
就个人而言,我只会使用通用版本,因为这样您就可以执行以下操作:

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

基本上…它最初不编译的原因是为了防止您执行以下操作:

public Image findMainImage(
    Collection<? extends Image> images1,
    Collection<? extends Image> images2
) {
    return images1.stream()
                  .filter(Image::isMain)
                  .findFirst()
                  .orElse(images2.iterator().next());
}
公共图像查找主图像(

集合如果它只是一个
集合
,这可能会起作用,但是泛型的工作方式,
是可选的。orElse
只能接受一个
T
。能否将方法签名更改为
public T findMainImage(集合图像)
@misha我通过更改签名了解它的工作原理,我更感兴趣的是理解其背后的原因。如果您将集合的返回值与通配符子类型(
?extends…
)一起使用,而不将其绑定到确定类型(例如,通过将其分配给
Image
类型的变量,您将拥有一个
?extensed Image
类型,其中
orElse
方法由于类型推断而需要一个
Image
。Java泛型是一个难题,特别是当涉及通配符时。@sanz原因是您知道
扩展Image
,而h参数化流与从
images.iterator().next()中产生的
?扩展图像
但编译器不知道。通过更改签名并为集合参数指定名称,您可以向编译器证明这两个位置的类型相同。我假设在
findFirst
之前确实有
.map
t
的类型是集合的上限,
Image
,因此无论您是否将
t
转换为
Image
,它都是一个
图像
,返回的
流现在是一个
流,而不是
Stream@rgettman
map
可以在任意位置进行。
Optional
也有一个方法
map
,所以我映射了一个
选项,我甚至没有意识到
Optional
还有一个
map
方法。俗话说“你每天都能学到新东西”,我刚刚学到了一些新东西。@targetman不管怎样,你不需要强制转换都很奇怪,不是吗?编译器如何知道所需的类型是
Image
Stream
Map
的方法都采用了
函数替换,你可以使用
集合。不可修改的集合(images)。Stream()…
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());
}