Java8新特性的学习

Java8新特性的学习

- Lambda表达式

-方法引用

-JAVA8内置四大核心函数式接口

-Stream API
-Optional容器
-default修饰的方法
-新时间日期API

1. Lambda表达式

Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可传递的代码(将代码像数据一样进行传递),可写出更简洁,更灵活的代码,使JAVA语言表达能力得到了提升。
- Lambda表达式引入了一个 叫箭头操作符或Lambda操作符 ->
- Lambda表达式 拆分成两部分 :
- 左侧: Lambda表达式的参数列表
- 右侧:Lambda表达式中所需执行的功能 即Lambda体

2.方法引用

若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可理解为方法引用是Lambda表达式的另一种表现形式)
主要有三种语法格式:
  • ①注意:Lambda体中调用方法的参数列表与返回值类型,要与函数式接口的参数列表 返回值类型一致!
2.1. 语法一 ( 对象::实例方法 )
Consumer<String> con = (x) -> System.out.println(x);
Consumer<String> con = System.out::println;
con.accept("你好贱");

Emp emp = new Emp();
Supplier<String> supplier = () -> emp.getName();
Supplier<String> supplier = emp::getName;
System.out.println(supplier.get());
2.2.语法二 ( 类::静态方法 )
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
Comparator<Integer> com = Integer::compare;
int num = com.compare(4, 2);
System.out.println(num);

在这里插入图片描述

2.3.语法三 ( 类::实例方法 )
  • ②注意:对于语法三格式有特殊要求 若Lambda参数列表第一个参数是 调用该实例方法的调用对象 而第二个参数是是实例方法的参数列表参数 可以使用此格式
BiPredicate<String, String> bp = (x,y) -> x.equals(y);
BiPredicate<String, String> bp = String::equals;
System.out.println(bp.test("打架机", "打架机"));
2.4语法四(ClassName::new)
Supplier<Emp> supplier = () -> new Emp();
Supplier<Emp> supplier2 = Emp::new;
System.out.println(supplier2.get());

Function<String, Emp> function = (str) -> new Emp(str);
Function<String, Emp> function1 = Emp::new;
System.out.println(function1.apply("黎智健"));

BiFunction<String, Integer, Emp> biFunction = Emp::new;
System.out.println(biFunction.apply("黎智健", 28));

2.5语法五(Type[]::new)
Function<Integer, String[]> function = (num) -> new String [num];
Function<Integer, String[]> function1 = String[]::new;
System.out.println(function1.apply(10).length);

3. JAVA8内置四大核心函数式接口

接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface 修饰 此注解可检查接口是否为 函数式接口
3.1 Consumer ---- 消费型接口
void accept(T t);
/**
 * Consumer 消费型接口
 */
@Test
public void test() {
	happy(2000, (m) -> System.out.println("我消费了"+m+"美元"));
}

public void happy(double money,Consumer<Double> consumer) {
	consumer.accept(money);
}
3.2.Supplier ---- 供给型接口
T get();
/**
 * Supplier 供给型接口
 */
@Test
public void test1(){
	List<Integer> list = randomCreateNumByInterface(10, () -> (int) (Math.random() * 100 ) );
	list.forEach(System.out::println);
}

public List<Integer> randomCreateNumByInterface(int num , Supplier<Integer> supplier){
	List<Integer> lists = new ArrayList<>();
	for (int i = 0; i < num; i++) {
		lists.add(supplier.get());
	}
	return lists;
}
3.3 Function<T,R> ---- 函数型接口
R apply(T t);
/**
 * Function<T,R> 函数型接口
 */
@Test
public void test2() {
	String trimStr = solveStr("\t\t\t\t\t帮我去掉空格", (str) -> str.trim());
	String subStr1 = solveStr("帮我截取一段其中的一段文字", (str) -> str.substring(0, 3));
	System.out.println(trimStr);
	System.out.println(subStr1);
}

