2016-09-16 30 views
1

我正在學習如何在Java 8中使用Streams,並希望瞭解如何將以下示例轉換爲基於流的方式。我做了幾次嘗試,但無法獲得基於流的方式進行編譯。我想我正在被嵌套循環和變量引用絆倒,這些引用似乎丟失了。將邏輯轉換爲使用Java 8流

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) {} 
    } 
} 
+1

你有什麼錯誤? – randominstanceOfLivingThing

+3

在你的第二個過濾器中,你只需要添加'item - >'使其成爲一個lambda – njzk2

回答

4

你的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更多的實際程序邏輯...

1

您需要在doSomething方法中使用外層對象。所以你不能映射到流中的Item對象。

可能最好的決定是嘗試簡化設計。使用流並不會讓它更容易實現。

在沒有流的版本中,inner 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)); 
} 
+0

代碼重複不是解決方案。 – Holger

0

試圖使其成爲一個單一的流媒體功能,使其閱讀和維護非常困難。

實施它的階段和爆發預測將是理想的。

這個實現讓你可讀,可維護的代碼和流功能。

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