java8十大特性

Java 8笔记

1、Lambda表达式

1.1什么叫Lambda表达式:

Lambda表达式就是一段带有参数的可执行语句块

1.2Lambda表达式在java语言中引入了一个新的语法元素和操作符;

这个操作符为->,该操作符被称为Lambda或箭头操作符;它将Lambda

Fenwick两个部分:

左侧:指定了Lambda表达式需要的所有参数

右侧:指定了Lambda体,即Lambda所需要执行的功能

1.3Lambda表达式的语法:

1.3.1、语法格式一:无参、无返回值,Lambda只需要一条语句

Runnable r1=() ->System.out.println(“hello word”);

1.3.2、语法格式二:带一个参数

Consumer<String>  fun=(args) ->System.out.println(args);

1.3.3、语法格式三:Lambda只需要一个参数时,参数的小括号可以省略

Consumer<String>  fun=args ->System.out.println(args);

1.3.4、语法格式四:Lambda只需要一个参数时,并且有返回值

BinaryOperator<Long> bo=(x,y) ->{

System.out.println(“实现函数式接口方法”);

return x+y;

};

1.3.5、语法格式五:当Lambda体只有一条语句是,大括号和return可以省略

BinaryOperator<Long> bo=(x,y) ->x+y

1.3.6、语法格式六:

BinaryOperator<Long> bo=(Long x,Long y) ->{

System.out.println(“实现函数式接口方法”);

return x+y;

};

//Lambda体参数类型可以省略,因为可有编译器推断的出来,称为类型推断

简单的举个例子:

*下面代码是老版本的Java中是如何排列字符串的:

List<String>  names=Arrays.asList(“peter”,”anna”,”mike”,”xenia”);

Collections.sort(names,new Comparator<String>);

@Override

Public int compare(String  a,String  b){

Return b.compareTo(a);

}

//只需要给静态方法Collecyions.sort传入一个List对象以及一个比较起来按指 定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort 方法

*java8中就没必要使用这种传统的匿名对象的方式,java8提供了更简洁的 语法,lambda表达式:

Collections sort(names,(a,b) ->b.compare(a))

2、函数式接口

2.1、什么是函数式接口:

2.1.1、只包含一个抽象方法的接口,称为“函数式接口”;

2.1.2、你可以通过Lambda表达式来创建该接口的对象,(若Lambda表达式抛出一 个受检查时异常,那么该异常需要在目标接口的抽象方法上进行声明)

2.1.3、可以在任意函数式上使用@FunctionalInterface注解,该注解可以检查它是否 是一个函数式接口,

2.2java8中常用的全新接口

2.2.1Predicate接口(断言型接口)

          Predicate接口只有一个参数,返回boolean类型,该接口包含多种默认方法   来将Predicate组合成其他复杂的逻辑(比如:与,或,非),包含方法boolean test(T t)

  代码如下:

   Predicate<String> predicate=(s) ->s.length()>0;

  Predicate.test(“foo”);//true

Predicate.negate().test(“foo”);//false

