带有可选项的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@rgettmanmap
可以在任意位置进行。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());
}