Java8从入门到上手

简介

好处的话不言而喻,简化了开发和代码的冗余,而且很多的底层源代码也是用到了,能更好的方便我们阅读源码等。

优点:

速度更快

代码更少

强大的Stream Api

最大化减少空指针异常 Optional

之前写了一篇关于java8的博客比较详细但是有部分疏漏,本篇将补充一些

链接:https://blog.csdn.net/qq_45384482/article/details/106974229?spm=1001.2014.3001.5501

Stream

Stream是一种高效处理数据的方式,能够像sql一样处理(集合、数据源、数组)中的数据。

集合讲的是数据,Stream讲的是计算

特点:

  1. 不会自己存储元素
  2. 不会改变源对象,相反会返回一个持有结果的新Stream
  3. 操作是延迟执行的,会等到需要的结果时才会去执行

步骤;

  1. 创建
  2. 中间操作
  3. 终止操作
    在这里插入图片描述

1.1创建Stream

package com.liyingdong.demo;

import org.junit.Test;

import java.util.ArrayList;
import java.util.stream.Stream;

/**
 * @author 李瀛东
 * @site www.xiaomage.com
 * @company xxx公司
 * @create  2021-04-01 22:24
 */

public class TestBase {
    @Test
    public  void  test1(){
       //1.获取流的方式  通过collection 系列对集合的流操作 or parallelstrean()并行流
        ArrayList<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //2.通过stream 类中的静态方法 of()
        Stream<String> aa = Stream.of("aa", "bb", "cc");

        //3.创建无限流
        //迭代  开始值 、相加
         Stream.iterate(0, (x) -> x + 2)//开始
                 .limit(10)//中间
                 .forEach(System.out::println);//结束

         //4.生成
        Stream.generate(()->Math.random())
                .limit(5)//取5条数据
                .forEach(System.out::println);

    }
}

结果:
在这里插入图片描述

1.2 Stream筛选与切片

filter—接收 Lambda , 从流中排除某些元素。

limit—截断流,使其元素不超过给定数量。

skip(n) —跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补

distinct—筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Employee {
	private int id;
	private String name;
	private int age;
	private double salary;
	public String show() {
		return "测试方法引用!";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(salary);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}

}

测试代码

package com.liyingdong.demo;
import com.liyingdong.demo.entity.Employee;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author 李瀛东
 * @site www.xiaomage.com
 * @company xxx公司
 * @create  2021-04-01 22:24
 */

public class TestBase2 {

    //2. 中间操作
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "张三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );

	

    //内部迭代:迭代操作 Stream API 内部完成
    @Test
    public void test2(){
        //所有的中间操作不会做任何的处理
        Stream<Employee> stream = emps.stream()
                .filter((e) -> {
                    System.out.println("测试中间操作");
                    return e.getAge() <= 35;
                });

        //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
        stream.forEach(System.out::println);
    }

    @Test
    public void test4(){
        //满足条件的只取3个
        emps.stream()
                .filter((e) -> {
                    System.out.println("短路!"); // &&  ||
                    return e.getSalary() >= 5000;
                }).limit(3)
                .forEach(System.out::println);
    }

    @Test
    public void test5(){
        //过滤满足条件的并且跳过前面两个
        emps.parallelStream()
                .filter((e) -> e.getSalary() >= 5000)
                .skip(2)
                .forEach(System.out::println);
    }

    @Test
    public void test6(){
        //去重复要重写两个方法
        emps.stream()
                .distinct()
                .forEach(System.out::println);
    }
}

结果:

test2
在这里插入图片描述

1.3 stream映射与排序

简单来说就是通过流的方式把对象中的元素映射成一个新的元素

flatMap和map的区别简单来说就是

add()和addAll()的区别:对比如下

map -> {aa,bb,[{aa},{aac}]}

flatMap -> {aa,bb,aa,aac}

简化了遍历时的嵌套

自然排序的话是根据字母顺序,定制排序是根据compareTo规则比较

package com.liyingdong.demo.entity;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author 李瀛东
 * @site www.xiaomage.com
 * @company xxx公司
 * @create  2021-04-01 22:24
 */

public class TestBase3 {
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "张三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );

