为什么你要使用java8

java8优势

相信对于java8这个字眼大家都已经不陌生了,但是对于java8的了解和使用很多人还不是很清楚,甚至很多人还在犹豫着要不要用java8,那么我写这篇文章的目的就是告诉你,你一定要使用java8以及你为什么要使用java8.

lambda

在Java7以及之前的代码里,为了实现带一个方法的接口,往往需要定义一个匿名类并复写接口方法,代码显得很臃肿。
比如我们用来给数组排序的Comparator接口:

String[] str = "aa、bb、cc、dd".split("、");
Arrays.sort(str, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.toLowerCase().compareTo(s2.toLowerCase());
    }
});

然而对于这种只有一个方法的接口,在Java8里面,我们可以把它视为一个函数,用lambda表示式简化如下的操作:

String[] str = "aa、bb、cc、dd".split("、");
Arrays.sort(str, (s1, s2) -> {
    return s1.toLowerCase().compareTo(s2.toLowerCase());
});

这样我们的代码看着就简洁了很多,或许单单看这一个例子大家还体会不到lambda那神奇的魔力.
如果接触过jedis的朋友,相信都知道在使用jedis的时候会有获取连接,进行操作,释放连接这几个步骤。
大家能看出来,除了进行操作这个步骤是不同的,连接的获取和释放代码是相同的,那么这时候我们就可以考虑用lambda表达式把他封装起来,具体的实现可以去我的github上看,仓库地址点击这里.

stream

集合类新增的stream()方法用于把一个集合变成Stream,然后,通过filter()、map()等实现Stream的变换。Stream还有一个forEach()来完成每个元素的迭代。

例如我原来要遍历一个list,要对这个list做一个for遍历

代码是这样的:

        List<String> a = new ArrayList<String>();
        for (String o : a) {
            System.out.println(o)
        }

而我用了stream之后,代码却简洁成这个样子:

        List<String> a = new ArrayList<>();
        a.stream().forEach(c-> System.out.println(c));

在比如我想取得这个list的的前10项:

List<String> list = oldList.limit(10).collect(Collectors.toList());

那么如果我想取得数列的第20~30项,可以这样做:

List<String> list = oldList.skip(20).limit(10).collect(Collectors.toList());

而且Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。
stream提供了parallelStream使用多线程进行操作,加大了运算效率.

Stream中还有fifter、sorted、Match、map、Reduce这一类的api,大家可以在日后的使用中慢慢去体会他的强大之处.

optional

Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一届中将要用到的重要概念,他最初源自于google出的框架包guava之中,于1.8正式引入到jdk中使用

Optional 被定义为一个简单的容器,其值可能是null或者不是null。在之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,然后这样的结果或许可能会让你的程序出现NullPointerException,会造成程序的崩溃等不可预估的问题,而在Java 8中,不推荐你返回null而是返回Optional。

Optional<String> optional = Optional.of("bam");

optional.isPresent();           // true
optional.get();                 // "bam"
optional.orElse("fallback");    // "bam"

optional.ifPresent((s) -> System.out.println(s.charAt(0)));     // "b"

构造函数和方法引用

构造函数

在java8之前我们新建一个对象都是这样的User u = new User()
而在java8中我们可以这么写代码User u = User::new

方法引用

我经常把方法引用和lambda合在一起使用
比如我们有一个业务需要把集合里每个元素做处理
那么我们根据业务规范要把这个处理的事件写成一个业务方法,然后遍历集合元素,并传递元素调用该方法

一般我们在使用java8以前都是这么写的:

//声明一个名为doSomeThing的方法  
public void doSomeThing(String item){
   // TODO
}


List<String> list = new ArrayList<String>();
for(String item:list){
   doSomeThing(item);
}

那么在java8中,上面的东西我很简单的就搞定了list.stream().foreach(item->doSomeThing(item))

我用方法引用再简化一下上面的代码,就变成了现在这个样子list.stream().foreach(this:: doSomeThing),很牛逼是不是!

hashMap的优化

  • 如果在hash冲突的时候,链表长度大于默认因子数8的时候,会变更为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,用以提高效率.
  • JDK1.7中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置,JDK1.8不会倒置.

详细的优化请参考美团技术团队写的这篇文章Java 8系列之重新认识HashMap

concurrentHashMap的优化

concurrentHashMap变成了cas无锁模式,只有在扩容的时候才会用sync进行锁,cas的无锁模式使得concurrentHashMap在吞吐量上有了一定等级的提升

JVM方面的优化

内存模型换成红黑树,有利于gc,减少内存泄露
java内存分带进行了改进,取消了永久代,变成了metaSpace

内存分带的改进:metaSpace

java8内存分带的改进之后带来哪些优势?

你的metaSpace使用了机器的堆内存,metaSpace是自动扩展的,但是你可以给他设置一个固定的最大容量,但是其实你是无需关系他的大小,让你不用像以前一样担心permGen溢出的问题.

在永久代被发明的时候那时候还没有spi,osgi这类的动态类加载机制,所以一个类一旦被JVM加载之后他就一直在内存之中,一直到JVM结束运行才会释放(其实这个时候说道释放也没有什么意义了),而现在的阶段类在JVM的生命周期变得不确定了,可以灵活的加载和释放,所以java8中吧永久代变为metaSpace的意义其实也是为了应对现在类机制灵活的变化.

metaSpace的缺点

上面我们谈到了内存分带改进的好处,但是metaSpace也有他的缺点

他的缺点是什么呢?

  • 拿class实例来讲,无论是永久代还是metaSpace都会存在类加载泄露的风险.唯一的区别是metaSpace的默认设置(自动调整metaSpace空间大小),这个看来是改进的地方,会让你在类加载泄露的问题变得更难发现.
  • 另一方面,如果metaSpace的东西占用的空间更大了之后,他是有可能耗尽操作系统的内存,这种情况的发生比耗尽JVM永久代的后果更严重,虽然你可以设置一个metaSpace的最大值,但是这个最大值的大小又会变成调优的另一个新问题了.

无论你是在JVM里使用metaSpace还是永久代,如果你正在使用动态类卸载,你应该采取措施来检测和防止类加载泄露.

参考的文章:

What is the difference between PermGen and Metaspace?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • Java8 in action 没有共享的可变数据,将方法和函数即代码传递给其他方法的能力就是我们平常所说的函数式...
    铁牛很铁阅读 1,223评论 1 2
  • 在过去(当自定义类加载器使用不普遍的时候),类几乎是“静态的”并且很少被卸载和回收,因此类也可以被看成“永久的”。...
    云狗狗狗狗狗阅读 4,377评论 0 8
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,218评论 11 349
  • 中午吃饭,跟几位同事走进了常去吃饭的那家饭馆,报好饭之后就在空位上等候了。刚坐了几分钟,出了一份餐,有一位同事就吃...
    flowerxuegao阅读 297评论 0 0