public String solveStr(String str , Function<String, String> function) {
	return function.apply(str);
}
3.4 Predicate 断言型接口
boolean test(T t);
/**
 * Predicate<T> 断言型接口
 */
@Test
public void test3() {
	List<String> lists = Arrays.asList("范德萨发生","胜多负少","防守打法","认为如果");
	List<String> templist = filter(lists, (str) -> str.length() > 4 );
	templist.forEach(System.out::println);
}

public List<String> filter(List<String> list,Predicate<String> predicate){
	List<String> temp = new ArrayList<>();
	for(String str : list) {
		if(predicate.test(str)) {
			temp.add(str);
		}
	}
	return temp;
}
3.5其他的函数式接口

在这里插入图片描述

4.Stream API

4.1流是什么?
是数据渠道,用于操作数据源(集合,数组等)所产生的元素序列。
集合讲的是数据,流讲的是计算
注意
①Stream自己不会存储元素的
②Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
③Stream操作是延迟执行的,这意味他们会等到需要结果的时候才执行
4.2Stream的操作的三个步骤
- 创建Stream
一个数据源(如 集合、数组),获取一个流
- 中间操作
一个中间操作链,对数据源的数据进行处理
- 终止操作
一个终止操作,执行中间操作链,并产生结果
1.创建流
  1. 可通过Collection集合提供的 stream()/串行流 和 parallelStream()/平行流创建流
List<String> lists = new ArrayList<>();
Stream<String> stream = lists.stream();
Stream<String> parallelStream = lists.parallelStream();
  1. 通过Arrays 中的静态方法 stream() 获取数组流
Emp [] emparr = new Emp[10];
Stream<Emp> stream1 = Arrays.stream(emparr);
  1. 通过Stream类静态方法of()
Stream<String> stream3 = Stream.of("abf","gdu","tew");
  1. 创建无限流 / 迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x+2);
iterate.limit(10).forEach(System.out::println);
  1. 创建无限流 / 生成
Stream.generate(() -> Math.random()).limit(20).forEach(System.out::println);
2.中间操作
  1. 筛选与切片