    //2. 中间操作
	/*
		映射
		map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
		flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
	 */
    @Test
    public void test1(){
        Stream<String> str = emps.stream()
                .map((e) -> e.getName());

        System.out.println("-------------------------------------------");

        List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");

        Stream<String> stream = strList.stream()
                .map(String::toUpperCase);

        stream.forEach(System.out::println);

        Stream<Stream<Character>> stream2 = strList.stream()
                .map(TestBase3::filterCharacter);

        stream2.forEach((sm) -> {
            sm.forEach(System.out::println);
        });

        System.out.println("---------------------------------------------");

        Stream<Character> stream3 = strList.stream()
                .flatMap(TestBase3::filterCharacter);

        stream3.forEach(System.out::println);
    }

    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();

        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }

        return list.stream();
    }

    /*
        sorted()——自然排序
        sorted(Comparator com)——定制排序
     */
    @Test
    public void test2(){
        List<String> list = Arrays.asList("cc", "aa", "bb");
        list.stream()
                .sorted()
                .forEach(System.out::println);

        System.out.println("------------------------------------");

        emps.stream()
                .sorted((x, y) -> {
                    if(x.getAge() == y.getAge()){
                        return x.getName().compareTo(y.getName());
                    }else{
                        //加上- 号是大到小排
                        return -Integer.compare(x.getAge(), y.getAge());
                    }
                }).forEach(System.out::println);
    }


}

test1
在这里插入图片描述

test2
在这里插入图片描述

1.4 stream查找与匹配

allMatch——检查是否匹配所有元素

anyMatch——检查是否至少匹配一个元素

noneMatch——检查是否没有匹配的元素

findFirst——返回第一个元素

findAny——返回当前流中的任意元素

count——返回流中元素的总个数

max——返回流中最大值

min——返回流中最小值

实例:

package com.liyingdong.demo.entity;

/**
 * @author 李瀛东
 * @site www.xiaomage.com
 * @company xxx公司
 * @create  2021-04-03 0:17
 */
public enum Status {
    FREE, BUSY, VOCATION;
}

实体类

package com.liyingdong.demo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Employee {

	private int id;
	private String name;
	private int age;
	private double salary;
	private Status status;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(salary);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}


}

测试案例

package com.liyingdong.demo;
import com.liyingdong.demo.entity.Employee;
import com.liyingdong.demo.entity.Status;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class TestStreamAPI2 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Status.BUSY),
			new Employee(101, "张三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	@Test
	public void test1(){
		//allMatch——检查是否匹配所有元素
			boolean bl = emps.stream()
				.allMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl);
		//anyMatch——检查是否至少匹配一个元素
			boolean bl1 = emps.stream()
				.anyMatch((e) -> e.getStatus().equals(Status.BUSY));

			System.out.println(bl1);
		//noneMatch——检查是否没有匹配的元素
			boolean bl2 = emps.stream()
				.noneMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl2);
	}
	
	@Test
	public void test2(){
		//findFirst——返回第一个元素
		Optional<Employee> op = emps.stream()
			.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
			.findFirst();
		
		System.out.println(op.get());
		
		System.out.println("--------------------------------");
		//findAny——返回当前流中的任意元素
		Optional<Employee> op2 = emps.parallelStream()//并行流
			.filter((e) -> e.getStatus().equals(Status.FREE))
			.findAny();
		
		System.out.println(op2.get());
	}
	
	@Test
	public void test3(){
		//count——返回流中元素的总个数
		long count = emps.stream()
						 .filter((e) -> e.getStatus().equals(Status.FREE))
						 .count();
		
		System.out.println(count);
		//max——返回流中最大值
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.max(Double::compare);
		
		System.out.println(op.get());
		//min——返回流中最小值
		Optional<Employee> op2 = emps.stream()
			.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		
		System.out.println(op2.get());
	}
	
	//注意:流进行了终止操作后,不能再次使用
	@Test
	public void test4(){
		Stream<Employee> stream = emps.stream()
		 .filter((e) -> e.getStatus().equals(Status.FREE));
		
		long count = stream.count();
		//终止之后操作报错
		stream.map(Employee::getSalary)
			.max(Double::compare);
	}
}

测试案例

