1、java8(JDK1.8)新特性简介
Java 8 是一次重大的发行版更新,引入了大量新特性和改进,以下是 Java 8 的主要特性:
2、Lamdba表达式
Lambda 允许在代码中直接定义匿名函数,简化了对函数式编程的支持。
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
nums.stream()
.filter(num -> num % 2 == 0) // 过滤偶数
.map(num -> num * 2) // 将每个元素乘以 2
.forEach(System.out::println); // 打印结
3、函数式接口
有且仅有一个抽象方法的接口,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda就是Java中函数式编程的体现
1. Function (函数型接口)
//输入参数 + 输出返回值
Function<String,String> function = s -> s+"函数";
function.apply("test");
// 输入参数 1 + 输入参数 2 + 输出返回值
BiFunction<String, String, String> biFunction= (s1, s2) -> s1 + s2;
biFunction.apply("test","test1");
2. Predicate (断定型接口)
//输入参数 + 输出返回值 Boolean类型
Predicate<Integer> predicate =(n)->{return n>0;};
boolean flag = predicate.test(2);
3. Consumer (消费型接口) 只有参数没有返回值
//输入参数
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("a");
//输入参数1 + 输入参数2
BiConsumer<String, String> biConsumer = (s1, s2) -> System.out.println(s1 + s2);
biConsumer.accept("a","b");
4. Supplier (供给型接口) 没有参数只有返回值
//返回值
Supplier<Integer> supplier = ()-> {return 1024;};
Integer num = supplier.get();
4、方法引用和构造引用
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是Lambda表达式的另一种表现形式)
主要有有三种语法格式:
对象 :: 实例方法名
类 :: 静态方法名
类 :: 实例方法名
注意:
1、Lambda体中调用方法的参数列表与返回值,要与函数式接口中抽象方法的函数列表和返回值类型保持一致
2、若Lambda 参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,
可以使ClassName :: method
对象::实例方法
//1.1 接口 变量名 = 匿名内部类
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("consumer1");
//1.2 接口 变量名 = lambda表达式
consumer = s -> {
System.out.println(s);
};
consumer.accept("consumer2");
//1.3 接口 变量名 = 方法引用
consumer = System.out::println;
consumer.accept("consumer3");
类::静态方法
//匿名内部类写法
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
System.out.println("comparator.compare(10,20) = " + comparator.compare(10, 20));
//用lambda表达式简化
comparator = (o1, o2) -> {
return Integer.compare(o1, o2);
};
System.out.println("comparator.compare(10,20) = " + comparator.compare(10, 20));
//用方法引用简化
comparator = Integer::compare;
System.out.println("comparator.compare(10,20) = " + comparator.compare(10, 20));
类::实例方法
Person person = new Person("张三");
//匿名内部类写法
Function<Person, String> function = new Function<Person, String>() {
@Override
public String apply(Person person) {
return person.getName();
}
};
System.out.println(function.apply(person));
//用lambda表达式简化
function = p -> p.getName();
System.out.println(function.apply(person));
//用方法引用简化
function = Person::getName;
System.out.println(function.apply(person));
类::new
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return new String("abc");
}
};
System.out.println(supplier.get());
//用lambda表达式简化
supplier = () -> new String("abc");
System.out.println(supplier.get());
//用方法引用简化
supplier = String::new;
System.out.println(supplier.get());
5、Stream API
通过 Stream API 可以轻松处理集合和数组等数据结构,提高了代码的可读性和可维护性。
流(stream) 到底是什么呢?
---- 是数据渠道,用于操作数据源(集合、数组等) 所生成的元素序列
三步骤
1、创建Stream : 一个数据源(如集合、数组) 获取一个流
2、中间操作: 一个中间操作链,对数据源的数据进行处理
3、终止操作: 一个终止操作,执行中间操作链,并产生结果
5.1、创建Stream
// 1、可以通过Collection 系列接口提供的stream() 或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
// 2、通过Arrays 中的静态方法stream() 获取数组流
Employee emp = new Employee[10];
Stream<Employee> stream = Arrays.stream(emp)
// 3、通过Stream类中的静态方法of()
Stream<String> stream = Stream.of("aa","bb","cc");
// 4、 创建无限流
// 迭代
Stream<String> stream = Stream.iterate(0,(x) -> x + 2);
stream.limit(4L).forEach(System.out::println)
// 生成
Stream.generate(() -> Math.random()).limit(5L).forEach(System.out::println)
5.2、中间操作
// 筛选与切片
filter(Predicate<? super T> predicate) ----> 接收Lambda,从流中排除某些元素
limit(long maxSize) ----> 截断流,使其元素不超过给定数量
skip(long n) ----> 跳过元素,返回一个扔掉前 n 个元素的流,若流中元素不足 n 个,则返回一个空流,与limit(n) 互补
distinct() ----> 筛选,通过流中所生成的hashcode() 和 equals() 去重,需要重写这两个方法
// 示例
list.stream().filter((e) -> e.getAge > 10).limit(2L).forEach(System.out::println)
// 映射
map(Function<? super T,? extends R> mapper) ----> 接收Lambda,将元素转换成其他形式提取信息,
接收一个函数作为参数,该函数会被应用到每个元素上,并将映射成一个新的元素
flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
----> 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连成一个流
//排序
sorted() -----> 自然排序
sorted(Comparator<? super T> comparator) ----> 定制排序
5.3、终止操作
// 查找与匹配
boolean allMatch(Predicate<? super T> predicate) ----> 检查是匹配所有元素
boolean anyMatch(Predicate<? super T> predicate) ----> 检查是否至少匹配一个元素
boolean noneMathch(Predicate<? super T> predicate) ----> 检查是否没有匹配所有元素
Optional<T> findFirst() ----> 返回描述此流的第一个元素的Optional如果流为空,则返回一个空的Optional
Optional<T> findAny() ----> 返回流中的任意元素的Optional如果流为空,则返回一个空的Optional
long count() ----> 返回流中的元素的总个数
Optional<T> max(Comparator<? super T> comparator) ----> 根据提供的 Comparator返回此流的最大元素。
Optional<T> min(Comparator<? super T> comparator) ----> 根据提供的 Comparator返回此流的最小元素。
// 归约
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator) ----> 可以将流中元素反复结合起来,得到一个值
//收集
<R,A> R collect(Collector<? super T,A,R> collector) ----> 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map),但是Collectors 实用类提供了很多静态方法,可以方便的创建常见收集器实例
// 示例
List<String> ll = list.stream().collect(Collectors.toList());
并行流与顺序流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
Java8 中将并行进行了优化,我们可以很容易的对数据进行并行操作,Stream API 可以声明性的通过parallel() 与 sequential() 在并行流与顺序流之间进行切换
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
Java8 中将并行进行了优化,我们可以很容易的对数据进行并行操作,Stream API 可以声明性的通过parallel() 与 sequential() 在并行流与顺序流之间进行切换
以下是Stream API中常用的方法:
1. **filter**(Predicate predicate):过滤出所有符合条件的元素。
```java
OPtional<String> list = list.stream().filter(d->"1".equals(d.getCode()));
- map(Function function):将元素转换为另一种类型。
List<String> list = list.stream().map(T::getValue).collect(Collectors.toSet());
- flatMap(Function function):将嵌套的多个流扁平化成一个流。
- distinct():去除重复元素。
- sorted():排序。
- boxed:将基本数据类型转换为对应的包装类类型。
- peek(Consumer action):对每个元素执行指定的操作。
- limit(long maxSize):限制元素数量。
- skip(long n):跳过前 n 个元素。
- forEach(Consumer action):对每个元素执行指定的操作。
- count():计数。
- reduce(BinaryOperator accumulator):将所有元素归约成一个结果。
- collect(Collector collector):收集结果到一个集合中。
- allMatch(Predicate predicate):判断是否所有元素都符合给定条件。
- anyMatch(Predicate predicate):判断是否任何一个元素符合给定条件。
- noneMatch(Predicate predicate):判断是否没有任何元素符合给定条件。
- findFirst():返回第一个元素。
- findAny():返回任意一个元素。
6、接口中的默认方法和静态方法
在Java 8之前,接口只能定义抽象方法,所有的方法都必须由实现该接口的类来实现。但是,在Java 8中,接口可以定义默认方法和静态方法。
默认方法的语法如下:
public interface MyInterface {
default void myMethod() {
// 默认方法的实现代码
}
}
在上面的例子中,myMethod()方法是一个默认方法,它的实现代码是在接口中定义的。注意到默认方法使用了default关键字来修饰。
静态方法的语法如下:
public interface MyInterface {
static void myStaticMethod() {
// 静态方法的实现代码
}
}
7、新时间日期API
在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:
非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:
Local(本地) − 简化了日期时间的处理,没有时区的问题。
Zoned(时区) − 通过制定的时区处理日期时间。
LocalDateTime currentTime = LocalDateTime.now();// 获取当前的日期时间
DateTimeFormatter dt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime.of(LocalDate.now(),LocalTime.MIN).format(dt); //2021-08-04 00:00:00
LocalDate date1 = currentTime.toLocalDate(); // LocalDate.now() 获取年月日
Month month = currentTime.getMonth(); // 月
int day = currentTime.getDayOfMonth(); // 天
int seconds = currentTime.getSecond(); // 秒
Date与LocalDateTime、LocalDate、LocalTime互相转换
// Date 转成 LocalDateTime、LocalDate、LocalTime
Date date = new Date();
// 系统默认时区 服务器时区不对会导致转换后的时间不对
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = date.toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();
// LocalDateTime 转成 Date
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zoneId).toInstant();
Date date = Date.from(instant);
// LocalDate 转成 Date
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
Date date = Date.from(instant);
// LocalTime 转成 Date
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = LocalDateTime.of(localDate, localTime).atZone(zone).toInstant();
Date date = Date.from(instant);
8、OPtional
Optional类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在 Optional 可以更好的表达这个概念,并且可以避免空指针异常
static <T> Optional<T> Optional.of(T t) ----> 创建一个Optional实例
static <T> Optional<T> Optional.empty() ----> 创建一个空的Optional实例
static <T> Optional<T> Optional.ofNullable(T t) ----> 若t 不为null,创建Optional 实例,否则空实例
boolean isPresent() ----> 判断是否包含值
T orElseGet(Supplier<? extends T> s) ----> 如果调用对象包含值,返回该值,否则返回 s 获取的值
T osElse(T t) ----> 若果调用对象包含值,返回值,否则返回t
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。