2017-02-17 18 views
6

Существует старая кода Java (без лямбда-выражений):Как я могу переписать этот классический Java-код на код Java Stream API?

public List<CheckerPosition> getAttackedCheckersForPoint(CheckerPosition from, boolean isSecondPlayerOwner, boolean isQueen, VectorDirection ignoredDirection){ 
    List<VectorDirection> allDirections = VectorDirection.generateAllDirections(); 
    List<CheckerPosition> result = new ArrayList<CheckerPosition>(); 

    for (VectorDirection direction : allDirections){ 
     if (!direction.equals(ignoredDirection)){ 
      Checker firstCheckerOnWay = findFirstCheckerOnWay(new CheckerBaseVector(from, direction), !isQueen); 
      if ((firstCheckerOnWay != null) && (firstCheckerOnWay.isSecondPlayerOwner() != isSecondPlayerOwner) && isCheckerBlocked(firstCheckerOnWay.getPosition(), direction)){ 
       result.add(firstCheckerOnWay.getPosition()); 
      } 
     } 
    } 
    return result; 
} 

Я пытаюсь переписать этот код на Java 8 Поток API стиль:

allDirections.stream() 
       .filter(d -> !d.equals(ignoredDirection)) 
       .map(d -> findFirstCheckerOnWay(new CheckerBaseVector(from, d), !isQueen)) // In this operation I map VectorDirection element (d) to Checker variable type. 
       .filter(c -> (c != null) && (c.isSecondPlayerOwner() != isSecondPlayerOwner) && isCheckerBlocked(c.getPosition(), d)); // But in this operation I need to access d variable... 

ПРОБЛЕМА: функция isCheckerBlocked() (которая использует в последней операции filter()) принимает переменную VectorDirection типа (переменная d). Но после вызова функции map() я теряю доступ к этой переменной. Как я могу сохранить доступ к переменной d после вызова функции map()?

Благодарим вас за внимание.

+2

Я боюсь, что вы не сможете получить доступ к 'direction', как только вы сопоставили его с новым типом. Возможно, вы можете создать новый объект, который инкапсулирует 'VectorDirection' и' Checker', и вы можете сопоставить «направление» этому типу. – user7

+3

Другая возможность: на этапе сопоставления, где оба c и d находятся в области видимости, вы можете сопоставить значение null, если isCheckerBlocked –

+2

Я не уверен, есть ли веская причина переписать его таким образом. Я не вижу, как это сделает код более читаемым, выполнимым, исполнительным и т. Д. – Calculator

ответ

5

Вы не можете делиться областями лямбда. На других языках вы можете использовать кортежи, поэтому вместо того, чтобы возвращать только результат, вы возвращаете результат и аргумент.

В java вы можете создать собственный класс для размещения требуемой пары данных или создать Tuple для размещения пары данных.

public class Tuple<A,B> { 
    public final A _1; 
    public final B _2; 
    public Tuple(A a, B b){ 
     _1 = a; 
     _2 = b; 
    } 
    public static <A,B> Tuple<A,B> tuple(A a, B b){ 
     return new Tuple<>(a, b); 
    } 
} 

Импорт кортеж статической функции как этот import static so.alpha.Tuple.tuple; вы можете map(tuple(d,f(d)))) тогда ваша следующая функция будет filter(t->p(t._1,t._2)), а затем вы будете map(t->t._1) или если добавить добытчик в кортеж вы также можете map(Tuple::get_1)

Таким образом, вы можете переведите d на следующий шаг.

Stream<String> s = Arrays.asList("sa","a","bab","vfdf").stream(); 

    Stream<Integer> result = s.map(d -> tuple(d.length(),d)) //String to Tuple<Integer,String> 
     .filter(t->t._1 >= 2 && t._2.contains("a")) // Filter using both 
     .map(Tuple::get_1); // Return just Integers