允许把函数作为一个方法的参数(函数作为参数传递到方法中)
有参数有返回值
interface LambdaDemo {
int operation(int a, int b);
}
@Test
void test() {
LambdaDemo demo1 = (a, b) -> a - b;
int operation1 = demo1.operation(2, 1);
System.out.println(operation1);
LambdaDemo demo2 = (a, b) -> a + b;
int operation2 = demo2.operation(2, 1);
System.out.println(operation2);
}
有参数无返回值
interface LambdaDemo {
void operation(int a, int b);
}
@Test
void test() {
LambdaDemo demo = (a, b) -> System.out.println(a + b);
demo.operation(2, 1);
}
可以直接引用已有Java类或对象(实例)的方法或构造器。
方法参考描述使用“::”符号
@FunctionalInterface,主要用于检查不符合函数式接口定义
@FunctionalInterface
public interface Supplier<T> {
T get();
}
public class Consumer {
public static Consumer create(final Supplier<Consumer> supplier) {
Consumer consumer = supplier.get();
System.out.println("createConsumer " + consumer);
return consumer;
}
public static void buyFood(final Consumer con) {
System.out.println("buyFood " + con.toString());
}
public void buyDrink() {
System.out.println("buyDrink " + this.toString());
}
}
引用
@Test
void test() {
// 构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
Consumer consumer = Consumer.create(Consumer::new);
List<Consumer> list = Arrays.asList(consumer);
//静态方法引用:它的语法是Class::static_method,实例如下:
list.forEach(Consumer::buyFood);
//特定类的任意对象的方法引用:它的语法是Class::method实例如下:
list.forEach(Consumer::buyDrink);
}
函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
新增加的函数接口:java.util.function
接口 | 描述 |
---|---|
BiConsumer<T,U> | 代表了一个接受两个输入参数的操作,并且不返回任何结果 |
BiFunction<T,U,R> | 代表了一个接受两个输入参数的方法,并且返回一个结果 |
BinaryOperator<T> | 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
BiPredicate<T,U> | 代表了一个两个参数的boolean值方法 |
BooleanSupplier | 代表了boolean值结果的提供方 |
Consumer<T> | 代表了接受一个输入参数并且无返回的操作 |
DoubleBinaryOperator | 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
DoubleConsumer | 代表一个接受double值参数的操作,并且不返回结果。 |
DoubleFunction<R> | 代表接受一个double值参数的方法,并且返回结果 |
DoublePredicate | 代表一个拥有double值参数的boolean值方法 |
DoubleSupplier | 代表一个double值结构的提供方 |
DoubleToIntFunction | 接受一个double类型输入,返回一个int类型结果。 |
DoubleToLongFunction | 接受一个double类型输入,返回一个long类型结果 |
DoubleUnaryOperator | 接受一个参数同为类型double,返回值类型也为double 。 |
Function<T,R> | 接受一个输入参数,返回一个结果。 |
IntBinaryOperator | 接受两个参数同为类型int,返回值类型也为int 。 |
IntConsumer | 接受一个int类型的输入参数,无返回值 。 |
IntFunction<R> | 接受一个int类型输入参数,返回一个结果 。 |
IntPredicate | 接受一个int输入参数,返回一个布尔值的结果。 |
IntSupplier | 无参数,返回一个int类型结果。 |
IntToDoubleFunction | 接受一个int类型输入,返回一个double类型结果 。 |
IntToLongFunction | 接受一个int类型输入,返回一个long类型结果。 |
IntUnaryOperator | 接受一个参数同为类型int,返回值类型也为int 。 |
LongBinaryOperator | 接受两个参数同为类型long,返回值类型也为long。 |
LongConsumer | 接受一个long类型的输入参数,无返回值。 |
LongFunction<R> | 接受一个long类型输入参数,返回一个结果。 |
LongPredicate | R接受一个long输入参数,返回一个布尔值类型结果。 |
LongSupplier | 无参数,返回一个结果long类型的值。 |
LongToDoubleFunction | 接受一个long类型输入,返回一个double类型结果。 |
LongToIntFunction | 接受一个long类型输入,返回一个int类型结果。 |
LongUnaryOperator | 接受一个参数同为类型long,返回值类型也为long。 |
ObjDoubleConsumer<T> | 接受一个object类型和一个double类型的输入参数,无返回值。 |
ObjIntConsumer<T> | 接受一个object类型和一个int类型的输入参数,无返回值。 |
ObjLongConsumer<T> | 接受一个object类型和一个long类型的输入参数,无返回值。 |
Predicate<T> | 接受一个输入参数,返回一个布尔值结果。 |
Supplier<T> | 无参数,返回一个结果。 |
ToDoubleBiFunction<T,U> | 接受两个输入参数,返回一个double类型结果 |
ToDoubleFunction<T> | 接受一个输入参数,返回一个double类型结果 |
ToIntBiFunction<T,U> | 接受两个输入参数,返回一个int类型结果。 |
ToIntFunction<T> | 接受一个输入参数,返回一个int类型结果。 |
ToLongBiFunction<T,U> | 接受两个输入参数,返回一个long类型结果。 |
ToLongFunction<T> | 接受一个输入参数,返回一个long类型结果。 |
UnaryOperator<T> | 接受一个参数为类型T,返回值类型也为T |
Predicate示例
@Test
void test() {
demo1(10, n -> n % 2 == 0);
Predicate<Integer> predicate = n -> n > 10;
boolean demo2 = predicate.test(2);
System.out.println(demo2);
}
public static void demo1(Integer n, Predicate<Integer> predicate) {
if (predicate.test(n)) {
System.out.println(n + " ");
}
}
默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
用 default 关键字
例如Predicate中的默认方法,and、negate、or
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
声明的方式处理数据。
forEach: 遍历
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
list.forEach(System.out::println);
map: 映射每个元素对应的结果
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
List<Integer> newList = list.stream().map(i -> i + i).collect(Collectors.toList());
filter: 过滤,只要不等于7的
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
List<Integer> newList = list.stream().filter(item -> item != 7).collect(Collectors.toList());
limit: 限制大小
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
List<Integer> newList = list.stream().limit(2).collect(Collectors.toList());
sorted: 排序
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
List<Integer> newList = list.stream().sorted().collect(Collectors.toList());
统计
List<Integer> list = Arrays.asList(7, 2, 3, 7, 7, 4, 4, 3, 5);
IntSummaryStatistics statistics = list.stream().mapToInt(item -> item).summaryStatistics();
System.out.println(statistics.getMax());
System.out.println(statistics.getMin());
用来解决空指针异常。
方法 | 描述 |
---|---|
static <T> Optional<T> empty() | 返回空的 Optional 实例。 |
boolean equals(Object obj) | 判断其他对象是否等于 Optional。 |
Optional<T> filter(Predicate<? super <T> predicate) | 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 |
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper) | 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
T get() | 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
int hashCode() | 返回存在值的哈希码,如果值不存在 返回 0。 |
void ifPresent(Consumer<? super T> consumer) | 如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
boolean isPresent() | 如果值存在则方法会返回true,否则返回 false。 |
<U>Optional<U> map(Function<? super T,? extends U> mapper) | 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
static <T> Optional<T> of(T value) | 返回一个指定非null值的Optional。 |
static <T> Optional<T> ofNullable(T value) | 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 |
T orElse(T other) | 如果存在该值,返回值, 否则返回 other。 |
T orElseGet(Supplier<? extends T> other) | 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 |
String toString() | 返回一个Optional的非空字符串,用来调试 |
嵌入式 JavaScript 引擎
使用 ScriptEngineManager, JavaScript 代码可以在 Java 中执行
@Test
void test() {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
String name = "hello word!";
try {
nashorn.eval("print('" + name + "')");
} catch (ScriptException e) {
System.out.println("执行脚本错误: " + e.getMessage());
}
}
java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作
本地时间
//获得本地年月日时分秒
LocalDateTime currentTime = LocalDateTime.now();
//获得时间的年月日
LocalDate date = currentTime.toLocalDate();
时区
@Test
void test() {
//根据巴黎时区获取当前时间
ZoneId parisZone = ZoneId.of("Europe/Paris");
System.out.println("ZoneId: " + parisZone);
System.out.println(LocalDateTime.now(parisZone));
//根据本地时区获取当前时间
ZoneId currentZone = ZoneId.systemDefault();
System.out.println("CurrentZone: " + currentZone);
System.out.println(LocalDateTime.now(currentZone));
}
时间枚举ChronoUnit
//Get the current date
LocalDate today = LocalDate.now();
System.out.println("Current date: " + today);
//add 1 week to the current date
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("Next week: " + nextWeek);
//add 1 month to the current date
LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
System.out.println("Next month: " + nextMonth);
//add 1 year to the current date
LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("Next year: " + nextYear);
//add 10 years to the current date
LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
System.out.println("Date after ten year: " + nextDecade);
日期数学计算 TemporalAdjuster
LocalDate localDate = LocalDate.now();
System.out.println("Current date: " + localDate);
//获得下个星期二的日期
LocalDate nextTuesday = localDate.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println("Next Tuesday on : " + nextTuesday);
方法名 | 描述 |
---|---|
static Base64.Decoder getDecoder() | 返回一个 Base64.Decoder ,解码使用基本型 base64 编码方案。 |
static Base64.Encoder getEncoder() | 返回一个 Base64.Encoder ,编码使用基本型 base64 编码方案。 |
static Base64.Decoder getMimeDecoder() | 返回一个 Base64.Decoder ,解码使用 MIME 型 base64 编码方案。 |
static Base64.Encoder getMimeEncoder() | 返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案。 |
static Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) | 返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案,可以通过参数指定每行的长度及行的分隔符。 |
static Base64.Decoder getUrlDecoder() | 返回一个 Base64.Decoder ,解码使用 URL 和文件名安全型 base64 编码方案。 |
static Base64.Encoder getUrlEncoder() | 返回一个 Base64.Encoder ,编码使用 URL 和文件名安全型 base64 编码方案。 |
@Test
void test() {
try {
// 使用基本编码
String base64encodedString = Base64.getEncoder().encodeToString("hello word".getBytes("utf-8"));
System.out.println("Base64 编码字符串 (基本) :" + base64encodedString);
// 解码
byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8"));
base64encodedString = Base64.getUrlEncoder().encodeToString("hello word".getBytes("utf-8"));
System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);
System.out.println("原始字符串: " + new String(Base64.getUrlDecoder().decode(base64encodedString), "utf-8"));
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 10; ++i) {
stringBuilder.append(UUID.randomUUID().toString());
}
byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
System.out.println("原始字符串: " + stringBuilder);
System.out.println("Base64 编码字符串 (MIME) :" + mimeEncodedString);
System.out.println("原始字符串: " + new String(Base64.getMimeDecoder().decode(mimeEncodedString), "utf-8"));
} catch (UnsupportedEncodingException e) {
System.out.println("Error :" + e.getMessage());
}
}