折纸的不归路(25)

一.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的新特性,内容说实话是挺多的,现在也没有完全消化,还得抽时间多巩固一哈.不忘初心,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值