package com.liyingdong.demo;
import com.liyingdong.demo.entity.Employee;
import com.liyingdong.demo.entity.Status;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class TestStreamAPI2 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Status.BUSY),
			new Employee(101, "张三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	@Test
	public void test1(){
		//allMatch——检查是否匹配所有元素
			boolean bl = emps.stream()
				.allMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl);
		//anyMatch——检查是否至少匹配一个元素
			boolean bl1 = emps.stream()
				.anyMatch((e) -> e.getStatus().equals(Status.BUSY));

			System.out.println(bl1);
		//noneMatch——检查是否没有匹配的元素
			boolean bl2 = emps.stream()
				.noneMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl2);
	}
	
	@Test
	public void test2(){
		//findFirst——返回第一个元素
		Optional<Employee> op = emps.stream()
			.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
			.findFirst();
		
		System.out.println(op.get());
		
		System.out.println("--------------------------------");
		//findAny——返回当前流中的任意元素
		Optional<Employee> op2 = emps.parallelStream()//并行流
			.filter((e) -> e.getStatus().equals(Status.FREE))
			.findAny();
		
		System.out.println(op2.get());
	}
	
	@Test
	public void test3(){
		//count——返回流中元素的总个数
		long count = emps.stream()
						 .filter((e) -> e.getStatus().equals(Status.FREE))
						 .count();
		
		System.out.println(count);
		//max——返回流中最大值
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.max(Double::compare);
		
		System.out.println(op.get());
		//min——返回流中最小值
		Optional<Employee> op2 = emps.stream()
			.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		
		System.out.println(op2.get());
	}
	
	//注意:流进行了终止操作后,不能再次使用
	@Test
	public void test4(){
		Stream<Employee> stream = emps.stream()
		 .filter((e) -> e.getStatus().equals(Status.FREE));
		
		long count = stream.count();
		//终止之后操作报错
		stream.map(Employee::getSalary)
			.max(Double::compare);
	}
}

1.5 stream归纳与收集

归约

reduce ——可以将流中元素反复结合起来,得到一个值。

收集

collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

案例:

package com.liyingdong.demo;

import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import com.liyingdong.demo.entity.Employee;
import com.liyingdong.demo.entity.Status;
import org.junit.Test;
public class TestStreamAPI3 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 79, 6666.66, Status.BUSY),
			new Employee(101, "张三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(104, "赵六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	
	//3. 终止操作
	/*
		归约
		reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
	 */
	@Test
	public void test1(){
		List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		
		Integer sum = list.stream()
			.reduce(0, (x, y) -> x + y);
		
		System.out.println(sum);
		
		System.out.println("----------------------------------------");
		
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.reduce(Double::sum);
		
		System.out.println(op.get());
	}

	
	//collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
	@Test
	public void test3(){
		List<String> list = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toList());
		
		list.forEach(System.out::println);
		
		System.out.println("----------------------------------");
		
		Set<String> set = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toSet());
		
		set.forEach(System.out::println);

		System.out.println("----------------------------------");
		
		HashSet<String> hs = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toCollection(HashSet::new));
		
		hs.forEach(System.out::println);
	}
	
	@Test
	public void test4(){
		//最大值
		Optional<Double> max = emps.stream()
			.map(Employee::getSalary)
			.collect(Collectors.maxBy(Double::compare));
		
		System.out.println(max.get());
		//最小值
		Optional<Employee> op = emps.stream()
			.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
		
		System.out.println(op.get());
		//总和
		Double sum = emps.stream()
			.collect(Collectors.summingDouble(Employee::getSalary));
		
		System.out.println(sum);
		//平均值
		Double avg = emps.stream()
			.collect(Collectors.averagingDouble(Employee::getSalary));
		
		System.out.println(avg);
		//统计
		Long count = emps.stream()
			.collect(Collectors.counting());
		
		System.out.println(count);
		
		System.out.println("--------------------------------------------");
		
		DoubleSummaryStatistics dss = emps.stream()
			.collect(Collectors.summarizingDouble(Employee::getSalary));
		
		System.out.println(dss.getMax());
	}
	
	//分组
	@Test
	public void test5(){
		Map<Status, List<Employee>> map = emps.stream()
			.collect(Collectors.groupingBy(Employee::getStatus));
		
		System.out.println(map);
	}
	
	//多级分组
	@Test
	public void test6(){
		Map<Status, Map<String, List<Employee>>> map = emps.stream()
			.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
				if(e.getAge() >= 60)
					return "老年";
				else if(e.getAge() >= 35)
					return "中年";
				else
					return "成年";
			})));
		
		System.out.println(map);
	}
	
	//分区
	@Test
	public void test7(){
		Map<Boolean, List<Employee>> map = emps.stream()
			.collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
		
		System.out.println(map);
	}
	
	//字符串的拼接
	@Test
	public void test8(){
		String str = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.joining("," , "----", "----"));
		
		System.out.println(str);
	}
	
	@Test
	public void test9(){
		Optional<Double> sum = emps.stream()
			.map(Employee::getSalary)
			.collect(Collectors.reducing(Double::sum));
		
		System.out.println(sum.get());
	}

	@Test
	public void test10(){
		//规约的集合
		DoubleSummaryStatistics dss = emps.stream()
				.collect(Collectors.summarizingDouble(Employee::getSalary));
		System.out.println(dss.getSum());//总和
		System.out.println(dss.getAverage());//平均值
		System.out.println(dss.getMax());//最大值

	}
}

