一、Lambda

1、定义/设计原因

官方解释:允许把函数作为一个方法的参数。使代码变的更加简洁紧凑。表达式免去了使用匿名方法的麻烦。

个人解释:用来创建匿名方法

2、结构

Lambda表达式可由逗号分隔的参数列表、->符号和语句块组成

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

3、规则

表达式用到的局部变量不管是不是final,都会被变成final,后面代码不可以改它了。全局变量则不受限。

4、使用


public class Java8Tester {
@FunctionalInterface
interface MathOperation {
int operation(int a, int b); } @FunctionalInterface
interface GreetingService {
void sayMessage(String message);
} public static void main(String args[]){
//老版本写法
MathOperation oldAdd = new MathOperation() {
@Override
public int operation(int a, int b) {
return a+b;
}
}; // jdk8类型声明
MathOperation addition = (int a, int b) -> a + b; // 不用类型声明
MathOperation subtraction = (a, b) -> a - b; // 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; }; // 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b; // 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message); // 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message); greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
} }

二、函数式接口

1、定义

官方解释:函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式和方法引用。

@FunctionalInterface,用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。

2、设计原因

lambda语法只能用函数式接口,为方便检查函数式接口,给了这个@FunctionalInterface注解

3、使用

@FunctionalInterfaceinterface
GreetingService {
void sayMessage(String message);
}
//使用Lambda表达式来表示该接口的一个实现
GreetingService greetService1 = message -> System.out.println("Hello " + message);

三、方法引用

1、定义/设计原因

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

个人解释:方法引用是一种更简洁易懂的Lambda表达式。直接访问类或者实例的方法或者构造方法。

2、使用

先创建个接口和类

 //函数式接口
@FunctionalInterface
public interface Supplier<T> {
T get();
} class Car { public static Car create(final Supplier<Car> supplier) {
return supplier.get();
} public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
} public void repair() {
System.out.println("Repaired " + this.toString());
}
}

开始使用方法引用:

   @Test
public void MethodReferenceTest() {
// 1、旧方法写法
// final Car oldCar = Car.create(new Supplier<Car>() {
// @Override
// public Car get() {
// return new Car();
// }
// });
// 2、jdk8的lambda
// final Car oldCar1 = Car.create(() -> new Car()); //3、jdk8写法
//构造器引用 Class::new
final Car newCar = Car.create(Car::new); //该方法返回的 List 与传入数组是映射关系(视图):set/get 操作直接作用于数组;直接修改数组,list 也会改变
final List<Car> cars = Arrays.asList(newCar);
/*-----------------------------分割线---------------------------------------*/ // 1、旧方法写法
// for (Car car : cars) {
// Car.collide(car);
// }
// 2、jdk8的forEach
// cars.forEach(new Consumer<Car>() {
// @Override
// public void accept(Car car) {
// Car.collide(car);
// }
// });
// 3、jdk8的lambda
// cars.forEach(car -> Car.collide(car)); //4、jdk8方法引用写法
//类名的方法引用 Class::static_method 或者 Class::method
cars.forEach(Car::collide);
/*-----------------------------分割线----------------------------------------*/ final Car police = Car.create(Car::new); // 1、jdk8的lambda
// cars.forEach(car -> police.follow(car)); //2、jdk8方法引用写法
//特定对象的方法引用 instance::method
cars.forEach(police::follow);
}
/*-----------------------------分割线---------------------------------------*/ String[] stringsArray= {"4","5"};
// 1、旧方法写法
// Arrays.sort(stringsArray, new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.compareToIgnoreCase(s2);
// }
// });
// 2、jdk8的lambda
// Arrays.sort(stringsArray,(s1,s2)->s1.compareToIgnoreCase(s2)); //3、jdk8的方法引用
Arrays.sort(stringsArray, String::compareToIgnoreCase);

四、接口的默认方法

1、定义

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

2、设计原因

