java isprime函数,Java8 编程规范入门之【函数式接口、lambda表达式、方法以及构造器引用】...

函数式接口使用背景

我们知道,java是一门面向对象编程语言,java中一切都是面向对象的(除了原始数据类型)。在java中函数(方法)是类/对象的一部分,不能单独存在。而其他一些函数式编程语言如C++、Javascript等语言,可以编写单独的函数并可以直接调用它们。

面向对象并非不好,只是有时候需要编写冗长的代码。举个简单的例子,我们需要创建一个Runnable实例,通常我们会使用匿名内部类如下:

Runnable r = new Runnable(){

@Override

public void run() {

System.out.println("My Runnable");

}};

其实在这段代码中,真实有用的仅仅只是内部的run方法,其他的代码只是java面向对象要求的。

java8函数式接口和lambda表达式可以让我们编写少量代码就能达到上述效果。

java8函数式接口

在java8中,本身只有一个抽象方法的接口即可称之为函数式接口,可以使用@FunctionalInterface注解显示标明接口是函数式接口。这个注解并非必须的,如果加上该注解,则接口若存在多于一个的抽象方法则会提示编译错误。

java8函数式接口的最大好处是可以使用lambda表达式来初始化函数式接口从而避免匿名内部类样式的笨重写法。

java8的集合API已经重写了,并且引进了使用很多的函数式接口的新的流式API。在java.util.function包下定义了很多函数式接口如:Consumer、Supplier、Function 和Predicate。

lambda表达式

通过lambda表达式我们可以将函数式编程在java的面向对象中形象化。

对象是java语言的基本,我们不可能离开对象单独去使用方法,这也是为什么java提供lambda表达式仅仅能使用函数式接口的原因。

如果只有一个抽象方法,那么使用lambda表达式就不会存在困惑了。

lambda表达式的签名:

*** (argument1, argument2,...) -> (body) ***

** (argument1, argument2,...)**表示方法签名,argument1, argument2,...是参数列表

** -> ** 是箭头,指向方法体

**(body) ** 是方法体,可以使用{}包裹代码块来表示

如果是无参方法,则方法签名可以使用 ()

如果只有一个参数的话,()可以省略

前面创建Runnable实例的代码可以使用lambda表达式实现:

Runnable r1 = () -> System.out.println("My Runnable");

解释下这段代码:

Runnable 是一个函数式接口,所以我们可以使用lambda表达式创建它的实例

因为 run()方法咩有参数,所以我们的lambda表达式也没有参数

就像if-else语句一样,如果只有一行代码的话我们可以省去{}符号了。

为什么要使用lambda表达式

减少代码量

使用匿名内部类和lambda表达式的代码量区分已经很明显了

支持连续地、并行地执行

lambda的另外一个好处就是我们可以使用流式API连续并行地执行程序。

为了说明这点,我们举个例子。判断一个数是不是质数:

这段代码不是最优的,但是可以达到目的:

private static boolean isPrime(int number) {

if(number < 2) return false;

for(int i=2; i

if(number % i == 0) return false;

}

return true;

}

解决这个问题的代码是连续的,如果给定的数字很大的话很耗时。另外一个缺陷是分支返回太多可读性不好。使用lambda和流式API的写法:

private static boolean isPrime(int number) {

return number > 1

&& IntStream.range(2, number).noneMatch(

index -> number % index == 0);

}

**IntStream **是一个自然排好序的元素为原始类型int的支持连续并行执行的流。为了更好阅读,代码可以进一步优化为:

private static boolean isPrime(int number) {

IntPredicate isDivisible = index -> number % index == 0;

return number > 1

&& IntStream.range(2, number).noneMatch(

isDivisible);

}

range(arg1,arg2)方法返回一个**IntStream **包含arg1,但是不包含arg2的步长为1的序列。

noneMatch()返回是否没有元素匹配不上给定的预定义条件Predicate。

给方法传递行为action

我们需要对一个list中满足某个条件的元素进行求和。

public static int sumWithCondition(List numbers, Predicate predicate) {

return numbers.parallelStream()

.filter(predicate)

.mapToInt(i -> i)

.sum();

}

使用方法如下:

//对所有元素求和

sumWithCondition(numbers, n -> true)

//对是偶数的元素求和

sumWithCondition(numbers, i -> i%2==0)

//对所有大于5的元素求和

sumWithCondition(numbers, i -> i>5)

高效率的懒加载

如果我们需要找出3-11之间的最大的奇数,并求出它的平方。

我们可能使用这样的代码:

private static int findSquareOfMaxOdd(List numbers) {

int max = 0;

for (int i : numbers) {

if (i % 2 != 0 && i > 3 && i < 11 && i > max) {

max = i;

}

}

return max * max;

}

上述代码是在一个序列中处理我们可以使用流式API代替:

public static int findSquareOfMaxOdd(List numbers) {

return numbers.stream()

.filter(NumberTest::isOdd)

.filter(NumberTest::isGreaterThan3)

.filter(NumberTest::isLessThan11)

.max(Comparator.naturalOrder())

.map(i -> i * i)

.get();

}

public static boolean isOdd(int i) {

return i % 2 != 0;

}

public static boolean isGreaterThan3(int i){

return i > 3;

}

public static boolean isLessThan11(int i){

return i < 11;

}

冒号表达式是方法的引用,NumberTest::isOdd 是 (i) -> isOdd(i) 或者

i -> NumberTest.isOdd (i) 的缩写。

更多的lambda表达式示例

() -> {} // 无参无方法体

() -> 42 // 无参有方法体

() -> null // 无参有方法体

() -> { return 42; } // 无参,代码块中返回结果

() -> { System.gc(); } //

// 复杂的代码块

() -> {

if (true) return 10;

else {

int result = 15;

for (int i = 1; i < 10; i++)

result *= i;

return result;

}

}

(int x) -> x+1 // 单个的声明类型的参数

(int x) -> { return x+1; } //

(x) -> x+1 // 单个参数,单条代码同上

x -> x+1 // 同上

(String s) -> s.length() //

(Thread t) -> { t.start(); } //

s -> s.length() // 单个的编译器可以推断的类型参数

t -> { t.start(); } // 单个的编译器可以推断的类型参数

(int x, int y) -> x+y // 多个的声明类型的参数

(x,y) -> x+y // 多个的可以推断的类型参数

(x, final y) -> x+y // 错误。不能修改final变量y

(x, int y) -> x+y // 错误,无法推断混合类型

方法、构造器引用

java8可以使用冒号表达式来引用方法:

System::getProperty

System.out::println

"abc"::length

ArrayList::new

int[]::new

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值