1.8新特性
Lambda表达式
简介
Lambda表示式(又称为闭包)是整个JAVA8发现版中最受期待的在Java语言层面上的改变
Lambda允许把函数作为一个参数(函数作为参数传递进方法中),或者把代码看成数据
Lambda表达式用于简化Java中接口式的匿名内部类,被称为函数式接口的概念,函数式接口就是一个具有一个方法的普通接口,像这样的接口可以被隐式转换为Lambda表达式
作用:简化代码
要求:一个接口或抽象类中只有一个抽象方法
优点:
1、简化代码
2、不会生成class文件
缺点:
1、有限制
2、对新手代码阅读增加困难
语法
(参数1,参数2,....)->{方法体}
Lambda表达式与函数式接口
1、没有参数时使用lambda表达式
public class Test01 {
public static void main(String[] args) {
IEatImpl iEatImpl = new IEatImpl();
iEatImpl.eat();
IEat iEat = new IEat() {
@Override
public void eat() {
System.out.println("吃东西01");
}
};
iEat.eat();
IEat iEat02 = ()->{
System.out.println("吃东西02");
};
iEat02.eat();
}
}
interface IEat{
void eat();
}
class IEatImpl implements IEat{
@Override
public void eat() {
System.out.println("吃东西");
}
}
2、带有参数时使用lambda表达式
public class Test01 {
public static void main(String[] args) {
IEat iEat01 = (String foodName)->{
System.out.println("吃"+foodName);
};
iEat01.eat("桃子");
IEat iEat02 = (foodName)->{
System.out.println("吃"+foodName);
};
iEat02.eat("桃子");
IEat iEat03 = foodName->{
System.out.println("吃"+foodName);
};
iEat03.eat("桃子");
IEat02 iEat04 = (foodName,name)->{
System.out.println(name+"吃"+foodName);
};
iEat04.eat("桃子","张三");
}
}
interface IEat{
void eat(String foodName);
}
interface IEat02{
void eat(String foodName,String name);
}
3、代码块中只有一句代码时使用lambda表达式
public class Test01 {
public static void main(String[] args) {
IEat iEat02 = ()->System.out.println("吃东西");
iEat02.eat();
}
}
interface IEat{
void eat();
}
4、代码块中有多句代码时使用lambda表达式
public class Test01 {
public static void main(String[] args) {
IEat iEat = ()->{
System.out.println("准备干饭");
System.out.println("吃东西");
System.out.println("就餐完毕");
};
iEat.eat();
}
}
interface IEat{
void eat();
}
5、有返回值的代码块
public class Test01 {
public static void main(String[] args) {
IEat iEat = ()->{
System.out.println("吃东西");
return true;
};
iEat.eat();
IEat iEat = ()->true;
iEat.eat();
}
}
interface IEat{
boolean eat();
}
6、参数中使用final关键字
public class Test01 {
public static void main(String[] args) {
IEat iEat = (final String foodName)->{
System.out.println("吃"+foodName);
return true;
};
iEat.eat();
}
}
interface IEat{
boolean eat(final String foodName);
}
相关注解
@FunctionalInterface
常见函数式接口
接口名称 类型 方法
Consumer<T> 消费型接口 void accept(T t):操作t
Supplier<T> 供给型接口 T get():返回t
Function<T,R> 函数型接口 R apply(T t):操作t,返回r
Predicate<T> 断言型接口 boolean test(T t):操作t,返回boolean
方法引用
简介
方法引用是Lambda表达式的一种简写形式
要求:如果Lambda表达式方法体中只是调用一个特殊的已经存在的方法,则可以使用方法引用
语法
1、对象::实例方法
要求:lambda传入的参数与就是所调用的方法的参数,并且方法体中只有一行代码
代码:
Consumer<String> consumer=s->System.out.println(s);
consumer.accept("hello");
Consumer<String> consumer2=System.out::println;
consumer2.accept("world");
2、类::静态方法
要求:lambda传入的参数与就是所调用的方法的参数,并且方法体中只有一行代码
代码:
Comparator<Integer> com=(o1,o2)->Integer.compare(o1, o2);
Comparator<Integer> com2=Integer::compare;
3、类::实例方法
要求:lambda传入的参数类型就是调用该方法的对象,并且方法体中只有一行代码
代码:
Function<Employee, String> function=e->e.getName();
Function<Employee, String> function2=Employee::getName;
System.out.println(function2.apply(new Employee("小明", 50000)));
class Employee{
private String name;
private int money;
public Employee(String name,int money) {
this.money = money;
this.name = name;
}
public String getName() {
return name;
}
}
4、类::new
要求:lambda方法体中只有一行创建对象的代码,并且返回值就是该对象
代码:
Supplier<Employee> supplier=()->new Employee();
Supplier<Employee> supplier2=Employee::new;
Employee employee=supplier.get();
class Employee{
private String name;
private int money;
public Employee(String name,int money) {
this.money = money;
this.name = name;
}
public String getName() {
return name;
}
}
Stream
简介
Stream:流
与集合类似,但是集合中存储的是数据,而Stream中存储的是对数据的操作过程
如图:
原料 -> 工序1 -> 工序2 -> 工序n -> 产品
注意:
1,Stream不会存储数据
2,Stream不会改变原数据,他们会返回一个持有加工后数据的新Stream
3,Stream会延迟执行,会等到需要的结果才执行
使用步骤
创建:
新建一个Stream
中间操作:
在一个或多个步骤中,将初始Stream转换为另一个Stream的中间操作
终止操作:
使用一个终止操作来产生一个结果,该操作会强制之前的延迟操作立即执行.此后该Stream不能在使用
获取Stream
1,通过集合对象(Collection)的stream()或parallelStream()方法
代码:
ArrayList<String> arrayList=new ArrayList<>();
Stream<String> stream = arrayList.parallelStream();
或
ArrayList<String> list = new ArrayList<String>();
Stream<String> stream = list.stream();
2,通过Arrays工具类的静态stream方法
代码:
String[] arr= {"aaa","bbb","ccc"};
Stream<String> stream2=Arrays.stream(arr);
3,通过Stream接口中的静态of,iterate,generate方法
代码:of普通流
Stream<Integer> stream = Stream.of(10,20,30,40,50);
代码:iterate迭代流
Stream<Integer> iterate = Stream.iterate(0, x->x+2);
代码:generate生成流
Stream<Integer> generate = Stream.generate(()->new
Random().nextInt(100));
4,通过IntStream,LongStream,DoubleStream接口的of,range,rangeClosed方法
代码:
IntStream stream = IntStream.of(100,200,300);
代码:
IntStream range = IntStream.rangeClosed(0, 50);
中间操作
1,filter过滤
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.filter(e->e.getMoney()>15000)
.forEach(System.out::println);
2,limit限制
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.limit(2)
.forEach(System.out::println);
3,skip跳过
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.skip(2)
.forEach(System.out::println);
4,distinct去掉重复
注意:存储对象必须实现hashCode()和equals()方法,用这两个方法判断是否重复,先调用哪个
hashCode方法,如果该方法的返回值与存储其他数据一致,在调用equals比较
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.distinct()
.forEach(System.out::println);
5,sorted排序
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.sorted((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()))
.forEach(System.out::println);
6,map映射操作
简介:将当前Stream中的每个元素都映射转换为另一个元素,从而得到一个新的Stream
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream()
.map(e->e.getName())
.forEach(System.out::println);
7,parallel并行流
简介:采用多线程 效率高
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream().parallel()
.forEach(System.out::println);
终止操作
1,forEach遍历
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
list.stream().forEach(System.out::println);
2,min最小值
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
Optional<Employee> min = list.stream().min((o1,o2)-
>Integer.compare(o1.getMoney(), o2.getMoney()));
System.out.println(min.get());
3,max最大值
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
Optional<Employee> max = list.stream().max((e1,e2)->Integer.compare(e1.getMoney(), e2.getMoney()));
System.out.println(max.get());
4,count数量
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
long count = list.stream().filter(o -> o.getMoney()>20000).count();
System.out.println(count);
5,reduce规约
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
Optional<Double> sum = list.stream()
.map(e->e.getMoney())
.reduce((x,y)->x+y);
System.out.println(sum.get());
6,collect收集
代码:
ArrayList<Employee> list=new ArrayList<>();
list.add(new Employee("小王", 15000));
list.add(new Employee("小张", 12000));
list.add(new Employee("小李", 18000));
list.add(new Employee("小孙", 20000));
list.add(new Employee("小刘", 25000));
list.add(new Employee("小刘", 25000));
List<String> names = list.stream()
.map(e->e.getName())
.collect(Collectors.toList());
for (String string : names) {
System.out.println(string);
}