您的位置:首页 > 其它

SortedMap和TreeMap

2016-04-30 20:58 417 查看
接口SortedMap<K,V>

public interface SortedMap<K,V>

extends Map<K,V>

保证按照键的升序排列的映射,可以按照键的自然顺序(参见 Comparable 接口)进行排序, 或者通过创建有序映射时提供的比较器进行排序。对有序映射的集合视图

(由 entrySet、keySet 和 values 方法返回)进行迭代时,此顺序就会反映出来。

要采用此排序,还需要提供一些其他操作(此接口是相似于 SortedSet 接口的映射)。

插入有序映射的所有键都必须实现 Comparable 接口(或者被指定的比较器所接受)。

另外,所有这些键都必须是可互相比较的:k1.compareTo(k2)(或 comparator.compare(k1, k2))

对有序映射中的任意两个元素 k1 和 k2 都不得抛出 ClassCastException。

试图违反这些限制将导致违反方法或者构造方法的调用,从而抛出 ClassCastException。

注意,如果有序映射正确实现了 Map 接口,则有序映射所保持的顺序(无论是否明确提供了比较器)都必须保持相等一致性。

(相等一致性 的精确定义请参阅 Comparable 接口或 Comparator 接口)。

这也是因为 Map 接口是按照 equals 操作定义的,但有序映射使用它的 compareTo(或 compare)方法对所有键进行比较,

因此从有序映射的观点来看,此方法认为两个对象拥有相等的映射键则说明它们是相等的。

即使顺序没有保持相等一致性,树映射的行为仍然是 定义良好的,只不过没有遵守 Map 接口的常规协定。

所有通用有序映射实现类都应该提供 4 个“标准”构造方法:

1) void(不带参数)构造方法,创建空的有序映射,按照键的自然顺序 排序。

2) 带有一个 Comparator 类型参数的构造方法,创建一个空的有序映射,根据指定的比较器排序。

3) 带有一个 Map 类型参数的构造方法,创建一个键-值映射关系与参数相同的有序映射,按照键的自然顺序排序。

4) 带有一个有序映射类型参数的构造方法,创建一个新的有序映射,键-值映射关系及排序方法与输入的有序映射相同。如:TreeMap(SortedMap<K,? extends V> m)

除了 JDK 实现(TreeMap 类)遵循此建议外,无法保证强制实施此建议(因为接口不能包含构造方法)。

SortedMap声明的接口

Public Methods
abstract Comparator<? super K>comparator()
Returns the comparator used to compare keys in this sorted map.
返回与此有序映射关联的比较器,如果使用键的自然顺序,则返回 null。
abstract KfirstKey()
Returns the first key in this sorted map.
返回有序映射中当前第一个(最小的)键。
abstract SortedMap<K, V>headMap(K endKey)
Returns a sorted map over a range of this sorted map with all keys that are less than the specified
endKey
.
返回此有序映射的部分元素,其元素的键值应该小于 toKey。
abstract KlastKey()
Returns the last key in this sorted map.
返回有序映射中当前最后一个(最大的)键。
abstract SortedMap<K, V>subMap(K startKey, K endKey)
Returns a sorted map over a range of this sorted map with all keys greater than or equal to the specified
startKey
and less than
the specified
endKey
.
返回此有序映射的部分视图,其键值从 fromKey(包括)到 toKey(不包括)。
abstract SortedMap<K, V>tailMap(K startKey)
Returns a sorted map over a range of this sorted map with all keys that are greater than or equal to the specified
startKey
.
返回有序映射的部分视图,其键大于或等于 fromKey。
TreeMap(1.2)

TreeMap是SortedMap接口的基于红黑树的实现。此类保证了映射按照升序顺序排列关键字, 根据使用的构造方法不同,可能会按照键的类的自然顺序进行排序(参见 Comparable), 或者按照创建时所提供的比较器进行排序。

此实现为 containsKey、get、put 和 remove 操作提供了保证的 log(n) 时间开销。

这些算法是 Cormen、Leiserson 和 Rivest 的《Introduction to Algorithms》中的算法的改编。

注意,如果有序映射要正确实现 Map 接口,则有序映射所保持的顺序(无论是否明确提供比较器)都必须保持与等号一致。

(请参见与等号一致 的精确定义的 Comparable 或 Comparator。)这也是因为 Map 接口是按照等号操作定义的,

但映射使用它的 compareTo(或 compare)方法对所有键进行比较,因此从有序映射的观点来看,

此方法认为相等的两个键就是相等的。即使顺序与等号不一致,有序映射的行为仍然是 定义良好的;

只不过没有遵守 Map 接口的常规约定。

注意,此实现不是同步的。如果多个线程同时访问一个映射,并且其中至少一个线程从结构上修改了该映射,

则其必须 保持外部同步。(结构上修改是指添加或删除一个或多个映射关系的操作;

仅改变与现有键关联的值不是结构上的修改。)这一般通过对自然封装该映射的某个对象进行同步操作来完成。

如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。

最好在创建时完成这一操作,以防止对映射进行意外的不同步访问,如下所示:

Map m = Collections.synchronizedMap(new TreeMap(...));

由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的:在迭代器创建之后,

如果从结构上对映射进行修改,除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,

迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,

而不是冒着在将来不确定的时间任意发生不确定行为的风险。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。

快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。

因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。

注意1:此实现不是同步的。不是线程安全的。

注意2:TreeMap是用键来进行升序顺序来排序的。通过Comparable 或 Comparator来排序。

注意3:由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的。

注意4:和HashMap一样,如果插入重复的元素,后面的元素会覆盖前面的。

注意5: 键不可以为null,但是值可以为null

示例1:

import java.util.Comparator;

import java.util.Random;

import java.util.TreeMap;

import java.util.concurrent.SynchronousQueue;

import java.util.concurrent.TimeUnit;

public class Test {

/**

* @param args

*/

public static void main(String[] args) {

TreeMap<Integer,People> map=new TreeMap();

People p1=new People("robin",1,28);

People p2=new People("robin",2,29);

People p3=new People("harry",3,30);

map.put(new Integer(100), p1);

map.put(new Integer(100), p2);

map.put(new Integer(1), p3);

map.put(new Integer(2), null);

for(People p:map.values())

{

System.out.println(p);

}

}

}

class People{

String name;

int id;

int age;

public People(String name,int id)

{

this(name,id,0);

}

public People(String name,int id,int age)

{

this.name=name;

this.id=id;

this.age=age;

}

public String toString()

{

return id+name+age;

}

public boolean equals(Object o)

{

if(o==null)

return false;

if(!(o instanceof People))

return false;

People p=(People)o;

boolean res=name.equals(p.name);

if(res)

System.out.println("name "+name+" is double");

else

System.out.println(name+" vS "+p.name);

return res;

}

public int hashCode()

{

return name.hashCode();

}

}

输出结果:

3harry30

null

2robin29
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: