簡體   English   中英

轉換邏輯以使用Java 8流

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM