-
idea创建一个普通的Java project
-
需要给该项目一个junit包,按照如下操作后就可以使用第三方的jar
lambda是一个匿名函数 ,可以更简洁的表示一个行为或者传递代码; 大家可以先看第4点,回头看再看3 -
lambda的基础语法:
语法 : (参数,参数) -> expression 或 (参数,参数) ->{ statements; }java8 的新操作符号,也叫lambda操作符,就是 ->
箭头的左侧是 lambda的参数列表
箭头的右侧是lambda需要执行的功能
语法1: 无参无返回值:
@Test
public void test1(){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello runnable");
}
});
t.start();
Thread t2 = new Thread(() -> System.out.println("hello lambda")) ;
t2.start();
Runnable r = ()->System.out.println("hello lambda runnable");
r.run();
}
语法2: 有参无返回值: 若这里的参数只有一个,则可以省略小括号
@Test
public void test2(){
Consumer consumer = (x)->System.out.println(x);
consumer.accept("hello");
}
语法3:有参数有返回值:
@Test
public void test3(){
Comparator<Integer> com = (a,b)->{
System.out.println("...");
return Integer.compare(a,b);
};
//若有只有一条语句,可以省略{} 和return 这种更推荐,
Comparator<Integer> com1 =(a,b)->Integer.compare(a,b);
// 以上没有写类型是因为jvm 可以根据上下文推断出类型,其实也可以写
// 数据类型推断,例如数组赋值,int a[] = {12,3,6,8,3}; List<StuInfo> list = new ArrayList<>();
Comparator<Integer> com2 =(Integer a,Integer b)->Integer.compare(a,b);
}
lambda需要函数式接口:
函数时表达式: 接口类中只有一个抽象方法
如何验证是否是函数式接口 @FunctionalInterface
- 使用lambda表达的好处:
假设需要分别输出计算机专业的信息,分别输出学生的年龄大于18的信息:
按照之前学过的实现方式: 定义两个方法,分别实现,但是大家会发现只有if中的条件不同,其他都相同,代码冗余
public List<StuInfo> selectProfessionals(List<StuInfo> stu){
List<StuInfo> list = new ArrayList<>();
for (StuInfo item:stu) {
if (item.getStuProfessional().equals("计算机")){
list.add(item);
}
}
return list ;
}
public List<StuInfo> selectAge(List<StuInfo> stu){
List<StuInfo> list = new ArrayList<>();
for (StuInfo item:stu) {
if (item.getStuAge()>=18){
list.add(item);
}
}
return list ;
}
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",8,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test1(){
List<StuInfo> professional = selectProfessionals(list);
for (StuInfo item : professional){
System.out.println(item);
}
System.out.println("-----------------------------");
List<StuInfo> ages = selectAge(list);
for (StuInfo item : ages){
System.out.println(item);
}
}
public class StuInfo {
private int stuId ;
private String stuName ;
private String stuSex;
private int stuAge ;
private String stuProfessional ;
setter...getter...
constructor 全参数和无参数的
重写toString方法
方式二:可以定义接口,两个类实现接口,然后根据传入不同的实现类,返回不同的结果,也叫策略模式
public interface Performer<T> {
public boolean isTrue(T t);
}
public class SelectAge implements Performer<StuInfo> {
@Override
public boolean isTrue(StuInfo stuInfo) {
if (stuInfo.getStuAge() >=18)
return true ;
return false;
}
}
public class SelectProfessional implements Performer<StuInfo> {
@Override
public boolean isTrue(StuInfo stuInfo) {
if (stuInfo.getStuProfessional().equals("计算机"))
return true ;
return false;
}
}
public List<StuInfo> shows (List<StuInfo > stus, Performer performer){
List<StuInfo> list = new ArrayList<>();
for (StuInfo item: stus ) {
if (performer.isTrue(item)){
list.add(item);
}
}
return list ;
}
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",8,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test2(){
List<StuInfo> professional = shows(list,new SelectProfessional());
for (StuInfo item : professional){
System.out.println(item);
}
System.out.println("---------------------------------");
List<StuInfo> ages = shows(list,new SelectAge());
for (StuInfo item : ages){
System.out.println(item);
}
}
方法三: 根据以上,可以使用匿名内部类实现,这样可以省略两个实现类
public interface Performer<T> {
public boolean isTrue(T t);
}
public List<StuInfo> shows (List<StuInfo > stus, Performer<StuInfo> performer){
List<StuInfo> list = new ArrayList<>();
for (StuInfo item: stus ) {
if (performer.isTrue(item)){
list.add(item);
}
}
return list ;
}
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",8,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test3(){
List<StuInfo> professional = shows(list, new Performer<StuInfo>() {
@Override
public boolean isTrue(StuInfo stuInfo) {
return stuInfo.getStuAge()>22;
}
});
for (StuInfo item : professional){
System.out.println(item);
}
}
方法四: lambda表达式,
public interface Performer<T> {
public boolean isTrue(T t);
}
public List<StuInfo> shows (List<StuInfo > stus, Performer<StuInfo> performer){
List<StuInfo> list = new ArrayList<>();
for (StuInfo item: stus ) {
if (performer.isTrue(item)){
list.add(item);
}
}
return list ;
}
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",8,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test4(){
List<StuInfo> professional = shows(list,(e) -> e.getStuAge()>22 );
professional.forEach(System.out::println);
}
方法五:使用stream API
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",8,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test5(){
// 输出所有年龄大于22的学生信息
list.stream().filter((e)->e.getStuAge()>22).forEach(System.out::println);
// 输出所有学生的姓名
list.stream().map(StuInfo::getStuName).forEach(System.out::println);
}
- 完成一个根据输入的数操作的案例
@FunctionalInterface
public interface Performer2<T> {
public Integer getNum(Integer val);
}
public Integer getNums(Integer num ,Performer2 per){
return per.getNum(num );
}
@Test
public void test4(){
int res = getNums(200,(x)->x+x);
int res1 = getNums(200,(x)->x*x);
System.out.println(res);
System.out.println(res1);
}
- 对集合排序 (先专业,专业相同按年龄比)
//对集合进行排序
List<StuInfo> list = Arrays.asList(
new StuInfo(1,"王五","男",58,"计算机"),
new StuInfo(2,"赵六","男",20,"心理学"),
new StuInfo(3,"钱五","女",25,"数学"),
new StuInfo(4,"孙家","女",18,"计算机"),
new StuInfo(5,"里尔","男",22,"数学")
);
@Test
public void test5(){
Collections.sort(list,(x,y)->{
if(x.getStuProfessional().equals(y.getStuProfessional())){
// return Integer.compare(x.getStuAge(),y.getStuAge()); // 按照年龄从小到大排序
return -Integer.compare(x.getStuAge(),y.getStuAge()); // 按照年龄从大到小排序
}else{
return x.getStuProfessional().compareTo(y.getStuProfessional());
}
});
for (StuInfo item : list){
System.out.println(item);
}
}
8.定义一个接口,里面有一个抽象方法public String getValue(String str);
实现将给定字符串全部转换位大写
public interface Performer {
public String getValue(String str);
}
public class TestLamda {
public String aa ( String str , Performer per){
return per.getValue(str);
}
@Test
public void test01(){
String str="hello";
String bb = aa(str, (x)-> x.toUpperCase());
System.out.println("bb="+bb);
String cc = aa(str,(x)->x.substring(2,4));
System.out.println("cc="+cc);
}
}
- 定义一个接口,传入两个泛型<T,R>, T是类型 R是返回值, 定义相应的抽象方法; 实现两个数的和
public interface Performer<T,R> {
public R show(T t,T t1);
}
public class TestLamda {
public Long aa (Long a,Long b, Performer<Long,Long> per){
return per.show(a,b);
}
@Test
public void test01(){
Long value = aa(12l,14l,(x,y)-> x+y);
System.out.println(value);
}
}
-
四大内置函数式接口
Consumer 消费型接口 void accept(T t)
public void aa(int num , Consumer con){ con.accept(num)}
public void test(){ aa(10),(x) ->System.out.println(“购买数量是:”+num) }
Supplier 供给型接口 T get()
public List aa (int num , Supplier sup){
List list = new ArrayList<>();
for (int i = 0 ; i < num ; i ++){
list.add(sup.get())
}
return list ;
}
public void test(){ List list = aa(3, ()->(int)Math.Random()*10) ;}
Function<T,R> 函数型接口 R apply(T t)
public String aa(String str,Function<String,String> fun){
return fun.apply(str);
}public void test(){ String ss = aa("hello ",(x)->x.substring(2,4)) ; }
Predicate 断言型接口 boolean test (T t)
public boolean aa(List list , Predicate pre){
List alsit = new ArrayList<>();
for (String item :list){
if(pre.test(item)){
alist.add(item)
}
}
return alist ;
}
public void test(){
List list = Arrays.asList(“zhang”,“wang”,“li”,“he”);
List blist = aa(list,(x)->x.length>2)
}除了以上4中还有其对应的子类
-
方法引用: lambda的另一种表示形式
语法: 对象:: 实例方法名 【非static修饰的一般方法就是实例方法】
以前:Comsumer con = (x)->System.out.println(x)
现在:Consumer con = System.out:println;
con.accept(“aaa”);以前:StuInfo stu = new StuInfo() Supplier<String> con = ()->stu.getStuName() 现在: Supplier<String> con = stu::getStuName; String str = con.get(); 类::静态方法名 以前:Comparator<Integer> con = (x,y)->Integer.compare(x,y) 现在: Comparator<Integer> con = Integer::compare; 以上 要求:调用的方法参数列表与返回值类型,要与函数式接口中的抽象方法的函数列表和返回值类型一致 类::实例方法名 以前: BiPredicate<String ,String > bp = (x,y) ->x.equals(y); 现在: BiPredicate<String ,String > bp =String:equals; 要求: 若lambda参数列表中第一个参数式实例方法的调用者,而第二个参数式实例方法的参数,使用 **类名::方法名**
-
构造器引用: 类名::new
需要调用的构造器参数列表要与函数式接口抽象方法的参数列表保持一致
以下匹配无参数构造方法:
Supplier stu = ()->new StuInfo();
Supplier stu1 = StuInfo::new调用1个参数构造方法: Function<Integer,StuInfo> fun = (x)->new StuInfo() Function<Integer,StuInfo> fun1 = StuInfo::new 调用两个参数的构造方法 BiFunction<Integer,Integer,StuInfo> bifun = StuInfo::new ;
-
数组引用 数据类型[] :: new
Function<Integer,String [] > fun= (x) -> new String[x];
String ss []= fun.apply(10);Function<Integer,String[]> fun1 = String[]:: new String ss1 []= fun1.apply(10);
lambda表达式可以使代码看起来简洁,但一定程度上增加了代码的可读性以及调试的复杂性