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. 终止操作
    Java8从入门到上手

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);

    }
}

结果:
Java8从入门到上手

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
Java8从入门到上手

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
Java8从入门到上手

test2
Java8从入门到上手

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

Java8从入门到上手

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);

Java8从入门到上手
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());

Java8从入门到上手

orElse

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

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

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

Java8从入门到上手
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"));

Java8从入门到上手
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);
		}
	}

Java8从入门到上手
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"));

Java8从入门到上手
注意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("失败"));

Java8从入门到上手
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("失败"));

Java8从入门到上手
ifPresent

判断是否包含值

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

Java8从入门到上手

Date(新日期格式)

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

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

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

都在java.time下面
Java8从入门到上手

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();
	}

格式可以根据自己选择
Java8从入门到上手
结果
Java8从入门到上手
案例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());
	}

}

上一篇:CentOS中环境变量和配置文件


下一篇:E - Let's Go Rolling!