java8添加了很多新的特性,这篇文章主要是挑几个重要的说一说,主要写的是lambda表达式,Stream API,OPtional类
1、lambda表达式
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以 传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了 提升。Lambda 表达式书写规则,(x1,x2…) -> {…},"->"将Lambda表达式分为了两部分,左边是参数列表,右边是方法体。如果方法没有参数,那么 -> 左边一定要是 (),如果有一个参数,可以将变量类型,括号都可以去掉,对于方法体,在有返回值的情况下,如果只有一段代码则可以省略大括号和return,如果多行代码的情况下,不能省略{}和return;在没有返回值的情况下,如果只有一段代码则可以省略大括号,如果多行代码的情况下,不能省略{}。
代码演示
// 不用 lambda 表达式
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("跑起来!!!");
}
};
r1.run();
// 使用 lambda 表达式,不传参数
Runnable r2 = () -> System.out.print("浪起来");
r2.run();
// 不用 lambda 表达式
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// 使用 Lambda 表达式,传2个参数
Comparator<Integer> com2 = (o1,o2) -> o1-o2;
// 一个参数
Consumer<String> com2 = s -> System.out.println(s);
// 方法体为多行
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
// lambda 中不用指定参数类型,是因为javac根据程序的上下文,在后台推断出了参数的数据类型,
是由编译器推断出来的,这就是 “类型推断”。
注意: 在java中lambda表达式代表的不是一个函数,而是一个接口的实例,当一个接口为函数式接口时才能使用 lambda 表达式,只包含一个抽象方法的接口称为函数式接口。
Stream API
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进 行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而Stream是有关计算的。前者是主要面向内存,存储在内存中,后者主要面向CPU,通过cpu实现计算。
注意:
1、Stream自己不会存储元素
2、Stream不会改变原对象,相反,会返回一个处理后的Stream对象
3、Stream 操作是延迟执行的,必须要有终止操作才能结束
创建Stream
- 方式一:通过集合方式
List<String> list = Arrays.asList("aaa", "bbb", "cccc"); Stream<String> stream = list.stream(); // 创建一个顺序流 Stream<String> stringStream = list.parallelStream(); // 创建一个并行流
方式二:通过数组
int [] a ={1,2,3,4,5,6,7}; IntStream stream = Arrays.stream(a);
方式三:通过Stream的of()
可以调用Stream类静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。int [] a ={1,2,3,4,5,6,7}; Stream<int[]> a1 = Stream.of(a);
filter(Predicate p) 接收 lambda,从流中排除某些元素。- Stream的中间操作
distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一
个空流。与 limit(n) 互补List<Integer> list = Arrays.asList(12, 4, 23, 5, 546, 1, 32, 55, 68, 131,1,1,1); // 获取大于50的值的一个Stream Stream<Integer> integerStream = list.stream().filter(x -> x > 50); // 排除重复的元素 list.stream().distinct().forEach(System.out::println); // 获取前5个值 Stream<Integer> limit = list.stream().limit(5); // 跳过前五个 Stream<Integer> skip = list.stream().skip(5);
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator com) 产生一个新流,其中按比较器顺序排序List<String> list1 = Arrays.asList("aaa", "bbb", "cccc"); Stream<String> stringStream = list1.stream().map(x -> x.toUpperCase()); // 通过map将每一个字符串都变为大写的。 List<Integer> list = Arrays.asList(12, 4, 23, 5, 546, 1, 32, 55, 68, 131,1,1,1); // 排序 Stream<Integer> sorted = list.stream().sorted((e1, e2) -> e1.compareTo(e2));
- Stream的终止操作
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)@Test public void test5(){ List<Integer> list = Arrays.asList(123, 1, 2, 31, 12, 442, 12, 567, 64, 43, 23, 21); // allMatch(Predicate p) 检查是否匹配所有元素 // 判断是否所有元素都大于50 boolean b = list.stream().allMatch(e -> e > 50); System.out.println("allMatch: " + b); // anyMatch(Predicate p) 检查是否至少匹配一个元素 // 判断是否有大于500的元素存在 boolean b1 = list.stream().anyMatch(e -> e > 500); System.out.println("anyMatch: " + b1); // noneMatch(Predicate p) 检查是否没有匹配所有元素 // 判断大于100 是否没有匹配所有的元素 boolean b2 = list.stream().noneMatch(e -> e > 1000); System.out.println("noneMatch: " + b2); // findFirst() 返回第一个元素 Optional<Integer> first = list.stream().findFirst(); System.out.println("findFirst: " + first); // findAny() 返回当前流中的任意元素 Optional<Integer> any = list.stream().findAny(); System.out.println("findAny: " + any); // count() 返回流中元素总数 long count = list.stream().count(); System.out.println("count: " + count); // max(Comparator c) 返回流中最大值 Optional<Integer> max = list.stream().max((e1, e2) -> Integer.compare(e1, e2)); System.out.println("max: " + max); // min(Comparator c) 返回流中最小值 Optional<Integer> min = list.stream().min((e1, e2) -> e1.compareTo(e2)); System.out.println("min: " + min); // forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代, // 称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了) // 遍历 list.stream().forEach(System.out::println); }
输出的结果:
allMatch: false anyMatch: true noneMatch: true findFirst: Optional[123] findAny: Optional[123] count: 12 max: Optional[567] min: Optional[1] 123 1 2 31 12 442 12 567 64 43 23 21
终止操作还有一个,收集
collect(Collector c)将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
toList List 把流中元素收集到List
toSet Set 把流中元素收集到SetList<Integer> list1 = Arrays.asList(10, 2, 30, 45, 16, 24, 21, 354, 65, 413, 54, 312, 53, 45, 13, 54, 123); List<Integer> collect = list1.stream().filter(e -> e > 100).collect(Collectors.toList()); Set<Integer> collect1 = list1.stream().collect(Collectors.toSet());
他还有其他的方法,在这就先不写了。
Optional 类
Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表 这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不 存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。创建Optional类对象的方法:
Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):t可以为nullclass People{ private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "People{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } public People(String name) { this.name = name; } } public class Test5 { @Test public void test1(){ People p1 = new People("小小"); Optional<People> optional = Optional.of(p1); // 参数必须是非空,否则报错 Optional<People> optional1 = Optional.ofNullable(p1); // 参数可以为null Optional<Object> empty = Optional.empty(); // 创建一个空的Optional实例 } }
判断Optional容器中是否包含对象:
boolean isPresent() : 判断是否包含对象
void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer
接口的实现代码,并且该值会作为参数传给它。public class Test5 { @Test public void test1(){ People p1 = new People("小小"); Optional<People> optional = Optional.of(p1); // 参数必须是非空,否则报错 boolean present = optional.isPresent(); # 判断是否包含对象 System.out.println(present); optional.ifPresent(e -> System.out.println(e.getName())); 如果有值,就执行Consumer 接口的实现代码,并且该值会作为参数传给它。 } }
获取Optional容器的对象:
T get(): 如果调用对象包含值,返回该值,否则抛异常
T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。People p1 = new People("小小"); Optional<People> optional = Optional.of(p1); People people = optional.get(); // 一般与 Optional.of() 一起用,因为of只能传递一个非空的 Optional<Object> empty = Optional.empty(); Object object = empty.orElse(new People("花花")); // empty是一个空的,所以返回的是 new People("花花") 这个对象