test10

在这里插入图片描述

Optional

Optional是一个容器类,代表一个值存在或者不存在,依赖用null表示,现在Optional可以更好的表达这个概念,并且可以避免空指针异常,配合stream效果更佳哦。

方法描述
of把指定的值封装为Optional对象,如果指定的值为null,则抛出NullPointerException
empty创建一个空的Optional对象
ofNullable把指定的值封装为Optional对象,如果指定的值为null,则创建一个空的Optional对象
get如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException
orElse如果创建的Optional中有值存在,则返回此值,否则返回一个默认值
orElseGet如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值
orElseThrow如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常
filter如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象
map如果创建的Optional中的值存在,对该值执行提供的Function函数调用
flagMap如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象
isPresent如果创建的Optional中的值存在,返回true,否则返回false
ifPresent如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做

示例

of

//创建一个值为张三的String类型的Optional
Optional<String> ofOptional = Optional.of("张三");
//如果我们用of方法创建Optional对象时,所传入的值为null,则抛出NullPointerException如下图所示
Optional<String> nullOptional = Optional.of(null);

在这里插入图片描述
ofNullable

//为指定的值创建Optional对象,不管所传入的值为null不为null,创建的时候都不会报错
		Optional<String> nullOptional = Optional.ofNullable(null);
//		Optional<String> nullOptional = Optional.ofNullable("lisi");

empty

不建议使用

//创建一个空的String类型的Optional对象
Optional<String> emptyOptional = Optional.empty();

get

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.get());

在这里插入图片描述

orElse

如果创建的Optional中有值存在,则返回此值,否则返回一个默认值

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.orElse("zhangsan"));

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.orElse("李四"));

在这里插入图片描述
orElseGet

如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.orElseGet(() -> "zhangsan"));

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.orElseGet(() -> "orElseGet"));

在这里插入图片描述
orElseThrow

如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常

public static void main(String[] args) {
		Optional<String> stringOptional = Optional.of("张三");
		System.out.println(stringOptional.orElseThrow(CustomException::new));

		Optional<String> emptyOptional = Optional.empty();
		System.out.println(emptyOptional.orElseThrow(CustomException::new));


	}
	private static class CustomException extends RuntimeException {
		private static final long serialVersionUID = -4399699891687593264L;

		public CustomException() {
			super("自定义异常");
		}

		public CustomException(String message) {
			super(message);
		}
	}

在这里插入图片描述
filter

如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象

Optional<String> stringOptional = Optional.of("zhangsan");
		System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("王五"));
		stringOptional = Optional.empty();
		System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("lisi"));

在这里插入图片描述
注意Optional中的filter方法和Stream中的filter方法是有点不一样的,Stream中的filter方法是对一堆元素进
行过滤,而Optional中的filter方法只是对一个元素进行过滤,可以把Optional看成是最多只包含一个元素
的Stream。

map

如果创建的Optional中的值存在,对该值执行提供的Function函数调用

//map方法执行传入的lambda表达式参数对Optional实例的值进行修改,修改后的返回值仍然是一个Optional对象
Optional<String> stringOptional = Optional.of("zhangsan");
System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("失败"));

stringOptional = Optional.empty();
System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("失败"));

在这里插入图片描述
flagMap

flatMap(Function mapper):与 map 类似,要求返回值必须是Optional

//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。 
//但flatMap方法中的lambda表达式返回值必须是Optionl实例
Optional<String> stringOptional = Optional.of("zhangsan");
System.out.println(stringOptional.flatMap(e -> Optional.of("lisi")).orElse("失败"));

stringOptional = Optional.empty();
System.out.println(stringOptional.flatMap(e -> Optional.empty()).orElse("失败"));

在这里插入图片描述
ifPresent

判断是否包含值

Optional<Employee> op = Optional.ofNullable(new Employee());
		
		if(op.isPresent()){
			System.out.println(op.get());
		}

在这里插入图片描述

Date(新日期格式)

2.1 解决传统时间格式化的线程安全性问题

