首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8函数式编程避免if条件

Java 8函数式编程避免if条件
EN

Stack Overflow用户
提问于 2020-09-25 03:20:00
回答 3查看 160关注 0票数 0

如何使用纯函数式编程(没有if条件)来实现与下面的transform()方法相同的功能?

Meta:我很感谢标题的编辑,我不知道如何用"functionalese“来表达这个问题。

代码语言:javascript
复制
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)
        );
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-09-25 03:46:17

这可能对你有用:

代码语言:javascript
复制
  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()))));
  }
票数 1
EN

Stack Overflow用户

发布于 2020-09-25 03:38:15

尽管我的解决方案不能满足您的结果,但我可以提供一个使用三元运算符的解决方案

代码语言:javascript
复制
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())));
}
票数 1
EN

Stack Overflow用户

发布于 2020-09-25 17:46:00

“纯函数式编程”不一定是质量的标志,本身也不是目的。

如果您想使代码更简单、更高效,这可能包括去掉If条件,特别是在源数据上进行第二次迭代时,您可以通过多种方式来实现。例如。

代码语言:javascript
复制
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();
    }
}

当空可选参数确实是例外情况时,您可以通过异常将标记作为方法契约的一部分,例如

代码语言:javascript
复制
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));
}
代码语言:javascript
复制
@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"));
}

更好的做法是从一开始就不要将可选参数放在元组列表中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64053043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档