jdk8新特性

1.接口的静态方法和默认方法

1.1默认方法

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个default关键字即可实现默认方法。

采用默认理由:接口本身是有弊有利,利:体现面向对象抽象编程而不是面向具体过程编程;弊:当对某一个接口进行修改时,则需要修改全部实现该接口的实现类。因为目前java8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关接口添加新的方法及实现,但对于已经发布的版本是没有办法给接口添加新的方法的同时不影响已经有的实现类,所以引进默认方法。目的是为了解决接口的修改与现有实现不兼容的问题。

1.2静态方法

给方法加上static关键字,使其成为静态方法,可写具体实现。

举例

interface Inf{
    int add(int a, int b);
    default int mul(int a, int b){
    return a * b;
}
 static double div(double a, double b){
    return a / b;
 }
}


class InfImp implements Inf{
@Override
public int add(int a, int b) {
    return a + b;
 }
}
public class InterfaceDemo {
  public static void main(String[] args) {
    Inf inf = new InfImp();
    System.out.println(inf.add(10, 20));
    System.out.println(inf.mul(10, 20));
    System.out.println(Inf.div(23, 2));
   }
}

2.Lambda表达式

Lambda表达式--也可以称为闭包,Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用Lambda表达式可以使代码变得更加简洁紧凑。

语法:

(parameters) -> expression
或
(parameters) ->{ statements; }

几大重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

举例:

简洁示例;

//传统方式
int add(int a, int b){
    return a +b;
}
  //lambda表达式
  (a,b) -> a + b

//传统方式
int add(int a, int b){
    System.out.println(a + b);
    return a + b;
}
//lambda表达式
(a, b) -> {
    System.out.println(a + b);
    return a + b;
}

具体示范:

public class LambdaDemo {
	
	interface inf{
		int add(int a,int b) ;
	}
	
	public static void main(String[] args) {
		//一:传统方法
		inf in = new inf() {
			
			@Override
			public int add(int a, int b) {
				return a+b;
			}
		};
		
		System.out.println(in.add(10, 20));
		
		//lambda表达式
		inf in2 = (a,b) -> a+b;
		System.out.println(in2.add(20, 30));
		
		//二:Comparator
		Comparator comparator = new Comparator() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return o1-o2;
			}
		};
		//lambda表达式
		Comparator comparator2 = (o1,o2) -> o1.length()-o2.length();
	}
}

总结注意点:

1.Lambda 表达式主要用来定义行内执行的方法类型接口

2.Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力

3.lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

4.可以直接在 lambda 表达式中访问外层的局部变量,局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

5.在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量

3.forEach

用于遍历信息,配合Lamdba一起使用

举例:

public class ForEachDemo {

	static Integer sum=0;
	
	public static void main(String[] args) {
		List list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		
		list.forEach(e -> {sum += e;});
		System.out.println(sum);
		
		Map map = new HashMap<>();
		map.put(1, "小赐赐");
		map.put(2, "宇宙");
		map.put(3, "无敌");
		map.put(4, "帅");
		
		map.forEach((k,v) -> System.out.println(k+"="+v));
	}
}

结果如图:

jdk8新特性_第1张图片

4.方法引用

方法引用通过方法的名字来指向一个方法,使用一对冒号 :: 可以使语言的构造更紧凑简洁,减少冗余代码。

注意:

如果Lambda表达式中仅仅调用一个已经存在的方法,那么可以通过方法名来引用这个已经存在的方法。被引用的方法要加上::。需要注意的是----定义的方法与方法体内调用的方法参数和返回值类型必须相同。

语法:

1.构造器引用:它的语法是Class::new,或者更一般的Class< T >::new

2.静态方法引用:它的语法是Class::static_method

3.特定类的任意对象的方法引用:它的语法是Class::method

4.特定对象的方法引用:它的语法是instance::method

应用实例:

public class MethodReferenceDemo {
	 interface Inf{
		 void output(int a) ;
	 }
	 
	 interface InfTwo{
		 public String create(String x);
	 }
	
	public static void main(String[] args) {	
		//匿名类
		Inf inf1 = new Inf() {
			
			@Override
			public void output(int a) {
				System.out.println(a);
				
			}
		};
		//lambda
		Inf inf2 = a ->System.out.println(a);
		
		//方法引用
		Inf inf3 = System.out::println;
		
		List list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.forEach(System.out::println);
		
		//new
		InfTwo infTwo2 = String::new;
		System.out.println(infTwo2.create("小赐赐"));
		//等同于 匿名内部类
		InfTwo infTwo = new InfTwo() {
			
			@Override
			public String create(String x) {
				return x;
			}
		};
	}
}

5.stream

是对集合或数组进行操作的一个工具。

特点:

元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。

数据源流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。

聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道。

内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。


获取Stream的常用方式

    A.stream() − 为集合创建串行流。

    B.parallelStream() − 为集合创建并行流。

public static Stream of(T... values)Stream的常用操作分类

    A.Intermediate方法

    B.Terminal方法

    C.Short-circuiting方法

常用操作分类具体如下:

A、Intermediate方法
  1.concat
concat方法将两个Stream连接在一起,合成一个Stream
Stream.concat(Stream.of(1, 2, 3, 4), Stream.of(4, 5, 6 , 7)).forEach(System.out::println);
  2.distinct
distinct方法以达到去除掉原Stream中重复的元素,生成的新Stream中没有没有重复的元素
Stream.concat(Stream.of(1, 2, 3, 4), Stream.of(4, 5, 6 ,7)).distinct().forEach(System.out::println);
  3.filter
filter方法对原Stream按照指定条件过滤,在新建的Stream中,只包含满足条件的元素,将不满足条件的元素过滤掉
Stream.of(1, 2, 3, 4, 5, 6).filter(e -> e % 2 == 0).forEach(System.out::println);
  4.map
