java8新加特性
函数式接口
函数式接口在Java中是指:有且仅有一个抽象方法的接口
常用 的一些函数式接口
public static void main(String[] args) {
// Consumer 消费型接口 接受一个参数 且不返回值
Consumer<String> cs = s -> System.out.println(s);
cs.accept("我爱java");
// predicate 接受一个参数返回一个布尔值 可以用于条件判断
Predicate<String> pc = s -> s.length() > 4;
System.out.println(pc.test("我爱java"));
//Function 接受一个参数,有一个返回值
Function<String, Integer> fc = s -> s.length();
System.out.println(fc.apply("我爱java"));
//Supplier 不接受参数,但是返回一个返回值
Supplier<String> su = () -> "String str";
System.out.println(su.get());
//BinaryOperator 接受两个参数 但是只返回一个结果
BinaryOperator<String> by = (a, b) -> a + b;
System.out.println(by.apply("李白", "爱java"));
}
自定义的函数式接口
/**
* 自定义一个函数式接口
*/
public class FctDemo3 {
public static void main(String[] args) {
FctDemo3Fun fn3 = arr -> {
int min = Integer.MIN_VALUE;
for (int i : arr) {
if (i > min) {
min = i;
}
}
return min;
};
System.out.println(fn3.add(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
}
}
@FunctionalInterface
interface FctDemo3Fun {
/**
* 提供多个整数,返回和
*
* @param a int类型的一个数组
* @return 数组最大值
*/
Integer add(int[] a);
}
@FunctionalInterface注解
该注解用来检测该接口是否为函数式接口,若接口中没有抽象方法或抽象方法的个数大于1那么就会报错,反之通过
@FunctionalInterface
public interface Demo1 {
public abstract String a1 (String parm1);
}
日期
java8使用了新的日期类来替换之前的date
java.util.Date的一些缺点
-
非线程安全的类
-
糟糕的设计,每次拿到一整个时间串,需要手动去处理格式化日期
-
时区问题是date最大没办法规避的的缺点
LocalDate日期
//获取当前日期
LocalDate today = LocalDate.now();
System.out.println("当前日期:" + today);
//获取指定日期
LocalDate localDate = LocalDate.of(2024, 7, 2);
System.out.println("一个指定的日期" + localDate);
//把一个字符串解析为日期
LocalDate parse = LocalDate.parse("2024-07-02");
System.out.println("字符串转换的一个日期" + parse);
LocalDate tomorrow = today.plusDays(1);
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
System.out.println("Tomorrow: " + tomorrow);
System.out.println("Next Week: " + nextWeek);
System.out.println("Next Month: " + nextMonth);
//日期之间的差距
long daysBetween = ChronoUnit.DAYS.between(localDate, today);
System.out.println("Days between: " + daysBetween);
LocalTime时间
// 获取当前时间
LocalTime now = LocalTime.now();
System.out.println("Current Time: " + now);
// 创建特定时间
LocalTime specificTime = LocalTime.of(14, 30, 15);
System.out.println("Specific Time: " + specificTime);
// 时间运算
LocalTime inTwoHours = now.plusHours(2);
LocalTime minusMinutes = now.minusMinutes(15);
LocalDateTime
// 获取当前日期和时间
LocalDateTime now = LocalDateTime.now();
System.out.println("Current DateTime: " + now);
// 创建特定日期时间
LocalDateTime specificDateTime = LocalDateTime.of(2024, 8, 15, 14, 30);
System.out.println("Specific DateTime: " + specificDateTime);
// 日期时间运算
LocalDateTime tomorrowSameTime = now.plusDays(1);
LocalDateTime nextMonthSameDay = now.plusMonths(1);
Instant时间戳
// 获取当前时间戳
Instant now = Instant.now();
System.out.println("Current Instant: " + now);
// 创建特定时间戳
Instant epochSecond = Instant.ofEpochSecond(0);
System.out.println("Epoch Second: " + epochSecond);
// 时间戳运算
Instant later = now.plusSeconds(3600);
Duration duration = Duration.between(now, later);
Duration&Period时间之差
// Duration: 时间点之间的差 分
LocalTime start = LocalTime.of(14, 0, 0);
LocalTime end = LocalTime.of(14, 1, 50);
Duration duration = Duration.between(start, end);
System.out.println("Duration: " + duration.toMinutes() + " minutes");
// Period: 日期之间的差 小时
LocalDate startDate = LocalDate.of(2024, 1, 1);
LocalDate endDate = LocalDate.of(2025, 1, 1);
Period period = Period.between(startDate, endDate);
System.out.println("Period: " + period.getYears() + " years");
日期之间的转换
// 1.LocalDate 转 LocalDateTime
LocalDate now = LocalDate.now();
LocalDateTime dateTime = now.atTime(LocalTime.now());
// 2.LocalDateTime 转 LocalDate LocalTime
LocalDateTime now2 = LocalDateTime.now();
LocalDate localDate = now2.toLocalDate();
LocalTime localTime = now2.toLocalTime();
//3.LocalDateTime转时间戳 需要时区作为参数
LocalDateTime now3 = LocalDateTime.now();
Instant instant = now3.atZone(ZoneId.systemDefault()).toInstant();
//4.date跟新的日期api之间的转换
Date date = new Date();
Instant instant4 = date.toInstant();
Lambda表达式
被誉为Java8最大的特性。Lambda 表达式方便了函数式编程,大大简化了开发。Lambda表达式由逗号分隔的参数列表、->符号和语句块三部分组成 。当只有一个参数和只有一条语句的时候括号是可以省略的
Lambda表达式的主体,可以是一个单一表达式,也可以是一个代码块。如果是单一表达式,可以省略大括号和return关键字;如果是代码块,需要使用大括号,并显式地使用return语句(如果有返回值)。
简单demo
public static void main(String[] args) {
//无参
Runnable lm1 = () -> System.out.println("爱java");
//有参数
Consumer<String> lm2 = s -> System.out.println(s + "爱java");
//有多个参数
BinaryOperator<Integer> lm3 = (a, b) -> a + b;
}
方法&构造器的引用
通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
//实例方法引用
numbers.forEach(System.out::println);
}
Stream流
创建流的三种方式
public static void main(String[] args) {
//通过集合
ArrayList<Object> list = new ArrayList<>();
Stream<Object> stream = list.stream();
//通过数组
Integer[] integers = new Integer[]{};
Stream<Integer> stream1 = Arrays.stream(integers);
//静态方法Stream.of
Stream<String> eqwewq = Stream.of("eqwewq", "qwe");
}
示例结构
public class Demo1 {
static List<User> list = new ArrayList<>();
static {
list.add(new User(3, "李白"));
list.add(new User(1, "花木兰"));
list.add(new User(2, "千年之狐"));
list.add(new User(2, "剑舞者"));
list.add(new User(2, "青春决赛季"));
list.add(new User(2, "青春决赛季"));
}
}
过滤filter
System.out.println("过滤");
list.stream().filter(u -> u.id == 1).forEach(System.out::println);
分页limit
System.out.println("分页");
list.stream().limit(2).forEach(System.out::println);
跳过skip
System.out.println("跳过");
list.stream().skip(3).forEach(System.out::println);
去重distinct
是通过equals和hashCode,所以要重写这两个方法
list.stream().distinct().forEach(System.out::println);
中间操作map
List<String> nameList = list.stream().map(u -> u.name).collect(Collectors.toList());
排序sorted
//数组排序
int[] ints = new int[]{4, 453, 35, 6564, 75634, 3};
Arrays.stream(ints).sorted().forEach(System.out::println);
//集合中的对象排序
list.stream().map(u -> u.id).sorted(Integer :: compareTo).forEach(System.out::println);
判断Match
//是否都满足条件
boolean b = list.stream().allMatch(user -> user.id == 3);
System.out.println(b);
//是否有一个满足条件
boolean b2 = list.stream().anyMatch(user -> user.id == 3);
System.out.println(b2);
//是否都不满足
boolean b3 = list.stream().noneMatch(user -> user.id == 4);
System.out.println(b3);
返回元素
//返回第一个
System.out.println(list.stream().findFirst().get());
//返回数据个数
System.out.println(list.stream().count());
//返回最大值
System.out.println(list.stream().map(user -> user.id).max(Integer::compareTo).get());
//返回最小值
System.out.println(list.stream().map(user -> user.id).min(Integer::compareTo).get());
规约
System.out.println(list.stream().map(e -> e.name).reduce((e1,e2) -> e1 + e2));
System.out.println(list.stream().map(e -> e.name).reduce("a:", (e1,e2) -> e1 + e2));
收集
Map<String, List<User>> collect = list.stream().collect(Collectors.groupingBy(e -> e.name));
collect.keySet().forEach(System.out::println);
Optional
使用场景
public class OptDateDemo {
static Datar datar = new Datar(new User(21, "李白"));
public static void main(String[] args) {
// 不用流
if (null == datar || null == datar.getUser() || null == datar.getUser().getName()) {
throw new RuntimeException();
}
String name = datar.getUser().getName();
// 优化后
String s = Optional.ofNullable(datar)
.map(Datar::getUser)
.map(User::getName)
.orElseThrow(RuntimeException::new);
}
}
创建方式
//方式1 参数不能为null
Optional<String> 参数 = Optional.of("参数");
//方式2 参数可以为null
Optional<Object> o = Optional.ofNullable(null);
//方式三 创建一个参数为null的Optional对象
Optional<Object> empty = Optional.empty();
判空
//1. isPresent 对象是否是null;
System.out.println(opt1.isPresent());
//2.ifPresent 支持在判断的时候接受一个函数 || 如果不为空的话 名字改为***
opt1.ifPresent(u -> u.setName("***"));
获取对象
User user = new User(27, "李白");
Optional<User> opt1 = Optional.ofNullable(user);
//1.get() 获取Optional中的元素 !元素为空回报错
System.out.println(opt1.get());
//2.orElseGet() 如果获取的元素为空 返回指定的对象
Optional<User> opt2 = Optional.ofNullable(null);
opt2.orElseGet(() -> new User(52,"张三"));
//3.orElse 类似于三目运算 如果对象为空的时候返回指定的对象
Optional<User> opt3 = Optional.ofNullable(null);
User user1 = opt3.orElse(new User(32, "花木兰"));
System.out.println(user1);
//4.orElseThrow 如果为空的话抛出指定的异常
Optional<User> opt6 = Optional.ofNullable(null);
opt6.orElseThrow(RuntimeException::new);
过滤
User user = new User(27, "李白");
Optional<User> opt1 = Optional.ofNullable(user);
//过滤名称等于李白的 不为空输出ok
opt1.filter(p -> p.getName().equals("李白")).ifPresent(x -> System.out.println("OK"));
映射
public static void main(String[] args) {
User user = new User(27, "李白");
Optional<User> opt1 = Optional.ofNullable(user);
//1. isPresent 对象是否是null;
System.out.println(opt1.isPresent());
//2.ifPresent 支持在判断的时候接受一个函数 || 如果不为空的话 名字改为***
opt1.ifPresent(u -> u.setName("***"));
}