




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java8新特新Lambda Stream function map(函数式编程)1.接口的默认方法Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法/Formula表示一个设计 计算公式 的接口 public interface Formula /计算double calculate(int a);/开方default double sqrt(int a)return Math.sqrt(a);main:Formula f = new Formula() Overridepublic double calculate(int a) return a+1;System.out.println(f.calculate(4);System.out.println(f.sqrt(8);注意:现在接口还可以存在静态方法,可以使用 接口名.静态方法名 的形式直接调用2.Lambda 表达式2.1 认识Lambda表达式例如:public class LambdaTest1 public static void main(String args) /假如一个list机会中的元素要排序List list = Arrays.asList(hello,tom,apple,bbc);/之前的排序我们可以这样写Collections.sort(list, new Comparator()Overridepublic int compare(String o1, String o2) return -pareTo(o2););/使用Lambda表达式Collections.sort(list,(String s1,String s2)-return pareTo(s2););/可以简写为/1.大括号里面就一句代码/2.编译器可以自动推导出参数类型Collections.sort(list,(s1,s2)-pareTo(s2);System.out.println(list);2.2 Functional接口“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。例如:public class LambdaTest2 public static void main(String args) LambdaTest2 t = new LambdaTest2();/也可以先创建对象/Action1 a1 = ()-System.out.println(hello);t.test1()-System.out.println(hello);/Action2 a2 = (f)-这个数字是:+f;/如果参数就一个,那么还可以这样简写 去掉小括号Action2 a2 = f-这个数字是:+f;t.test2(a2);public void test1(Action1 a)a.run();public void test2(Action2 a)System.out.println(a.run(3);/这个注解不加也可以,加上只是为了让编译器检查FunctionalInterfaceinterface Action1public void run();/这个注解不加也可以,加上只是为了让编译器检查FunctionalInterfaceinterface Action2public T run(F f);注意:lambda表达式无法访问接口的默认方法2.3 方法与构造函数引用Java 8 允许你使用 : 关键字来传递方法(静态方法和非静态方法)例如:public class LambdaTest3 public static void main(String args) LambdaTest3 t = new LambdaTest3();/使用Lambda引用类的静态方法/能引用Integer类中的静态方法toBinaryString的原因是:/Action3接口中只有一个方法且方法的参数类型和返回值类型/与Integer类中的静态方法toBinaryString的参数类型、返回类型是一致的Action3 a3 = Integer:toBinaryString;System.out.println(a3.run(4);/使用Lambda引用对象的非静态方法/能引用对象t中的非静态方法test的原因是和上面的描述是一致的Action3 aa3 = t:test;System.out.println(aa3.run(4);public String test(int i)return i=+i;FunctionalInterfaceinterface Action3public String run(int Integer);下面是一个接口中带泛型的时候特殊例子: 可以使用 类名:非静态方法 的形式引用方法public class LambdaTest6 public static void main(String args) Model m = new Model();/方法有一个参数,然后没返回类型,这里参数类型会自动识别Action a1 = (s)-System.out.println(hello);a1.run(m);/注意:如果这里泛型类型不是Model 那么就不能引用Model中的方法/可以引用Model类中任意方法 只要满足一点:该方法没有参数/将来run方法中就会调用Model类型对象m的此处引用的方法Action a2 = Model:test3;a2.run(m);/引用对象m中的test2方法/因为test2方法的参数和返回类型和Action接口的方法完全一致Action a3 = m:test2;a3.run(m);interface Actionpublic void run(T t);class Modelpublic void test1()System.out.println(test1);public void test2(Model a)System.out.println(test2);public int test3()System.out.println(test3);return 1;Java 8 允许你使用 : 关键字来引用构造函数public class LambdaTest4 public static void main(String args) /Lambda表达式引用构造函数/根据构造器的参数来自动匹配使用哪一个构造器Action4Creater creater = Action4:new;Action4 a4 = creater.create(zhangsan);a4.say();class Action4private String name;public Action4() public Action4(String name) = name;public void say()System.out.println(name = +name);interface Action4Createrpublic Action4 create(String name);2.4 lambda表达式中的变量访问public class LambdaTest5 private static int j;private int k;public static void main(String args) LambdaTest5 t = new LambdaTest5();t.test();public void test()int num = 10;j = 20;k = 30;/lambda表达式中可以访问成员变量也可以方法局部变量Action5 a5 = (i)-System.out.println(操作后:i=+(i+num+j+k);a5.run(1);/但是这个被访问的变量默认变为final修饰的 不可再改变 否则编译不通过/num = 60;j = 50;k = 70;interface Action5public void run(int i);2.5 Predicate接口和lambda表达式java.util.function.Predicate接口是用来支持java函数式编程新增的一个接口,使用这个接口和lamb表达式就可以以更少的代码为API方法添加更多的动态行为。 public class LambdaTest6 public static void main(String args) List languages = Arrays.asList(Java, html5,JavaScript, C+, hibernate, PHP);/开头是J的语言filter(languages,(name)-name.startsWith(J);/5结尾的filter(languages,(name)-name.endsWith(5);/所有的语言filter(languages,(name)-true);/一个都不显示filter(languages,(name)-false);/显示名字长度大于4filter(languages,(name)-name.length()4);System.out.println(-);/名字以J开头并且长度大于4的Predicate c1 = (name)-name.startsWith(J);Predicate c2 = (name)-name.length()4;filter(languages,c1.and(c2);/名字不是以J开头Predicate c3 = (name)-name.startsWith(J);filter(languages,c3.negate();/名字以J开头或者长度小于4的Predicate c4 = (name)-name.startsWith(J);Predicate c5 = (name)-name.length()4;filter(languages,c4.or(c5);/名字为Java的filter(languages,Predicate.isEqual(Java);/判断俩个字符串是否相等boolean test = Predicate.isEqual(hello).test(world);System.out.println(test);public static void filter(List languages, Predicate condition) for(String name: languages) if(condition.test(name) System.out.println(name + ); 2.6 Function 接口 Function有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法 compose方法表示在某个方法之前执行 andThen方法表示在某个方法之后执行 注意:compose和andThen方法调用之后都会把对象自己本身返回,这可以方便链式编程 default Function andThen(Function after) 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。default Function compose(Function before)返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象。static Function identity() 返回一个执行了apply()方法之后只会返回输入参数的函数对象。public interface Function R apply(T t);default Function compose(Function before) Objects.requireNonNull(before);return (V v) - apply(before.apply(v);default Function andThen(Function after) Objects.requireNonNull(after);return (T t) - after.apply(apply(t);/注意: t-t是(t)-t的简写/t-t是作为方法identity的返回值的,也就是Function类型对象/类似于这样的写法:Function f = t-t;/那么f.apply(test) 返回字符串test/传入什么则返回什么static Function identity() return t - t;例如:public class LambdaTest7 /静态内部类private static class Studentprivate String name;public Student(String name) = name;public String getName() return name;public static void main(String args) /*用户注册输入一个名字tom*/String name = tom;/*使用用户的输入的名字创建一个对象*/Function f1 =(s)-new Student(s);/注意上面的代码也可以写出这样,引用类中的构造器/Function f1 =Student:new;Student stu1 = f1.apply(name);System.out.println(stu1.getName();/*需求改变,使用name创建Student对象之前需要给name加一个前缀*/Function before = (s)-briup_+s;/表示f1调用之前先执行before对象的方法,把before对象的方法返回结果作为f1对象方法的参数Student stu2 = pose(before).apply(name);System.out.println(stu2.getName();/*获得创建好的对象中的名字的长度*/Function after = (stu)-stu.getName().length();/before先调用方法,结果作为参数传给f1来调用方法,结果再作为参数传给after,结果就是我们接收的数据int len = pose(before).andThen(after).apply(name);System.out.println(len); 2.7 Supplier接口Supplier接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数public interface Supplier T get();例如:public class LambdaTest8 public static void main(String args) /生成一个八位的随机字符串Supplier f = ()-String base = abcdefghijklmnopqrstuvwxyz0123456789; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i 8; i+) /生成0,base.length)之间的随机数int number = random.nextInt(base.length(); sb.append(base.charAt(number); return sb.toString(); ;System.out.println(f.get();2.8 Consumer接口Consumer接口接收一个任意范型的值,和Function接口不同的是该接口没有任何值public interface Consumer void accept(T t);default Consumer andThen(Consumer after) Objects.requireNonNull(after);return (T t) - accept(t); after.accept(t); ;例如:public class LambdaTest9 /静态内部类private static class Studentprivate String name;public String getName() return name;public void setName(String name) = name;public static void main(String args) Student s = new Student();s.setName(tom);Consumer c = stu-System.out.println(hello!+stu.getName();c.accept(s);总结:Function 接口 R apply(T t); 有参数有返回值Supplier 接口 T get(); 没参数有返回值Consumer 接口 void accept(T t); 有参数没返回值另外需要注意的接口: 其用法和上面介绍的接口使用方式类同BinaryOperator接口 T apply(T t, T t) 将两个T作为输入,返回一个T作为输出BiFunction接口 R apply(T t, U u) 将一个T和一个U输入,返回一个R作为输出BinaryOperator接口继承了BiFunction接口public interface BinaryOperator extends BiFunctionBiConsumer接口 void accept(T t, U u) 将俩个参数传入,没有返回值2.9 Optional类Optional 不是接口而是一个类,这是个用来防止NullPointerException异常的辅助类型Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。public class Optotion public static void main(String args) /*of方法 为非null的值创建一个Optional*/of方法通过工厂方法创建Optional类。/需要注意的是,创建对象时传入的参数不能为null。/如果传入参数为null,则抛出NullPointerException 。Optional op1 = Optional.of(hello);/*ofNullable方法 为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。*/ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况Optional op2 = Optional.ofNullable(null);/*isPresent方法 如果值存在返回true,否则返回false。*/*get方法 如果Optional有值则将其返回,否则抛出NoSuchElementException。*/if(op1.isPresent()System.out.println(op1.get();if(op2.isPresent()System.out.println(op2.get();/*ifPresent方法 如果Optional实例有值则为其调用consumer,否则不做处理*/consumer接口中的方法只有参数没有返回值op1.ifPresent(str-System.out.println(str);op2.ifPresent(str-System.out.println(str);/这个不执行 因为op2里面的值是null/*orElse方法 如果有值则将其返回,否则返回指定的其它值。*/System.out.println(op1.orElse(如果op1中的值为null则返回这句话,否则返回这个值);System.out.println(op2.orElse(如果op2中的值为null则返回这句话,否则返回这个值);/*orElseGet方法 orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。*/Supplier接口中的方法没有参数但是有返回值System.out.println(op1.orElseGet()-自己定义的返回值);System.out.println(op2.orElseGet()-自己定义的返回值);/*orElseThrow方法 如果有值则将其返回,否则抛出supplier接口创建的异常。*/在orElseThrow中我们可以传入一个lambda表达式或方法,如果值不存在来抛出异常。/orElseThrow方法的声明如下 所有只能返回一个Throwable类型对象/public T orElseThrow(Supplier exceptionSupplier) throws Xtry System.out.println(op1.orElseThrow(Exception:new);/System.out.println(op2.orElseThrow(Exception:new);这个会抛出异常 catch (Exception e) e.printStackTrace();/*map方法 如果有值,则对其执行调用mapper函数得到返回值。*/返回值并且依然Optional包裹起来,其泛型和你返回值的类型一致/public Optional map(Function mapper)Optional map1 = op1.map(str-1);System.out.println(map1.get();Optional map2 = op2.map(str-1.2);System.out.println(map2.orElse(0.0);/*flatMap方法 如果有值,为其执行mapper函数返回Optional类型返回值,否则返回空Optional。*/flatMap与map方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。/需要我们自己把返回值封装为Optional/public Optional flatMap(Function? super T, Optional mapper) System.out.println(op1.flatMap(str-Optional.of(str+_briup).get();/op1.flatMap(str-);编译出错/*filter方法 如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。*/public Optional filter(Predicate predicate) op1 = op1.filter(str-str.length()str.length()10);System.out.println(op1.orElse(值为null);2.10 Stream 接口java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来(链式编程)。Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作2.10.1 Stream对象的构建:/ 1.使用值构建Stream stream = Stream.of(a, b, c);/ 2. 使用数组构建String strArray = new String a, b, c;Stream stream = Stream.of(strArray);Stream stream = Arrays.stream(strArray);/ 3. 利用集合构建(不支持Map集合)List list = Arrays.asList(strArray);stream = list.stream();对于基本数值型,目前有三种对应的包装类型 Stream:IntStream、LongStream、DoubleStream。当然我们也可以用 Stream、Stream 、Stream,但是 自动拆箱装箱会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。Java 8 中还没有提供其它基本类型数值的Stream2.10.2 数值Stream的构建:IntStream stream1 = IntStream.of(new int1, 2, 3);/1,3)IntStream stream2 = IntStream.range(1, 3);/1,3IntStream stream3 = IntStream.rangeClosed(1, 3);2.10.3 Stream转换为其它类型:Stream stream = Stream.of(hello,world,tom);/ 1. 转换为ArrayString strArray = stream.toArray(String:new);/ 2. 转换为CollectionList list1 = stream.collect(Collectors.toList();List list2 = stream.collect(Collectors.toCollection(ArrayList:new);Set set3 = stream.collect(Collectors.toSet();Set set4 = stream.collect(Collectors.toCollection(HashSet:new);/ 3. 转换为StringString str = stream.collect(Collectors.joining().toString();特别注意 : 一个 Stream 只可以使用一次,上面的代码为了简洁而重复使用了多次。这个代码直接运行会抛出异常的:java.lang.IllegalStateException: stream has already been operated upon or closed2.10.4 Stream操作当把一个数据结构包装成Stream后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下。Intermediate:中间操作map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unorderedTerminal: 最终操作forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iteratorShort-circuiting: 短路操作anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limitmap/flatMap映射 把 Stream中 的每一个元素,映射成另外一个元素。例子:转换大写Stream wordList = Stream.of(hello,world,tom);List output = wordList. map(String:toUpperCase). collect(Collectors.toList(); /也可以直接使用forEach循环输出wordList.map(String:toUpperCase).collect(Collectors.toList().forEach(System.out:println);例子:计算平方数List nums = Arrays.asList(1, 2, 3, 4);List squareNums = nums.stream().map(n - n * n).collect(Collectors.toList();map生成的是个1:1映射,每个输入元素,都按照规则转换成为另外一个元素。还有一些场景,是一对多映射关系的,这时需要 flatMap。map和flatMap的方法声明是不一样的 Stream map(Function mapper); Stream flatMap(Function? super T, ? extends Stream mapper);例子:/stream1中的每个元素都是一个List集合对象StreamList stream1 = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) );Stream stream2 = stream1.flatMap(e) - e.stream();stream2.forEach(e-System.out.println(e);/输出1 2 3 4 5 6flatMap 把 stream1 中的层级结构扁平化,就是将最底层元素抽出来放到一起,最终新的 stream2 里面已经没有 List 了,都是直接的数字。例子:Stream stream1 = Stream.of(tom.Li,lucy.Liu);/flatMap方法把stream1中的每一个字符串都用.分割成了俩个字符串/最后返回了一个包含4个字符串的stream2Stream stream2 = stream1.flatMap(s-Stream.of(s.split(.);stream2.forEach(System.out:println);输出结果:tomLilucyLiuforEach 遍历 接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。forEach 是 terminal 操作,执行完stream就不能再用了例子:List list = Arrays.asList(test,hello,world,java,tom,C,javascript);list.stream().forEach(System.out:println);filter 过滤 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作例子:List list = Arrays.asList(test,hello,world,java,tom,C,javascript);list.stream().filter(s-s.length()4).forEach(System.out:println);注意:System.out:println 这个是lambda表达式中对静态方法的引用peek 对每个元素执行操作并返回一个新的 Stream注意:调用peek之后,一定要有一个最终操作peek是一个intermediate 操作例子:List list = Arrays.asList(one, two, three, four)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 桡骨头骨折课件
- 2025年公务员考试练习题考试练习题及答案指导
- 2025年融媒体舆情分析笔试高频考点解析集
- 桌球培训课程内容
- 2025年篮球规则试题及答案
- 2025年篮球明星试题及答案
- 2025年注册验船师资格考试(A级船舶检验专业案例分析)综合试题及答案二
- 桃红葡萄酒发酵工艺
- 2025年视觉设计岗位面试常见题
- 栽蒜苗课件教学课件
- 2025年广西玉林产业投资集团有限公司社会招聘5人笔试备考题库及答案解析
- 《质量管理与可靠性》课件-第4章 质量检验
- 2025年财政部高层次财会人才选拔考试历年参考题库含答案详解(5套)
- 电子技术基础说课
- 医院科室主任年度目标责任书模板
- 2025年成考考试题目解析及答案
- 2025年足球裁判三级试题及答案
- 旅行团队管理办法
- 2025年秋期部编版四年级上册小学语文教学计划+教学进度表
- 2025年特种设备检验检测项目合作计划书
- 安全生产投入费用明细
评论
0/150
提交评论