一、java8新特性内容概述
- Lambda表达式;
- 方法引用、构造器引用;
- stream流:并行流、串行流;
- 接口的增强:静态方法、动态方法;
- Optional类;
- 新的时间的日期API
- 其他:重复注解、类型注解、通用目标类型判断;
速度更快
代码更少:增加了新的语法,lambda表达式
stream流
便于并行
最大化减少空指针异常:Optinal
Nashorn引擎,允许在jvm上运行js应用
二、Lambda表达式
写法:6种
public class Lambda {
@Test
public void test3(){
// 语法格式一:无参无返回值
Runnable er2 = ()-> System.out.println("345345346456");
er2.run();
// 语法格式二:有参无返回值
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("5345345");
// 语法格式二:有参无返回值
Consumer<String> consumer2 = (String s) -> {
System.out.println(s);
};
consumer2.accept("343543");
// 引用写法
Consumer<String> consumer3 = System.out::println;
consumer3.accept("343543");
// 语法格式三:类型推断,可以省略类型
Consumer<String> consumer4 = (s) -> {
System.out.println(s);
};
consumer4.accept("3435434343");
// 语法格式四:参数只有一个,()可以省略
Consumer<String> consumer5 = s -> {
System.out.println(s);
};
consumer5.accept("343455434343");
}
@Test
public void test2(){
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
int compare = comparator.compare(12, 32);
System.out.println(compare);
// lambda表达式写法
// 语法格式五:有参有返回值
Comparator<Integer> comparator1 = (o1,o2) -> {
return Integer.compare(o1, o2);
};
int compare1 = comparator1.compare(43, 22);
System.out.println(compare1);
// 方法引用
Comparator<Integer> comparator2 = Integer::compareTo;
int compare2= comparator2.compare(43, 22);
System.out.println(compare2);
// 语法格式六:lambda只有一条语句,{}和return都可以省略
Comparator<Integer> comparator3 = (o1,o2) -> Integer.compare(o1, o2);
int comparator33 = comparator3.compare(43, 22);
System.out.println(comparator33);
}
}
三、函数式接口
如果一个接口中只声明了一个抽象的方法,就叫函数式接口;
Lambda表达式的本质就是作为函数式接口的实例;
接口加@FunctionalInterface 注解定义可以验证,是不是函数式接口
四、方法引用与构造器引用
/**
* 使用场景:
* 1、对象::非静态方法(实例方法)
* 2、类::静态方法
* 3、类::非静态方法
*
* 使用要求:接口中的抽象方法的形参列表和返回值类型 和
* 方法引用的方法形参列表和返回值类型 相同
*/
public class MethodRefTest {
@Test
void test1(){
Consumer<String> consumer = str -> System.out.println(str);
consumer.accept("被急加速");
// 方法引用写法一 对象::非静态方法
Consumer<String> consumer2 = System.out::println;
// 或者
PrintStream ps = System.out;
Consumer<String> consumer3 = ps::println;
}
@Test
void test2(){
// 方法引用写法二 类::静态方法
Comparator<Integer> comparator = Integer::compare;
}
@Test
void test3(){
Comparator<Integer> comparator = (s1,s2)-> s1.compareTo(s2);
// 方法引用写法三 类::非静态方法(实例方法)
Comparator<Integer> comparator3 = Integer::compareTo;
}
}
五、构造器引用和数组引用
六、Stream API 666
是数据渠道。用于操作数据源所生成的元素序列。
public class StreamTest {
// 通过集合创建Stream流
@Test
void test1(){
UserData data = new UserData();
List<User> userList = data.getUserList();
// 默认是串行流
Stream<User> stream = userList.stream();
// 并行流
Stream<User> userStream = userList.parallelStream();
}
// 通过数组创建Stream流
@Test
void test2(){
IntStream stream = Arrays.stream(new int[]{1, 2, 3});
UserData data = new UserData();
User[] userArr = data.getUserArr();
Stream<User> userStream = Arrays.stream(userArr);
}
// 通过Stream的of方法
@Test
void test3(){
Stream<Integer> integerStream = Stream.of(1, 2, 3);
}
}
Stream流的方法操作
// stream的筛选与切片
@Test
public void test4(){
UserData data = new UserData();
List<User> userList = data.getUserList();
// 查询手机号码是110d的用户,输出
userList.stream().filter(e -> e.getPhone().equals("110")).forEach(System.out::println);
System.out.println("===============");
// limit(n) 截断流,使其元素不超过n
userList.stream().limit(2).forEach(System.out::println);
System.out.println("===============");
// skip(n) 跳过元素前2个元素
userList.stream().skip(2).forEach(System.out::println);
System.out.println("===============");
// distinct 去重,通过流所生成元素的hashcode()和equals()去重
// 注意:distinct()用于基本数据类型和String可以去重,但对于对象,不能做到去重;
// 可以在对象中重写hashcode()和equals()方法去重,或者
//根据name属性去重
userList.stream().filter(distinctByKey(User::getId)).forEach(System.out::println);
// 或者,利用TreeSet
userList.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList::new))
.forEach(System.out::println);
}
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor){
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
map 与 flatmap 映射
// stream的映射 map flatmap
@Test
public void test5(){
UserData data = new UserData();
List<User> userList = data.getUserList();
// 拿到用户姓名长度大于3的用户姓名
userList.stream().filter(user -> user.getName().length() > 3)
.map(User::getName).forEach(System.out::println);
// 转换成大小写
List<String> strings = Arrays.asList("aa", "bb", "cc");
strings.stream().map(String::toUpperCase).forEach(System.out::println);
// Stream嵌套stream 比较map和flatmap的区别
// map需要foreach两次
Stream<Stream<Character>> streamStream = strings.stream().map(StreamTest::fromstreamToStream);
streamStream.forEach(s -> {
s.forEach(System.out::println);
});
// flatmap只需要一次foreach ,对于集合套集合的情况,优先flatmap
Stream<Character> characterStream = strings.stream().flatMap(StreamTest::fromstreamToStream);
characterStream.forEach(System.out::println);
}
public static Stream<Character> fromstreamToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for(Character a : str.toCharArray()){
list.add(a);
}
return list.stream();
}
// 排序
@Test
public void test6() {
// sorted 自然排序 数字默认从小到大排序 如果排序对象会报错,因为对象没有实现Compable排序接口
List<Integer> integers = Arrays.asList(666, 44, -98, 1, 33, 44, 66, 77);
integers.stream().sorted().forEach(System.out::println);
System.out.println("============================");
List<String> integers2 = Arrays.asList("斩杀", "ed", "44", "我的世界", "43534");
integers2.stream().sorted().forEach(System.out::println);
// sorted(Compator c) 定制排序
UserData userData = new UserData();
List<User> userList = userData.getUserList();
// 默认从小到大
userList.stream().sorted(Comparator.comparingInt(User::getPhone)).forEach(System.out::println);
// 按照电话从小到大,按照从大到小
userList.stream().sorted((e1, e2) -> {
int v = Integer.compare(e1.getPhone(),e2.getPhone());
if (v == 0){
return v;
}else {
// 在前面加 - 负号
return -Integer.compare(e1.getId(),e2.getId());
}
}).forEach(System.out::println);
}
Stream流的终止操作
// stream流的终止操作
// 1、匹配与查找
@Test
public void test8(){
// allMatch(Predicate e) 判断是否匹配所有元素
List<User> userList = new UserData().getUserList();
boolean b = userList.stream().allMatch(e -> e.getId() > 2);
System.out.println(b); // ----false
List<User> userList2 = new UserData().getUserList();
boolean c = userList.stream().allMatch(e -> e.getId() > 0);
System.out.println(c); // ----true
// anyMatch 判断是否至少匹配一个元素
boolean d = userList.stream().anyMatch(e -> e.getId() > 0);
System.out.println(d); // ----true
// noneMatch 没有一个存在的,判断是否没有匹配的元素
boolean f = userList.stream().noneMatch(e -> e.getId() < 0);
System.out.println(f); // ----true
// findFirst --返回第一个元素
// findAny 返回任意一个元素
Optional<User> any = userList.parallelStream().findAny();
System.out.println(any);
// count 返回元素的个数
// max 返回流中的最大值
// min 返回流中的最小值 --返回id最小的用户
Optional<User> min = userList.stream().min(Comparator.comparingInt(User::getId));
System.out.println(min);
}
// 归约 reduce 收集collect
@Test
public void test9(){
// 求1-5的和
List<Integer> list = Arrays.asList(1,2,3,4,5);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
}
七、Optional类
Optional类是一个容器类。可以避免空指针异常。是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回这个对象