1 Lambda(蓝布达)表达式

编译后会产生一个$XXXImpl1的编译文件,与匿名内部类相似,但不等同于匿名内部类。
其原理是将方法作为参数进行传递,
JVM会使用一个动态调用的指令调用函数式接口中的方法。
同时使用lambda将会使代码更简洁易读。
别名:【闭包】
使用方式:①使用JDK自有的函数式接口【接口列表】②自定义函数式接口使用。
如下:
1)自定义函数式接口,并且只定义一个方法,返回值与参数没有限制

/** 接口1 要点:参数再封装返回 */ 
@FunctionalInterface 
public interface EventExector { 
	String event(String methodName); 
} 
/** 接口2 要点:计算两个数字之和返回 */
 @FunctionalInterface 
 public interface LambdaInterface1 { 
 	int mathOption(int a,int b); 
}
 /** 接口3 要点:获取当前时间的时间戳 */ 
 @FunctionalInterface 
 public interface LambdaInterface2 { 
 	void catCurrentDate(Date date); 
 } 
 /** 接口4 要点:将Map中的value取出放入一个list中 */ 
 @FunctionalInterface 
 public interface LambdaInterface3 { 
 	void copyMap(Map<String,Integer> map, List<Integer> list); 
 } 
 /** 接口5 要点:无返回无参数 */ 
 

2)将定义号的函数式接口通过参数传入

/** 接口1注入方法1 */ 
private static int operation(int a,int b,LambdaInterface1 interface1) { 
	return interface1.mathOption(a,b); 
} 
/** 接口2注入方法2 */ 
private static String realize(String target,EventExector exector) { 
	return exector.event(target); 
} 
/** 接口3注入方法3 */ 
private static void getDate(Date date,LambdaInterface2 interface2) { 
	interface2.catCurrentDate(date); 
} 
/** 接口4注入方法4 */ 
private static void replaceMap(LambdaInterface3 interface3, Map map,List list) { 
	interface3.copyMap(map,list); 
} 
/** 接口5注入方法5 */ 
private static void goToWay(LambdaInterface4 interface4) { 
	interface4.onTheWay(); 
} 
  1. 调用方法,其中()中的参数为传入的参数, -> 代表lambda表达式的箭头指引符,
    箭头符号的后面,需注意,如果有返回值,有两种返回书写方式。
    在大括号中,使用return返回,没有大括号,直接将返回值写在箭头符后面。
    如果没有返回值,箭头符后面的指引内容将是纯粹的Java指令,不会有任何返回。
/** 传入一个参数 有返回 */ 
System.out.println(realize("xx", (x) -> "HELLO GUYS! " + x)); 
/** lambda 传入两个参数 有返回 */ 
System.out.println(operation(1, 2, (a, b) -> a + b)); 
/** 传入一个参数,无返回 */ 
getDate(new Date(), date -> { 
	long time = date.getTime(); 
	System.out.println("当前内容时间戳"+time); 
}); 
/** 传入两个参数,无返回 */ 
Map<String,Integer> map = new Hashtable<>(); 
map.put("one",1);
map.put("two",2); 
map.put("three",3); 
map.put("four",4); 
List list = new ArrayList(); 
replaceMap((map1, list1) -> { 
	for (String s : map.keySet()) {
		 list.add(map.get(s)); 
 	} 
 },map,list); 
/** 无参数无返回 */ 
goToWay(() -> System.err.println("请纠正你的方向!")); 

4)使用lambda注意事项

  1. 外部局部变量[基本类型]放在lambda中使用时,必须使用final修饰.
    因为lambda中外部局部变量无法传递!变量值无法改变。
    final:
    ① 如果修饰给基本类型变量,则表示值不可改变;
    ② 如果修饰引用类型变量,那么变量的引用地址不可改变,但是属性值是可以改变的。

  2. 考虑性能,如果代码不繁多,可以不用lambda

@Test 
public void lambda2() { 
	String name = "我醉了"; 
	int age = 12; 
	sayHello("高进",message -> { 
		name = "dsa";  // 此处编译会报错 
		age = 11; // 此处编译会报错 
		System.out.println(message+name+age); 
	}); 
} 

