我看到这样的代码。
if (!substanceList.isEmpty() && (substanceList.size() > 0))
{
substanceText = createAmountText(substanceList);
}
并且,可以像这样重构它。?
if (!substanceList.isEmpty())
{
substanceText = createAmountText(substanceList);
}
我想对上面的代码进行一些解释并想知道第二种方式可能会引起一些错误。?
答案 0 :(得分:4)
如有疑问,请阅读Javadoc:
如果此集合不包含任何元素,则返回true。
返回此集合中元素的数量
因此,假设集合正确实现:
collection.isEmpty() <=> collection.size() == 0
或者反过来说:
!collection.isEmpty() <=> collection.size() != 0
由于元素的数量应该只是正数,这意味着:
!collection.isEmpty() <=> collection.size() > 0
是的,这两种形式是等价的。
警告:实际上,如果您的集合未同时从其他线程进行修改,则它们只是等效的。
此:
!substanceList.isEmpty() && (substanceList.size() > 0)
按照上面的逻辑,相当于:
!substanceList.isEmpty() && !substanceList.isEmpty()
您只能将此简化为
!substanceList.isEmpty()
如果您可以保证其值在substanceList.isEmpty()
的评估之间不会发生变化。
实际上,您不太可能需要关心这些情况之间的差异,至少在代码的这一点上。您可能需要关心在另一个线程中更改的列表,但是,如果它在执行createAmountText
之前(或同时)变空。但这不是重构所引入的。
TL; DR:使用if (!substanceList.isEmpty()) {
几乎完全相同,并且阅读起来更清楚。
答案 1 :(得分:2)
第一种方法和第二种方法的唯一区别在于第一种方法执行冗余检查。没别的。
因此,您宁愿避免冗余检查,也不要采用第二种方法。
答案 2 :(得分:2)
isEmpty()
中AbstractCollection
的实施情况如下:
public boolean isEmpty() {
return size() == 0;
}
因此,您可以放心地假设!list.isEmpty()
等同于list.size() > 0
。
至于“什么是更好的代码”,如果你想检查列表是否为空,isEmpty()
肯定更具表现力。
子类也可以覆盖isEmpty()
中的AbstractCollection
,并以比size() == 0
更有效的方式实施。所以(纯理论上)isEmpty()
可能更有效率。
答案 3 :(得分:1)
是的,它可以像你一样重构。这两种方法的问题在于,每次要在List上调用方法createAmountText
时都要进行检查。这意味着您将重复逻辑,更好的方法是使用DRY(不要重复自己)原则并将这些检查纳入您的方法。
因此,您的方法的主体应该通过此检查进行封装。
应该看起来像:
<access modifier> String createAmountText(List substanceList){
if(substanceList != null && !substanceList.isEmpty()){
<The methods logic>
}
return null;
}
答案 4 :(得分:1)
Collection.size()
的{{3}}和Collection.isEmpty()
说:
boolean isEmpty()
如果此集合不包含任何元素,则返回true。
int size()
返回此集合中元素的数量
由于“不包含元素”意味着集合中元素的数量为零,因此list.isEmpty()
和list.size() == 0
将评估为相同的值。
我想对上面的代码进行一些解释
第二个版本是正确的。第一个版本看起来像是由自动代码生成器或者不是真正理解Java的程序员编写的。没有良好的理由以这种方式编写代码。
(注意:如果其他一些线程可以同时修改列表,那么除非有正确的同步,否则两个版本都有问题。如果列表操作不同步则可能存在内存危险。但在第一个版本中,还有竞争条件的可能性......列表显示为空并且大小非零!)
并想知道第二种方式可能会导致一些错误。
不会。
顺便提一句,list.isEmpty()
优于list.size() == 0
,原因如下:
O(N)
操作,并可能产生其他不良影响。例如,如果一个集合是一个惰性列表,只有在迭代元素时才会被激活,那么调用size()
可能会导致内存使用过多。答案 5 :(得分:1)
当然 - 这两种方法可以用来表达同样的事情。
但值得在此处添加:size() > 0
以某种方式更多直接违反了Tell, don't ask原则:您访问“实施细节”,然后做出决定基于此。
从这个意义上说,isEmpty()
应该是你的首选!
当然,在使用isEmpty()
时,您仍然违反TDA - 因为您再次从某个对象获取状态,然后对其做出决定。
因此,最好的选择是编写完全不需要对集合的内部状态进行此类查询的代码,然后对其进行驱动决策。相反,只需确保createAmountText()
正确处理您传入空列表!为什么用户此列表或该方法需要关心列表是否为空?!
长话短说:也许这就是“过度思考” - 但同样:不使用这些方法会导致你编写更少的代码!这总是表明一个好主意。
答案 6 :(得分:1)
实际上,您可以阅读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;
}
我认为这解决了所有查询。