简体   繁体   English

!list.isEmpty() 和 list.size()>0 是否相等?

[英]Is !list.isEmpty() and list.size()>0 equal?

I've seen code as below:我已经看到如下代码:

     if (!substanceList.isEmpty() && (substanceList.size() > 0))
    {
      substanceText = createAmountText(substanceList);
    }

Would the following be a valid refactor?以下是有效的重构吗?

     if (!substanceList.isEmpty())
    {
      substanceText = createAmountText(substanceList);
    }

I would be grateful for an explanation of the above code and whether the second version may cause errors?不胜感激对上述代码的解释以及第二个版本是否可能导致错误?

If in doubt, read the Javadoc:如果有疑问,请阅读 Javadoc:

Collection.isEmpty() : Collection.isEmpty() :

Returns true if this collection contains no elements.如果此集合不包含任何元素,则返回 true。

Collection.size() : Collection.size()

Returns the number of elements in this collection返回此集合中的元素数

So, assuming the collection is implemented correctly:因此,假设正确实现了集合:

collection.isEmpty() <=> collection.size() == 0

Or, conversely:或者,相反:

!collection.isEmpty() <=> collection.size() != 0

Since the number of elements should only be positive, this means that:由于元素的数量应该只为正数,这意味着:

!collection.isEmpty() <=> collection.size() > 0

So yes, the two forms are equivalent.所以是的,这两种形式是等价的。

Caveat : actually, they're only equivalent if your collection isn't being modified from another thread at the same time.警告:实际上,只有当您的集合没有同时被另一个线程修改时,它们才等效。

This:这个:

!substanceList.isEmpty() && (substanceList.size() > 0)

is equivalent to, by the logic I present above:根据我上面提出的逻辑,相当于:

!substanceList.isEmpty() && !substanceList.isEmpty()

You can only simplify this to您只能将其简化为

!substanceList.isEmpty()

if you can guarantee that its value doesn't change in between evaluations of substanceList.isEmpty() .如果你能保证它的值在substanceList.isEmpty()评估之间不会改变。

Practically, it is unlikely that you need to care about the difference between these cases, at least at this point in the code.实际上,您不太可能需要关心这些情况之间的区别,至少在代码的这一点上是这样。 You might need to care about the list being changed in another thread, however, if it can become empty before (or while) executing createAmountText .可能需要关心在另一个线程中更改的列表,但是,如果它在执行createAmountText之前(或同时)变为空。 But that's not something that was introduced by this refactoring.但这不是这次重构引入的东西。

