java8(jdk1.8、jdk8)新特性,Lambda表达式、函数式接口、方法引用与构造器引用、Stream API、新时间日期API


前言

JAVA 8(又名jdk 1.8或者jdk8)是oracle公司2014年3月份发布的。众所周知,jdk8可以看成是jdk5发布以来最具有革命性的一代,其新增了很多新特性,为我们的编程带来了极大的便捷,现在很多公司开发都是使用的java 8。


一、Lambda表达式

Lambda 表达式, Java 8 发布的最重要新特性之一,其允许把函数作为一个方法的参数(函数作为参数传递进方法中),极大简化了代码,更具有灵活性。
Lambda表达式在java语言中引入了一种新的语法元素和操作符号:“->”,它将Lambda表达式分割为两部分。
左边:指Lambda表达式的所有参数 。
右边:指Lambda体,即表示Lambda表达式需要执行的功能。
Lambda 表达式之所以简洁,还有一个原因,就是它有“类型推断”功能。
Lambda 表达式省略掉了很多类型声明,很多参数类型都是由编译器推断得出的,表达式中无需指定类型,程序依然可以编译,这是因为javac根据程序的上下文,在后台推断出了参数类型。

1.1语法一:无参数、无返回值

//匿名内部类
Runnable r1 = new Runnable(){
    
    
            @Override
            public void run(){
    
    
                log.info("Hello World!");
            }
 };

使用Lamdba表达式简化:

 //Lambda表达式
 Runnable r2 = () -> log.info("Hello Lambda!");

1.2语法二:一个参数、无返回值

Consumer<String> consumer = new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                log.info(s);
            }
        };
        consumer.accept("Hello World!");

使用Lambda表达式简化:

 Consumer<String> consumer1 = (s) -> log.info(s);
        consumer1.accept("Hello Lambda!");

1.3语法三:只有一个参数时,参数的()可以省略

 Consumer<String> consumer1 = s -> log.info(s);
        consumer1.accept("Hello Lambda!");

使用Lambda表达式简化:

 //Lambda表达式
 Runnable r2 = () -> log.info("Hello Lambda");

1.4语法四:Lambda有两个参数,并且有返回值

BinaryOperator<Long> bo = (x,y)-> {
    
    
	log.info("实现函数接口方法!");
	return x + y;
};

1.5语法五:当Lambda体只有一条语句时,return与大括号可以省略

代码如下(示例):

BinaryOperator<Long> bo = (x,y)-> x + y;

1.6语法六:数据类型可以省略,因为编译器可以推断得出

```java
BinaryOperator<Long> bo = (Long x,Long y)-> {
    
    
	log.info("实现函数接口方法!");
	return x + y;
};

使用Lamdba表达式简化,去掉x和y的声明:

BinaryOperator<Long> bo = (x,y)-> {
    
    
	log.info("实现函数接口方法!");
	return x + y;
};

二、函数式接口

2.1什么是函数式接口

java8 之前,往接口里新加一个方法,那么所有的实现类都需要变动,都需要同步实现这个方法。
java8 给接口新增了两个关键字:default和static,使得可以往接口里添加默认方法,子类可以无需变动。

函数式接口是指一个接口内只有一个抽象方法,若干个 default 方法的接口,一般函数式接口都会使用 @FunctionalInterface 注解进行标注,来检测它是否是符合函数式接口。同时javac也会包含一条声明,说明这个接口是否符合函数式接口。
但是并不是说没有该注解就不是一个函数式接口了,该注解只是用于编译期检查,如果有多个抽象方法,那么编译将不通过。

2.2自定义函数式接口

@FunctionalInterface
public interface MyNumber{
    
    
    public double getValue();
}

2.3函数式接口中使用泛型

@FunctionalInterface
public interface MyFunc<T>{
    
    
    public T getValue(T t);
}

2.4作为参数传递Lambda表达式

public String toUpperString(MyFunc<String> mf, String str){
    
    
    public T getValue(T t);
}
//作为参数传递Lambda表达式:
String newStr = toUpperString(
		(str) -> str.toUpperCase(), "abcd");
    log.info(newStr);
}

2.5java内置四种大函数式接口

在这里插入图片描述

三、方法引用和构造器引用

3.1方法引用

当要传递给Lambda体的操作已经有实现方法,可以直接使用方法引用(注意:实现抽象方法的列表,必须要和方法引用的方法参数列表一致)
格式:使用操作符“::”将方法名和对象或者类分割开来。
有下列三种情况:
对象::实例方法
类::实例方法
类::静态方法

(x) -> System.out.println(x);
//等同于:
System.out::println;
BinaryOperator<Double> bo = (x,y) -> Math.pow(x,y);
//等同于:
BinaryOperator<Double> bo = Math::pow;
compare((x,y) -> x.equals(y),"abcd","abcd");
//等同于:
compare(String::equals,"abcd","abcd");

3.2构造器引用

格式:ClassName :: new

Function<Integer, MyClass> fun = (n) -> new MyClass(n);
//等同于:
Function<Integer, MyClass> fun = MyClass::new;

3.3数组引用

格式:type[]:: new

Function<Integer,Integer[]> fun = (num) ->new Integer[num];
//等同于:
Function<Integer,Integer[]> fun = Integer[]::new;

四、Stream API的三个步骤

Stream API是Java8中另一个最为重要的改变,还有一个是我们最开始提到的Lambda表达式。
Stream API(java.util.stream.*)大大简化了在编程中对于集合的处理,可以对集合执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API的三个步骤:
1、创建Stream:一个数据源(例如:集合、数组),获取一个流
2、中间操作:一个中间操作链,对数据源的数据进行处理
3、终止操作:一个终止操作,执行中间操作链,并产生结果
需要注意的是:流内所有的中间操作都必须遇到终端操作才会执行,否则就是一个定义,不会产生结果

4.1创建stream

4.1.1通过集合Collection创建stream

Java8中的Collection接口被扩展,提供了两个获取流的方法:

default Stream<E> stream() //返回一个顺序流
default Stream<E> parallelStream 返回一个并行流(可多线程)
//例如
List<String> list = new ArrayList<>();
Stream<String> stringStream = list.stream(); //返回一个顺序流
Stream<String> parallelStream = list.parallelStream(); //返回一个并行流(可多线程)

4.1.2通过数组Arrays创建stream

Java8中的Arrays的静态方法stream()可以获取数组流:

static <T> Stream<T> stream(T[] array) //返回一个流
//重载形式,能够处理对应基本类型的数组:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)
//例如
 Stream<String> stream1 = Arrays.stream(new String[]{
    
    "ABB", "BBC", "CCD", "XCC"});

4.1.3由值创建stream

可以使用静态方法Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。

public static<T> Stream<T> of(T... values)//返回一个流
//例如
Stream<String> stream = Stream.of("A", "B", "C", "D");

4.1.4由函数创建流:创建无限流

可以使用静态方法Stream.iterate() 和Stream.generate(), 创建无限流。

//迭代
public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f)//返回一个流
//生成
public static<T> Stream<T> generate(Supplier<T> s)//返回一个流
//例如
//迭代:遍历10个奇数
Stream.iterate(1,t->t+2).limit(10).forEach(System.out::println);//生成:生成10个随机数      
Stream.generate(Math::random).limit(10).forEach(System.out::println);

4.2stream的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值” 。

4.2.1筛选与切片

在这里插入图片描述
具体的使用方法在后面的4.4练习中可以使用到。

4.2.2映射

在这里插入图片描述

List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
Stream<String> stream = strList.stream()
			   .map(String::toUpperCase);
stream.forEach(System.out::println);

4.2.3排序

在这里插入图片描述

public class TestStreamAPI1 {
    
    
	List<Employee> emps = Arrays.asList(
			new Employee(101, "张三", 18, 9999.99),
			new Employee(102, "李四", 59, 6666.66),
			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)
	);
	/*
		sorted()——自然排序
		sorted(Comparator com)——定制排序
	 */
	@Test
	public void test2(){
    
    
		emps.stream()
			.map(Employee::getName)
			.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);
	}
}

4.3终止操作

4.3.1查找与匹配

在这里插入图片描述
在这里插入图片描述

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)
	);
	
	//3. 终止操作
	/*
		allMatch——检查是否匹配所有元素
		anyMatch——检查是否至少匹配一个元素
		noneMatch——检查是否没有匹配的元素
		findFirst——返回第一个元素
		findAny——返回当前流中的任意元素
		count——返回流中元素的总个数
		max——返回流中最大值
		min——返回流中最小值
	 */
	@Test
	public void test1(){
    
    
			boolean bl = emps.stream()
				.allMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl);
			
			boolean bl1 = emps.stream()
				.anyMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl1);
			
			boolean bl2 = emps.stream()
				.noneMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl2);
	}
	
	@Test
	public void test2(){
    
    
		Optional<Employee> op = emps.stream()
			.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
			.findFirst();
		
		System.out.println(op.get());
		
		System.out.println("--------------------------------");
		
		Optional<Employee> op2 = emps.parallelStream()
			.filter((e) -> e.getStatus().equals(Status.FREE))
			.findAny();
		
		System.out.println(op2.get());
	}
	
	@Test
	public void test3(){
    
    
		long count = emps.stream()
						 .filter((e) -> e.getStatus().equals(Status.FREE))
						 .count();
		
		System.out.println(count);
		
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.max(Double::compare);
		
		System.out.println(op.get());
		
		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);
	}
}

Employee类:

public class Employee {
    
    

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

	public Employee() {
    
    
	}

	public Employee(String name) {
    
    
		this.name = name;
	}

	public Employee(String name, int age) {
    
    
		this.name = name;
		this.age = age;
	}

	public Employee(int id, String name, int age, double salary) {
    
    
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}

	public Employee(int id, String name, int age, double salary, Status status) {
    
    
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
		this.status = status;
	}

	public Status getStatus() {
    
    
		return status;
	}

	public void setStatus(Status status) {
    
    
		this.status = status;
	}

	public int getId() {
    
    
		return id;
	}

	public void setId(int id) {
    
    
		this.id = id;
	}

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	public int getAge() {
    
    
		return age;
	}

	public void setAge(int age) {
    
    
		this.age = age;
	}

	public double getSalary() {
    
    
		return salary;
	}

	public void setSalary(double salary) {
    
    
		this.salary = 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;
	}

	@Override
	public String toString() {
    
    
		return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
				+ "]";
	}

	public enum Status {
    
    
		FREE, BUSY, VOCATION;
	}

}

4.3.2归约在这里插入图片描述

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());
	}
	
	//需求:搜索名字中 “六” 出现的次数
	@Test
	public void test2(){
    
    
		Optional<Integer> sum = emps.stream()
			.map(Employee::getName)
			.flatMap(TestStreamAPI1::filterCharacter)
			.map((ch) -> {
    
    
				if(ch.equals('六'))
					return 1;
				else 
					return 0;
			}).reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
}

4.3.3收集

在这里插入图片描述
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List 、Set 、Map) 。但是Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
在这里插入图片描述
在这里插入图片描述

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. 终止操作
	//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());
	}
}

4.4Stream API练习

4.4.1练习1

public class TestStreamAPI {
    
    
	
	/*
	  	1.	给定一个数字列表,如何返回一个由每个数的平方构成的列表呢?
		,给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。
	 */
	@Test
	public void test1(){
    
    
		Integer[] nums = new Integer[]{
    
    1,2,3,4,5};
		
		Arrays.stream(nums)
			  .map((x) -> x * x)
			  .forEach(System.out::println);
	}

	/*
	 2.	怎样用 map 和 reduce 方法数一数流中有多少个Employee呢?
	 */
	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 test2(){
    
    
		Optional<Integer> count = emps.stream()
			.map((e) -> 1)
			.reduce(Integer::sum);
		
		System.out.println(count.get());
	}
}

4.4.2练习2

public class TestTransaction {
    
    
	
	List<Transaction> transactions = null;
	
	@Before
	public void before(){
    
    
		Trader raoul = new Trader("Raoul", "Cambridge");
		Trader mario = new Trader("Mario", "Milan");
		Trader alan = new Trader("Alan", "Cambridge");
		Trader brian = new Trader("Brian", "Cambridge");
		
		transactions = Arrays.asList(
				new Transaction(brian, 2011, 300),
				new Transaction(raoul, 2012, 1000),
				new Transaction(raoul, 2011, 400),
				new Transaction(mario, 2012, 710),
				new Transaction(mario, 2012, 700),
				new Transaction(alan, 2012, 950)
		);
	}
	
	//1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
	@Test
	public void test1(){
    
    
		transactions.stream()
					.filter((t) -> t.getYear() == 2011)
					.sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
					.forEach(System.out::println);
	}
	
	//2. 交易员都在哪些不同的城市工作过?
	@Test
	public void test2(){
    
    
		transactions.stream()
					.map((t) -> t.getTrader().getCity())
					.distinct()
					.forEach(System.out::println);
	}
	
	//3. 查找所有来自剑桥的交易员,并按姓名排序
	@Test
	public void test3(){
    
    
		transactions.stream()
					.filter((t) -> t.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getTrader)
					.sorted((t1, t2) -> t1.getName().compareTo(t2.getName()))
					.distinct()
					.forEach(System.out::println);
	}
	
	//4. 返回所有交易员的姓名字符串,按字母顺序排序
	@Test
	public void test4(){
    
    
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.forEach(System.out::println);
		
		System.out.println("-----------------------------------");
		
		String str = transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.reduce("", String::concat);
		
		System.out.println(str);
		
		System.out.println("------------------------------------");
		
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.flatMap(TestTransaction::filterCharacter)
					.sorted((s1, s2) -> s1.compareToIgnoreCase(s2))
					.forEach(System.out::print);
	}
	
	public static Stream<String> filterCharacter(String str){
    
    
		List<String> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
    
    
			list.add(ch.toString());
		}
		
		return list.stream();
	}
	
	//5. 有没有交易员是在米兰工作的?
	@Test
	public void test5(){
    
    
		boolean bl = transactions.stream()
					.anyMatch((t) -> t.getTrader().getCity().equals("Milan"));
		
		System.out.println(bl);
	}
	
	
	//6. 打印生活在剑桥的交易员的所有交易额
	@Test
	public void test6(){
    
    
		Optional<Integer> sum = transactions.stream()
					.filter((e) -> e.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getValue)
					.reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
	
	
	//7. 所有交易中,最高的交易额是多少
	@Test
	public void test7(){
    
    
		Optional<Integer> max = transactions.stream()
					.map((t) -> t.getValue())
					.max(Integer::compare);
		
		System.out.println(max.get());
	}
	
	//8. 找到交易额最小的交易
	@Test
	public void test8(){
    
    
		Optional<Transaction> op = transactions.stream()
					.min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()));
		
		System.out.println(op.get());
	}

}
//交易类
public class Transaction {
    
    

	private Trader trader;
	private int year;
	private int value;

	public Transaction() {
    
    
	}

	public Transaction(Trader trader, int year, int value) {
    
    
		this.trader = trader;
		this.year = year;
		this.value = value;
	}

	public Trader getTrader() {
    
    
		return trader;
	}

	public void setTrader(Trader trader) {
    
    
		this.trader = trader;
	}

	public int getYear() {
    
    
		return year;
	}

	public void setYear(int year) {
    
    
		this.year = year;
	}

	public int getValue() {
    
    
		return value;
	}

	public void setValue(int value) {
    
    
		this.value = value;
	}

	@Override
	public String toString() {
    
    
		return "Transaction [trader=" + trader + ", year=" + year + ", value="
				+ value + "]";
	}

}
//交易员类
public class Trader {
    
    

	private String name;
	private String city;

	public Trader() {
    
    
	}

	public Trader(String name, String city) {
    
    
		this.name = name;
		this.city = city;
	}

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	public String getCity() {
    
    
		return city;
	}

	public void setCity(String city) {
    
    
		this.city = city;
	}

	@Override
	public String toString() {
    
    
		return "Trader [name=" + name + ", city=" + city + "]";
	}

}

五、新时间日期API

可以参考之前写的一篇文章,里面介绍的很详细了:
链接: java获取当前时间的方法:LocalDateTime、Date、Calendar,以及三者的比较


总结

Java8新特性给我们的日常开发带来了极大的便利,可能刚开始还不太习惯或者有点难懂,但是还是学一下比较好,就算自己不用不代表别人不用,如果在项目中看到别人使用新特性语法可能就看不太懂了,所以还是需要掌握的。
一起学习,一起加油!

猜你喜欢

转载自blog.csdn.net/sunzixiao/article/details/129489381