JDK8新特性
jdk8 optional list 业务转换写法 -回复
jdk8 optional list 业务转换写法-回复JDK8 Optional List业务转换写法在Java编程中,Optional是JDK8引入的一个新特性,旨在解决空指针异常的问题。
通过Optional,我们可以更好地处理可能为null的值,避免了繁琐的空值检查和错误处理。
本文将以JDK8 Optional List业务转换写法为主题,详细介绍如何利用Optional和List进行业务转换,以及为什么使用Optional和List能够提高代码的可读性和可维护性。
1. 什么是Optional和List?在开始之前,我们先简单介绍一下Optional和List的概念。
Optional是一个容器类,可用于包装一个可能为null的值。
通过Optional 类,我们可以更好地处理可能为null的值,避免了空指针异常的问题。
List是Java中的一个接口,用于表示一个有序的集合。
List可以包含任意类型的元素,并且可以动态地改变其大小。
2. 为什么使用Optional和List进行业务转换?在实际的业务场景中,我们经常需要对数据进行转换或者处理。
传统的方法中,我们需要进行繁琐的空值判断和错误处理,容易导致代码的冗余和可读性的降低。
而使用Optional和List进行业务转换,则可以避免这些问题。
Optional 可以更好地处理可能为null的值,而List则提供了丰富的转换和处理方法,能够更方便地进行数据的处理和转换。
3. 如何利用Optional和List进行业务转换?下面我们将一步一步介绍如何利用Optional和List进行业务转换。
首先,我们假设有一个需求:给定一个Person对象列表,我们需要找出其中年龄大于18岁的人,并返回一个包含这些人的名字的List列表。
javaclass Person {private String name;private int age;省略构造函数和getter/setter方法List<Person> persons = Arrays.asList(new Person("Alice", 17),new Person("Bob", 20),new Person("Carol", 19),new Person("David", 22));首先,我们可以使用stream()方法将List转换为流,并使用filter()方法对流中的元素进行过滤。
java技术选型
java技术选型综述JDK版本:JDK8/JDK7 + OracleJDK/OpenJDKJava开发框架:Spring Boot/Spring + Hibernate/MyBatis前后端分离:单页应⽤/模板引擎前后端接⼝⽂档⾃动⽣成:Swagger业务端逻辑校验框架:Functional Validator/Fluent Validator/Hibernate ValidatorCT框架:RundeckUT框架:TestNG/JUnit历史操作记录⽅案:Canal/AOP/硬编码1. JDK版本1.1 Why JDK8?开发效率的提升:⽤更少的代码完成更多的⼯作(Lambda代替匿名内部类、易于并⾏)可以使⽤函数式思维编程(⾼阶函数解放思想、消除副作⽤、简洁、各语⾔发展的趋势)未来趋势:⼀些开源项⽬及框架开始基于java8开发JVM新特性:元空间代替永久代(避免JDK以及前期版本中常见的永久内存错误OOM:PermGen)1.1.1 JDK8与JDK7代码对⽐JDK7JDK8for (int i = 0; i < arr.length; i++) {if (arr[i] % 2 != 0) {arr[i]++;}System.out.println(arr[i]); }Stream.of(arr).map(x →(x % 2 == 0 ? x : x + 1)) .forEach(System.out::println);Optional:优雅的处理nullJDK7JDK8 public User getUser() {return user;}public List<Order> getOrders() { User user = getUser();if (user != null) {return user.getOrders();} else {return Collections.emptyList(); }}public Optional<User> getUser() { return Optional.ofNullable(user);}public List<Order> getOrders() { return getUser().map(u → u.getOrdes()) .orElse(Collections.emptyList());}建议:如果接⼝的返回值有可能是null,请⽤Optional封装优雅,下游不⽤写恶⼼的if-else判断安全:告知接⼝的使⽤⽅返回值可能为null,需要处理,以避免代码缺陷⽂档化:接⼝中可能为空的值⽂档化1.1.2 易于并⾏统计1-1000000内所有质数的数量串⾏并⾏IntStream.range(1, 1000000) .filter(PrimeUtil::isPrime).count();IntStream.range(1, 1000000) .parallel().filter(PrimeUtil::isPrime).count();增强的Future:CompletableFuture读写锁的改进:StampedLock(乐观的读策略增加系统的并⾏度)原⼦类的增强:LongAdder(更快的原⼦类)、LongAccumulator1.1.3 JVM新特性:元空间代替永久代参考:JDK7:“永久的”数据存放在⼀个叫做永久代的区域。
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,这样效率更⾼)。
JDK8新特性去重对象中重复的字段
JDK8新特性去重对象中重复的字段问题当下互联⽹技术成熟,越来越多的趋向去中⼼化、分布式、流计算,使得很多以前在数据库侧做的事情放到了Java端。
今天有⼈问道,如果数据库字段没有索引,那么应该如何根据该字段去重?⼤家都⼀致认为⽤Java来做,但怎么做呢?解答忽然想起以前写过list去重的⽂章,找出来⼀看。
做法就是将list中对象的hashcode和equals⽅法重写,然后丢到HashSet⾥,然后取出来。
这是最初刚学Java的时候像被字典⼀样背写出来的答案。
就⽐如⾯试,⾯过号称做了3年Java的⼈,问Set和HashMap的区别可以背出来,问如何实现就不知道了。
也就是说,初学者只背特性。
但真正在项⽬中使⽤的时候你需要确保⼀下是不是真的这样。
因为背书没⽤,只能相信结果。
你需要知道HashSet如何帮我做到去重了。
换个思路,不⽤HashSet可以去重吗?最简单,最直接的办法不就是每次都拿着和历史数据⽐较,都不相同则插⼊队尾。
⽽HashSet只是加速了这个过程⽽已。
⾸先,给出我们要排序的对象User@Data@Builder@AllArgsConstructorpublic class User {private Integer id;private String name;}List<User> users = Lists.newArrayList(new User(1, "a"),new User(1, "b"),new User(2, "b"),new User(1, "a"));⽬标是取出id不重复的user,为了防⽌扯⽪,给个规则,只要任意取出id唯⼀的数据即可,不⽤拘泥id相同时算哪个。
⽤最直观的办法这个办法就是⽤⼀个空list存放遍历后的数据。
@Testpublic void dis1() {List<User> result = new LinkedList<>();for (User user : users) {boolean b = result.stream().anyMatch(u -> u.getId().equals(user.getId()));if (!b) {result.add(user);}}System.out.println(result);}⽤HashSet背过特性的都知道HashSet可以去重,那么是如何去重的呢?再深⼊⼀点的背过根据hashcode和equals⽅法。
JDK1.7与JDK1.8的区别,你知道了吗
JDK1.7与JDK1.8的区别,你知道了吗Java 8于2014年3⽉18⽇发布,在阅读相关⽂章后,在本教程中,我们将通过⽰例研究 Java 8功能。
⼀、Java 8 的新特性1. Iterable 接⼝中的 forEach()⽅法2. 接⼝中允许有默认⽅法和静态⽅法3. 函数式接⼝与 Lambda 表达式4. ⽤于集合上批量数据操作的 Java Stream API5. 新的时间 API6. 集合 API 的改进7. 并发 API 的改进8. Java IO 的改进9. 其他核⼼ API 的改进以上是 Java 8 的新特性的列举,接下来展⽰⼀些代码⽚段,来更好理解这些新特性⼆、新特性应⽤2.1、Iterable 接⼝中的 forEach()⽅法package com.taotao.springboot;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.function.Consumer;public class IterableForEachExample {public static void main(String[] args) {List<Integer> ints = new ArrayList<>();for (int i = 0; i < 10; i++) ints.add(i);//迭代器遍历Iterator<Integer> iterator = ints.iterator();while (iterator.hasNext()) {Integer i = iterator.next();System.out.println("Iterator Value::" + i);}//使⽤forEach⽅法遍历,这⾥使⽤了匿名内部类ints.forEach(new Consumer<Integer>() {public void accept(Integer t) {System.out.println("forEach anonymous class Value::" + t);}});//通过实现Consumer接⼝的⼦类遍历,业务处理从遍历逻辑中抽取出来MyConsumer action = new MyConsumer();ints.forEach(action);}}//实现Conumer接⼝class MyConsumer implements Consumer<Integer> {public void accept(Integer t) {System.out.println("Consumer impl Value::" + t);}}通过上⾯这个例⼦,看出使⽤ forEach()⽅法代码⾏数会增加,但是它将遍历逻辑与业务处理逻辑分离,有助于我们将关注点放在业务逻辑的处理上。
新特性总结及案例
一 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值的结果。
ja8 标准
ja8 标准
Java 8(也称为JDK )于2014年3月18日发布,是Java编程语言的一
个重要版本。
该版本引入了几个新特性和改进,包括Lambda表达式、流API、默认方法、Optional类、日期和时间API等。
Lambda表达式是一个重要的新特性,它允许以更简洁和更功能性的方式表示行为。
流API则提供了处理数据序列的高级功能,如过滤、映射、排序和聚合等。
默认方法允许在接口中添加新方法,而不会破坏实现这些接口的类的兼容性。
Optional类用于更好地处理null值,并减少空指针异常。
日期
和时间API提供了更直观和全面的日期和时间处理功能。
此外,Java 8还有索尼爱立信大众市场功能性手机Java平台8(JP-8)新
增的API,包括MSA通用标准JSR-248: 安全及可信服务API(JSR-177)、定位服务API (JSR-179)、J2ME的SIP API (JSR-180)、移动终端3D图形API (JSR-184)、内容管理者API (JSR-211)、J2ME可变2D矢量图形API (JSR-226)、移动支付API (JSR-229)、移动国际化API (JSR-238)、索尼爱立信补充的API(非MSA标准API)、适用于OpenGLJava® ES API的Java 绑定 (JSR-239)和适用于可以感应振动的应用的移动传感器API (JSR 256)等。
如需更多关于Java 8标准的信息,建议查阅相关资料或咨询专业的技术从业者。
互联网大厂面试题目答案
阿里篇1.1.1 如何实现一个高效的单向链表逆序输出?1.1.2 已知sqrt(2)约等于1.414,要求不用数学库,求sqrt(2)精确到小数点后10位1.1.3 给定一个二叉搜索树(BST),找到树中第K 小的节点1.1.4 LRU缓存机制1.1.5 关于epoll和select的区别,以下哪些说法是正确的1.1.6 从innodb的索引结构分析,为什么索引的key 长度不能太长1.1.7 MySQL的数据如何恢复到任意时间点?1.1.8 NFS 和SMB 是最常见的两种NAS(Network Attached Storage)协议,当把一个文件系统同时通过NFS 和SMB 协议共享给多个主机访问时,以下哪些说法是错误的1.1.9 输入ping IP 后敲回车,发包前会发生什么?1.2.0 请解释下为什么鹿晗发布恋情的时候,微博系统会崩溃,如何解决?1.2.1 现有一批邮件需要发送给订阅顾客,且有一个集群(集群的节点数不定,会动态扩容缩容)来负责具体的邮件发送任务,如何让系统尽快地完成发送?1.2.2 有一批气象观测站,现需要获取这些站点的观测数据,并存储到Hive 中。
但是气象局只提供了api 查询,每次只能查询单个观测点。
那么如果能够方便快速地获取到所有的观测点的数据?1.2.3 如何实现两金额数据相加(最多小数点两位)1.2.4 关于并行计算的一些基础开放问题1.2.5 请计算XILINX公司VU9P芯片的算力相当于多少TOPS,给出计算过程与公式1.2.6 一颗现代处理器,每秒大概可以执行多少条简单的MOV指令,有哪些主要的影响因素1.2.7 请分析MaxCompute 产品与分布式技术的关系、当前大数据计算平台类产品的市场现状和发展趋势1.2.8 对大数据平台中的元数据管理是怎么理解的,元数据收集管理体系是怎么样的,会对大数据应用有什么样的影响1.2.9 你理解常见如阿里,和友商大数据平台的技术体系差异以及发展趋势和技术瓶颈,在存储和计算两个方面进行概述1.3.0 在云计算大数据处理场景中,每天运行着成千上万的任务,每个任务都要进行IO 读写。
Java8CompletableFuture详解
Java8CompletableFuture详解Java 8来了,是时候学⼀下新的东西了。
Java 7和Java 6只不过是稍作修改的版本,⽽Java 8将会发⽣重⼤的改进。
或许是Java 8太⼤了吧?今天我会给你彻底地解释JDK 8中的新的抽象 – CompletableFuture。
众所周知,Java 8不到⼀年就会发布,因此这篇⽂章是基于JDK 8 build 88 with lambda support的。
CompletableFuture extends Future提供了⽅法,⼀元操作符和促进异步性以及事件驱动编程模型,它并不⽌步于旧版本的Java中。
如果你打开JavaDoc of CompletableFuture你⼀定会感到震惊。
⼤约有五⼗种⽅法(!),⽽且它们中的⼀些⾮常有意思⽽且不好理解,例如:复制代码代码如下:public <U,V> CompletableFuture<V> thenCombineAsync(CompletableFuture<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor)不必担⼼,继续读下去。
CompletableFuture收集了所有ListenableFuture in Guava 和 SettableFuture的特征。
此外,内置的lambda表达式使它更接近于Scala/Akka futures。
这听起来好得令⼈难以置信,但是请继续读下去。
CompletableFuture有两个主要的⽅⾯优于ol中的Future – 异步回调/转换,这能使得从任何时刻的任何线程都可以设置CompletableFuture的值。
通常futures代表其它线程中运⾏的代码,但事实并⾮总是如此。
有时你想要创造⼀个Future来表⽰你知道将会发⽣什么,例如JMS message arrival。
JDk以及各个版本的区别
JDK的含义:java development kit是程序员编写java程序需要的软件,JDK是整个java 的核心,包括了java运行环境、java工具和java基础的类库。
JDK包含的基本组件包括:.javac—编译器,将源程序转成字节码.jar—打包工具,将相关的类文件打包成一个文件.javadoc—文档生成器,从源码注释中提取文档.jdb—debugger,查错工具.java—运行编译后的java程序appletviewer:小程序浏览器,一种执行HTML文件上的java小程序的java浏览器。
javah:产生可以调用java过程的C过程,或建立能被java程序调用的C过程的头文件。
javap:java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。
jconsole:java进行系统调试和监控的工具。
ng:这个是系统的基础类,比如String等都是这里面的,这个package是唯一一个可以不用import就可以使用的package;java.io:这里面有所有输入输出有关的类,比如文件操作等;:这是与网络有关的类,比如URL,URLConnection等;java.util:这个是系统辅助类,特别是集合类Collection,List,Map等;java.sql:这个是数据库操作的类,Connection,Statement,ResultSet等;javax.servlet这个是JSP,Servlet等使用到的类;JDK各个版本的新特性:jdk1.5的新特性(代号:猛虎):1.静态导入(import static)import语句可以导入一个类或是某个包中的所有类。
import static 语句可以导入一个类中的某个静态方法或是所有静态方法。
例如:Math类提供了很多于数学运算的静态方法,通常情况下我们是以Math.abs();这样的方式来进行调用函数的。
但是我们可不可以只写出adb();在JDK1.5之后,可以使用import static 语句导入一个类中的某个静态方法或是所有静态方法。
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的每⼀个元素去执⾏给定的动作,直到所有的元素都执⾏完,或者抛出异常。
【黑马程序员】Java面试之Java8新特性
【黑马程序员】Java面试之Java8新特性JDK8的新特性一般都是面试热点话题了,其实不用特别的去记忆,因为加的一些东西我们用的也比较少。
1、JDK8提供了接口static和Default方法。
特别是Default修饰的方法,dafault修饰符是我们设计模式中的适配器设计模式的重要实现原理,让我们接口实现类不需要重写全部的抽象方法,default修饰的方法可以选择性的重写。
2、JDK8新增了线程安全的日期API,在Java.time包下,如LocalDateTime,ZonedDateTimepublic final class ZonedDateTimeimplements Temporal, ChronoZonedDateTime<LocalDate>, Serializable { }1233、对部分接口做了性能提升,list接口增加了sort(comparator)排序功能HashMap性能提升,新节点插入到链表的尾部,当节点数量大于8个时会转换成红黑树concurrentHashMap有原来的分段锁协议提升为CAS算法CAS算法比较- 设置例如现在有三个数:内存值V ,旧的预期值A ,要修改成B那么当且仅当A = V 时,才会修改内存V的值为B并返回true,否则什么都不做返回false,CAS一定要volatile 关键字的支持,利用volatile关键字的可见性,保证每次从主内存中拿到的都是最新的那个值,否则旧的预期值A对于某条线程来说永远都是一个不会变的值只要某次CAS操作失败,那么永远都不可能成功4、新增了Lambda表达式这个还是比较重要的5、新增了Stream流的支持,例如FileInputStream,FileOutPutStream。
字节流6、数组集合增加了支持并行操作。
JDK8到JDK17各个版本的重要特性整理
JDK8到JDK17各个版本的重要特性整理JDK8新特性(2014年初)(LTS版本)1、Lambda表达式2、函数式编程3、接⼝可以添加默认⽅法和静态⽅法,也就是定义不需要实现类实现的⽅法4、⽅法引⽤5、重复注解,同⼀个注解可以使⽤多次6、引⼊Optional来避免空指针7、引⼊Streams相关的API8、引⼊新的Date/Time相关的API9、新增jdeps命令⾏,来分析类、⽬录、jar包的类依赖层级关系10、JVM使⽤MetaSpace代替了永久代(PermGen Space)重要特性:Lambda表达式、函数式接⼝、⽅法引⽤、Stream流式API、采⽤MetaSpace代替了永久代(PermGen Space)JDK9新特性(2017年9⽉)1、接⼝⽅法可以使⽤private来修饰2、设置G1为JVM默认垃圾收集器3、⽀持http2.0和websocket的API重要特性:主要是API的优化,如⽀持HTTP2的Client API、JVM采⽤G1为默认垃圾收集器JDK10新特性(2018年3⽉)1、局部变量类型推断,类似JS可以通过var来修饰局部变量,编译之后会推断出值的真实类型2、并⾏Full GC,来优化G1的延迟3、允许在不执⾏全局VM安全点的情况下执⾏线程回调,可以停⽌单个线程,⽽不需要停⽌所有线程或不停⽌线程重要特性:通过var关键字实现局部变量类型推断,使Java语⾔变成弱类型语⾔、JVM的G1垃圾回收由单线程改成多线程并⾏处理,降低G1的停顿时间JDK11新特性(2018年9⽉)(LTS版本)1、ZGC,ZGC可以看做是G1之上更细粒度的内存管理策略。
由于内存的不断分配回收会产⽣⼤量的内存碎⽚空间,因此需要整理策略防⽌内存空间碎⽚化,在整理期间需要将对于内存引⽤的线程逻辑暂停,这个过程被称为"Stop the world"。
只有当整理完成后,线程逻辑才可以继续运⾏。
JDK各个版本新特性
JDK各个版本新特性jdk1.5的新特性:1,泛型(它允许指定集合⾥元素的类型,这样你可以得到强类型在编译时刻进⾏类型检查的好处) ArrayList list=new ArrayList()------>ArrayList<Integer>list=new ArrayList<Integer>();2,⾃动装箱/拆箱 ⾃动装包:基本类型⾃动转为包装类.(int >> Integer) ⾃动拆包:包装类⾃动转为基本类型.(Integer >> int) nt i=list.get(0).parseInt();-------->int i=list.get(0);原始类型与对应的包装类不⽤显式转换3,for-each(循环清晰许多,并且避免了强制类型转换) i=0;i<a.length;i++------------>for(int i:a){......}4,static import (静态导⼊:要使⽤⽤静态成员(⽅法和变量)我们必须给出提供这个⽅法的类。
使⽤静态导⼊可以使被导⼊类的所有静态变量和静态⽅法在当前类直接可见,使⽤这些静态成员⽆需再给出他们的类名。
) import static ng.Math.*; Math.sqrt();--------------->sqrt();5 变长参数 int sum(int ...intlist)有任意个参数,把他看作数组6 枚举(Enums) 然后可以这样来使⽤Color myColor = Color.Red. 枚举类型还提供了两个有⽤的静态⽅法values()和valueOf(). 我们可以很⽅便地使⽤它们jdk1.6新特性1,Desktop类和SystemTray类 在JDK1.6中,AWT新增加了两个类:Desktop和SystemTray. 前者可以⽤来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端给指定的邮箱发邮件,⽤默认应⽤程序打开或编辑⽂件(⽐如,⽤记事本打开以txt为后缀名的⽂件),⽤系统默认的打印机打印⽂档;后者可以⽤来在系统托盘区创建⼀个托盘程序.2,使⽤JAXB2来实现对象与XML之间的映射 JAXB是Java Architecture for XML Binding的缩写,可以将⼀个Java对象转变成为XML格式,反之亦然. 我们把对象与关系数据库之间的映射称为ORM,其实也可以把对象与XML之间的映射称为OXM(Object XML Mapping).原来JAXB是Java EE的⼀部分,在JDK1.6中,SUN将其放到了Java SE中,这也是SUN的⼀贯做法.JDK1.6中⾃带的这个JAXB版本是2.0,⽐起 1.0(JSR 31)来,JAXB2(JSR 222)⽤JDK5的新特性Annotation来标识要作绑定的类和属性等,这就极⼤简化了开发的⼯作量.实际上,在Java EE 5.0中,EJB 和Web Services也通过Annotation来简化开发⼯作.另外,JAXB2在底层是⽤StAX(JSR 173)来处理XML⽂档.除了JAXB之外,我们还可以通过XMLBeans和Castor等来实现同样的功能.3,StAX StAX(JSR 173)是JDK1.6.0中除了DOM和SAX之外的⼜⼀种处理XML⽂档的API. StAX 的来历:在JAXP1.3(JSR 206)有两种处理XML⽂档的⽅法:DOM(Document Object Model)和SAX(Simple API for XML). JDK1.6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都会⽤到StAXSun决定把StAX加⼊到JAXP家族当中来,并将JAXP的版本升级到1.4(JAXP1.4是JAXP1.3的维护版本).JDK1.6⾥⾯JAXP的版本就是1.4. StAX是The Streaming API for XML的缩写,⼀种利⽤拉模式解析(pull-parsing)XML⽂档的API.StAX通过提供⼀种基于事件迭代器(Iterator)的API让程序员去控制xml⽂档解析过程,程序遍历这个事件迭代器去处理每⼀个解析事件,解析事件可以看做是程序拉出来的,也就是程序促使解析器产⽣⼀个解析事件然后处理该事件,之后⼜促使解析器产⽣下⼀个解析事件,如此循环直到碰到⽂档结束符; SAX也是基于事件处理xml⽂档,但却是⽤推模式解析,解析器解析完整个xml⽂档后,才产⽣解析事件,然后推给程序去处理这些事件;DOM采⽤的⽅式是将整个xml⽂档映射到⼀颗内存树,这样就可以很容易地得到⽗节点和⼦结点以及兄弟节点的数据,但如果⽂档很⼤,将会严重影响性能.4,使⽤Compiler API 现在我们可以⽤JDK1.6 的Compiler API(JSR 199)去动态编译Java源⽂件,Compiler API结合反射功能就可以实现动态的产⽣Java代码并编译执⾏这些代码,有点动态语⾔的特征. 这个特性对于某些需要⽤到动态编译的应⽤程序相当有⽤,⽐如JSP Web Server,当我们⼿动修改JSP后,是不希望需要重启Web Server才可以看到效果的,这时候我们就可以⽤Compiler API来实现动态编译JSP⽂件,当然,现在的JSP Web Server也是⽀持JSP热部署的,现在的JSP Web Server通过在运⾏期间通过Runtime.exec或ProcessBuilder来调⽤javac来编译代码,这种⽅式需要我们产⽣另⼀个进程去做编译⼯作,不够优雅容易使代码依赖与特定的操作系统;Compiler API通过⼀套易⽤的标准的API提供了更加丰富的⽅式去做动态编译,是跨平台的.5,轻量级Http Server API JDK1.6 提供了⼀个简单的Http Server API,据此我们可以构建⾃⼰的嵌⼊式Http Server,它⽀持Http和Https协议,提供了HTTP1.1的部分实现,没有被实现的那部分可以通过扩展已有的Http Server API来实现,程序员⾃⼰实现HttpHandler接⼝,HttpServer会调⽤HttpHandler实现类的回调⽅法来处理客户端请求,在这⾥,我们把⼀个Http请求和它的响应称为⼀个交换,包装成HttpExchange类,HttpServer负责将HttpExchange传给 HttpHandler实现类的回调⽅法.6,插⼊式注解处理API(Pluggable Annotation Processing API) 插⼊式注解处理API(JSR 269)提供⼀套标准API来处理Annotations(JSR 175)实际上JSR 269不仅仅⽤来处理Annotation,我觉得更强⼤的功能是它建⽴了Java 语⾔本⾝的⼀个模型,它把method,package,constructor,type,variable, enum,annotation等Java语⾔元素映射为Types和Elements(两者有什么区别?),从⽽将Java语⾔的语义映射成为对象,我们可以在ng.model包下⾯可以看到这些类. 我们可以利⽤JSR 269提供的API来构建⼀个功能丰富的元编程(metaprogramming)环境.JSR 269⽤Annotation Processor在编译期间⽽不是运⾏期间处理Annotation,Annotation Processor相当于编译器的⼀个插件,称为插⼊式注解处理.如果Annotation Processor处理Annotation时(执⾏process⽅法)产⽣了新的Java代码,编译器会再调⽤⼀次Annotation Processor,如果第⼆次处理还有新代码产⽣,就会接着调⽤Annotation Processor,直到没有新代码产⽣为⽌.每执⾏⼀次process()⽅法被称为⼀个"round",这样整个Annotation processing过程可以看作是⼀个round的序列.JSR 269主要被设计成为针对Tools或者容器的API. 举个例⼦,我们想建⽴⼀套基于Annotation的单元测试框架(如TestNG),在测试类⾥⾯⽤Annotation来标识测试期间需要执⾏的测试⽅法.7,⽤Console开发控制台程序 JDK1.6中提供了java.io.Console 类专⽤来访问基于字符的控制台设备.你的程序如果要与Windows下的cmd或者Linux下的Terminal交互,就可以⽤Console类代劳. 但我们不总是能得到可⽤的Console,⼀个JVM是否有可⽤的Console依赖于底层平台和JVM如何被调⽤.如果JVM是在交互式命令⾏(⽐如 Windows的cmd)中启动的,并且输⼊输出没有重定向到另外的地⽅,那么就可以得到⼀个可⽤的Console实例. 8,对脚本语⾔的⽀持 如: ruby,groovy,javascript9,Common Annotations Common annotations原本是Java EE 5.0(JSR 244)规范的⼀部分,现在SUN把它的⼀部分放到了Java SE 6.0中.随着Annotation元数据功能(JSR 175)加⼊到Java SE 5.0⾥⾯,很多Java 技术(⽐如EJB,Web Services)都会⽤Annotation部分代替XML⽂件来配置运⾏参数(或者说是⽀持声明式编程,如EJB的声明式事务),如果这些技术为通⽤⽬的都单独定义了⾃⼰的Annotations,显然有点重复建设,,为其他相关的Java技术定义⼀套公共的Annotation是有价值的,可以避免重复建设的同时,也保证Java SE和Java EE 各种技术的⼀致性. 下⾯列举出Common Annotations 1.0⾥⾯的10个Annotations Common Annotations Annotation Retention Target Description Generated Source ANNOTATION_TYPE,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE ⽤于标注⽣成的源代码Resource Runtime TYPE,METHOD,FIELD⽤于标注所依赖的资源,容器据此注⼊外部资源依赖,有基于字段的注⼊和基于setter⽅法的注⼊两种⽅式 Resources Runtime TYPE同时标注多个外部依赖,容器会把所有这些外部依赖注⼊PostConstruct Runtime METHOD标注当容器注⼊所有依赖之后运⾏的⽅法,⽤来进⾏依赖注⼊后的初始化⼯作,只有⼀个⽅法可以标注为PostConstruct PreDestroy Runtime METHOD 当对象实例将要被从容器当中删掉之前,要执⾏的回调⽅法要标注为PreDestroy RunAs Runtime TYPE⽤于标注⽤什么安全⾓⾊来执⾏被标注类的⽅法,这个安全⾓⾊和Container的Security⾓⾊⼀致的.RolesAllowed Runtime TYPE,METHOD⽤于标注允许执⾏被标注类或⽅法的安全⾓⾊,这个安全⾓⾊和Container的Security⾓⾊⼀致的PermitAll Runtime TYPE,METHOD允许所有⾓⾊执⾏被标注的类或⽅法DenyAll Runtime TYPE,METHOD不允许任何⾓⾊执⾏被标注的类或⽅法,表明该类或⽅法不能在Java EE容器⾥⾯运⾏DeclareRoles Runtime TYPE⽤来定义可以被应⽤程序检验的安全⾓⾊,通常⽤isUserInRole来检验安全⾓⾊.jdk1.7新特性1,对集合类的语⾔⽀持 Java将包含对创建集合类的第⼀类语⾔⽀持。
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。
JDK8新特性之判空遍历写法
JDK8新特性之判空遍历写法在⼯作中,经常会处理各种变量,但往往会在使⽤变量的时候,要进⾏空判断,不然要报错。
Java 8 提供了判空写法:Optional.ofNullable(变量).orElse(默认值);例1:求字符串 s 的长度(为空的时候返回0 )。
常规写法:String s = getKey();if (s == null) {return 0;} else {return s.length();}Java 8 写法:String s = getKey();return Optional.ofNullable(s).orElse("").length();例2:循环遍历集合常规写法:List<String> list = getList();if (list != null) {for(String s: list){System.out.println(s);}}Java 8 写法:List<String> list = getList();Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(o -> {System.out.println(o);});PS:使⽤Optional避免null导致的NullPointerException空指针异常是导致Java应⽤程序失败的最常见原因。
以前,为了解决空指针异常,Google公司著名的Guava项⽬引⼊了Optional类,Guava通过使⽤检查空值的⽅式来防⽌代码污染,它⿎励程序员写更⼲净的代码。
受到Google Guava的启发,Optional类已经成为Java 8类库的⼀部分。
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。
Optional提供很多有⽤的⽅法,这样我们就不⽤显式进⾏空值检测。
基于JDK8-lambda表达式四种forEach性能对比
基于JDK8-lambda表达式四种forEach性能对⽐jdk8新特性流Stream编程看了⽹上⼀些性能的⽐较,这⾥⾃⼰写⼀个进⾏测试对⽐以下四种普通forEach、java8中新的forEach、stream+forEach、parallelStream+forEachpackage mbda;import lombok.extern.slf4j.Slf4j;import org.junit.Before;import org.junit.Test;import java.util.ArrayList;import java.util.List;@Slf4jpublic class Mode2 {List<User> listUser = new ArrayList<>();@Beforepublic void initList() {listUser = this.getListUsers();}@Testpublic void test() {//⼀般forEachlong startSimpleTime = System.currentTimeMillis();for (User user : listUser) {user.toString();}long endSimpleTime = System.currentTimeMillis();System.out.println("Simple:" + (endSimpleTime - startSimpleTime));//java8中新的forEachlong startLambda = System.currentTimeMillis();listUser.forEach(User::toString);long endLambda = System.currentTimeMillis();System.out.println("Lambda:" + (endLambda - startLambda));//java8中新的stream+forEachlong startStream = System.currentTimeMillis();listUser.stream().forEach(User::toString);long endStream = System.currentTimeMillis();System.out.println("Stream:" + (endStream - startStream));//java8中新的parallelStream+forEachlong startParallelStream = System.currentTimeMillis();listUser.parallelStream().forEach(User::toString);long endParallelStream = System.currentTimeMillis();System.out.println("ParallelStream:" + (endParallelStream - startParallelStream));}private List<User> getListUsers() {List<User> listUser = new ArrayList<User>();for (int i = 0; i < 10000000; i++) {listUser.add(new User("user" + i, i));}return listUser;}}package mbda;import lombok.Data;@Datapublic class User {private String name;private Integer age;public User(String name, Integer age) { = name;this.age = age;}}1000W条数据100W条数据10W条数据1W条数据1000条数据java8中新加⼊的forEach和普通的forEach临界值⼤概在150W条由以上测试能得到的结果:150W条数据以下and10W以上:lambda>simple>stream>paralleStream150W条数据以上:simple>lambda>stream>paralleStream从性能上考虑:⼩数据量⽤普通的forEach就可以,没有必要使⽤java8中的新出来的⼏种,已经在项⽬中使⽤的也不需要改回来,10W条也就⼏毫秒的差距jdk8中forEach使⽤问题实话说,jdk8出来好久了,公司⼀直⽤的还是jdk7,没有升级,最近终于升级到jdk8了,所以来⾃⼰改改代码,使⽤jdk8中的新特性,最简单的forEach先来试试测试代码如下:public static void testJDK8ForEach(){List<String> asList = Arrays.asList("a","b","a","d");int i=0;// jdk7 forfor(String s:asList){if(s.equals("a")){++i;}}//2 jdk8 forEachasList.forEach(s -> {if(s.equals("a")){++i; // Local variable i defined in an enclosing scope must be final or effectively final}});System.out.println(i);//3 jdk8 streamlong count = asList.stream().filter(s -> s.equalsIgnoreCase("a")).count();System.out.println(count);}⾸先forEach 的确很好⽤,配合lambda表达式,遍历起来很⽅便。
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格式的字符串。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
public interface Runnable { public abstract void run();
}
Lambda表达式
函数式接口的重要属性是:我们能够使用 Lambda 实例化它们, Lambda 表达式实例化函数接口作为方法参数,或者将代码作为数据 对待。 在 Java 8 之前:匿名内部类,监听器和事件处理器的使用都显得很 冗长,代码可读 性很差。 在 Java 8:Lambda 表达式的应用则使代码变得更加紧凑,可读性增 强; Lambda 表达式使并行 操作大集合变得很方便,可以充分发挥多 核 CPU 的优势,更易于为多核处理器编写代码;
findAny:操作用于获取含有Stream中的某个元素的Optional,如果Stream为 空,则返回一个空的Optional。由于此操作的行动是不确定的,其会自由的 选择Stream中的任何元素 findFirst:findFirst操作用于获取含有Stream中的第一个元素的Optional,如 果Stream为空,则返回一个空的Optional。 、limit:截取原Stream前指定值N个元素 noneMatch:noneMatch方法将判断Stream中的所有元素是否满足指定的条 件,如果所有元素都不满足条件,返回true;否则,返回false.
Lambda和匿名内部类
匿名表示法
button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.print(“这是内部类的表示法!"); } }); Lambada表示法 button.addActionListener( (ActionEvent e)-> System.out.print("Helllo Lambda in actionPerformed") );
流的种类
流有串行和并行两种,串行流上的操作是在一个线程中依次 完成,而并行流则是在多个线程 上同时执行。并行与串行的 流可以相互切换:通过 stream.sequential() 返回串行的流, 通 过 stream.parallel() 返回并行的流。相比较串行的流,并行的 流可以很大程度上提高 程序的执行效率。 下面是分别用串行和并行的方式对集合进行排序。 list.stream().sequential()).sorted().count();
Lambda 表达式由三个部分组成:第一部分为一个括号内用逗号分隔 的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭 头符号:->; 第三部分为方法体,可以是表达式和代码块。
语法如下: 1. 方法体为表达式,该表达式的值作为返回值返回。 (parameters) -> expression 2. 方法体为代码块,必须用 {} 来包裹起来,且需要一个 return 返回 值,但若函数式接 口里面方法返回值是 void,则无需返回值。
MathOperation<Long, Long> multiplication = (a, b) -> {return a * b;};
// 没有大括号及返回语句 MathOperation<Float,Float> division = (Float a, Float b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("MyInterface");
}
}
重复注解
重复注解:允许在同一声明或类型(类,属性,或方法)的 使用中多次使用同一个注解
@Repeatable(Authorities.class) public @interface Authority { String role(); }
方法引用
是lambda表达式的一个简化写法,所引用的方法其实是lambda表 达式的方法体实现: List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu"); Collections.sort(names, String::compareTo); Function<Integer, String> f1 = String::valueOf; Function<String,String> function = String::new;
JDK8新特性
Oracle甲骨文公司终于在2014年3月发布了Java 8正式版,它是 java的一个里程牌版本,带来了诸多新特性。 官网介绍:/technetwork/java/javase/8whats-new-2157071.html 一、针对java编程语言(Java Programming Language) 二、针对集合(Collections) 三、Compact Profiles 四、安全性 五、JavaFX 六 工具(tools) 七、国际化 八、部署 九、Date-Time Package 十、Scripting
java编程语言
(Java Programming Language)
1:lambda表达式:一种新的语言特性,能够把函数作为方法的参数或将代 码作为数据。lambda表达式使你在表示函数接口(具有单个方法的接口)的 实例更加紧凑。 2.方法引用 是lambda表达式的一个简化写法,所引用的方法其实是lambda表 达式的方法体实现,这样使代码更容易阅读 3.默认方法:Java 8引入default method,或者叫virtual extension method, 目的是为了让接口可以事后添加新方法而无需强迫所有实现该接口的类都提 供新方法的实现。也就是说它的主要使用场景可能会涉及代码演进。 4.重复注解:允许在同一声明或类型(类,属性,或方法)的使用中多次使 用同一个注解 5.改善了类型推断 6.方法参数反射
泛型的推断改进
jdk1.5: List<Apple> box = new ArrayList<Apple>(); Jdk1.7: List<Apple> box = new ArrayList<>(); Jdk1.8: List<String> list = new ArrayList<>(); list.addAll(new ArrayList<>()); // 由于addAll期望获得Collection<? extends String>类型的参数,JDK8可以根据声明的类型自动判断。 //lambda表达式的推断 MathOperation<Integer, Integer> subtraction = (a, b) -> a - b;
Sream概念
Stream 不是 集合元素,也不是数据结构,它相当于一个 高 级版本的 Iterator,不可以重复遍历里面的数据,像水一样, 流过了就一去不复返。它和普通的 Iterator 不同的是,它可 以并行遍历,普通的 Iterator 只能是串行,在一个线程中执 行。 操作包括:中间操作 和 最终操作(只能操作一遍) 串行流操作在一个线程中依次完成。 并行流在多个线程中完成,主要利用了 JDK7 的 Fork/Join 框 架来拆分任务和加速处理。相比串行流,并行流可以很大程 度提高程序的效率
流的操作分类:中间
中间操作:Intermediate主要是用来对Stream做出相应转换及限制流,实际上是将源Stream转换为一个新的Stream, 以达到需求效果。 filter(): 元素过滤:Stream.of(1, 2, 3, 4, 5).filter(item -> item > 3) sorted():元素排序:Stream.of(1,2,3,1,2,3).distinct() map(): 元素映射:Stream.of(“a”, “b”, “hello”).map(item-> item.toUpperCase()); flatMap: 元素映射:Stream.of(1, 2, 3).Map(integer -> Stream.of(integer * 10)) distinct():去重操作 concat(): 拼接:Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5)); Peek:peek方法生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例), 新Stream每个元素被消费的时候都会执行给定的消费函数,并且消费函数优先执行 skip:跳过。skip方法将过滤掉原Stream中的前N个元素,返回剩下的元素所组成的新Stream Iterate: 其返回的也是一个无限长度的Stream,通过函数f迭代对给指定的元素种子而产生无限连续有序Stream,其 中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环 generator方法,返回一个无限长度的Stream,其元素由Supplier接口的提供。
流的操作分类:短路
短路操作(Short-circuiting):对流中的元素进行判断、取值等操作。
allMatch:判断Stream中的元素是否全部满足指定条件。如果全部满足条件 返回true,否则返回false。
anyMatch:判断Stream中的是否有满足指定条件的元素。如果最少有一个满 足条件返回true,否则返回false。
函数式接口
Java 8 引入的一个核心概念是函数式接口(Functional Interfaces)。 接口定义个唯一一个抽象方法, 那么这个接口就成为函数式接口。 同时,引入了一个新的注解:@FunctionalInterface。可以把他它放 在一个接口前,表示这个接口是一个函数式接口。这个注解是非 必须的,只要接 口只包含一个方法的接口,虚拟机会自动判断, 不过最好在接口上使用注解 @FunctionalInterface 进行声明。 @FunctionalInterface