2 双冒号::语法

这种 [方法引用] 或者说 [双冒号运算] 对应的参数类型是 Function<T,R> T表示传入类型,R表示返回类型。
比如表达式 person -> person.getAge(); 传入参数是 person,返回值是 person.getAge()
那么方法引用 Person::getAge 就对应着 Function<Person,Integer> 类型。

/** 所需函数式接口 */ 
@FunctionalInterface 
public interface Merchant<T> { 
	T get(); 
} 
/** 接口使用类 */ 
public class Computer { 
	public static Computer create(final Merchant<Computer> merchant) { 
		return merchant.get(); 
	} 
	public static void getComputer(final Computer computer) { 
		System.out.println("地址:"+computer.toString()); 
	} 
	public void getPro(final Computer computer) { 
		System.out.println(computer.hashCode()); 
	} 
	public void getDate() { 
		System.out.println(LocalDate.now().get(ChronoField.YEAR)); 
	} 
	public void getTime() { 
		System.out.println(LocalTime.now().get(IsoFields.DAY_OF_QUARTER)); 
	} 
} 

主要有四种类型:
1)构造器引用 [Class::new]
Computer computer = Computer.create(Computer::new);
2)静态方法引用 [Class::static_method]

List<Computer> list = Arrays.asList(computer); 
list.forEach(Computer::getComputer); 

3)特定类的任意对象的方法引用 [Class::method]

List<Computer> list = Arrays.asList(computer);
list.forEach(Computer::getDate);
list.forEach(Computer::getTime); 

4)特定对象的方法引用 [instance::new]

