当我们有SortedMap / SortedSet时,为什么我们需要TreeMap / TreeSet?

时间:2013-02-07 05:10:19

标签: java treemap treeset

好的,SortedMap / SortedSet是一个界面,TreeMap / TreeSet是它的实现。它们都按顺序排列元素,对吧?那么为什么我们需要TreeMap / TreeSet

5 个答案:

答案 0 :(得分:13)

接口不提供任何功能,它们只是根据它提供的方法定义类的大纲。但SortedMap / SortedSet内部没有代码实现如何实现此功能。

事实上,您通常可以通过多种方式实现相同的功能。想想界面java.util.Set:您可以将其实现为TreeSet,也可以实现为HashSet。通常,在不同的实现之间存在一些权衡:散列集平均可以提供更快的访问时间,而树集可能更好地保持其项目的顺序。

然而,通常情况下,开发人员并不真正关心实现细节,只要他们知道他们可以将项目存储在集合中并检索它们。接口定义了这个基本思想,但不是如何实现它。

这也是您无法实例化接口的原因。如果您尝试以下操作:

SortedSet<Integer> set = new SortedSet<Integer>();

你的编译器会抱怨。这是因为“SortedSet”并没有真正实现一个集合本身,它只是定义了一个有序集合的实现必须在方法方面提供的。

这是一个人为的例子。想象一下,您希望提供一种功能来计算集合中正整数的百分比。您可以定义一个方法:

public double getPercentageOfPositives(Set<Integer> set) {
    if (set.size() == 0) {
        return 0.0;
    }

    int count = 0;

    for (Iterator<Integer> iter = set.iterator(); iter.hasNext();) {
        if (iter.next() > 0) count++;
    }

    return 100.0 * count / set.size();
}

在这里,您并不关心方法的用户是否为您提供TreeSetHashSet。给定类使用哪个原则并不重要,因为无论如何你只是调用size()方法和iterator()方法。您所需要的只是相信任何一组都有这两种方法。界面为您提供信任。

因此,您的方法签名只询问Set,这是一个接口,定义实现它的所有类必须提供(其中包括)size()iterator()方法。如果你这样写:

public double getPercentageOfPositives(SortedSet<Integer> set) {
    ...
}

我有一个HashSet的实例,即使HashSet提供size()iterator(),我也无法使用您的方法。 : - (

从这个意义上说,接口就像一个超类,它定义了所有类必须具有实现它的共性。但它本身并没有提供任何功能。

因此,回到SortedSet的原始示例:此接口不提供任何功能。它仅定义了排序集实现必须提供的方法。 TreeSet就是这样的实现。

同样的思路适用于SortedMap

答案 1 :(得分:4)

正确的原因是,当我们有时,我们需要接口

SortedMapSortedSet定义了使用TreeMapTreeSet的树实现的功能。

答案 2 :(得分:2)

SortedMap / SortedSet是接口,因此您无法实例化它们。 TreeMap / TreeSet是类,可以实例化和使用。我们需要SortedMap / SortedSet的原因是可能存在除Sun基于树的实现之外的实现。

答案 3 :(得分:1)

这是一张备忘单以获得全局(来源在图片中)

enter image description here

答案 4 :(得分:0)

答案在你的问题中; SortedMapSortedSet是接口。它们定义方法和属性,但它们实际上并没有实现它们,因此它们不提供任何功能。

TreeMapTreeSet是这些接口的实现。

良好的OOP设计实践建议您对接口进行编码,而不是实现。这意味着您的所有方法签名都应该引用接口而不是类。

所以你会这样做:

Object squishObjects(SortedMap map);

而不是

Object squishObjects(TreeMap map);

这样,如果出现更好的SortedMap实现,您可以将其切换,而无需修改依赖TreeMap的所有方法。