简体   繁体   English

收集Java方法中的错误,清空ArrayList与LinkedList

[英]Collecting errors in a Java method, empty ArrayList vs. LinkedList

I seem to create these two kind of methods occasionally: 我似乎偶尔会创建这两种方法:

// return null on errors, and append errors to 2nd param, otherwise return result
String fetchSomething(String parameter, List<String> errorMessagesOut);

// return empty list or null on no errors, otherwise list of errors
List<String> verifySomething(String parameter);

And then the code which calls these will join the error list with appropriate separator (such as simple comma, newline, HTML tags...), usually using Apache Commons Stringutils.join method. 然后调用这些代码的代码将使用适当的分隔符(例如简单的逗号,换行符,HTML标记...)加入错误列表,通常使用Apache Commons Stringutils.join方法。 And in normal case there's no error, and list will be empty. 在正常情况下,没有错误,列表将为空。

So, I started wondering about these two questions: 所以,我开始怀疑这两个问题:

  1. Do you see a problem with returning error message strings as list? 您是否看到将错误消息字符串作为列表返回时出现问题? If so, what is better alternative? 如果是这样,有什么更好的选择? (Not exceptions, that would be thrown by code which calls these methods, when that is wanted.) (不是例外,在需要时会调用这些方法的代码抛出。)

  2. Is new LinkedList() or new ArrayList(0) or new ArrayList() better for list which is expected to remain empty, and which should normally have only sequential iterator access when it is not empty? 对于预期保持为空的列表, new LinkedList()new ArrayList(0)new ArrayList()更好,并且当它不为空时通常只应具有顺序迭代器访问权限?


EDIT: Example use case: 编辑:示例用例:

List<String> verifyParameters(JSONObject params) {
    List<String> ret = new ArrayList<String>(0);

    if (!verifyKey(params.get("key"))) 
        ret.add("Invalid key: " + key);

    if (!verifyAccess(params.get("user"), params.get("pass"))) 
        ret.add("Authentication error");

   return ret;
}

... ...

List<String> errors = verifyParameters(params);
if (!errors.isEmpty()) {

    connection.sendErrorListMessage(errors);
    logger.warn(StringUtils.join(errors, ", "));
    controlPanel.show("Errors: \n- " + StringUtils.join(errors, "\n- ") + '\n');
    throw new AbortException("invalid params); // or maybe return false/null;
}
// proceed with valid params

Usually handling of error list would not have all of those, it just tries to illustrate the point that error list is a list of messages meant for humans to see, independent of how it will be shown, and also not related to/useful for handling different errors differently. 通常错误列表的处理不会包含所有这些,它只是试图说明错误列表是一个供人类查看的消息列表,与其显示方式无关,也与处理无关/有用不同的错误不同。

I think it's fine to use a List for the Strings. 我认为使用List for the Strings很好。 I would be inclined to make a dedicated Result class at least for fetchSomthing and make it like this, especially if the errorMessagesOut passed is never anything except a new empty List: 我倾向于至少为fetchSomthing创建一个专门的Result类,并使它像这样,特别是如果传递的errorMessagesOut永远不会是一个新的空List:

Result result = fetchSomething(String parameter);
if (result.hasErrors()) {
    List<String> errors = result.getErrors();
} else {
    String fetched = result.getValue();
}

I would then also put any of the methods that process the error Strings on this class also so you could do something like: 然后我还会把处理错误字符串的任何方法放在这个类上,这样你就可以做类似的事情:

String errorMessage = result.getErrorString();

This encapsulates the error data and the formatting of it within the one Class and means that in the case of no errors you don't need to create any List internally in your Result instance. 这将错误数据及其格式封装在一个Class中,这意味着在没有错误的情况下,您不需要在Result实例内部创建任何List。

My above points are mostly about the code design. 我的上述观点主要是代码设计。 There is no point in trying micro-optimization without profiling and having benchmarks to compare to the results of any changes. 没有分析并且有基准来与任何变化的结果进行比较,尝试微优化没有意义。

What are these errors for? 这些错误是什么? Are you going to do some business decision off of the errors returned by a method? 您是否要根据方法返回的错误做出一些商业决策? Otherwise, if the errors are just for logging, a simple Logging solution would suggest that the errors are logged as soon as they occur. 否则,如果错误仅用于记录,则简单的记录解决方案将建议在错误发生时立即记录错误。 I'm talking about those logger.debug("Error message"); 我在谈论那些logger.debug("Error message"); .

Anyway, could you give us an example of what is done to this errors after they are returned? 无论如何,你能给我们一个例子,说明这些错误在返回后做了什么吗?

One thing I point, though: It tends to be confusing if you're using the same array / list / collection for both processing results and for errors. 但有一点我指出:如果你使用相同的数组/列表/集合来处理结果和错误,那么它往往会让人感到困惑。 It would also be confusing if your methods returned error lists (or empty/null lists in case of no error) as it would appear that the errors are the very result of executing your method. 如果您的方法返回错误列表(或者在没有错误的情况下为空/空列表),这也会令人困惑,因为看起来错误是执行方法的结果。

There is nothing wrong in trying to collect all error information using a list. 尝试使用列表收集所有错误信息没有错。 Using an ArrayList will work fine, no need to worry about that... 使用ArrayList可以正常工作,无需担心...

In case you know there are no errors you could return Collections.emptyList(); 如果你知道没有错误,你可以return Collections.emptyList(); .

In general with Collections avoid returning both null or empty list. 通常,Collections避免返回null或空列表。 I always use empty list as does not break for loops. 我总是使用空列表,因为不会中断循环。

Do you see a problem with returning error message strings as list? 您是否看到将错误消息字符串作为列表返回时出现问题? If so, what is better alternative? 如果是这样,有什么更好的选择?

No. There is nothing wrong in using a list if it solves your problem there. 没有。如果在那里解决你的问题,使用列表没有错。

Is new LinkedList() or new ArrayList(0) or new ArrayList() better for list which is expected to remain empty, and which should normally have only sequential iterator access when it is not empty? 对于预期保持为空的列表, new LinkedList()new ArrayList(0)new ArrayList()更好,并且当它不为空时通常只应具有顺序迭代器访问权限?

Knowing about how many elements the list is going to store and instantiating the list with that capacity will not have any significant improvement in the performance: 了解列表将存储多少元素并使用该容量实例化列表将不会对性能有任何显着改进:

Each ArrayList instance has a capacity. 每个ArrayList实例都有一个容量。 The capacity is the size of the array used to store the elements in the list. 容量是用于存储列表中元素的数组的大小。 It is always at least as large as the list size. 它始终至少与列表大小一样大。 As elements are added to an ArrayList, its capacity grows automatically. 当元素添加到ArrayList时,其容量会自动增加。 The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost. 除了添加元素具有恒定的摊销时间成本这一事实之外,未指定增长策略的详细信息。

You'll however save some memory with new ArrayList(0) if the list is most often empty as the size of list is initialized to 10 when no initial capacity is specified. 但是,如果列表最常为空,则可以使用new ArrayList(0)保存一些内存,因为当没有指定初始容量时,列表的大小初始化为10

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM