Java函数式编程使用方法

函数式编程functional programming(FP)要么是一种理念先进的、应该广泛传播的程序设计方法;要么是一种偏学术性的、实际用途不多的编程方式,下面为大家讲解一下Java函数式编程使用方法。

一. 函数式编程

Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力。

下面来近距离观察一下函数式编程的几个特点: •函数可以作为变量、参数、返回值和数据类型。 •基于表达式来替代方法的调用 •函数无状态,可以并发和独立使用 •函数无副作用,不会修改外部的变量 •函数结果确定性;同样的输入,必然会有同样的结果。 下面jdk1.8里面对函数式编程的定义。只是一个 FunctionalInterface 接口。特别的简单。

1 @Documented
2 @Retention(RetentionPolicy.RUNTIME)
3 @Target(ElementType.TYPE)
4 public @interface FunctionalInterface {}

这个函数式接口有几点以下的限制: •唯一的抽象方法,有且仅有一个 (即所有的函数式接口,有且只能有一个抽象方法) •加上标注,则会触发JavaCompiler的检查。对于符合函数接口的接口,加不加都无关紧要,但是加上则会提供一层编译检查的保障。如果不符合,则会报错。 •不能被覆盖之后,再声明为抽象方法,则不算抽象方法。例如接口实现了Object中的方法。 •可用于lambda类型的使用方式

二. Java8新增函数式接口

Stream的操作是建立在函数式接口的组合之上的。Java8中新增的函数式接口都在java.util.function包下。这些函数式接口可以有多种分类方式。

2.1 Function

Function是从T到R的一元映射函数。将参数T传递给一个函数,返回R。即R = Function(T)

Function最常用的应该是 Stream map(Function mapper);

比如List person里面有age,name…. 我传入age,他就会返回age的集合给我。

@FunctionalInterface
public interface Function {

   R apply(T t);

   default  Function compose(Function before) {
       Objects.requireNonNull(before);
       return (V v) -> apply(before.apply(v));
   }

   default  Function andThen(Function after) {
       Objects.requireNonNull(after);
       return (T t) -> after.apply(apply(t));
   }

   static  Function identity() {
       return t -> t;
   }
}

2.2 Predicate

Predicate是一个谓词函数,主要作为一个谓词演算推导真假值存在,返回布尔值的函数。Predicate等价于一个Function的boolean型返回值的子集。

predicate最常用的莫过于 Stream filter(Predicate predicate);

比如我要过滤年龄 > 18 的人,我传入age,判断是否为true。为true则保留,false丢弃。

@FunctionalInterface
public interface Predicate
{

boolean test(T t);

default Predicate and(Predicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}

default Predicate negate() {
return (t) -> !test(t);
}

default Predicate or(Predicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}

static Predicate isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}

2.3 Consumer

Consumer是从T到void的一元函数,接受一个入参但不返回任何结果的操作。

Consumer最常用的肯定是 default void forEach(Consumer action) {}

这是一段forEach循环的代码,传入实现的方法,并不返回任何值。只是循环。

@FunctionalInterface
public interface Consumer {

   void accept(T t);

   default Consumer
andThen(Consumer after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }

三. Lambda表达式

3.1 基本语法

Lambda 的基本结构为 (arguments) -> body,有如下几种情况: •参数类型可推导时,不需要指定类型,如 (a) -> System.out.println(a) •当只有一个参数且类型可推导时,不强制写 (), 如 a -> System.out.println(a) •参数指定类型时,必须有括号,如 (int a) -> System.out.println(a) •参数可以为空,如 () -> System.out.println(“hello”) •body 需要用 {} 包含语句,当只有一条语句时 {} 可省略

3.2 Lambda原理

比如如下代码:

List list = new ArrayList();

list.stream().filter((x) -> x >= 18)

Stream filter(Predicate predicate);

@FunctionalInterface
public interface Predicate {

   boolean test(T t);

}

比如List里面存个个人的年龄,现在筛选出年龄大于等于18的人。

此时我们就可以用 list.stream().filter((x) -> x >= 18) 这就是一个典型的lambda表达式

(x) -> x >= 18 传给 Predicate 函数式接口。

原理其实是:

JVM帮我们动态生成了一个内部类,然后这个内部类实现了 Predicate 这个函数式接口。

重写了里面的test方法。生成的类似如下:

static final class Main$$Lambda$1 implements Predicate {
   private Main$$Lambda$1() {
   }

   @Override
   public boolean test(Integer x) {
       return x >= 18;
   }
}

3.3 Lambda用法

public class Main {
   public static void main(String[] args) {

       List list = new ArrayList();
       list.add(40);
       list.add(50);
       list.add(20);
       list.add(30);
       List collect = list.stream().filter(x -> x >= 30)
               .map((x) -> x + 10).sorted((x, y) -> -x.compareTo(y))
               .collect(Collectors.toList());
       System.out.println(collect);
   }
}

这个一段很典型的Lambda + Stream的用法。 •list.stream()获取list的stream的流 •filter筛选出年龄大于30的人 (里面是一个Predicate接口,返回真假) •map做一个function映射 •sort排序,里面是compartor

四. 总结

Lambda 表达式可以减少很多代码,能提高生产力。但也要理解其原理。比如3.3中的代码,为什么filter里面是断言表达式,map里面是function表达式。

这都要从lambda的原理入手,也就是JVM动态生成一个内部类,并继承其中的抽象方法。

本次主要介绍了Java函数式编程的原理以及应用,主要从Stream和lambda入手。通过一些简单的概念,以及代码,更好的理解Java的函数式编程。

掌握Java的函数式编程,对平时我们开发代码,看其他人的代码,都有很大的帮助。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/222797.html<

(0)
管理的头像管理
上一篇2025-04-15 16:11
下一篇 2025-04-15 16:12

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注