List<Computer> list = Arrays.asList(computer); 
final Computer huawei = Computer.create(Computer::new);`
list.forEach(huawei::getPro); 

3 Optional

JDK8处理空指针异常的工具类,减少空指针判断,可以存储空对象
只有两个值,一个是原本值,一个是空值

/** 静态方法 */ 
Optional.empty() 返回一个空的Optional对象 
Optional.of() 返回一个指定非null值的Optional 
Optional.ofNullable() 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional	
/** 实例方法 */ 
optional.hashcode 返回存在值的哈希码,如果值不存在 返回 0 
optional.toString 返回一个Optional的非空字符串,用来调试 
optional.get 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException 
optional.equals 判断其他对象是否等于 Optional 
optional.isPresent 如果值存在则方法会返回true,否则返回 false 
optional.ifPresent 如果值存在则使用该值调用 consumer , 否则不做任何事情 
optional.filter 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional
optional.flatMap 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional 
optional.orElse 如果存在该值,返回值, 否则返回 other 
optional.map 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,
		     则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional 
optional.orElseGet 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果 
optional.orElseThrow 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 

4 Stream

/** 生成流 */ 
list.stream() list.parallelStream() 
/** 所有操作 */ 
forEach() -> 循环操作 filter() -> 条件满足 map() -> 值处理 sorted()
		  -> 排序 limit() -> 控制数量 summaryStatistics() -> 数据统计
在之前需要使用mapTo系列方法,也就是前提需要有数据流(int,float,double),主要有最大值,最小值,总和,总数,平均数
collect(Collectors.toList()) -> 转换成集合 collect(Collectors.joining(分隔符)) -> 将字符串内容合并到一起 
/** 代码示例 */ 
/** Stream 得到集合中元素值大于等于7的元素数量 */ 
List<Integer> numbers = Arrays.asList(1, 2, 2752, 2200, 7857, 6, 7, 8, 45, 54, 78, 857, 3, 357857, 86, 200780); 
numbers.stream()
	.filter(obj -> obj % 2 == 0)
	.limit(5).map(obj -> obj << 2)
	.sorted((o1, o2) -> o2 - o1)
	.forEach(integer -> {
		System.out.print(integer+"\t"); 
	}); 
/** 使用Join */ 
List<String> stringList = Arrays.asList("张三","李四","王五","赵六","钱七","胡八"," "); 
String collect = stringList.stream()
						   .collect(Collectors.joining("先生,"))
						   .trim(); 
// 取出字符串尾部的 ',' 
System.out.println(collect.substring(0,collect.length()-1)); 
========控制台出入如下========= 
11008	8800	32	24	8	 
张三先生,李四先生,王五先生,赵六先生,钱七先生,胡八先生 

5 时间API

/** 月份支持 获取单独月份的支持 */
Month 
/*月份天数支持 可以获取月日格式的时间 */
MonthDay 
/**年份支持 可以获取年份*/
Year 
/*年份月支持 获取年月格式的时间*/
YearMonth 
/*时间戳操作 sql包中的获取时间戳中的方法*/
TimeStamp
/*瞬时时间 获取时间戳格式的时间*/ 
Instant 
/*星期支持 星期天数的格式时间获取*/
DayOfWeek 
/*日期支持 只获取基本的日期格式的时间。如【年-月-日】*/
LocalDate 
/*日期时间支持 获取日期时间支持,不包含时区与星期。,如【年-月-日T时:分:秒.Nano秒】,其中T分隔符*/
LocalDateTime
/*时间支持 只支持时间,不封装时区及任何时间信息*/ 
LocalTime 
/*日期时间转换器 提供日期时间格式的转换*/
DateTimeFormatter 
/*单线程日期时间转换器 只有一个返回字符串的静态方法*/
DateTimeFormatterBuilder

6 重复注解与类型注解

/** 重复注解,可以重复使用,原理是用了注解容器 **/ 
@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(Annos.class) 
public @interface Anno { 
	String value(); 
} 
@Retention(RetentionPolicy.RUNTIME)  
@interface Annos { 
	Anno[] value(); 
} 

使用重复注解的原理使用了注解容器,实际上被声明的类上的注解是容器注解

/** 类型注解主要就是泛型与声明类型的时候可以使用,保证了程序的健壮性 */ 
/** 定义一个可以使用在类型上的注解 */ 
@Retention(RetentionPolicy.RUNTIME) 
// TYPE_USE 用于类型 
TYPE_PARAMETER 用于表示泛型 
@Target(ElementType.TYPE_USE) 
public @interface MyTest { 
	String value() default ""; 
} 

7 concurrent并发包

// JUC包是jdk1.8为并发编程提供的工具包 提供了一些并发工具实现,后续补充

8 默认方法

在JDK8之前,一旦修改了接口中的方法,所有实现类都必须改动。
为了不影响之前的版本,提供在接口中定义默认方法的实现。
在方法前修饰default,并在代码域中编写默认内容

public interface Vehicle { 
	/** 默认方法 */ 
	default void print() { 
		System.out.println("我是一辆车!"); 
	} 	
	/** 静态方法 */
	static void hornBlock() { 
		System.out.print("我要超车了!");
	} 
} 

9 Base64编码

// 编码 
private static String printEncoding(String str) { 
	Base64.Encoder encoder = Base64.getEncoder(); 
	byte[] encode = encoder.encode(str.getBytes()); 
	return new String(encode); 
} 
// 解码 
private static String printDecoding(String str) { 
	Base64.Decoder decoder = Base64.getDecoder(); 
	byte[] decode = decoder.decode(str.getBytes()); 
	return new String(decode); 
} 

10 内置函数式接口的应用

/** 菜鸟教程实例 */ 
https://www.runoob.com/java/java8-functional-interfaces.html 
/** 方法调用 */ 
public static void main(String[] args) { 
/** BiConsumer<T,U> 接收两个参数,不返回任何结果 */ 
getSomeSubject((s, integer) -> System.out.println(integer),"张三",12); 
/** BiFunction<T,U,R> 接收两个参数,返回一个结果 */ 
String someSubject = getSomeSubject((num1, num2) -> {
	return num1*num2+"";
},12,10); 
System.out.println("返回的结果为:"+someSubject); } 
// 方法定义 
private static String getSomeSubject(BiFunction<Integer,Integer,String> function,Integer num1,Integer num2) { 
	return function.apply(num1,num2); 
} 
private static void getSomeSubject(BiConsumer<String,Integer> consumer,String name,Integer age) {
	consumer.accept(name,age); 
} 
09-26 11:17