首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8模式匹配?

Java 8模式匹配?
EN

Stack Overflow用户
提问于 2012-06-27 13:19:39
回答 5查看 24K关注 0票数 30

Java 8会像Scala和其他函数式程序那样支持模式匹配吗?我正在将Java 8的Lambda特性的演示文稿放在一起。我在这个特殊的函数式编程概念上找不到任何东西。

我记得让我对函数式编程感兴趣的是快速排序实现,特别是与命令式编程的实现相比。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-01 05:17:53

我猜想您谈论的不是在字符串上应用正则表达式的意义上的模式匹配,而是applied in Haskell。例如,使用通配符:

代码语言:javascript
复制
head (x:_)  = x
tail (_:xs) = xs

Java 8本身并不支持这一点,但是,对于Lambda表达式,有一些方法可以做到这一点,比如计算阶乘:

代码语言:javascript
复制
public static int fact(int n) {
     return ((Integer) new PatternMatching(
          inCaseOf(0, _ -> 1),
          otherwise(  _ -> n * fact(n - 1))
     ).matchFor(n));
}

如何实现这一点您将在这篇博客文章中找到更多信息:Towards Pattern Matching in Java

票数 32
EN

Stack Overflow用户

发布于 2015-06-12 01:49:41

可以在Java 8中将模式匹配实现为一个库(利用lambda表达式),但不幸的是,我们仍然会错过Haskell或Scala等语言所具有的编译器穷举检查。

Cyclops-react有一个强大的Pattern Matching模块,它既提供了Java8的结构化模式匹配,也提供了通过guards的模式匹配。

它提供了when / then / filter和匹配,包括基于标准Java谓词的解构(例如,匹配可用于过滤流)。

守卫配对

为了匹配via guards,我们使用whenGuard / then /否则清楚地显示驱动测试的是案例,而不是被测试对象的结构。

例如,对于基于保护的匹配,如果我们实现了一个实现Matchable接口的Case类

代码语言:javascript
复制
 static class MyCase  implements Matchable{ int a; int b; int c;}

(顺便说一句,Lombok可以非常方便地创建密封的case类层次结构)

我们可以根据它的内部值进行匹配(如果需要,可以递归匹配,或者在其他各种选项中按类型匹配)。

代码语言:javascript
复制
  import static com.aol.cyclops.control.Matchable.otherwise;
  import static com.aol.cyclops.control.Matchable.whenGuard;

  new MyCase(1,2,3).matches(c->c.is(whenGuard(1,2,3)).then("hello"),
                               .is(whenGuard(4,5,6)).then("goodbye")
                               ,otherwise("goodbye")
                           );

如果我们有一个没有实现Matchable的对象,我们可以强制它成为Matchable,我们的代码将变成

代码语言:javascript
复制
Matchable.ofDecomposable(()->new MyCase(1,2,3)))
         .matches(c->c.is(whenGuard(1,2,3)).then("hello"),
                      .is(whenGuard(4,5,6)).then("goodbye")
                      ,otherwise("hello"));

如果我们不关心其中一个值,我们可以使用通配符

