当前位置: 首页 > 后端技术 > Java

Java笔记(九)

时间:2023-04-01 23:25:37 Java

JDK新特性一、Lambda表达式1、体验Lambda表达式要求:启动一个线程,在控制台输出一句话:多线程程序启动方法一:定义一个类MyRunnable实现Runnable接口,编写run()方法创建MyRunnable类的对象创建Thread类的对象并将MyRunnable对象作为构造参数传入启动线程方法二:改进匿名内部类的方法newThread(newRunnable(){@Overridepublicvoidrun(){System.out.println("多线程程序启动");}}).start();该方法的形参为空,表示调用该方法时不需要传递任何参数。当方法返回值类型为void时,表示该方法执行不返回结果。方法体中的内容就是我们需要做的。方法三:改进的Lambda表达式newThread(()->{System.out.println("多线程程序启动");}).start();():里面没有内容,可以看做是方法形参为空。->:使用箭头指向下一步要做的事情。{}:包含一段代码,称为代码块,可视为方法体的内容。构成Lambda表达式的三个元素:形式参数、箭头和代码块。Lambda表达式的格式●格式:(形式参数)->{代码块}●形式参数:如果有多个参数,用逗号分隔;如果没有参数,就留空->:英文由一个中间破折号和一个大于号组成,写法是固定的。表示指向动作●代码块:就是我们具体需要做的,也就是我们之前写的方法体内容中使用Llambda表达式的前提:有接口;接口中只有一个抽象方法。2.Lambda表达式的省略方式省略规则:●参数类型可以省略。但是当有多个参数时,你不能只省略一个。如果只有一个参数,则括号可以省略。如果代码块中只有一条语句,可以省略花括号和分号,甚至return。3.Lambda表达式注意事项注意:●使用Lambda时,必须有一个接口,接口中必须有一个且只能有一个抽象方法。●必须有上下文环境,可以推导出Lambda对应的接口。根据局部变量的赋值知道Lambda。对应接口:Runnabler=()->System.out.println("Lambda表达式");根据调用方法的参数知道Lambda对应的接口:newThread(()->System.out.println("Lambdaexpression")).start();4、Lambda表达式和匿名内部类的区别需要不同的类型:匿名内部类:可以是接口也可以是抽象类也可以是具体类Lambda表达式:仅可能是接口使用限制不同:如果有接口中只有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类如果接口中有多个抽象方法,只能使用匿名内部类,不能使用Lambda表达式实现原理不同:●匿名内部类:编译后生成一个单独的.class字节码文件。●Lambda表达式:编译后,没有一个.class字节码文件。相应的字节码是在运行时动态生成的。二、接口的新特性1、接口组成更新概述接口的组成:ConstantpublicstaticfinalAbstractmethodpublicabstractDefaultmethod(Java8)Staticmethod(Java8)Privatemethod(Java9)2.Defaultininterface方法接口中默认方法的定义格式:格式:publicdefault返回值类型方法名(参数列表){}示例:publicdefaultvoidshow3(){}接口中默认方法注意事项:默认方法不是一个抽象方法,所以它不是强制被重写的。但是可以重写,写的时候去掉default关键字public可以省略,default不能省略3.接口中的静态方法接口中静态方法的定义格式:格式:publicstatic返回值类型方法名(参数列表){}●示例:publicstaticvoidshow(){}接口中静态方法注意事项:●静态方法只能通过接口名调用,不能通过实现类名或对象名调用●public可以省略,static不能省略4.Interface私有方法接口中私有方法的定义格式:格式一:私有返回值类型方法名(参数列表){}例一:privatevoidshow(){}格式二:私有静态返回值类型方法名(参数列表){}示例2:privatestaticvoidmethod(){}接口中私有方法注意事项:默认方法可以调用私有静态方法和非静态方法静态方法只能调用私有静态方法三.方法引用1.方法引用符方法引用符●::该符号是引用运算符,它所在的表达式称为方法引用。在经验方法参考中查看我们的代码:Lambda表达式:usePrintable(s->System.out.println(s));分析:获取参数s后,通过Lambda表达式传递给System.out.println方法进行处理●方法参考:usePrintable(System.out::printIn);分析:直接用System.out中的println方法代替Lambda,代码更简洁,省略:●如果使用Lambda,那么可以根据“是”可以省略的原则推导,不需要指定参数类型,不需要指定重载形式,会自动推导●如果使用方法引用,也可以按上面推导●方法引用是Lambda的孪生兄弟2.引用一个类method引用类方法实际上是引用类的静态方法●格式:类名::static方法●示例:Integer::parseIntInteger类方法:publicstaticintparselnt(Strings)将这个String转换为int类型数据练习:●定义一个接口(Converter),其中定义一个抽象方法intconvert(Strings);●定义一个测试类(ConverterDemo),在测试类中提供两个方法一个方法是:useConverter(Converterd)一个方法是main方法,在main方法中调用useConverter方法3.引用对象的实例方法引用对象的实例方法实际上是引用类中的一个成员方法格式:object::membermethod示例:"HelloWorld"::toUpperCaseString类中的方法:publicStringtoUpperCase(),把这个String的所有字符都转成大写做法:定义一个类(PrintString),里面定义了一个方法publicvoidprintUpper(Strings):把字符串参数转成大写数据,然后在控制台输出定义一个接口(Printer),接口定义一个抽象方法voidprintUpperCase(Strings)定义一个测试类(PrinterDemo),在测试类中提供两个方法一个方法是:usePrinter(Printerp)一个方法是main方法,方法中调用了usePrinter方法方法四、引用类的实例方法引用类的实例方法实际上是引用类中的成员方法格式:类名::成员方法示例:String::substringString类中的方法:publicStringsubstring(intbeginIndex,intendIndex)从beginIndex到endIndex,截取字符串,返回长度为endIndex-beginIndex的子串做法:定义一个接口(MyString),接口定义了一个抽象方法:StringmySubString(Strings,intx,inty);●定义一个测试类(MyStringDemo),在测试类中提供两个方法一个方法是:useMyString(MyStringmy)一个方法是main方法,在main方法中调用useMyString方法5.引用构造函数引用一个构造函数其实就是一个引用一个构造方法格式:类名::new例子:Student::new实践:定义一个类(Student),有两个成员变量(name,age),并提供一个无参构造方法对应的get和set方法带参数和成员变量的构造方法定义一个接口(StudentBuilder),接口定义一个抽象方法Studentbuild(Stringname,intage);定义一个测试类(StudentDemo),在测试中提供了两个方法一个方法是:useStudentBuilder(StudentBuilders)另一个方法是main方法,在main方法中调用useStudentBuilder方法四、功能接口1、功能接口概述功能接口:一个只有一个抽象方法的接口JavaJava中的函数式编程是Lambda表达式,所以函数式接口是Lambda可以使用的接口。只有保证接口中只有一个抽象方法,才能顺利推导Java中的Lambda。如何查看一个接口是否是函数式接口呢?@Functionallnterface放在接口定义上面:如果接口是函数式接口,编译通过;如果不是,则编译失败。注意:@Functionallnterface在我们定义自己的函数式接口时是可选的。即使我不写这个注解,只要满足函数式接口定义的条件,它仍然是函数式接口。但是,建议添加此注释。2.函数式接口作为方法的参数定义一个类(RunnableDemo),在类中提供两个方法一个方法是:startThread(Runnabler)方法参数Runnable是一个函数式接口,另一个方法是main方法,在方法调用startThread方法如果方法的参数是函数式接口,我们可以使用Lambda表达式作为参数传递startThread(0->System.out.println(Thread.currentThread().getName()+"threadstarted));3.函数式接口作为方法的返回值要求:定义一个类(ComparatorDemo),类中提供两个方法,一个方法是:ComparatorgetComparator()方法的返回值Comparator是一个函数式接口,一个方法是main方法,在方法中调用getComparator方法如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为返回结果privatestaticComparatorgetComparator(){返回(s1,s2)->s1。length()-s2.length();}4.Supplier接口Supplier:包含一个没有参数的方法Tget():获取结果这个方法不需要参数,它会遵循一定的实现逻辑(通过Lambda表达式实现)返回数据Supplier接口也称为生产接口。如果我们指定了接口范式的类型,那么接口中的get方法会产生什么样的数据供我们使用5.Consumer接口Consumer:包含两个方法voidaccept(Tt):执行这个操作给定参数defaultConsumerandThen(Consumerafter):返回一个组合Consumer,依次执行本次操作,然后执行after操作●Consumer接口也叫消费接口,数据的数据类型它消耗由泛型指定。6、Predicate接口Predicate:常用的四种方法booleantest(Tt):判断给定的参数(判断逻辑由Lambda表达式实现),返回一个布尔值defaultPredicatenegate():返回一个逻辑否定,对应非逻辑defaultPredicateand(Predicateother):返回组合判断,对应shortcircuit和defaultPredicateor(Predicateother):返回组合判断,对应shortcircuitOrthePredicate接口通常用于判断参数是否满足指定条件。,33"};字符串数组中有多条信息,请通过Predicate接口的组装将符合要求的字符串过滤到集合ArrayList中,并遍历ArrayList集合●同时满足以下要求:姓名长度大于2;年龄大于33publicclassPredicateTest{publicstaticvoidmain(String[]args)[String[]strArray={"林青霞,30","柳岩,34",张曼玉,35",貂蝉,31","王祖贤,33"};ArrayListarray=myFilter(strArray,s->s.split(",")[0].length()>2,s->Integer.parseInt(s.split(",")[1])>33);for(Stringstr:array){System.out.println(str);}}//通过汇编Predicate接口的,将符合要求的字符串过滤到集合Arraylist中privatestaticArrayListmyFilter(String[]strArray,Predicatepre1,Predicatepre2){//定义一个集合ArrayListarray=newArrayList();//遍历数组for(Stringstr:strArray){if(pre1.and(pre2).test(str)){数组。添加(海峡);}}返回数组;}}7.函数接口Function:两个常用的方法Rapply(Tt):将这个函数应用于给定的参数defaultFunctionandThen(Functionafter):返回一个组合函数,首先应用functiontoinputandthenapplytheafterfunctiontotheresultFunction接口通常用于处理和转换参数(处理逻辑由Lambda表达式实现),然后返回一个新值。遍历创建一个集合,存储多个字符串元素将集合中以“张”开头的所有元素存储到一个新集合中将以“张”开头的集合中长度为3的元素存储到一个新的集合中遍历上一步得到的集合使用Stream完成过滤操作:list.stream().filter(s->s.startsWith("Zhang")).filter(s->s.length()==3).forEach(System.out::打印);●直读代码字面意思,完美展现无关逻辑模式的语义:生成流,筛选姓氏,筛选长度为3,逐条打印。Java2引入的函数式编程风格Stream流的生成方式Stream流的使用通过数据源(集合、数组等)生成流来生成流list.stream()可以在流之后进行中间操作跟随零个或多个中间操作,其主要目的是打开流,做某种程度的数据过滤/映射,然后返回一个新的流供下一个操作使用filter()终端操作一个流只能有终结操作。当执行此操作时,流被“点亮”并且不能再被操作。所以这一定是流的最后一个操作。ForEach()是生成流的常用方法。Collection系统中的集合可以使用默认的方法stream()来生成流。默认Streamstream()。Map系统中的集合可以间接生成流。数组可以通过Stream接口的(T...values)静态方法生成流3.Stream常用的中间操作方法Streamfilter(Predicatepredicate):用于过滤流中的数据方法中的方法Predicateinterfacebooleantest(Tt):判断给定的参数,返回一个布尔值Streamlimit(longmaxSize):返回这个流中的元素组成的流,截取Stream之前指定参数个数的数据skip(longn):跳过指定参数个数的数据,返回一个由流的剩余元素组成的流staticStreamconcat(Streama,Streamb):合并aandbAstream是一个streamStreamdistinct():返回由stream的不同元素组成的stream(根据Object.equals(Object))Streamsorted():返回由的元素组成的stream此流Stream,按照自然顺序排序Streamsorted(Comparatorcomparator):返回由流的元素组成的流,按照提供的ComparatorStreammap(Functionmapper):返回由函数接口R中的方法创建的流apply(Tt)IntStreammapTolnt(TolntFunctionmapper):返回一个IntStream,其中包含将给定函数应用于此流的元素的结果。4.Stream流的常用终端操作方法Stream的常用终端操作方法voidforEach(Consumeraction):对流的每个元素执行操作Consumer接口中的方法voidaccept(Tt):对给定的参数执行此操作operationlongcount():返回这个stream中的元素个数5.Stream流的集合操作使用Stream流的方法来操作数据,我想把stream中的数据收集到一个集合中,应该怎么办做??Stream收集方法Rcollect(Collectorcollector)但是这个收集方法的参数是一个Collector接口工具类Collectors提供了具体的收集方法publicstaticCollectortoList():将元素收集到List集合中publicstaticCollectortoSet():将元素收集到Set中setpublicstaticCollectortoMap(FunctionkeyMapper,FunctionvalueMapper):将元素收集到Map集合中