好的,SortedMap
/ SortedSet
是一个界面,TreeMap
/ TreeSet
是它的实现。它们都按顺序排列元素,对吧?那么为什么我们需要TreeMap
/ TreeSet
?
答案 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();
}
在这里,您并不关心方法的用户是否为您提供TreeSet
或HashSet
。给定类使用哪个原则并不重要,因为无论如何你只是调用size()
方法和iterator()
方法。您所需要的只是相信任何一组都有这两种方法。界面为您提供信任。
因此,您的方法签名只询问Set
,这是一个接口,定义实现它的所有类必须提供(其中包括)size()
和iterator()
方法。如果你这样写:
public double getPercentageOfPositives(SortedSet<Integer> set) {
...
}
我有一个HashSet
的实例,即使HashSet
提供size()
和iterator()
,我也无法使用您的方法。 : - (
从这个意义上说,接口就像一个超类,它定义了所有类必须具有实现它的共性。但它本身并没有提供任何功能。
因此,回到SortedSet
的原始示例:此接口不提供任何功能。它仅定义了排序集实现必须提供的方法。 TreeSet
就是这样的实现。
同样的思路适用于SortedMap
。
答案 1 :(得分:4)
正确的原因是,当我们有类时,我们需要接口。
SortedMap
和SortedSet
定义了使用TreeMap
和TreeSet
的树实现的功能。
答案 2 :(得分:2)
SortedMap
/ SortedSet
是接口,因此您无法实例化它们。 TreeMap
/ TreeSet
是类,可以实例化和使用。我们需要SortedMap
/ SortedSet
的原因是可能存在除Sun基于树的实现之外的实现。
答案 3 :(得分:1)
这是一张备忘单以获得全局(来源在图片中)
答案 4 :(得分:0)
答案在你的问题中; SortedMap
和SortedSet
是接口。它们定义方法和属性,但它们实际上并没有实现它们,因此它们不提供任何功能。
TreeMap
和TreeSet
是这些接口的实现。
良好的OOP设计实践建议您对接口进行编码,而不是实现。这意味着您的所有方法签名都应该引用接口而不是类。
所以你会这样做:
Object squishObjects(SortedMap map);
而不是
Object squishObjects(TreeMap map);
这样,如果出现更好的SortedMap
实现,您可以将其切换,而无需修改依赖TreeMap
的所有方法。