前言
首先大致讲一下什么是lambda表达式:
你也可以将它就当做是匿名函数,lambda表达式其实就是匿名函数演化出的一种语法系统。
举个栗子:
普通函数
1 2
| int function(int x, int y); function(1, 2);
|
匿名函数(lambda表达式)
1 2
| [](int x, int y){函数主体}; [](int x, int y){函数主体}(1, 2);
|
一个很明显的区别就是使用lambda表达式就省去了给函数命名的工作
而且对于一些简短的函数,直接用lambda表达式声明+调用能提高一点编码效率
就比如说,常用的自定义sort的比较函数。
关于lambda表达式如果想进一步了解:
使用Java的同学可以再读读廖老师这篇教程 -> 传送门
使用C++的同学可以读读这篇博客 -> 传送门
如果我们用普通函数的写法来重载运算符
那么是这样写
(想了解更多,可以读读我的这篇文章 -> 传送门)
正文开始
C++篇
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<bits/stdc++.h> using namespace std; int a[15]={0,10,9,8,1,5,2,3,6,4,7}; bool cmp(int x,int y){return x>y;}
int main() { sort(a, a+11, cmp); for(int i=0;i<=10;i++) cout<<a[i]<<" "; return 0; }
|
而用lambda表达式就可以这样写
1 2 3 4 5 6 7 8 9 10
| #include<bits/stdc++.h> using namespace std; int a[15]={0,10,9,8,1,5,2,3,6,4,7}; int main() { sort(a,a+11,[](int x,int y){return x>y;}); for(int i=0;i<=10;i++) cout<<a[i]<<" "; return 0; }
|
同样lambda表达式对vector也是适用的
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include<bits/stdc++.h> using namespace std; int a[15]={0,10,9,8,1,5,2,3,6,4,7}; int main() { vector<int> b; for(auto x : a) b.push_back(x); sort(b.begin(),b.end(),[](int x,int y){return x>y;} ); for(int i=0;i<=10;i++) cout<<b[i]<<" "; return 0; }
|
大多数情况下,我们可能是针对pair或结构体来自定义比较函数
那么修改对应数据类型(结构体名)就ok了,类似这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<bits/stdc++.h> using namespace std; int a[15]={0,10,9,8,1,5,2,3,6,4,7}; typedef pair<int, int> pii; int main() { vector<pii> b; for(auto x : a) b.push_back(make_pair(x,x+1)); sort(b.begin(),b.end(),[](pii x,pii y){return x.first>y.first;} ); for(int i=0;i<=10;i++) cout<<b[i].second<<" "; return 0; }
|
补充一点
1
| sort(b.begin(),b.end(),[](int x,int y){return x>y;} );
|
原本应该是这样的,
1
| sort(b.begin(),b.end(),[](int x,int y) -> bool {return x>y;} );
|
不过C++可以自动识别函数返回值得数据类型,所以可以简写。
Java篇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Integer[] a = {0,10,9,8,1,5,2,3,6,4,7}; Arrays.sort(a, (x,y) -> { return y-x; }); for (int i = 0; i < a.length; i++) { System.out.printf("%d ",a[i]); } } }
|
Java的sort比较机制不同与C++
如果要实现降序就是后-前
升序就是前-后
此外,这样写也能实现降序(用内置compareTo函数)。
1 2 3
| Arrays.sort(a, (x,y) -> { return y.compareTo(x); });
|
反之,return x.compareTo(y); 就是升序。
因为只有一行语句,所以可以更简洁美观一点,直接省略花括号。
1
| Arrays.sort(a, (x,y) -> y-x;);
|
结构体方面,感觉java用起来没有C++舒服。
我们就通过这道经典的[NOIP2007 普及组] 奖学金演示一遍Java的写法吧。
做这道题需要用到Java的类与接口
朴素做法就是通过自定义一个class从而自定义compareTo来做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); Student[] stu = new Student[n+5]; for(int i=1; i<=n; i++) { int c = sc.nextInt(); int m = sc.nextInt(); int e = sc.nextInt(); stu[i] = new Student(i, c, m, e, c+m+e); } Arrays.sort(stu, 1, n+1); for(int i=1; i<=5; i++) System.out.println(stu[i].id+" "+stu[i].tot); } } class Student implements Comparable<Student> { int c,m,e,id; int tot; public Student(int id,int c,int m,int e,int tot) { this.id=id; this.c=c; this.m=m; this.e=e; this.tot=tot; } public int compareTo(Student st) { if(this.tot != st.tot) return st.tot-this.tot; if(this.c != st.c) return st.c-this.c; return this.id-st.id; } }
|
不过Java和C++的一个不同点是,
Java没有结构体
而Java里定义一个类本身也就要求必须有compareTo
所以在本题中的这个Student类就没法自定义匿名比较函数。
当然这道题想用lambda表达式来简化代码,也是可以的。
因为Java里的数组也是对象,所以我们也可以对一个二维数组中进行sort,而lambda表达式也是可以针对数组对象的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] a = new int[n+5][6]; for(int i=1; i<=n; i++) { a[i][1] = i; for(int j=2; j<=4; j++) { a[i][j] = sc.nextInt(); a[i][5] += a[i][j]; } } Arrays.sort(a, 1, 1+n, (x,y)->{ if(x[5] != y[5]) return y[5]-x[5]; if(x[2] != y[2]) return y[2]-x[2]; return x[1]-y[1]; }); for(int i=1; i<=5; i++) System.out.println(a[i][1]+" "+a[i][5]); } }
|
这样写,代码就简化很多了