There is a old Java code (without lambda expressions):
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;
}
I'm trying to rewrite this code to Java 8 Stream API style:
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...
PROBLEM: The function isCheckerBlocked()
(which uses in last filter()
operation) takes variable of VectorDirection
type (variable d
). But after calling map()
function I lose access to this variable. How I can save access to d
variable after calling map()
function?
Thank you for attention.
You cannot share scopes of lambdas like that. In other languages you can use tuples, so instead of returning just the result, you return result and argument.
In java you can create a custom class to host the pair of data you need or create a Tuple to host the pair of data .
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);
}
}
Importing the tuple static function like this import static so.alpha.Tuple.tuple;
you can map(tuple(d,f(d))))
then your next function will be filter(t->p(t._1,t._2))
and then you will map(t->t._1)
or if you add getters to the tuple you can also map(Tuple::get_1)
That way you can carry on your d to the next step.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With