TL;DR: using if (!substanceList.isEmpty()) { does practically the same thing, and is clearer to read. TL;DR:使用if (!substanceList.isEmpty()) {几乎做同样的事情,并且更清晰易读。

Actually, you can read the source code downloaded in the JDK:实际上,您可以阅读JDK中下载的源代码:

/**
 * Returns <tt>true</tt> if this list contains no elements.
 *
 * @return <tt>true</tt> if this list contains no elements
 */
public boolean isEmpty() {
    return size == 0;
}

I think that this settles all the queries.我认为这可以解决所有疑问。

The only difference between the first and the second approach is that the first approach performs a redundant check.第一种方法和第二种方法之间的唯一区别是第一种方法执行冗余检查。 nothing else.没有别的。

Thus, you'd rather avoid the redundant check and go with the second approach.因此,您宁愿避免冗余检查并采用第二种方法。

Implementation of isEmpty() in AbstractCollection is as follows: AbstractCollectionisEmpty()实现如下:

public boolean isEmpty() {
    return size() == 0;
}

So you can safely assume that !list.isEmpty() is equivalent to list.size() > 0 .所以你可以放心地假设!list.isEmpty()等价于list.size() > 0

As for "what is better code", if you want to check if the list is empty or not, isEmpty() is definitely more expressive.至于“什么是更好的代码”,如果要检查列表是否为空, isEmpty()肯定更具表现力。
Subclasses might also override isEmpty() from AbstractCollection and implement in more efficient manner than size() == 0 .子类也可能覆盖AbstractCollection isEmpty()并以比size() == 0更有效的方式实现。 So (purely theoretically) isEmpty() might be more efficient.所以(纯粹理论上) isEmpty()可能更有效。

Yes, it can be refactored as you did.是的,它可以像您一样重构。 The issue with both approaches is that you would do the check every time you want to call the method createAmountText on a List.这两种方法的问题在于,每次要调用 List 上的createAmountText方法时,都需要进行检查。 This means you would be repeating the logic, a better way would be to use DRY (don't Repeat Yourself) principle and factor these checks into your method.这意味着您将重复逻辑,更好的方法是使用 DRY(不要重复自己)原则并将这些检查因素纳入您的方法。 So your method's body should encapsulated by this check.所以你的方法的主体应该被这个检查封装。

It should look like:它应该看起来像:

<access modifier> String createAmountText(List substanceList){
   if(substanceList != null && !substanceList.isEmpty()){
       <The methods logic>
   }
   return null;   
}

The javadocs for Collection.size() and Collection.isEmpty() say: Collection.size()Collection.isEmpty()javadocs说:

boolean isEmpty()

Returns true if this collection contains no elements.如果此集合不包含任何元素,则返回 true。

int size()

Returns the number of elements in this collection返回此集合中的元素数

Since "contains no elements" implies that the number of elements in the collection is zero, it follows that list.isEmpty() and list.size() == 0 will evaluate to the same value.由于“不包含任何元素”意味着集合中的元素数量为零,因此list.isEmpty()list.size() == 0将评估为相同的值。

I want to some explanation of above code我想对上面的代码做一些解释

The second version is correct.第二个版本是正确的。 The first version looks like it was written either by an automatic code generator, or a programmer who doesn't really understand Java.第一个版本看起来像是由自动代码生成器或并不真正了解 Java 的程序员编写的。 There is no good reason to write the code that way.没有充分的理由以这种方式编写代码。

(Note: if some other thread could be concurrently modifying the list, then both versions are problematic unless there is proper synchronization. If the list operations are not synchronized then may be memory hazards. But in the first version, there is also the possibility of a race condition ... where the list appears be empty and have a non-zero size!) (注意:如果其他线程可以并发修改列表,那么除非有适当的同步,否则两个版本都有问题。如果列表操作不同步则可能是内存危害。但在第一个版本中,也有可能竞争条件......列表显示为空且大小非零!)

and want to know second way may be caused some error.并想知道第二种方式可能会导致一些错误。

It won't.不会。


Incidentally list.isEmpty() is preferable to list.size() == 0 for a couple of reasons:顺便说一下,由于以下几个原因, list.isEmpty()list.size() == 0更可取:

  • It is more concise (fewer characters).它更简洁(字符更少)。
  • It expresses the intent of your code more precisely.它更准确地表达了代码的意图
  • It may be more efficient.它可能更有效率。 Some collection implementations may need to count the elements in the collection to compute the size.一些集合的实现可能需要集合中的元素来计算尺寸。 That may be an O(N) operation, and could other undesirable effects.这可能是O(N)操作,也可能是其他不良影响。 For example, if a collection is a lazy list that only gets reified as you iterate the elements, then calling size() may result in excessive memory use.例如,如果一个集合是一个惰性列表,它只会在您迭代元素时被具体化,那么调用size()可能会导致过多的内存使用。

Sure - the two methods can be used to express the same thing.当然 - 这两种方法可以用来表达同样的事情。

But worth adding here: going for size() > 0 is somehow a more direct violation of the Tell, don't ask principle: you access an "implementation detail", to then make a decision based on that.但值得在这里补充:选择size() > 0在某种程度上直接违反了Tell, don't ask原则:您访问“实现细节”,然后基于此做出决定。

In that sense, isEmpty() should be your preferred choice here!从这个意义上说, isEmpty()应该是你的首选!

Of course, you are still violating TDA when using isEmpty() - because you are again fetching status from some object to then make a decision on it.当然,您在使用isEmpty()仍然违反了 TDA - 因为您再次从某个对象获取状态然后对其做出决定。

So the really best choice would be to write code that doesn't need at all to make such a query to internal state of your collection to then drive decisions on it.因此,真正最好的选择是编写完全不需要对集合的内部状态进行此类查询的代码,然后驱动对它的决策。 Instead, simply make sure that createAmountText() properly deals with you passing in an empty list!相反,只需确保createAmountText()正确处理您传入的列表! Why should users of this list, or of that method need to care whether the list is empty or not?!为什么这个列表,或该方法需要用户关心的列表是否为空?

Long story short: maybe that is "over thinking" here - but again: not using these methods would lead you to write less code!长话短说:也许这里是“过度思考”——但同样:不使用这些方法会导致你编写更少的代码! And that is always an indication of a good idea.这总是一个好主意的迹象。

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

相关问题 为什么 list.size()&gt;0 在 Java 中比 list.isEmpty() 慢? - Why is list.size()>0 slower than list.isEmpty() in Java? 静态list.isEmpty()操作上的java.lang.NullPointerException - java.lang.NullPointerException on a static list.isEmpty() operation 相当于BitSet的list.size()是什么? - Whats the list.size() equivalent of the BitSet? 为什么recyclerview不添加所有list.size? - Why the recyclerview don't add all list.size? 对话框中的Bug RecyclerView.scrollToPosition(list.size() - 1) - Bug RecyclerView.scrollToPosition(list.size()-1) in Dialog 为什么运行时间复杂(清单 <Object> )list.size()是O(1)吗? - Why the running time complexity of (List<Object>) list.size() is O(1)? 使用 list.size() 或变量进行多次使用? (局部优化) - Use list.size() or a variable for multiple use ? (local optimization) 继续调用 array.length 或 list.size() 的性能损失 - Performance loss of continued call to array.length or list.size() for(int i = 0,length = list.size; i有什么区别 - What is the difference between “for(int i=0,length=list.size;i<length;i++) ” and “for(int i=0;i<list.size;i++) ”? 当A Thread(list.add())和B Thread(list.size())工作时,此行如何工作? - how this line works when A Thread(list.add()) and B Thread(list.size()) works?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM