[英]Convert multiple for loops with conditional logic to Java 8 streams
[英]Convert logic to use Java 8 Streams
我正在学习如何在Java 8中使用Streams,并且想了解如何将以下示例转换为基于流的方式。 我做了几次尝试,但无法获得基于流的编译方式。 我想我似乎迷失了嵌套循环和变量引用。
import java.util.Collection;
import java.util.Objects;
import gov.geo.argcci.product.parts.layers.PlatformMarkerLayer;
public class Test {
public void java7Method(final Collection<Item> items) {
for (final LayerHolder layerHolder : getLayerHolders()) {
if (layerHolder.getLayer() instanceof MyLayer) {
final MyLayer myLayer = (MyLayer) layerHolder.getLayer();
final Item current = myLayer.getItem();
if (current != null) {
for (final Item item : items) {
if (Objects.equals(item.getSomeKey(), current.getSomeKey())
&& Objects.equals(item.getSomeOtherKey(), current.getSomeOtherKey())) {
final SomeObject someObject = getObjectBasedOnItem(current);
someObject.doSomething(layerHolder);
}
}
}
}
}
}
public void java8Method(final Collection<Item> items) {
getLayerHolders()
.stream()
.filter(layerHolder -> layerHolder.getLayer() instanceof MyLayer)
.map(layerHolder -> (MyLayer) layerHolder.getLayer())
.map(layerHolder -> layerHolder.getItem())
.filter(Objects::nonNull)
.forEach(current->{
items.stream()
.filter(Objects.equals(item.getSomeKey(), current.getSomeKey()) && Objects.equals(item.getSomeOtherKey(), current.getSomeOtherKey()));
// final SomeObject someObject = getObjectBasedOnItem(current);
// someObject.doSomething(layerHolder);
});
}
// The Code below this line is auto-generated to make sure example can compile without errors
private SomeObject getObjectBasedOnItem(Item current) {
return null;
}
private Collection<LayerHolder> getLayerHolders() {
return null;
}
private class Item {
public Object getSomeKey() {
return null;
}
public Object getSomeOtherKey() {
return null;
}
}
private class LayerHolder {
public MyLayer getLayer() {
return null;
}
}
private class MyLayer {
public Item getItem() {
return null;
}
}
private class SomeObject {
public void doSomething(LayerHolder layerHolder) {}
}
}
Java 7代码的直接翻译是
public void java8Method(final Collection<Item> items) {
getLayerHolders().forEach(layerHolder -> {
Optional.of(layerHolder)
.map(LayerHolder::getLayer)
.filter(MyLayer.class::isInstance)
.map(l -> ((MyLayer)l).getItem())
.ifPresent(current-> items.stream()
.filter(item ->
Objects.equals(item.getSomeKey(), current.getSomeKey())
&& Objects.equals(item.getSomeOtherKey(), current.getSomeOtherKey()))
.forEach(ignored ->
getObjectBasedOnItem(current).doSomething(layerHolder))
);
});
}
除了不会两次调用getLayer()
。
但是我有一种强烈的感觉,你真正想做的是
public void java8Method(final Collection<Item> items) {
getLayerHolders().forEach(layerHolder ->
Optional.of(layerHolder)
.map(LayerHolder::getLayer)
.filter(MyLayer.class::isInstance)
.map(l -> ((MyLayer)l).getItem())
.filter(current-> items.stream()
.anyMatch(item ->
Objects.equals(item.getSomeKey(), current.getSomeKey())
&& Objects.equals(item.getSomeOtherKey(), current.getSomeOtherKey())))
.ifPresent(current ->
getObjectBasedOnItem(current).doSomething(layerHolder))
);
}
通常,您应该更多地考虑实际的程序逻辑,而不是使用代码将Java 8之前的代码转换为Stream API。
您需要在doSomething
方法中使用外层对象。 因此,您无法映射到流中的Item对象。
最好的决定可能是尝试简化设计。 使用流不会使其更简单地实现。
在没有流的版本中,内部for循环正在测试图层的项目是否在列表内,这可能是流中的另一个过滤器。
代码可以是:
public void java8Method(final Collection<Item> items) {
getLayerHolders()
.stream()
.filter(layerHolder -> layerHolder.getLayer() instanceof MyLayer)
.filter(layerHolder -> Objects.nonNull(((MyLayer) layerHolder.getLayer()).getItem()))
.filter(layerHolder->{ Item current = ((MyLayer) layerHolder.getLayer()).getItem();
return items.stream()
.anyMatch(item->Objects.equals(item.getSomeKey(), current.getSomeKey()) &&
Objects.equals(item.getSomeOtherKey(), current.getSomeOtherKey())); })
.forEach(layerHolder-> getObjectBasedOnItem(((MyLayer) layerHolder.getLayer()).getItem()).doSomething(layerHolder));
}
试图使其成为单个流功能使其很难读取和维护。
分阶段实施它并突破谓词将是理想的。
此实现使您既可读又可维护的代码以及流式传输功能。
public void java8Method(Collection<Item> items)
{
Predicate<LayerHolder> hasMyLayer = lh -> MyLayer.class
.isInstance(lh.getLayer());
Predicate<MyLayer> hasNonNullItem = ml -> Objects.nonNull(ml.getItem());
Predicate<MyLayer> hasMatchingItem = (ml) -> items.stream()
.filter(i -> i.getSomeKey().equals(ml.getItem().getSomeKey()))
.filter(i -> i.getSomeOtherKey().equals(ml.getItem().getSomeOtherKey()))
.count() > 0;
getLayerHolders().stream().filter(lh -> hasMyLayer.test(lh))
.filter(lh -> hasNonNullItem.test(lh.getLayer()))
.filter(lh -> hasMatchingItem.test(lh.getLayer()))
.forEach(lh -> getObjectBasedOnItem(lh.getLayer().getItem())
.doSomething(lh));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.