函数式编程小分享
Posted 云户
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数式编程小分享相关的知识,希望对你有一定的参考价值。
函数式编程小分享
近期发现有不少小伙伴对于lambda以及函数式编程不太熟悉,今天把之前的一些小demo分享给大家。
JDK8接口特性
新增接口默认default的类型方法实现,可以方便接口扩展和升级
///只有一个要实现的方法的接口 适合使用lambda表达式实例化
@FunctionalInterface //函数式接口注释 最好要加,方便编译器检查语法 思想是一个接口只做一个事情
interface Intfce{
int doubleNum(int i);
//jdk8新增 默认实现接口方法 可以不在实现类中实现
default int add(int x,int y){
return x+y;
}
}
函数式接口
@FunctionalInterface
interface FormartMoney{
String formartMoney(int money);
}
class MyMoney {
private final int money;
MyMoney(int money) {
this.money = money;
}
void printMyMoney(FormartMoney formartMoney){
System.out.println("我的钱:"+formartMoney.formartMoney(this.money));
}
}
public class LambdaDemo2 {
public static void main(String[] args) {
MyMoney myMoney = new MyMoney(999999);
myMoney.printMyMoney(i->{
return new DecimalFormat("#,###").format(i);
});
}
}
jdk自带的接口
public class Testlambda {
/**
* 消费型接口
*/
@Test
public void test1(){
happy(2000,m->System.out.println("打车消费了"+m+"元"));
}
public void happy(double money, Consumer<Double> consumer){
consumer.accept(money);
}
/**
* 供给型接口
*/
@Test
public void test2(){
sup(10, ()->(int)(Math.random()*100)).forEach(e->System.out.println(e));
}
public List<Integer> sup(int size, Supplier<Integer> supplier){
List<Integer> list=new ArrayList<>();
for (int i=0;i<size;i++){
list.add(supplier.get());
}
return list;
}
/**
* 函数型接口
*/
@Test
public void test3(){
System.out.println(dealStr("我去你大2222爷",x->x.length()));
}
public Integer dealStr(String s, Function<String,Integer> function){
return function.apply(s);
}
/**
* 断言型接口
*/
@Test
public void test4(){
List<String> list = Arrays.asList("李四","张三","王五");
judgeInList(list,x->x.contains("李")).forEach(System.out::println);
}
public List<String> judgeInList(List<String> list,Predicate<String> predicate){
List<String> list1=new ArrayList<>();
list.forEach(s -> {
if(predicate.test(s)){
list1.add(s);
}
});
return list1;
}
}
方法引用
比较简单,一看就明白了
List<String> list = Arrays.asList("李四","张三","王五");
list.forEach(System.out::println);
//构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
//静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide );
//特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair );
//特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
变量引用
匿名类引用外边的变量必须是final,其实JDK8里也是没有变,只是可以省略final关键字,但是还是要求该变量为实际final类型
@FunctionalInterface
interface IntfceVar{
void doubleNum(int i);
}
public class VarDemo {
public static void main(String[] args) {
String ss = "asda";
// ss="2222";//当去掉注释会报错
IntfceVar intfceVar = s-> System.out.println(ss);
}
}
思考为什么内部类引用外部变量必须是final?
由于java引用是传值,而不是传引用(这个话可能理解存在差异),以下代码为例
public class VarDemo {
public static void main(String[] args) {
List<String> ss = new ArrayList<>();//这里ss指向 new ArrayList<>()的实例地址
// ss=new ArrayList<>();//当去掉注释会报错
IntfceVar intfceVar = s-> System.out.println(ss);//这里ss 也是指向上边实例的地址,但是当ss改变时,实际指向了新的对象实例地址,而由于实际运行时,字节码执行的顺序问题,可能导致匿名内部类中的方法执行的对象与实际的对象指引有差异。因此java做了这样的限制。
}
}
级联表达式和柯里化
级联表达式
就是有多个箭头的lambda表达式
public class CurryDemo {
public static void main(String[] args) {
x->y-> x + y; //当然目前是报错的
}
}
public class CurryDemo {
public static void main(String[] args) {
Function<Integer,Function<Integer,Integer>> functionFunction = x-> y-> x + y;//编译成功
System.out.println(functionFunction.apply(2).apply(3));//输出5
}
}
柯里化
那么柯里化是什么?
把多个参数的函数,转化为只有一个参数的函数,这个就叫做柯里化
如上的级联表达式。
目的
函数标准化
显而易见,函数的参数是固定一个
批量处理
Function<Integer,Function<Integer,Function<Integer,Integer>>> fun2 = x-> y-> z-> x + y+z;
int[] nums={2,3,4};
Function f = fun2;
for (int i = 0; i < nums.length; i++) {
if(f instanceof Function){
Object obj = f.apply(nums[i]);
if(obj instanceof Function){
f = (Function)obj;
}else{
System.out.println("最终结果:"+obj);
}
}
}
高阶函数
返回函数的函数
后续还有stream、响应式编程会分享给大家,尽情期待。
以上是关于函数式编程小分享的主要内容,如果未能解决你的问题,请参考以下文章