gai*_*nco 8 java optional java-8 java-stream
我试图重构旧代码以使用流,我的第一个方法是这样的:
public void run() throws IOException {
Files.list(this.source)
.filter(Images::isImage)
.map(Image::new)
.filter(image -> image.isProportional(this.height, this.width))
.map(image -> image.resize(this.height, this.width))
.forEach(image -> Images.write(image, this.destination));
}
Run Code Online (Sandbox Code Playgroud)
这不是编译,因为新的Image()和Images.write()抛出IOExceptions.
使用UncheckedIOException包装这些异常将不起作用,因为如果其中一个失败,我不想阻止处理其他图像.
所以我结束了写2个私有方法:
private Optional<Image> createImage(Path imagePath) {
try {
return Optional.of(new Image(imagePath));
} catch (IOException e) {
return Optional.empty();
}
}
private void write(Image image) {
try {
Images.write(image, this.destination);
} catch (IOException e) {
// log error
}
}
Run Code Online (Sandbox Code Playgroud)
createImage()返回一个Optional,因为这看似合理.但是在此之后我的代码变得非常难看:
public void run() throws IOException {
Files.list(source)
.filter(Images::isImage)
.map(this::createImage)
.filter(image -> image.isPresent() && image.get().isProportional(this.height, this.width))
.map(image -> image.get().resize(this.height, this.width))
.forEach(this::write);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法避免在该代码上使用get()和isPresent()?
谢谢!
srb*_*gan 16
Optionals的优点之一是在它们上应用过滤,映射和平面映射功能仅在Optional :: isPresent为true时触发,因此:
public void run() throws IOException {
Files.list(source)
.filter(Images::isImage)
.map(this::createImage)
// turns every non-proportional Optional<Image> into empty optionals
.map(image -> image.filter(i -> i.isProportional(this.height, this.width)))
// resizes every proportional Optional<Image>, while doing nothing on the empties
.map(image -> image.map(i -> i.resize(this.height, this.width)))
// applies the writing consumer for each non-empty Optional<Image>
.forEach(image -> image.ifPresent(this::write));
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是只调用Optional :: isPresent和Optional :: get进行单独的Stream转换:
public void run() throws IOException {
Files.list(source)
.filter(Images::isImage)
.map(this::createImage)
// filter out the empty optionals
.filter(Optional::isPresent)
// replace every optional with its contained value
.map(Optional::get)
.filter(image -> image.isProportional(this.height, this.width))
.map(image -> image.resize(this.height, this.width))
.forEach(this::write);
}
Run Code Online (Sandbox Code Playgroud)
另一种方式(我拒绝建议作为主要解决方案,因为它相对古怪)是将静态图像创建方法更改为Stream生成器而不是可选生成器,以利用flatMap:
private Stream<Image> createImage(Path imagePath) {
try {
return Stream.of(new Image(imagePath));
} catch (IOException e) {
return Stream.empty();
}
}
public void run() throws IOException {
Files.list(source)
.filter(Images::isImage)
// inserts into the stream the resulting image (empty streams are handled seamlessly)
.flatMap(this::createImage)
.filter(image -> image.isProportional(this.height, this.width))
.map(image -> image.resize(this.height, this.width))
.forEach(this::write);
}
Run Code Online (Sandbox Code Playgroud)
第二个想法,继续这个解决方案; 它似乎更简单,而且由于静态方法无论如何都是私有的,最终用户,其他开发人员以及可以访问体面的Java 8反编译器的随机人员都不会尖叫(http://www.benf.org/other/ cfr /).
| 归档时间: |
|
| 查看次数: |
11859 次 |
| 最近记录: |