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的写法
一、前言在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实战教程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_归约、收集、分组、分区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流式编程特地感谢鲁班⼤叔的分享,原学习地址:以下是学习过程整理的笔记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的⼗⼤新特性介绍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()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]。
java8新特性stream流的方式遍历集合和数组操作
java8新特性stream流的⽅式遍历集合和数组操作前⾔:在没有接触java8的时候,我们遍历⼀个集合都是⽤循环的⽅式,从第⼀条数据遍历到最后⼀条数据,现在思考⼀个问题,为什么要使⽤循环,因为要进⾏遍历,但是遍历不是唯⼀的⽅式,遍历是指每⼀个元素逐⼀进⾏处理(⽬的),⽽并不是从第⼀个到最后⼀个顺次处理的循环,前者是⽬的,后者是⽅式。
所以为了让遍历的⽅式更加优雅,出现了流(stream)!1.流的⽬的在于强掉做什么假设⼀个案例:将集合A根据条件1过滤为⼦集B,然后根据条件2过滤为⼦集C在没有引⼊流之前我们的做法可能为:public class Demo02NormalFilter {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张⽆忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");List<String> zhangList = new ArrayList<>();for (String name : list) {if (name.startsWith("张")) {zhangList.add(name);}}List<String> shortList = new ArrayList<>();for (String name : zhangList) {if (name.length() == 3) {shortList.add(name);}}for (String name : shortList) {System.out.println(name);}}}现在以流的⽅式实现同样的功能:public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张⽆忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");list.stream().filter(s->s.startsWith("张")).filter(s-> s.length() == 3).forEach(System.out::println);从上⾯的两段代码可以看出流的存在让代码更加优雅。
java8新特性instant
java8新特性instantJava 8⽬前已经开始进⼊⼤众的视线,其中笔者在写本⽂之前,留意到其中Java 8预览版中将会出现新的关于⽇期和时间的API(遵守规范)。
在本系列⽂章中,将对这些新的API进⾏举例说明。
⾸先在本⽂中,将先介绍以下⼏个:Instant,LocalDate,LocalTime 和LocalDateTime。
⾸先看看 Instant 对象的使⽤⽅法:Instant (java.time.Instant)可能 java.time 包中最容易开始学习的内容就是 Instant 这个类。
所谓的 Instant 类代表的是某个时间(有点像 java.util.Date),它是精确到纳秒的(⽽不是象旧版本的Date精确到毫秒)。
如果使⽤纳秒去表⽰⼀个时间则原来使⽤⼀位Long类型是不够的,需要占⽤更多⼀点的存储空间,实际上其内部是由两个Long字段组成,第⼀个部分保存的是⾃标准Java计算时代(就是1970年1⽉1⽇开始)到现在的秒数,第⼆部分保存的是纳秒数(永远不会超过999,999,999)。
我们看下⼀个具体的例⼦://获得当前时间Instant instant = Instant.now();// 以ISO-8601输出System.out.println(instant);在 Open JDK 中运⾏上⾯的代码,可以有如下格式的输出:2013-06-25T16:22:52.966Z,可以看到,输⼊了更为精确的⽇期。
下⾯的例⼦是更多的关于 Instant 类的⽤法,如://将java.util.Date转换为InstantInstant instant = Instant.ofEpochMilli(new Date().getTime());//从字符串类型中创建Instant类型的时间instant = Instant.parse("1995-10-23T10:12:35Z");注意,在上⾯的例⼦中,有壹個字符串中创建 Instant 类型的时间,但 Instant 代表的是⼀个时间,并不包括时区的概念,所以必须传⼊的是符合 UTC格式的字符串。
jav8特性特性应用
jav8特性特性应⽤List<JSONObject> tableData = new ArrayList(1);tableData = tableData.stream().sorted(paring(jsonObject -> StringNullUtil.isNotBlank((jsonObject).getString("id1Sort"))?(jsonObject).getInteger List<DeptTree> collect = deptAllList.stream().filter(dept -> dept.getDeptId().intValue() != dept.getParentId()).sorted(paringInt(SysDept::getSort)).map(dept -> {DeptTree node = new DeptTree();node.setId(dept.getDeptId());node.setParentId(dept.getParentId());node.setName(dept.getName());return node;}).collect(Collectors.toList());Map<String, List<CatalogSystem>> map = catalogSystemsPOIList.stream().filter(item -> StrUtil.isNotBlank(item.getName())).collect(Collectors.groupingBy(CatalogSystem::getName));//list按逗号隔开,输出stringList<String> msgList = new ArrayList<>();msgList.stream().map(v->String.valueOf(v)).collect(Collectors.joining(";"))Map<Integer, String> map = userList.stream().collect(Collectors.toMap(User::getAge, User::getName, (a, b) -> b));Map<String, SysDept> sysDeptMap=sysDeptList.stream().collect(Collectors.toMap(SysDept::getName, v -> v));List<SysRoleMenu> roleMenuList = Arrays.stream(menuIds.split(",")).map(menuId -> {SysRoleMenu roleMenu = new SysRoleMenu();roleMenu.setRoleId(roleId);roleMenu.setMenuId(Integer.valueOf(menuId));return roleMenu;}).collect(Collectors.toList());List<Integer> dataType = StringUtils.isNotBlank(quotaLibrary.getDataType()) ? JSONArray.parseArray(quotaLibrary.getDataType(), Integer.TYPE): new ArrayList<>();list拼接字符串逗号拼接String join = CollectionUtil.join(deptIds, ",");String rules = StringUtils.join(ruleList, ",");String.join(",", newFunctionStrs)String转listString[] split = rules.split(",");List<String> ruleList = Arrays.asList(split);String[] functionStrs = StrUtil.split(f.getFieldFunction(), ",");List<String> functionStrs = CollUtil.toList(StrUtil.split(functionField.getFieldFunction(), ","));//list转mapList<SysDept> sysDeptList = new SysDept().selectList(sysDeptQueryWrapper);Map<String, SysDept> sysDeptMap = new HashMap<>();if(CollUtil.isNotEmpty(sysDeptList)){sysDeptMap=sysDeptList.stream().collect(Collectors.toMap(SysDept::getName, v -> v));}Map<Long, Long> interfaceDataMap = new HashMap<>();interfaceDataMap =interfaceData.stream().collect(Collectors.toMap(GradeInterfaceData::getInterfaceId,GradeInterfaceData::getInterfaceId));List<TaskBaseMaterial> taskBaseMaterialList = new ArrayList<>();newMaterialList.forEach(matMaterial -> {TaskBaseMaterial taskBaseMaterial = new TaskBaseMaterial();taskBaseMaterial.setTaskId(guideId);taskBaseMaterial.setMaterialId(matMaterial.getId());taskBaseMaterialList.add(taskBaseMaterial);});List<GradeInterfaceDTO> dtoList = new ArrayList<>();list=new GradeInterface().selectList(queryWrapper);if(list!=null&&!list.isEmpty()){list.forEach(q -> {//查询问题选项GradeInterfaceDTO interfaceDTO = new GradeInterfaceDTO();BeanUtils.copyProperties(q, interfaceDTO);dtoList.add(interfaceDTO);});}list转单个stirng数组List<Long> oldIds = list.stream().map(QuesQuestionTask::getId).collect(Collectors.toList());list转JSONARRAYdnaAnswerList.stream().map(QuesAnswer::getContent).map(JSON::parseArray).toArray()//获取最⼤的部⻔idInteger parentId = deptAllList.stream().max(paring(SysDept::getParentId)).get().getParentId();// 获取最⼤值Optional<GradeQuota> userOp = gradeQuotaList.stream().max(paringInt(GradeQuota::getQuotaLevel));gradeQuotaList.stream().filter(gradeQuota -> gradeQuota.getHasSon() == 0).map(GradeQuota::getId).collect(Collectors.toSet()));tableData = tableData.stream().sorted(paring(jsonObject -> StringNullUtil.isNotBlank((jsonObject).getString("id1Sort"))?(jsonObject).getInteger("id1Sort"):0)).collect(Collectors.toList());List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());tableData=tableData.stream().sorted(paring(jsonObject -> ((JSONObject)jsonObject).getInteger("id1"))).collect(Collectors.toList());// 查询全部部⻔// List<DeptTree> deptList = deptMapper.selectList(Wrappers.emptyWrapper()).stream().filter(dept -> dept.getDeptId().intValue() != dept.getParentId())// .sorted(paringInt(SysDept::getSort)).map(dept -> {// DeptTree node = new DeptTree();// node.setId(dept.getDeptId());// node.setParentId(dept.getParentId());// node.setName(dept.getName());// return node;// }).collect(Collectors.toList());// 权限内部⻔List<DeptTree> collect = deptAllList.stream().filter(dept -> dept.getDeptId().intValue() != dept.getParentId()).sorted(paringInt(SysDept::getSort)).map(dept -> {DeptTree node = new DeptTree();node.setId(dept.getDeptId());node.setParentId(dept.getParentId());node.setName(dept.getName());return node;}).collect(Collectors.toList());//java8 filter ⽤法1.输出符合表达式的每⼀个对象employees.stream().filter(p -> p.getAge() > 21).forEach(System.out::println);//输出每⼀个对象122.返回⼀个符合表达式的集合Stream<Person> personStream = collection.stream().filter(new Predicate<Person>() {@Overridepublic boolean test(Person person) {return "男".equals(person.getGender());//只保留男性}});collection = personStream.collect(Collectors.toList());//将Stream转化为ListSystem.out.println(collection.toString());//查看结果//拼接String str = Joiner.on(",").join(ids);这种写法最简单,直接Joiner.on 拼接 “,” “#” “、”_" “-” 之类的也是最常⽤的⽅法//拼接StringBuilder strBur = new StringBuilder(); list.forEach(val -> { strBur.append(val).append("#"); }); strBur.toString();//拼接String result = list.stream().collect(Collectors.joining("_"));。
Java8新特性:2-消费者(Consumer)接口
Java8新特性:2-消费者(Consumer)接⼝(原)在上⼀篇,⽤到过这样⼀个⽅法:list.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer t) {System.out.println(t);}});这⾥重点看List的foreach⽅法;/** Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/package ng;import java.util.Iterator;import java.util.Objects;import java.util.Spliterator;import java.util.Spliterators;import java.util.function.Consumer;/*** Implementing this interface allows an object to be the target of* the "for-each loop" statement. See* <strong>* <a href="{@docRoot}/../technotes/guides/language/foreach.html">For-each Loop</a>* </strong>** @param <T> the type of elements returned by the iterator** @since 1.5* @jls 14.14.2 The enhanced for statement*/public interface Iterable<T> {/*** Returns an iterator over elements of type {@code T}.** @return an Iterator.*/Iterator<T> iterator();/*** Performs the given action for each element of the {@code Iterable}* until all elements have been processed or the action throws an* exception. Unless otherwise specified by the implementing class,* actions are performed in the order of iteration (if an iteration order* is specified). Exceptions thrown by the action are relayed to the* caller.*针对于Iterable的每⼀个元素去执⾏给定的动作,直到所有的元素都执⾏完,或者抛出异常。
浅谈Java8新特性Predicate接口
浅谈Java8新特性Predicate接⼝⽬录⼀、前⾔⼆、test(T t)三、and(Predicate<? super T> other)四、or(Predicate<? super T> other)五、negate()六、isEqual(Object targetRef)七、not(Predicate<? super T> target)⼀、前⾔Java 8中引⼊了Predicate功能接⼝。
Java Predicate表⽰⼀个参数的谓词。
Predicate是⼀个布尔值的函数。
Java Predicate是⼀个功能接⼝,属于java.util.function包。
Predicate的功能⽅法是test(T t)。
Predicate的其他⽅法是test、isEqual、and、or、negate和not。
not⽅法在Java 11中被引⼊。
在本⽂章,我们将提供Predicate的例⼦及其所有⽅法。
⼆、test(T t)boolean test(T t)test是Predicate的功能⽅法。
它在给定的参数上评估这个谓词。
例1:PredicateTestDemo1.javaimport java.util.function.Predicate;public class PredicateTestDemo1 {public static void main(String[] args) {// Is username validPredicate<String> isUserNameValid = u -> u != null && u.length() > 5 && u.length() < 10;System.out.println(isUserNameValid.test("Mahesh")); //true// Is password validPredicate<String> isPasswordValid = p -> p != null && p.length() > 8 && p.length() < 15;System.out.println(isPasswordValid.test("Mahesh123")); //true// Word matchPredicate<String> isWordMatched = s -> s.startsWith("Mr.");System.out.println(isWordMatched.test("Mr. Mahesh")); //true//Odd numbersPredicate<Integer> isEven = n -> n % 2 == 0;for(int i = 0 ; i < 5 ; i++) {System.out.println("Is "+ i + " even: " + isEven.test(i));}}}输出结果truetruetrueIs 0 even: trueIs 1 even: falseIs 2 even: trueIs 3 even: falseIs 4 even: true例2:PredicateTestDemo2.javaimport java.util.function.Function;import java.util.function.Predicate;public class PredicateTestDemo2 {public static void main(String[] args){Predicate<Student> maleStudent = s-> s.getAge() >= 20 && "male".equals(s.getGender()); Predicate<Student> femaleStudent = s-> s.getAge() > 18 && "female".equals(s.getGender()); Function<Student,String> maleStyle = s-> "Hi, You are male and age "+s.getAge();Function<Student,String> femaleStyle = s-> "Hi, You are female and age "+ s.getAge();Student s1 = new Student("Gauri", 20,"female");if(maleStudent.test(s1)){System.out.println(s1.customShow(maleStyle));}else if(femaleStudent.test(s1)){System.out.println(s1.customShow(femaleStyle));}}Student.javaimport java.util.function.Function;public class Student {private String name;private int age;private String gender;private int marks;public Student(String name, int age, String gender){ = name;this.age = age;this.gender = gender;}public Student(String name, int age, String gender, int marks){ = name;this.age = age;this.gender = gender;this.marks = marks;}public String getName() {return name;}public int getAge() {return age;}public String getGender() {return gender;}public int getMarks() {return marks;}public String customShow(Function<Student,String> fun){return fun.apply(this);}public String toString(){return name+" - "+ age +" - "+ gender + " - "+ marks;}}输出结果Hi, You are female and age 20三、and(Predicate<? super T> other)default Predicate<T> and(Predicate<? super T> other)and是Predicate的默认⽅法,它返回⼀个组成的谓词,表⽰这个谓词和其他谓词的短路逻辑AND。
JAVA8新特性之List的各种用法(最大、最小、平均值、分组、求和、遍历、过滤、排序)
JAVA8新特性之List的各种⽤法(最⼤、最⼩、平均值、分组、求和、遍历、过滤、排序)构建⼀个User实体类供演⽰public class Users {/*** ID*/private Long id;/*** ⽤户名*/private String name;/*** 年龄*/private int age;/*** ⼯号*/private String jobNumber;/*** 性别*/private String sex;/*** 注册时间*/private Date entryDate;/*** 成员组织*/private BigDecimal familyMemberQuantity;private Long userId;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) { = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getJobNumber() {return jobNumber;}public void setJobNumber(String jobNumber) {this.jobNumber = jobNumber;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getEntryDate() {return entryDate;}public void setEntryDate(Date entryDate) {this.entryDate = entryDate;}public BigDecimal getFamilyMemberQuantity() {return familyMemberQuantity;}public void setFamilyMemberQuantity(BigDecimal familyMemberQuantity) {this.familyMemberQuantity = familyMemberQuantity;}public Long getUserId() {return userId;}public void setUserId(Long userId) {erId = userId;}@Overridepublic String toString() {return "Users{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", jobNumber='" + jobNumber + '\'' +", sex='" + sex + '\'' +", entryDate=" + DateFormatUtils.format(entryDate, "yyyy-MM-dd HH:mm:ss") +", familyMemberQuantity=" + familyMemberQuantity +'}';}}⼀、根据字段分组得到多个List集合构建⼀个产⽣Users的静态法/*** ⽣产虚拟⽤户** @return*/public static List<Users> produceUser() {List<Users> usersList = new ArrayList<>();for (int i = 1; i <= 10; i++) {Users users = new Users();users.setId(Long.valueOf(i));users.setName("kobe" + i);users.setAge(15 + new Random().nextInt(5));users.setJobNumber("jobNumber" + i);if (i % 2 == 0) {users.setSex("男");} else {users.setSex("⼥");}users.setEntryDate(new Date());users.setFamilyMemberQuantity(new BigDecimal(i));usersList.add(users);}return usersList;}利⽤Java8 特性,根据对象的某个属性进⾏分组@Testpublic void groupByGender() {List<Users> list = produceUser();// 根据性别进⾏分组Map<String, List<Users>> collect = list.stream().collect(Collectors.groupingBy(Users::getSex)); Set<Map.Entry<String, List<Users>>> entries = collect.entrySet();entries.forEach(item -> {// 性别男 / ⼥String gender = item.getKey();// 男集合 / ⼥集合List<Users> usersList = item.getValue();System.out.println(gender);usersList.forEach(user -> System.out.println(user));});}输出结果如下⼆、集合求和2.1 根据对象中的某个字段求和/*** 根据年龄字段求总和*/@Testpublic void getSumByStream() {List<Users> list = produceUser();int sum = list.stream().mapToInt(Users::getAge).sum();System.out.println("共计:" + list.size() + "个⽤户,所有年龄总和为:" + sum);// 求最⼤年龄Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get();System.out.println(integer);// 得到最⼤年龄对象Users users = list.stream().max(paringInt(Users::getAge)).get();System.out.println(users);// 求平均年龄System.out.println(list.stream().mapToInt(Users::getAge).average().getAsDouble());// 求最⼤年龄System.out.println(list.stream().mapToInt(Users::getAge).max().getAsInt());}输出结果如下2.2 List<数值型> 求和/*** 根据List求和*/@Testpublic void getListSumByJava8() {List<Integer> listInt = new ArrayList();List<Double> listDoub = new ArrayList();for (int i = 0; i < 500; i++) {listInt.add(new Random().nextInt(1000));listDoub.add(new Random().nextDouble());}System.out.println("=======数值型Integer求和======");Integer integer = listInt.stream().reduce(Integer::sum).orElse(0);System.out.println(integer);System.out.println("=======数值型Double求和======");Double integer1 = listDoub.stream().reduce(Double::sum).orElse(0.00);System.out.println(integer1);// 取最⼤值System.out.println(listInt.stream().reduce(Integer::max).orElse(0));System.out.println(listInt.stream().mapToInt(Integer::valueOf).max().getAsInt());// 取最⼩值System.out.println(listInt.stream().reduce(Integer::min).orElse(0));// 取平均值System.out.println(listInt.stream().mapToInt(Integer::valueOf).average().getAsDouble());}输出结果如下三、遍历List集合/*** 遍历对象*/@Testpublic void traverseByJava8(){List<Users> list = produceUser();list.forEach(System.out::println);}输出结果如下四、过滤List集合/*** 过滤对象*/@Testpublic void filterByJava8() {List<Users> list = produceUser();System.out.println("原始数据为:");System.out.println("==============过滤后的数据为===============");list.forEach(System.out::println);//筛选出年龄⼤于3岁⼩于8岁的对象List<Users> collect = list.stream().filter(s -> s.getAge() > 13 && s.getAge() < 18).collect(Collectors.toList()); System.out.println("过滤结束后的数据为:");collect.forEach(System.out::println);}输出结果如下五、获取List中的最⼤最⼩值5.1 根据特定需求中的某个字段求最⼤最⼩/*** 求最⼤最⼩值,根据业务类型选择合适的类型值*/@Testpublic void maxOrMinByJava8() {List<Users> list = produceUser();//根据mapTO**得到最⼤最⼩ ---写法⼀double asDouble = list.stream().mapToDouble(Users::getAge).max().getAsDouble(); System.out.println("将最⼤值转换为Double类型进⾏展⽰,最⼤为:" + asDouble);double asDouble1 = list.stream().mapToDouble(Users::getAge).min().getAsDouble(); System.out.println("将最⼩值转换为Double类型进⾏展⽰,最⼩为:" + asDouble1);int asInt = list.stream().mapToInt(Users::getAge).max().getAsInt();System.out.println("将最⼤值转换为Int类型进⾏展⽰,最⼤为:" + asInt);//根据map得到最⼤最⼩ ---写法⼆(推荐)Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get();System.out.println("将最⼤值转换为字段对应类型进⾏展⽰,最⼤为:" + integer);Integer integer1 = list.stream().map(Users::getAge).min(Integer::compareTo).get();System.out.println("将最⼩值转换为字段对应类型进⾏展⽰,最⼩为:" + integer1);}输出结果如下5.2 根据特定需求中的某个字段求平均值/*** 求最⼤最⼩值,根据业务类型选择合适的类型值*/@Testpublic void avgByJava8() {List<Users> list = produceUser();double avgAge = list.stream().mapToDouble(Users::getAge).average().getAsDouble(); System.out.println("平均年龄为:" + avgAge);}输出结果如下六、根据需求将List转为Map/*** List -> Map* 需要注意的是:* toMap 如果集合对象有重复的key,会报错Duplicate key ....* user1,user2的id都为1。
java8新特性-reduce
java8新特性-reducereduce是⽤来执⾏聚合操作的reduce⽅法有三个override的⽅法:Optional<T> reduce(BinaryOperator<T> accumulator);T reduce(T identity, BinaryOperator<T> accumulator);<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);1. 第⼀种⽅法BinaryOperator接⼝,可以看到reduce⽅法接受⼀个函数,这个函数有两个参数,第⼀个参数是上次函数执⾏的返回值(也称为中间结果),第⼆个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执⾏这个函数的第⼀个参数。
要注意的是:第⼀次执⾏的时候第⼀个参数的值是Stream的第⼀个元素,第⼆个参数是Stream的第⼆个元素。
这个⽅法返回值类型是Optional。
Optional accResult = Stream.of(1, 2, 3, 4).reduce((acc, item) -> {System.out.println("acc : " + acc);acc += item;System.out.println("item: " + item);System.out.println("acc+ : " + acc);System.out.println("--------");return acc;});System.out.println("accResult: " + accResult.get());System.out.println("--------");// 结果打印--------acc : 1item: 2acc+ : 3--------acc : 3item: 3acc+ : 6--------acc : 6item: 4acc+ : 10--------accResult: 10--------2. 第⼆种⽅法第⼆个变形,与第⼀种变形相同的是都会接受⼀个BinaryOperator函数接⼝,不同的是其会接受⼀个identity参数,⽤来指定Stream循环的初始值。
java8新特性,使用流遍历集合
java8新特性,使⽤流遍历集合 在这篇“Java 8新特性教程”系列⽂章中,我们会深⼊解释,并通过代码来展⽰,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值。
在之前的⽂章“遍历、过滤、处理集合及使⽤Lambda表达式增强⽅法”中,我已经深⼊解释并演⽰了通过lambda表达式和⽅法引⽤来遍历集合,使⽤predicate接⼝来过滤集合,实现接⼝的默认⽅法,最后还演⽰了接⼝静态⽅法的实现。
源代码都在我的Github上:可以从克隆。
内容列表使⽤流来遍历集合。
从集合或数组创建流。
聚合流中的值。
1. 使⽤流来遍历集合简介:Java的集合框架,如List和Map接⼝及Arraylist和HashMap类,让我们很容易地管理有序和⽆序集合。
集合框架⾃引⼊的第⼀天起就在持续的改进。
在Java SE 8中,我们可以通过流的API来管理、遍历和聚合集合。
⼀个基于流的集合与输⼊输出流是不同的。
如何⼯作?它采⽤⼀种全新的⽅式,将数据作为⼀个整体,⽽不是单独的个体来处理。
当你使⽤流时,你不需要关⼼循环或遍历的细节。
你可以直接从⼀个集合创建⼀个流。
然后你就能⽤这个流来许多事件了,如遍历、过滤及聚和。
我将从项⽬ Java8Features 的com.tm.java8.features.stream.traversing 包下的例⼦开始。
代码在⼀个SequentialStream 类中,Java SE 8 中有两种集合流,即串⾏流和并⾏流。
List<person> people = new ArrayList<>();people.add(new Person("Mohamed", 69));people.add(new Person("Doaa", 25));people.add(new Person("Malik", 6));Predicate<person> pred = (p) -> p.getAge() > 65;displayPeople(people, pred);...........private static void displayPeople(List<person> people, Predicate<person> pred) {System.out.println("Selected:");people.forEach(p -> {if (pred.test(p)) {System.out.println(p.getName());}});}在这两种流中,串⾏流相对⽐较简单,它类似⼀个迭代器,每次处理集合中的⼀个元素。
详解Java8新特性Stream之list转map及问题解决
详解Java8新特性Stream之list转map及问题解决List集合转Map,⽤到的是Stream中Collectors的toMap⽅法:Collectors.toMap具体⽤法实例如下://声明⼀个List集合List<Person> list = new ArrayList();list.add(new Person("1001", "⼩A"));list.add(new Person("1002", "⼩B"));list.add(new Person("1003", "⼩C"));System.out.println(list);//将list转换mapMap<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));System.out.println(map);输出结果为:注意:⽤Collectors的toMap⽅法转换List,⼀般会遇到两个问题。
⼀个是转换map,key重复问题;另⼀个是空指针异常,即转为map的value是null。
问题解决⼀、第⼀种问题报的错误如下:Duplicate key原因是声明List集合时,有的值重复,如图:解决⽅法:(分三种,具体哪种看业务需求)1.重复时⽤后⾯的value 覆盖前⾯的valueMap<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key2 ));System.out.println(map);输出结果:2.重复时将前⾯的value 和后⾯的value拼接起来;Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key1+","+key2 ));System.out.println(map);输出结果:3.重复时将重复key的数据组成集合Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId,p -> {List<String> getNameList = new ArrayList<>();getNameList.add(p.getName());return getNameList;},(List<String> value1, List<String> value2) -> {value1.addAll(value2);return value1;}));System.out.println(map);输出结果:⼆、第⼆种问题报的错误如下:NullPointerException原因是声明List集合时有的值为空(如图),但是HashMap中k,v是可以存null值的。
java8新特性--Stream将List转为Map汇总
java8新特性--Stream将List转为Map汇总Stream将List转换为Map,使⽤Collectors.toMap⽅法进⾏转换背景:User类,类中分别有id,name,age三个属性。
List集合,userList,存储User对象1、指定key-value,value是对象中的某个属性值。
Map<Integer,String> userMap1 = userList.stream().collect(Collectors.toMap(User::getId,User::getName));2、指定key-value,value是对象本⾝,User->User 是⼀个返回本⾝的lambda表达式Map<Integer,User> userMap2 = userList.stream().collect(Collectors.toMap(User::getId,User->User));3、指定key-value,value是对象本⾝,Function.identity()是简洁写法,也是返回对象本⾝Map<Integer,User> userMap3 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));4、指定key-value,value是对象本⾝,Function.identity()是简洁写法,也是返回对象本⾝,key 冲突的解决办法,这⾥选择第⼆个key覆盖第⼀个key。
Map<Integer,User> userMap4 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(),(key1,key2)->key2));实际项⽬中的例⼦:T_CONTACTOR表结构主要有:T_FUNDCONTACTRELA表结构主要有:业务如下:⾸先有⼀张产品跟联系⼈关联关系表和⼀张联系⼈表,当我在界⾯新增⼀个联系⼈数据时,数据进⼊的是T_CONTACTOR表,如果需要给该联系⼈绑定产品,则加⼀条数据进⼊T_FUNDCONTACTRELA产品联系⼈关联关系表,在关联关系表的主要有CONTACTOR_ID这个字段绑定关系。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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类型能包含视频、图像、文本、音频、应用程序等数据。