问:为什么要有这个特性?

答:首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

3、使用

(1)接口的默认方法

最基本使用,接口通过default定义默认方法,实现类无需实现该方法

interface Vehicle {
default void print() {
System.out.println("我是一辆车!");
}
} class Car implements Vehicle{ }

如果一个类实现了多个接口,且这些接口有相同的默认方法,则可以通过

重写接口的默认方法,或者使用 super 来调用指定接口的默认方法

public interface Vehicle {
default void print(){
System.out.println("我是一辆车!");
}
}
public interface FourWheeler {
default void print(){
System.out.println("我是一辆四轮车!");
}
}
//创建自己的默认方法,来覆盖重写接口的默认方法
public class Car implements Vehicle, FourWheeler {
default void print(){
System.out.println("我是一辆四轮汽车!");
}
}
//使用 super 来调用指定接口的默认方法
public class Car implements Vehicle, FourWheeler {
public void print(){
Vehicle.super.print();
}
}

(2)接口的静态默认方法

不实例化接口的时候也可以用,个人感觉失去了接口的本质,但是妥协旧代码是这样的啦

public interface Animal {
static void putUpHands(){
System.out.println("举手");
}
} class Cat {
void catPutUpHands(){
Animal.putUpHands();
}
}

五、Stream

1、定义

官方解释:让你以一种声明的方式处理数据。将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

个人解释:把数组通过.stream()或者.parallelStream()转换成流,然后通过filter、map、distinct、sorted、limit等方法进行中间处理,最后通过collect、forEach、count得出最终结果。

2、设计原因

简化数组处理

2、使用

public static void main(String[] args) {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5, 1, 9, 10, 4, 1);
/*=======================返回Stream<T>==========================*/
//1、filter过滤
strings.stream().filter(string -> !string.isEmpty());
//2、map映射每个元素到对应的结果
numbers.stream().map(i -> i * i);
//3、distinct去重
numbers.stream().distinct();
//4、sorted排序
numbers.stream().sorted();
//4、limit限制数量
numbers.stream().limit(5);
//5、并行处理,主要适用于大数据量的数组
strings.parallelStream(); /*=======================对流进行转换或处理的==========================*/
//1、collect转换成列表或字符串,Collectors 可将流转换成集合和聚合元素
List<String> collect = strings.stream().collect(Collectors.toList());
String collectStr = strings.stream().collect(Collectors.joining(", "));
//2、forEach迭代流中的每个数据
strings.stream().forEach(System.out::println);
//3、count统计数量
long count = strings.stream().count(); /*=======================拓展IntStream,LongStream,DoubleStream==========================*/ //1.1、mapToInt将Stream转换成IntStream, summaryStatistics是对IntStream数据进行汇总统计的方法,(LongStream,DoubleStream同理)
IntSummaryStatistics summary = numbers.stream().mapToInt(x ->x).summaryStatistics();
System.out.println(summary.getAverage());
System.out.println(summary.getCount());
System.out.println(summary.getMax());
System.out.println(summary.getMin());
System.out.println(summary.getSum()); //1.2、IntStream,LongStream创建区间方式是一样的
int[] range1 = IntStream.rangeClosed(13, 15).toArray();//生产区间 [a,b] range1=[13,14,15]
int[] range2 = IntStream.range(13, 15).toArray();//生产区间 [a,b) range2=[13,14]
double[] doubles = DoubleStream.of(5.33, 2.34, 5.32, 2.31, 3.51).toArray(); //doubles=[5.33, 2.34, 5.32, 2.31, 3.51] //1.2、IntStream的统计方法(LongStream,DoubleStream同理)
double average = IntStream.range(13, 15).average().getAsDouble();//average=13.5
int max = IntStream.range(13, 15).max().getAsInt(); //max=14
int min = IntStream.range(13, 15).min().getAsInt(); //min=13
int sum = IntStream.range(13, 15).sum(); //sum=27
}