方法名作用
filter接受Lambda,从流中排除某种元素
limit截断流,使其流不超过给定数量
skip(n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流, 【与limit(n) 互补】
distinct筛选,通过流所生成元素的hashCode() 和 equals() 去除重复元素
1.filter
Stream<Emp> filter = emps.stream().filter( (e) -> e.getAge() > 18 );
filter.forEach(System.out::println);

补充:上边提到的 ‘延迟加载’
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为‘惰性求值’

Stream<Emp> filter = emps.stream().filter( (e) -> {
System.out.println("延迟加载。。。。");
return e.getAge() > 18;
});
filter.forEach(System.out::println);

注意:①找到满足条件的数据的指定条数 就不往下迭代。

2.limit
Stream<Emp> filter = emps.stream().filter( (e) -> e.getAge() > 18 );
filter.limit(1).forEach(System.out::println);
3.skip
Stream<Emp> filter = emps.stream().filter( (e) -> e.getAge() > 18);
filter.skip(2).forEach(System.out::println);
  1. 映射
方法名作用
map接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的对象
flatMap接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流这两个区别就是当提取的是一个 流对象 map只能在流对象 装 提取出的流对象 而 flatMap可以将提取的所有流对象 变为一个流对象和add() addAll() 很像
1.map
Stream<Emp> map = emps.stream().map((emp) -> {emp.setAge(12); return emp;});
map.forEach(System.out::println);

List<String> asList = Arrays.asList("wreew","dfa","sdfs","sdfs");
Stream<String> map2 = asList.stream().map((x) -> x.toUpperCase());
map2.forEach(System.out::println);

emps.stream().map(Emp::getName).forEach(System.out::println);
1.map
List<String> asList = Arrays.asList("wreew","dfa","sdfs","sdfs");
Stream<Stream<Character>> map = asList.stream().map(TestStreamAPI2::fileterToCharacter);
map.forEach( (stream) -> stream.forEach(System.out::println) );

public static Stream<Character> fileterToCharacter(String str){
List<Character> lists = new ArrayList<Character>();
for(char c : str.toCharArray()) {
	lists.add(c);
}
return lists.stream();
}

2.flatmap
List<String> asList = Arrays.asList("wreew","dfa","sdfs","sdfs");
Stream<Character> flatMap = asList.stream().flatMap(TestStreamAPI2::fileterToCharacter);
flatMap.forEach(System.out::println);

public static Stream<Character> fileterToCharacter(String str){
List<Character> lists = new ArrayList<Character>();
for(char c : str.toCharArray()) {
	lists.add(c);
}
return lists.stream();
}

在这里插入图片描述

f l a t m a p ( ) 是 扁 平 化 映 射 , 不 单 只 是 s t r e a m 流 的 拼 接 , 还 有 S t r i n g 数 组 或 L i s t 集 合 也 是 可 以 进 行 扁 平 化 映 射 的 \color{#FF0000}{flatmap()是扁平化映射,不单只是stream流的拼接,还有String数组或List集合也是可以进行扁平化映射的} flatmap()streamStringList

  1. 排序
方法名作用
sorted()自然排序(Comparable)
sorted(Comparator com)定制排序(Comparator)
1.sorted
List<String> asList = Arrays.asList("wreew","dfa","sdfs","sdfs");
asList.stream().sorted().forEach(System.out::println);

2.sorted(Comparator com)
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);
3.Stream终止操作
  1. 查找与匹配
方法名作用
allMatch检查是否匹配所有的元素
anyMatch检查是否至少匹配一个元素
noneMatch检查是否没有匹配的所有元素
findFirst返回第一个元素
findAny返回当前流任意一个元素 (如果是并行流返回的是第一个 如果是串行流返回的是随机任意一个)
count返回流中元素的总个数
max返回流中最大值
min返回流中最小值
1.allMatch
boolean allMatch = emps.stream().allMatch( (emp) -> emp.getStatus().equals(Status.BUSY) );
System.out.println(allMatch);

2.anyMatch
boolean anyMatch = emps.stream().anyMatch( (emp) -> emp.getStatus().equals(Status.BUSY) );
System.out.println(anyMatch);

3.noneMatch
boolean noneMatch = emps.stream().noneMatch( (emp) -> emp.getStatus().equals(Status.BUSY) );
System.out.println(noneMatch);
4.findFirst
Optional<Emp> findFirst = emps.stream().findFirst();
System.out.println(findFirst.get());

5.findAny
Optional<Emp> findAny = emps.stream().filter( (emp) -> emp.getSalary() > 2500 ).findAny();
System.out.println(findAny.get());

(parallelStream是并行流  多个线程同时找谁找到就算谁的)
Optional<Emp> findAny1 = emps.parallelStream().filter( (emp) -> emp.getSalary() > 2500 ).findAny();
System.out.println(findAny1.get());
6.count
long count = emps.stream().count();
System.out.println(count);
7.max
Optional<Emp> max = emps.stream().max( (emp1,emp2) -> Double.compare(emp1.getSalary(), emp2.getSalary()) );
System.out.println(max.get());

8.min
Optional<Double> min = emps.stream().map(Emp::getSalary).min(Double::compareTo);
System.out.println(min.get());
  1. 归约

(BinaryOperator extends -> BiFunction extends -> Function)

方法名作用
reduce(T identify, BinaryOperator)identify是起始值
reduce(BinaryOperator)

①注意: x=0; y=stream里面的元素 x = x + y;

List<Integer> lists = Arrays.asList(1,2,34,57,8,4);
Integer reduce = lists.stream().reduce(0, (x,y) -> x+y);
System.out.println(reduce);
  1. 收集
方法名作用
collect将流转化为其他形式。接受一个Collector接口的实现,用于给Stream中的元素做汇总的方法
Collectors类里有很多收集方法 和 收集方式
List<String> list = emps.stream().map(Emp::getName).collect(Collectors.toList());
list.forEach(System.out::println);
 
Set<String> listset = emps.stream().map(Emp::getName).collect(Collectors.toSet());
listset.forEach(System.out::println);

HashSet<String> collect = emps.stream().map(Emp::getName).collect(Collectors.toCollection(HashSet::new));
collect.forEach(System.out::println);

String collect = emps.stream().map(Emp::getName).collect(Collectors.joining(",","===","+++"));  中间分隔符  首部  尾部
System.out.println(collect);
总条数
Long collect = emps.stream().collect(Collectors.counting());
System.out.println(collect);

平均值
Double collect2 = emps.stream().collect(Collectors.averagingDouble(Emp::getSalary));
System.out.println(collect2);

最大值
maxBy·············
最小值
minBy·············

分组
Map<Status, List<Emp>> collect = emps.stream().collect(Collectors.groupingBy(Emp::getStatus));
System.out.println(collect);

多级分组    分组下再次分组  
Map<Status, Map<String, List<Emp>>> collect = emps.stream().collect(Collectors.groupingBy(Emp::getStatus, Collectors.groupingBy( (emp) -> {
if(emp.getAge() < 18) {
	return "青少年";
}else if(emp.getAge() > 18 && emp.getAge() < 40) {
	return "中年组";
}else {
	return "老年组";
}
} )));
System.out.println(collect);

分区  满足条件的分个区    不满足条件的分个区
Map<Boolean, List<Emp>> collect = emps.stream().collect(Collectors.partitioningBy( (emp) -> emp.getSalary() >3000 ));
System.out.println(collect);

获取总条数 总和 平均值 最大值 最小值 其它方式
DoubleSummaryStatistics collect = emps.stream().collect(Collectors.summarizingDouble(Emp::getSalary));
System.out.println(collect.getCount());
System.out.println(collect.getAverage());
System.out.println(collect.getSum());
System.out.println(collect.getMax());
System.out.println(collect.getMin());
5.Optional 容器类的常用方法
方法名作用
Optional.of(T t)创建一个Optional实例
Optional.empty()创建一个空的Optional实例
Optional.ofNullable(T t)若t为不为null,创建Optional实例,t若为null,创建空实例
isPresent()判断是否包含值
orElse(T t)如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s)如果调用对象包含值,返回该值,否则返回s获取的值
map(Function f)如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
flatMap(Function mapper)与map类似,要求返回值必须是Optional
5.1 Optional.of(T t) ①注意:如果 T 传的是null 会报空指针异常NullPointException
Optional<Emp> of = Optional.of(new Emp());
System.out.println(of.get());
5.2 Optional.empty() ①注意:空的Optional实例是get()方法获取不了的 会报java.util.NoSuchElementException: No value present
Optional<Emp> empty = Optional.empty();
System.out.println(empty.get());
5.3 Optional.ofNullable(T t) 和 5.4 isPresent() 和 5.5 orElse(T t)
Optional<Emp> ofNullable = Optional.ofNullable(null);
if(ofNullable.isPresent()) {
	System.out.println(ofNullable.get());
}
Emp emp = ofNullable.orElse(new Emp());
System.out.println(emp);
5.6 orElseGet(Supplier s)
Optional<Emp> of = Optional.ofNullable(null);
Emp orElseGet = of.orElseGet( () -> new Emp());
System.out.println(orElseGet);
5.7 map(Function f)
Optional<Emp> ofNullable = Optional.ofNullable(new Emp("李志坚", 14, 88888888, Status.FREE));
Optional<String> str = ofNullable.map(Emp::getName);
System.out.println(str.get());
6.default关键字
这个default和访问控制权的default不一样,这个default关键字只能修饰接口中的默认方法
权限类内同包不同包子类不同包非子类
private×××
default××
protected×
public
① 在java8新增了 ,在接口中可以有默认方法 用default修饰的方法 可以有方法体,然而default方法不会影响函数式接口。
② 并且接口中可以写静态方法和在类中的静态方法用法没区别
这样个default关键字优点
1 避免子类代码重复

