How do you do the equivalent of the following transform() method using pure functional programming (without the if-conditional).
Meta: I'd appreciate a title edit, I'm not sure how to word this question in "functionalese"
public class Playground {
private static Optional<Map<String,Integer>> transform(List<Tuple<String,Optional<Integer>>> input) {
if (input.stream().anyMatch(t->t.second.isEmpty())) return Optional.empty();
Map<String, Integer> theMap = input.stream()
.map(t -> new Tuple<>(t.first, t.second.get()))
.collect(Collectors.groupingBy(
t1 -> t1.first,
Collectors.mapping(t2 -> t2.second, toSingle())));
return Optional.of(theMap);
}
@Test
public void collect() {
List<Tuple<String,Optional<Integer>>> input1 = new ArrayList<>();
input1.add(new Tuple<>("foo", Optional.of(1)));
input1.add(new Tuple<>("bar", Optional.empty()));
Optional<Map<String,Integer>> result1 = transform(input1);
assertTrue(result1.isEmpty());
List<Tuple<String,Optional<Integer>>> input2 = new ArrayList<>();
input2.add(new Tuple<>("foo", Optional.of(1)));
input2.add(new Tuple<>("bar", Optional.of(2)));
Optional<Map<String,Integer>> result2 = transform(input2);
assertTrue(result2.isPresent());
assertEquals((int)1, (int)result2.get().get("foo"));
assertEquals((int)2, (int)result2.get().get("bar"));
}
private static class Tuple<T1,T2> {
public T1 first;
public T2 second;
public Tuple(T1 first, T2 second) {
this.first = first;
this.second = second;
}
}
public static <T> Collector<T, ?, T> toSingle() {
return Collectors.collectingAndThen(
Collectors.toList(),
list -> list.get(0)
);
}
}
ifstatement seems to be to select between two alternative return values. I'm unsure whether it meets your criteria, but it should be possible to use the ternary operator instead.Optional.filter()into doing the job of theif, following up withOptional.map()to perform the computation in the case that you actually want to do that..map(t -> new Tuple<>(t.first, t.second.get())) .collect(Collectors.groupingBy(t1 -> t1.first, Collectors.mapping(t2 -> t2.second, toSingle())))you can simply use.collect(Collectors.toMap(t -> t.first, t -> t.second.get(), (a,b) -> a))