目录
Java8新特性
Lambda表达式
Lambda是一个匿名函数
本质
Java中Lambda表达式其实作为是函数式接口实现类的对象,其中函数式接口是只有一个抽象方法的接口(函数式接口)
格式
->
:箭头操作符/Lambda操作符
->
左边:Lambda形参列表,其实就是接口中的抽象方法的形参列表
->
右边:Lambda体,其实就是接口中的抽象方法的方法体
使用
-
语法格式一:无参、无返回值
@Test public void test1() { // 不用Lambda表达式的Runnable实现类的对象写法 Runnable r1 = new Runnable() { @Override public void run() { System.out.println("This is runnable"); } }; r1.run(); // 使用Lambda表达式的写法 Runnable r2 = ()-> System.out.println("This is runnbale from lambda"); r2.run(); }
-
语法格式二:一个参数但是没有返回值
interface Consumer<T>{ void accept(T t); } @Test public void test1() { Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("haha"); }
-
语法格式三:数据类型可以省略,因为可以由编译器推断而出,称为“类型推断”
interface Consumer<T>{ void accept(T t); } @Test public void test1() { // 因为有泛型,所以参数类型不需要写类型 Consumer<String> con1 = (s) -> { System.out.println(s); }; con1.accept("haha"); }
-
语法格式四:只有一个参数,可以省略括号
interface Consumer<T>{ void accept(T t); } @Test public void test1() { // 因为有泛型,所以参数类型不需要写类型 Consumer<String> con1 = s -> { System.out.println(s); }; con1.accept("haha"); }
-
语法格式五:有多个参数,多条执行语句,并且可以有返回值
@Test public void test1() { Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1,o2); } }; System.out.println(com1.compare(12, 13)); Comparator<Integer> com2 = (o1, o2) -> { return Integer.compare(o1,o2); }; System.out.println(com2.compare(12, 13)); }
-
语法格式六:当Lambda体只有一条语句,则可以省略return和大括号
@Test public void test1() { Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1,o2); } }; System.out.println(com1.compare(12, 13)); Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1,o2); System.out.println(com2.compare(12, 13)); }
函数式接口
在Java8之后新增了注解@FunctionalInterface
Java内置核心函数式接口
简单演示:
Consumer<>
@Test
public void test1()
{
consumeMoney(100, money -> System.out.println("花费了:"+money));
}
public void consumeMoney(int money, Consumer<Integer> con)
{
con.accept(money);
}
Predicate<>
public class LambdaTest {
@Test
public void test1()
{
List<Integer> list= Arrays.asList(1,2,3,4);
ArrayList<Integer> result = testPredicate(list, i -> {
return i % 2 == 0;
});
System.out.println(result);
}
public ArrayList<Integer> testPredicate(List<Integer> list, Predicate<Integer> pre)
{
ArrayList<Integer> result = new ArrayList<Integer>();
for (int i:list) {
if(pre.test(i))
result.add(i);
}
return result;
}
}
方法引用和构造器引用
方法引用的使用情形
当要传递给Lambda体的操作已经有实现的方法了,可以使用方法引用!方法引用,本质上就是Lambda表达式。
格式
类(或对象)::方法名
-
对象::非静态方法
@Test public void test1() { User user = new User(12,"BILL"); Supplier<String> sup = user::getName; System.out.println(sup.get()); }
-
类::静态方法
@Test public void test1() { Comparator<Integer> com1 = (t1,t2)->{return Integer.compare(t1,t2);}; System.out.println(com1.compare(11, 12)); Comparator<Integer> com2 = Integer::compare; System.out.println(com2.compare(12,11)); }
对于情况1和2,要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同
-
类::实例方法
其中第一个参数作为对象调用实例方法,第二个参数作为实例方法的参数
t1.compareTo(t2);
@Test public void test1() { Comparator<Integer> com1 = (t1,t2)->{return Integer.compare(t1,t2);}; System.out.println(com1.compare(11, 12)); Comparator<Integer> com2 = Integer::compareTo; System.out.println(com2.compare(12,11)); }
构造器引用
注意对应的参数的个数使用不同的函数式接口,格式Class::new
@Test
public void test1()
{
// 无参构造用Supplier
Supplier<User> sup = User::new;
User user = sup.get();
System.out.println(user);
System.out.println("*********************************");
// 两个参数的构造用BiFunction
BiFunction<Integer,String,User> bif = User::new;
User user2 = bif.apply(12,"Bill");
System.out.println(user2);
}
数组引用
把数组看作一个特殊的类,则与构造器引用一致
public void test1()
{
Function<Integer,Double[]> func = (length) -> new Double[length];
Double[] arr1 = func.apply(5);
System.out.println(Arrays.toString(arr1));
System.out.println("****************");
Function<Integer,Double[]> func2 = Double[]::new;
Double[] arr2 = func.apply(5);
System.out.println(Arrays.toString(arr2));
}
Stream API
Stream关注的是对数据的运算,与CPU打交道,Colletcion关注的是数据的存储,与内存打交道
特性:
- Stream 自己不会存储元素
- Stream 不会改变源对象,相反他们会返回一个持有结果的新Stream
- Stream 操作是延迟执行的,这意味着他们会等到需要结果的时候才执行
执行流程
- Stream的实例化
- 一系列中间操作:一个中间操作链
- 终止操作:一旦终止,就执行中间操作链,并产生结果,之后不会再被使用
创建Stream
public void test1()
{
// 通过集合返回流
List<Integer> list=Arrays.asList(1,2,4,5,7,8,9);
// 返回一个顺序流
Stream<Integer> s1 = list.stream();
// 返回一个并行流
Stream<Integer> s2 = list.parallelStream();
// 通过数组返回流 Arryas.stream(T[] t);
IntStream s3 = Arrays.stream(new int[]{1, 2, 3});
// 通过Stream类的静态函数of()
Stream<Integer> s4 = Stream.of(1, 2, 3, 4, 5);
}
中间操作
筛选和分片
包括filter(Predict p)、limit(int n)、skip(int n)、distinct()
public void test1()
{
// 通过集合返回流
List<Integer> list=Arrays.asList(1,2,4,4,4,5,7,8,9);
// 返回一个顺序流
Stream<Integer> s1 = list.stream();
System.out.println("*******filter*******");
// filter(Predict p)--接受Lambda,从流中排除某些元素
s1.filter(e -> e>=5).forEach(System.out::println);
System.out.println("*******limit*******");
s1 = list.stream();
// Limit(n)--截断流,使其元素不超过给定的数量
s1.limit(3).forEach(System.out::println);
System.out.println("*******skip*******");
s1 = list.stream();
// skip(n)--跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流
s1.skip(5).forEach(System.out::println);
System.out.println("*******distinct*******");
s1 = list.stream();
// distinct()--筛选,通过流生成的hashCode()和equals()筛选
s1.distinct().forEach(System.out::println);
}
映射
排序
@Test
public void test1()
{
//sorted()
//自定义类需要实现Comparable接口
List<Integer> list = Arrays.asList(12,31,1,345,0,10);
Stream<Integer> s1 = list.stream();
s1.sorted().forEach(System.out::println);
//sorted(Comparator com)
List<User> users = Arrays.asList(new User(12, "Bill"), new User(20, "haha"), new User(8, "123"));
users.stream().sorted( (user1,user2)-> Integer.compare(user1.getAge(), user2.getAge())).forEach(System.out::println);
}
终止操作
匹配与查找
public void test1()
{
List<Integer> list = Arrays.asList(12,31,1,345,0,10);
Stream<Integer> s1 = list.stream();
System.out.println(list.stream().allMatch(e1 -> e1 > 1));//false
System.out.println(list.stream().anyMatch(e1 -> e1 > 1));//true
System.out.println(list.stream().noneMatch(e1 -> e1 < 0));//true
// 对应的还有findAny(),返回任意一个
System.out.println(list.stream().findFirst());
//Optional[12]
// 返回一个Optional类型的元素
System.out.println(list.stream().count());//6
//对应的还有min
System.out.println(list.stream().max(Integer::compare));
//Optional[345]
list.stream().forEach(System.out::println);
}
归约
reduce(T identity, BinaryOperator)
–可以将流中的元素反复结合起来,得到一个值,返回。
@Test
public void test1()
{
List<Integer> list = Arrays.asList(12,31,1,345,0,10);
// identity作为初始值,BinaryOperator继承于BiFunction<T,T,T>,是一个二元函数并返回相同类型的值
System.out.println(list.stream().reduce(0, Integer::sum));//399
}
收集
collect(Collector c)
–将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。
@Test
public void test1()
{
List<Integer> list = Arrays.asList(12,31,1,345,0,10);
System.out.println(list.stream().filter(e -> e > 10).collect(Collectors.toList()));//[12, 31, 345]
}
ty作为初始值,BinaryOperator继承于BiFunction<T,T,T>,是一个二元函数并返回相同类型的值
System.out.println(list.stream().reduce(0, Integer::sum));//399
}
#### 收集
`collect(Collector c)`--将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。
```java
@Test
public void test1()
{
List<Integer> list = Arrays.asList(12,31,1,345,0,10);
System.out.println(list.stream().filter(e -> e > 10).collect(Collectors.toList()));//[12, 31, 345]
}