Java8新特性
文章目录
前言
本文主要介绍Java8新特性以及使用用法。
提示:以下是本篇文章正文内容,下面案例可供参考
一.基本内容:
1)lambda表达式
2)函数式接口
3)方法的引用与构造器
4)Stream API
5)接口中的默认方法和静态方法
6)新时间日期API
7) 其他新特性
二.Java8新特性的简介优点
速度更快(增加了新的语法lambda表达式)
强大的Stream API
便于并行
最大化减少空指针异常 Optional
三.JAVA8学习
1.lambda表达式的语法
语法格式一:
* 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符
* 箭头操作符将 Lambda 表达式拆分成两部分:
*
* 左侧:Lambda 表达式的参数列表
* 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
语法格式二:无参数,无返回值 ,若只有一个参数小括号可以不写
* () -> System.out.println("Hello Lambda!")
语法格式三:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句 则需要加大括号
* Comparator<Integer> com = (x, y) -> {
* System.out.println("函数式接口");
* return Integer.compare(x, y);
* };
语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
* Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
* (Integer x, Integer y) -> Integer.compare(x, y);
lambda表达式需要“函数式接口的支持”
* 可以使用注解 @FunctionalInterface 修饰
* 可以检查是否是函数式接口
基本案例:
案例一:函数式接口
@FunctionalInterface
public interface MyFunction {
public String getValue(String str);
}
@Test
public void test2(){
String trimStr=strHandler("\t\t\t 学习lambda表达式",(str) -> str.trim());
System.out.println(trimStr);
String upper=strHandler("abcdefg",str->str.toUpperCase());
System.out.println(upper);
String newStr=strHandler("好好学习lambda表达式",str -> str.substring(2,5));
System.out.println(newStr);
}
/**
*
* 处理字符串
*/
public String strHandler(String str, MyFunction mf){
return mf.getValue(str);
}
public interface MyFunction2<T, R> {
public R getValue(T t1, T t2);
}
//需求:用于处理字符串
public String strHandler(String str, MyFunction mf){
return mf.getValue(str);
}
@Test
public void test3(){
op(100L, 200L, (x, y) -> x + y);
op(100L, 200L, (x, y) -> x * y);
}
//需求:对于两个 Long 型数据进行处理
public void op(Long l1, Long l2, MyFunction2<Long, Long> mf){
System.out.println(mf.getValue(l1, l2));
}
2.四大函数式 接口
JAVA8内置了四大核心函数式接口
1)、Consumer:消费型接口 void accept(T t);
2)、Supplier:供给型接口 T get();
3)、Function<T ,R>:函数型接口 R apply(T t);
4)、Predication:断言式接口 boolean test(T t);
代码案例:
/**
* 类描述: java8内置的函数式接口
*
* @author :DaShu
* @version 1.0
* @date 2021/8/6 23:19
*/
public class Execlambda3 {
//Comsumer<T> 消费型接口
@Test
public void test1(){
happy(1000,(m) ->System.out.println("消费了这么多钱"+m));
}
public void happy(double money, Consumer<Double> con){
con.accept(money);
}
//供给型接口 Supplier<T>
@Test
public void test3(){
List<Integer> list= getNumList(10,()->(int)(Math.random()*100));
list.stream().forEach(System.out::println);
}
//产生一些整数 并放入集合中
public List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list=new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n=sup.get();
list.add(n);
}
return list;
}
//函数型接口 Function<T,R>
@Test
public void test4(){
String newStr=strHadler("好好 学习 ~~啦啦啦",(str)->str.substring(0,3));
System.out.println(newStr);
}
//用于处理字符串
public String strHadler(String str,Function<String,String> fun){
return fun.apply(str);
}
//函数型接口 Function<T,R>
@Test
public void test7(){
Function<Integer,String[]> fun=(x)->new String[x];
String[] strs=fun.apply(10);
System.out.println("数组长度"+strs.length);
}
//断言型接口 Predicate<T>
@Test
public void test5(){
List<String> list= Arrays.asList("hello","JD","Lambda","www","OKKk");
filterStr(list,(s)->s.length()>3);
}
//需求:将满足条件的字符串放入集合中
public List<String> filterStr(List<String>list, Predicate<String> pre){
List<String> strList=new ArrayList<>();
strList.stream().forEach(str->{
if(pre.test(str)){
strList.add(str);
}
});
return strList;
}
}
3.方法引用与构造器引用
一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用
* (可以将方法引用理解为 Lambda 表达式的另外一种表现形式)
*
* 1. 对象的引用 :: 实例方法名
*
* 2. 类名 :: 静态方法名
*
* 3. 类名 :: 实例方法名
①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
基本案例:
public class ExecMethodRef {
//类::实例方法名
@Test
public void test4(){
BiPredicate<String,String> bp=(x,y)->x.equals(y);
BiPredicate<String,String> bp2=String::equals;
}
//类::静态方法名
@Test
public void test3(){
Comparator<Integer> com=(x,y)->Integer.compare(x,y);
Comparator<Integer> com1=Integer::compare;
}
//对象::实例方法名
@Test
public void test1(){
Consumer<String> con2=System.out::println;
con2.accept("abcdef");
}
//构造器引用
@Test
public void test5(){
Supplier<Employee> sup=()->new Employee();
//构造器引用方式
Supplier<Employee> sup2=Employee::new;//无参构造
Employee emp=sup2.get();
System.out.println(emp);
}
@Test
public void test6(){
Function<String,Employee> fun =(x) ->new Employee(x);
Function<String ,Employee> fun2=Employee::new;//一个参数
Employee emp=fun2.apply("张三");
System.out.println(emp);
}
//数组引用
@Test
public void test7(){
Function<Integer,String[]> fun=(x)->new String[x];
String[] strs=fun.apply(10);
System.out.println("数组长度"+strs.length);
}
}
4.Stream API的使用
1)Stream的三个步骤
创建 Stream: 一个数据源(如:集合、数组),获取 一个流
中间操作:一个中间操作链,对数据源的数据进行处理
终止操作:一个终止操作,执行中间操作链,并产生结果
2)中间操作 方法
筛选与切片
filter——接收 Lambda , 从流中排除某些元素。
limit——截断流,使其元素不超过给定数量。
skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
映射:
map:——接收 Lambda , 将元素转换成其他形式或提取信息
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
排序:
sorted()---自然排序(Comaparable)
sorted(Comparator com)--定制排序(Comparator)
查找与匹配:
allMatch--检查是否匹配所有元素
anyMatch--检查是否至少匹配一个元素
noneMatch--检查是否没有匹配所有元素
findFirst--返回第一个元素
count--返回流中元素的总个数
max--返回流中的最大值
min--返回流中的最小值
归约
*reduce(T identity, BinaryOperator) /reduce(BinaryOperator) --可以将流中元素反复结合起来 得到一个值
*T --起始值
收集
collect--将流转换为其他形式,比如取list的对象的某个元素 转化为一个新list,set,map等
/**
* 类描述: StreamAPI
*
* @author :DaShu
* @version 1.0
* @date 2021/8/7 18:40
*/
public class TestStreamAPI1 {
List<Employee> employee = Arrays.asList(
new Employee(102, "李四", 59, 9999.99,FREE),
new Employee(101, "张三", 18, 9999.99,FREE),
new Employee(103, "王五", 28, 3333.33,BUSY),
new Employee(104, "赵六", 8, 7777.77,BUSY),
new Employee(104, "赵六", 8, 7777.77,VOCATION),
new Employee(104, "赵六", 8, 7777.77,VOCATION),
new Employee(105, "田七", 38, 5555.55,BUSY),
new Employee(105, "田七", 38, 5555.55,FREE)
);
/** .
* 创建stream 流
* */
@Test
public void test1(){
//1.可以通过Collection 系列集合提供的stream() 或者是parallelStream()
List<String> list=new ArrayList<>();
Stream<String> stream1=list.stream();
//2.通过Arrays 中的静态方法获取数组流
Employee [] emps=new Employee[10];
Stream<Employee> stream2= Arrays.stream(emps);
//通过Stream类中的静态方法of()
Stream<String> stream3=Stream.of("aa","bb","cc");
//创建无限流
//迭代
Stream<Integer> stream4=Stream.iterate(0,(x)->x+2);
stream4.limit(10).forEach(System.out::println);
//生成
Stream.generate(()->Math.random());
}
/**
筛选与切片
filter——接收 Lambda , 从流中排除某些元素。
limit——截断流,使其元素不超过给定数量。
skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
*/
@Test
public void test2() {
Stream<Employee> stream = employee.stream().filter(emp -> emp.getAge() > 20).limit(2);
stream.forEach(System.out::println);
Stream<Employee> stream2 = employee.stream().filter(emp -> {
System.out.println("===========");
return emp.getAge() > 20;
}).limit(2);
Stream<Employee> stream3 = employee.stream().filter(emp -> emp.getAge() ==38).distinct();
stream3.forEach(System.out::println);
employee.stream().forEach(employee1 -> {
employee1.getName().toUpperCase();
});
employee.stream().map(Employee::getName).forEach(System.out::println);
}
/** .
*
* 排序 sorted()---自然排序(Comaparable)
* sorted(Comparator com)--定制排序(Comparator)
*/
@Test
public void test3(){
employee.stream().map(Employee::getAge).sorted().forEach(System.out::println);
employee.stream().sorted((x,y)->{
if(x.getAge()==y.getAge()){
return x.getName().compareTo(y.getName());
}else {
return Integer.compare(x.getAge(),y.getAge());
}
});
}
/**
*查找与匹配:
* allMatch--检查是否匹配所有元素
* anyMatch--检查是否至少匹配一个元素
* noneMatch--检查是否没有匹配所有元素
* findFirst--返回第一个元素
* count--返回流中元素的总个数
* max--返回流中的最大值
* min--返回流中的最小值
*
* */
@Test
public void test4(){
boolean b1=employee.stream().allMatch(e->e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
boolean b2=employee.stream().anyMatch(e->e.getStatus().equals(BUSY));
System.out.println(b2);
Optional<Employee> op=employee.stream().sorted((e1,e2)->
Double.compare(e1.getSalary(),e2.getSalary()))
.findFirst();
System.out.println(op.get());
Optional<Employee>op2= employee.stream().max((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));
System.out.println(op2.get());
}
/** .
*
* 归约
*reduce(T identity, BinaryOperator) /reduce(BinaryOperator) --可以将流中元素反复结合起来 得到一个值
* T --起始值
*
* map和reduce 的连接通常称为map-reduce 模式 ,因为Google 用它 来进行网络搜索而出名
* */
@Test
public void test5(){
List<Integer> list=Arrays.asList(1,2,3,4,5,6,7,8,9,20);
Integer sum=list.stream().reduce(0,(x,y)->x+y);
System.out.println(sum);
Optional<Double> sumSqlary=employee.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println("工资的累加和"+sumSqlary);
}
/**
* 收集collect--将流转换为其他形式,比如取list的对象的某个元素 转化为一个新list,set,map等
*/
@Test
public void test6(){
List<String> list=employee.stream().map(Employee::getName).collect(Collectors.toList());
list.forEach(System.out::println);
Set<String> set=employee.stream().map(Employee::getName).collect(Collectors.toSet());
set.forEach(System.out::println);
HashSet<String> hashSet=employee.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);
hashSet.forEach(System.out::println);
Map<String, Employee> hashMap=employee.stream().
collect(Collectors.toMap(Employee::getName, Function.identity(),(v1,v2)->v1));
hashMap.forEach((x,y)->System.out.println(x+"="+y));
//求总数
Long count=employee.stream().collect(Collectors.counting());
System.out.println(count);
//求平均值
Double avg=employee.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(avg);
//求总和
Double sum=employee.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
//最大值
Optional<Employee> max=employee.stream().collect(Collectors.maxBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(max.get());
//最小值F1
Optional<Employee> minEmployee=employee.stream().collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(minEmployee.get());
Optional<Double> min=employee.stream().map(Employee::getSalary).collect(Collectors.maxBy(Double::compare));
System.out.println(min.get());
}
//分区
@Test
public void test7(){
Map<Boolean, List<Employee>> map = employee.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
System.out.println(map);
}
//拼接字符串
@Test
public void test8(){
String str = employee.stream()
.map(Employee::getName)
.collect(Collectors.joining("," , "----", "----"));
System.out.println(str);
}
//分组
@Test
public void test9(){
Map<Employee.Status, List<Employee>> map = employee.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(map);
}
//多级分组
@Test
public void test10(){
Map<Employee.Status, Map<String, List<Employee>>> map = employee.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);
}
}
5.并行流和串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作,Stream API 可以
声明性地通过parallel()与 sequential在并行流和顺序流之间进行切换
Fork/Join
Fork/Join框架:就是在必要的情况下,将一个大任务,进行拆分fork 成若干个小任务(拆到不可再拆时),再将一个个小任务运算的结果进行join汇总
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nNu1i5ua-1628515398113)(C:\Users\10393\AppData\Roaming\Typora\typora-user-images\image-20210808213336096.png)]
Fork/Join框架与传统线程池的区别
采用“工作窃取”模式
当执行新的任务时,它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中
相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上
在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续执行,那么该线程就会处于等待状态,
而在fork/join框架中,如果某个子问题由于等待另外一个子问题的完成而无法继续执行,那么处理该
子问题的线程会主动寻找其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提升了性能。
6、Optional的使用
/*
* 一、Optional 容器类:用于尽量避免空指针异常
* Optional.of(T t) : 创建一个 Optional 实例
* Optional.empty() : 创建一个空的 Optional 实例
* Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
* isPresent() : 判断是否包含值
* orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
* orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
* map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
* flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
*/
@Test
public void test1(){
Optional<Employee> op=Optional.of(new Employee());
System.out.println(op.get());
}
@Test
public void test2(){
Optional<Employee> op=Optional.empty();
System.out.println(op.get());
}
@Test
public void test3(){
Optional<Employee> op=Optional.ofNullable(new Employee());
System.out.println(op.get());
}
@Test
public void test4() {
Optional<Employee> op = Optional.ofNullable(new Employee());
if (op.isPresent()) {
System.out.println(op.get());
}
}
@Test
public void test5() {
//如果op有值不为空则打印默认值,否则打印new的新值
Optional<Employee> op = Optional.ofNullable(new Employee());
Employee emp=op.orElse(new Employee(1,"张三",18,888.88, Employee.Status.BUSY));
System.out.println(emp);
}
@Test
public void test6() {
Optional<Employee> op = Optional.ofNullable(new Employee(1,"张三",18,888.88, Employee.Status.BUSY));
Optional<String>str=op.map((e)->e.getName());
System.out.println(str);
}
7、java8中允许接口有默认方法和静态方法
用default修饰
public interface MyInterface {
default String getName(){
return "呵呵呵";
}
public static void show(){
System.out.println("接口中的静态方法");/8.
}
}
8.新日期类型
SimpleDateFormat: 存在线程安全问题,故多线程中使用,需要用ThreadLocal<DateFormat>
java8中可以直接使用DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
//LocalDate LocalTime LocalDateTime
package com.huadian.mytest;
import org.junit.Test;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
public class testLocalDateTime {
//ZoneDate/ ZonedTime ZonedDateTime 指定时区
@Test
public void test8() {
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallian"));
System.out.println(ldt);
LocalDateTime ldt2 = LocalDateTime.now();
ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Europe/Tallian"));//带偏移量 与UTC标准时区差异
}
//DateTimeFormatter:格式化时间/日期
@Test
public void test6() {
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);//2021-08-09T20:52:33.957
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String strDate2 = dtf2.format(ldt);
System.out.println(strDate2);//2021年08月09日 20:58:21
LocalDateTime newLdt = ldt.parse(strDate2, dtf2);
System.out.println(newLdt);//2021-08-09T20:59:30
}
@Test
public void test5() {
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);
}
//Duration: 计算两个“时间”之间的间隔
//Period:计算两个日期之间的间隔
@Test
public void test4() {
LocalDate ld1 = LocalDate.of(2015, 1, 1);
LocalDate ld2 = LocalDate.now();
Period period = Period.between(ld1, ld2);
System.out.println(period);
System.out.println("" + period.getYears());
System.out.println("" + period.getMonths());
System.out.println("" + period.getDays());
}
@Test
public void test3() {
Instant ins1 = Instant.now();
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
Instant ins2 = Instant.now();
Duration duration = Duration.between(ins1, ins2);
System.out.println("-------------" + duration.toMillis());
LocalTime lt1 = LocalTime.now();
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
LocalTime lt2 = LocalTime.now();
System.out.println(Duration.between(lt1, lt2).toMillis());
}
//Instant :时间戳(以Unix元年:1970年1月1日00:00:00到某个时间的毫秒值)
@Test
public void test2() {
Instant ins1 = Instant.now();//默认获取UTC时区
System.out.println(ins1);//2021-08-09T10:38:22.109Z
OffsetDateTime ofd = ins1.atOffset(ZoneOffset.ofHours(8));
System.out.println("偏移后的时间" + ofd);//2021-08-09T18:38:22.109+08:00
System.out.println("时间戳" + ins1.toEpochMilli());//1628505634048
Instant ins2 = Instant.ofEpochSecond(1);
System.out.println("从元年加上 多少秒" + ins2);//1970-01-01T00:00:01Z
}
//LocalDate LocalTime LocalDateTime
@Test
public void test1() {
LocalDateTime ldt = LocalDateTime.now();
System.out.println("时间日期为" + ldt);//2021-08-09T16:02:45.253
LocalDateTime ldt2 = LocalDateTime.of(2021, 8, 9, 13, 22, 33);
System.out.println("~~~~~~" + ldt2);//2021-08-09T13:22:33
LocalDateTime ldt3 = ldt.plusYears(2);
System.out.println("加上两年" + ldt3);//2023-08-09T18:28:25.224
LocalDateTime ldt4 = ldt.minusMonths(2);
System.out.println("减去两个月" + ldt4);//2021-06-09T18:28:25.224
System.out.println("年" + ldt.getYear());//2021
System.out.println("月" + ldt.getMonthValue());//8
System.out.println("日" + ldt.getDayOfMonth());//9
System.out.println("时" + ldt.getHour());
System.out.println("分" + ldt.getMinute());
System.out.println("秒" + ldt.getSecond());
}
}
一些lambada表达式应用案例
/**
**map:
*/
employee.stream().forEach(employee1 -> {
employee1.getName().toUpperCase();
});
employee.stream().map(Employee::getName).forEach(System.out::println);
/**
* 排序 sorted()---自然排序(Comaparable)
* sorted(Comparator com)--定制排序(Comparator)
*/
@Test
public void test7(){
employee.stream().map(Employee::getAge).sorted().forEach(System.out::println);
employee.stream().sorted((x,y)->{
if(x.getAge()==y.getAge()){
return x.getName().compareTo(y.getName());
}else {
return Integer.compare(x.getAge(),y.getAge());
}
});
}
package com.huadian.exer;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 类描述:Stream API练习题
*
* @author :DaShu
* @version 1.0
* @date 2021/8/8 20:11
*/
public class ExecStream {
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) -> {
return 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"))
.sorted((t1,t2)->t1.getTrader().getName().compareTo(t2.getTrader().getName()))
.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 b=transactions.stream()
.anyMatch(t->t.getTrader().getCity().equals("Milan"));
System.out.println(b);
}
//6. 打印生活在剑桥的交易员的所有交易额
@Test
public void test6(){
Double sum= transactions.stream()
.filter(t->t.getTrader().getCity().equals("Cambridge"))
.collect(Collectors.summingDouble(t->t.getValue()));
System.out.println("第一种写法"+sum);
Optional<Integer>op= transactions.stream()
.filter(t->t.getTrader().getCity().equals("Cambridge"))
.map(Transaction::getValue)
.reduce(Integer::sum);
System.out.println("第二种写法"+op.get());
}
//7. 所有交易中,最高的交易额是多少
@Test
public void test7(){
Optional<Integer> max=transactions.stream()
.map(Transaction::getValue)
.max(Integer::compare);
System.out.println(max.get());
}
//8. 找到交易额最小的交易
@Test
public void test8(){
Optional<Transaction> minTransaction=transactions.stream()
.min((t1,t2)->Integer.compare(t1.getValue(),t2.getValue()));
System.out.println(minTransaction.get());
}
}
系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档