// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s) //输出Hello shawn @Test void test12(){ // 用括号 GreetingService greetService = (message) -> System.out.println("Hello " + message); greetService.sayMessage("shawn"); } interface GreetingService { void sayMessage(String message); }
函数接口是只有一个抽象方法的接口,用作 Lambda 表达式的类型。使用@FunctionalInterface注解修饰的类,编译器会检测该类是否只有一个抽象方法或接口,否则,会报错。可以有多个默认方法,静态方法。
函数接口 | 抽象接口 | 功能 | 参数 | 返回类型 |
---|---|---|---|---|
Predicate | test(T t) | 判断真假 | T | boolean |
Consumer | accept(T t) | 消费消息 | T | void |
Function | R apply(T t) | 将T映射为R | T | R |
Supplier | T get() | 生产消息 | None | T |
UnaryOperator | T apply(T t) | 一元操作 | T | T |
BinaryOperator | apply(T t,U u) | 二元操作 | (T,U) | T |
常用的方法举例
@SpringBootTest public class Java8FunctionalTests { @Test void test01(){ Predicate<Integer> predicate = x -> x > 170; Student student = new Student("shawn", 175); System.out.println("shawn的身高有超过170吗?" + predicate.test(student.getHeight())); Consumer<String> consumer = System.out::println; consumer.accept("我命由我不命天"); //Student映射成String Function<Student, String> function = Student::getName; String name = function.apply(student); System.out.println(name); Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString()); System.out.println(supplier.get()); UnaryOperator<Boolean> unaryOperator = flag -> !flag; Boolean apply2 = unaryOperator.apply(true); System.out.println(apply2); BinaryOperator<Integer> operator = (x, y) -> x * y; Integer integer = operator.apply(2, 3); System.out.println(integer); test(() -> "我是一个演示的函数式接口"); } /** * 演示自定义函数式接口使用 * * @param worker */ public static void test(Worker worker) { String work = worker.work(); System.out.println(work); } @FunctionalInterface public interface Worker { String work(); } }
Stream(流)是一个来自数据源的元素队列并支持聚合操作
1. collect(Collectors.toList())
将流转换为list。还有toSet(),toMap()等。及早求值。
@Test void test01(){ List<Student> studentList = Stream.of( new Student("shawn",165), new Student("shawn22",170)) .collect(Collectors.toList()); System.out.println(studentList); } //[Student(name=shawn, height=165), Student(name=shawn22, height=170)]
2. forEach
Stream 提供了新的方法 forEach
来迭代流中的每个数据
@Test void test02(){ Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println); }
3. filter
过滤筛选的作用。内部就是Predicate接口。惰性求值。
@Test void test03(){ List<Student> studentList = Stream.of( new Student("shawn",165), new Student("shawn22",170)) .filter(s -> s.getHeight()>165) .collect(Collectors.toList()); System.out.println(studentList); } //[Student(name=shawn22, height=170)]
3. map
转换功能,内部就是Function接口。惰性求值
@Test void test04(){ List<String> studentList = Stream.of( new Student("shawn",165), new Student("shawn22",170)) .filter(s -> s.getHeight() > 165) .map(s-> s.getName()) .collect(Collectors.toList()); System.out.println(studentList); } //[shawn22]
5. flatMap
将多个Stream合并为一个Stream。惰性求值
@Test void test05(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); Stream.of(studentList, Collections.singletonList( new Student("shawn222", 180))) .flatMap(Collection::stream) .map(s->s.getName()) .forEach(System.out::println); } //shawn //shawn22 //shawn222
6. max和min
集合中求最大值和最小值,及早求值。maxBy或者minBy就是求最大值与最小值。
@Test void test06(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); Optional<Student> student = studentList.stream() .min(Comparator.comparing(Student::getHeight)); if(student.isPresent()){ System.out.println(student.get()); } } //Student(name=shawn, height=165)
7. count
统计功能,一般都是结合filter使用,因为先筛选出我们需要的再统计即可。及早求值
@Test void test07(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); long count = studentList.stream().filter(s -> s.getHeight() > 165).count(); System.out.println(count); } //1
8. reduce
reduce 操作可以实现从一组值中生成一个值
@Test void test08(){ System.out.println(Stream.of(1, 2, 3, 4, 5).reduce(10, Integer::sum)); } //25
9. collect高级用法
//将分成true和false两个集合 @Test void test09(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); System.out.println(studentList.stream() .collect(Collectors.partitioningBy(s -> s.getName().contains("shawn")))); } //{false=[], true=[Student(name=shawn, height=165), Student(name=shawn22, height=170)]} //Collectors.groupingBy与SQL 中的 group by 操作是一样的。 @Test void test010(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); System.out.println(studentList.stream() .collect(Collectors.groupingBy(Student::getName))); } //字符串拼接 @Test void test011(){ List<Student> studentList = Arrays.asList( new Student("shawn",165), new Student("shawn22",170)); System.out.println(studentList.stream().map(Student::getName) .collect(Collectors.joining(",","[","]"))); } //[shawn,shawn22]
Optional 类是一个可以为null的容器对象。目的是为了解决空指针异常。
1. empty()
返回一个Optional
容器对象,而不是 null。建议常用⭐⭐⭐⭐
2. get()
如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException
。在判空之前,千万不要直接使用!尽量别用!⭐
//会报错java.util.NoSuchElementException: No value present @Test void test01(){ Optional<User> opt = Optional.empty(); System.out.println(opt.get()); }
3. of(T value)
创建一个Optional
对象,如果 value 是 null,则抛出 NPE。不建议用⭐⭐
4. ofNullable(T value)
同上,创建一个Optional
对象,但 value 为空时返回Optional.empty()
。推荐使用⭐⭐⭐⭐⭐
@Test void test02(){ User user = null; //输出Optional.empty,若存在就输出值 System.out.println(Optional.ofNullable(user)); //会报错java.lang.NullPointerException System.out.println(Optional.of(user)); }
5. orElse(T other)
同样是返回Optional
中包装的值,但不同的是当取不到值时,返回你指定的 default。可以用⭐⭐⭐
6. orElseGet(Supplier<? extends T> other)
如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值。推荐使用⭐⭐⭐⭐⭐
private User createNewUser() { System.out.println("user方法创建"); return new User("shawn", "男"); } @Test public void test03() { User user = null; //下面两个若是空,都会调用本地方法创建新的,但是orElse无论是否存在值,都会执行方法,另一个却不会 User result = Optional.ofNullable(user).orElse(createNewUser()); User result2 = Optional.ofNullable(user).orElseGet(this::createNewUser); System.out.println(result); System.out.println(result2); } /*结果显示 user方法创建 user方法创建 User(name=shawn, sex=男) User(name=shawn, sex=男) */
7. orElseThrow(Supplier<? extends X> exceptionSupplier)
如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常。阻塞性业务场景推荐使用⭐⭐⭐⭐
@Test public void test04() { User user = null; User result = Optional.ofNullable(user).orElseThrow(NullPointerException::new); } //输出java.lang.NullPointerException
8. isPresent()
如果创建的Optional中的值存在,返回true,否则返回false。在某些情况下很有用,但尽量不要用在 if 判断体中。可以用⭐⭐⭐
9. ifPresent(Consumer<? super T> consumer)
判断Optional
中是否有值,有值则执行 consumer,否则什么都不干。日常情况下请使用这个⭐⭐⭐⭐
10. filter(Predicate<? super T> predicate)
如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象
11. map
如果创建的Optional中的值存在,对该值执行提供的Function函数调用
@Test public void test05() { User user = new User("shawn", "男"); String sex = Optional.ofNullable(user) .map(User::getSex).orElse("女"); System.out.println(sex); } //输出男
12. flagMap
如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象,其返回的值是解除包装的值
//该方法在User类中定义 public Optional<String> getPosition() { return Optional.ofNullable(name); } @Test public void test06() { User user = new User("shawn", "男"); String sex = Optional.ofNullable(user) .flatMap(User::getPosition).orElse("女"); System.out.println(sex); } //输出男
13. filter
filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。
@Test public void test07() { User user = new User("shawn", "男"); Optional<User> result = Optional.ofNullable(user) .filter(u -> u.getName() != null && u.getSex().contains("女")); System.out.println(result); } //返回Optional.empty
14. 其他
Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。or() 方法与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象。
Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:
@Test void test01() throws Exception { // 编码 String B64 = Base64.getEncoder().encodeToString("hello?world".getBytes(StandardCharsets.UTF_8)); System.out.println(B64); // 输出为: aGVsbG8/d29ybGQ= // 解码 byte[] baseBytes = Base64.getDecoder().decode("aGVsbG8/d29ybGQ="); System.out.println(new String(baseBytes, StandardCharsets.UTF_8)); // 输出为: hello?world String urlB64 = Base64.getUrlEncoder().encodeToString("hello?world".getBytes(StandardCharsets.UTF_8)); System.out.println(urlB64); // 输出为: aGVsbG8_d29ybGQ= String mineB64 = Base64.getMimeEncoder().encodeToString("hello?world".getBytes(StandardCharsets.UTF_8)); System.out.println(mineB64); // 输出为: aGVsbG8/d29ybGQ= }
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
@Test void test(){ // 获取当前的日期时间 LocalDateTime currentTime = LocalDateTime.now(); //当前时间: 2021-08-05T12:06:15.590185 System.out.println("当前时间: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); //当前日期: 2021-08-05 System.out.println("当前日期: " + date1); Month month = currentTime.getMonth(); int month1 = currentTime.get(ChronoField.MONTH_OF_YEAR); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); //月: 8, 日: 5, 秒: 15 System.out.println("月: " + month1 +", 日: " + day +", 秒: " + seconds); LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2022); //date2: 2022-08-10T12:06:15.590185 System.out.println("date2: " + date2); LocalDate date3 = LocalDate.of(2022, Month.DECEMBER, 12); //date3: 2022-12-12 System.out.println("date3: " + date3); LocalTime date4 = LocalTime.of(22, 15); //date4: 22:15 System.out.println("date4: " + date4); // 解析字符串 LocalTime date5 = LocalTime.parse("20:15:30"); //date5: 20:15:30 System.out.println("date5: " + date5); Instant instant = Instant.now(); long currentMilli = instant.toEpochMilli(); //当前毫秒数:1628136375597 System.out.println("当前毫秒数:"+currentMilli); // 获取当前时间日期 ZonedDateTime date6 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]"); //date6: 2021-08-05 System.out.println("date6: " + date1); ZoneId id = ZoneId.of("Europe/Paris"); //ZoneId: Europe/Paris System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); //当期时区: Asia/Shanghai System.out.println("当期时区: " + currentZone); }
参考文章:
https://www.matools.com/api/java8
https://www.runoob.com/java/java8-new-features.html
https://mp.weixin.qq.com/s/8n_3VaAcwauGHgoSG1K14g