JAVA8 新特性
前言
随着代码的简化,高效的提升。今天我也来做一次总结。慢慢积累,来年硕果累累。
首先要学习新特性的话,我们就要先了解什么是函数式接口
- Predicate boolean test(T t); 判断型:传入T返回Boolean
- Consumer void accept(T t); 消费型:传入T无返回值
- Supplier T get(); 供给型:无需传值就能获取数据
- Function R apply(T t); 消费型供给型结合体:传入T返回R
一、JAVA8 主要引入了什么?
- Lambda表达式
- 方法引用
- Stream API
- Date Time API
- Optional 类
1.Lambda表达式使用案例
代码如下(示例):
List<String> userNames = userList.stream().map(e -> e.getUserName()).collect(Collectors.toCollection(ArrayList::new));
使用lambda的标识就是 ()加 -> 就能使用了。如果是一个参数的话,可以像上面的一样不用使用括号包裹起来。
2.方法引用
代码如下(示例):
List<String> userNames = userList.stream().map(User::getUserName).collect(Collectors.toCollection(ArrayList::new));
由此可见方法的引用就使代码更加的简洁了,可以看上面的案例。
3.Stream API
代码如下(示例):
如下是单线程流处理
List<String> userNames = userList.stream().map(User::getUserName).collect(Collectors.toCollection(ArrayList::new));
如下是并行流处理
List<String> userNames = userList.parallelStream().map(User::getUserName).collect(Collectors.toCollection(ArrayList::new));
由此可见方法的引用就使代码更加的简洁了,可以看上面的案例。
4.Date Time API
1.时间API,保证了线程安全问题。
代码如下(示例):
ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.parse("2021-01-29 10:51:25", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), ZoneId.of("Asia/Shanghai"));
大伙儿,可以直接拷贝代码进行使用,只需要将时间字符串动态传递即可,同时也可以手动设置时区。
2.Temporal 时间接口
3.Duration 对象(被final修饰了)。
5.Optional 类
这个类的功能就强大了,有两种方式。用来处理我们最常见的NullPointerException异常。
代码如下(示例):
UserBean userBean = Optional.ofNullable(user).orElse(new UserBean());
UserBean userBean = Optional.ofNullable(user).orElseGet(() -> new UserBean());
这样我们就不会出现空指针异常了。
二、创建实例
package com.hh.userservice;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable,Cloneable {
private String userName;
private Integer userAge;
public User(String userName, Integer userAge) {
this.userName = userName;
this.userAge = userAge;
}
public User(){
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return clone;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
}
三、积累常用案例
List<String> arrayList1 = new ArrayList<>();
arrayList1.add("1");
arrayList1.add("2");
arrayList1.add("3");
List<String> arrayList2 = new ArrayList<>();
arrayList2.add("2");
arrayList2.add("4");
1.两(N)个集合,获取交集功能
第一种方式,通过流中的过滤器,加上集合内部的方法引用。
List<String> stringArrayList = arrayList1.stream().filter(arrayList2::contains).collect(Collectors.toCollection(ArrayList::new));
第二种方式,更加高级一点,扁平化处理集合,加上流中的过滤功能。
List<String> collect = Stream.of(arrayList1, arrayList2).flatMap(Collection::stream).distinct().collect(Collectors.toCollection(ArrayList::new));
第三种方式,通过集合中的retainAll方法实现(切记有坑哦)。
如下代码执行后,切记只能获取arrayList1中的集合,因为arrayList2集合的数据不会变,不会被移除。
System.out.println(arrayList1); // [1, 2, 3]
System.out.println(arrayList2);[2, 3]
boolean b = arrayList1.retainAll(arrayList2);
System.out.println(b); // true
System.out.println(arrayList1); // [2, 3]
System.out.println(arrayList2); // [2, 3]
如下代码执行后可以随意获取那个集合中的数据。
boolean b1 = arrayList1.retainAll(arrayList2);
boolean b2 = arrayList2.retainAll(arrayList1);
如下源码:
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
2.两(N)个集合,获取差集功能
List<String> array1 = arrayList1.stream().filter(e -> !arrayList2.contains(e)).collect(Collectors.toCollection(ArrayList::new));
// arrayList.forEach(System.out::println);
List<String> array2 = arrayList2.stream().filter(e -> !arrayList1.contains(e)).collect(Collectors.toCollection(ArrayList::new));
strings.forEach(System.out::println); //结果:4 注意:获取的值是当前arrayList2集合的差集。arrayList1集合内的数据不会被加载。
List<String> newList = Stream.of(array1, array2).flatMap(Collection::stream).distinct().collect(Collectors.toCollection(ArrayList::new));
3.两(N)个集合,获取并集功能
List<String> arrayList = Stream.of(arrayList1, arrayList2).flatMap(Collection::stream).distinct().collect(Collectors.toCollection(ArrayList::new));
System.out.println(arrayList); //结果: [1, 2, 3, 4]
4.使用toMap需要注意的
1.在这边通过Collectors工具类,将流中的数据收集,将数据转换成功Map类型的数据。在这边我需要强调一下,首先我们这里有三个参数,第一个参数也就是Map的Key,第二个参数是我们的Value,第三个参数最为重要,(如果相同的话就会报错,如果没有报错的话确实没有任何问题的),表示如果Key相同的话,会将老的数据返回,新的Key被覆盖。
List<User> userList = getUserList();
Map<String, Integer> map = userList.stream().collect(Collectors.toMap(User::getUserName, User::getUserAge, (oldValue, newValue) -> oldValue));
5.Lamdba遍历Map集合的一种方式
1.高大上,比entrySet(),keySet()方式简洁,但是本质上还是enterSet()方式遍历的。
map.forEach((key, value) -> {
System.out.print(key);
System.out.print(value);
System.out.println();
});
6.sorted方法内的比较器Comparator使用案例
1.使用比较器的方式对集合进行排序。代码非常的简洁明了。
List<User> collect1 = userList1.parallelStream().sorted(Comparator.comparing(User::getUserAge)).collect(Collectors.toCollection(ArrayList::new));
2.使用比较器中的reversed() 方法实现数组数据反转功能。
List<User> collect2 = userList1.parallelStream().sorted(Comparator.comparing(User::getUserAge).reversed()).collect(Collectors.toCollection(ArrayList::new));
3.使用一个比较冷门的方法Comparator.nullsFirst() 用来处理空对象,防止NPE。
List<User> userList = new ArrayList<>();
userList.add(new User("zhangsan",19));
userList.add(new User("lisi",39));
userList.add(new User("wangwu",26));
userList.add(new User("maliu",26));
userList.add(new User("maliu",26));
userList.add(null);
List<User> collect = userList.parallelStream().sorted(Comparator.nullsFirst(Comparator.comparing(User::getUserAge))).collect(Collectors.toCollection(ArrayList::new));
4.使用比较器实现多个字段进行比较方式。(链式编程之thenComparing()方法)
List<User> collect3 = userList1.parallelStream().sorted(Comparator.comparing(User::getUserName).thenComparing(User::getUserAge)).collect(Collectors.toCollection(ArrayList::new));
总结
简单,是一种态度。不争,顺其自然,不求,一切随缘,不气,心胸开阔,不怨,心怀感激。放下计较矛盾,轻松地活;看淡金钱财富,知足地过。远离是是非非,不理流言蜚语。简单的人生,简单地活;简单的日子,简单地过。