map方法将对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素
list.stream().map(e -> e.toUpperCase()).forEach(System.out::println);
  5.sorted
sorted方法将对原Stream进行排序,返回一个有序列的新Stream
list.stream().sorted((o1, o2) -> o1.length() - o2.length()).forEach(System.out::println);
B、Terminal方法
  1.collect
将流重新生成列表
List list2 = Stream.of(1, 2, 3, 4, 5, 6).filter(e -> e % 2 ==0).collect(Collectors.toList());
  2.forEach
其用于遍历Stream中的所元素,避免了使用for循环,让代码更简洁,逻辑更清晰
  3.count
count方法将返回Stream中元素的个数。
long v = Stream.of(1, 2, 3, 4, 5, 6).filter(e -> e % 2 == 0).count();
  4.min
min方法根据指定的Comparator,返回一个Optional,该Optional中的value值就是Stream中最小的元素
String min = list.stream().min((o1, o2) -> o1.length() - o2.length()).get();
  5.max
max方法根据指定的Comparator,返回一个Optional,该Optional中的value值就是Stream中最大的元素
String max= list.stream().max((o1, o2) -> o1.length() - o2.length()).get();
C、Short-circuiting方法
  1.allMatch
allMatch操作用于判断Stream中的元素是否全部满足指定条件。如果全部满足条件返回true,否则返回false。
boolean b = Stream.of(10, 2, 30, 4, 50, 6).allMatch(e -> e % 2 == 0);
  2.anyMatch
anyMatch操作用于判断Stream中的是否有满足指定条件的元素。如果最少有一个满足条件返回true,否则返回false。
boolean b2 = Stream.of(10, 2, 3, 4, 50, 6).anyMatch(e -> e % 2 == 0);
  3.findFirst
findFirst操作用于获取含有Stream中的第一个元素的Optional,如果Stream为空,则返回一个空的Optional。
Integer i = Stream.of(10, 2, 3, 4, 50, 6).findFirst().get();
  4.limit
limit方法将截取原Stream,截取后Stream的最大长度不能超过指定值N。如果原Stream的元素个数大于N,将截取原Stream的前N个元素;如果原Stream的元素个数小于或等于N,将截取原Stream中的所有元素。
Stream.of(10, 2, 3, 4, 50, 6).limit(3).forEach(System.out::println);
  5.noneMatch

noneMatch方法将判断Stream中的所有元素是否满足指定的条件,如果所有元素都不满足条件,返回true;否则,返回false.

boolean b3 = Stream.of(101, 21, 301, 41, 501, 61).noneMatch(e -> e % 2 == 0);

举例:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo {
	public static void main(String[] args) {
		List list = new ArrayList<>();
		list.add("abv");
		list.add("ddee");
		list.add("jheee");
		list.add("dd");
		
		//filter
		Stream.of(1,2,3,4,5,6).filter(e -> e%2==0).forEach(System.out::print);
		System.out.println();
		//concat
		Stream.concat(Stream.of(1,2,3), Stream.of(1,2,3,4)).forEach(System.out::print);
		System.out.println();
		//distinct
		Stream.concat(Stream.of(1,2,3), Stream.of(1,2,3,4)).distinct().forEach(System.out::print);
		System.out.println();
		//map
		list.stream().map(e -> e.toUpperCase()).forEach(System.out::print);
		System.out.println();
		//sorted
		list.stream().sorted((o1,o2) -> o1.length()-o2.length()).forEach(System.out::println);
		System.out.println();
		//collect
		List list2 = Stream.of(1,2,3,4,5,6).filter(e -> e%2==0).collect(Collectors.toList());
		System.out.println(list2);
		//count
		long v = Stream.of(1,2,3,4,5,6).count();
		System.out.println(v);
		//min
		String min = list.stream().min((o1,o2) -> o1.length()-o2.length()).get();
		System.out.println(min);
		//max
		String max = list.stream().max((o1,o2) -> o1.length()-o2.length()).get();
		System.out.println(max);
		//allMatch
		boolean allMatch = Stream.of(1,2,3,4,5,6).allMatch(e -> e%2==0);
		System.out.println(allMatch);
		//anyMatch
		boolean anyMatch = Stream.of(1,2,3,4,5,6).anyMatch(e -> e%2==0);
		System.out.println(anyMatch);
		//noneMatch
		boolean noneMatch = Stream.of(1,2,3,4,5,6).noneMatch(e -> e%2==0);
		System.out.println(noneMatch);
		//findFirst
		Integer fInteger = Stream.of(1,2,3,4,5,6).findFirst().get();
		System.out.println(fInteger);
		//limit
		Stream.of(1,2,3,4,5,6).limit(3).forEach(System.out::print);
	}
}

结果如下:

jdk8新特性_第2张图片

6.新的日期时间API

LocalDateTime年月日十分秒

LocalDate日期

LocalTime时间

举例:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class LocalDateTimeDemo {

	public static void main(String[] args) {
		//获取系统时间
		LocalDateTime localDataTime = LocalDateTime.now();
		System.out.println(localDataTime);
		//转换
		String time = localDataTime.format(DateTimeFormatter.ofPattern("yy-MM-dd HH-mm-ss"));
		System.out.println(time);
		//Date转换
		Date date = Date.from(localDataTime.atZone(ZoneId.systemDefault()).toInstant());
		System.out.println(date);
		LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
		System.out.println(localDataTime);
		
		System.out.println(localDataTime.getYear());
		System.out.println(localDataTime.plusYears(1).getYear());
		System.out.println(localDataTime.minusYears(1).getYear());

	}
}

具体结果如下:

jdk8新特性_第3张图片


你可能感兴趣的:(java)