当多个类实现一个接口的某个方法时,如果方法的具体实现代码相同,那么就会造成代码重复问题。接口增强相当于把公共的代码提取出来,放入接口定义中,实现类不需要重写该方法,解决了实现该接口的子类代码重复的问题。

2 克服单继承的缺陷

接口中可以定义static或default类型这两种有具体实现的方法,减少了接口和抽象类之间的区别。对于子类而言,抽象类只能单继承,接口可以实现多个。

7.新时间日期API
以前的时间日期API存在线程安全问题
作用
DateTimeFormatter格式化时间/日期
静态方法:
方法作用
ofPattern()指定时间格式
实例方法:
方法作用
format格式化时间对象
LocalDate parse = LocalDate.parse("20181222", DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(parse);
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String format = ofPattern.format(LocalDate.now());
System.out.println(format);
7.1. JAVA8中 给人读的时间有三个
作用
LocalDate本地日期
LocalTime本地时间
LocalDateTime本地日期时间
上面的三个类都有这两个静态方法API
方法作用
now()获取当前日期/时间
of(…)指定 数据 创建LocalDateTime对象
now()
LocalDate date = LocalDate.now();
System.out.println(date);
LocalTime time = LocalTime.now();
System.out.println(time);
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime);
of(…)
LocalDate date = LocalDate.of(2020,5,9);
System.out.println(date);
LocalTime time = LocalTime.of(22,48,22);
System.out.println(time);
LocalDateTime dateTime = LocalDateTime.of(date,time);
System.out.println(dateTime);
上面的三个类都有这两个实例方法API
方法作用
plus…()给调用对象 加
minus…()给调用对象 减
get…()获取调用对象的 指定数据
with…()指定数据到月或日
1.plus..()

