Java8新特性
2022-01-13 14:37:35 0 举报
AI智能生成
详细简绍Java8新特性
作者其他创作
大纲/内容
简介
Oracle在2014年3月份发布了java8正式版,Java 8 (又称为 jdk 1.8)是Java发布以来改动最大的一个版本。<br> <br>
特点
速度更快 <br>
数据结构 <br>
jdk1.7<br>
数组、链表(单项链表)<br>
HashMap在jdk1.7中他的底层数据结构是数组+链表,最开始以数组结构进行存储数据,HashMap是以哈希值确认位置,HashMap的加载因子是0.75(当链表的长度达到75%的时候,HashMap会自动扩容,需要将链表中的所有数据的哈希值从新计算,从新放入相应的哈希值对应的位置。这里存在一个问题就是哈希碰撞,哈希值是会重复的,也就是说发生碰撞,那这个时候它会把老的值以链的形式缀在新值后面,形成一个链型结构,也就是链表。)<br>
jdk1.8<br>
数组、链表、红黑树(平衡二叉树)
HashMap在jdk1.8中底层数据结构是数组+链表+红黑树,相比于jdk1.7多了一个红黑树,首先最初的数据结构是数据,如发生哈希碰撞就会以链表的形式存储。jdk1.8在链表的碰撞数量大于8,HashMap总容量大于64的时候,那么就会将链表转换成红黑树,红黑树就像一个二分法,一直把这个列表一分二,二分四。这样的好处是插入的时候我不需要比较这个链表中所有的哈希值按照树形结构比较,如果比较相同,就向下比较,反之就挂在上一个碰撞的值下面。
在线演示红黑树
内存结构 <br>
里面直接用的就是物理内存,而不是你来分配内存了,这样垃圾回收机制就几乎不做回收了,虽然1.7里面方法区也一般不会被回收,但还是有一些被回收的情况,所以1.8直接优化了内存机制。
jvm <br>
永久区
永久区是Hotspot虚拟机对方法区的具体实现,在jdk1.8被移除,取而代之是元空间<br>
元空间
内存泄漏以及新类加载器的创建导致的,通常出现于代码热部署时。相对于正式产品,该问题在开发机上出现的 频率更高,在产品中最常见的“问题”是默认值太低了。常用的解决方法是将其设置为256MB或更高。JDK8 HotSpot JVM 将移除永久区,使用本地内存来存储类元数据信息并称之为:元空间(Metaspace)。这意味着不会再有java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用。<br>
方法区
类变量
类加载器的引用<br>
Class类的引用<br>
方法信息<br>
域信息
类型信息
代码更少 <br>
新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。它可以让你以一种声明的方式处理数据,从而写出高效率、干净、简洁的代码。<br>
强大的Stream API<br> <br>
Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator 。可以执行非常复杂的查找、过滤和映射数据等操作 。<br> <br>
1.使用Stream,并不会直接进行计算,只会在结束操作的时候才会运算。这种特质叫惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行 ,流传递的可以理解为逻辑。<br>2.不是数据结构,不会保存数据。<br>3.不会修改原本的数据源,而是会生成一个个新的数据源。<br>
便于并行 <br>
通过图上的例子可以很好理解并行的运行速度是要比串行要快的
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。<br>
最大化减少空指针异常Optional <br>
OptionalAPI
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase(); 代码中存在什么问题?
可能会存在空指针的情况,那么我们平常的代码如何去写
if (user != null) {<br> Address address = user.getAddress();<br> if (address != null) {<br> Country country = address.getCountry();<br> if (country != null) {<br> String isocode = country.getIsocode();<br> if (isocode != null) {<br> isocode = isocode.toUpperCase();<br> }<br> }<br> }<br>}
使用Optional代码示例
public static void main(String[] args) {<br> //返回一个Optional实例<br> /*Optional<User> optional1 = Optional.empty();<br> System.out.println(optional1);*/<br><br><br> /*Map map =new HashMap<>();<br> map.put("key1",1);<br> Optional<Object> optional2 = Optional.ofNullable(map);<br> System.out.println(optional2);<br> Map optionalMap = (Map)optional2.get();<br> System.out.println(optionalMap);*/<br><br><br> /*User user = null;<br> String str = Optional.ofNullable(user).map(User::getName).orElse(null);<br> System.out.println(str);*/<br><br> }<br>
@Data<br>public class User {<br> private Integer id;<br> private String name;<br>}<br>
新增特性
lambda表达式<br> <br>
Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。<br>
//匿名内部类<br>public class demo {<br><br> public static void main(String[] args) {<br> ICacheService ic = new ICacheService() {<br> @Override<br> public void initDictCache() {<br> System.out.println("这个一个匿名方法");<br> }<br> };<br> ic.initDictCache();<br> }<br>}
Lambda 表达式的基础语法 : Java8 中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符,箭头操作符将 Lambda 表达式拆分成两部分 :<br>左侧 : Lambda 表达式的参数列表<br>右侧 : Lambda 表达式中所需执行的功能, 即 Lambda 体
lambda特性示例
集合处理
循环差异
List
public static void main(String[] args) {<br> List<Integer> list = new ArrayList<>();<br> list.add(1);<br> list.add(2);<br> list.add(3);<br> list.add(4);<br> list.add(5);<br> //旧循环方式<br> for (Integer integer : list) {<br> System.out.println(integer);<br> }<br> //使用 lambda<br> list.forEach(x-> System.out.println(x));<br> }
Map
public static void main(String[] args) {<br> Map<String,Object> map = new HashMap<>();<br> map.put("key1","value1");<br> map.put("key2","value2");<br> map.put("key3","value4");<br> map.put("key4","value4");<br> map.put("key5","value5");<br> //旧循环方式<br> Set<String> keys = map.keySet();<br> for (String key : keys) {<br> System.out.println("key是"+key+"value"+map.get(key));<br> }<br> //使用 lambda<br> map.forEach((k,v)-> System.out.println("key是"+k+"value"+v));<br> }
过滤条件
public static void main(String[] args) {<br> List list = new ArrayList<>();<br> list.add("1");<br> list.add("1");<br> list.add("2");<br> list.add("2");<br> list.add("2");<br> list.add("3");<br> list.add("4");<br> list.add("4");<br> list.add("4");<br> //我现在只要list中为2的<br> //旧方式<br> List<Object> listTwo = new ArrayList<>();<br> for (Object obj : list) {<br> if("2".equals(obj)){<br> listTwo.add(obj);<br> }<br> }<br> System.out.println(listTwo);<br> //使用 lambda<br> List<Object> objectList = (List<Object>) list.stream().filter(x -> x.equals("2")).collect(Collectors.toList());<br> System.out.println(objectList);<br> }
函数式接口 <br>
@FunctionalInterfac
//函数式接口就是定义一个抽象方法<br>public interface demo {<br> void NoReturnMultiParam();<br>}
虽然这个也是函数式接口,但是后续的人可以继续加抽象方法,那么这个就不是函数式接口
@FunctionalInterface<br>public interface demo {<br> void NoReturnMultiParam();<br>}
总结:就是在类上面添加注解,标注这个类只有一个抽象方法,再多就直接报红
Stream API<br> <br>
并行流和串行流的比较
串行流
long start = System.currentTimeMillis();<br> long sum = 0L;<br> for (long i = 0L; i <= 100; i++) {<br> sum += i;<br> }<br> System.out.println(sum);<br> long end = System.currentTimeMillis();<br> System.out.println("耗费的时间为: " + (end - start)+"毫秒");<br>
long start = System.currentTimeMillis();<br> Long sum1 = LongStream.rangeClosed(0L, 100L)<br> .sequential()//串行<br> .reduce(0,Long::sum);<br> System.out.println(sum1);<br> long end = System.currentTimeMillis();<br> System.out.println("耗费的时间为: " + (end - start)+"毫秒");
并行流<br>
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。串行流则相反,并行流的底层其实就是ForkJoin框架的一个实现。
long start = System.currentTimeMillis();<br> Long sum1 = LongStream.rangeClosed(0L, 100L)<br> .parallel()//并行<br> .reduce(0,Long::sum);<br> System.out.println(sum1);<br> long end = System.currentTimeMillis();<br> System.out.println("耗费的时间为: " + (end - start)+"毫秒");<br>
接口增强 <br>
默认方法
在 java 8 之前,接口与其实现类之间的 耦合度 太高了(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现。
public interface demo {<br><br> default void test(){<br> //逻辑代码<br> };<br>}
静态方法
public interface demo {<br> static void staticMethod(){<br> System.out.println("我是静态方法");<br> }<br>}
Optional类<br> <br>
新增时间日期API <br>
//获取当前日期对象<br> LocalDate now = LocalDate.now();<br> System.out.println("今天的日期是:"+now);<br> <br> <br> Date date = new Date();<br> System.out.println("今天的日期是:"+date);
API
收藏
0 条评论
下一页