JAVA8-新特性总结及案例

合集下载

Java8用法总结

Java8用法总结

Java8⽤法总结⼀、新特性Java8带来了很多的新特性,本篇就以下⼏个⽅⾯,从实际⽤法的⾓度进⾏介绍。

Lambda 表达式函数式接⼝Stream默认⽅法Optional 类⼆、Lambda表达式2.1 引例@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class Product {private String id;private Long num;private Double price;}为了以后排序,我们定义⼀种⽐较器,按价格排序:Comparator<Product> byPrice = new Comparator<Product>() {@Overridepublic int compare(Product o1, Product o2) {return o1.getPrice().compareTo(o2.getPrice());}};byPrice的作⽤是按价格⽐较2种产品,它是⼀种⾏为,可以⽤Lambda表达:Comparator<Product> byPrice = (Product o1, Product o2) -> o1.getPrice().compareTo(o2.getPrice();这⾥只有⼀种类型Product,可根据Comparator<Product>判断,因此进⼀步简化:Comparator<Product> byPrice = (o1, o2) -> o1.getPrice().compareTo(o2.getPrice();2.2 概念Lambda表⽰⼀种⾏为,通过Lambda表达式将⾏为参数化,这样,⾏为可以和对象⼀样传递;从第三章可以了解,Lambda表达式可以⽤函数式接⼝表⽰,Comparator就是⼀种函数式接⼝;2.3 表达式Lambda表达式有三部分,参数列表、"->"、Lambda主体,实际中有以下2种形式:(parameters) -> expression(parameters) ->{ statements; }(List<Product> list) -> list.isEmpty; // 判断队列为空() -> new Product(); // 新建⼀个对象(String s) -> s.length; // 求字符串长度(Product p) -> System.out.println(p); // 输出对象三、函数式接⼝3.1 相关概念函数式接⼝:只定义⼀个抽象⽅法的接⼝;它可能还会有很多默认⽅法,但有且仅有⼀个抽象⽅法;常见的函数式接⼝如Comparator, Runnable;函数式接⼝可以⽤来表达Lamdba表达式;如将⼀个Lamdba表达式传递给⼀个函数式接⼝,即Lamdba表达式以内联的⽅式实现了函数式接⼝;函数描述符:函数式接⼝的抽象⽅法;如果我们想写⼀个⽤于2个数计算的计算器,可能需要实现如下⼏个函数,根据运算符调⽤对应函数计算;public <T> T add(T a, T b);public <T> T add(T a, T b);public <T> T multiply(T a, T b);public <T> T divide(T a, T b);换⼀种思路,如果有这样⼀个函数 public double func(double a, double b, Function f); f是⼀个函数式接⼝,它表⽰具体运算,具体代码实现如下:@Log4j2public class T19 {public static void main(String[] args) {(myFunction(1, 2, (a, b) -> a + b));(myFunction(1.0, 2.0, (a, b) -> a - b));(myFunction(BigDecimal.ZERO, BigDecimal.valueOf(2), (a, b) -> a.multiply(b)));}public static <T> T myFunction(T a, T b, MyBiFunctionInterface<T> f) {return f.apply(a, b);}}@FunctionalInterfacepublic interface MyBiFunctionInterface<T> {T apply(T a, T b);}输出如下:2018-09-01 19:39:11 - test.other.T19 INFO test.other.T19.main(T19.java:20) : 32018-09-01 19:39:11 - test.other.T19 INFO test.other.T19.main(T19.java:21) : -1.02018-09-01 19:39:11 - test.other.T19 INFO test.other.T19.main(T19.java:22) : 0Java8提供了很多函数式接⼝,⼀般情况下不⽤去定义函数式接⼝,⽐如例⼦中MyBiFunctionInterface,可⽤BinaryOperator代替,BinaryOperator这个函数式接⼝,接收2个类型为T的参数,返回⼀个类型为T的结果,即(T, T) -> T,修改后如下:public static <T> T myFunction(T a, T b, BinaryOperator<T> f) {return f.apply(a, b);}3.3 常见函数式接⼝Function<T, R>T-> RPredict<T>T -> booleanConsumer<T>T -> voidSupplier<T>() -> TUnaryOperator<T>T -> TBinaryOperator<T>(T, T) -> TBiFunction<T, U>(T, U) -> RBiPredicate<L, R>(L, R) -> booleanBiConsumer<T, U>(T, U) -> void3.4 ⽅法引⽤Lamdba表达式的快捷写法,它更直观,可读性更好,⽐如:(Product p) -> p.getPrice == Product::getPrice⽅法引⽤主要有⼆类:(1)指向静态⽅法;如 Integer::parseInt;(2)指向实例⽅法:如 String::length;(3)构造函数的⽅法引⽤:如Supplier<Product> p = Product::new;例:第⼆章引例中还可以如下表达:Comparator<Product> c = paring(Product::getPrice);复合,就是将多个Lamdba表达式连接起来,表⽰更加复杂的功能;主要有以下三种(1)函数复合:将Function代表的Lamdba复合起来,有andThen, compose;其中f.andThen(g) = g(f(x)),先计算f表达式,将结果再计算g表达式;pose(g) = f(g(x)),先计算g表达式,将结果再计算f表达式;Function<Integer, Integer> f = x -> x + 1;Function<Integer, Integer> g = x -> x * 2;Function<Integer, Integer> h1 = f.andThen(g); // (1 + 1) * 2 = 4Function<Integer, Integer> h2 = pose(g); // (1 * 2) + 1 = 3(2)Predicate的复合,有negate, and, or,分别表⽰⾮、且、或,按从左到右的顺序Predicate<Product> p1 = a -> a.getPrice() > 100; // ⼤于100Predicate<Product> p2 = p1.negate(); // ⼩于等于100Predicate<Product> p3 = p1.negate().and(a -> a.getNum() > 10); // 价格⼩于等于100,且数量⼤于10(3)⽐较器复合,如Comparator<Product> c = paring(Product::getPrice).reversed().thenComparing(Product::getNum);四、流4.1 概念流⽤来处理数据集合,它具有如下特点:(1)流强调的是计算,它是源+数据处理,流将外部迭代(如for/while)转化为对我们透明的内部迭代;(2)只能遍历⼀次,遍历完就关闭;流具有如下优点:(1)内置了很多常⽤⽅法(如排序、分类、统计);(2)能透明的并⾏处理;(3)声明式的,只需关注我要怎么样,不⽤关注我该如何实现,通过内置的⽅法与复合很容易实现;4.2 流的操作流的操作分为:(1)中间操作:filter(Predicate<T>), map(Function(T, R), limit, sorted(Comparator<T>), distinct,flatMap;(2)终端操作:只有终端操作才能产⽣输出,包括:allMatch, anyMatch, noneMatch, findAny, findFirst, forEach, collect, reduce, count4.3 流的⽤法@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class Product {private String id;private Long num;private Double price;private Boolean isUse;}List<Product> list = Lists.newArrayList(Product.builder().id("11").num(20l).price(100d).isUse(true).build(),Product.builder().id("12").num(25L).price(120d).isUse(true).build(),Product.builder().id("13").num(25L).price(100d).isUse(true).build(),Product.builder().id("14").num(20L).price(110d).isUse(false).build());(1)filter, 找出价格⼤于100的产品:List<Product> list1 = list.stream().filter(p -> p.getPrice() > 100).collect(Collectors.toList());(2)distinct,去重Arrays.asList(1, 2, 3, 1).stream().distinct().forEach(System.out::print); // 输出123(3)limit,输出前n个Arrays.asList(1, 2, 3, 1).stream().limit(2).forEach(System.out::print); //输出12(4)skip,跳过前n个Arrays.asList(1, 2, 3, 1).stream().skip(2).forEach(System.out::print); // 输出31(5)map, 映射,T -> R<R> Stream<R> map(Function<? super T, ? extends R> mapper);list.stream().map(Product::getPrice).distinct().forEach(System.out::println);输出:100.0120.0110.0(6)flatMap,扁平化,将每个元素产⽣的中间集合合并成⼀个⼤集合;接收的Function将T->Stream<R> <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);Arrays.asList(new String[]{"hello", "world"}).stream().map(p -> p.split("")).flatMap(Arrays::stream) //.flatMap(p -> Arrays.stream(p)).distinct().forEach(System.out::print);// 输出:helowrd(7)匹配boolean anyMatch(Predicate<? super T> predicate);allMatch: 都满⾜条件才返回true;anyMatch: 有⼀个满⾜就返回true;noneMatch: 都不满⾜才返回true;boolean b = Arrays.asList(1, 2, 3, 1).stream().anyMatch(p -> p > 2); //返回true(8)查找,与其它操作结合使⽤findAny: Optional<T> findAny()findFirst: Optional<T> findFirst()Arrays.asList(1, 2, 3, 4, 1).stream().filter(p -> p > 2).findAny() //输出Optional[3]Arrays.asList(1, 2, 3, 4, 1).stream().filter(p -> p > 2).findFirst() //输出Optional[3]4.4 reduce归约归约操作是很常⽤的操作,它将流中的值反复的结合起来,最终得到⼀个值,它是⼀种终端操作;(1)Optional<T> reduce(BinaryOperator<T> accumulator);(2)T reduce(T identity, BinaryOperator<T> accumulator);(3)<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);(1)给定归约算法,最终归约成⼀个值,考虑到流可能为空,所以返回类型为Option,例:Optional<Integer> op1 = Arrays.asList(1, 2, 3, 4, 1).stream().reduce(Integer::sum); //输出Optional[11](2)给定了初值,归约算法,返回结果;Arrays.asList(1, 2, 3, 4, 1).stream().reduce(0, Integer::sum); //输出11// Steam<T>中T为包装类型,没有sum,但Java8为流的原始类型提供了⼀些⽅法,如下Arrays.asList(1, 2, 3, 4, 1).stream().mapToInt(a -> a).sum();list.stream().mapToLong(Product::getNum).sum();(3)第三个参数表⽰合并⽅式,当是并⾏流时,各线程独⽴计算结果,最后将各线程的结果合并;BiFunction<Double, Product, Double> f1 = (Double a, Product b) -> a + b.getNum();BinaryOperator<Double> f2 = (a, b) -> a + b;double b2 = list.parallelStream().reduce(0d, f1, f2);(b2); //输出904.5 数值流数值流除了具有流的⽅法外,还有⼀些特殊的统计⽅法,例DoubleStream doubleStream = list.stream().mapToDouble(Product::getPrice);double average = doubleStream.average().getAsDouble();//数值流->对象流Stream<Double> sd = doubleStream.boxed();// ⽣成n以内的勾股数Stream<double[]> stream = IntStream.rangeClosed(1, 30).boxed().flatMap(a -> IntStream.rangeClosed(a, 30).mapToObj(b -> new double[]{a, b, Math.sqrt(a * a + b * b)}).filter(t -> t[2] % 1 == 0));stream.limit(3).forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2]));输出:3.0,4.0,5.05.0, 12.0, 13.06.0, 8.0, 10.04.6 构建流Stream.iterate(0, n -> n + 2).limit(10);Stream.generate(Math::random).limit(10);五、收集器(collect归约)5.1 常见⽤法Map<Double, List<Product>> map = list.stream().collect(groupingBy(Product::getPrice));Long allNum = list.stream().collect(summingLong(Product::getNum));double average = list.stream().collect(averagingDouble(Product::getPrice));LongSummaryStatistics statistics = list.stream().collect(summarizingLong(Product::getNum));String ids = list.stream().map(Product::getId).collect(joining(", "));5.2 reducing归约Optional<Product> opp = list.stream().collect(reducing((a, b) -> a.getPrice() > b.getPrice() ? a : b));long allNum2 = list.stream().collect(reducing(0L, Product::getNum, Long::sum));long allNum3 = list.stream().collect(reducing(0L, Product::getNum, (i, j) -> i + j));collect中reducing归约三要素,初值,提取值,归约⽅法,若⽆初值返回Optional,若提取值即是对象本⾝,可省略;5.3 多重分组Map<Double, Map<Long, List<Product>>> map = list.stream().collect(groupingBy(Product::getPrice, groupingBy(Product::getNum))); Map<Double, Map<String, List<Product>>> map2 = list.stream().collect(groupingBy(Product::getPrice, groupingBy(p -> {if (p.getNum() <= 80L)return "little";else if (p.getNum() >= 120L)return "many";elsereturn "normal";})));System.out.println(JacksonUtil.toJson(map));System.out.println(JacksonUtil.toJson(map2));输出如下:{"100.0" : {"20" : [ {"id" : "11","num" : 20,"price" : 100.0,"isUse" : true} ],"25" : [ {"id" : "13","num" : 25,"price" : 100.0,"isUse" : true} ]},"110.0" : {"20" : [ {"id" : "14","num" : 20,"price" : 110.0,"isUse" : false} ]},"120.0" : {"25" : [ {"id" : "12","num" : 25,"price" : 120.0,"isUse" : true} ]}}{"100.0" : {"little" : [ {"id" : "11","num" : 20,"price" : 100.0,"isUse" : true}, {"id" : "13","num" : 25,"price" : 100.0,"isUse" : true} ]},"110.0" : {"little" : [ {"id" : "14","num" : 20,"price" : 110.0,"isUse" : false} ]},"120.0" : {"little" : [ {"id" : "12","num" : 25,"price" : 120.0,"isUse" : true} ]}}在⼀次分组的⼦集合中处理数据Map<Double, Long> map = list.stream().collect(groupingBy(Product::getPrice, counting()));Map<Double, Optional<Product>> map2 = list.stream().collect(groupingBy(Product::getPrice, maxBy(comparingLong(Product::getNum)))); Comparator<Product> c = ((p1, p2) -> p1.getNum().compareTo(p2.getNum()));Map<Double, Optional<Product>> map3 = list.stream().collect(groupingBy(Product::getPrice, maxBy(c)));Map<Double, Product> map4 = list.stream().collect(groupingBy(Product::getPrice,collectingAndThen(maxBy(comparing(Product::getNum)), Optional::get)));5.4 分区由⼀个谓词作为分类,分为2类,true与false,⽤法与groupingBy完全⼀样Map<Boolean, List<Product>> map = list.stream().collect(partitioningBy(Product::getIsUse));Map<Boolean, Map<Double, List<Product>>> map2 = list.stream().collect(partitioningBy(Product::getIsUse,groupingBy(Product::getPrice)));Map<Boolean, LongSummaryStatistics> map3 = list.stream().collect(partitioningBy(Product::getIsUse,summarizingLong(Product::getNum)));Map<Boolean, Double> map4 = list.stream().collect(partitioningBy(Product::getIsUse, averagingLong(Product::getNum)));六、optional6.1 使⽤(1)单级包装⽤法:我们会见到如下代码,String name = null;if (product != null) {name = product.getId();}利⽤optional可转化为Optional<Product> optProduct = Optional.ofNullable(product);Optional<String> optName = optProduct.map(Product::getId);(2)多级包装⽤法public String getName(Person person) {return person.getCar().getInsurance().getName();}经过包装如下,注意为防⽌Optional<Optional<T>>这种中间结果造成编译不通过,需要使⽤flatMap public String getName(Person person) {Optional<Person> optPerson = Optional.ofNullable(person);return optPerson.flatMap(Person::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("Unknown"); }。

java8将object转map的写法

java8将object转map的写法

一、前言在Java编程中,经常会遇到需要将一个对象转换为Map的情况,这在实际的开发过程中是非常常见的需求。

Java8为我们提供了一种简洁而优雅的方式来实现这一转换操作,本文将介绍如何利用Java8的新特性来将Object转换为Map。

二、传统的方式在Java8之前,我们通常会使用一些传统的方式来实现Object到Map的转换,比如手动遍历对象的字段,然后将字段名和字段值放入Map中。

这种方式虽然可行,但是比较繁琐且容易出错。

在Java8之前的代码中,通常会看到以下类型的实现:```javapublic Map<String, Object> convertObjectToMap(Object obj) { Map<String, Object> map = new HashMap<>();for (Field field : obj.getClass().getDeclaredFields()) {field.setAccessible(true);try {map.put(field.getName(), field.get(obj));} catch (IllegalAccessException e) {e.printStackTrace();}}return map;}```这种实现方式需要手动遍历对象的字段,并且需要处理字段的访问权限等问题,代码量比较大且可读性不是很好。

三、利用Java8的新特性在Java8中,引入了Streams和Lambdas等新特性,这些新特性极大地简化了编程过程。

我们可以利用这些新特性来实现Object到Map的转换,使得代码变得更加简洁和优雅。

下面是利用Java8的新特性来实现Object到Map转换的代码:```javapublic Map<String, Object> convertObjectToMap(Object obj) { return Arrays.stream(obj.getClass().getDeclaredFields()).peek(field -> field.setAccessible(true)).collect(Collectors.toMap(Field::getName, field -> {try {return field.get(obj);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}));}```在这段代码中,我们首先通过Arrays.stream()方法将对象的字段转换为Stream,然后通过peek()方法设置字段的访问权限。

java8新特性之stream的collect实战教程

java8新特性之stream的collect实战教程

java8新特性之stream的collect实战教程1、list转换成list不带return⽅式List<Long> ids=wrongTmpList.stream().map(c->c.getId()).collect(Collectors.toList());带return⽅式// spu集合转化成spubo集合//java8的新特性List<SpuBo> spuBos=spuList.stream().map(spu -> {SpuBo spuBo = new SpuBo();BeanUtils.copyProperties(spu, spuBo);//查询品牌名称Brand brand = this.brandMapper.selectByPrimaryKey(spu.getBrandId());spuBo.setBname(brand.getName());//查询类别名称List<String> names = this.categoryService.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));spuBo.setCname(StringUtils.join(names, "-"));return spuBo;}).collect(Collectors.toList());2、list转mapMap<Long, Active> activeMap = actives.stream().collect(Collectors.toMap(Active::getId, s->s));3、分组统计计算list转map(根据某个属性进⾏分组)Map<Long, List<TrainPlan>> trainMaps = trainPlans.stream().collect(Collectors.groupingBy(TrainPlan::getModuleId));list转map(统计计算)List<StatDepartment> statDepartments = projectModuleBSDao.statProModByDepartment(params);Map<Long, Integer> projectNumByDep = statDepartments.stream().collect(Collectors.groupingBy(StatDepartment::getDepartmentId, Collectors.summingInt(StatDepartment::getProjectNum)));补充知识:Java8新特性学习-函数式编程(Stream/Function/Optional/Consumer)Java8新引⼊函数式编程⽅式,⼤⼤的提⾼了编码效率。

Java8新特性_Stream_归约、收集、分组、分区

Java8新特性_Stream_归约、收集、分组、分区

Java8新特性_Stream_归约、收集、分组、分区1、归约、收集、分组、分区1、归约reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到⼀个值。

2、收集collect——将流转换为其他形式。

接收⼀个 Collector接⼝的实现,⽤于给Stream中元素做汇总的⽅法3、分组及多级分组 Collectors.groupingBy()4、分区 Collectors.partitioningBy()2、源码package com.atguigu.java8;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 org.junit.Test;import com.atguigu.java8.Employee.Status;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) ——可以将流中元素反复结合起来,得到⼀个值。

Java8新特性之Steam流式编程

Java8新特性之Steam流式编程

Java8新特性之Steam流式编程特地感谢鲁班⼤叔的分享,原学习地址:以下是学习过程整理的笔记1、简介Stream 流处理,⾸先要澄清的是 java8 中的 Stream 与 I/O 流 InputStream 和 OutputStream 是完全不同的概念。

Stream 机制是针对集合迭代器的增强。

流允许你⽤声明式的⽅式处理数据集合(通过查询语句来表达,⽽不是临时编写⼀个实现)2、创建对象流的三种⽅式1. 由集合对象创建流。

对⽀持流处理的对象调⽤ stream()。

⽀持流处理的对象包括 Collection 集合及其⼦类List<Integer> list = Arrays.asList(1,2,3);Stream<Integer> stream = list.stream();2. 由数组创建流。

通过静态⽅法 Arrays.*stream()* 将数组转化为流(Stream)IntStream stream = Arrays.stream(new int[]{3, 2, 1});3. 通过静态⽅法 Stream.of() ,但是底层其实还是调⽤ Arrays.stream()Stream<Integer> stream = Stream.of(1, 2, 3);注意:还有两种⽐较特殊的流空流:Stream.empty()⽆限流:**Stream.generate() ** 和 **Stream.iterate() **。

可以配合 limit() 使⽤可以限制⼀下数量// 接受⼀个 Supplier 作为参数Stream.generate(Math::random).limit(10).forEach(System.out::println);// 初始值是 0,新值是前⼀个元素值 + 2Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);3、流处理的特性1. 不存储数据2. 不会改变数据源3. 不可以重复使⽤测试⽤例:package com.godfrey.stream.features;import org.junit.Assert;import org.junit.Test;import java.util.ArrayList;import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;/*** 流特性** @author godfrey* @since 2021-08-15*/class StreamFeaturesTest {/*** 流的简单例⼦*/@Testpublic void test1() {List<Integer> list = Stream.of(1, 2, 5, 9, 7, 3).filter(val -> val > 2).sorted().collect(Collectors.toList());for (Integer item : list) {System.out.println(item);}}/*** 流不会改变数据源*/@Testpublic void test2() {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(1);Assert.assertEquals(3, list.stream().distinct().count());Assert.assertEquals(4, list.size());}/*** 流不可以重复使⽤*/@Test(expected = IllegalStateException.class)public void test3() {Stream<Integer> integerStream = Stream.of(1, 2, 3);Stream<Integer> newStream = integerStream.filter(val -> val > 2);integerStream.skip(1);}}⾸先,test1() 向我们展⽰了流的⼀般⽤法,由下图可见,源数据流经管道,最后输出结果数据。

Java版本:JDK8的十大新特性介绍

Java版本:JDK8的十大新特性介绍

Java版本:JDK8的⼗⼤新特性介绍JDK8常⽤包及概述java.applet 提供了需要创建⼀个⼩程序和⽤来跟其他⼩程序交流上下⽂的类。

Java.awt 包含⽤于创建⽤户界⾯和绘制图形图像的所有类Java.io 提供与输⼊输出相关的类Java.beans 包含与开发javaBeans相关的类ng 提供java语⾔程序设计的基础类 提供实现⽹络操作相关的类Java.nio 为输⼊输出提供缓冲区的类Java.text 提供处理⽂本、⽇期、数字和消息的类和接⼝Java.util 提供处理⽇期、时间、随机数⽣成等各种使⽤⼯具的类 提供⽤于⽹络应⽤程序的类、⽹络应⽤扩展类Java.swing 提供⼀组与AWT功能相同的纯java的组件类java.sql 该包提供了使⽤Java语⾔访问并处理存储在数据源(通常是⼀个关系型数据库)中的数据API。

java.RMI 该包提供远程⽅法调⽤相关APIJDK8新特性:mbda表达式2.新的⽇期API3.引⼊Optional4.使⽤Base645.接⼝的默认⽅法和静态⽅法6.新增⽅法引⽤格式7.新增Stream类8.注解相关的改变9.⽀持并⾏(parallel)数组10.对并发类(Concurrency)的扩展。

⼀、Lambda表达式Lambda 表达式也可称为闭包,是推动Java 8 发布的最重要新特性。

lambda表达式本质上是⼀个匿名⽅法。

Lambda允许把函数作为⼀个⽅法的参数(函数作为参数传递进⽅法中)或者把代码看成数据。

使⽤Lambda 表达式可以使代码变的更加简洁紧凑。

在最简单的形式中,⼀个lambda可以由:⽤逗号分隔的参数列表、–>符号、函数体三部分表⽰,在某些情况下lambda的函数体会更加复杂,这时可以把函数体放到在⼀对花括号中,就像在Java中定义普通函数⼀样。

Lambda可以引⽤类的成员变量与局部变量(如果这些变量不是final的话,它们会被隐含的转为final,这样效率更⾼)。

新特性总结及案例

新特性总结及案例

一 Lambda函数(箭头函数)Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

(parameters) -> expression或(parameters) ->{statement1;statement2;...... }lambda表达式的重要特征:可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回,大括号需指定表达式返回数值。

本质上,Lambda函数是对匿名内部类对象的简写。

应用举例1(比较JAVA7与JAVA8):Lambda函数做类的属性运行结果:应用举例2(比较JAVA7与JAVA8):Lambda函数做main函数变量应用举例3:应用举例4:多线程启动时使用Lambda函数应用举例5:在中,匿名内部类只能使用定义为final的外部变量,会自动为Lambda函数使用的外部变量加上final,因此final可以省略不写。

二方法引用(::方法名 ----》调用了方法对象)应用举例1:应用举例2:三函数式接口函数式接口(Functional Interface)就是一个具有一个方法的普通接口。

函数式接口可以被隐式转换为lambda表达式。

函数式接口可以现有的函数友好地支持 lambda。

JDK 之前已有的函数式接口:新增加的函数接口:它包含了很多类,用来支持 Java的函数式编程,该包中的函数式接口有:序号接口 & 描述1BiConsumer<T,U>代表了一个接受两个输入参数的操作,并且不返回任何结果2BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果3BinaryOperator<T>代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果4BiPredicate<T,U>代表了一个两个参数的boolean值方法5BooleanSupplier代表了boolean值结果的提供方6Consumer<T>代表了接受一个输入参数并且无返回的操作7DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。

Java8新特性:list.stream().map().collect()

Java8新特性:list.stream().map().collect()

Java8新特性:list.stream().map().collect()StreamStream(流)是⼀个来⾃数据源的元素队列并⽀持聚合操作;mapmap ⽅法⽤于映射每个元素到对应的结果;CollectorsCollectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。

Collectors 可⽤于返回列表或字符串。

使⽤⽅式:1.⾸先创建⼀个实体类,添加部分属性;public class Student {public Student(String name,Integer age){=name;this.age=age;}private String name;private Integer age;public String getName() {return name;}public void setName(String name) { = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "name="+getName()+", age="+getAge();}}2. 新建实体集合并添加⼏条数据;List<Student> list = new ArrayList<>();list.add(new Student("ymw", 30));list.add(new Student("yh", 30));返回结果:[name=ymw, age=30, name=yh, age=30]3. 清空某个属性的值并返回结果:list.stream().map(it ->{it.setName("");return it;}).collect(Collectors.toList());System.out.println(list.toString());返回结果:[name=, age=30, name=, age=30]4. 获取其中某个属性的集合:List collection = list.stream().map(Student::getAge).collect(Collectors.toList());System.out.println(collection.toString());返回结果:[30, 30]。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一 Lambda函数(箭头函数)
Lambda 表达式,也可称为闭包,它是推动Java 8 发布の最重要新特性。

Lambda 允许把函数作为一个方法の参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变の更加简洁紧凑。

(parameters) ->expression或(parameters) ->{
statement1;
statement2;
...... }
lambda表达式の重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选の参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选の大括号:如果主体包含了一个语句,就不需要使用大括号。

可选の返回关键字:如果主体只有一个表达式返回值则编译器会自动返回,大括号需指定表达式返回数值。

本质上,Lambda函数是对匿名内部类对象の简写。

应用举例1(比较JAVA7与JAVA8):Lambda函数做类の属性
运行结果:
应用举例2(比较JAVA7与JAVA8):Lambda函数做main函数变量
应用举例3:
应用举例4:多线程启动时使用Lambda函数
应用举例5:在 1.7中,匿名内部类只能使用定义为finalの外部变量,1.8会自动为Lambda函数使用の外部变量加上final,因此final可以省略不写。

二方法引用(::方法名 ----》调用了方法对象)应用举例1:
应用举例2:
三函数式接口
函数式接口(Functional Interface)就是一个具有一个方法の普通接口。

函数式接口可以被隐式转换为lambda表达式。

函数式接口可以现有の函数友好地支持 lambda。

JDK 1.8之前已有の函数式接口:
ng.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
parator
四接口の默认方法
默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个default关键字即可实现默认方法。

为什么要有这个特性?
1.8之前,修改接口意味着要修改全部实现该接口の类,例如,java 8之前の集合框架没有foreach方法,通常の解决办法是在JDK里给相关の接口添加新の方法及实现类。

对于已经发布の版本,会影响已有の实现。

接口引进了の默认方法の机制。

最大化の解决了接口の修改与现有の实现不兼容の问题。

需求变更,需要修改接口,此时使用java8新特性中の接口默认方法,实现类TestImpl无需改变代码,ITest接口即可提供服务。

当然TestImpl也可以覆盖接口中の变更方法print
五 JAVA8 Stream
Stream 使用一种类似用 SQL 语句从数据库查询数据の直观方式来提供一种对 Java 集合运算和表达の高阶抽象。

Stream API可以极大提供Java程序员の生产力,让程序员写出高效率、干净、简洁の代码。

这种风格将要处理の元素集合看作一种流,流在管道中传输,并且可以在管道の节点上进行处理,比如筛选,排序,聚合等,最后由最终操作(terminal operation)得到前面处理の结果。

+--------------------++------++------++---++-------+|stream of elements +----->|filter+->|sorted+->|map+->|collect|+--------------------++------++------++---++-------+
以上の流程转换为 Java 代码为:
List<Integer>transactionsIds =widgets.stream().filter(b ->b.getColor()== RED).sorted((x,y)->x.getWeight()-y.getWeight()).mapToInt(Widget::getWeight).sum();
5.1生成流:
在 Java 8 中, 集合接口有两个方法来生成流:
stream()− 为集合创建串行流。

parallelStream()− 为集合创建并行流。

【串行与并行】
5.2 forEach遍历方法
5.3 map方法
map用于映射每个元素到对应の运行结果
5.4 filter、limit、sorted、parallelStream filter 方法用于通过设置の条件过滤出元素。

limit 获取指定数量の流
sorted 对流对象进行排序
parallelStream 并行流替代串行流
5.5 collect方法及Collectors类
Collectors.toList方法由流转变为List集合
Collectors.joining(",")方法,由流转变为字符串
5.6 IntSummaryStatistics统计收集器
六 JAVA8 Optional类
Optional 类是一个可以为nullの容器对象,它可以保存类型Tの值,或者仅仅保存null。

如果值存在,则isPresent()方法会返回true,调用get()方法会返回该对象。

这样我们就不用显式进行空值检测。

Optional 类の引入很好の解决空指针异常。

类声明
以下是一个java.util.Optional<T>类の声明:
public final class Optional<T>extends Object 类方法
七 JAVA8 Nashorn引擎
Nashorn是一个javascript 引擎,从JDK 1.8开始,Nashorn取代Rhino(JDK 1.6, JDK1.7)成为Javaの嵌入式JavaScript引擎。

Nashorn完全支持ECMAScript 5.1规范以及一些扩展,可以将JavaScript编译成Java字节码,带来了2到10倍の性能提升。

7.1 jjs命令行工具
jjs是个基于Nashorn引擎の命令行工具。

它接受一些JavaScript源代码为参数,并且执行这些源代码。

//print语句,浏览器执行就是直接调打印程序,控制台执行就是在控制台显示信息
7.2 JAVA调用Javascript程序
使用 ScriptEngineManager, JavaScript 代码可以在 Java 中执行.
7.3 Javascript调用JAVA程序
八 JAVA8 日期时间API
Java 8通过发布新のDate-Time API 来进一步加强对日期与时间の处理。

在 Java7之前の版本中,日期时间 API 存在の问题如下:
非线程安全− java.util.Date 是异步の,非线程安全の,这是Java日期类最大の问题之一。

设计很差− Javaの日期/时间类の定义并不一致,在java.util和java.sqlの包中都有日期类,此外用于格式化和解析の类在java.text包中定义。

java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期。

另外这两个类都有相同の名字,这本身就是一个非常糟糕の设计。

时区处理麻烦− 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有の问题。

Java 8 在java.time包下提供了很多新の API。

以下为两个比较重要の API:
Local(本地)− 简化了日期时间の处理,没有时区の问题。

Zoned(时区)− 通过制定の时区处理日期时间。

Java8中新のjava.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)の操作。

8.1 本地化日期时间API
media type),MIME使用一个简单の字符串组成,最初是为了标识邮件Email附件の类型,在html文件中可以使用content-type属性表示,描述了文件类型の互联网标准。

MIME类型能包含视频、图像、文本、音频、应用程序等数据。

相关文档
最新文档