IDEA warning Call to ‘toArray()‘ with pre-sized array argument ‘new String[results.size()]‘

51 篇文章 6 订阅
本文讨论了在Java开发中,尤其是在IntelliJIDEA中,如何处理从List到String数组的转换。提到使用预设大小数组(如`toArray(newString[c.size()])`)的旧习惯,以及自JDK6更新后空数组(如`toArray(newString[0])`)的性能提升和并发安全性。建议根据JDK版本选择合适的转换策略。
摘要由CSDN通过智能技术生成

概述

IDEA几乎是Javaer的开发IDE标配。

Call to ‘toArray()’ with pre-sized array argument ‘new String[results.size()]’

在IDEA里阅读代码时遇到如下黄色的代码库,鼠标放置上去,给出如下warning提示:
在这里插入图片描述
代码折叠一下:
在这里插入图片描述
不难看出这是一个自己实现的org.apache.commons.lang3.StringUtils.split(String str, String separatorChars)方法,方法最后一行把List<String>转换成String数组。

按照IDEA的提示,调整后的代码:

return results.toArray(new String[0]);

源码如下:

public static String[] split(String string, String separators) {
    if (string == null) {
        return null;
    } else {
        int length = string.length();
        if (length == 0) {
            return new String[0];
        } else {
            ArrayList<String> results = new ArrayList<>();
            int i = 0;
            int start = 0;
            boolean tokenInProgress = false;
            if (separators == null) {
                while (i < length) {
                    if (Character.isWhitespace(string.charAt(i))) {
                        if (tokenInProgress) {
                            results.add(string.substring(start, i));
                            tokenInProgress = false;
                        }
                        ++i;
                        start = i;
                    } else {
                        tokenInProgress = true;
                        ++i;
                    }
                }
            } else if (separators.length() == 1) {
                char separator = separators.charAt(0);
                while (i < length) {
                    if (string.charAt(i) == separator) {
                        if (tokenInProgress) {
                            results.add(string.substring(start, i));
                            tokenInProgress = false;
                        }
                        ++i;
                        start = i;
                    } else {
                        tokenInProgress = true;
                        ++i;
                    }
                }
            } else {
                while (i < length) {
                    if (separators.indexOf(string.charAt(i)) >= 0) {
                        if (tokenInProgress) {
                            results.add(string.substring(start, i));
                            tokenInProgress = false;
                        }
                        ++i;
                        start = i;
                    } else {
                        tokenInProgress = true;
                        ++i;
                    }
                }
            }
            if (tokenInProgress) {
                results.add(string.substring(start, i));
            }
            return results.toArray(new String[results.size()]);
        }
    }
}

分析

Google搜索到如下pinpoint-issue

Call to ‘toArray()’ with pre-sized array argument ‘new PathMatcher[collection.size()]’

Inspection info: There are two styles to convert a collection to an array: either using a pre-sized array (like c.toArray(new String[c.size()])) or using an empty array (like c.toArray(new String[0]).

In older Java versions using pre-sized array was recommended, as the reflection call which is necessary to create an array of proper size was quite slow. However since late updates of OpenJDK 6 this call was intrinsified, making the performance of the empty array version the same and sometimes even better, compared to the pre-sized version. Also passing pre-sized array is dangerous for a concurrent or synchronized collection as a data race is possible between the size and toArray call which may result in extra nulls at the end of the array,if the collection was concurrently shrunk during the operation.

This inspection allows to follow the uniform style: either using an empty array (which is recommended in modern Java) or using a pre-sized array (which might be faster in older Java versions or non-HotSpot based JVMs).

粗糙翻译中文版

将集合转换为数组有两种方法:

  • 使用预先调整大小的数组:c.toArray(new String[c.size()])
  • 使用空数组:c.toArray(new String[0])

在JDK低版本中,建议使用预先调整大小的数组,因为创建适当大小的数组所需的反射调用非常慢。但在JDK6后,这个调用被内在化(intrinsified),使得空数组版本的性能与预先设置的版本相同,有时甚至更好。另外,传递预先确定大小的数组对于并发或同步的集合是危险的,因为如果集合在操作期间同时减少(元素被删除),那么在size()和toArray()调用之间可能会发生数据竞争,可能会导致数组末尾出现额外的空值。

根据JDK版本不同,选择使用哪一种方法:

  • JDK6以后,使用空数组
  • JDK6以前,或非HotSpot JVM中,使用预先设置大小的数组

参考

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnny233

晚饭能不能加鸡腿就靠你了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值