2.2.2Function<T,R>接口(函数型接口):T代表参数,R代表返回值

           Function接口有一个参数并且返回一个结果,并附带了一些可以和其他函 数组合的默认方法(compose,andThen,包含方法 R apply (T t);

   代码如下:

Function<String,Integer> tolnteger=integer::valueOf;

Function<String,String> backToString=tointeger.andThen(String::valueOf);

backToString.apply(“123”);//123

2.2.3Supplier接口(供给型接口):返回一个任意泛型的值,Function不同的是该接 口没有任何参数,包含方法T get();

代码如下:

Supplier<Person> personSupplier=person::new;

personSupplier.get();//new Person

2.2.4Consumer<T>接口(消费型接口):对类型为T的对象应用操作,包含方法void accept(T t);

代码如下:

Consumer<Person> greeter=(p) ->System.out.println(“hello”+p.firstName);

Greeter.accept(new Person(“Luke”,”Skywalker”));

 

3、方法引用和构造引用

3.1、方法引用

*当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

 (实现抽象方法的参数列表,必须与方法引用的参数列表保持一致!)

*方法引用:使用操作符”::” ,将方法名和对象或类的名字分开。

如下三种使用情况:

*对象::实例方法

*类::静态方法

*类::实例方法

1:

(x) ->System.out.println(x);

等同于

System.out::println;

2

Compare((x,y) ->x.equals(y),”abc”,”abc”)

等同于

Compare(String::equals”abc”,”abc”)

3.2、构造函数引用

用函数式接口相结合,自动与函数式接口种方法兼容,可以把构造器引用赋值给定 义的方法,构造器参数列表要与接口中抽象方法的参数列表一致。

例子:

Function<Integer,MyClass> fun=(n) ->new MyClass(n);

等同于

Function<Integer,MyClass> fun=MyClass::new;

3.3、数组引用

格式:Type[]::new

例子:Function<Integer,MyClass> fun=(n) ->new Integer[n];

等同于

Function<Integer,MyClass> fun=Integer::new;

 

4、Stream API

4.1、流(Stream)到底是什么

是数据渠道用于操作数据源(集合,数组等)所生成的元素序列

(集合讲究的是数据,流讲究的是计算)

注意:

  *Stream自己不会存储元素

*Stream不会改变源对象;相反,他们会反回持有结果的新流(Stream)

*Stream操作是延迟执行的,需要结果的时候才会执行

4.2Stream操作的三个步骤

4.2.1、创建Stream

一个数据源(如:集合、数组),获取一个流

4.2.2、中间操作

一个中间操作链,对数据源的数据进行处理

4.2.3、终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果

------>一系列的中间处理操作(map(),filter())------>终止操作

 

4.3Stream怎么用,

*Java8扩展了集合类,可以通过Collection.stream()或者Collection.parallelStream() 创建一个Stream

下面举例子说明:

List<String > stringCollection=new ArrayList<>();

stringCollection.add(“ddd2”);

stringCollection.add(“aaa2”);

stringCollection.add(“bbb1”);

stringCollection.add(“aaa1”);

stringCollection.add(“bbb3”);

stringCollection.add(“ccc”);

stringCollection.add(“bbb2”);

stringCollection.add(“ddd1”);

4.3.1:filter方法过滤:

StringCollection.stream()

  .filete((s) ->s.startsWith(“a”))

  .forEach(System.out::println);//输出结果”aaa2”,”aaa1”

4.3.2sort排序

排序是个中间操作,返回的实拍序号后的stream,如果不指定一个字定义的 Comparator则会使用默认排序;

代码如下:

StringCollection.stream()

  .sorted()

  Filter((s) ->s.startsWith(“a”))

  .forEach(System.out::println);//输出结果”aaa1”,”aaa1”

//排序只创建一个排序好后的stream,而不会影响原来的数据源,排序号之后源数 StringCollection是不会修改的;

4.3.3map映射

中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,

下面的示例展示了将字符串转换成大写字符串,你也可以通过map来将对象转换 成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的

例子:

StringCollection.stream()

 .map(String::toUpperCase)

  .sorted((a,b) ->b,compareTo(a))

  .forEach(System.out::println);

//输出结果:”DDD2”,”DDD1”,”CCC”,”BBB3”,”BBB2”,”AAA2”,”AAA1”

4.3.4Match匹配

Stream提供了多种匹配操作,允许检测制定的Predicate是否匹配整个Stream ,

所有的匹配操作都是最终操作,并且返回一个boolean类型的值

例子:

Boolean anyStartsWithA=

stringCollection.stream()

.anyMatch((s) ->s.startsWith(“a”))

System.out.println(anyStartsWithA);//true

4.3.5count计数

技术是一个最终操作,返回Stream中元素的个数,返回值类型是long

例子:

Long startsWithB=

stringCollection.stream()

 .filter((s)->s.startsWith(“b”))

 .count();

SystemOut.println(startsWithB);//3

4.3.6、规约

这是一个人最终操作,允许通过指定的函数来将stream中的多个元素规约为一个 元素,规约后的结果是通过Optional接口表示的

代码:

Optional<String> reduced=

stringCollection.stream()

.sorted()

.reduce((s1,s2) ->s1+”#”+s2);

Reduced.ifPresent(System.out::println);

//输出结果:“aaa1#aaa2#bbb2#bbb3#ccc#ddd1#ddd2

4.3.7、并行Streams

Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,

而并行Stream则是在多个线程上同时执行

通过并行Stream可以提升性能,可以减少执行时间,他没有空闲的线程核

一个线程执行完了,它会去从别的别的线程核末尾偷一个执行

 

 

 

5、接口中的默认方法与静态方法

5.1、接口的默认方法

Java8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,

这个特征有叫做扩展方法

代码如下:

Interface Formula{

double calculate(int a );

default double sqrt(int a ){

Return Math.sqrt(a);

}

}

在上面Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了 Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以 直接使用。

*接口默认方法”类优先”原则:

若一个接口中定义了一个默认的方法,而另外一个父类或接口中又定义了一个同名 的方法时。

---选择父类的方法,如果一个父类提供了具体的实现,那么接口中具有相同名称和   参数的默认方法会忽略

---接口冲突,如果一个父接口提供一个默认的方法,而另外一个接口也提供了一个   具有相同名称和参数列表的方法(不管方法是不是默认方法),那么必须覆盖该方   法来解决冲突

简单例子:

Interface MyFun(){

Defalut String getName()

 Return “hello”;

}

}

Interface  Named(){

Defalut String getName()

 Return “hello word”;

}

}

