3

Minimum complete definition of Collection interface consists only of two methods: iterator() and size(), which are abstract in AbstractCollection.

Why all other methods not made default in Java 8? Compatibility shouldn't be an issue, for example, Iterator.remove() was abstract until Java 7, but made default since Java 8.

Subclassing from AbstractCollection is inconvenient sometimes, when I want a Collection implementation to be a member of another class hierarchy. Wasn't that one of the reasons why default methods in interfaces actually needed in Java?

The same question about Map, List and other basic interfaces, comprising Java Collection Framework.

UPDATE

Paul Sandoz:

Generally we have only converted existing abstract methods on an interface to non-abstract if there was a compelling reason to aid implementations, such as Iterator.remove.

These are not new methods on Collection, and there are already implementations in AbstractCollection. The advantage of converting these abstract into non-abstract methods its not particularly compelling given one is most likely to inherit from AbstractCollection or provide more efficient implementations.

It would be possible to move all non-abstract methods on AbstractCollection to Collection. If we were starting from a blank sheet of paper that is what we might have done. (Note one cannot do this with all non-abstract methods on AbstractList.)

http://mail.openjdk.java.net/pipermail/core-libs-dev/2014-February/025118.html

4

1 回答 1

5

默认方法的主要目标是实现接口的兼容演变。请参阅Lambda文档状态的第 10 节。这种演变的主要方向之一是促进内部迭代。请参阅Lambda 状态:库版本的内部与外部迭代部分。为此,出现了新的方法,例如、和。Iterable.forEachCollection.removeIfList.replaceAll

添加了其他类似List.sort的方法,因为它允许单独的具体列表实现提供更有效的排序算法,而Collections.sort.

最后,为了方便起见,添加了默认方法,例如Iterator.remove. 多年来,我们和许多其他人都对添加一个remove每次UnsupportedOperationException实现新的Iterator. 默认方法remove为我们执行此操作。请注意,至关重要的是,此方法实际上并未删除任何元素。(会怎样?)

为一堆方法提供默认实现似乎很方便,这些Collection方法是用其他方法编写的,例如iterator. 但是,我认为它不是很有用,实际上我不确定某些方法是否可行。

考虑Collection.contains(Object)方法。可以想象,可以iterator通过逐步遍历每个元素并比较是否相等来编写此默认实现。TreeSet对于 a或 a之类的东西,这将是一个非常糟糕的实现HashSet。即使是具体的List实现,例如LinkedListArrayList提供比单步执行迭代器更有效的快速路径实现。有一个默认实现Collection.contains可能有点方便,但实际上,它并没有增加太多价值。实际上,每个集合都希望覆盖它。

现在考虑equals。的规范引发Collection.equals了一系列微妙的问题。简单来说,aSet只能等于 another Set,aList只能等于 another List,而且equals运算必须是对称的。因此,Collection既不是 aList也不是 a 的 aSet永远不能等于 aList或 a Set

好的,所以我们的Collection.equals默认方法必须预先进行一系列instanceof检查。如果两者都是,Lists我们可以委托给AbstractList.equals,如果两者都是,Sets我们可以委托给AbstractSet.equals。现在让我们假设这个对象和另一个对象既不是Lists也不是Sets。如果它们是不能彼此相等的不同具体实现怎么办?我们不能说。

撇开这一点不谈,让我们假设我们的平等被定义为具有相同的成员资格。我们唯一能做的就是遍历每个集合。但是我们不能(通常)对迭代顺序做出任何假设,所以我们不能同时迭代它们并像列表那样成对地比较元素。相反,我们必须将一个集合中的所有元素加载到某种临时集合中。这不可能是Set因为我们可能有重复。然后,我们将检查另一个元素的每个元素,Collection以确保其中的每个元素都在第一个元素中,并且第一个元素中没有多余的元素。这不是很困难,但它很昂贵,并且不支持某些语义,例如顺序敏感性。

我无法想象任何具体的集合子类实际上想要使用这个算法。


总之,使用默认方法使集合实现更容易并不是默认方法的设计目标之一。此外,虽然提供默认方法似乎Collection很方便,但它们实际上似乎没有用。任何合理Collection的实现都需要覆盖所有方法,以提供它想要的语义,而不会非常低效。

于 2014-02-14T08:21:45.410 回答