目录
1.内部类
内部类有成员内部类、局部内部类(定义在方法内部的)、匿名内部类、静态内部类
2.匿名内部类
匿名内部类,顾名思义就是没有名称的内部类。
//匿名内部类
Runnable r1 = new Runnable(){
@Override
public void run(){
System.out.println("Hello World!");
}
};
// 其中r1 的功能和R2类相同
class R2 implements Runnable{
@Override
public void run() {
System.out.println("Hello World!");
}
}
Runnable r2 = new R2();
r1.run();
r2.run();
3.lambda表达式
lambda是一个匿名函数,可以把lambda表达式理解为 一段可以传递的代码。
->:java8引入的新操作符,称为lambda操作符
->左侧:lambda表达式的参数列表
->右侧:lambda表达式所需执行的功能。
3.1 函数式接口@FunctionalInterface
只包含一个抽象方法的接口,称为函数式接口,可以用lambda表达式创建该接口的对象。典型的函数式接口有Runnable接口。
3.2 lambda表达式语法
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* @Description:
* @Author: cc
* @CreateDate: 2018/11/7 15:01
*/
public class LambdaDemo {
/**
* lambda格式一:无参无返回值
*/
@Test
public void test1(){
//匿名内部类
Runnable r1 = new Runnable(){
@Override
public void run(){
System.out.println("Hello World!");
}
};
// Lambda 表达式
Runnable r2=()->System.out.println("Hello!");
}
/**
* lambda格式二:一个参数无返回值
* ()可以省略不写:Consumer<String> consumer = x->System.out.println(x);
*/
@Test
public void test2(){
Consumer<String> consumer = (x)->System.out.println(x);
consumer.accept("hello");
}
/**
* lambda格式三:多个参数有返回值,函数体为多条语句
* 需要写{}大括号
*/
@Test
public void test3(){
Comparator<Integer> com= (x,y)->{
System.out.println(x);
return Integer.compare(x,y);
};
System.out.println(com.compare(4,7));
}
/**
* lambda格式四:有返回值,函数体为一条语句
* {}大括号可以省略不写
*/
@Test
public void test4(){
Comparator<Integer> c = (x,y)->Integer.compare(x,y);
System.out.println(c.compare(2,5));
}
}
4. 应用
4.1 自定义运算
@FunctionalInterface
public interface MyFun {
public Integer getValue(Integer t);
}
// 将函数式接口作为参数传递
public Integer operator(Integer num,MyFun myFun){
return myFun.getValue(num);
}
@Test
public void exercise1(){
// 使用函数式编程实现平方操作
Integer e= operator(100,(x)-> x * x);
Integer s = operator(222,(x)->20+x);
System.out.println(e +"\n"+s);
}
4.2 排序
调用Collections.sort,比较两个Employee,先按年龄排序,年龄相同按姓名排序
private List<Employee> employees = Arrays.asList(
new Employee("小王",23,"111"),
new Employee("小张",22,"111"),
new Employee("哈哈",100,"111"));
@Test
public void exercise2(){
Collections.sort(employees,(e1,e2)->{
if (e1.getYear()==e2.getYear())
return e1.getName().compareTo(e2.getName());
else
return Integer.compare(e1.getYear(),e2.getYear());
});
for (Employee e:employees)
System.out.println(e);
/** 输出
* Emloyee{name='小张', year='22', position='111'}
* Emloyee{name='小王', year='23', position='111'}
* Emloyee{name='哈哈', year='100', position='111'}
*/
}
4.3 泛型函数式接口
@FunctionalInterface
public interface MyFun2<T,R>{
public R getValue(T t1,T t2);
}
public void op(Long l1,long l2,MyFun2<Long,Long> mf){
System.out.println(mf.getValue(l1,l2));
}
@Test
public void exercise3(){
op(100L,22L,(x,y)->x+y);
}
5. java 8内置函数式接口
四大核心函数式接口
接口 | 方法 | 说明 |
---|---|---|
Consumer | void accept(T t) | 消费型接口 |
Supplier | T get() | 供给型接口 |
Function<T, R> | R apply(T,t) | 函数型接口 |
Predicate | Boolean test(T t) | 断言型接口 |
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* @Description:
* @Author: cc
* @CreateDate: 2018/11/7 18:07
*/
public class java8Inner {
public void happly(double m, Consumer<Double> con){
con.accept(m>100?m-1:m+1);
}
@Test
public void test1(){
happly(100,m->System.out.println("happly "+m*2));
//结果为: happly 202.0
}
//生成指定个数的整数集合
public List<Integer> getNumList(int num, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for (int i=0;i<num;i++){
Integer n = supplier.get();
list.add(n);
}
return list;
}
@Test
public void test2(){
List<Integer> numList= getNumList(10,()->(int)(Math.random()*100));
for (int l:numList)
System.out.print(l+" ");
}
//处理字符串
@Test
public void test3(){
String s1 = handlerStr("222 ",(s)->s.trim());
String s2 = handlerStr("222 www",s->s.substring(2,1));
System.out.println(s1+" "+s2);
}
public String handlerStr(String s, Function<String,String> fun){
return fun.apply(s);
}
// 返回大于3的字符串集合
@Test
public void test4(){
List<String> list = Arrays.asList("22","sssssss","hhh");
List<String> newList = filterStr(list,(s)->s.length()>3);
for(String s:newList)
System.out.println(s);
}
public List<String> filterStr(List<String> list, Predicate<String> predicate){
List<String> stringList = new ArrayList<>();
for (String str:list){
if (predicate.test(str))
stringList.add(str);
}
return stringList;
}
}
6. 方法引用
如果lambda体中的内容已经实现,我们可以使用方法引用。lambda体中的调用的参数列表和返回值类型要与函数式接口中抽象方法的参数列表和返回值类型保持一致。
主要有三种格式:
- 对象::实例方法名
- 类::实例方法名
- 类::静态方法名
import org.junit.Test;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @Description:
* @Author: cc
* @CreateDate: 2018/11/7 19:49
*/
public class MethodRefercen {
// 方法引用1 —— 对象::实例方法名
@Test
public void test1(){
Consumer<String> c1 = (x)->System.out.println(x);
Consumer<String> consumer1= System.out::println;
}
// 方法引用2 —— 类::静态方法名
@Test
public void test2(){
Comparator<Integer> com = (x,y)->Integer.compare(x,y);
Comparator<Integer> com2 = Integer::compare;
}
//方法引用3 —— 类::实例方法
// 若lambda体中的第一参数是实例方法的调用者,第二参数是实例方法的参数时
@Test
public void test3(){
BiPredicate<String,String> biPredicate = (x,y)->x.equals(y);
BiPredicate<String,String> bp2 = String::equals;
}
}
7.构造器引用
格式为: 类名::new
需要调用构造器的参数列表 和 函数式接口 抽象参数列表一致
public void test(){
Supplier<Employee> sup1 = ()->new Employee();
Supplier<Employee> sup2 = Employee::new;
}