一、Lambda表达式
本质是一种匿名函数,是没有方法声明的方法,也没有访问修饰符、返回值声明和名字。
先定义一个接口Fu
package cn.cy.study.lambda;
public interface Fu {
int add(int a, String b);
}
类的内部实现Fu接口,两种方式,第一种是匿名内部类方式,第二种是Lambda表达式方式
package cn.cy.study.lambda;
public class LambalTest {
public static void main(String[] args) {
// 方式一:匿名内部类
Fu fu = new Fu() {
@Override
public int add(int a, String b) {
System.out.println("add方法" + b);
return a;
}
};
fu.add(10, "add");
// 方式二:Lambda表达式
// ()中的参数类型可省略,只有一个参数时,()也可省略
Fu fuLambda = (a, b) -> {
System.out.println("add方法" + b);
return a;
};
fuLambda.add(10, "add");
}
}
接口中,只能有一个抽象方法(并不是只能有一个方法),这时才能使用Lambda表达式。此接口即下面介绍的函数式接口。
二、函数式接口
2.1 函数式接口定义
- 在接口中只能定义一个抽象方法,其他的可以用default,static,Object里继承的方法等。
- Java8中专门提供了
@FunctionalInterface
注解来检验是否为函数式接口。
2.2 内置的函数式接口
JDK提供了大量的函数式接口,使得Lambda表达式运用更加方便、高效。特别介绍四个函数式接口。
- Consumer<T>:消费型接口,有参数无返回值。
void accept(T t)
- Supplier<T>:供给型接口,无参数有返回值。
T get()
- Function<T, R>:函数型接口,有参数有返回值。
R apply(T t)
- Predicate<T>:断言型接口。输入一个参数,返回一个boolean值。
boolean test(T t)
2.3 Lambda表达式-遍历list集合
package cn.cy.study.functionInterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class FunctionInterface {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1,2,3,4,5,6);
// 遍历list
// 方式一:匿名内部类
Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println("值为:" + integer + 1);
}
};
list.forEach(consumer);
// 方式二:Lambda表达式
Consumer<Integer> consumer2 = i -> System.out.println("值为:" + i + 1);
list.forEach(consumer2);
}
}
三、方法引用
- Lambda体可能仅调用一个已存在方法,而不做任何其它事。对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰。
- 方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,方法引用操作符是双冒号
::
- 特定使用场景,如果参数传来,不做任何处理,则能用方法引用
package cn.cy.study.functionInterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class FunctionInterface {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1,2,3,4,5,6);
// 遍历list
Consumer<Integer> consumer3 = System.out::println;
list.forEach(consumer3);
}
}
四、Stream流
Stream作为Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全不同的概念。 它是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的聚合操作或者大批量数据操作。
4.1 Stream流操作
Stream有如下三个操作步骤:
- 创建Stream:从一个数据源,如集合、数组中获取流。
- 中间操作:一个操作的中间链,对数据源的数据进行操作。
- 终止操作:一个终止操作,执行中间操作链,并产生结果。
4.2 重要的中间操作
-
filter:过滤
根据指定的条件过滤流中的元素,只保留满足条件的元素。其中传参是一个断言函数式接口,写过滤条件,若返回true则保留,返回false则过滤掉。 -
distinct:去重
对集合的元素,进行去重操作。 -
sorted:排序
默认是升序排序,要想降序排序,则可以使用.sorted((x, y) -> Integer.compare(x, y))
。 -
limit:限制个数
传递的参数是int类型的数,意思是输出前n个数据。 -
skip:跳过
传递的参数是int类型的数,意思是跳过前n个数据。 -
map:操作
可以对流中每一个元素,进行计算或转换,例如想将每一个元素值增加5,则可以使用.map(x -> x + 5)
4.3 重要的结束操作(List转Map)
- forEach:结束
对流中的每个元素执行指定的操作,处理完所有元素后才结束流。 - count:计算
计算流中元素的数量,处理完所有元素后返回数量值。 - min:最小
根据指定的比较器,找到流中的最小元素,处理完所有元素后返回最小元素。例,list.stream().max(Integer::compare)
。 - max:最大
max: 根据指定的比较器,找到流中的最大元素,处理完所有元素后返回最大元素。例,list.stream().max(Integer::compare)
。 - collect:收集
根据指定的收集器,将流中的元素进行收集操作,传递一个Collector接口的实现,处理完所有元素后返回一个结果对象。
package cn.cy.study.stream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<>();
Collections.addAll(list1, 1, 20, 6, 55, 190, 9, 1, 40, 6);
Collections.addAll(list2, 1, 1, 1, 1, 190, 9, 9, 9, 6);
Collections.addAll(list3, "1a", "a2b", "ab6c","dd3dd");
// toList()
List<Integer> collectList = list1.stream().filter(x -> x > 10).collect(Collectors.toList());
System.out.println(collectList);
// toSet()
Set<Integer> collectSet = list2.stream().map(x -> x * 2).collect(Collectors.toSet());
System.out.println(collectSet);
// toMap(): List转Map案例,第一个参数为key,第二个参数为value
Person p1 = new Person(1001L, "张三");
Person p2 = new Person(1002L, "李四");
Person p3 = new Person(1002L, "王五");
List<Person> personList = Arrays.asList(p1, p2);
List<Person> personList2 = Arrays.asList(p1, p2, p3);
// key不重复情况
Map<Long, String> collectMap = personList.stream().collect(Collectors.toMap(Person::getId, Person::getName));
// key重复情况,则取重复的第一个id
personList2.stream().collect(Collectors.toMap(Person::getId, Person::getName, (o1, o2) -> o1));
System.out.println(collectMap);
// toCollection(): 转出的类型可以自定义
TreeSet<Integer> collectTreeSet = list1.stream().sorted().collect(Collectors.toCollection(TreeSet::new));
System.out.println(collectTreeSet);
// joining(): 对字符串操作
String collectJoining = list3.stream().collect(Collectors.joining("-"));
System.out.println(collectJoining);
}
}
- sorted:排序
对流中的元素进行排序,需要保持状态来进行排序操作。 - findFirst:返回流中的第一个
返回流中的第一个元素,如果流为空则返回一个空的Optional对象。 - findAny:返回流中的任意一个
返回流中的任意一个元素,如果流为空则返回一个空的Optional对象。 - anyMatch:是否存在满足指定条件
判断流中是否存在满足指定条件的元素,一旦找到满足条件的元素,立即返回true,不再继续处理剩余元素。 - allMatch:所有元素是否都满足指定条件
判断流中的所有元素是否都满足指定条件,一旦发现有不满足条件的元素,立即返回false,不再继续处理剩余元素。
package cn.cy.study.stream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
// 创建Stream流的方式1
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3);
Stream<Integer> stream = list.stream();
// 创建Stream流的方式2
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4);
// 创建Stream流的方式3
int []arr = {1, 2, 3, 4};
IntStream stream2 = Arrays.stream(arr);
// 创建Stream流的方式4
Stream<Double> generate = Stream.generate(() -> Math.random());
// 创建Stream流的方式5
Stream<Integer> iterate = Stream.iterate(6, i -> 2 + i);
// 创建Stream流的方式6
}
}
4.4 使用Comparator.comparing进行排序
//返回 对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(类::属性一));
//返回 对象集合以类属性一降序排序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,结果进行属性一降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序
//返回 对象集合以类属性一升序 属性二升序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
//返回 对象集合以类属性一降序 属性二升序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序
//空/Null数据排序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(item -> item.属性二, Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());
//空/Null数据分组
Map<String, List<类>> map = list.stream().collect(Collectors.groupingBy(item -> {
if (item.属性一 == null || item.属性一.equals("")) {
return "";
}
return DateFormat.getDateInstance().format(item.属性一);
}))
项目中的应用: 数量降序,顺序升序来排序:
list = list.stream().sorted(Comparator.comparing(CountItem::getQuantity, Comparator.reverseOrder()).thenComparing(CountItem::getPriority)).collect(Collectors.toList());
五、Optional对象
5.1 Optional介绍
Optional存在的意义是简化为了防止空指针而进行的if-else判断的代码,提供了全局的value属性存储值。
5.2 Optional方法介绍
package cn.cy.study.stream;
import java.util.Optional;
public class OptionalTest {
public static void main(String[] args) {
Person person = null;
getPer(person);
}
public static void getPer(Person person) {
// of()
Optional<Person> optional1 = Optional.of(person);
// ofNullable()
Optional<Person> optional2 = Optional.ofNullable(person);
// orElse()和orElseGet()
// 若person为空,则创建一个Person对象
Person person1 = Optional.ofNullable(person).orElse(new Person());
Person person2 = Optional.ofNullable(person).orElseGet(Person::new);
// ifPresent()
// 若person不为空,则做ifPresent中的操作
Optional.ofNullable(person).ifPresent(x -> {
System.out.println("person对象不为null");
x.setId(111L);
});
// map()
Optional<Boolean> f = Optional.ofNullable(person).map(x -> {
x.setId(112L);
return true;
});
// 判断是否有返回值
boolean present = f.isPresent();
// 得到返回值
boolean res = f.get();
// filter()
Optional<Person> person3 = Optional.ofNullable(person).filter(x -> x.getId() > 200);
}
}
of()
:如果对象为null,直接报空指针异常ofNullable()
:如果对象为null,返回Optional.empty,不会报错orElse()
:如果传递的对象为null,则执行orElse()操作;如果传递的对象不为null,则orElse方法仍然会执行orElseGet()
:如果传递的对象为null, 则执行orElseGet()操作;如果传递的对象不为null,则orElseGet()操作不再执行ifPresent()
:如果传递的对象不为null,则进入ifPresent方法执行操作,这个方法无返回值map()
:如果传递的对象不为null,则进入map方法执行,并可以得到一个返回值isPresent()
:返回值是否为null,为null返回false,不为null返回trueget()
:map方法的返回值获取filter()
:如果返回值不为null,则执行filter中的操作,并返回