版权声明:本文为博主原创文章,未经博主允许不得转载https://blog.csdn.net/qq_37146354/article/details/97131038
Lambda表达式:
1.匿名内部类创建
创建一个Communication通讯接口,里面仅且只有callBack方法,可以加入函数式接口注解
/**
* FunctionalInterface:定义这个接口是函数式接口,只能有一个抽象方法
*/
@FunctionalInterface
public interface Communication {
void callback();
}
在Person类中,使用这个通讯接口,因为是一个接口,所以要进行匿名内部类的创建。
// 创建实例,重写callback方法
Communication communication = ()->{System.out.println("callback:123");};
// 调用
communication.callback();
在Person类中写一个test方法,接收这个通讯接口
/**
* 测试方法
* @param name 普通参数
* @param communication 通讯接口
*/
public void test(String name, Communication communication){
System.out.println("name:" + name);
communication.callback();
}
在调用这个方法时候,传入通讯接口时,要进行匿名内部类的创建,使用Lambda方式,因为通讯接口中只有一个方法,所以会自动适配这个方法,重写这个方法里面的参数,传入到test方法中。
new Person().test("123",()->{System.out.println("callback:123");});
当重写通讯方法时候只有一行代码,可以省略里面的大括号
// 简化方式
Communication communication2 = () -> System.out.println("callback:123");
// 调用
communication2.callback();
如果重写的代码只有一个输出语句,输出的数据是传入的数据,则 ()-> 都可以省略
// 重写Consumer中的accept,只输出传入的值
Consumer consumer = System.out::println;
// 入参后调用打印的方法
consumer.accept("123");
// 输出 123
如果这个方法有返回值时,大括号和return都可以省略
/**
* FunctionalInterface:定义这个接口是函数式接口,只能有一个抽象方法
*/
@FunctionalInterface
public interface Communication3 {
// 接收两个int值且有返回值
int callback(int a ,int b);
}
int a = 1 ;
int b = 2 ;
// 实例化匿名内部类 , x 和 y 是 callback 的 a 和 b , -> 后面 x + y 是重写 callback 方法体里面的代码
Communication3 communication3 = (x,y)-> x + y;
// 调用 callback 方法
int ret = communication3.callback(1,2);
System.out.println(ret);
// 输出3
2.接口方法的定义
- 在1.8以前类实现接口,一定要重写接口里面的方法,如果不想重写接口的方法,只能有抽象类来过渡。
- 在1.8以后类实现接口可以不用都重写接口里面的方法,在接口中用default关键字描述的方法,在其他实现类中,可以重写它,也可以不管它。
public interface Communication {
void callback();
/**
* 接口的默认方法,在其他实现类中,可以重写它,也可以不管它
*/
default void callback1(){
}
}
// Person1实现接口只重写callback方法,不会报错
public class Person1 implements Communication{
@Override
public void callback() {
}
}
// Person2实现接口重写callback和callback1两个方法
public class Person2 implements Communication{
@Override
public void callback() {
}
@Override
public void callback1() {
}
}
- 在接口中可以定义静态方法,但是只能由接口进行调用
public interface Communication {
/**
* 接口的静态方法,只能由此接口使用,它的实现类不能使用
*/
static void callbackStatic(){
}
}
public static void main(String[] args) {
// 接口静态方法
Communication.callbackStatic();
}
3.Optionnal运用
说明:优雅的操作数据
(1)构造Optional对象
// 创建一个Optional对象,value不能为空
Optional optional = Optional.of("123");
System.out.println(optional.get());
// 创建一个Optional对象,value可以传空
String a = null;
Optional<String> ret = Optional.ofNullable(a);
// 创建一个Optional空对象
Optional<Object> empty = Optional.empty();
System.out.println(empty);
(2)其他方法
1)isPresent
isPresent() :判断Optional中的value是否有值,有值返回true,没有值返回false。
// 判断optional是否存在值
String a = "123";
Optional optional = Optional.of(a);
boolean result = optional.isPresent();
System.out.println(result);
// true
String b = null;
Optional<String> optionalS = Optional.ofNullable(b);
boolean ret = optionalS.isPresent();
System.out.println(ret);
// false
2)ifPresent
ifPresent(Consumer<? super T> consumer) :如果consumer不为null ,则执行consumer。
// 实例化Consumer对象
Consumer consumer = System.out::println;
consumer.accept("123");
// 如果optional中value中不为空,执行consumer的accept,如果String C = null,则不会执行consumer.accept方法
String c = "456";
Optional<String> optionalS1 = Optional.ofNullable(c);
optionalS1.ifPresent(consumer);
3)get
get():获取optional中的value值。
Optional optional = Optional.of("123");
// 获取123
System.out.println(optional.get());
4)orElse
orElse() :optional 如果是null ,则返回other,否则返回optional里面的value值。
// optional 如果是null ,则返回other
Optional optionalS2 = Optional.ofNullable(null);
Object o1 = optionalS2.orElse("789");
System.out.println(o1);
// optional 有值,则返回optional中的value
String d = "123";
Optional optionalS3 = Optional.ofNullable(d);
Object o2 = optionalS2.orElse("789");
System.out.println(o2);
5)orElseGet
orElseGet():optional 如果是null ,则调用supplier.get()方法,否则返回optional里面的value值。
// 创建Supplier实例
Supplier<Integer> supplier = () -> { return 1+2;};
Optional optionalS4 = Optional.ofNullable(null);
// 如果optional.value=null,则执行Supplier的get方法
Object o3 = optionalS4.orElseGet(supplier);
System.out.println(o3);
// 简化代码
Object o3 = Optional.ofNullable(null).orElseGet(() -> {return 1+2;});
System.out.println(o3);
6)orElseThrow
orElseThrow(Supplier<? extends X> exceptionSupplier) :如果optional没有值则执行exceptionSupplier并且抛出异常。
// optional中的value如果不为null,返回value中的值
String a = Optional.ofNullable("abc").orElseThrow(() -> new NullPointerException());
System.out.println(a);
// 输出abc
// optional中的value如果为null,抛后面的异常
Optional.ofNullable(null).orElseThrow(() -> new RuntimeException());
7)map
map(Function<? super T, ? extends U> mapper):映射,返回映射规则后的值,自动由Optional包装,map后面还可以使用optional中的api。
// 创建person类,设置参数
Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);
// 当optional中的值不为null,执行map中的映射规则,返回person.getName的值。如果optional中的值是null,则执行orElse后面的值
String personResult = Optional.ofNullable(person).map(son -> son.getName()).orElse(null);
System.out.println(personResult);
简化写法
// map中使用类名::参数名获取参数值返回
String personResult2 = Optional.ofNullable(person).map(Person::getName).orElse(null);
System.out.println(personResult2);
8)flatmap
flatMap(Function<? super T, Optional< U > > mapper) :同map类似,但是flatMap返回值和传入的参数类型保持不变,但是入参必须是Optional类型
// 创建person类,设置参数
Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);
// 因为传入的是Optional对象,所以返回值要封装成Optional对象
String personResult1 = Optional.ofNullable(person).flatMap(son -> Optional.of(son.getName())).orElse(null);
System.out.println(personResult1);
9)filter
filter(Predicate<? super T> predicate) :过滤,按规则进行过滤,不符合规则则返回empty,可以继续使用Optional的Api。
Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);
// 过滤名字为李四的,如果实体的名字为张三则返回这个实体,如果不为张三,则返回empty
Optional<Person> nameOptional = Optional.ofNullable(person).filter(son -> son.getName().equals("张三"));
System.out.println(nameOptional.get().getName());
4.stream运用
(1) 构造流的方式
// 个别流构造,以String为例
Stream<String> stringStream = Stream.of("a","b","c");
// Arrays构造
String [] stringArray = {"1","2","3","4","5","6"};
Stream<String> stringStream1 = Stream.of(stringArray);
Stream<String> stringStream2 = Arrays.stream(stringArray);
// 集合构造
List<String> list = new ArrayList<String>();
Stream<String> stringStream3 = list.stream();
// 数值流的构造,只提供了三个类(IntStream , LongStream , DoubleStream)
IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
LongStream longStream = LongStream.of(new long[]{1L, 2L, 3L, 4L});
DoubleStream doubleStream = DoubleStream.of(new double[]{12.33, 12.11});
(2)中间操作 [Intermediate]
1)map
map(Function<? super T, ? extends R> mapper):一对一的把 input Stream的每一个元素,映射成 output Stream 的另外一个元素。
// 准备参数
Person person1 = new Person();
person1.setName("张三");
person1.setAge(30);
person1.setHigh(180);
Person person2 = new Person();
person2.setName("李四");
person2.setAge(30);
person2.setHigh(180);
List<Person> list = new ArrayList<Person>();
list.add(person1);
list.add(person2);
// 收集Person类的名称形成新的List
List<String> ret = list.stream().map(Person::getName).collect(Collectors.toList());
System.out.println(ret);
// 输出:[张三, 李四]
// 转换小写字母变成大写字母
List<String> stringList = new ArrayList<String>();
stringList.add("a");
stringList.add("b");
List<String> collect = stringList.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect);
// 输出:[A, B]
// 对List值进行计算
List<Integer> number = new ArrayList<Integer>();
number.add(1);
number.add(2);
List<Integer> numList = number.stream().map(num -> num * 5).collect(Collectors.toList());
System.out.println(numList);
// 输出:[5, 10]
2)flatmap
flatmap(Function<? super T, ? extends Stream<? extends R>> mapper):一对多映射关系,将多个流扁平化成为一个流。
// 多个流
List<Integer> integers = Arrays.asList(1);
List<Integer> integers1 = Arrays.asList(2, 3);
List<Integer> integers2 = Arrays.asList(4, 5, 6);
Stream<List<Integer>> inputStream = Stream.of(
integers,
integers1,
integers2
);
inputStream.forEach(x ->{
System.out.println(x.toString());
// 输出:[1]
// [2, 3]
// [4, 5, 6]
});
Stream<List<Integer>> inputStream2 = Stream.of(
integers,
integers1,
integers2
);
// 多个流合并成一个流,
List<Integer> collect = inputStream2.flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(collect);
// 输出:[1, 2, 3, 4, 5, 6]
3)filter
filter (Predicate<? super T> predicate):根据规则过滤出需要的元素。
List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");
// 过滤出大写的字母形成一个新的流,再收集成List
List<String> collect = code.stream().filter(c -> Character.isUpperCase(c.charAt(0))).collect(Collectors.toList());
System.out.println(collect.toString());
// 输出:[A, B, C]
4)limit
limit (long maxSize):返回前n个元素。
List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");
// 返回前三个元素
List<String> collect = code.stream().limit(3).collect(Collectors.toList());
System.out.println(collect);
// 输出 [a, b, c]
5)skip
skip(long n):跳过前三个元素。
List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");
// 跳过前三个元素
List<String> collect = code.stream().skip(3).collect(Collectors.toList());
System.out.println(collect);
// 输出 [A, d, B, C]
6)distinct
distinct():去除重复项
List<String> code = new ArrayList<String>();
code.add("A");
code.add("B");
code.add("C");
code.add("C");
code.add("C");
// 去除重复项
List<String> collect = code.stream().distinct().collect(Collectors.toList());
System.out.println(collect);
// 输出 [A, B, C]
7)sorted
sorted():无参数排序,以自然序排序一个list。
Eg:排序一个字母List和一个自然数
List<Integer> intList = new ArrayList<Integer>();
intList.add(10);
intList.add(3);
intList.add(15);
intList.add(9);
// 以自然顺序进行排序
List<Integer> collect = intList.stream().sorted().collect(Collectors.toList());
System.out.println(collect);
// 输出:[3, 9, 10, 15]
List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");
// 以自然顺序进行排序
List<String> collect = code.stream().sorted().collect(Collectors.toList());
System.out.println(collect);
// 输出:[A, B, C, a, b, c, d]
sorted(Comparator<? super T> comparator):有参数排序,以自己定义的规则排序。
Eg:按照人的年龄从大到小排序
Person person1 = new Person();
person1.setName("张三");
person1.setAge(30L);
person1.setHigh(180);
Person person2 = new Person();
person2.setName("李四");
person2.setAge(31L);
person2.setHigh(180);
Person person3 = new Person();
person3.setName("王五");
person3.setAge(32L);
person3.setHigh(180);
Person person4 = new Person();
person4.setName("赵六");
person4.setAge(33L);
person4.setHigh(180);
List<Person> list = new ArrayList<Person>();
list.add(person4);
list.add(person2);
list.add(person3);
list.add(person1);
List<Person> collectPerson = list.stream().sorted((t1,t2)->t2.getAge().compareTo(t1.getAge())).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='赵六', age=33, high=180}, Person{name='王五', age=32, high=180}, Person{name='李四', age=31, high=180}, Person{name='张三', age=30, high=180}]
使用Comparator 来排序一个list
// 按照人的年龄从小到大排序
List<Person> collectPerson1 = list.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='张三', age=30, high=180}, Person{name='李四', age=31, high=180}, Person{name='王五', age=32, high=180}, Person{name='赵六', age=33, high=180}]
// 按照人的年龄从大到小排序
List<Person> collectPerson2 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='赵六', age=33, high=180}, Person{name='王五', age=32, high=180}, Person{name='李四', age=31, high=180}, Person{name='张三', age=30, high=180}]
注意:
排序时间对比:Collections.sort() < TreeSet < stream.sort(),虽然java8中流的排序效率低过前面两个,但是Java8的流排序可以省去构造冗长的比较器,编写更简洁的代码。
8)min
min():IntStream中min是无参方法,找出集合里面的最小值。
IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
int asInt = intStream.min().getAsInt();
System.out.println(asInt);
min(Comparator<? super T> comparator):在stream中要传入Comparator.naturalOrder(),找出最小值。
Integer[] nums = new Integer[]{1, 2, 2, 3, 4, 5, 5, 6};
Integer integer = Arrays.stream(nums).min(Comparator.naturalOrder()).get();
System.out.println(integer);
9)max
max():IntStream中min是无参方法,找出集合里面的最大值。
IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
int asInt = intStream.max().getAsInt();
System.out.println(asInt);
max(Comparator<? super T> comparator):在stream中要传入Comparator.naturalOrder(),找出最大值。
Integer[] nums = new Integer[]{1, 2, 2, 3, 4, 5, 5, 6};
Integer integer = Arrays.stream(nums).max(Comparator.naturalOrder()).get();
System.out.println(integer);
10)Match
-
allMatch
allMatch(Predicate<? super T> predicate):Stream 中全部元素符合规则,则返回 true,否则返回false。
Person person1 = new Person(); person1.setName("张三"); person1.setAge(30L); person1.setHigh(180); Person person2 = new Person(); person2.setName("李四"); person2.setAge(31L); person2.setHigh(180); Person person3 = new Person(); person3.setName("王五"); person3.setAge(32L); person3.setHigh(180); Person person4 = new Person(); person4.setName("赵六"); person4.setAge(33L); person4.setHigh(180); List<Person> list = new ArrayList<Person>(); list.add(person4); list.add(person2); list.add(person3); list.add(person1); boolean result = list.stream().allMatch(t -> t.getAge() >= 30L); System.out.println("是否所有人都符合年龄大于等于30岁:" + result); // 输出true
-
anyMatch
anyMatch(Predicate<? super T> predicate):Stream 中只要有一个元素符合规则,返回 true,否则返回false。
Person person1 = new Person(); person1.setName("张三"); person1.setAge(30L); person1.setHigh(180); Person person2 = new Person(); person2.setName("李四"); person2.setAge(31L); person2.setHigh(180); Person person3 = new Person(); person3.setName("王五"); person3.setAge(32L); person3.setHigh(180); Person person4 = new Person(); person4.setName("赵六"); person4.setAge(33L); person4.setHigh(180); List<Person> list = new ArrayList<Person>(); list.add(person4); list.add(person2); list.add(person3); list.add(person1); boolean result = list.stream().anyMatch(t -> t.getAge() >= 33L); System.out.println("是否有一个人符合年龄大于等于33岁:" + result); // 输出true
-
noneMarch
noneMarch(Predicate<? super T> predicate):Stream 中没有一个元素符合规则,返回 true,否则返回false。
Person person1 = new Person(); person1.setName("张三"); person1.setAge(30L); person1.setHigh(180); Person person2 = new Person(); person2.setName("李四"); person2.setAge(31L); person2.setHigh(180); Person person3 = new Person(); person3.setName("王五"); person3.setAge(32L); person3.setHigh(180); Person person4 = new Person(); person4.setName("赵六"); person4.setAge(33L); person4.setHigh(180); List<Person> list = new ArrayList<Person>(); list.add(person4); list.add(person2); list.add(person3); list.add(person1); boolean result = list.stream().noneMatch(t -> t.getAge() >= 60L); System.out.println("是否没有一个人符合年龄大于等于60岁:" + result); // 输出true
11)groupingBy
groupingBy(Function<? super T, ? extends K> classifier):对stream按照规则分组。
Eg:对订单的货币进行分组,相同的货币分成一个组。
Order order1 = new Order();
order1.setOrderId(1L);
order1.setOrderName("订单1");
order1.setCurrency("CNY");
Order order2 = new Order();
order2.setOrderId(2L);
order2.setOrderName("订单2");
order2.setCurrency("CNY");
Order order3 = new Order();
order3.setOrderId(3L);
order3.setOrderName("订单3");
order3.setCurrency("USD");
Order order4 = new Order();
order4.setOrderId(4L);
order4.setOrderName("订单4");
order4.setCurrency("USD");
List<Order> list = new ArrayList<Order>();
list.add(order1);
list.add(order2);
list.add(order3);
list.add(order4);
list.stream().collect(Collectors.groupingBy(Order::getCurrency)).forEach((currency,order)->{
System.out.println("货币:"+currency+",订单列表:" + order.toString());
});
// 输出:
// 货币:USD,订单列表:[Order{orderId=3, currency='USD', orderName='订单3'}, Order{orderId=4, currency='USD', orderName='订单4'}]
// 货币:CNY,订单列表:[Order{orderId=1, currency='CNY', orderName='订单1'}, Order{orderId=2, currency='CNY', orderName='订单2'}]
12 )partitioningBy
partitioningBy(Predicate<? super T> predicate):对区间进行分组,返回一个Map,key是boolean代表是否在这个区间,value是分组后的List列表。
Eg:对订单金额分为两个区间,一个是大于1000区间,一个是小于等于1000区间。
Order order1 = new Order();
order1.setOrderId(1L);
order1.setOrderName("订单1");
order1.setCurrency("CNY");
order1.setMoney(100);
Order order2 = new Order();
order2.setOrderId(2L);
order2.setOrderName("订单2");
order2.setCurrency("CNY");
order2.setMoney(1000);
Order order3 = new Order();
order3.setOrderId(3L);
order3.setOrderName("订单3");
order3.setCurrency("USD");
order3.setMoney(2000);
Order order4 = new Order();
order4.setOrderId(4L);
order4.setOrderName("订单4");
order4.setCurrency("USD");
order4.setMoney(300);
List<Order> list = new ArrayList<Order>();
list.add(order1);
list.add(order2);
list.add(order3);
list.add(order4);
list.stream().collect(Collectors.partitioningBy(order -> order.getMoney() >= 1000 )).forEach((money,order)->{
System.out.println("货币金额:"+money+",订单列表:" + order.toString());
});
// 输出:
// 货币金额:false,订单列表:[Order{orderId=1, currency='CNY', orderName='订单1', money=100}, Order{orderId=4, currency='USD', orderName='订单4', money=300}]
// 货币金额:true,订单列表:[Order{orderId=2, currency='CNY', orderName='订单2', money=1000}, Order{orderId=3, currency='USD', orderName='订单3', money=2000}]
(3)终止操作 [terminal]
1)forEach
forEach(Consumer<? super T> action):遍历数据流。
Person person1 = new Person();
person1.setName("张三");
person1.setAge(30);
person1.setHigh(180);
Person person2 = new Person();
person2.setName("李四");
person2.setAge(30);
person2.setHigh(180);
List<Person> list = new ArrayList<Person>();
list.add(person1);
list.add(person2);
// 遍历list中的每个值,打印名称
list.stream().forEach(son ->{
System.out.println(son.getName());
});
注意:在遍历中不能修改本地变量,可以修改List中的属性值,但是List不能为空。
// 修改List中的每个类名称
list.stream().forEach(son ->{
son.setName("王五");
System.out.println(son.getName());
});
// 打印列表中的每个类名称
list.stream().forEach(son ->{
System.out.println(son.getName());
});
// 输出:
// 王五
// 王五
int a = 1;
list.stream().forEach(son ->{
// 报错不能修改
a = 2;
son.setName("王五");
System.out.println(son.getName());
});
List<Person> list1 = null;
// 空指针
list1.stream().forEach(son ->{
System.out.println(son.getName());
});
注意:
在少数据时效率为:for > foreach > stream foreach,在大数据时,三个性能差不多。但是java8的stream编写更简洁的代码。
2)reduce
reduce(BinaryOperator accumulator):根据一定的规则将Stream中的元素进行计算后返回一个唯一的值。
Eg:假设有一个数组从1加到10。
Integer[] nums = new Integer[]{1,2,3,4,5,6};
Integer sum = Arrays.stream(nums).reduce((integer, integer2) -> integer + integer2).get();
System.out.println("总数:"+sum);
// 输出:21
从0开始相加
Integer[] nums2 = new Integer[]{1,2,3,4,5,6};
Integer sum2 = Arrays.stream(nums2).reduce(0,(integer, integer2) -> integer + integer2);
System.out.println("总数:"+sum);
// 输出:21