百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

你还在使用Guava的Lists.newArrayList()吗

liuian 2025-05-27 15:54 4 浏览

Guava

说起Guava,做Java开发的应该没人不知道吧,毕竟“google出品,必属精品”。虽然应该没有Spring那样让Javaer无法避开,但是其中很多工具类的封装还是让人欲罢不能。

而我们今天要说的就是Guava中对集合类型构造方法的封装,拿Lists.newArrayList()举例。

源码

事情的起因其实是某次Code Review中同事说到的一句话,他问“你们为什么不直接用new ArrayList(),却喜欢用Lists.newArrayList()?”。多么朴实无华的问题,我当然要趁此机会推销一波,“使用Lists.newArrayList()多有逼格啊”,“内部其实就是new了个List,性能没区别的”。然后他慢悠悠地说了后半句:“源码注释写着不建议使用”。

说实话,源码我肯定是看过的,毕竟很简单,只要你点进去过,你就敢说自己看过源码。这就是我之前视角中的源码,除了方法调用栈深了一层,跟new ArrayList()有半毛钱区别吗?

public static <E> ArrayList<E> newArrayList() {
  return new ArrayList<>();
}

但其实完整地带注释的方法源码长这样,版本是28.1-jre。

/**
 * Creates a <i>mutable</i>, empty {@code ArrayList} instance (for Java 6 and earlier).
 *
 * <p><b>Note:</b> if mutability is not required, use {@link ImmutableList#of()} instead.
 *
 * <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
 * deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor}
 * directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
 */
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList() {
  return new ArrayList<>();
}

重点是注释的后半部分,对于Java7以及之后的版本,本方法不必要且应被弃用,建议直接使用ArrayList的构造方法,可以利用新的“菱形语法”的优势。

一开始看到菱形语法这个新名词我是懵逼的,还好注释里很贴心地贴了个链接,其实就是泛型中的<>,这玩意儿就叫菱形语法。那为啥两个看上去没啥区别的方法又和这个扯上关系了呢?

泛型实例创建时的类型推断

泛型是JDK1.5推出的一个语法糖,但其实我本人觉得还是挺有用的,可以在编译期帮助我们提前发现代码的问题。平时我们泛型见得最多的地方应该就是集合了,比如List<String>就代表这个列表只能存放String类型的变量,如果放错了,我相信你的ide就会友好地提醒你,除非你用记事本编程。

在idea中新建一个ArrayList试试,为了直观地显示idea的提示,我这边使用截图。

  • 第一行不加菱形有一个警告,提示你应该使用泛型
  • 第二行,perfect
  • 第三行,提示String多余

我这边使用的是JDK8,按照Oracle的官方说明,在JDK7其实就有这种现象了:

In Java SE 7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<>):

Map<String, List<String>> myMap = new HashMap<>();

还有一句比较关键的话

Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond.

这就是为啥第一行会报警告的原因,因为不加这个菱形就不做类型推断。

为啥不推荐用

看到这里是不是还是一脸懵逼,不知道Guava为啥不推荐使用,因为Lists.newArrayList()的内部就是new ArrayList<>(),带菱形的,完全符合JDK7及以上版本的要求。所以我只好把Oracle的解释全文看了一遍,并且找到了关键点:

List<String> list = new ArrayList<>();
list.add("A");

  // The following statement should fail since addAll expects
  // Collection<? extends String>

list.addAll(new ArrayList<>());

In comparison, the following example compiles:

// The following statements compile:

List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);

是的,如果不明确在构造方法指明泛型类型,也就是单纯的一个菱形,那类型推断功能是受限的。拿上面的举例,new ArrayList<>()并不能根据上上下推断出想要构造的集合是一个List<? extends String>。所以按照官方的意思,在这种情况下用Lists.newArrayList()就搞不定了。

上面的例子是Oracle的官方说法,那到底是不是呢?idea中试一把。

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("A");

    // The following statement should fail since addAll expects
    // Collection<? extends String>

    list.addAll(new ArrayList<>());
}

跑起来完全没问题。。。当然,将allAll方法中的new ArrayList<>()替换为Lists.newArrayList()也是没问题的。

写在最后

从我个人观点来看,我觉得这应该不是idea做的优化,这么看来,官方的说法还是有待考证。

就算官方的说法是对的,那么也只是限制了某些编译期就会报错的场景,似乎问题不大,所以到底用不用Guava的集合创建方法,还是看大家的个人喜好吧。

相关推荐

那些Java架构师必知必会的技术

Java基础#Java对象的内存布局MapStruct解了对象映射的毒周末我把HashMap源码又过了一遍Java7和Java8中的ConcurrentHashMap原理解析Java中自定...

Java内存泄漏最全详解(6大原因及解决方案)

大家好,我是mikechen。内存泄漏是经常出现的线上故障,也是大厂面试经常考察的,下面我就全面来详解内存泄漏以及解决方案@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题...

都说Feign是RPC,没有侵入性,为什么我的代码越来越像 C++

1.概览随着SpringCloud的流行性,Feign已经成为RPC的事实标准,由于其构建与Http协议之上,对请求和返回值缺少规范约束,在日常开发过程中经常由于设计不当对系统造成一...

面试题系列-java后端面试题List 和 Set 的区别

List和Set的区别List,Set都是继承自Collection接口List特点:元素有放入顺序,元素可重复,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(...

一直不理解为什么在重写equals方法时都要重写hashCode方法

为什么在重写equals方法时都要重写hashCode方法呢?首先jdk的要求是这样的,equals与hashcode间的关系:1、如果两个对象相同(即用equals比较返回true),那么它们的ha...

翻了ConcurrentHashMap1.7 和1.8的源码,我总结了它们的主要区别

ConcurrentHashMap思考:HashTable是线程安全的,为什么不推荐使用?HashTable是一个线程安全的类,它使用synchronized来锁住整张Hash表来实现线程安全,即每次...

10 个经典的 Java 集合面试题,看你能否答得上来?

来自:evget.com/article/2014/11/27/21869.html这里有10个经典的Java面试题,也为大家列出了答案。这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之...

MyBatis3.5.11-从入门到高阶

一.课程介绍MyBatis概述MyBatis基础应用MyBatis高级MyBatis进阶二.MyBatis概述1、为什么需要MyBatis在我们程序中,运行时期产生的数据都是存放在内存中的,那么在内存...

灵魂拷问:如何检查 Java 数组中是否包含某个值?

作者|沉默王二责编|Elle在逛programcreek的时候,我发现了一些专注细节但价值连城的主题。比如说:如何检查Java数组中是否包含某个值?像这类灵魂拷问的主题,非常值得深入地研...

Java后端学习路线是什么?

关于Java后端(SpringBoot为主)学习路线:一、Java基础阶段编程语言基础掌握基本数据类型(如int、double、char等)、变量、常量的定义和使用。理解运算符(算术、关...

Mybatis配置文件XML全貌详解,再不懂我也没招了

一、为什么要使用配置文件试想,如果没有配置文件,我们的应用程序将只能沿着固定的姿态运行,几乎不能做任何动态的调整,那么这不是一套完美的设计,因为我们希望拥有更宽更灵活的操作空间和更多的兼容度,同时也能...

软件性能调优全攻略:从瓶颈定位到工具应用

性能调优是软件测试中的重要环节,旨在提高系统的响应时间、吞吐量、并发能力、资源利用率,并降低系统崩溃或卡顿的风险。通常,性能调优涉及发现性能瓶颈、分析问题根因、优化代码和系统配置等步骤,调优之前需要先...

你还在使用Guava的Lists.newArrayList()吗

Guava说起Guava,做Java开发的应该没人不知道吧,毕竟“google出品,必属精品”。虽然应该没有Spring那样让Javaer无法避开,但是其中很多工具类的封装还是让人欲罢不能。而我们今天...

JDK成长记7:3张图搞懂HashMap底层原理

HashMap基本原理和优缺点HashMap基本原理和优缺点一句话讲,HashMap底层数据结构,JDK1.7数组+单向链表、JDK1.8数组+单向链表+红黑树。HashMap的3个底层原理Hash...

如何深度理解mybatis?

深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...