传统的SimpleDateFormat它是线程不安全的

java8新推出的日期类是线程安全且方便

都在java.time下面
在这里插入图片描述

public static void main(String[] args) throws Exception {

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
		Callable<LocalDate> task = new Callable<LocalDate>() {

			@Override
			public LocalDate call() throws Exception {
				LocalDate ld = LocalDate.parse("20161121", dtf);
				return ld;
			}

		};

		ExecutorService pool = Executors.newFixedThreadPool(10);

		List<Future<LocalDate>> results = new ArrayList<>();

		for (int i = 0; i < 10; i++) {
			results.add(pool.submit(task));
		}

		for (Future<LocalDate> future : results) {
			System.out.println(future.get());
		}

		pool.shutdown();
	}

格式可以根据自己选择
在这里插入图片描述
结果
在这里插入图片描述
案例demo

package com.liyingdong.demo;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Set;
import org.junit.Test;

public class TestOptional {

	//6.ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
	@Test
	public void test7(){
		LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
		System.out.println(ldt);

		ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
		System.out.println(zdt);
	}

	@Test
	public void test6(){
		Set<String> set = ZoneId.getAvailableZoneIds();
		set.forEach(System.out::println);
	}


	//5. DateTimeFormatter : 解析和格式化日期或时间
	@Test
	public void test5(){
//		DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");

		LocalDateTime ldt = LocalDateTime.now();
		String strDate = ldt.format(dtf);

		System.out.println(strDate);

		LocalDateTime newLdt = ldt.parse(strDate, dtf);
		System.out.println(newLdt);
	}

	//4. TemporalAdjuster : 时间校正器
	@Test
	public void test4(){
		LocalDateTime ldt = LocalDateTime.now();
		System.out.println(ldt);

		LocalDateTime ldt2 = ldt.withDayOfMonth(10);
		System.out.println(ldt2);

		LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
		System.out.println(ldt3);

		//自定义:下一个工作日
		LocalDateTime ldt5 = ldt.with((l) -> {
			LocalDateTime ldt4 = (LocalDateTime) l;

			DayOfWeek dow = ldt4.getDayOfWeek();

			if(dow.equals(DayOfWeek.FRIDAY)){
				return ldt4.plusDays(3);
			}else if(dow.equals(DayOfWeek.SATURDAY)){
				return ldt4.plusDays(2);
			}else{
				return ldt4.plusDays(1);
			}
		});

		System.out.println(ldt5);

	}

	//3.
	//Duration : 用于计算两个“时间”间隔
	//Period : 用于计算两个“日期”间隔
	@Test
	public void test3(){
		//计算时间
		Instant ins1 = Instant.now();

		System.out.println("--------------------");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
		}

		Instant ins2 = Instant.now();

		System.out.println("所耗费时间为:" + Duration.between(ins1, ins2));

		System.out.println("----------------------------------");

		LocalDate ld1 = LocalDate.now();
		LocalDate ld2 = LocalDate.of(2011, 1, 1);

		Period pe = Period.between(ld2, ld1);
		System.out.println(pe.getYears());
		System.out.println(pe.getMonths());
		System.out.println(pe.getDays());
	}

	//2. Instant : 时间戳。 (使用 Unix 元年  1970年1月1日 00:00:00 所经历的毫秒值)
	@Test
	public void test2(){
		//获取系统时间
		Instant ins = Instant.now();  //默认使用 UTC 时区
		System.out.println(ins);

		//偏移8个小时
		OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
		System.out.println(odt);

		//解析
		System.out.println(ins.getNano());

		//反解析
		Instant ins2 = Instant.ofEpochSecond(5);
		System.out.println(ins2);
	}

	//1. LocalDate、LocalTime、LocalDateTime
	@Test
	public void test1(){
		//获取本地时间
		LocalDateTime ldt = LocalDateTime.now();
		System.out.println(ldt);
        //自定义时间
		LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
		System.out.println(ld2);
        //在获取到的时间加上20年
		LocalDateTime ldt3 = ld2.plusYears(20);
		System.out.println(ldt3);
        //加上两小时
		LocalDateTime ldt4 = ld2.minusMonths(2);
		System.out.println(ldt4);

		//逐个获取
		System.out.println(ldt.getYear());
		System.out.println(ldt.getMonthValue());
		System.out.println(ldt.getDayOfMonth());
		System.out.println(ldt.getHour());
		System.out.println(ldt.getMinute());
		System.out.println(ldt.getSecond());
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值