JDK8的部分特性
JDK8提供了十个特性。
我自己的理解:Scala —— 开发语言使用的是Java。Scala的效率比Java高,Java为了提高效率推出了1.8版本,1.8版本就仿照了Scala来规范代码格式。
1、接口的默认方法
从JDK1.8开始,接口中允许存在实体方法,要求这个实体方法必须用default修饰。个数不做限定。也可以声明静态实体方法,静态实体方法不能用default修饰。
由于接口允许多继承和多实现,所以此时可能会产生方法调用的混乱。
interface Calc {
// 无论是抽象方法还是实体方法都必须用public修饰
int add(int i, int j);
public default double minus(double i, double j) {
return i - j;
}
public default double multiply(double i, double j) {
return i * j;
}
public static double sqrt(double d) {
return Math.sqrt(d);
}
}
2、Lambda表达式
格式
(参数列表)->{表达式};
Lambda表达式实际上是重写接口中的抽象方法。如果方法体只有一句,可以省略{}和return;也可以省略参数类型,在编译的时候JVM会根据上文自动推导参数类型。
public class LambdaDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("Cat", "Dog", "Pig", "Panda", "Lion", "Tiger", "Dragon");
// 按照首字母来进行升序排序
// Collections.sort(list, new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.charAt(0) - s2.charAt(0);
// }
// });
// Collections.sort(list, (String s1, String s2) -> {
// return s1.charAt(0) - s2.charAt(0);
// });
// 此时方法体只有一句话,那么{}以及return可以省略不写,此时这一句的执行结果默认就是返回值
// Collections.sort(list, (String s1, String s2) -> s1.charAt(0) -
// s2.charAt(0));
// 可以省略参数类型不写,JVM在编译的时候会根据上文自动推导参数类型
Collections.sort(list, (s1, s2) -> s1.charAt(0) - s2.charAt(0));
System.out.println(list);
}
}
任何一个Lambda表达式都不能用Object接住。想要接住需要强转。
@SuppressWarnings("unused")
public static void main(String[] args) {
// Object r = new Runnable() {
//
// @Override
// public void run() {
// System.out.println("hahah~~~");
// }
// };
Object r = (Runnable)() -> System.out.println("hahah~~~");
// new Thread(r).start();
}
注意
使用Lambda表达式的接口中,只允许存在一个抽象方法。
例如之前学过的:Comparator、Runnable、FileFilter、FilenameFilter、Comparable、Iterable。
静态方法的传递
public class LambdaDemo2 {
public static void main(String[] args) {
// 如果参数列表中只有一个参数,()可以省略
// 此时方法体只有一句话,而且这句话是调用已有类中的某个静态方法
// Cal c = d -> Math.sqrt(d);
// 静态方法的传递
Cal c = Math::sqrt;
System.out.println(c.sqrt(16));
}
}
@FunctionalInterface
interface Cal {
public double sqrt(double d);
}
3、函数式接口
如果一个接口中只有一个抽象方法,那么此时可以将该接口声明为一个函数式接口,在接口上添加@FunctionalInterface注解表示将接口声明为函数式接口。
1.Predicate< T > interface(判断者)
重要方法
test(T t);
需要指定判断规则。
public class PredicateDemo {
public static void main(String[] args) {
// 判断字符串是否是一个字母开头
Predicate<String> p = str -> str.matches("[a-zA-Z].*");
System.out.println(p.test("a23"));
}
}
2.Function< T,R > interface(转化者)
重要方法
apply(T t);
按照指定的规则将参数转化为指定结果类型。
public class FuntionDemo {
public static void main(String[] args) {
// 输入一个字符串,将字符串转化为整数之后,求平方
// String -> Integer
Function<String, Integer> f = str -> Integer.parseInt(str) * Integer.parseInt(str);
// 输入一个字符串,将字符串转化为整数之后,求平方,输出平方的两倍
Function<String, Integer> f2 = f.andThen(i -> i * 2);
System.out.println(f2.apply("10"));
}
}
3.Supplier< T > interface(供给者)
只有结果,不需要参数。
重要方法
get();
返回结果。
public class SupplierDemo {
public static void main(String[] args) {
// 供给者---只有结果而不需要参数
Supplier<Double> s = () -> Math.random();
System.out.println(s.get());
}
}
4.Consumer< T > interface(消费者)
重要方法
accept(T t);
只接收而没有返回值。
public class ConsumerDemo {
public static void main(String[] args) {
// 方法体只有一句话,而且是调用了对象out中的println方法
// Consumer<String> c = str -> System.out.println(str);
Consumer<String> c = System.out::println;
c.accept("abc");
}
}
4、Stream< T > interface(流式结构)
不是流,是一个流式结构。提供了一系列的操作而不改变原流的方法。根据这些方法的返回值类型,将其分为中间方法和完结方法。
如果返回值类型是stream类型,则称之为中间方法;反之则称之为完结方法。
通过集合来获取Stream对象。
重要方法
中间方法
sorted();
排序。
filter(Predicate< ? super T> predicate);
map(Function< ? super T,? extends R> mapper);
完结方法
allMatch(Predicate< ? super T> predicate);
判断所有元素是否匹配提供的规则。
collect(Collector);
将流式结构转化为为一个集合,要转化为那种集合由自己指定。
reduce();
规约。
示例
public class StreamDemo1 {
public static void main(String[] args) {
List<String> list = Arrays.asList("Cat", "Dog", "Pig", "Panda", "Lion", "Tiger", "Dragon");
// 获取Stream对象
Stream<String> stream = list.stream();
// 将集合排序之后,获取所有的以D开头的字符串,将其所有的字母转化为大写只有再打印
// stream.sorted().filter(str -> str.startsWith("D")).map(str ->
// str.toUpperCase()).forEach(str -> System.out.println(str));
// 判断集合中是否含有以字母"A"开头的字符串
// System.out.println(stream.filter(str -> str.startsWith("A")).count()
// > 0);
// System.out.println(stream.anyMatch(str -> str.startsWith("P")));
// 判断集合中的元素是否都是以数字开头
// System.out.println(stream.filter(str -> str.matches("\\d.*")).count()
// == list.size());
// System.out.println(stream.allMatch(str -> str.matches("\\d.*")));
// 将流式结构转化为一个集合
// List<String> ls = stream.collect(Collectors.toList());
stream.collect(Collectors.toSet());
}
}
5、时间包(time package)
在JDK8中,对时间体系进行了全新的划分,就划出了一个单独的包
LocalDate
只包含日期的类。
public class LocalDateDemo {
public static void main(String[] args) {
// Date date = new Date();
// System.out.println(date);
// 只包含日期而不包含时间的类
LocalDate date = LocalDate.now();
// System.out.println(date);
// System.out.println(date.getDayOfWeek());
// System.out.println(date.getDayOfYear());
// System.out.println(date.getMonthValue());
// 第一个参数表示的是数量
// 第二个参数表示的是单位
System.out.println(date.plus(3,ChronoUnit.WEEKS));
// 判断是否是一个闰年
// System.out.println(date.isLeapYear());
//
// LocalDate date2 = LocalDate.of(2000, 12, 12);
// System.out.println(date2);
// System.out.println(date.isAfter(LocalDate.of(2000, 12, 12)));
}
}
LocalTime
只包含时间的类。
public class LocalTimeDemo {
public static void main(String[] args) {
// LocalTime time = LocalTime.now();
// System.out.println(time);
LocalTime time = LocalTime.of(12, 23, 50, 56);
System.out.println(time.plus(10, ChronoUnit.SECONDS));
}
}