六、Optional 类

1、定义

官方解释:Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。

个人解释:换言之就是把变量转成Optional对象,其中null都转成Optional.empty()(就是一个空的Optional对象),然后就可以对Optional对象进行操作。好处就是发现null可选择抛出异常。

2、设计原因

不用显式进行空值检测。解决空指针异常。避免null。

3、使用

public class OptionalTest {
public static void main(String args[]){
handleParam(null,1);//后面两个参数自己随意写 }
//处理参数举例子
static void handleParam(String a,Integer b){
//对于处理string参数
Optional<String> aOpt = Optional.ofNullable(a); //允许参数空。如果非空返回一个包含引用Optional实例,否则返回Optional.empty()。
System.out.println(aOpt.isPresent());//输出aOpt是否为空
a=aOpt.orElse("defaultValue");//如果为空,就给一个默认值defaultValue
System.out.println(a); //同理对于处理int参数
Optional<Integer> bOpt = Optional.of(b);//不允许参数空,不然会抛出异常
b=bOpt.get();//get的时候不允许变量为空
System.out.println(b);
}
}

六、日期时间类

1、定义

加强对日期与时间的处理。

2、设计原因

在旧版的 Java 中,日期时间 API 存在诸多问题

  • (1)非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • (2)设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。

    java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • (3)时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

3、使用

 public static void testTime() {

        // 当前详细时间
LocalDateTime currentTime = LocalDateTime.now(); //currentTime = 2019-05-30T15:05:46.408
// 当前年月日
LocalDate date1 = currentTime.toLocalDate(); //date1 = 2019-05-30 //获取详细时间的月日秒
Month month = currentTime.getMonth();//month=MAY
int day = currentTime.getDayOfMonth();//day=30
int seconds = currentTime.getSecond();//seconds=46 //替换详细时间的年月
LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);//date2 = 2012-05-10T15:05:46.408 //自定义年月日
LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);//date3= 2014-12-12 //自定义时分
LocalTime date4 = LocalTime.of(22, 15); //date4 = 22:15 //解析字符串
LocalTime date5 = LocalTime.parse("20:15:30"); //date5 = 20:15:30
LocalDateTime date6 = LocalDateTime.parse("2019-05-30T15:05:46.408");//date6 = 2019-05-30T15:05:46.408 // 获取当前时间日期
ZonedDateTime date7 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");//date6=2015-12-03T10:15:30+08:00[Asia/Shanghai]
// 获取时区ID
ZoneId id = ZoneId.of("Europe/Paris");//id= Europe/Paris
//获取默认时区
ZoneId defaultZone = ZoneId.systemDefault();//defaultZone=sia/Shanghai
}

七、Base64

1、定义

官方解释:Base64工具类提供了一套静态方法获取下面三种BASE64编码器和解码器:

  • 基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
  • URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件。
  • MIME:输出隐射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割。

2、使用

public static void main(String args[]) {
try { // 使用基本编码
String base64encodedString = Base64.getEncoder().encodeToString("我是测试字符串".getBytes("utf-8"));//base64encodedString = "5oiR5piv5rWL6K+V5a2X56ym5Liy" // 解码
byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
String base64decodedStr= new String(base64decodedBytes, "utf-8");//base64decodedStr = "我是测试字符串" //使用URL编码
String urlEncodedString = Base64.getUrlEncoder().encodeToString("testUrl?java8".getBytes("utf-8"));//urlEncodedString = "VHV0b3JpYWxzUG9pbnQ_amF2YTg=" //使用MIME编码
String mimeEncodedString = Base64.getMimeEncoder().encodeToString(("QWERTYUIOP-ASDFGHJKL-ZXCVBNM").getBytes("utf-8"));//mimeEncodedString = "UVdFUlRZVUlPUC1BU0RGR0hKS0wtWlhDVkJOTQ==" }catch(UnsupportedEncodingException e){
System.out.println("Error :" + e.getMessage());
}
}

