Java 为什么List.add(E)返回布尔值,而List.add(int,E)返回void?

Java 为什么List.add(E)返回布尔值,而List.add(int,E)返回void?,java,collections,arraylist,Java,Collections,Arraylist,查看,我发现ArrayList有一个重载的add方法: 公共布尔加法(E) 将指定的元素追加到此列表的末尾 及 公共无效添加(整数索引, 电子元件) 在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(将一个元素添加到其索引中) 我注意到第一个返回的是布尔值,而第二个返回的是空值。事实证明,第一个add必须返回一个布尔值,因为: 返回: true(由Collection.add(E)指定) 所以我去了: 布尔加法(E) 确保此集合包含指定的元素(可选操作)。

查看,我发现ArrayList有一个重载的add方法:

公共布尔加法(E)

将指定的元素追加到此列表的末尾

公共无效添加(整数索引, 电子元件)

在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(将一个元素添加到其索引中)

我注意到第一个返回的是
布尔值
,而第二个返回的是
空值
。事实证明,第一个
add
必须返回一个
布尔值,因为:

返回: true(由Collection.add(E)指定)

所以我去了:

布尔加法(E)

确保此集合包含指定的元素(可选操作)。如果此集合因调用而更改,则返回true。(如果此集合不允许重复并且已包含指定元素,则返回false。)

所以我的问题是,为什么指定
add
返回布尔值而不是空值?当我
添加
某个东西时,我希望只执行一个操作

我知道,与ArrayList相反,还有其他数据结构不允许重复(例如集合)。但即便如此,问题也不能通过以下方式解决:

public void add(E e){
    if(e is not in set){
        add e;
    }
}

这样,如果
e
在集合中,则不会采取任何操作。为什么返回一个
boolean
而不是
void
方法更好呢?

因为知道是否确实添加了某些内容,或者是否已经添加了一些内容通常很有用。

因为这是一个额外的信息,不需要花费任何费用,在某些情况下可能有用。例如:

Set<String> set = new HashSet<String>();
set.add("foobar");
boolean wasAlreadyThere = set.add("foobar");

这需要两倍的工作(首先必须查找,然后再次查找才能添加)。

Collection.add
是一种非常通用的方法(不是Java泛型,而是广泛适用的)。因此,他们需要一个普遍适用的返回值

有些类(如
ArrayList
)总是接受元素,因此总是返回
true
。在这些情况下,返回类型为
void
也一样好

但是其他的,比如
Set
,有时不允许添加元素。在
Set
的情况下,如果已经存在相等的元素,则会发生这种情况。知道这一点通常是有帮助的。另一个例子是有界集合(它只能容纳一定数量的元素)

您可以问,“难道代码不能手动检查吗?”例如,使用一组:

if (!set.contains(item)) {
    set.add(item);
    itemWasAdded(item);
}
这比您现在可以做的更详细,但不是全部:

if (set.add(item)) {
    itemWasAdded(item);
}

但是这种check-then-act行为不是线程安全的,这在多线程应用程序中非常重要。例如,可能是另一个线程在您检查第一个代码段中的
set.contains(item)
set.add(item)
之间添加了一个相等的项。在多线程场景中,这两个动作确实需要是单个原子动作;从方法返回
boolean
使之成为可能。

我的猜测是因为有时您可能想知道是否未能将某些内容放入集合中。如果返回了
void
,则除了查找后面的元素之外,没有其他方法可以知道。但是,我想不出任何相关的例子……您的代码不会做同样的工作,因为它不会让调用方知道它是否已经包含对象。等价的代码在.add之前应该有一个.contains。如果您不关心对
add
的调用是否导致了任何更改,那么您就没有义务对结果做任何处理。但其他人可能会发现这些信息很有用。我最近使用了一个使用示例:一个处理队列和一个搜索算法,该算法只在邻居是新的情况下查看分片并将邻居添加到队列中(否则,如果你自己弯曲,你将永远搜索)。显然可以用几种不同的方式实现,但这是其中之一。这个答案更适合作为注释。所有答案都适合作为注释,答案实际上在javadocs中->
返回:如果此集合由于调用而更改,则返回:true。。。不公平的否决票顺便说一句,@A4L这并不公平。我同意你的观点,但它肯定回答了OP的一半问题,并且没有错,因此可能不值得投赞成票,但肯定不值得投反对票。被接受的答案在内容上与这个答案完全相同,因为它没有回答关于
List#add(int,E)
的部分,它只是更详细了一点,但是有这么多的投票,这很奇怪。我之所以不投票,问题是为什么这两个调用有不同的返回类型。如果有人问“为什么许多澳大利亚哺乳动物都有育儿袋,而在世界其他地方却很罕见?”我会投反对票:“这样它们就可以抱着它们的孩子了”。我不想变得很迂腐,但是。。。第一个例子中的逻辑不是倒过来的吗?
不是Java泛型的意义上的逻辑
-谢天谢地!:)+回答得好。对于某些类型的实现,检查然后添加也可能是低效的,因此API允许您以更好的方式处理这些情况,这很好。谢谢您的回答。我不同意任何细节。”返回类型的void也一样好。直到现在,我还没有发现任何情况下,返回虚空将是一个好主意。我宁愿让添加的对象返回,也不要void。
if (set.add(item)) {
    itemWasAdded(item);
}