代码语言:javascript
复制
new MyCase(1,2,3).matches(c->c.is(whenGuard(1,__,3)).then("hello"),
                              .is(whenGuard(4,__,6)).then("goodbye")
                              ,otherwise("hello)
                           );

或者递归地解除一组嵌套类的结构

代码语言:javascript
复制
Matchable.of(new NestedCase(1,2,new NestedCase(3,4,null)))
                .matches(c->c.is(whenGuard(1,__,has(3,4,__)).then("2")
                 ,otherwise("default");

其中NestedCase看起来像这样-

代码语言:javascript
复制
class NestedCase implemends Decomposable { int a; int b; NestedCase c; }

用户还可以使用hamcrest编写模式匹配表达式

代码语言:javascript
复制
 import static com.aol.cyclops.control.Matchable.otherwise;
 import static com.aol.cyclops.control.Matchable.then;
 import static com.aol.cyclops.control.Matchable.when;

 Matchable.of(Arrays.asList(1,2,3))
                .matches(c->c.is(when(equalTo(1),any(Integer.class),equalTo(4)))
                        .then("2"),otherwise("default"));

结构化模式匹配

我们还可以匹配被测试对象的确切结构。也就是说,我们可以让编译器确保我们的用例与所提供对象的结构相匹配,而不是使用if / then测试来查看结构是否恰好与我们的用例匹配。执行此操作的DSL与基于保护的匹配几乎相同,但我们使用when / then / almost来清楚地显示驱动测试用例的对象结构,而不是相反。

代码语言:javascript
复制
  import static com.aol.cyclops.control.Matchable.otherwise;
  import static com.aol.cyclops.control.Matchable.then;
  import static com.aol.cyclops.control.Matchable.when;

  String result =  new Customer("test",new Address(10,"hello","my city"))
                            .match()
                            .on$_2()
                            .matches(c->c.is(when(decons(when(10,"hello","my city"))),then("hello")), otherwise("miss")).get();

  //"hello"

在结构上匹配从客户提取的Address对象。Customer和Address类的位置如下所示

代码语言:javascript
复制
@AllArgsConstructor
static class Address{
    int house;
    String street;
    String city;

    public MTuple3<Integer,String,String> match(){
        return Matchable.from(()->house,()->street,()->city);
    }
}
@AllArgsConstructor
static class Customer{
    String name;
    Address address;
    public MTuple2<String,MTuple3<Integer,String,String>> match(){
        return Matchable.from(()->name,()->Maybe.ofNullable(address).map(a->a.match()).orElseGet(()->null));
    }
}

cyclops-react提供了一个Matchables类,它允许对常见的JDK类型进行结构化模式匹配。

票数 10
EN

Stack Overflow用户

发布于 2017-01-09 23:00:47

我意识到这个问题已经得到了回答,而且我是函数式编程的新手,但在犹豫了很久之后,我最终决定参与这个讨论,以获得关于以下内容的反馈。

我会建议(也是?)下面是简单的实现。它与公认答案中引用的(很好的)文章略有不同;但在我(短暂的)经验中,它的使用更灵活,更易于维护(当然,这也是一个品味问题)。

代码语言:javascript
复制
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

final class Test
{
    public static final Function<Integer, Integer> fact = new Match<Integer>()
            .caseOf( i -> i == 0, i -> 1 )
            .otherwise( i -> i * Test.fact.apply(i - 1) );

    public static final Function<Object, String> dummy = new Match<Object>()
            .caseOf( i -> i.equals(42), i -> "forty-two" )
            .caseOf( i -> i instanceof Integer, i -> "Integer : " + i.toString() )
            .caseOf( i -> i.equals("world"), i -> "Hello " + i.toString() )
            .otherwise( i -> "got this : " + i.toString() );

    public static void main(String[] args)
    {
        System.out.println("factorial : " + fact.apply(6));
        System.out.println("dummy : " + dummy.apply(42));
        System.out.println("dummy : " + dummy.apply(6));
        System.out.println("dummy : " + dummy.apply("world"));
        System.out.println("dummy : " + dummy.apply("does not match"));
    }
}

final class Match<T>
{
    public <U> CaseOf<U> caseOf(Predicate<T> cond, Function<T, U> map)
    {
        return this.new CaseOf<U>(cond, map, Optional.empty());
    }

    class CaseOf<U> implements Function<T, Optional<U>>
    {
        private Predicate<T> cond;
        private Function<T, U> map;
        private Optional<CaseOf<U>> previous;

        CaseOf(Predicate<T> cond, Function<T, U> map, Optional<CaseOf<U>> previous)
        {
          this.cond = cond;
          this.map = map;
          this.previous = previous;
        }

        @Override
        public Optional<U> apply(T value)
        {
            Optional<U> r = previous.flatMap( p -> p.apply(value) );
            return r.isPresent() || !cond.test(value) ? r
                : Optional.of( this.map.apply(value) );
        }

        public CaseOf<U> caseOf(Predicate<T> cond, Function<T, U> map)
        {
          return new CaseOf<U>(cond, map, Optional.of(this));
        }

        public Function<T,U> otherwise(Function<T, U> map)
        {
            return value -> this.apply(value)
                .orElseGet( () -> map.apply(value) );
        }
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11219858

复制
相关文章

相似问题

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