一.jdk8新特性
1.lambda表达式
2.方法的引用
3.函数式编程
4.Stream的api
5.新的日期api
二.接口
作用:
1.拓展了单继承的问题
2.定义规范的
接口的使用方式
1.方法都是抽象方法,jdk1.8之后可以定义方法的实现
静态方法
默认方法
2.变量的修饰符默认是:public static final 相当于一个常量
接口的实例化:
由于接口不能直接实现实例化
1.使用一个类来实现该接口
1)使用实现类来声明
2)使用接口来声明,指向实现类的对象
2.匿名内部类
例:写一个接口Formula.java
package JDK8;
/**
* 定义一个计算的接口
*
* @author Acer
*
*/
public interface Formula {
// 计算
void calculate(int i);
// void add(int i);
// jdk8提供了默认方法和静态方法的实现
default void sqrt(int i) {
// 使用Math的方法进行开放\方
System.out.println(Math.sqrt(i));
}
static void abs(int i) {
System.out.println(Math.abs(i));
}
public static void main(String[] args) {
// //1.使用实现类去声明
// F f = new F();
// f.calculate(10);
// f.sqrt(4);
// Formula.abs(-10);
// 2.使用接口去声明
// Formula f = new F();
// f.calculate(10);
// f.sqrt(4);
// Formula.abs(-10);
// F.abs(-20);
// 3.使用匿名内部类
Formula f = new Formula() {
@Override
public void calculate(int i) {
System.out.println("匿名结果为" + (i + 200));
}
};
f.calculate(10);
f.sqrt(2);
Formula.abs(-30);
}
}
class F implements Formula {
@Override
public void calculate(int i) {
System.out.println("结果为:" + (i + 100));
}
public void sqrt(int i) {
System.out.println("F" + Math.sqrt(i));
}
static void abs(int i) {
System.out.println("F" + Math.abs(i));
}
}
三.函数式编程
将精力移到函数的具体实现上,不用产生对象去完成,可以创造出更简洁的代码
四.lambda表达式
语法:
(参数列表)->(表达式或者代码块)
package JDK8;
import java.util.*;
public class LambdaTest1 {
public static void main(String[] args) {
//回顾一下提供一个比较器
//准备一个集合
List<String> list = Arrays.asList("hello","world","tom","test");
//使用默认排序
//Collections.sort(list);
// Collections.sort(list,new Comparator<String>() {
//
// @Override
// public int compare(String o1, String o2) {
// // TODO Auto-generated method stub
// return -o1.compareTo(o2);
// }
// });
//可以尝试提炼出关键信息
//参数列表,关键执行代码,返回值
//使用lambda表达式进行简化
Comparator<String> c1 = (String o1,String o2)->{
return -o1.compareTo(o2);
};
//类型推断
Comparator<String> c2 = (o1,o2)->{
return -o1.compareTo(o2);
};
Comparator<String> c3 = (o1,o2)-> -o1.compareTo(o2);
//最终形态(o1,o2)-> -o1.compareTo(o2);
Collections.sort(list,(o1,o2)-> -o1.compareTo(o2));
//Collections.sort(list,c3);
System.out.println(list);
}
}
例子:
()->5
代表没有参数,返回值为int,永久返回5
(String s) -> s.length
代表传入的参数为String,返回值为int,返回s的长度
(String s,int i) -> {
System.out.println(s+":"+i);
}
代表传入一个String和一个int类型的参数,没有返回值,直接输出s的值:i的值
lambda表达式访问变量
成员变量
静态变量
实例变量
局部变量
例:LambdaTest6
public class LambdaTest6 {
private static int j;
private int k;
public static void main(String[] args) {
new LambdaTest6().test();
}
public void test() {
j = 10;
k = 20;
// 局部变量
int num = 30;
// Action6 a = i -> System.out.println(i + j + k + num);
// a.run(40);// 结果是多少?
// 来进行一下赋值
j = 1;
k = 2;
num = 3;// num已经变成了final类型
}
}
interface Antion6 {
void run(int i);
}
成员变量都可以正常访问和再赋值,局部变量在仿问
结束后都会变成final类型,不可以再赋值
五.函数式接口:
定义
接口中有且只有一个抽象方法,该接口叫函数式接口
lambda表达式只能配合函数式接口一起使用
@Functional Interface
作用:注解在接口上,用来在编译阶段验证一个接口是否是函数式接口
函数式接口只有一个抽象方法,方便和lambda表达式配合使用让表达式能够唯一匹配抽象方法
函数式编程不会产生对象,但是可以替代内部类完成
package JDK8;
public class LambdaTest2 {
public static void main(String[] args) throws InterruptedException {
// 传统方式
test(new Action2() {
@Override
public void run(String s) {
System.out.println(s + "传统方式...1");
}
});
// lambda表达式
Action2 a = b -> System.out.println(b + "lambda方式...1");
test(a);
Action2pro a2p = i -> "本次获得的数据为:" + i + "";
testpro(a2p);
// 使用lambda表达式来实现runnable接口
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
});
t1.start();
t1.join();
System.out.println("结束");
}
public static void test(Action2 a) {
String s = "hello world";
a.run(s);
}
public static void testpro(Action2pro<String, Integer> ap) {
int i = 199;
System.out.println(ap.run(i));
}
}
@FunctionalInterface
// 函数式接口有且只有一个抽象方法
interface Action2 {
void run(String s);
// void show(int i);
default void say() {
System.out.println("say....");
}
default void hello() {
System.out.println("hello....");
}
}
// 函数式泛型接口
interface Action2pro<T, A> {
T run(A a);
}
六.方法的引用
语法::(双冒号)
1.具体对象的实例方法的引用
要通过对象名::实例方法的名字
2.静态方法的引用
要通过类名::静态方法的名字
3.任意对象的实例方法的引用
要通过类名::非静态方法的名字(不能有参数)
4.构造方法的引用
要通过类名::new 使用哪个构造器,就在函数式接口的抽象方法中传递参数
引用过程中的一些规则
保证方法的参数列表相同,方法的返回值法相同
package JDK8;
public class LambdaTest4 {
public static void main(String[] args) {
// 使用lambda表达式
// test(s->System.out.println("s"+s));
// 使用方法的引用
// 静态方法的引用
// test(C4::test1);
// 代表把C4类中静态方法test1的实现引用过来,替代Action4中的run方法的实现
// C4 c = new C4();
// 实例方法的引用
// test(c::test2);
// test(c::test3);
// test(c::test4);//没有参数的
// 使用泛型
Action4Pro<C4> ac1 = c -> C4.test1("111");
Action4Pro<C4> ac2 = c -> c.test2("222");
Action4Pro<C4> ac3 = a -> System.out.println(a.test3("333"));
Action4Pro<C4> ac4 = a -> System.out.println(a.test4());
// 方法的引用
Action4Pro<C4> ac5 = C4::test0;
// testT(ac5);
Action4Pro<C4> ac6 = C4::test4;
// 要求任意对象的非静态方法,必须是无参的
testT(ac6);
}
public static void test(Action4 a) {
String s = "hello";
a.run(s);
}
public static void testT(Action4Pro<C4> apc) {
C4 c = new C4();
apc.run(c);
}
}
interface Action4 {
// 抽象方法的特点,有String类型的参数,但是没有返回值
void run(String s);
}
interface Action4Pro<T> {
void run(T t);
}
class C4 {
public static void test0(C4 c) {
c.test2("C4 222");
}
// 静态方法
public static void test1(String s1) {
System.out.println("test1" + s1);
}
// 实例方法
public void test2(String s2) {
System.out.println("test2" + s2);
}
// 带返回值的方法
public String test3(String s3) {
return "test3" + s3;
}
// 带返回值但是没有参数的方法
public String test4() {
System.out.println("test4执行了...");
return "test4";
}
}
七.JDK中的提供的一些函数式接口
java.util.function 包下
判断型函数式接口 predicate
要求输入一个T类型的参数,返回一个布尔值
and
or
negate
isEqual
package JDK8;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class PredicateTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("Java","JavaScript","C","C++","C#","Spring","SpingMVC","CSS","HTML");
//如果只返回true或者false代表全部打印或者全部不打印
Predicate<String> p1 = s->false;
Predicate<String> p2 = s->true;
// show(list,p1);
// show(list,p2);
//打印字符串长度大于4的长度
Predicate<String> p3 = s->s.length()>4;
// show(list,p3);
//打印字符串以J开头的元素
Predicate<String> p4 = s->s.startsWith("J");
// show(list,p4);
//打印字符串以C开头且字符串长度不大于2的元素
Predicate<String> p5 = s->s.startsWith("C");
Predicate<String> p6 = s->s.length()<=2;
Predicate<String> p7 = p5.and(p6);
// show(list,p7);
//打印字符串以S开头,或者以C结尾的元素
Predicate<String> p8 = s->s.startsWith("S");
Predicate<String> p9 = s->s.endsWith("C");
Predicate<String> p10 = p8.and(p9);
// show(list,p10);
//打印字符串不以S开头,或者以C结尾的元素
// show(list,p8.negate().or(p9));
//打印等同于Java的元素
Predicate<String> p11 = Predicate.isEqual("Java");
show(list,p11);
}
// 用来遍历集合
public static void show(List<String> list,Predicate<String> p) {
for(String s:list) {
//因为返回值是布尔,就需要对输入的s进行验证,如果符合返回true
if(p.test(s)) {
System.out.println(s);
}
}
}
}
生产性函数式接口 SupplierTest
要求不输入任何参数,返回一个T类型对象
get
package JDK8;
import java.util.function.Supplier;
public class SupplierTest {
public static void main(String[] args) {
// 生产一个4位数的验证码
String str = "qwertyuioplkjhgfdsazxcvbnm1234567890";
char[] data = str.toCharArray();
// 准备一个可变字符串
StringBuilder sb = new StringBuilder();
Supplier<String> s = ()->{
for(int i = 0;i<8;i++) {
int index = (int)(data.length*Math.random());
sb.append(data[index]);
}
return sb.toString();
};
// Supplier<String> s1 = ()->"helloworld";
String result = s.get();
System.out.println(result);
}
}
消费型函数式接口 Consumer
要求输入单个T类型的参数,并且不返回任何结果
accept
andThen
package JDK8;
import java.util.function.Consumer;
public class ConsumerTest {
public static void main(String[] args) {
Consumer<String> c1 = a->{
System.out.println("第一次执行:"+a);
};
Consumer<String> c2 = s->{
System.out.println("第二次执行:"+s);
};
// c1.accept("aaaaaa");
c1.andThen(c2).accept("bbbbb");
}
}
函数型函数式接口
要求输入单个T类型的参数,并返回R类型的结果,
就是指第一个泛型是apply的参数,第二个泛型是apply返回值类型
apply
compose
andThen
identity
package jdk8day2;
import java.util.function.Function;
public class FunctionTest {
public static void main(String[] args) {
// 需求:需要传入一个String类型的name,返回一个Student类型
String name = "tom";
Function<String, Student> f1 = Student::new;
// 等号后与s->new Student(s);完全等价
Student stu = f1.apply(name);
// 匿名内部类的写法
// Student stu1 = new Function<String,Student>() {
//
// @Override
// public Student apply(String t) {
// return new Student(t);
// }
// }.apply("joker");
System.out.println(stu);
System.out.println(stu.getName());
System.out.println("=======");
// 需求:在name创建对象之前,给name加一个前缀
Function<String, String> f2 = s -> "briup_" + s;
Student stu2 = f1.compose(f2).apply(name);
System.out.println(stu2);
System.out.println(stu2.getName());
System.out.println("=======");
// 需求:创建完对象之后,输出该对象的name的字符串的长度
Function<Student, Integer> f3 = s -> s.getName().length();
int len = f1.compose(f2).andThen(f3).apply("joker");// 链式操作
System.out.println(len);
System.out.println(stu2);
System.out.println(stu2.getName());
Function.identity();
}
}
class Student {
private String name;
public Student() {
super();
}
public Student(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
}
八.心得
今天学的是要是jdk8的新特性,内容说实话是挺多的,现在也没有完全消化,还得抽时间多巩固一哈.不忘初心,加油!