如何使用纯函数式编程(没有if条件)来实现与下面的transform()方法相同的功能?
Meta:我很感谢标题的编辑,我不知道如何用"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)
);
}
}发布于 2020-09-25 03:46:17
这可能对你有用:
private static Optional<Map<String, Integer>> transform(
List<Tuple<String, Optional<Integer>>> input) {
return Optional.of(input)
.filter(t -> t.stream().allMatch(a -> a.second.isPresent()))
.map(
in ->
in.stream()
.filter(t -> t.second.isPresent())
.map(t -> new Tuple<>(t.first, t.second.get()))
.collect(
Collectors.groupingBy(
t1 -> t1.first, Collectors.mapping(t2 -> t2.second, toSingle()))));
}发布于 2020-09-25 03:38:15
尽管我的解决方案不能满足您的结果,但我可以提供一个使用三元运算符的解决方案
private static Map<String, Integer> transform(List<Tuple<String, Optional<Integer>>> input) {
return input.stream().anyMatch(t -> t.second.isEmpty()) ? Collections.emptyMap() :
input.stream()
.map(t -> new Tuple<>(t.first, t.second.get()))
.collect(Collectors.groupingBy(
t1 -> t1.first,
Collectors.mapping(t2 -> t2.second, toSingle())));
}发布于 2020-09-25 17:46:00
“纯函数式编程”不一定是质量的标志,本身也不是目的。
如果您想使代码更简单、更高效,这可能包括去掉If条件,特别是在源数据上进行第二次迭代时,您可以通过多种方式来实现。例如。
private static <K,V> Optional<Map<K,V>> transform(List<Tuple<K,Optional<V>>> input) {
final class AbsentValue extends RuntimeException {
AbsentValue() { super(null, null, false, false); }
}
try {
return Optional.of(input.stream().collect(Collectors.toMap(
t1 -> t1.first,
t2 -> t2.second.orElseThrow(AbsentValue::new),
(first,next) -> first)));
} catch(AbsentValue av) {
return Optional.empty();
}
}当空可选参数确实是例外情况时,您可以通过异常将标记作为方法契约的一部分,例如
public static class AbsentValueException extends RuntimeException {
}
private static <K,V> Map<K,V> transform(List<Tuple<K,Optional<V>>> input)
throws AbsentValueException {
return input.stream().collect(Collectors.toMap(
t1 -> t1.first,
t2 -> t2.second.orElseThrow(AbsentValueException::new),
(first,next)->first));
}@Test(expected = AbsentValueException.class)
public void collect1() {
List<Tuple<String,Optional<Integer>>> input1 = new ArrayList<>();
input1.add(new Tuple<>("foo", Optional.of(1)));
input1.add(new Tuple<>("bar", Optional.empty()));
Map<String,Integer> result1 = transform(input1);
}
@Test
public void collect2() {
List<Tuple<String,Optional<Integer>>> input2 = new ArrayList<>();
input2.add(new Tuple<>("foo", Optional.of(1)));
input2.add(new Tuple<>("bar", Optional.of(2)));
Map<String,Integer> result2 = transform(input2);
assertEquals((int)1, (int)result2.get("foo"));
assertEquals((int)2, (int)result2.get("bar"));
}更好的做法是从一开始就不要将可选参数放在元组列表中。
https://stackoverflow.com/questions/64053043
复制相似问题