浓缩版java8新特性的更多相关文章

  1. java8新特性全面解析

    在Java Code Geeks上有大量的关于Java 8 的教程了,像玩转Java 8--lambda与并发,Java 8 Date Time API 教程: LocalDateTime和在Java ...

  2. Java8 新特性之Stream----java.util.stream

    这个包主要提供元素的streams函数操作,比如对collections的map,reduce. 例如: int sum = widgets.stream() .filter(b -> b.ge ...

  3. 干货 | Java8 新特性教程

    本教程翻译整理自 https://github.com/winterbe/java8-tutorial 本教程首发自个人网站: https://www.exception.site/java8/jav ...

  4. 乐字节-Java8新特性之Date API

    上一篇文章,小乐给大家带来了Java8新特性之Optional,接下来本文将会给大家介绍Java8新特性之Date API 前言: Java 8通过发布新的Date-Time API来进一步加强对日期 ...

  5. 乐字节-Java8新特性-接口默认方法

    总概 JAVA8 已经发布很久,而且毫无疑问,java8是自java5(2004年发布)之后的最重要的版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性. Java8 新特性列表如下: 接 ...

  6. Java8新特性

    Java8新特性 Java8主要的新特性涵盖:函数式接口.Lambda 表达式.集合的流式操作.注解的更新.安全性的增强.IO\NIO 的改进.完善的全球化功能等. 1.函数式接口 Java 8 引入 ...

  7. Java系列 - 用Java8新特性进行Java开发太爽了

    本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome/ 前言 从开始写博客到现在已经过去3个 ...

  8. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

  9. Java8新特性之二:方法引用

    上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...

随机推荐

  1. Django之创建项目、目录层级、基本操作

    创建项目 在合适的位置创建一个目录 打开cmd窗口,进入到创建的目录内 输入django-admin startproject project 目录层级 manage.py 是一个命令行工具,可以使我 ...

  2. CF306C White, Black and White Again

    CF306C White, Black and White Again 洛谷评测传送门 题目描述 Polycarpus is sure that his life fits the descripti ...

  3. c++基础第一篇

    前言:我是从c和c++对比的角度来讲解c++的基础知识. (1)c++格式如下: #include <iostream> //标准输入输出头文件 using namespace std; ...

  4. js实现一键复制

    方法一: 使用插件 引入clipboard.js 使用如下 <script> copyFn = function() { var clipboard = new Clipboard('.c ...

  5. Elasticsearch由浅入深(八)搜索引擎:mapping、精确匹配与全文搜索、分词器、mapping总结

    下面先简单描述一下mapping是什么? 自动或手动为index中的type建立的一种数据结构和相关配置,简称为mappingdynamic mapping,自动为我们建立index,创建type,以 ...

  6. Consul 使用手册(感觉比较全了)

    HTTP API consul的主要接口是RESTful HTTP API,该API可以用来增删查改nodes.services.checks.configguration.所有的endpoints主 ...

  7. Nacos集成Spring Cloud Gateway 基础使用

    项目结构 项目 端口 描述 nacos-provider 8000 服务 nacos-getway 8001 网关 nacos-provider项目依赖 <dependencies> &l ...

  8. 3 datax mysql和hive之间相互导入

                                                mysql-->hive     0 参考文档: https://github.com/alibaba/D ...

  9. (十)golang--运算符

    1.算术运算符 + -  * / % ++ -- 使用细节:(1)对于"/"号,整数除和小数除的区别: (2)++和--只能独立使用,即a=a++是不允许的:没有++a和--a:i ...

  10. ECMAScript 初探 - 对象篇

    一.对象 如果你用过 C++ 或 Java,肯定熟悉类(class).在 ECMAScript 中并没有 "类" 这个词, 其对应的是 "对象定义",不过这太拗 ...