(1)速度更快
比如HashMap的重构
(2)代码更少
新增Lambda表达式
(3)强大的StreamAPI
(4)便于并行
(5)减少空指针:Optional
(6)Nashorn引擎,允许JVM执行JS应用
(1)Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段传递的代码,
(2)Lambda表达式的使用
①举例:(o1,o2)-> Integer.compare(o1,o2);
②格式:
-> :Lambda操作符或箭头操作符
->左边:Lambda形参列表 (其实就是接口中的抽象方法的形参列表)
->右边:Lambda体,(其实就是重写抽象方法的方法体)
(3)使用(分3种情况)
package com.test.course.jdk8test;
import org.junit.Test;
import java.net.InetAddress;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* 〈Lanbda〉
* @author PitterWang
* @create 2020/5/17
* @since 1.0.0
*/
public class LambdaTest {
/**
* 语法1:无参,无返回值
*/
@Test
public void test(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Runnable Run 方法");
}
};
r1.run();
System.out.println("***********************");
Runnable r2 = () -> System.out.println("Runnable Lambda Run 方法");
r2.run();
}
/**
* 语法2:一个参数,无返回值
*/
@Test
public void test1(){
Consumer consumer = new Consumer() {
@Override
public void accept(Object o) {
System.out.println("Consumer Run"+ o);
}
};
consumer.accept("Java8之前");
/**
* 不省略数据类型
*/
Consumer consumer1 = (Object s) -> System.out.println("Consumer Run" + s);
consumer1.accept("Java8之后");
/**
* 省略数据类型,省略(),省略{}
*/
Consumer consumer2 = s -> System.out.println("Consumer Run" + s);
consumer1.accept("Java8之后");
}
/**
* 语法3:多个参数,有返回值
*/
@Test
public void test3(){
Comparator comparator = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(comparator.compare(12, 31));
System.out.println("**********************************");
Comparator comparator1 = (o1, o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(comparator1.compare(31, 12));
}
}
总结:①->左边:Lambda形参列表的参数类型可以省略(类型推断):如果lambda形参列表只有一 个参数,()也可以省略
②->右s边:Lambda体应该使用一对{}包裹,如果只有一条执行语句(可能是return),也可 以省略{}和return关键字
(4)Lambda表达式的本质:作为函数式接口的实例
(1)只含有一个抽象方法的接口,称为函数式接口
(2)我们可以使用@FunctionalInterface注解,来检查是否是一个函数式接口
(3)在java.util.functional包下定义了Java8的丰富的函数式接口
(4)以前匿名实现类表示的现在都可以用Lambda表达式来写
(5)Java内置的四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer消费型接口 | T | void | 对类型为T的对象引用操作,包含方法void accept(T t) |
Supplier供给型接口 | 无 | T | 返回类型为T的对象,包含方法,T get() |
Function |
T | R | 对类型为T的对象应用操作,并返回结构,及金额跟式R类型的对象,包含方法R apply(T t) |
Predicate 断定型接口 | T | boolean | 确定类型T的对象是否满足某约束,并返回boolean值,包含方法boolean test(T t) |
(6)自定义函数式接口
package com.test.course.jdk8test;
@FunctionalInterface
public interface MyInterFace {
void test();
}
@Test
public void test4() {
MyInterFace myInterFace = () -> System.out.println("NDY");
myInterFace.test();
}
(1)方法引用
①但传递给Lambda体的操作,已经有实现的方法时,可以使用方法引用
②实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致
③格式: 使用操作符“ ::” 将类或对象与方法名隔开
④如下三种使用情况
对象::实例方法名
类::静态方法名
类::实例方法名
⑤方法引用使用要求,要求接口中的抽象方法的形参列表和返回值类型和方法引用的方法的形参列表和返回值类型相同
package com.test.course.jdk8test;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 〈MethodRefTest〉
*
* @author PitterWang
* @create 2020/5/17
* @since 1.0.0
*/
public class MethodRefTest {
/***
* 情况1: 对象::实例对象
* consumer.accept(T t);
* PrintStream println
*/
@Test
public void test1() {
Consumer<String> consumer = str -> System.out.println(str);
consumer.accept("Consumer Systemout");
System.out.println("**************************");
Consumer<String> consumer1 = System.out :: println;
consumer1.accept("Consumer MethodRefTest");
}
/***
* 情况2: 类::静态方法名
* Comparator compare(T t1,T t2);
* Integer 中int compare
*/
@Test
public void test2() {
Comparator<Integer> comparator = (t1,t2)->Integer.compare(t1,t2);
System.out.println(comparator.compare(12, 13));
System.out.println("*********************");
Comparator<Integer> comparator1 = Integer::compare;
System.out.println(comparator1.compare(14, 12));
}
/***
* 情况2: 类::静态方法名
* Function R apply(T t);
* Math round(double a)
*/
@Test
public void test3() {
Function<Double,Long> function = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
System.out.println(function.apply(12.8));
System.out.println("***************************************");
Function<Double,Long> function1 = d -> Math.round(d);
System.out.println(function1.apply(12.8));
System.out.println("***************************************");
Function<Double,Long> function2 = Math::round;
System.out.println(function2.apply(12.8));
}
/***
* 情况3: 类::实例方法
*/
@Test
public void test4() {
Comparator<String> comparator = (t1,t2)->t1.compareTo(t2);
System.out.println(comparator.compare("abc","df"));
System.out.println("*********************");
Comparator<String> comparator1 = String::compareTo;
System.out.println(comparator.compare("abc","df"));
}
}
(2)构造器引用
和方法引用差不多,函数式接口的抽象方法的形参列表和构造器的形参列表一致。
package com.test.course.jdk8test;
import org.junit.Test;
import java.util.function.Supplier;
/**
* 〈ConstructorRefTest〉
*
* @author PitterWang
* @create 2020/5/17
* @since 1.0.0
*/
public class ConstructorRefTest {
@Test
public void test1() {
Supplier<Persion> supplier = new Supplier() {
@Override
public Object get() {
return new Persion();
}
};
supplier.get();
System.out.println("**********************");
Supplier<Persion> supplier1 =()->new Persion();
supplier1.get();
System.out.println("**********************");
Supplier<Persion> supplier2 = Persion::new;
supplier2.get();
}
}
(3)数组引用
@Test
public void test2() {
Function<Integer,String[]> function = lenth ->new String[lenth];
String[] apply = function.apply(4);
System.out.println(Arrays.toString(apply));
System.out.println("**********************");
Function<Integer,String[]> function1 = String[]::new;
String[] apply1 = function.apply(4);
System.out.println(Arrays.toString(apply1));
}
(1)Stream API(java.util.stream)把真正的函数式编程风格引入到Java中。
(2)Stream 是java8中出来集合的关键抽象概念,他可以指定你希望对集合进行的操作,可以执行复杂的查找,过滤,和映射数据等操作。使用Stream API来并行执行操作。
(3)Stream和Collection的区别:Collection是一种静态的内存数据结构,而Stream是有关计算的。前者主要面向内存的,而后者主要面向CPU,通过CPU实现计算
(4)Stream自己不会存储数据。不会改变源对象。相反,他们会返回一个持有结果的新Stream。Stream操作是延迟执行的,
(5)Stream操作的三个步骤
①创建Stream:数据源,获取一个流
创建方式一:通过集合。Java8中的Collection接口被扩展,提供两个获取流的方法。
/**
*返回一个顺序流
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
*返回一个并行流
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
创建方式二:通过数组。Java8中的Arrays的静态方法stream()可以获取数据流
创建方式三:通过Stream的of()方法
创建方式四:创建无限流 Stream.iterate和Stream.generate
②中间操作:中间操作链,对数据源的数据进行处理(过滤,映射等)
1.筛选与切片
方法 | 描述 |
---|---|
filter(Predicate p) | 接受Lambda,从流中排除某些元素 |
distanct() | 筛选,通过流生成的hashcode和equals去除重复数据 |
limit(long maxSize) | 截断流,使其元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉了前n个元素的流,如果不足n个,就返回一个空流,与limit互补 |
2.映射
方法 | 描述 |
---|---|
map(Function f) | 接受一个函数作为参数,该函数会被应用到每个元素上,并减去映射到一个新元素 |
flatMap(Function f) | 接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
3.排序
方法 | 描述 |
---|---|
sorted() | 产生一个新流,按照自然顺序排序 |
sorted(Comparator com) | 产生一个新流,按比较器顺序排序 |
package com.test.course.jdk8test;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* 〈中间操作〉
*
* @author PitterWang
* @create 2020/5/18
* @since 1.0.0
*/
public class StreamAPITest {
@Test
public void test(){
List<Persion> persionData = PersionData.getPersionData();
/***
* 从流中排除某些元素
*/
persionData.parallelStream().filter(e->e.getId() > 3).forEach(System.out:: println);
System.out.println("******************************************");
persionData.stream().distinct().forEach(System.out:: println);
System.out.println("******************************************");
persionData.stream().limit(3).forEach(System.out:: println);
System.out.println("******************************************");
persionData.stream().skip(3).forEach(System.out:: println);
}
@Test
public void test1(){
List<Persion> persionData = PersionData.getPersionData();
persionData.parallelStream().map(persion -> persion.getName().toUpperCase()).forEach(System.out:: println);
}
@Test
public void test2(){
List<Persion> persionData = PersionData.getPersionData();
/**
* Persion重写compareTo方法
*/
persionData.stream().sorted().forEach(System.out:: println);
System.out.println("***********************");
persionData.stream().sorted((s1,s2)->s1.getName().compareTo(s2.getName())).forEach(System.out:: println);
}
}
③终止操作:一旦执行终止操作,就执行中间操作,并产生结果。之后不会再被使用
1.匹配与查找
2.规约
3.收集
package com.test.course.jdk8test;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* 〈〉
*
* @author PitterWang
* @create 2020/5/18
* @since 1.0.0
*/
public class StreamAPI1Test {
@Test
public void test(){
List<Persion> persionData = PersionData.getPersionData();
/**
* 检查匹配所有元素
* 所有的name长度都是1
*/
boolean d = persionData.stream().allMatch(persion -> persion.getName().length() == 1);
System.out.println(d);
/**
* 检查是否至少一个元素
*
* 是否有以d结尾的name
*/
boolean c = persionData.stream().anyMatch(persion -> persion.getName().endsWith("d"));
System.out.println(c);
/**
* 检查是否没有匹配元素
*/
boolean d1 = persionData.stream().noneMatch(persion -> persion.getName().endsWith("d"));
System.out.println(d1);
/**
* 返回第一个元素
*/
Optional<Persion> first = persionData.stream().findFirst();
System.out.println(first);
/**
* 返回任意元素
*/
Optional<Persion> any = persionData.stream().findAny();
System.out.println(any);
/**
* 返回元素的总个数
*/
System.out.println(persionData.stream().count());
/**
* 返回最大
*/
System.out.println(persionData.stream().map(e -> e.getId()).max(Double::compare));
/**
* 返回最小
*/
System.out.println(persionData.stream().map(e -> e.getId()).min(Double::compare));
/**
* 遍历
*/
persionData.stream().forEach(System.out::println);
}
/**
* 规约
*/
@Test
public void test1(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
/**
* 1到7的和
*/
System.out.println(list.stream().reduce(0, Integer::sum));
}
}
(1)是一个容器类,可以保存类型T的值,代表这个值存在,或仅仅保存null,表示这个值不存在。以前用过null保存一个值不存在,现在Optional可以更好的表达,可以避免空指针。
(2)这个是个可以为null的容器对象,如果只存在者isPresent()方法会返回true,调用get()可以返回该对象。
package java.util;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* A container object which may or may not contain a non-null value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
*
* Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(java.lang.Object) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
* of code if the value is present).
*
*
This is a value-based
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code Optional} may have unpredictable results and should be avoided.
*
* @since 1.8
*/
public final class Optional {
/**
* Common instance for {@code empty()}.
*/
private static final Optional> EMPTY = new Optional<>();
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
/**
* Constructs an empty instance.
*
* @implNote Generally only one empty instance, {@link Optional#EMPTY},
* should exist per VM.
*/
private Optional() {
this.value = null;
}
/**
* Returns an empty {@code Optional} instance. No value is present for this
* Optional.
*
* @apiNote Though it may be tempting to do so, avoid testing if an object
* is empty by comparing with {@code ==} against instances returned by
* {@code Option.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param Type of the non-existent value
* @return an empty {@code Optional}
*/
public static Optional empty() {
@SuppressWarnings("unchecked")
Optional t = (Optional) EMPTY;
return t;
}
/**
* Constructs an instance with the value present.
*
* @param value the non-null value to be present
* @throws NullPointerException if value is null
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* 创建Optional实例,value必须非空
*/
public static Optional of(T value) {
return new Optional<>(value);
}
/**
* 创建Optional实例,value可以为空
*/
public static Optional ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* 如果调用对象包含返回值,返回该值,否者抛异常
* @see Optional#isPresent()
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* 判断是否包含对象
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
/**
* 如果有值,执行Consumer接口实现的方法
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer super T> consumer) {
if (value != null)
consumer.accept(value);
}
/**
* If a value is present, and the value matches the given predicate,
* return an {@code Optional} describing the value, otherwise return an
* empty {@code Optional}.
*
* @param predicate a predicate to apply to the value, if present
* @return an {@code Optional} describing the value of this {@code Optional}
* if a value is present and the value matches the given predicate,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the predicate is null
*/
public Optional filter(Predicate super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
/**
* If a value is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status. For example, the
* following code traverses a stream of file names, selects one that has
* not yet been processed, and then opens that file, returning an
* {@code Optional}:
*
* {@code
* Optional fis =
* names.stream().filter(name -> !isProcessedYet(name))
* .findFirst()
* .map(name -> new FileInputStream(name));
* }
*
* Here, {@code findFirst} returns an {@code Optional}, and then
* {@code map} returns an {@code Optional} for the desired
* file if one exists.
*
* @param The type of the result of the mapping function
* @param mapper a mapping function to apply to the value, if present
* @return an {@code Optional} describing the result of applying a mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null
*/
public Optional map(Function super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* If a value is present, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code Optional}.
*
* @param The type parameter to the {@code Optional} returned by
* @param mapper a mapping function to apply to the value, if present
* the mapping function
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null or returns
* a null result
*/
public Optional flatMap(Function super T, Optional> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
/**
* 如果有值则返回,否者返回其他对象
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* 如果有值则返回,否者返回Supplier接口实现提供的对象
*/
public T orElseGet(Supplier extends T> other) {
return value != null ? value : other.get();
}
/**
* 如果有值则返回,否者返回Supplier接口实现提供的异常
*/
public T orElseThrow(Supplier extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this Optional. The
* other object is considered equal if:
*
* - it is also an {@code Optional} and;
*
- both instances have no value present or;
*
- the present values are "equal to" each other via {@code equals()}.
*
*
* @param obj an object to be tested for equality
* @return {code true} if the other object is "equal to" this object
* otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional> other = (Optional>) obj;
return Objects.equals(value, other.value);
}
/**
* Returns the hash code value of the present value, if any, or 0 (zero) if
* no value is present.
*
* @return hash code value of the present value or 0 if no value is present
*/
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* Returns a non-empty string representation of this Optional suitable for
* debugging. The exact presentation format is unspecified and may vary
* between implementations and versions.
*
* @implSpec If a value is present the result must include its string
* representation in the result. Empty and present Optionals must be
* unambiguously differentiable.
*
* @return the string representation of this instance
*/
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}