LocalDateTime now = LocalDateTime.now();
LocalDateTime plusDays = now.plusDays(22);
System.out.println(plusDays);
2.minus...()

LocalDateTime now = LocalDateTime.now();
LocalDateTime plusDays = now.minusDays(22);
System.out.println(plusDays);
3.get...()

LocalDateTime now = LocalDateTime.now();
System.out.println(now.getYear());
4.with...()

LocalDate withDayOfMonth = LocalDate.now().withDayOfMonth(12);
System.out.println(withDayOfMonth);
7.2. Instant 时间戳
作用
Instant时间戳(以Unix 元年: 1970年1月1日00:00:00到某个时间之间的毫秒值)
静态方法:
方法作用
now()默认获取UTC时区
1.now()

Instant now = Instant.now();
System.out.println(now);
实例方法:
方法作用
atOffset(ZoneOffset.of…())设置时区时差
toEpochMilli()转化成毫秒
getEpochSecond()转化成秒
getNano()转化成纳秒
1.atOffset(ZoneOffset.of...())

OffsetDateTime atOffset = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(atOffset);
1.toEpochMilli()
2.getEpochSecond()
3.getNano()

System.out.println(now.toEpochMilli());
System.out.println(now.getEpochSecond());
System.out.println(now.getNano());
7.3. Duration Period
作用
Duration计算两个’时间‘之间的间隔
Period计算两个‘日期’之间的间隔
1.Duration    between 计算两个时间之间的间隔  toMillis() 转换成毫秒

Instant begin = Instant.now();
Instant end = Instant.now();
Duration between = Duration.between(begin, end);
System.out.println(between.toMillis());
2.Period   between 计算两个日期之间的间隔  getMonths() getDays() 间隔的月和日

LocalDate ld1 = LocalDate.of(2015, 12, 13);
LocalDate ld2 = LocalDate.now();
Period between = Period.between(ld1, ld2);
System.out.println(between.getMonths());
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值