文章目录
前言
Java 8 是一次重大的版本升级,然而存在一定的学习使用的门槛,导致可读性不强实际开发使用并不普遍。这里主要是经常忘记,记录下常用的。一、Say Something — Author (SSA)
纵观人类历史的活动,可以理解为对物质(根据质能守恒定律,质量可转化为能量)的分类。无论是庄稼将太阳能转化为粮食,还是劳动者将庄稼收获分类。无论是采矿采石于炼金业于建筑业,还是你家洗衣做饭搞卫生,将灰尘分离出房子将能量(粮食)传递到人。都是按照人的意识收集分类着物质。说到守恒定律,唯一不守恒的是人,因为一个单位的价值,经过人会产生两个单位的价值甚至更多,这也是资本家剥削所在。回到笔者现在所做,也是将一个个现有的知识理论分类,清晰的管理。只是这个分类的对象相对抽象。
二、Java8新特性(Get To The Point言归正传)
1.函数式接口和Lambda表达式
函数式接口定义:
- 函数式接口可以有默认方法和静态方法。
- 一个函数式接口只有一个抽象方法(SAM,single abstract method)。
- Object 类中的 public abstract method 不会被视为单一的抽象方法。
- 函数式接口必须显式的使用@FunctionalInterface 注解进行修饰说明某个接口是函数式接口(原因就是上面的约束,避免破坏函数式接口导致报错)。
所以函数式接口可以自定义也可以用JDK提供的,先看下官方的常用的。
- 函数型接口
函数型接口中的代表为Function,其抽象方法位apply(), 接受有一个参数,并且有返回值。示例如下:
将字符串转化为整型
public static void main(String[] args) {
System.out.println(convert("100", (e) -> Integer.parseInt(e)));
}
public static Integer convert(String str, Function<String, Integer> fun) {
return fun.apply(str);
}
- 消费型接口
消费型接口典型的代表为Consumer,其抽象方法为accept(), 该方法仅接受一个参数,并且没有返回值。示例如下:
//打印字符串
public static void main(String[] args) {
handle("Hello world!", (s) -> System.out.println(s));
}
public static void handle(String s, Consumer<String> con) {
con.accept(s);
}
- 供给型接口
供给型接口的典型代表为Supplier,其抽象方法为get(), 该方法不接受参数,但有返回值。示例如下:
public static void main(String[] args) {
List<Integer> list = getNumList(10, () -> (int)(Math.random() *100));
for(Integer i:list) {
System.out.println(i);
}
}
//产生指定个数的整数,并将其置于集合中
public static List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for(int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
- 断言型接口
断言型接口的典型接口为Predicate,其抽象方法为test(), 接受一个参数,并返回一个布尔值。示例如下:
// 将满足条件的整数放于集合中
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 5, 7, 11, 20, 47);
List<Integer> myList = filterInt(list, (e) -> e > 3);
for(Integer i : myList) {
System.out.println(i);
}
}
public static List<Integer> filterInt(List<Integer> list, Predicate<Integer> pre ){
List<Integer> myList = new ArrayList<>();
for(Integer i : list) {
if(pre.test(i)) {
myList.add(i);
}
}
return myList;
}
lambda表达式是实现函数式接口的一个快捷方式
下面以供给型函数式接口为例
Predicate<Person> predicate = (Person person) -> {
Integer age = person.getAge();
return age >= 18;
};
可以简化为
Predicate<Person> predicate = person -> person.getAge() >= 18
- 绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型,所以参数类型省略。
- 当lambda表达式的参数个数只有一个,可以省略小括号。
- 表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。
- 被lambda表达式引用的对象,会被隐式的使用final修饰
2.Streams
概念:对集合操作非常麻烦,JDK的这个特性就是简化这个问题。
1. Java8新增stream API,可看成一个高级迭代器。
2. Collection接口中,新增非抽象的stream()方法,用来获取集合的流。
3. 流的操作是内部迭代的,传统开发中使用的for循环、迭代器属于外部迭代。
4. 流只能使用一次,使用之后,流也就会废掉。
流的使用示例
public class Test {
public static void main(String[] args) {
List<User> list = new ArrayList<>(
new User("李", 21);
new User("王", 22);
new User("曾", 23);
new User("刘", 24);
);
List<User> newList = new ArrayList<>(6);
/**
* 第一、传统方式过滤排序
*/
//遍历集合,提取大于等于22岁用户存放至newList中
for (User s : list) {
if (s.getAge() >= 18) {
newList.add(s);
}
}
//对newList按照年龄进行降序排序
newList.sort(new Comparator<User>() {
@Override
public int compare(User s1, User s2) {
//降序排序
return Integer.compare(s2.getAge(), s1.getAge());
}
});
System.out.println(newList);
/*
*第二、使用stream的写法
* 1、获取List的stream对象
* 2、使用filter方法进行过滤
* 3、使用sorted方法进行排序
* 4、使用collect方法将处理好的stream对象转换为集合对象
*/
newList = list.stream()
.filter(s -> s.getAge() >= 18)
.sorted(Comparator.comparing(User::getAge).reversed())
.collect(Collectors.toList());
System.out.println(newList);
}
}
流的API
- 筛选filter
List<Person> result = list.stream()
.filter(Person::isStudent)
.collect(toList());
- 去重distinct
List<Person> result = list.stream()
.distinct()
.collect(toList());
- 截取
List<Person> result = list.stream()
.limit(3)
.collect(toList());
- 跳过
List<Person> result = list.stream()
.skip(3)
.collect(toList());
- 映射
对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
如,获取每个人的姓名(实则是将Perosn类型转换成String类型):
List<Person> result = list.stream()
.map(Person::getName)
.collect(toList());
3.LocalDateTime API
- 获取当前时间
LocalDateTime nowDateTime = LocalDateTime.now();
// 输出 2021-01-11T16:16:49.426
- 使用自定义格式器DateTimeFormatter替换了Java8之前的SimpleDateFormat
String nowDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(“yyyy-MM-dd hh:mm:ss”));
// 输出 2021-01-11 16:17:35
4.Optional 类
-
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
-
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
-
Optional 类的引入很好的解决空指针异常。
/*
* @since 1.8 标记1.8版本后才有的
*/
public final class Optional<T> {
//内部实例化一个Optional实例,命名为EMPTY ,全局唯一的
private static final Optional<?> EMPTY = new Optional<>();
//value属性
private final T value;
//empty()方法实际上 就是返回之前那个命名为EMPTY 实例
public static<T> Optional<T> empty() {@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
//构造函数,注意是私有的,无法在外部用new访问
private Optional() {
this.value = null;
}
示例
1 public static void main(String[] args) {
2 Optional< String > fullName = Optional.ofNullable( null );
3 System.out.println( "Full Name is set? " + fullName.isPresent() );
4 System.out.println( "Full Name: " + fullName.orElseGet( () -> “[none]” ) );
5 System.out.println( fullName.map( s -> "Hey " + s + “!” ).orElse( “Hey Stranger!” ) );
6 }
结果:
Full Name is set? false
Full Name: [none]
Hey Stranger!
说明
- ifPresent()方法当Optional实例的值非空时返回true,否则返回false;
- orElseGet()方法当Optional包含非空值时返回该值,否则通过接收的function生成一个默认的;
- map()方法转换当前Optional的值,并返回一个新的Optional实例;
- orElse()方法与orElseGet方法相似,不同的是orElse()直接返回传入的默认值。
API
方法 | 描述 |
---|---|
empty | 返回一个空的 Optional 实例 |
filter | 如果值存在并且满足提供的谓词,就返回包含该值的 Optional 对象;否则返回一个空的Optional 对象 |
flatMap | 如果值存在,就对该值执行提供的 mapping 函数调用,返回一个 Optional 类型的值,否则就返回一个空的 Optional 对象 |
get | 如果该值存在,将该值用 Optional 封装返回,否则抛出一个 NoSuchElementException 异常 |
ifPresent | 如果值存在,就执行使用该值的方法调用,否则什么也不做 |
isPresent | 如果值存在就返回 true ,否则返回 false |
map | 如果值存在,就对该值执行提供的 mapping函数调用 |
of | 将指定值用 Optional 封装之后返回,如果该值为 null ,则抛出一个 NullPointerException异常 |
ofNullable | 将指定值用 Optional 封装之后返回,如果该值为 null ,则返回一个空的 Optional 对象 |
orElse | 如果有值则将其返回,否则返回一个默认值 |
orElseGet | 如果有值则将其返回,否则返回一个由指定的 Supplier 接口生成的值 |
orElseThrow | 如果有值则将其返回,否则抛出一个由指定的 Supplier 接口生成的异常 |
总结
提示:这里对文章进行总结: