百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

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

lipiwang 2025-05-28 18:34 4 浏览 0 评论

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的集合创建方法,还是看大家的个人喜好吧。

相关推荐

小程序-如何获取用户表单控件中的值

背景在小程序开发中,经常有用到表单,我们往往需要在小程序端获取用户表单输入框中的值(通常用户输入的有:switch,input,checkbox,slider,radio,picker)等,通过触发事...

Js基础7:表单元素属性

一、封装获取元素的方法封装思想——函数封装——代码复用 function get_id(id){    //这个函数是专门来通过id获...

泰媒:到泰国曼谷旅游,注意别被嘟嘟车司机坑!

据泰国《世界日报》微信公众号报道,近日,一名导游投诉称,3名外籍游客在泰国曼谷搭载嘟嘟车时,被嘟嘟车司机坑。该导游认为嘟嘟车司机坑害外国游客的行为,破坏泰国的旅游形象,希望能以此为戒。当地时间25日上...

快速了解JavaScript的表单操作

前言在HTML中使用<form>表单元素在JavaScript中对应的是HTMLFormElement类型,而HTMLFormElement继承了HTMLElement接口...

10《Vue 入门教程》Vue 双向绑定指令

1.前言本小节我们将介绍Vue中数据的双向绑定指令v-model。v-model的学习相对简单。我们可以用v-model指令在表单<input>、<textarea&...

手把手教你搭建消防安全答题小程序-实现答题及提交答卷到数据库

手把手教你搭建答题活动小程序系列,第一阶段为界面设计篇,分别描写了如何搭建答题小程序界面。第二阶段为功能交互篇。而上两篇文章分别描写了,如何用云开发实现查询题库功能,以及将获取到的题目数据动态更新到答...

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

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

Mybatis参数传递

1.概述Mybatis的sql参数传递就是将接口方法中定义的参数传输到sql中。sql有两种形式,一种是XML格式(Mapper映射器)中的sql;一种是注解方式的sql。常用参数的类型主要包括:基...

python中的map和filter避坑指南

Pythonic的方式使用map和filter列表迭代在python中是非常pythonic的使用方式definc(x):returnx+1>>>list(map...

2025 年 Object 和 Map 如何选择?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。1.什么是...

如何使用Java读取Excel文件到List&gt;格式

引言在开发过程中,我们经常会遇到需要读取Excel文件并将数据转换成Java对象的需求。ApachePOI是一个强大的库,它提供了读取和写入MicrosoftOffice格式文件的功能,包括Exc...

Nginx L4 stream Solution white list map

nginx正向透明代理nginx正向透明代理安全方面的一些限制对于代理而已,有时候可能还不够安全,而且这个是基于4层的,所以想要在http上,或者所谓的http头上做限制还是比较难实现了。所以变...

Java响应式编程 第五篇 flatMap vs map

1作用不同1.2映射?展平?map只执行映射flatMap既执行映射,也执行展平什么叫只能执行映射?我理解是把一个数据执行一个方法,转换成另外一个数据。举个例子:mapper函数把输入的字符...

Java对象拷贝原理剖析及最佳实践

作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的...

mybatis手把手教学,希望大家能拿下它

目录1.jdbc封装中的问题12.mybatis介绍43.框架搭建41)导包52)配置文件6配置dtd约束73)创建SqlSessionFactory对象94.入门案例91.部门实体...

取消回复欢迎 发表评论: