java8新特性


前言

Java 8 是一次重大的版本升级,然而存在一定的学习使用的门槛,导致可读性不强实际开发使用并不普遍。这里主要是经常忘记,记录下常用的。

一、Say Something — Author (SSA)

纵观人类历史的活动,可以理解为对物质(根据质能守恒定律,质量可转化为能量)的分类。无论是庄稼将太阳能转化为粮食,还是劳动者将庄稼收获分类。无论是采矿采石于炼金业于建筑业,还是你家洗衣做饭搞卫生,将灰尘分离出房子将能量(粮食)传递到人。都是按照人的意识收集分类着物质。说到守恒定律,唯一不守恒的是人,因为一个单位的价值,经过人会产生两个单位的价值甚至更多,这也是资本家剥削所在。回到笔者现在所做,也是将一个个现有的知识理论分类,清晰的管理。只是这个分类的对象相对抽象。


二、Java8新特性(Get To The Point言归正传)

1.函数式接口和Lambda表达式

函数式接口定义:
  1. 函数式接口可以有默认方法和静态方法。
  2. 一个函数式接口只有一个抽象方法(SAM,single abstract method)。
  3. Object 类中的 public abstract method 不会被视为单一的抽象方法。
  4. 函数式接口必须显式的使用@FunctionalInterface 注解进行修饰说明某个接口是函数式接口(原因就是上面的约束,避免破坏函数式接口导致报错)。

所以函数式接口可以自定义也可以用JDK提供的,先看下官方的常用的。

在这里插入图片描述

  1. 函数型接口
    函数型接口中的代表为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);
	}
  1. 消费型接口
    消费型接口典型的代表为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);
	}
  1. 供给型接口
    供给型接口的典型代表为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;
	}
  1. 断言型接口
    断言型接口的典型接口为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
  1. 筛选filter
List<Person> result = list.stream()
                    .filter(Person::isStudent)
                    .collect(toList());
  1. 去重distinct
List<Person> result = list.stream()
                   .distinct()
                   .collect(toList());
  1. 截取
List<Person> result = list.stream()
                   .limit(3)
                   .collect(toList());
  1. 跳过
List<Person> result = list.stream()
                   .skip(3)
                   .collect(toList());
  1. 映射
    对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给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 接口生成的异常

总结

提示:这里对文章进行总结:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值