Class MyClass  implements MyFun, Named(){

 Public String getName(){

Return Named.super.getName()

}

}

5.2静态方法

接口中允许添加静态方法

例子:

Interface Nmaed(){

Public Integer Myfun();

Defalut String getName(){

 Return “hello”;

]

Static void show(){

System .out.println(“静态方法引用”);

}

}

 

6、新时间日期API

6.1、在java8中,添加了一个新包:java.time,它提供了结构良好的API来处理时间和日 期;

新的API:java.time,5个包组成:

.java.time              --包含值对象的基础包

.java.time.chrono   --提供对不同的日历系统的访问

.java.time.format   --格式化和解析时间日期

.java.time.temporal   --包括底层框架和扩展特性

.java.time.zone   --包含时区支持的类

*以前版本存在的问题

1、可变性:所有的日期类都是可变的,线程不安全

2、偏移性:Data中的年份是从1990开始的,而月份都是从0开始的

3java的日期/时间类的定义并不一致,在Java.UtilJava.sql的包中都有日期类, 此为用于格式化和解析的类在java.text包中定义

4java.util.Date 同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql

          包并不合理,另外这连个类都有相同的名字,本身设计不合理

5、对于时间、时间戳、格式化以及解析,并没有一些明确定义的类。对于格式化 和解析的需求,我们有java.text.DateFormat类被用于此类需求

6、日期类并不提供国际化,没有时区支持,因此java引入了java.util.Calendar java.util.TimeZone类,但他们同样存在上述所有的问题

*LocalDate类方法例子如下:

LocalDate date=LocalDate .of(2014,Month.JUNE,10);

Int year=date.getYear();//2014

Month month=date.getMonth();//6

Int dom=date.getDayOfMonth();//10

DayOfWeek dow=date.getDayOfWeek();//星期二

Int len=date.lengthOfMonth();//30(6月份的天数)

bolean leap=date.isLeapYear();//false(不是闰年)

*LocalTime类的用法跟LacalDate相似:

LocalTime time=LocalTime.of(20,30);

Int hour=date.getHour();//20

Int minute=date.getMinute();//30

Time=time.withSecound(6);//20:30:06

Time=time.plusMinutes(3);//20:33:06

*LocalDateTime类是LocalDateLocalTime的简单组合,它表示一个跟时区无关的日期 和时间;LocalDateTime可以直接创建,或者组合时间和日期:

例子:

LocalDateTime dt1=LocalDateTime.of(2014,Month.JUNE,10,20,30);

LocalDateTime dt2=LocalDateTime .of(date,time);

LocalDateTime dt2=date.atTime(20,30);

LocalDateTime dt4=date.atTime(time);

7、类型注解与重复注解

7.1什么是类型注解

7.1.1Java8ElementType枚举增加了TYPE_PARAMETERTYPE_USE两个枚举值,从而可以使 @Target(ElementType_TYPE_USE)修饰注解定义,这种注解称为类型注解,可以用在任何使 用到类型的地方;

  * ElementType.TYPE_PARAMETE表示注解能写在类型变量的的声明语句中(

   class  MyClass{...}).

      *ElementType.TYPE_USE表示注解注解能写在使用类型的任何语句中(例如声明语

           句、泛型和强制转换语句中的类型)

7.1.2、在Java8之前,注解只能在声明的地方使用,比如类、方法、属性;

java8里面,注解可以应用在任何地方;

        简单的举几个例子:

*创建类实例

New @interned MyObject();

*类型映射

myString=(@NonNull String) str;

@Encrypted String data;

* 泛型

List<@NonNull String> strings;//防止非空,java8里面还没有内置这个注解,    编译时会报错要配合框架使用(checker      framework)

MyGRAph=(@Immutable Graph)  tmpGraph ;

7.2什么是可重复注解

*允许在同一申明类型(类、属性、方法)的多次使用同一个注解

例子:

*Java8之前也有重复注解的解决方案,但可读性不是很好,

Java8里面的做法:

@Repeatable(MyAnnotations.class)

Public @interface MyAnnotation{

String role();

}

Public @interface MyAnnotations{

MyAnnotation[] role();

}

Public class Repeat{

@MyAnnotation(role=”Admin”)

@MyAnnotation(role=”Admin”)

public void TestAnnotations(){

}

}

*Java8不同地方的是,创建重复注解MyAnnotation时,加上@Repeatable,指向存储

注解MyAnnotations(给注解创建一个容器),在使用时候,直接可以重复使用 MyAnnotation

注解

8、Optional

8.1*OPtional(java.util.Optional)是一个容器类,可以为null的容器对象,如果值存在则   isPresent()方法会返回true,调用get()方法会返回该对象

*OPtional类的引入很好的解决了空指针异常

8.2of方法

可以用of方法通过工厂方法创建Optionnal类,创建对象时传入的参数不能为null,

如果传入参数为null,则抛出NullPointerException

简单例子:

//调用工厂方法创建Optional实例

Optional<String> name=Optional.of(“aaaa”);

//传入参数为null,抛出NullPointerException

Optional<String> someNull=Optional.pf(null);

8.3ofNullable方法

为指定的值创建一个Optionnal,如果指定的值为null,则返回一个空 的 Optional;

ofNullof方法相似,唯一的区别是可以接受参数为null的情况

示例如下:

//下面创建一个不包含任何值的Optional实例

//例如值为‘null

Optional  empty=Optional.ofNull(null);

8.4isPresent方法

如果值存在返回true,否则返回false

例子:

//isPresent方法用来检查Optional实例中是否包含值

If(name.isPresent()){

//Optional实例类调用get()返回存在的值

System.out.println(name.get());

}

8.5get方法

如果Optional有值则将其返回,否则抛出NosuchElementException.

8.6orElse方法

如果有值则将其返回,否则返回指定的其他值

8.7orElesGet方法

orElesGetorElse方法类似,区别在于得到的默认值。

orElse方法见传入的字符串作为默认值,orElesGet方法可以接受Supplier接口的实 现来生成默认值

8.8orElseThrow方法

如果有值则将其返回,否则抛出Supplier接口创建的异常

8.9map方法

如果有值,则对其执行调用mapping函数得到返回值,如果返回值不为null,则创 建包含mapping返回值的Optional作为map方法的返回值,否则返回空Optional.

代码如下:

//map方法执行传入的lambda表达式参数对Optional实力的值进行修改

//lambada表达式的返回值创建新的Optional实例作为map方法的返回值

Optional<String> upperName=name.map((value) ->value.toUpperCase());

System.out.println(upperName.orElse(“No value found”));

8.10flatMap方法

    如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional;

flatMapmap(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是 Optional,调用结束时,flatMap不会对结果用Optional封装

8.11filter方法

通过传入限定条件对Optional实例的值进行过滤

简单的举个例子:

//filter方法检查给定的Option值是否满足某些条件

//如果满足则返回同一个Optional实例,否则返回空Optional

Optional<String> longName=name.filter((value) ->value.length()>6);

System.out.println(longName.orElse(“The name less than 6characters”))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值