Java Knowledge series 7

Pepole who make a greate contribution on common libaraies deserve our respect.

Component(Widget) / STL / Container(Collection)

  1. 合成不会强迫我们的程序设计进入继承的分级结构中has-a relationship。同时,合成显得更加灵活,因为可以动态选择一种类型(以及行为),而继承要求在编译期间准确地知道一种类型。
  2. Java的工具(实用程序)库提供了一些“集合类”(亦称作“容器类”,但该术语已由AWT使用,所以这里仍采用“集合”这一称呼)。利用这些集合类,我们可以容纳乃至操纵自己的对象。Aggregate; container;
  3. 有两方面的问题将数组与其他集合类型区分开来:效率efficiency 和类型type。
  4. 对于Java来说,为保存和访问一系列对象(实际是对象的句柄 handle, or pointer in C++)数组,最有效的方法莫过于数组。数组实际代表一个简单的线性序列,它使得元素的访问速度非常快,但我们却要为这种速度付出代价:创建一个数组对象时,它的大小是固定的,而且不可在那个数组对象的“存在时间”内发生改变。可创建特定大小的一个数组,然后假如用光了存储空间,就再创建一个新数组,将所有句柄从旧数组移到新数组。这属于“矢量”(Vector)类的行为.
  5. 在Java中,由于对数组和集合都要进行范围检查,所以对性能有一定的影响。
  6. 这些类都涉及对对象的处理——好象它们没有特定的类型。换言之,它们将其当作Object类型处理(Object类型是Java中所有类的“根”类)。从某个角度看,这种处理方法是非常合理的:我们仅需构建一个集合,然后任何Java对象都可以进入那个集合(除基本数据类型外built-in type——可用Java的基本类型封装类将其作为常数置入集合,或者将其封装到自己的类内,作为可以变化的值使用)。这再一次反映了数组优于常规集合:创建一个数组时,可令其容纳一种特定的类型。这意味着可进行编译期类型检查,预防自己设置了错误的类型,或者错误指定了准备提取的类型。
  7. 无论使用的数组属于什么类型,数组标识符实际都是指向真实对象的一个句柄。那些对象本身是在内存“堆”里创建的。堆对象既可“隐式”创建(即默认产生),亦可“显式”创建(即明确指定,用一个new表达式)。堆对象的一部分(实际是我们能访问的唯一字段或方法)是只读的length(长度)成员,它告诉我们那个数组对象里最多能容纳多少元素。
  8. 集合类只能容纳对象句柄。但对一个数组,却既可令其直接容纳基本类型的数据,亦可容纳指向对象的句柄。利用象Integer、Double之类的“封装器”类,可将基本数据类型的值置入一个集合里。
  9. 象C和C++这样的语言会使问题复杂化,因为我们不能返回一个数组,只能返回指向数组的一个指针。这样就非常麻烦,因为很难控制数组的“存在时间”,它很容易造成内存“漏洞”的出现。Java采用的是类似的方法,但我们能“返回一个数组”。当然,此时返回的实际仍是指向数组的指针。但在Java里,我们永远不必担心那个数组的是否可用——只要需要,它就会自动存在。而且垃圾收集器会在我们完成后自动将其清除。
  10. 为容纳一组对象,最适宜的选择应当是数组。而且假如容纳的是一系列基本数据类型,更是必须采用数组。Have to use array when containing built-in type.
  11. 当我们编写程序时,通常并不能确切地知道最终需要多少个对象。有些时候甚至想用更复杂的方式来保存对象。为解决这个问题,Java提供了四种类型的“集合类”:Vector(矢量)、BitSet(位集)、Stack(堆栈)以及Hashtable(散列表)。
  12. 使用Java集合的“缺点”是在将对象置入一个集合时丢失了类型信息。之所以会发生这种情况,是由于当初编写集合时,那个集合的程序员根本不知道用户到底想把什么类型置入集合。若指示某个集合只允许特定的类型,会妨碍它成为一个“常规用途”的工具,为用户带来麻烦。为解决这个问题,集合实际容纳的是类型为Object的一些对象的句柄。这种类型当然代表Java中的所有对象,因为它是所有类的根。当然,也要注意这并不包括基本数据类型,因为它们并不是从“任何东西”继承来的。(It is solved with template in C++)这是一个很好的方案,只是不适用下述场合:
    • (1) 将一个对象句柄置入集合时,由于类型信息会被抛弃,所以任何类型的对象都可进入我们的集合——即便特别指示它只能容纳特定类型的对象。举个例子来说,虽然指示它只能容纳猫,但事实上任何人都可以把一条狗扔进来。
    • (2) 由于类型信息不复存在,所以集合能肯定的唯一事情就是自己容纳的是指向一个对象的句柄。正式使用它之前,必须对其进行造型,使其具有正确的类型。
  13. 参数化类型 parameterization type这类问题并不是孤立的——我们许多时候都要在其他类型的基础上创建新类型。此时,在编译期间拥有特定的类型信息是非常有帮助的。这便是“参数化类型”的概念。在C++中,它由语言通过“模板Template” 获得了直接支持。至少,Java保留了关键字generic,期望有一天能够支持参数化类型。但我们现在无法确定这一天何时会来临。
  14. 可利用“反复器”(Iterator)的概念达到这个目的。它可以是一个对象,作用是遍历一系列对象,并选择那个序列中的每个对象,同时不让客户程序员知道或关注那个序列的基础结构。此外,我们通常认为反复器是一种“轻量级”对象;也就是说,创建它只需付出极少的代价。但也正是由于这个原因,我们常发现反复器存在一些似乎很奇怪的限制。例如,有些反复器只能朝一个方向移动。Java的Enumeration(枚举,注释②)便是具有这些限制的一个反复器的例子。除下面这些外,不可再用它做其他任何事情:
    • (1) 用一个名为elements()的方法要求集合为我们提供一个Enumeration。我们首次调用它的nextElement()时 The de facto meaning is to move to next element and return the current element,这个Enumeration会返回序列中的第一个元素。
    • (2) 用nextElement()获得下一个对象。
    • (3) 用hasMoreElements()检查序列中是否还有更多的对象。
  15. ②:“反复器”这个词在C++和OOP的其他地方是经常出现的,所以很难确定为什么Java的开发者采用了这样一个奇怪的名字。Java 1.2的集合库修正了这个问题以及其他许多问题。
  16. BitSet实际是由“二进制位”构成的一个Vector。如果希望高效率地保存大量“开-关”信息,就应使用BitSet。它只有从尺寸的角度看才有意义;如果希望的高效率的访问,那么它的速度会比使用一些固有类型的数组慢一些。此外,BitSet的最小长度是一个长整数(Long)的长度:64位。这意味着假如我们准备保存比这更小的数据,如8位数据,那么BitSet就显得浪费了。所以最好创建自己的类,用它容纳自己的标志位。
  17. Stack有时也可以称为“后入先出”(LIFO)集合。换言之,我们在堆栈里最后“压入”的东西将是以后第一个“弹出”的。和其他所有Java集合一样,我们压入和弹出的都是“对象”,所以必须对自己弹出的东西进行“造型”。一种很少见的做法是拒绝使用Vector作为一个Stack的基本构成元素,而是从Vector里“继承”一个Stack。这样一来,它就拥有了一个Vector的所有特征及行为,另外加上一些额外的Stack行为。很难判断出设计者到底是明确想这样做,还是属于一种固有的设计。
  18. 这种“从一系列对象中选择”的概念亦可叫作一个“映射 map”、“字典 dictionary”或者“关联数组 relation array”。从概念上讲,它看起来象一个Vector,但却不是通过数字来查找对象,而是用另一个对象来查找它们!这通常都属于一个程序中的重要进程。
  19. 这个概念具体反映到抽象类Dictionary身上。该类的接口是非常直观的size()告诉我们其中包含了多少元素;isEmpty()判断是否包含了元素(是则为true);put(Object key, Object value)添加一个值(我们希望的东西),并将其同一个键关联起来(想用于搜索它的东西);get(Object key)获得与某个键对应的值;而remove(Object Key)用于从列表中删除“键-值”对。还可以使用枚举技术:keys()产生对键的一个枚举(Enumeration);而elements()产生对所有值的一个枚举。这便是一个Dictionary(字典)的全部。
  20. 散列码可以获取对象中的信息,然后将其转换成那个对象“相对唯一”的整数(int)。所有对象都有一个散列码,而hashCode()是根类Object的一个方法。Hashtable获取对象的hashCode(),然后用它快速查找键。这样可使性能得到大幅度提升(④)。
  21. 大家或许认为此时要做的全部事情就是正确地覆盖hashCode()。但这样做依然行不能,除非再做另一件事情:覆盖也属于Object一部分的equals()。当散列表试图判断我们的键是否等于表内的某个键时,就会用到这个方法。同样地,默认的Object.equals()只是简单地比较对象地址,了在散列表中将自己的类作为键使用,必须同时覆盖override hashCode() 和equals() befor objectize
  22. 调用了一个名为getProperties()的static方法,用于获得一个特殊的Properties对象,对系统的某些特征进行描述。list()属于Properties的一个方法,可将内容发给我们选择的任何流式输出。也有一个save()方法,可用它将属性列表写入一个文件,以便日后用load()方法读取。尽管Properties类是从Hashtable继承的,但它也包含了一个散列表,用于容纳“默认”属性的列表。所以假如没有在主列表里找到一个属性,就会自动搜索默认属性。
  23. JGL实现了许多功能,可满足对一个集合库的大多数常规需求,它与C++的模板机制非常相似。JGL包括相互链接起来的列表、设置、队列、映射、堆栈、序列以及反复器,它们的功能比Enumeration(枚举)强多了。同时提供了一套完整的算法,如检索和排序等。
  24. JGL已包括到一些厂商发行的Java套件中,而且ObjectSpace公司自己也允许所有用户免费使用JGL,包括商业性的使用。详细情况和软件下载可访问http://www.ObjectSpace.com。与JGL配套提供的联机文档做得非常好,可作为自己的一个绝佳起点使用。
  25. 我感觉特别好的一个是用“反复器”(Inerator)代替了“枚举”(Enumeration)。
  26. 此次重新设计也加强了集合库的功能。现在新增的行为包括链接列表、队列以及撤消组队(即“双终点队列”)。集合库的设计是相当困难的(会遇到大量库设计问题)。在C++中,STL用多个不同的类来覆盖基础。这种做法比起STL以前是个很大的进步,那时根本没做这方面的考虑。但仍然没有很好地转换到Java里面。结果就是一大堆特别容易混淆的类。在另一个极端,我曾发现一个集合库由单个类构成:colleciton,它同时作为Vector和Hashtable使用。新集合库的设计者则希望达到一种新的平衡:实现人们希望从一个成熟集合库上获得的完整功能,同时又要比STL和其他类似的集合库更易学习和使用。这样得到的结果在某些场合显得有些古怪。但和早期Java库的一些决策不同,这些古怪之处并非偶然出现的,而是以复杂性作为代价,在进行仔细权衡之后得到的结果。这样做也许会延长人们掌握一些库概念的时间,但很快就会发现自己很乐于使用那些新工具,而且变得越来越离不了它。
  27. 新的集合库考虑到了“容纳自己对象”的问题,并将其分割成两个明确的概念:
    • (1) 集合(Collection):一组单独的元素,通常应用了某种规则。在这里,一个List(列表)必须按特定的顺序容纳元素,而一个Set(集)不可包含任何重复的元素。相反,“包”(Bag)的概念未在新的集合库中实现,因为“列表”已提供了类似的功能。
    • (2) 映射(Map):一系列“键-值”对(这已在散列表身上得到了充分的体现)。从表面看,这似乎应该成为一个“键-值”对的“集合”,但假若试图按那种方式实现它,就会发现实现过程相当笨拙。这进一步证明了应该分离成单独的概念。另一方面,可以方便地查看Map的某个部分。只需创建一个集合,然后用它表示那一部分即可。这样一来,Map就可以返回自己键的一个Set、一个包含自己值的List或者包含自己“键-值”对的一个List。
  28. 利用iterator()方法,所有集合都能生成一个“反复器”(Iterator)。反复器其实就象一个“枚举”(Enumeration),是后者的一个替代物,只是:
    • (1) 它采用了一个历史上默认、而且早在OOP中得到广泛采纳的名字(反复器)。
    • (2) 采用了比Enumeration更短的名字:hasNext()代替了hasMoreElement(),而next()代替了nextElement()。
    • (3) 添加了一个名为remove()的新方法,可删除由Iterator生成的上一个元素。所以每次调用next()的时候,只需调用remove()一次。在SimpleCollection.java中,大家可看到创建了一个反复器,并用它在集合里遍历,打印出每个元素。
  29. 用一个集合能做的所有事情(亦可对Set和List做同样的事情,尽管List还提供了一些额外的功能)。Map不是从Collection继承的,所以要单独对待
  30. Set拥有与Collection完全相同的接口,所以和两种不同的List不同,它没有什么额外的功能。相反,Set完全就是一个Collection,只是具有不同的行为(这是实例和多形性最理想的应用:用于表达不同的行为)。在这里,一个Set只允许每个对象存在一个实例(正如大家以后会看到的那样,一个对象的“值”的构成是相当复杂的)。
  31. Set(接口) 添加到Set的每个元素都必须是独一无二的;否则Set就不会添加重复的元素。添加到Set里的对象必须定义equals(),从而建立对象的唯一性。Set拥有与Collection完全相同的接口。一个Set不能保证自己可按任何特定的顺序维持自己的元素
    • HashSet* 用于除非常小的以外的所有Set。对象也必须定义hashCode()
    • ArraySet 由一个数组后推得到的Set。面向非常小的Set设计,特别是那些需要频繁创建和删除的。对于小Set,与HashSet相比,ArraySet创建和反复所需付出的代价都要小得多。但随着Set的增大,它的性能也会大打折扣。不需要HashCode()
    • TreeSet 由一个“红黑树”后推得到的顺序Set(注释⑦)。这样一来,我们就可以从一个Set里提到一个顺序集合
  32. Map(接口) 维持“键-值”对应关系(对),以便通过一个键查找相应的值
  33. HashMap* 基于一个散列表实现(用它代替Hashtable)。针对“键-值”对的插入和检索,这种形式具有最稳定的性能。可通过构建器对这一性能进行调整,以便设置散列表的“能力”和“装载因子”ArrayMap 由一个ArrayList后推得到的Map。对反复的顺序提供了精确的控制。面向非常小的Map设计,特别是那些需要经常创建和删除的。对于非常小的Map,创建和反复所付出的代价要比HashMap低得多。但在Map变大以后,性能也会相应地大幅度降低TreeMap 在一个“红-黑”树的基础上实现。
  34. 可在ArraySet以及HashSet间作出选择,具体取决于Set的大小(如果需要从一个Set中获得一个顺序列表,请用TreeSet;注释⑧)
  35. 选择不同的Map实施方案时,注意Map的大小对于性能的影响是最大的.
  36. Arrays类为所有基本数据类型的数组提供了一个过载的sort()和binarySearch(),它们亦可用于String和Object。
  37. 可用与数组相同的形式排序和搜索一个列表(List)。用于排序和搜索列表的静态方法包含在类Collections中,但它们拥有与Arrays中差不多的签名:sort(List)用于对一个实现了Comparable的对象列表进行排序;binarySearch(List,Object)用于查找列表中的某个对象;sort(List,Comparator)利用一个“比较器”对一个列表进行排序;而binarySearch(List,Object,Comparator)则用于查找那个列表中的一个对象(注释⑨)。
  38. Synchronized关键字是“多线程”机制一个非常重要的部分。
  39. 数组包含了对象的数字化索引。它容纳的是一种已知类型的对象,所以在查找一个对象时,不必对结果进行造型处理。数组可以是多维的,而且能够容纳基本数据类型。但是,一旦把它创建好以后,大小便不能变化了。
  40. Vector(矢量)也包含了对象的数字索引——可将数组和Vector想象成随机访问集合。当我们加入更多的元素时,Vector能够自动改变自身的大小。但Vector只能容纳对象的句柄,所以它不可包含基本数据类型;而且将一个对象句柄从集合中取出来的时候,必须对结果进行造型处理。
  41. Hashtable(散列表)属于Dictionary(字典)的一种类型,是一种将对象(而不是数字)同其他对象关联到一起的方式。散列表也支持对对象的随机访问,事实上,它的整个设计方案都在突出访问的“高速度”。
  42. Stack(堆栈)是一种“后入先出”(LIFO)的队列.

Collection Interfaces - Represent different types of collections, such as sets, lists and maps. These interfaces form the basis of the framework.
General-purpose Implementations - Primary implementations of the collection interfaces.
Legacy Implementations - The collection classes from earlier releases, Vector and Hashtable, have been retrofitted to implement the collection interfaces.
Special-purpose Implementations - Implementations designed for use in special situations. These implementations display nonstandard performance characteristics, usage restrictions, or behavior.
Concurrent Implementations - Implementations designed for highly concurrent use.
Wrapper Implementations - Add functionality, such as synchronization, to other implementations.
Convenience Implementations - High-performance "mini-implementations" of the collection interfaces.
Abstract Implementations - Partial implementations of the collection interfaces to facilitate custom implementations.
Algorithms - Static methods that perform useful functions on collections, such as sorting a list.
Infrastructure - Interfaces that provide essential support for the collection interfaces.
Array Utilities - Utility functions for arrays of primitives and reference objects. Not, strictly speaking, a part of the Collections Framework, this functionality was added to the Java platform at the same time and relies on some of the same infrastructure.

Iterable Interface

 1 import java.util.Iterator;
 2 /**
 3  * Instances of classes that implement this interface can be used with
 4  * the enhanced for loop.
 5  *
 6  * @since 1.5
 7  */
 8 public interface Iterable<T> {
 9 
10     /**
11      * Returns an {@link Iterator} for the elements in this object.
12      *
13      * @return An {@code Iterator} instance.
14      */
15     Iterator<T> iterator();
16 }
View Code

Collection Interface

  1 package java.util;
  2 
  3 
  4 /**
  5  * {@code Collection} is the root of the collection hierarchy. It defines operations on
  6  * data collections and the behavior that they will have in all implementations
  7  * of {@code Collection}s.
  8  *
  9  * All direct or indirect implementations of {@code Collection} should implement at
 10  * least two constructors. One with no parameters which creates an empty
 11  * collection and one with a parameter of type {@code Collection}. This second
 12  * constructor can be used to create a collection of different type as the
 13  * initial collection but with the same elements. Implementations of {@code Collection}
 14  * cannot be forced to implement these two constructors but at least all
 15  * implementations under {@code java.util} do.
 16  *
 17  * Methods that change the content of a collection throw an
 18  * {@code UnsupportedOperationException} if the underlying collection does not
 19  * support that operation, though it's not mandatory to throw such an {@code Exception}
 20  * in cases where the requested operation would not change the collection. In
 21  * these cases it's up to the implementation whether it throws an
 22  * {@code UnsupportedOperationException} or not.
 23  *
 24  * Methods marked with (optional) can throw an
 25  * {@code UnsupportedOperationException} if the underlying collection doesn't
 26  * support that method.
 27  */
 28 public interface Collection<E> extends Iterable<E> {
 29 
 30     /**
 31      * Attempts to add {@code object} to the contents of this
 32      * {@code Collection} (optional).
 33      *
 34      * After this method finishes successfully it is guaranteed that the object
 35      * is contained in the collection.
 36      *
 37      * If the collection was modified it returns {@code true}, {@code false} if
 38      * no changes were made.
 39      *
 40      * An implementation of {@code Collection} may narrow the set of accepted
 41      * objects, but it has to specify this in the documentation. If the object
 42      * to be added does not meet this restriction, then an
 43      * {@code IllegalArgumentException} is thrown.
 44      *
 45      * If a collection does not yet contain an object that is to be added and
 46      * adding the object fails, this method <i>must</i> throw an appropriate
 47      * unchecked Exception. Returning false is not permitted in this case
 48      * because it would violate the postcondition that the element will be part
 49      * of the collection after this method finishes.
 50      *
 51      * @param object
 52      *            the object to add.
 53      * @return {@code true} if this {@code Collection} is
 54      *         modified, {@code false} otherwise.
 55      *
 56      * @throws UnsupportedOperationException
 57      *                if adding to this {@code Collection} is not supported.
 58      * @throws ClassCastException
 59      *                if the class of the object is inappropriate for this
 60      *                collection.
 61      * @throws IllegalArgumentException
 62      *                if the object cannot be added to this {@code Collection}.
 63      * @throws NullPointerException
 64      *                if null elements cannot be added to the {@code Collection}.
 65      */
 66     public boolean add(E object);
 67 
 68     /**
 69      * Attempts to add all of the objects contained in {@code Collection}
 70      * to the contents of this {@code Collection} (optional). If the passed {@code Collection}
 71      * is changed during the process of adding elements to this {@code Collection}, the
 72      * behavior is not defined.
 73      *
 74      * @param collection
 75      *            the {@code Collection} of objects.
 76      * @return {@code true} if this {@code Collection} is modified, {@code false}
 77      *         otherwise.
 78      * @throws UnsupportedOperationException
 79      *                if adding to this {@code Collection} is not supported.
 80      * @throws ClassCastException
 81      *                if the class of an object is inappropriate for this
 82      *                {@code Collection}.
 83      * @throws IllegalArgumentException
 84      *                if an object cannot be added to this {@code Collection}.
 85      * @throws NullPointerException
 86      *                if {@code collection} is {@code null}, or if it
 87      *                contains {@code null} elements and this {@code Collection} does
 88      *                not support such elements.
 89      */
 90     public boolean addAll(Collection<? extends E> collection);
 91 
 92     /**
 93      * Removes all elements from this {@code Collection}, leaving it empty (optional).
 94      *
 95      * @throws UnsupportedOperationException
 96      *                if removing from this {@code Collection} is not supported.
 97      *
 98      * @see #isEmpty
 99      * @see #size
100      */
101     public void clear();
102 
103     /**
104      * Tests whether this {@code Collection} contains the specified object. Returns
105      * {@code true} if and only if at least one element {@code elem} in this
106      * {@code Collection} meets following requirement:
107      * {@code (object==null ? elem==null : object.equals(elem))}.
108      *
109      * @param object
110      *            the object to search for.
111      * @return {@code true} if object is an element of this {@code Collection},
112      *         {@code false} otherwise.
113      * @throws ClassCastException
114      *                if the object to look for isn't of the correct
115      *                type.
116      * @throws NullPointerException
117      *                if the object to look for is {@code null} and this
118      *                {@code Collection} doesn't support {@code null} elements.
119      */
120     public boolean contains(Object object);
121 
122     /**
123      * Tests whether this {@code Collection} contains all objects contained in the
124      * specified {@code Collection}. If an element {@code elem} is contained several
125      * times in the specified {@code Collection}, the method returns {@code true} even
126      * if {@code elem} is contained only once in this {@code Collection}.
127      *
128      * @param collection
129      *            the collection of objects.
130      * @return {@code true} if all objects in the specified {@code Collection} are
131      *         elements of this {@code Collection}, {@code false} otherwise.
132      * @throws ClassCastException
133      *                if one or more elements of {@code collection} isn't of the
134      *                correct type.
135      * @throws NullPointerException
136      *                if {@code collection} contains at least one {@code null}
137      *                element and this {@code Collection} doesn't support {@code null}
138      *                elements.
139      * @throws NullPointerException
140      *                if {@code collection} is {@code null}.
141      */
142     public boolean containsAll(Collection<?> collection);
143 
144     /**
145      * Compares the argument to the receiver, and returns true if they represent
146      * the <em>same</em> object using a class specific comparison.
147      *
148      * @param object
149      *            the object to compare with this object.
150      * @return {@code true} if the object is the same as this object and
151      *         {@code false} if it is different from this object.
152      * @see #hashCode
153      */
154     public boolean equals(Object object);
155 
156     /**
157      * Returns an integer hash code for the receiver. Objects which are equal
158      * return the same value for this method.
159      *
160      * @return the receiver's hash.
161      *
162      * @see #equals
163      */
164     public int hashCode();
165 
166     /**
167      * Returns if this {@code Collection} contains no elements.
168      *
169      * @return {@code true} if this {@code Collection} has no elements, {@code false}
170      *         otherwise.
171      *
172      * @see #size
173      */
174     public boolean isEmpty();
175 
176     /**
177      * Returns an instance of {@link Iterator} that may be used to access the
178      * objects contained by this {@code Collection}. The order in which the elements are
179      * returned by the iterator is not defined. Only if the instance of the
180      * {@code Collection} has a defined order the elements are returned in that order.
181      *
182      * @return an iterator for accessing the {@code Collection} contents.
183      */
184     public Iterator<E> iterator();
185 
186     /**
187      * Removes one instance of the specified object from this {@code Collection} if one
188      * is contained (optional). The element {@code elem} that is removed
189      * complies with {@code (object==null ? elem==null : object.equals(elem)}.
190      *
191      * @param object
192      *            the object to remove.
193      * @return {@code true} if this {@code Collection} is modified, {@code false}
194      *         otherwise.
195      * @throws UnsupportedOperationException
196      *                if removing from this {@code Collection} is not supported.
197      * @throws ClassCastException
198      *                if the object passed is not of the correct type.
199      * @throws NullPointerException
200      *                if {@code object} is {@code null} and this {@code Collection}
201      *                doesn't support {@code null} elements.
202      */
203     public boolean remove(Object object);
204 
205     /**
206      * Removes all occurrences in this {@code Collection} of each object in the
207      * specified {@code Collection} (optional). After this method returns none of the
208      * elements in the passed {@code Collection} can be found in this {@code Collection}
209      * anymore.
210      *
211      * @param collection
212      *            the collection of objects to remove.
213      * @return {@code true} if this {@code Collection} is modified, {@code false}
214      *         otherwise.
215      *
216      * @throws UnsupportedOperationException
217      *                if removing from this {@code Collection} is not supported.
218      * @throws ClassCastException
219      *                if one or more elements of {@code collection}
220      *                isn't of the correct type.
221      * @throws NullPointerException
222      *                if {@code collection} contains at least one
223      *                {@code null} element and this {@code Collection} doesn't support
224      *                {@code null} elements.
225      * @throws NullPointerException
226      *                if {@code collection} is {@code null}.
227      */
228     public boolean removeAll(Collection<?> collection);
229 
230     /**
231      * Removes all objects from this {@code Collection} that are not also found in the
232      * {@code Collection} passed (optional). After this method returns this {@code Collection}
233      * will only contain elements that also can be found in the {@code Collection}
234      * passed to this method.
235      *
236      * @param collection
237      *            the collection of objects to retain.
238      * @return {@code true} if this {@code Collection} is modified, {@code false}
239      *         otherwise.
240      * @throws UnsupportedOperationException
241      *                if removing from this {@code Collection} is not supported.
242      * @throws ClassCastException
243      *                if one or more elements of {@code collection}
244      *                isn't of the correct type.
245      * @throws NullPointerException
246      *                if {@code collection} contains at least one
247      *                {@code null} element and this {@code Collection} doesn't support
248      *                {@code null} elements.
249      * @throws NullPointerException
250      *                if {@code collection} is {@code null}.
251      */
252     public boolean retainAll(Collection<?> collection);
253 
254     /**
255      * Returns a count of how many objects this {@code Collection} contains.
256      *
257      * @return how many objects this {@code Collection} contains, or Integer.MAX_VALUE
258      *         if there are more than Integer.MAX_VALUE elements in this
259      *         {@code Collection}.
260      */
261     public int size();
262 
263     /**
264      * Returns a new array containing all elements contained in this {@code Collection}.
265      *
266      * If the implementation has ordered elements it will return the element
267      * array in the same order as an iterator would return them.
268      *
269      * The array returned does not reflect any changes of the {@code Collection}. A new
270      * array is created even if the underlying data structure is already an
271      * array.
272      *
273      * @return an array of the elements from this {@code Collection}.
274      */
275     public Object[] toArray();
276 
277     /**
278      * Returns an array containing all elements contained in this {@code Collection}. If
279      * the specified array is large enough to hold the elements, the specified
280      * array is used, otherwise an array of the same type is created. If the
281      * specified array is used and is larger than this {@code Collection}, the array
282      * element following the {@code Collection} elements is set to null.
283      *
284      * If the implementation has ordered elements it will return the element
285      * array in the same order as an iterator would return them.
286      *
287      * {@code toArray(new Object[0])} behaves exactly the same way as
288      * {@code toArray()} does.
289      *
290      * @param array
291      *            the array.
292      * @return an array of the elements from this {@code Collection}.
293      *
294      * @throws ArrayStoreException
295      *                if the type of an element in this {@code Collection} cannot be
296      *                stored in the type of the specified array.
297      */
298     public <T> T[] toArray(T[] array);
299 }
View Code

List Interface

  1 package java.util;
  2 
  3 
  4 /**
  5  * A {@code List} is a collection which maintains an ordering for its elements. Every
  6  * element in the {@code List} has an index. Each element can thus be accessed by its
  7  * index, with the first index being zero. Normally, {@code List}s allow duplicate
  8  * elements, as compared to Sets, where elements have to be unique.
  9  */
 10 public interface List<E> extends Collection<E> {
 11     /**
 12      * Inserts the specified object into this {@code List} at the specified location.
 13      * The object is inserted before the current element at the specified
 14      * location. If the location is equal to the size of this {@code List}, the object
 15      * is added at the end. If the location is smaller than the size of this
 16      * {@code List}, then all elements beyond the specified location are moved by one
 17      * position towards the end of the {@code List}.
 18      *
 19      * @param location
 20      *            the index at which to insert.
 21      * @param object
 22      *            the object to add.
 23      * @throws UnsupportedOperationException
 24      *                if adding to this {@code List} is not supported.
 25      * @throws ClassCastException
 26      *                if the class of the object is inappropriate for this
 27      *                {@code List}.
 28      * @throws IllegalArgumentException
 29      *                if the object cannot be added to this {@code List}.
 30      * @throws IndexOutOfBoundsException
 31      *                if {@code location < 0 || location > size()}
 32      */
 33     public void add(int location, E object);
 34 
 35     /**
 36      * Adds the specified object at the end of this {@code List}.
 37      *
 38      * @param object
 39      *            the object to add.
 40      * @return always true.
 41      * @throws UnsupportedOperationException
 42      *                if adding to this {@code List} is not supported.
 43      * @throws ClassCastException
 44      *                if the class of the object is inappropriate for this
 45      *                {@code List}.
 46      * @throws IllegalArgumentException
 47      *                if the object cannot be added to this {@code List}.
 48      */
 49     public boolean add(E object);
 50 
 51     /**
 52      * Inserts the objects in the specified collection at the specified location
 53      * in this {@code List}. The objects are added in the order they are returned from
 54      * the collection's iterator.
 55      *
 56      * @param location
 57      *            the index at which to insert.
 58      * @param collection
 59      *            the collection of objects to be inserted.
 60      * @return true if this {@code List} has been modified through the insertion, false
 61      *         otherwise (i.e. if the passed collection was empty).
 62      * @throws UnsupportedOperationException
 63      *                if adding to this {@code List} is not supported.
 64      * @throws ClassCastException
 65      *                if the class of an object is inappropriate for this
 66      *                {@code List}.
 67      * @throws IllegalArgumentException
 68      *                if an object cannot be added to this {@code List}.
 69      * @throws IndexOutOfBoundsException
 70      *                if {@code location < 0 || > size()}
 71      */
 72     public boolean addAll(int location, Collection<? extends E> collection);
 73 
 74     /**
 75      * Adds the objects in the specified collection to the end of this {@code List}. The
 76      * objects are added in the order in which they are returned from the
 77      * collection's iterator.
 78      *
 79      * @param collection
 80      *            the collection of objects.
 81      * @return {@code true} if this {@code List} is modified, {@code false} otherwise
 82      *         (i.e. if the passed collection was empty).
 83      * @throws UnsupportedOperationException
 84      *                if adding to this {@code List} is not supported.
 85      * @throws ClassCastException
 86      *                if the class of an object is inappropriate for this
 87      *                {@code List}.
 88      * @throws IllegalArgumentException
 89      *                if an object cannot be added to this {@code List}.
 90      */
 91     public boolean addAll(Collection<? extends E> collection);
 92 
 93     /**
 94      * Removes all elements from this {@code List}, leaving it empty.
 95      *
 96      * @throws UnsupportedOperationException
 97      *                if removing from this {@code List} is not supported.
 98      * @see #isEmpty
 99      * @see #size
100      */
101     public void clear();
102 
103     /**
104      * Tests whether this {@code List} contains the specified object.
105      *
106      * @param object
107      *            the object to search for.
108      * @return {@code true} if object is an element of this {@code List}, {@code false}
109      *         otherwise
110      */
111     public boolean contains(Object object);
112 
113     /**
114      * Tests whether this {@code List} contains all objects contained in the
115      * specified collection.
116      *
117      * @param collection
118      *            the collection of objects
119      * @return {@code true} if all objects in the specified collection are
120      *         elements of this {@code List}, {@code false} otherwise.
121      */
122     public boolean containsAll(Collection<?> collection);
123 
124     /**
125      * Compares the given object with the {@code List}, and returns true if they
126      * represent the <em>same</em> object using a class specific comparison. For
127      * {@code List}s, this means that they contain the same elements in exactly the same
128      * order.
129      *
130      * @param object
131      *            the object to compare with this object.
132      * @return boolean {@code true} if the object is the same as this object,
133      *         and {@code false} if it is different from this object.
134      * @see #hashCode
135      */
136     public boolean equals(Object object);
137 
138     /**
139      * Returns the element at the specified location in this {@code List}.
140      *
141      * @param location
142      *            the index of the element to return.
143      * @return the element at the specified location.
144      * @throws IndexOutOfBoundsException
145      *                if {@code location < 0 || >= size()}
146      */
147     public E get(int location);
148 
149     /**
150      * Returns the hash code for this {@code List}. It is calculated by taking each
151      * element' hashcode and its position in the {@code List} into account.
152      *
153      * @return the hash code of the {@code List}.
154      */
155     public int hashCode();
156 
157     /**
158      * Searches this {@code List} for the specified object and returns the index of the
159      * first occurrence.
160      *
161      * @param object
162      *            the object to search for.
163      * @return the index of the first occurrence of the object or -1 if the
164      *         object was not found.
165      */
166     public int indexOf(Object object);
167 
168     /**
169      * Returns whether this {@code List} contains no elements.
170      *
171      * @return {@code true} if this {@code List} has no elements, {@code false}
172      *         otherwise.
173      * @see #size
174      */
175     public boolean isEmpty();
176 
177     /**
178      * Returns an iterator on the elements of this {@code List}. The elements are
179      * iterated in the same order as they occur in the {@code List}.
180      *
181      * @return an iterator on the elements of this {@code List}.
182      * @see Iterator
183      */
184     public Iterator<E> iterator();
185 
186     /**
187      * Searches this {@code List} for the specified object and returns the index of the
188      * last occurrence.
189      *
190      * @param object
191      *            the object to search for.
192      * @return the index of the last occurrence of the object, or -1 if the
193      *         object was not found.
194      */
195     public int lastIndexOf(Object object);
196 
197     /**
198      * Returns a {@code List} iterator on the elements of this {@code List}. The elements are
199      * iterated in the same order that they occur in the {@code List}.
200      *
201      * @return a {@code List} iterator on the elements of this {@code List}
202      *
203      * @see ListIterator
204      */
205     public ListIterator<E> listIterator();
206 
207     /**
208      * Returns a list iterator on the elements of this {@code List}. The elements are
209      * iterated in the same order as they occur in the {@code List}. The iteration
210      * starts at the specified location.
211      *
212      * @param location
213      *            the index at which to start the iteration.
214      * @return a list iterator on the elements of this {@code List}.
215      * @throws IndexOutOfBoundsException
216      *                if {@code location < 0 || location > size()}
217      * @see ListIterator
218      */
219     public ListIterator<E> listIterator(int location);
220 
221     /**
222      * Removes the object at the specified location from this {@code List}.
223      *
224      * @param location
225      *            the index of the object to remove.
226      * @return the removed object.
227      * @throws UnsupportedOperationException
228      *                if removing from this {@code List} is not supported.
229      * @throws IndexOutOfBoundsException
230      *                if {@code location < 0 || >= size()}
231      */
232     public E remove(int location);
233 
234     /**
235      * Removes the first occurrence of the specified object from this {@code List}.
236      *
237      * @param object
238      *            the object to remove.
239      * @return true if this {@code List} was modified by this operation, false
240      *         otherwise.
241      * @throws UnsupportedOperationException
242      *                if removing from this {@code List} is not supported.
243      */
244     public boolean remove(Object object);
245 
246     /**
247      * Removes all occurrences in this {@code List} of each object in the specified
248      * collection.
249      *
250      * @param collection
251      *            the collection of objects to remove.
252      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
253      * @throws UnsupportedOperationException
254      *                if removing from this {@code List} is not supported.
255      */
256     public boolean removeAll(Collection<?> collection);
257 
258     /**
259      * Removes all objects from this {@code List} that are not contained in the
260      * specified collection.
261      *
262      * @param collection
263      *            the collection of objects to retain.
264      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
265      * @throws UnsupportedOperationException
266      *                if removing from this {@code List} is not supported.
267      */
268     public boolean retainAll(Collection<?> collection);
269 
270     /**
271      * Replaces the element at the specified location in this {@code List} with the
272      * specified object. This operation does not change the size of the {@code List}.
273      *
274      * @param location
275      *            the index at which to put the specified object.
276      * @param object
277      *            the object to insert.
278      * @return the previous element at the index.
279      * @throws UnsupportedOperationException
280      *                if replacing elements in this {@code List} is not supported.
281      * @throws ClassCastException
282      *                if the class of an object is inappropriate for this
283      *                {@code List}.
284      * @throws IllegalArgumentException
285      *                if an object cannot be added to this {@code List}.
286      * @throws IndexOutOfBoundsException
287      *                if {@code location < 0 || >= size()}
288      */
289     public E set(int location, E object);
290 
291     /**
292      * Returns the number of elements in this {@code List}.
293      *
294      * @return the number of elements in this {@code List}.
295      */
296     public int size();
297 
298     /**
299      * Returns a {@code List} of the specified portion of this {@code List} from the given start
300      * index to the end index minus one. The returned {@code List} is backed by this
301      * {@code List} so changes to it are reflected by the other.
302      *
303      * @param start
304      *            the index at which to start the sublist.
305      * @param end
306      *            the index one past the end of the sublist.
307      * @return a list of a portion of this {@code List}.
308      * @throws IndexOutOfBoundsException
309      *                if {@code start < 0, start > end} or {@code end >
310      *                size()}
311      */
312     public List<E> subList(int start, int end);
313 
314     /**
315      * Returns an array containing all elements contained in this {@code List}.
316      *
317      * @return an array of the elements from this {@code List}.
318      */
319     public Object[] toArray();
320 
321     /**
322      * Returns an array containing all elements contained in this {@code List}. If the
323      * specified array is large enough to hold the elements, the specified array
324      * is used, otherwise an array of the same type is created. If the specified
325      * array is used and is larger than this {@code List}, the array element following
326      * the collection elements is set to null.
327      *
328      * @param array
329      *            the array.
330      * @return an array of the elements from this {@code List}.
331      * @throws ArrayStoreException
332      *                if the type of an element in this {@code List} cannot be stored
333      *                in the type of the specified array.
334      */
335     public <T> T[] toArray(T[] array);
336 }
View Code

Set Interface

  1 package java.util;
  2 
  3 
  4 /**
  5  * A {@code Set} is a data structure which does not allow duplicate elements.
  6  *
  7  * @since 1.2
  8  */
  9 public interface Set<E> extends Collection<E> {
 10 
 11     /**
 12      * Adds the specified object to this set. The set is not modified if it
 13      * already contains the object.
 14      *
 15      * @param object
 16      *            the object to add.
 17      * @return {@code true} if this set is modified, {@code false} otherwise.
 18      * @throws UnsupportedOperationException
 19      *             when adding to this set is not supported.
 20      * @throws ClassCastException
 21      *             when the class of the object is inappropriate for this set.
 22      * @throws IllegalArgumentException
 23      *             when the object cannot be added to this set.
 24      */
 25     public boolean add(E object);
 26 
 27     /**
 28      * Adds the objects in the specified collection which do not exist yet in
 29      * this set.
 30      *
 31      * @param collection
 32      *            the collection of objects.
 33      * @return {@code true} if this set is modified, {@code false} otherwise.
 34      * @throws UnsupportedOperationException
 35      *             when adding to this set is not supported.
 36      * @throws ClassCastException
 37      *             when the class of an object is inappropriate for this set.
 38      * @throws IllegalArgumentException
 39      *             when an object cannot be added to this set.
 40      */
 41     public boolean addAll(Collection<? extends E> collection);
 42 
 43     /**
 44      * Removes all elements from this set, leaving it empty.
 45      *
 46      * @throws UnsupportedOperationException
 47      *             when removing from this set is not supported.
 48      * @see #isEmpty
 49      * @see #size
 50      */
 51     public void clear();
 52 
 53     /**
 54      * Searches this set for the specified object.
 55      *
 56      * @param object
 57      *            the object to search for.
 58      * @return {@code true} if object is an element of this set, {@code false}
 59      *         otherwise.
 60      */
 61     public boolean contains(Object object);
 62 
 63     /**
 64      * Searches this set for all objects in the specified collection.
 65      *
 66      * @param collection
 67      *            the collection of objects.
 68      * @return {@code true} if all objects in the specified collection are
 69      *         elements of this set, {@code false} otherwise.
 70      */
 71     public boolean containsAll(Collection<?> collection);
 72 
 73     /**
 74      * Compares the specified object to this set, and returns true if they
 75      * represent the <em>same</em> object using a class specific comparison.
 76      * Equality for a set means that both sets have the same size and the same
 77      * elements.
 78      *
 79      * @param object
 80      *            the object to compare with this object.
 81      * @return boolean {@code true} if the object is the same as this object,
 82      *         and {@code false} if it is different from this object.
 83      * @see #hashCode
 84      */
 85     public boolean equals(Object object);
 86 
 87     /**
 88      * Returns the hash code for this set. Two set which are equal must return
 89      * the same value.
 90      *
 91      * @return the hash code of this set.
 92      *
 93      * @see #equals
 94      */
 95     public int hashCode();
 96 
 97     /**
 98      * Returns true if this set has no elements.
 99      *
100      * @return {@code true} if this set has no elements, {@code false}
101      *         otherwise.
102      * @see #size
103      */
104     public boolean isEmpty();
105 
106     /**
107      * Returns an iterator on the elements of this set. The elements are
108      * unordered.
109      *
110      * @return an iterator on the elements of this set.
111      * @see Iterator
112      */
113     public Iterator<E> iterator();
114 
115     /**
116      * Removes the specified object from this set.
117      *
118      * @param object
119      *            the object to remove.
120      * @return {@code true} if this set was modified, {@code false} otherwise.
121      * @throws UnsupportedOperationException
122      *             when removing from this set is not supported.
123      */
124     public boolean remove(Object object);
125 
126     /**
127      * Removes all objects in the specified collection from this set.
128      *
129      * @param collection
130      *            the collection of objects to remove.
131      * @return {@code true} if this set was modified, {@code false} otherwise.
132      * @throws UnsupportedOperationException
133      *             when removing from this set is not supported.
134      */
135     public boolean removeAll(Collection<?> collection);
136 
137     /**
138      * Removes all objects from this set that are not contained in the specified
139      * collection.
140      *
141      * @param collection
142      *            the collection of objects to retain.
143      * @return {@code true} if this set was modified, {@code false} otherwise.
144      * @throws UnsupportedOperationException
145      *             when removing from this set is not supported.
146      */
147     public boolean retainAll(Collection<?> collection);
148 
149     /**
150      * Returns the number of elements in this set.
151      *
152      * @return the number of elements in this set.
153      */
154     public int size();
155 
156     /**
157      * Returns an array containing all elements contained in this set.
158      *
159      * @return an array of the elements from this set.
160      */
161     public Object[] toArray();
162 
163     /**
164      * Returns an array containing all elements contained in this set. If the
165      * specified array is large enough to hold the elements, the specified array
166      * is used, otherwise an array of the same type is created. If the specified
167      * array is used and is larger than this set, the array element following
168      * the collection elements is set to null.
169      *
170      * @param array
171      *            the array.
172      * @return an array of the elements from this set.
173      * @throws ArrayStoreException
174      *             when the type of an element in this set cannot be stored in
175      *             the type of the specified array.
176      * @see Collection#toArray(Object[])
177      */
178     public <T> T[] toArray(T[] array);
179 }
View Code

Queue Interface

 1 public interface Queue<E> extends Collection<E> {
 2     /**
 3      * Inserts the specified element into this queue if it is possible to do so
 4      * immediately without violating capacity restrictions, returning
 5      * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
 6      * if no space is currently available.
 7      *
 8      * @param e the element to add
 9      * @return <tt>true</tt> (as specified by {@link Collection#add})
10      * @throws IllegalStateException if the element cannot be added at this
11      *         time due to capacity restrictions
12      * @throws ClassCastException if the class of the specified element
13      *         prevents it from being added to this queue
14      * @throws NullPointerException if the specified element is null and
15      *         this queue does not permit null elements
16      * @throws IllegalArgumentException if some property of this element
17      *         prevents it from being added to this queue
18      */
19     boolean add(E e);
20 
21     /**
22      * Inserts the specified element into this queue if it is possible to do
23      * so immediately without violating capacity restrictions.
24      * When using a capacity-restricted queue, this method is generally
25      * preferable to {@link #add}, which can fail to insert an element only
26      * by throwing an exception.
27      *
28      * @param e the element to add
29      * @return <tt>true</tt> if the element was added to this queue, else
30      *         <tt>false</tt>
31      * @throws ClassCastException if the class of the specified element
32      *         prevents it from being added to this queue
33      * @throws NullPointerException if the specified element is null and
34      *         this queue does not permit null elements
35      * @throws IllegalArgumentException if some property of this element
36      *         prevents it from being added to this queue
37      */
38     boolean offer(E e);
39 
40     /**
41      * Retrieves and removes the head of this queue.  This method differs
42      * from {@link #poll poll} only in that it throws an exception if this
43      * queue is empty.
44      *
45      * @return the head of this queue
46      * @throws NoSuchElementException if this queue is empty
47      */
48     E remove();
49 
50     /**
51      * Retrieves and removes the head of this queue,
52      * or returns <tt>null</tt> if this queue is empty.
53      *
54      * @return the head of this queue, or <tt>null</tt> if this queue is empty
55      */
56     E poll();
57 
58     /**
59      * Retrieves, but does not remove, the head of this queue.  This method
60      * differs from {@link #peek peek} only in that it throws an exception
61      * if this queue is empty.
62      *
63      * @return the head of this queue
64      * @throws NoSuchElementException if this queue is empty
65      */
66     E element();
67 
68     /**
69      * Retrieves, but does not remove, the head of this queue,
70      * or returns <tt>null</tt> if this queue is empty.
71      *
72      * @return the head of this queue, or <tt>null</tt> if this queue is empty
73      */
74     E peek();
75 }
View Code

SortedSet Interface

 1 package java.util;
 2 
 3 public interface SortedSet<E> extends Set<E> { 
 4     public Comparator<? super E> comparator();
 5     public E first();
 6     public SortedSet<E> headSet(E end);  
 7     public E last();
 8     public SortedSet<E> subSet(E start, E end);
 9     public SortedSet<E> tailSet(E start);
10 }
View Code

NavigableSet Interface

 1 public interface NavigableSet<E> extends SortedSet<E> {
 2     E lower(E e);
 3     E floor(E e);
 4     E ceiling(E e);
 5     E higher(E e);
 6     E pollFirst();
 7     E pollLast();
 8     Iterator<E> iterator();
 9     NavigableSet<E> descendingSet();
10     Iterator<E> descendingIterator();
11     NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
12                            E toElement,   boolean toInclusive);
13     NavigableSet<E> headSet(E toElement, boolean inclusive);
14     NavigableSet<E> tailSet(E fromElement, boolean inclusive);
15     SortedSet<E> subSet(E fromElement, E toElement);
16     SortedSet<E> headSet(E toElement);
17     SortedSet<E> tailSet(E fromElement);
18 }
View Code

AbstractCollection Abstract Class

  1 public abstract class AbstractCollection<E> implements Collection<E> {
  2 
  3     /**
  4      * Constructs a new instance of this AbstractCollection.
  5      */
  6     protected AbstractCollection() {
  7     }
  8 
  9     public boolean add(E object) {
 10         throw new UnsupportedOperationException();
 11     }
 12 
 13     /**
 14      * Attempts to add all of the objects contained in {@code collection}
 15      * to the contents of this {@code Collection} (optional). This implementation
 16      * iterates over the given {@code Collection} and calls {@code add} for each
 17      * element. If any of these calls return {@code true}, then {@code true} is
 18      * returned as result of this method call, {@code false} otherwise. If this
 19      * {@code Collection} does not support adding elements, an {@code
 20      * UnsupportedOperationException} is thrown.
 21      * <p>
 22      * If the passed {@code Collection} is changed during the process of adding elements
 23      * to this {@code Collection}, the behavior depends on the behavior of the passed
 24      * {@code Collection}.
 25      *
 26      * @param collection
 27      *            the collection of objects.
 28      * @return {@code true} if this {@code Collection} is modified, {@code false}
 29      *         otherwise.
 30      * @throws UnsupportedOperationException
 31      *                if adding to this {@code Collection} is not supported.
 32      * @throws ClassCastException
 33      *                if the class of an object is inappropriate for this
 34      *                {@code Collection}.
 35      * @throws IllegalArgumentException
 36      *                if an object cannot be added to this {@code Collection}.
 37      * @throws NullPointerException
 38      *                if {@code collection} is {@code null}, or if it contains
 39      *                {@code null} elements and this {@code Collection} does not support
 40      *                such elements.
 41      */
 42     public boolean addAll(Collection<? extends E> collection) {
 43         boolean result = false;
 44         Iterator<? extends E> it = collection.iterator();
 45         while (it.hasNext()) {
 46             if (add(it.next())) {
 47                 result = true;
 48             }
 49         }
 50         return result;
 51     }
 52 
 53     /**
 54      * Removes all elements from this {@code Collection}, leaving it empty (optional).
 55      * This implementation iterates over this {@code Collection} and calls the {@code
 56      * remove} method on each element. If the iterator does not support removal
 57      * of elements, an {@code UnsupportedOperationException} is thrown.
 58      * <p>
 59      * Concrete implementations usually can clear a {@code Collection} more efficiently
 60      * and should therefore overwrite this method.
 61      *
 62      * @throws UnsupportedOperationException
 63      *                it the iterator does not support removing elements from
 64      *                this {@code Collection}
 65      * @see #iterator
 66      * @see #isEmpty
 67      * @see #size
 68      */
 69     public void clear() {
 70         Iterator<E> it = iterator();
 71         while (it.hasNext()) {
 72             it.next();
 73             it.remove();
 74         }
 75     }
 76 
 77     /**
 78      * Tests whether this {@code Collection} contains the specified object. This
 79      * implementation iterates over this {@code Collection} and tests, whether any
 80      * element is equal to the given object. If {@code object != null} then
 81      * {@code object.equals(e)} is called for each element {@code e} returned by
 82      * the iterator until the element is found. If {@code object == null} then
 83      * each element {@code e} returned by the iterator is compared with the test
 84      * {@code e == null}.
 85      *
 86      * @param object
 87      *            the object to search for.
 88      * @return {@code true} if object is an element of this {@code Collection}, {@code
 89      *         false} otherwise.
 90      * @throws ClassCastException
 91      *                if the object to look for isn't of the correct type.
 92      * @throws NullPointerException
 93      *                if the object to look for is {@code null} and this
 94      *                {@code Collection} doesn't support {@code null} elements.
 95      */
 96     public boolean contains(Object object) {
 97         Iterator<E> it = iterator();
 98         if (object != null) {
 99             while (it.hasNext()) {
100                 if (object.equals(it.next())) {
101                     return true;
102                 }
103             }
104         } else {
105             while (it.hasNext()) {
106                 if (it.next() == null) {
107                     return true;
108                 }
109             }
110         }
111         return false;
112     }
113 
114     /**
115      * Tests whether this {@code Collection} contains all objects contained in the
116      * specified {@code Collection}. This implementation iterates over the specified
117      * {@code Collection}. If one element returned by the iterator is not contained in
118      * this {@code Collection}, then {@code false} is returned; {@code true} otherwise.
119      *
120      * @param collection
121      *            the collection of objects.
122      * @return {@code true} if all objects in the specified {@code Collection} are
123      *         elements of this {@code Collection}, {@code false} otherwise.
124      * @throws ClassCastException
125      *                if one or more elements of {@code collection} isn't of the
126      *                correct type.
127      * @throws NullPointerException
128      *                if {@code collection} contains at least one {@code null}
129      *                element and this {@code Collection} doesn't support {@code null}
130      *                elements.
131      * @throws NullPointerException
132      *                if {@code collection} is {@code null}.
133      */
134     public boolean containsAll(Collection<?> collection) {
135         Iterator<?> it = collection.iterator();
136         while (it.hasNext()) {
137             if (!contains(it.next())) {
138                 return false;
139             }
140         }
141         return true;
142     }
143 
144     /**
145      * Returns if this {@code Collection} contains no elements. This implementation
146      * tests, whether {@code size} returns 0.
147      *
148      * @return {@code true} if this {@code Collection} has no elements, {@code false}
149      *         otherwise.
150      *
151      * @see #size
152      */
153     public boolean isEmpty() {
154         return size() == 0;
155     }
156 
157     /**
158      * Returns an instance of {@link Iterator} that may be used to access the
159      * objects contained by this {@code Collection}. The order in which the elements are
160      * returned by the {@link Iterator} is not defined unless the instance of the
161      * {@code Collection} has a defined order.  In that case, the elements are returned in that order.
162      * <p>
163      * In this class this method is declared abstract and has to be implemented
164      * by concrete {@code Collection} implementations.
165      *
166      * @return an iterator for accessing the {@code Collection} contents.
167      */
168     public abstract Iterator<E> iterator();
169 
170     /**
171      * Removes one instance of the specified object from this {@code Collection} if one
172      * is contained (optional). This implementation iterates over this
173      * {@code Collection} and tests for each element {@code e} returned by the iterator,
174      * whether {@code e} is equal to the given object. If {@code object != null}
175      * then this test is performed using {@code object.equals(e)}, otherwise
176      * using {@code object == null}. If an element equal to the given object is
177      * found, then the {@code remove} method is called on the iterator and
178      * {@code true} is returned, {@code false} otherwise. If the iterator does
179      * not support removing elements, an {@code UnsupportedOperationException}
180      * is thrown.
181      *
182      * @param object
183      *            the object to remove.
184      * @return {@code true} if this {@code Collection} is modified, {@code false}
185      *         otherwise.
186      * @throws UnsupportedOperationException
187      *                if removing from this {@code Collection} is not supported.
188      * @throws ClassCastException
189      *                if the object passed is not of the correct type.
190      * @throws NullPointerException
191      *                if {@code object} is {@code null} and this {@code Collection}
192      *                doesn't support {@code null} elements.
193      */
194     public boolean remove(Object object) {
195         Iterator<?> it = iterator();
196         if (object != null) {
197             while (it.hasNext()) {
198                 if (object.equals(it.next())) {
199                     it.remove();
200                     return true;
201                 }
202             }
203         } else {
204             while (it.hasNext()) {
205                 if (it.next() == null) {
206                     it.remove();
207                     return true;
208                 }
209             }
210         }
211         return false;
212     }
213 
214     /**
215      * Removes all occurrences in this {@code Collection} of each object in the
216      * specified {@code Collection} (optional). After this method returns none of the
217      * elements in the passed {@code Collection} can be found in this {@code Collection}
218      * anymore.
219      * <p>
220      * This implementation iterates over this {@code Collection} and tests for each
221      * element {@code e} returned by the iterator, whether it is contained in
222      * the specified {@code Collection}. If this test is positive, then the {@code
223      * remove} method is called on the iterator. If the iterator does not
224      * support removing elements, an {@code UnsupportedOperationException} is
225      * thrown.
226      *
227      * @param collection
228      *            the collection of objects to remove.
229      * @return {@code true} if this {@code Collection} is modified, {@code false}
230      *         otherwise.
231      * @throws UnsupportedOperationException
232      *                if removing from this {@code Collection} is not supported.
233      * @throws ClassCastException
234      *                if one or more elements of {@code collection} isn't of the
235      *                correct type.
236      * @throws NullPointerException
237      *                if {@code collection} contains at least one {@code null}
238      *                element and this {@code Collection} doesn't support {@code null}
239      *                elements.
240      * @throws NullPointerException
241      *                if {@code collection} is {@code null}.
242      */
243     public boolean removeAll(Collection<?> collection) {
244         boolean result = false;
245         Iterator<?> it = iterator();
246         while (it.hasNext()) {
247             if (collection.contains(it.next())) {
248                 it.remove();
249                 result = true;
250             }
251         }
252         return result;
253     }
254 
255     /**
256      * Removes all objects from this {@code Collection} that are not also found in the
257      * {@code Collection} passed (optional). After this method returns this {@code Collection}
258      * will only contain elements that also can be found in the {@code Collection}
259      * passed to this method.
260      * <p>
261      * This implementation iterates over this {@code Collection} and tests for each
262      * element {@code e} returned by the iterator, whether it is contained in
263      * the specified {@code Collection}. If this test is negative, then the {@code
264      * remove} method is called on the iterator. If the iterator does not
265      * support removing elements, an {@code UnsupportedOperationException} is
266      * thrown.
267      *
268      * @param collection
269      *            the collection of objects to retain.
270      * @return {@code true} if this {@code Collection} is modified, {@code false}
271      *         otherwise.
272      * @throws UnsupportedOperationException
273      *                if removing from this {@code Collection} is not supported.
274      * @throws ClassCastException
275      *                if one or more elements of {@code collection}
276      *                isn't of the correct type.
277      * @throws NullPointerException
278      *                if {@code collection} contains at least one
279      *                {@code null} element and this {@code Collection} doesn't support
280      *                {@code null} elements.
281      * @throws NullPointerException
282      *                if {@code collection} is {@code null}.
283      */
284     public boolean retainAll(Collection<?> collection) {
285         boolean result = false;
286         Iterator<?> it = iterator();
287         while (it.hasNext()) {
288             if (!collection.contains(it.next())) {
289                 it.remove();
290                 result = true;
291             }
292         }
293         return result;
294     }
295 
296     /**
297      * Returns a count of how many objects this {@code Collection} contains.
298      * <p>
299      * In this class this method is declared abstract and has to be implemented
300      * by concrete {@code Collection} implementations.
301      *
302      * @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE}
303      *         if there are more than {@code Integer.MAX_VALUE} elements in this
304      *         {@code Collection}.
305      */
306     public abstract int size();
307 
308     public Object[] toArray() {
309         int size = size(), index = 0;
310         Iterator<?> it = iterator();
311         Object[] array = new Object[size];
312         while (index < size) {
313             array[index++] = it.next();
314         }
315         return array;
316     }
317 
318     @SuppressWarnings("unchecked")
319     public <T> T[] toArray(T[] contents) {
320         int size = size(), index = 0;
321         if (size > contents.length) {
322             Class<?> ct = contents.getClass().getComponentType();
323             contents = (T[]) Array.newInstance(ct, size);
324         }
325         for (E entry : this) {
326             contents[index++] = (T) entry;
327         }
328         if (index < contents.length) {
329             contents[index] = null;
330         }
331         return contents;
332     }
333 
334     /**
335      * Returns the string representation of this {@code Collection}. The presentation
336      * has a specific format. It is enclosed by square brackets ("[]"). Elements
337      * are separated by ', ' (comma and space).
338      *
339      * @return the string representation of this {@code Collection}.
340      */
341     @Override
342     public String toString() {
343         if (isEmpty()) {
344             return "[]";
345         }
346 
347         StringBuilder buffer = new StringBuilder(size() * 16);
348         buffer.append('[');
349         Iterator<?> it = iterator();
350         while (it.hasNext()) {
351             Object next = it.next();
352             if (next != this) {
353                 buffer.append(next);
354             } else {
355                 buffer.append("(this Collection)");
356             }
357             if (it.hasNext()) {
358                 buffer.append(", ");
359             }
360         }
361         buffer.append(']');
362         return buffer.toString();
363     }
364 }
View Code

 AbstractSet AbstractClass

 1 public abstract class AbstractSet<E> extends AbstractCollection<E> implements
 2         Set<E> {
 3 
 4     /**
 5      * Constructs a new instance of this AbstractSet.
 6      */
 7     protected AbstractSet() {
 8     }
 9 
10     /**
11      * Compares the specified object to this Set and returns true if they are
12      * equal. The object must be an instance of Set and contain the same
13      * objects.
14      *
15      * @param object
16      *            the object to compare with this set.
17      * @return {@code true} if the specified object is equal to this set,
18      *         {@code false} otherwise
19      * @see #hashCode
20      */
21     @Override
22     public boolean equals(Object object) {
23         if (this == object) {
24             return true;
25         }
26         if (object instanceof Set) {
27             Set<?> s = (Set<?>) object;
28 
29             try {
30                 return size() == s.size() && containsAll(s);
31             } catch (NullPointerException ignored) {
32                 return false;
33             } catch (ClassCastException ignored) {
34                 return false;
35             }
36         }
37         return false;
38     }
39 
40     /**
41      * Returns the hash code for this set. Two set which are equal must return
42      * the same value. This implementation calculates the hash code by adding
43      * each element's hash code.
44      *
45      * @return the hash code of this set.
46      * @see #equals
47      */
48     @Override
49     public int hashCode() {
50         int result = 0;
51         Iterator<?> it = iterator();
52         while (it.hasNext()) {
53             Object next = it.next();
54             result += next == null ? 0 : next.hashCode();
55         }
56         return result;
57     }
58 
59     /**
60      * Removes all occurrences in this collection which are contained in the
61      * specified collection.
62      *
63      * @param collection
64      *            the collection of objects to remove.
65      * @return {@code true} if this collection was modified, {@code false}
66      *         otherwise.
67      * @throws UnsupportedOperationException
68      *                if removing from this collection is not supported.
69      */
70     @Override
71     public boolean removeAll(Collection<?> collection) {
72         boolean result = false;
73         if (size() <= collection.size()) {
74             Iterator<?> it = iterator();
75             while (it.hasNext()) {
76                 if (collection.contains(it.next())) {
77                     it.remove();
78                     result = true;
79                 }
80             }
81         } else {
82             Iterator<?> it = collection.iterator();
83             while (it.hasNext()) {
84                 result = remove(it.next()) || result;
85             }
86         }
87         return result;
88     }
89 }
View Code

HashSet 

  1 package java.util;
  2 
  3 import java.io.IOException;
  4 import java.io.ObjectInputStream;
  5 import java.io.ObjectOutputStream;
  6 import java.io.Serializable;
  7 
  8 
  9 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable,
 10         Serializable {
 11 
 12     private static final long serialVersionUID = -5024744406713321676L;
 13 
 14     transient HashMap<E, HashSet<E>> backingMap;
 15 
 16     /**
 17      * Constructs a new empty instance of {@code HashSet}.
 18      */
 19     public HashSet() {
 20         this(new HashMap<E, HashSet<E>>());
 21     }
 22 
 23     /**
 24      * Constructs a new instance of {@code HashSet} with the specified capacity.
 25      *
 26      * @param capacity
 27      *            the initial capacity of this {@code HashSet}.
 28      */
 29     public HashSet(int capacity) {
 30         this(new HashMap<E, HashSet<E>>(capacity));
 31     }
 32 
 33     /**
 34      * Constructs a new instance of {@code HashSet} with the specified capacity
 35      * and load factor.
 36      *
 37      * @param capacity
 38      *            the initial capacity.
 39      * @param loadFactor
 40      *            the initial load factor.
 41      */
 42     public HashSet(int capacity, float loadFactor) {
 43         this(new HashMap<E, HashSet<E>>(capacity, loadFactor));
 44     }
 45 
 46     /**
 47      * Constructs a new instance of {@code HashSet} containing the unique
 48      * elements in the specified collection.
 49      *
 50      * @param collection
 51      *            the collection of elements to add.
 52      */
 53     public HashSet(Collection<? extends E> collection) {
 54         this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection
 55                 .size() * 2));
 56         for (E e : collection) {
 57             add(e);
 58         }
 59     }
 60 
 61     HashSet(HashMap<E, HashSet<E>> backingMap) {
 62         this.backingMap = backingMap;
 63     }
 64 
 65     /**
 66      * Adds the specified object to this {@code HashSet} if not already present.
 67      *
 68      * @param object
 69      *            the object to add.
 70      * @return {@code true} when this {@code HashSet} did not already contain
 71      *         the object, {@code false} otherwise
 72      */
 73     @Override
 74     public boolean add(E object) {
 75         return backingMap.put(object, this) == null;
 76     }
 77 
 78     /**
 79      * Removes all elements from this {@code HashSet}, leaving it empty.
 80      *
 81      * @see #isEmpty
 82      * @see #size
 83      */
 84     @Override
 85     public void clear() {
 86         backingMap.clear();
 87     }
 88 
 89     /**
 90      * Returns a new {@code HashSet} with the same elements and size as this
 91      * {@code HashSet}.
 92      *
 93      * @return a shallow copy of this {@code HashSet}.
 94      * @see java.lang.Cloneable
 95      */
 96     @Override
 97     @SuppressWarnings("unchecked")
 98     public Object clone() {
 99         try {
100             HashSet<E> clone = (HashSet<E>) super.clone();
101             clone.backingMap = (HashMap<E, HashSet<E>>) backingMap.clone();
102             return clone;
103         } catch (CloneNotSupportedException e) {
104             throw new AssertionError(e);
105         }
106     }
107 
108     /**
109      * Searches this {@code HashSet} for the specified object.
110      *
111      * @param object
112      *            the object to search for.
113      * @return {@code true} if {@code object} is an element of this
114      *         {@code HashSet}, {@code false} otherwise.
115      */
116     @Override
117     public boolean contains(Object object) {
118         return backingMap.containsKey(object);
119     }
120 
121     /**
122      * Returns true if this {@code HashSet} has no elements, false otherwise.
123      *
124      * @return {@code true} if this {@code HashSet} has no elements,
125      *         {@code false} otherwise.
126      * @see #size
127      */
128     @Override
129     public boolean isEmpty() {
130         return backingMap.isEmpty();
131     }
132 
133     /**
134      * Returns an Iterator on the elements of this {@code HashSet}.
135      *
136      * @return an Iterator on the elements of this {@code HashSet}.
137      * @see Iterator
138      */
139     @Override
140     public Iterator<E> iterator() {
141         return backingMap.keySet().iterator();
142     }
143 
144     /**
145      * Removes the specified object from this {@code HashSet}.
146      *
147      * @param object
148      *            the object to remove.
149      * @return {@code true} if the object was removed, {@code false} otherwise.
150      */
151     @Override
152     public boolean remove(Object object) {
153         return backingMap.remove(object) != null;
154     }
155 
156     /**
157      * Returns the number of elements in this {@code HashSet}.
158      *
159      * @return the number of elements in this {@code HashSet}.
160      */
161     @Override
162     public int size() {
163         return backingMap.size();
164     }
165 
166     private void writeObject(ObjectOutputStream stream) throws IOException {
167         stream.defaultWriteObject();
168         stream.writeInt(backingMap.table.length);
169         stream.writeFloat(HashMap.DEFAULT_LOAD_FACTOR);
170         stream.writeInt(size());
171         for (E e : this) {
172             stream.writeObject(e);
173         }
174     }
175 
176     @SuppressWarnings("unchecked")
177     private void readObject(ObjectInputStream stream) throws IOException,
178             ClassNotFoundException {
179         stream.defaultReadObject();
180         int length = stream.readInt();
181         float loadFactor = stream.readFloat();
182         backingMap = createBackingMap(length, loadFactor);
183         int elementCount = stream.readInt();
184         for (int i = elementCount; --i >= 0;) {
185             E key = (E) stream.readObject();
186             backingMap.put(key, this);
187         }
188     }
189 
190     HashMap<E, HashSet<E>> createBackingMap(int capacity, float loadFactor) {
191         return new HashMap<E, HashSet<E>>(capacity, loadFactor);
192     }
193 }
View Code

TreeSet

  1 /*
  2  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3  *  contributor license agreements.  See the NOTICE file distributed with
  4  *  this work for additional information regarding copyright ownership.
  5  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6  *  (the "License"); you may not use this file except in compliance with
  7  *  the License.  You may obtain a copy of the License at
  8  *
  9  *     http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  *  Unless required by applicable law or agreed to in writing, software
 12  *  distributed under the License is distributed on an "AS IS" BASIS,
 13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  *  See the License for the specific language governing permissions and
 15  *  limitations under the License.
 16  */
 17 
 18 package java.util;
 19 
 20 import java.io.IOException;
 21 import java.io.ObjectInputStream;
 22 import java.io.ObjectOutputStream;
 23 import java.io.Serializable;
 24 
 25 /**
 26  * TreeSet is an implementation of SortedSet. All optional operations (adding
 27  * and removing) are supported. The elements can be any objects which are
 28  * comparable to each other either using their natural order or a specified
 29  * Comparator.
 30  *
 31  * @since 1.2
 32  */
 33 public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>,
 34         Cloneable, Serializable {
 35 
 36     private static final long serialVersionUID = -2479143000061671589L;
 37 
 38     /** Keys are this set's elements. Values are always Boolean.TRUE */
 39     private transient NavigableMap<E, Object> backingMap;
 40 
 41     private transient NavigableSet<E> descendingSet;
 42 
 43     TreeSet(NavigableMap<E, Object> map) {
 44         backingMap = map;
 45     }
 46 
 47     /**
 48      * Constructs a new empty instance of {@code TreeSet} which uses natural
 49      * ordering.
 50      */
 51     public TreeSet() {
 52         backingMap = new TreeMap<E, Object>();
 53     }
 54 
 55     /**
 56      * Constructs a new instance of {@code TreeSet} which uses natural ordering
 57      * and containing the unique elements in the specified collection.
 58      *
 59      * @param collection
 60      *            the collection of elements to add.
 61      * @throws ClassCastException
 62      *                when an element in the collection does not implement the
 63      *                Comparable interface, or the elements in the collection
 64      *                cannot be compared.
 65      */
 66     public TreeSet(Collection<? extends E> collection) {
 67         this();
 68         addAll(collection);
 69     }
 70 
 71     /**
 72      * Constructs a new empty instance of {@code TreeSet} which uses the
 73      * specified comparator.
 74      *
 75      * @param comparator
 76      *            the comparator to use.
 77      */
 78     public TreeSet(Comparator<? super E> comparator) {
 79         backingMap = new TreeMap<E, Object>(comparator);
 80     }
 81 
 82     /**
 83      * Constructs a new instance of {@code TreeSet} containing the elements of
 84      * the specified SortedSet and using the same Comparator.
 85      *
 86      * @param set
 87      *            the SortedSet of elements to add.
 88      */
 89     public TreeSet(SortedSet<E> set) {
 90         this(set.comparator());
 91         Iterator<E> it = set.iterator();
 92         while (it.hasNext()) {
 93             add(it.next());
 94         }
 95     }
 96 
 97     /**
 98      * Adds the specified object to this {@code TreeSet}.
 99      *
100      * @param object
101      *            the object to add.
102      * @return {@code true} when this {@code TreeSet} did not already contain
103      *         the object, {@code false} otherwise.
104      * @throws ClassCastException
105      *             when the object cannot be compared with the elements in this
106      *             {@code TreeSet}.
107      * @throws NullPointerException
108      *             when the object is null and the comparator cannot handle
109      *             null.
110      */
111     @Override
112     public boolean add(E object) {
113         return backingMap.put(object, Boolean.TRUE) == null;
114     }
115 
116     /**
117      * Adds the objects in the specified collection to this {@code TreeSet}.
118      *
119      * @param collection
120      *            the collection of objects to add.
121      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
122      *         otherwise.
123      * @throws ClassCastException
124      *             when an object in the collection cannot be compared with the
125      *             elements in this {@code TreeSet}.
126      * @throws NullPointerException
127      *             when an object in the collection is null and the comparator
128      *             cannot handle null.
129      */
130     @Override
131     public boolean addAll(Collection<? extends E> collection) {
132         return super.addAll(collection);
133     }
134 
135     /**
136      * Removes all elements from this {@code TreeSet}, leaving it empty.
137      *
138      * @see #isEmpty
139      * @see #size
140      */
141     @Override
142     public void clear() {
143         backingMap.clear();
144     }
145 
146     /**
147      * Returns a new {@code TreeSet} with the same elements, size and comparator
148      * as this {@code TreeSet}.
149      *
150      * @return a shallow copy of this {@code TreeSet}.
151      * @see java.lang.Cloneable
152      */
153     @SuppressWarnings("unchecked")
154     @Override
155     public Object clone() {
156         try {
157             TreeSet<E> clone = (TreeSet<E>) super.clone();
158             if (backingMap instanceof TreeMap) {
159                 clone.backingMap = (NavigableMap<E, Object>) ((TreeMap<E, Object>) backingMap)
160                         .clone();
161             } else {
162                 clone.backingMap = new TreeMap<E, Object>(backingMap);
163             }
164             return clone;
165         } catch (CloneNotSupportedException e) {
166             throw new AssertionError(e);
167         }
168     }
169 
170     /**
171      * Returns the comparator used to compare elements in this {@code TreeSet}.
172      *
173      * @return a Comparator or null if the natural ordering is used
174      */
175     public Comparator<? super E> comparator() {
176         return backingMap.comparator();
177     }
178 
179     /**
180      * Searches this {@code TreeSet} for the specified object.
181      *
182      * @param object
183      *            the object to search for.
184      * @return {@code true} if {@code object} is an element of this
185      *         {@code TreeSet}, {@code false} otherwise.
186      * @throws ClassCastException
187      *             when the object cannot be compared with the elements in this
188      *             {@code TreeSet}.
189      * @throws NullPointerException
190      *             when the object is null and the comparator cannot handle
191      *             null.
192      */
193     @Override
194     public boolean contains(Object object) {
195         return backingMap.containsKey(object);
196     }
197 
198     /**
199      * Returns true if this {@code TreeSet} has no element, otherwise false.
200      *
201      * @return true if this {@code TreeSet} has no element.
202      * @see #size
203      */
204     @Override
205     public boolean isEmpty() {
206         return backingMap.isEmpty();
207     }
208 
209     /**
210      * Returns an Iterator on the elements of this {@code TreeSet}.
211      *
212      * @return an Iterator on the elements of this {@code TreeSet}.
213      * @see Iterator
214      */
215     @Override
216     public Iterator<E> iterator() {
217         return backingMap.keySet().iterator();
218     }
219 
220     /**
221      * {@inheritDoc}
222      *
223      * @see java.util.NavigableSet#descendingIterator()
224      * @since 1.6
225      */
226     public Iterator<E> descendingIterator() {
227         return descendingSet().iterator();
228     }
229 
230     /**
231      * Removes an occurrence of the specified object from this {@code TreeSet}.
232      *
233      * @param object
234      *            the object to remove.
235      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
236      *         otherwise.
237      * @throws ClassCastException
238      *             when the object cannot be compared with the elements in this
239      *             {@code TreeSet}.
240      * @throws NullPointerException
241      *             when the object is null and the comparator cannot handle
242      *             null.
243      */
244     @Override
245     public boolean remove(Object object) {
246         return backingMap.remove(object) != null;
247     }
248 
249     /**
250      * Returns the number of elements in this {@code TreeSet}.
251      *
252      * @return the number of elements in this {@code TreeSet}.
253      */
254     @Override
255     public int size() {
256         return backingMap.size();
257     }
258 
259     /**
260      * Returns the first element in this set.
261      * @exception NoSuchElementException when this TreeSet is empty
262      */
263     public E first() {
264         return backingMap.firstKey();
265     }
266 
267     /**
268      * Returns the last element in this set.
269      * @exception NoSuchElementException when this TreeSet is empty
270      */
271     public E last() {
272         return backingMap.lastKey();
273     }
274 
275     /**
276      * {@inheritDoc}
277      *
278      * @see java.util.NavigableSet#pollFirst()
279      * @since 1.6
280      */
281     public E pollFirst() {
282         Map.Entry<E, Object> entry = backingMap.pollFirstEntry();
283         return (entry == null) ? null : entry.getKey();
284     }
285 
286     /**
287      * {@inheritDoc}
288      *
289      * @see java.util.NavigableSet#pollLast()
290      * @since 1.6
291      */
292     public E pollLast() {
293         Map.Entry<E, Object> entry = backingMap.pollLastEntry();
294         return (entry == null) ? null : entry.getKey();
295     }
296 
297     /**
298      * {@inheritDoc}
299      *
300      * @see java.util.NavigableSet#higher(java.lang.Object)
301      * @since 1.6
302      */
303     public E higher(E e) {
304         return backingMap.higherKey(e);
305     }
306 
307     /**
308      * {@inheritDoc}
309      *
310      * @see java.util.NavigableSet#lower(java.lang.Object)
311      * @since 1.6
312      */
313     public E lower(E e) {
314         return backingMap.lowerKey(e);
315     }
316 
317     /**
318      * {@inheritDoc}
319      *
320      * @see java.util.NavigableSet#ceiling(java.lang.Object)
321      * @since 1.6
322      */
323     public E ceiling(E e) {
324         return backingMap.ceilingKey(e);
325     }
326 
327     /**
328      * {@inheritDoc}
329      *
330      * @see java.util.NavigableSet#floor(java.lang.Object)
331      * @since 1.6
332      */
333     public E floor(E e) {
334         return backingMap.floorKey(e);
335     }
336 
337     /**
338      * {@inheritDoc}
339      *
340      * @see java.util.NavigableSet#descendingSet()
341      * @since 1.6
342      */
343     public NavigableSet<E> descendingSet() {
344         return (descendingSet != null) ? descendingSet
345                 : (descendingSet = new TreeSet<E>(backingMap.descendingMap()));
346     }
347 
348     /**
349      * {@inheritDoc}
350      *
351      * @see java.util.NavigableSet#subSet(Object, boolean, Object, boolean)
352      * @since 1.6
353      */
354     @SuppressWarnings("unchecked")
355     public NavigableSet<E> subSet(E start, boolean startInclusive, E end,
356             boolean endInclusive) {
357         Comparator<? super E> c = backingMap.comparator();
358         int compare = (c == null) ? ((Comparable<E>) start).compareTo(end) : c
359                 .compare(start, end);
360         if (compare <= 0) {
361             return new TreeSet<E>(backingMap.subMap(start, startInclusive, end,
362                     endInclusive));
363         }
364         throw new IllegalArgumentException();
365     }
366 
367     /**
368      * {@inheritDoc}
369      *
370      * @see java.util.NavigableSet#headSet(Object, boolean)
371      * @since 1.6
372      */
373     @SuppressWarnings("unchecked")
374     public NavigableSet<E> headSet(E end, boolean endInclusive) {
375         // Check for errors
376         Comparator<? super E> c = backingMap.comparator();
377         if (c == null) {
378             ((Comparable<E>) end).compareTo(end);
379         } else {
380             c.compare(end, end);
381         }
382         return new TreeSet<E>(backingMap.headMap(end, endInclusive));
383     }
384 
385     /**
386      * {@inheritDoc}
387      *
388      * @see java.util.NavigableSet#tailSet(Object, boolean)
389      * @since 1.6
390      */
391     @SuppressWarnings("unchecked")
392     public NavigableSet<E> tailSet(E start, boolean startInclusive) {
393         // Check for errors
394         Comparator<? super E> c = backingMap.comparator();
395         if (c == null) {
396             ((Comparable<E>) start).compareTo(start);
397         } else {
398             c.compare(start, start);
399         }
400         return new TreeSet<E>(backingMap.tailMap(start, startInclusive));
401     }
402 
403     /**
404      * Returns a {@code SortedSet} of the specified portion of this {@code TreeSet} which
405      * contains elements greater or equal to the start element but less than the
406      * end element. The returned SortedSet is backed by this TreeSet so changes
407      * to one are reflected by the other.
408      *
409      * @param start
410      *            the start element
411      * @param end
412      *            the end element
413      * @return a subset where the elements are greater or equal to
414      *         <code>start</code> and less than <code>end</code>
415      *
416      * @exception ClassCastException
417      *                when the start or end object cannot be compared with the
418      *                elements in this TreeSet
419      * @exception NullPointerException
420      *                when the start or end object is null and the comparator
421      *                cannot handle null
422      */
423     @SuppressWarnings("unchecked")
424     public SortedSet<E> subSet(E start, E end) {
425         return subSet(start, true, end, false);
426     }
427 
428     /**
429      * Returns a {@code SortedSet} of the specified portion of this {@code TreeSet} which
430      * contains elements less than the end element. The returned SortedSet is
431      * backed by this TreeSet so changes to one are reflected by the other.
432      *
433      * @param end
434      *            the end element
435      * @return a subset where the elements are less than <code>end</code>
436      *
437      * @exception ClassCastException
438      *                when the end object cannot be compared with the elements
439      *                in this TreeSet
440      * @exception NullPointerException
441      *                when the end object is null and the comparator cannot
442      *                handle null
443      */
444     @SuppressWarnings("unchecked")
445     public SortedSet<E> headSet(E end) {
446         return headSet(end, false);
447     }
448 
449     /**
450      * Returns a {@code SortedSet} of the specified portion of this {@code TreeSet} which
451      * contains elements greater or equal to the start element. The returned
452      * SortedSet is backed by this TreeSet so changes to one are reflected by
453      * the other.
454      *
455      * @param start
456      *            the start element
457      * @return a subset where the elements are greater or equal to
458      *         <code>start</code>
459      *
460      * @exception ClassCastException
461      *                when the start object cannot be compared with the elements
462      *                in this TreeSet
463      * @exception NullPointerException
464      *                when the start object is null and the comparator cannot
465      *                handle null
466      */
467     @SuppressWarnings("unchecked")
468     public SortedSet<E> tailSet(E start) {
469         return tailSet(start, true);
470     }
471 
472     private void writeObject(ObjectOutputStream stream) throws IOException {
473         stream.defaultWriteObject();
474         stream.writeObject(backingMap.comparator());
475         int size = backingMap.size();
476         stream.writeInt(size);
477         if (size > 0) {
478             Iterator<E> it = backingMap.keySet().iterator();
479             while (it.hasNext()) {
480                 stream.writeObject(it.next());
481             }
482         }
483     }
484 
485     @SuppressWarnings("unchecked")
486     private void readObject(ObjectInputStream stream) throws IOException,
487             ClassNotFoundException {
488         stream.defaultReadObject();
489         TreeMap<E, Object> map = new TreeMap<E, Object>(
490                 (Comparator<? super E>) stream.readObject());
491         int size = stream.readInt();
492         if (size > 0) {
493             for (int i=0; i<size; i++) {
494                 E elem = (E)stream.readObject();
495                 map.put(elem, Boolean.TRUE);
496             }
497         }
498         backingMap = map;
499     }
500 }
View Code

 

AbstractList AbstractClass

  1 /*
  2  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3  *  contributor license agreements.  See the NOTICE file distributed with
  4  *  this work for additional information regarding copyright ownership.
  5  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6  *  (the "License"); you may not use this file except in compliance with
  7  *  the License.  You may obtain a copy of the License at
  8  *
  9  *     http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  *  Unless required by applicable law or agreed to in writing, software
 12  *  distributed under the License is distributed on an "AS IS" BASIS,
 13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  *  See the License for the specific language governing permissions and
 15  *  limitations under the License.
 16  */
 17 
 18 package java.util;
 19 
 20 
 21 public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
 22 
 23     /**
 24      * A counter for changes to the list.
 25      */
 26     protected transient int modCount;
 27 
 28     private class SimpleListIterator implements Iterator<E> {
 29         int pos = -1;
 30 
 31         int expectedModCount;
 32 
 33         int lastPosition = -1;
 34 
 35         SimpleListIterator() {
 36             expectedModCount = modCount;
 37         }
 38 
 39         public boolean hasNext() {
 40             return pos + 1 < size();
 41         }
 42 
 43         public E next() {
 44             if (expectedModCount == modCount) {
 45                 try {
 46                     E result = get(pos + 1);
 47                     lastPosition = ++pos;
 48                     return result;
 49                 } catch (IndexOutOfBoundsException e) {
 50                     throw new NoSuchElementException();
 51                 }
 52             }
 53             throw new ConcurrentModificationException();
 54         }
 55 
 56         public void remove() {
 57             if (this.lastPosition == -1) {
 58                 throw new IllegalStateException();
 59             }
 60 
 61             if (expectedModCount != modCount) {
 62                 throw new ConcurrentModificationException();
 63             }
 64 
 65             try {
 66                 AbstractList.this.remove(lastPosition);
 67             } catch (IndexOutOfBoundsException e) {
 68                 throw new ConcurrentModificationException();
 69             }
 70 
 71             expectedModCount = modCount;
 72             if (pos == lastPosition) {
 73                 pos--;
 74             }
 75             lastPosition = -1;
 76         }
 77     }
 78 
 79     private final class FullListIterator extends SimpleListIterator implements ListIterator<E> {
 80         FullListIterator(int start) {
 81             if (start >= 0 && start <= size()) {
 82                 pos = start - 1;
 83             } else {
 84                 throw new IndexOutOfBoundsException();
 85             }
 86         }
 87 
 88         public void add(E object) {
 89             if (expectedModCount == modCount) {
 90                 try {
 91                     AbstractList.this.add(pos + 1, object);
 92                 } catch (IndexOutOfBoundsException e) {
 93                     throw new NoSuchElementException();
 94                 }
 95                 pos++;
 96                 lastPosition = -1;
 97                 if (modCount != expectedModCount) {
 98                     expectedModCount = modCount;
 99                 }
100             } else {
101                 throw new ConcurrentModificationException();
102             }
103         }
104 
105         public boolean hasPrevious() {
106             return pos >= 0;
107         }
108 
109         public int nextIndex() {
110             return pos + 1;
111         }
112 
113         public E previous() {
114             if (expectedModCount == modCount) {
115                 try {
116                     E result = get(pos);
117                     lastPosition = pos;
118                     pos--;
119                     return result;
120                 } catch (IndexOutOfBoundsException e) {
121                     throw new NoSuchElementException();
122                 }
123             }
124             throw new ConcurrentModificationException();
125         }
126 
127         public int previousIndex() {
128             return pos;
129         }
130 
131         public void set(E object) {
132             if (expectedModCount == modCount) {
133                 try {
134                     AbstractList.this.set(lastPosition, object);
135                 } catch (IndexOutOfBoundsException e) {
136                     throw new IllegalStateException();
137                 }
138             } else {
139                 throw new ConcurrentModificationException();
140             }
141         }
142     }
143 
144     private static final class SubAbstractListRandomAccess<E> extends
145             SubAbstractList<E> implements RandomAccess {
146         SubAbstractListRandomAccess(AbstractList<E> list, int start, int end) {
147             super(list, start, end);
148         }
149     }
150 
151     private static class SubAbstractList<E> extends AbstractList<E> {
152         private final AbstractList<E> fullList;
153 
154         private int offset;
155 
156         private int size;
157 
158         private static final class SubAbstractListIterator<E> implements
159                 ListIterator<E> {
160             private final SubAbstractList<E> subList;
161 
162             private final ListIterator<E> iterator;
163 
164             private int start;
165 
166             private int end;
167 
168             SubAbstractListIterator(ListIterator<E> it,
169                     SubAbstractList<E> list, int offset, int length) {
170                 iterator = it;
171                 subList = list;
172                 start = offset;
173                 end = start + length;
174             }
175 
176             public void add(E object) {
177                 iterator.add(object);
178                 subList.sizeChanged(true);
179                 end++;
180             }
181 
182             public boolean hasNext() {
183                 return iterator.nextIndex() < end;
184             }
185 
186             public boolean hasPrevious() {
187                 return iterator.previousIndex() >= start;
188             }
189 
190             public E next() {
191                 if (iterator.nextIndex() < end) {
192                     return iterator.next();
193                 }
194                 throw new NoSuchElementException();
195             }
196 
197             public int nextIndex() {
198                 return iterator.nextIndex() - start;
199             }
200 
201             public E previous() {
202                 if (iterator.previousIndex() >= start) {
203                     return iterator.previous();
204                 }
205                 throw new NoSuchElementException();
206             }
207 
208             public int previousIndex() {
209                 int previous = iterator.previousIndex();
210                 if (previous >= start) {
211                     return previous - start;
212                 }
213                 return -1;
214             }
215 
216             public void remove() {
217                 iterator.remove();
218                 subList.sizeChanged(false);
219                 end--;
220             }
221 
222             public void set(E object) {
223                 iterator.set(object);
224             }
225         }
226 
227         SubAbstractList(AbstractList<E> list, int start, int end) {
228             fullList = list;
229             modCount = fullList.modCount;
230             offset = start;
231             size = end - start;
232         }
233 
234         @Override
235         public void add(int location, E object) {
236             if (modCount == fullList.modCount) {
237                 if (location >= 0 && location <= size) {
238                     fullList.add(location + offset, object);
239                     size++;
240                     modCount = fullList.modCount;
241                 } else {
242                     throw new IndexOutOfBoundsException();
243                 }
244             } else {
245                 throw new ConcurrentModificationException();
246             }
247         }
248 
249         @Override
250         public boolean addAll(int location, Collection<? extends E> collection) {
251             if (modCount == fullList.modCount) {
252                 if (location >= 0 && location <= size) {
253                     boolean result = fullList.addAll(location + offset,
254                             collection);
255                     if (result) {
256                         size += collection.size();
257                         modCount = fullList.modCount;
258                     }
259                     return result;
260                 }
261                 throw new IndexOutOfBoundsException();
262             }
263             throw new ConcurrentModificationException();
264         }
265 
266         @Override
267         public boolean addAll(Collection<? extends E> collection) {
268             if (modCount == fullList.modCount) {
269                 boolean result = fullList.addAll(offset + size, collection);
270                 if (result) {
271                     size += collection.size();
272                     modCount = fullList.modCount;
273                 }
274                 return result;
275             }
276             throw new ConcurrentModificationException();
277         }
278 
279         @Override
280         public E get(int location) {
281             if (modCount == fullList.modCount) {
282                 if (location >= 0 && location < size) {
283                     return fullList.get(location + offset);
284                 }
285                 throw new IndexOutOfBoundsException();
286             }
287             throw new ConcurrentModificationException();
288         }
289 
290         @Override
291         public Iterator<E> iterator() {
292             return listIterator(0);
293         }
294 
295         @Override
296         public ListIterator<E> listIterator(int location) {
297             if (modCount == fullList.modCount) {
298                 if (location >= 0 && location <= size) {
299                     return new SubAbstractListIterator<E>(fullList
300                             .listIterator(location + offset), this, offset,
301                             size);
302                 }
303                 throw new IndexOutOfBoundsException();
304             }
305             throw new ConcurrentModificationException();
306         }
307 
308         @Override
309         public E remove(int location) {
310             if (modCount == fullList.modCount) {
311                 if (location >= 0 && location < size) {
312                     E result = fullList.remove(location + offset);
313                     size--;
314                     modCount = fullList.modCount;
315                     return result;
316                 }
317                 throw new IndexOutOfBoundsException();
318             }
319             throw new ConcurrentModificationException();
320         }
321 
322         @Override
323         protected void removeRange(int start, int end) {
324             if (start != end) {
325                 if (modCount == fullList.modCount) {
326                     fullList.removeRange(start + offset, end + offset);
327                     size -= end - start;
328                     modCount = fullList.modCount;
329                 } else {
330                     throw new ConcurrentModificationException();
331                 }
332             }
333         }
334 
335         @Override
336         public E set(int location, E object) {
337             if (modCount == fullList.modCount) {
338                 if (location >= 0 && location < size) {
339                     return fullList.set(location + offset, object);
340                 }
341                 throw new IndexOutOfBoundsException();
342             }
343             throw new ConcurrentModificationException();
344         }
345 
346         @Override
347         public int size() {
348             if (modCount == fullList.modCount) {
349                 return size;
350             }
351             throw new ConcurrentModificationException();
352         }
353 
354         void sizeChanged(boolean increment) {
355             if (increment) {
356                 size++;
357             } else {
358                 size--;
359             }
360             modCount = fullList.modCount;
361         }
362     }
363 
364     /**
365      * Constructs a new instance of this AbstractList.
366      */
367     protected AbstractList() {
368     }
369 
370     /**
371      * Inserts the specified object into this List at the specified location.
372      * The object is inserted before any previous element at the specified
373      * location. If the location is equal to the size of this List, the object
374      * is added at the end.
375      * <p>
376      * Concrete implementations that would like to support the add functionality
377      * must override this method.
378      *
379      * @param location
380      *            the index at which to insert.
381      * @param object
382      *            the object to add.
383      *
384      * @throws UnsupportedOperationException
385      *                if adding to this List is not supported.
386      * @throws ClassCastException
387      *                if the class of the object is inappropriate for this
388      *                List
389      * @throws IllegalArgumentException
390      *                if the object cannot be added to this List
391      * @throws IndexOutOfBoundsException
392      *                if {@code location < 0 || >= size()}
393      */
394     public void add(int location, E object) {
395         throw new UnsupportedOperationException();
396     }
397 
398     /**
399      * Adds the specified object at the end of this List.
400      *
401      *
402      * @param object
403      *            the object to add
404      * @return true
405      *
406      * @throws UnsupportedOperationException
407      *                if adding to this List is not supported
408      * @throws ClassCastException
409      *                if the class of the object is inappropriate for this
410      *                List
411      * @throws IllegalArgumentException
412      *                if the object cannot be added to this List
413      */
414     @Override
415     public boolean add(E object) {
416         add(size(), object);
417         return true;
418     }
419 
420     /**
421      * Inserts the objects in the specified Collection at the specified location
422      * in this List. The objects are added in the order they are returned from
423      * the collection's iterator.
424      *
425      * @param location
426      *            the index at which to insert.
427      * @param collection
428      *            the Collection of objects
429      * @return {@code true} if this List is modified, {@code false} otherwise.
430      * @throws UnsupportedOperationException
431      *             if adding to this list is not supported.
432      * @throws ClassCastException
433      *             if the class of an object is inappropriate for this list.
434      * @throws IllegalArgumentException
435      *             if an object cannot be added to this list.
436      * @throws IndexOutOfBoundsException
437      *             if {@code location < 0 || > size()}
438      */
439     public boolean addAll(int location, Collection<? extends E> collection) {
440         Iterator<? extends E> it = collection.iterator();
441         while (it.hasNext()) {
442             add(location++, it.next());
443         }
444         return !collection.isEmpty();
445     }
446 
447     /**
448      * Removes all elements from this list, leaving it empty.
449      *
450      * @throws UnsupportedOperationException
451      *             if removing from this list is not supported.
452      * @see List#isEmpty
453      * @see List#size
454      */
455     @Override
456     public void clear() {
457         removeRange(0, size());
458     }
459 
460     @Override
461     public boolean equals(Object object) {
462         if (this == object) {
463             return true;
464         }
465         if (object instanceof List) {
466             List<?> list = (List<?>) object;
467             if (list.size() != size()) {
468                 return false;
469             }
470 
471             Iterator<?> it1 = iterator(), it2 = list.iterator();
472             while (it1.hasNext()) {
473                 Object e1 = it1.next(), e2 = it2.next();
474                 if (!(e1 == null ? e2 == null : e1.equals(e2))) {
475                     return false;
476                 }
477             }
478             return true;
479         }
480         return false;
481     }
482     public abstract E get(int location);
483 
484     @Override
485     public int hashCode() {
486         int result = 1;
487         Iterator<?> it = iterator();
488         while (it.hasNext()) {
489             Object object = it.next();
490             result = (31 * result) + (object == null ? 0 : object.hashCode());
491         }
492         return result;
493     }
494     public int indexOf(Object object) {
495         ListIterator<?> it = listIterator();
496         if (object != null) {
497             while (it.hasNext()) {
498                 if (object.equals(it.next())) {
499                     return it.previousIndex();
500                 }
501             }
502         } else {
503             while (it.hasNext()) {
504                 if (it.next() == null) {
505                     return it.previousIndex();
506                 }
507             }
508         }
509         return -1;
510     }
511 
512     @Override
513     public Iterator<E> iterator() {
514         return new SimpleListIterator();
515     }
516 
517     public int lastIndexOf(Object object) {
518         ListIterator<?> it = listIterator(size());
519         if (object != null) {
520             while (it.hasPrevious()) {
521                 if (object.equals(it.previous())) {
522                     return it.nextIndex();
523                 }
524             }
525         } else {
526             while (it.hasPrevious()) {
527                 if (it.previous() == null) {
528                     return it.nextIndex();
529                 }
530             }
531         }
532         return -1;
533     }
534  
535     public ListIterator<E> listIterator() {
536         return listIterator(0);
537     }
538 
539     public ListIterator<E> listIterator(int location) {
540         return new FullListIterator(location);
541     }
542 
543 
544     public E remove(int location) {
545         throw new UnsupportedOperationException();
546     }
547 
548     protected void removeRange(int start, int end) {
549         Iterator<?> it = listIterator(start);
550         for (int i = start; i < end; i++) {
551             it.next();
552             it.remove();
553         }
554     }
555 
556     public E set(int location, E object) {
557         throw new UnsupportedOperationException();
558     }
559 
560     public List<E> subList(int start, int end) {
561         if (start >= 0 && end <= size()) {
562             if (start <= end) {
563                 if (this instanceof RandomAccess) {
564                     return new SubAbstractListRandomAccess<E>(this, start, end);
565                 }
566                 return new SubAbstractList<E>(this, start, end);
567             }
568             throw new IllegalArgumentException();
569         }
570         throw new IndexOutOfBoundsException();
571     }
572 }
View Code

Vector

   1 /*
   2  *  Licensed to the Apache Software Foundation (ASF) under one or more
   3  *  contributor license agreements.  See the NOTICE file distributed with
   4  *  this work for additional information regarding copyright ownership.
   5  *  The ASF licenses this file to You under the Apache License, Version 2.0
   6  *  (the "License"); you may not use this file except in compliance with
   7  *  the License.  You may obtain a copy of the License at
   8  *
   9  *     http://www.apache.org/licenses/LICENSE-2.0
  10  *
  11  *  Unless required by applicable law or agreed to in writing, software
  12  *  distributed under the License is distributed on an "AS IS" BASIS,
  13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14  *  See the License for the specific language governing permissions and
  15  *  limitations under the License.
  16  */
  17 
  18 package java.util;
  19 
  20 import java.io.IOException;
  21 import java.io.ObjectOutputStream;
  22 import java.io.Serializable;
  23 import java.lang.reflect.Array;
  24 
  25 /**
  26  * Vector is an implementation of {@link List}, backed by an array and synchronized.
  27  * All optional operations including adding, removing, and replacing elements are supported.
  28  *
  29  * <p>All elements are permitted, including null.
  30  *
  31  * <p>This class is equivalent to {@link ArrayList} with synchronized operations. This has a
  32  * performance cost, and the synchronization is not necessarily meaningful to your application:
  33  * synchronizing each call to {@code get}, for example, is not equivalent to synchronizing on the
  34  * list and iterating over it (which is probably what you intended). If you do need very highly
  35  * concurrent access, you should also consider {@link java.util.concurrent.CopyOnWriteArrayList}.
  36  *
  37  * @param <E> The element type of this list.
  38  */
  39 public class Vector<E> extends AbstractList<E> implements List<E>,
  40         RandomAccess, Cloneable, Serializable {
  41 
  42     private static final long serialVersionUID = -2767605614048989439L;
  43 
  44     /**
  45      * The number of elements or the size of the vector.
  46      */
  47     protected int elementCount;
  48 
  49     /**
  50      * The elements of the vector.
  51      */
  52     protected Object[] elementData;
  53 
  54     /**
  55      * How many elements should be added to the vector when it is detected that
  56      * it needs to grow to accommodate extra entries. If this value is zero or
  57      * negative the size will be doubled if an increase is needed.
  58      */
  59     protected int capacityIncrement;
  60 
  61     private static final int DEFAULT_SIZE = 10;
  62 
  63     /**
  64      * Constructs a new vector using the default capacity.
  65      */
  66     public Vector() {
  67         this(DEFAULT_SIZE, 0);
  68     }
  69 
  70     /**
  71      * Constructs a new vector using the specified capacity.
  72      *
  73      * @param capacity
  74      *            the initial capacity of the new vector.
  75      * @throws IllegalArgumentException
  76      *             if {@code capacity} is negative.
  77      */
  78     public Vector(int capacity) {
  79         this(capacity, 0);
  80     }
  81 
  82     /**
  83      * Constructs a new vector using the specified capacity and capacity
  84      * increment.
  85      *
  86      * @param capacity
  87      *            the initial capacity of the new vector.
  88      * @param capacityIncrement
  89      *            the amount to increase the capacity when this vector is full.
  90      * @throws IllegalArgumentException
  91      *             if {@code capacity} is negative.
  92      */
  93     public Vector(int capacity, int capacityIncrement) {
  94         if (capacity < 0) {
  95             throw new IllegalArgumentException();
  96         }
  97         elementData = newElementArray(capacity);
  98         elementCount = 0;
  99         this.capacityIncrement = capacityIncrement;
 100     }
 101 
 102     /**
 103      * Constructs a new instance of {@code Vector} containing the elements in
 104      * {@code collection}. The order of the elements in the new {@code Vector}
 105      * is dependent on the iteration order of the seed collection.
 106      *
 107      * @param collection
 108      *            the collection of elements to add.
 109      */
 110     public Vector(Collection<? extends E> collection) {
 111         this(collection.size(), 0);
 112         Iterator<? extends E> it = collection.iterator();
 113         while (it.hasNext()) {
 114             elementData[elementCount++] = it.next();
 115         }
 116     }
 117 
 118     @SuppressWarnings("unchecked")
 119     private E[] newElementArray(int size) {
 120         return (E[]) new Object[size];
 121     }
 122 
 123     /**
 124      * Adds the specified object into this vector at the specified location. The
 125      * object is inserted before any element with the same or a higher index
 126      * increasing their index by 1. If the location is equal to the size of this
 127      * vector, the object is added at the end.
 128      *
 129      * @param location
 130      *            the index at which to insert the element.
 131      * @param object
 132      *            the object to insert in this vector.
 133      * @throws ArrayIndexOutOfBoundsException
 134      *                if {@code location < 0 || location > size()}.
 135      * @see #addElement
 136      * @see #size
 137      */
 138     @Override
 139     public void add(int location, E object) {
 140         insertElementAt(object, location);
 141     }
 142 
 143     /**
 144      * Adds the specified object at the end of this vector.
 145      *
 146      * @param object
 147      *            the object to add to the vector.
 148      * @return {@code true}
 149      */
 150     @Override
 151     public synchronized boolean add(E object) {
 152         if (elementCount == elementData.length) {
 153             growByOne();
 154         }
 155         elementData[elementCount++] = object;
 156         modCount++;
 157         return true;
 158     }
 159 
 160     /**
 161      * Inserts the objects in the specified collection at the specified location
 162      * in this vector. The objects are inserted in the order in which they are
 163      * returned from the Collection iterator. The elements with an index equal
 164      * or higher than {@code location} have their index increased by the size of
 165      * the added collection.
 166      *
 167      * @param location
 168      *            the location to insert the objects.
 169      * @param collection
 170      *            the collection of objects.
 171      * @return {@code true} if this vector is modified, {@code false} otherwise.
 172      * @throws ArrayIndexOutOfBoundsException
 173      *                if {@code location < 0} or {@code location > size()}.
 174      */
 175     @Override
 176     public synchronized boolean addAll(int location, Collection<? extends E> collection) {
 177         if (location >= 0 && location <= elementCount) {
 178             int size = collection.size();
 179             if (size == 0) {
 180                 return false;
 181             }
 182             int required = size - (elementData.length - elementCount);
 183             if (required > 0) {
 184                 growBy(required);
 185             }
 186             int count = elementCount - location;
 187             if (count > 0) {
 188                 System.arraycopy(elementData, location, elementData, location
 189                         + size, count);
 190             }
 191             Iterator<? extends E> it = collection.iterator();
 192             while (it.hasNext()) {
 193                 elementData[location++] = it.next();
 194             }
 195             elementCount += size;
 196             modCount++;
 197             return true;
 198         }
 199         throw arrayIndexOutOfBoundsException(location, elementCount);
 200     }
 201 
 202     /**
 203      * Adds the objects in the specified collection to the end of this vector.
 204      *
 205      * @param collection
 206      *            the collection of objects.
 207      * @return {@code true} if this vector is modified, {@code false} otherwise.
 208      */
 209     @Override
 210     public synchronized boolean addAll(Collection<? extends E> collection) {
 211         return addAll(elementCount, collection);
 212     }
 213 
 214     /**
 215      * Adds the specified object at the end of this vector.
 216      *
 217      * @param object
 218      *            the object to add to the vector.
 219      */
 220     public synchronized void addElement(E object) {
 221         if (elementCount == elementData.length) {
 222             growByOne();
 223         }
 224         elementData[elementCount++] = object;
 225         modCount++;
 226     }
 227 
 228     /**
 229      * Returns the number of elements this vector can hold without growing.
 230      *
 231      * @return the capacity of this vector.
 232      * @see #ensureCapacity
 233      * @see #size
 234      */
 235     public synchronized int capacity() {
 236         return elementData.length;
 237     }
 238 
 239     /**
 240      * Removes all elements from this vector, leaving it empty.
 241      *
 242      * @see #isEmpty
 243      * @see #size
 244      */
 245     @Override
 246     public void clear() {
 247         removeAllElements();
 248     }
 249 
 250     /**
 251      * Returns a new vector with the same elements, size, capacity and capacity
 252      * increment as this vector.
 253      *
 254      * @return a shallow copy of this vector.
 255      * @see java.lang.Cloneable
 256      */
 257     @Override
 258     @SuppressWarnings("unchecked")
 259     public synchronized Object clone() {
 260         try {
 261             Vector<E> vector = (Vector<E>) super.clone();
 262             vector.elementData = elementData.clone();
 263             return vector;
 264         } catch (CloneNotSupportedException e) {
 265             throw new AssertionError(e);
 266         }
 267     }
 268 
 269     /**
 270      * Searches this vector for the specified object.
 271      *
 272      * @param object
 273      *            the object to look for in this vector.
 274      * @return {@code true} if object is an element of this vector,
 275      *         {@code false} otherwise.
 276      * @see #indexOf(Object)
 277      * @see #indexOf(Object, int)
 278      * @see java.lang.Object#equals
 279      */
 280     @Override
 281     public boolean contains(Object object) {
 282         return indexOf(object, 0) != -1;
 283     }
 284 
 285     /**
 286      * Searches this vector for all objects in the specified collection.
 287      *
 288      * @param collection
 289      *            the collection of objects.
 290      * @return {@code true} if all objects in the specified collection are
 291      *         elements of this vector, {@code false} otherwise.
 292      */
 293     @Override
 294     public synchronized boolean containsAll(Collection<?> collection) {
 295         return super.containsAll(collection);
 296     }
 297 
 298     /**
 299      * Attempts to copy elements contained by this {@code Vector} into the
 300      * corresponding elements of the supplied {@code Object} array.
 301      *
 302      * @param elements
 303      *            the {@code Object} array into which the elements of this
 304      *            vector are copied.
 305      * @throws IndexOutOfBoundsException
 306      *             if {@code elements} is not big enough.
 307      * @see #clone
 308      */
 309     public synchronized void copyInto(Object[] elements) {
 310         System.arraycopy(elementData, 0, elements, 0, elementCount);
 311     }
 312 
 313     /**
 314      * Returns the element at the specified location in this vector.
 315      *
 316      * @param location
 317      *            the index of the element to return in this vector.
 318      * @return the element at the specified location.
 319      * @throws ArrayIndexOutOfBoundsException
 320      *                if {@code location < 0 || location >= size()}.
 321      * @see #size
 322      */
 323     @SuppressWarnings("unchecked")
 324     public synchronized E elementAt(int location) {
 325         if (location < elementCount) {
 326             return (E) elementData[location];
 327         }
 328         throw arrayIndexOutOfBoundsException(location, elementCount);
 329     }
 330 
 331     /**
 332      * Returns an enumeration on the elements of this vector. The results of the
 333      * enumeration may be affected if the contents of this vector is modified.
 334      *
 335      * @return an enumeration of the elements of this vector.
 336      * @see #elementAt
 337      * @see Enumeration
 338      */
 339     public Enumeration<E> elements() {
 340         return new Enumeration<E>() {
 341             int pos = 0;
 342 
 343             public boolean hasMoreElements() {
 344                 return pos < elementCount;
 345             }
 346 
 347             @SuppressWarnings("unchecked")
 348             public E nextElement() {
 349                 synchronized (Vector.this) {
 350                     if (pos < elementCount) {
 351                         return (E) elementData[pos++];
 352                     }
 353                 }
 354                 throw new NoSuchElementException();
 355             }
 356         };
 357     }
 358 
 359     /**
 360      * Ensures that this vector can hold the specified number of elements
 361      * without growing.
 362      *
 363      * @param minimumCapacity
 364      *            the minimum number of elements that this vector will hold
 365      *            before growing.
 366      * @see #capacity
 367      */
 368     public synchronized void ensureCapacity(int minimumCapacity) {
 369         if (elementData.length < minimumCapacity) {
 370             int next = (capacityIncrement <= 0 ? elementData.length
 371                     : capacityIncrement)
 372                     + elementData.length;
 373             grow(minimumCapacity > next ? minimumCapacity : next);
 374         }
 375     }
 376 
 377     /**
 378      * Compares the specified object to this vector and returns if they are
 379      * equal. The object must be a List which contains the same objects in the
 380      * same order.
 381      *
 382      * @param object
 383      *            the object to compare with this object
 384      * @return {@code true} if the specified object is equal to this vector,
 385      *         {@code false} otherwise.
 386      * @see #hashCode
 387      */
 388     @Override
 389     public synchronized boolean equals(Object object) {
 390         if (this == object) {
 391             return true;
 392         }
 393         if (object instanceof List) {
 394             List<?> list = (List<?>) object;
 395             if (list.size() != elementCount) {
 396                 return false;
 397             }
 398 
 399             int index = 0;
 400             Iterator<?> it = list.iterator();
 401             while (it.hasNext()) {
 402                 Object e1 = elementData[index++], e2 = it.next();
 403                 if (!(e1 == null ? e2 == null : e1.equals(e2))) {
 404                     return false;
 405                 }
 406             }
 407             return true;
 408         }
 409         return false;
 410     }
 411 
 412     /**
 413      * Returns the first element in this vector.
 414      *
 415      * @return the element at the first position.
 416      * @throws NoSuchElementException
 417      *                if this vector is empty.
 418      * @see #elementAt
 419      * @see #lastElement
 420      * @see #size
 421      */
 422     @SuppressWarnings("unchecked")
 423     public synchronized E firstElement() {
 424         if (elementCount > 0) {
 425             return (E) elementData[0];
 426         }
 427         throw new NoSuchElementException();
 428     }
 429 
 430     /**
 431      * Returns the element at the specified location in this vector.
 432      *
 433      * @param location
 434      *            the index of the element to return in this vector.
 435      * @return the element at the specified location.
 436      * @throws ArrayIndexOutOfBoundsException
 437      *                if {@code location < 0 || location >= size()}.
 438      * @see #size
 439      */
 440     @Override
 441     public E get(int location) {
 442         return elementAt(location);
 443     }
 444 
 445     private void grow(int newCapacity) {
 446         E[] newData = newElementArray(newCapacity);
 447         // Assumes elementCount is <= newCapacity
 448         assert elementCount <= newCapacity;
 449         System.arraycopy(elementData, 0, newData, 0, elementCount);
 450         elementData = newData;
 451     }
 452 
 453     /**
 454      * JIT optimization
 455      */
 456     private void growByOne() {
 457         int adding = 0;
 458         if (capacityIncrement <= 0) {
 459             if ((adding = elementData.length) == 0) {
 460                 adding = 1;
 461             }
 462         } else {
 463             adding = capacityIncrement;
 464         }
 465 
 466         E[] newData = newElementArray(elementData.length + adding);
 467         System.arraycopy(elementData, 0, newData, 0, elementCount);
 468         elementData = newData;
 469     }
 470 
 471     private void growBy(int required) {
 472         int adding = 0;
 473         if (capacityIncrement <= 0) {
 474             if ((adding = elementData.length) == 0) {
 475                 adding = required;
 476             }
 477             while (adding < required) {
 478                 adding += adding;
 479             }
 480         } else {
 481             adding = (required / capacityIncrement) * capacityIncrement;
 482             if (adding < required) {
 483                 adding += capacityIncrement;
 484             }
 485         }
 486         E[] newData = newElementArray(elementData.length + adding);
 487         System.arraycopy(elementData, 0, newData, 0, elementCount);
 488         elementData = newData;
 489     }
 490 
 491     /**
 492      * Returns an integer hash code for the receiver. Objects which are equal
 493      * return the same value for this method.
 494      *
 495      * @return the receiver's hash.
 496      * @see #equals
 497      */
 498     @Override
 499     public synchronized int hashCode() {
 500         int result = 1;
 501         for (int i = 0; i < elementCount; i++) {
 502             result = (31 * result)
 503                     + (elementData[i] == null ? 0 : elementData[i].hashCode());
 504         }
 505         return result;
 506     }
 507 
 508     /**
 509      * Searches in this vector for the index of the specified object. The search
 510      * for the object starts at the beginning and moves towards the end of this
 511      * vector.
 512      *
 513      * @param object
 514      *            the object to find in this vector.
 515      * @return the index in this vector of the specified element, -1 if the
 516      *         element isn't found.
 517      * @see #contains
 518      * @see #lastIndexOf(Object)
 519      * @see #lastIndexOf(Object, int)
 520      */
 521     @Override
 522     public int indexOf(Object object) {
 523         return indexOf(object, 0);
 524     }
 525 
 526     /**
 527      * Searches in this vector for the index of the specified object. The search
 528      * for the object starts at the specified location and moves towards the end
 529      * of this vector.
 530      *
 531      * @param object
 532      *            the object to find in this vector.
 533      * @param location
 534      *            the index at which to start searching.
 535      * @return the index in this vector of the specified element, -1 if the
 536      *         element isn't found.
 537      * @throws ArrayIndexOutOfBoundsException
 538      *                if {@code location < 0}.
 539      * @see #contains
 540      * @see #lastIndexOf(Object)
 541      * @see #lastIndexOf(Object, int)
 542      */
 543     public synchronized int indexOf(Object object, int location) {
 544         if (object != null) {
 545             for (int i = location; i < elementCount; i++) {
 546                 if (object.equals(elementData[i])) {
 547                     return i;
 548                 }
 549             }
 550         } else {
 551             for (int i = location; i < elementCount; i++) {
 552                 if (elementData[i] == null) {
 553                     return i;
 554                 }
 555             }
 556         }
 557         return -1;
 558     }
 559 
 560     /**
 561      * Inserts the specified object into this vector at the specified location.
 562      * This object is inserted before any previous element at the specified
 563      * location. All elements with an index equal or greater than
 564      * {@code location} have their index increased by 1. If the location is
 565      * equal to the size of this vector, the object is added at the end.
 566      *
 567      * @param object
 568      *            the object to insert in this vector.
 569      * @param location
 570      *            the index at which to insert the element.
 571      * @throws ArrayIndexOutOfBoundsException
 572      *                if {@code location < 0 || location > size()}.
 573      * @see #addElement
 574      * @see #size
 575      */
 576     public synchronized void insertElementAt(E object, int location) {
 577         if (location >= 0 && location <= elementCount) {
 578             if (elementCount == elementData.length) {
 579                 growByOne();
 580             }
 581             int count = elementCount - location;
 582             if (count > 0) {
 583                 System.arraycopy(elementData, location, elementData,
 584                         location + 1, count);
 585             }
 586             elementData[location] = object;
 587             elementCount++;
 588             modCount++;
 589         } else {
 590             throw arrayIndexOutOfBoundsException(location, elementCount);
 591         }
 592     }
 593 
 594     /**
 595      * Returns if this vector has no elements, a size of zero.
 596      *
 597      * @return {@code true} if this vector has no elements, {@code false}
 598      *         otherwise.
 599      * @see #size
 600      */
 601     @Override
 602     public synchronized boolean isEmpty() {
 603         return elementCount == 0;
 604     }
 605 
 606     /**
 607      * Returns the last element in this vector.
 608      *
 609      * @return the element at the last position.
 610      * @throws NoSuchElementException
 611      *                if this vector is empty.
 612      * @see #elementAt
 613      * @see #firstElement
 614      * @see #size
 615      */
 616     @SuppressWarnings("unchecked")
 617     public synchronized E lastElement() {
 618         try {
 619             return (E) elementData[elementCount - 1];
 620         } catch (IndexOutOfBoundsException e) {
 621             throw new NoSuchElementException();
 622         }
 623     }
 624 
 625     /**
 626      * Searches in this vector for the index of the specified object. The search
 627      * for the object starts at the end and moves towards the start of this
 628      * vector.
 629      *
 630      * @param object
 631      *            the object to find in this vector.
 632      * @return the index in this vector of the specified element, -1 if the
 633      *         element isn't found.
 634      * @see #contains
 635      * @see #indexOf(Object)
 636      * @see #indexOf(Object, int)
 637      */
 638     @Override
 639     public synchronized int lastIndexOf(Object object) {
 640         return lastIndexOf(object, elementCount - 1);
 641     }
 642 
 643     /**
 644      * Searches in this vector for the index of the specified object. The search
 645      * for the object starts at the specified location and moves towards the
 646      * start of this vector.
 647      *
 648      * @param object
 649      *            the object to find in this vector.
 650      * @param location
 651      *            the index at which to start searching.
 652      * @return the index in this vector of the specified element, -1 if the
 653      *         element isn't found.
 654      * @throws ArrayIndexOutOfBoundsException
 655      *                if {@code location >= size()}.
 656      * @see #contains
 657      * @see #indexOf(Object)
 658      * @see #indexOf(Object, int)
 659      */
 660     public synchronized int lastIndexOf(Object object, int location) {
 661         if (location < elementCount) {
 662             if (object != null) {
 663                 for (int i = location; i >= 0; i--) {
 664                     if (object.equals(elementData[i])) {
 665                         return i;
 666                     }
 667                 }
 668             } else {
 669                 for (int i = location; i >= 0; i--) {
 670                     if (elementData[i] == null) {
 671                         return i;
 672                     }
 673                 }
 674             }
 675             return -1;
 676         }
 677         throw arrayIndexOutOfBoundsException(location, elementCount);
 678     }
 679 
 680     /**
 681      * Removes the object at the specified location from this vector. All
 682      * elements with an index bigger than {@code location} have their index
 683      * decreased by 1.
 684      *
 685      * @param location
 686      *            the index of the object to remove.
 687      * @return the removed object.
 688      * @throws IndexOutOfBoundsException
 689      *                if {@code location < 0 || location >= size()}.
 690      */
 691     @SuppressWarnings("unchecked")
 692     @Override
 693     public synchronized E remove(int location) {
 694         if (location < elementCount) {
 695             E result = (E) elementData[location];
 696             elementCount--;
 697             int size = elementCount - location;
 698             if (size > 0) {
 699                 System.arraycopy(elementData, location + 1, elementData,
 700                         location, size);
 701             }
 702             elementData[elementCount] = null;
 703             modCount++;
 704             return result;
 705         }
 706         throw arrayIndexOutOfBoundsException(location, elementCount);
 707     }
 708 
 709     /**
 710      * Removes the first occurrence, starting at the beginning and moving
 711      * towards the end, of the specified object from this vector. All elements
 712      * with an index bigger than the element that gets removed have their index
 713      * decreased by 1.
 714      *
 715      * @param object
 716      *            the object to remove from this vector.
 717      * @return {@code true} if the specified object was found, {@code false}
 718      *         otherwise.
 719      * @see #removeAllElements
 720      * @see #removeElementAt
 721      * @see #size
 722      */
 723     @Override
 724     public boolean remove(Object object) {
 725         return removeElement(object);
 726     }
 727 
 728     /**
 729      * Removes all occurrences in this vector of each object in the specified
 730      * Collection.
 731      *
 732      * @param collection
 733      *            the collection of objects to remove.
 734      * @return {@code true} if this vector is modified, {@code false} otherwise.
 735      * @see #remove(Object)
 736      * @see #contains(Object)
 737      */
 738     @Override
 739     public synchronized boolean removeAll(Collection<?> collection) {
 740         return super.removeAll(collection);
 741     }
 742 
 743     /**
 744      * Removes all elements from this vector, leaving the size zero and the
 745      * capacity unchanged.
 746      *
 747      * @see #isEmpty
 748      * @see #size
 749      */
 750     public synchronized void removeAllElements() {
 751         for (int i = 0; i < elementCount; i++) {
 752             elementData[i] = null;
 753         }
 754         modCount++;
 755         elementCount = 0;
 756     }
 757 
 758     /**
 759      * Removes the first occurrence, starting at the beginning and moving
 760      * towards the end, of the specified object from this vector. All elements
 761      * with an index bigger than the element that gets removed have their index
 762      * decreased by 1.
 763      *
 764      * @param object
 765      *            the object to remove from this vector.
 766      * @return {@code true} if the specified object was found, {@code false}
 767      *         otherwise.
 768      * @see #removeAllElements
 769      * @see #removeElementAt
 770      * @see #size
 771      */
 772     public synchronized boolean removeElement(Object object) {
 773         int index;
 774         if ((index = indexOf(object, 0)) == -1) {
 775             return false;
 776         }
 777         removeElementAt(index);
 778         return true;
 779     }
 780 
 781     /**
 782      * Removes the element found at index position {@code location} from
 783      * this {@code Vector}. All elements with an index bigger than
 784      * {@code location} have their index decreased by 1.
 785      *
 786      * @param location
 787      *            the index of the element to remove.
 788      * @throws ArrayIndexOutOfBoundsException
 789      *                if {@code location < 0 || location >= size()}.
 790      * @see #removeElement
 791      * @see #removeAllElements
 792      * @see #size
 793      */
 794     public synchronized void removeElementAt(int location) {
 795         if (location >= 0 && location < elementCount) {
 796             elementCount--;
 797             int size = elementCount - location;
 798             if (size > 0) {
 799                 System.arraycopy(elementData, location + 1, elementData,
 800                         location, size);
 801             }
 802             elementData[elementCount] = null;
 803             modCount++;
 804         } else {
 805             throw arrayIndexOutOfBoundsException(location, elementCount);
 806         }
 807     }
 808 
 809     /**
 810      * Removes the objects in the specified range from the start to the, but not
 811      * including, end index. All elements with an index bigger than or equal to
 812      * {@code end} have their index decreased by {@code end - start}.
 813      *
 814      * @param start
 815      *            the index at which to start removing.
 816      * @param end
 817      *            the index one past the end of the range to remove.
 818      * @throws IndexOutOfBoundsException
 819      *                if {@code start < 0, start > end} or
 820      *                {@code end > size()}.
 821      */
 822     @Override
 823     protected void removeRange(int start, int end) {
 824         if (start >= 0 && start <= end && end <= elementCount) {
 825             if (start == end) {
 826                 return;
 827             }
 828             if (end != elementCount) {
 829                 System.arraycopy(elementData, end, elementData, start,
 830                         elementCount - end);
 831                 int newCount = elementCount - (end - start);
 832                 Arrays.fill(elementData, newCount, elementCount, null);
 833                 elementCount = newCount;
 834             } else {
 835                 Arrays.fill(elementData, start, elementCount, null);
 836                 elementCount = start;
 837             }
 838             modCount++;
 839         } else {
 840             throw new IndexOutOfBoundsException();
 841         }
 842     }
 843 
 844     /**
 845      * Removes all objects from this vector that are not contained in the
 846      * specified collection.
 847      *
 848      * @param collection
 849      *            the collection of objects to retain.
 850      * @return {@code true} if this vector is modified, {@code false} otherwise.
 851      * @see #remove(Object)
 852      */
 853     @Override
 854     public synchronized boolean retainAll(Collection<?> collection) {
 855         return super.retainAll(collection);
 856     }
 857 
 858     /**
 859      * Replaces the element at the specified location in this vector with the
 860      * specified object.
 861      *
 862      * @param location
 863      *            the index at which to put the specified object.
 864      * @param object
 865      *            the object to add to this vector.
 866      * @return the previous element at the location.
 867      * @throws ArrayIndexOutOfBoundsException
 868      *                if {@code location < 0 || location >= size()}.
 869      * @see #size
 870      */
 871     @SuppressWarnings("unchecked")
 872     @Override
 873     public synchronized E set(int location, E object) {
 874         if (location < elementCount) {
 875             E result = (E) elementData[location];
 876             elementData[location] = object;
 877             return result;
 878         }
 879         throw arrayIndexOutOfBoundsException(location, elementCount);
 880     }
 881 
 882     /**
 883      * Replaces the element at the specified location in this vector with the
 884      * specified object.
 885      *
 886      * @param object
 887      *            the object to add to this vector.
 888      * @param location
 889      *            the index at which to put the specified object.
 890      * @throws ArrayIndexOutOfBoundsException
 891      *                if {@code location < 0 || location >= size()}.
 892      * @see #size
 893      */
 894     public synchronized void setElementAt(E object, int location) {
 895         if (location < elementCount) {
 896             elementData[location] = object;
 897         } else {
 898             throw arrayIndexOutOfBoundsException(location, elementCount);
 899         }
 900     }
 901 
 902     /**
 903      * This method was extracted to encourage VM to inline callers.
 904      * TODO: when we have a VM that can actually inline, move the test in here too!
 905      */
 906     private static ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException(int index, int size) {
 907         throw new ArrayIndexOutOfBoundsException(size, index);
 908     }
 909 
 910     /**
 911      * Sets the size of this vector to the specified size. If there are more
 912      * than length elements in this vector, the elements at end are lost. If
 913      * there are less than length elements in the vector, the additional
 914      * elements contain null.
 915      *
 916      * @param length
 917      *            the new size of this vector.
 918      * @see #size
 919      */
 920     public synchronized void setSize(int length) {
 921         if (length == elementCount) {
 922             return;
 923         }
 924         ensureCapacity(length);
 925         if (elementCount > length) {
 926             Arrays.fill(elementData, length, elementCount, null);
 927         }
 928         elementCount = length;
 929         modCount++;
 930     }
 931 
 932     /**
 933      * Returns the number of elements in this vector.
 934      *
 935      * @return the number of elements in this vector.
 936      * @see #elementCount
 937      * @see #lastElement
 938      */
 939     @Override
 940     public synchronized int size() {
 941         return elementCount;
 942     }
 943 
 944     /**
 945      * Returns a List of the specified portion of this vector from the start
 946      * index to one less than the end index. The returned List is backed by this
 947      * vector so changes to one are reflected by the other.
 948      *
 949      * @param start
 950      *            the index at which to start the sublist.
 951      * @param end
 952      *            the index one past the end of the sublist.
 953      * @return a List of a portion of this vector.
 954      * @throws IndexOutOfBoundsException
 955      *                if {@code start < 0} or {@code end > size()}.
 956      * @throws IllegalArgumentException
 957      *                if {@code start > end}.
 958      */
 959     @Override
 960     public synchronized List<E> subList(int start, int end) {
 961         return new Collections.SynchronizedRandomAccessList<E>(super.subList(
 962                 start, end), this);
 963     }
 964 
 965     /**
 966      * Returns a new array containing all elements contained in this vector.
 967      *
 968      * @return an array of the elements from this vector.
 969      */
 970     @Override
 971     public synchronized Object[] toArray() {
 972         Object[] result = new Object[elementCount];
 973         System.arraycopy(elementData, 0, result, 0, elementCount);
 974         return result;
 975     }
 976 
 977     /**
 978      * Returns an array containing all elements contained in this vector. If the
 979      * specified array is large enough to hold the elements, the specified array
 980      * is used, otherwise an array of the same type is created. If the specified
 981      * array is used and is larger than this vector, the array element following
 982      * the collection elements is set to null.
 983      *
 984      * @param contents
 985      *            the array to fill.
 986      * @return an array of the elements from this vector.
 987      * @throws ArrayStoreException
 988      *                if the type of an element in this vector cannot be
 989      *                stored in the type of the specified array.
 990      */
 991     @Override
 992     @SuppressWarnings("unchecked")
 993     public synchronized <T> T[] toArray(T[] contents) {
 994         if (elementCount > contents.length) {
 995             Class<?> ct = contents.getClass().getComponentType();
 996             contents = (T[]) Array.newInstance(ct, elementCount);
 997         }
 998         System.arraycopy(elementData, 0, contents, 0, elementCount);
 999         if (elementCount < contents.length) {
1000             contents[elementCount] = null;
1001         }
1002         return contents;
1003     }
1004 
1005     /**
1006      * Returns the string representation of this vector.
1007      *
1008      * @return the string representation of this vector.
1009      * @see #elements
1010      */
1011     @Override
1012     public synchronized String toString() {
1013         if (elementCount == 0) {
1014             return "[]";
1015         }
1016         int length = elementCount - 1;
1017         StringBuilder buffer = new StringBuilder(elementCount * 16);
1018         buffer.append('[');
1019         for (int i = 0; i < length; i++) {
1020             if (elementData[i] == this) {
1021                 buffer.append("(this Collection)");
1022             } else {
1023                 buffer.append(elementData[i]);
1024             }
1025             buffer.append(", ");
1026         }
1027         if (elementData[length] == this) {
1028             buffer.append("(this Collection)");
1029         } else {
1030             buffer.append(elementData[length]);
1031         }
1032         buffer.append(']');
1033         return buffer.toString();
1034     }
1035 
1036     /**
1037      * Sets the capacity of this vector to be the same as the size.
1038      *
1039      * @see #capacity
1040      * @see #ensureCapacity
1041      * @see #size
1042      */
1043     public synchronized void trimToSize() {
1044         if (elementData.length != elementCount) {
1045             grow(elementCount);
1046         }
1047     }
1048 
1049     private synchronized void writeObject(ObjectOutputStream stream)
1050             throws IOException {
1051         stream.defaultWriteObject();
1052     }
1053 }
View Code

ArrayList

  1 /*
  2  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3  *  contributor license agreements.  See the NOTICE file distributed with
  4  *  this work for additional information regarding copyright ownership.
  5  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6  *  (the "License"); you may not use this file except in compliance with
  7  *  the License.  You may obtain a copy of the License at
  8  *
  9  *     http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  *  Unless required by applicable law or agreed to in writing, software
 12  *  distributed under the License is distributed on an "AS IS" BASIS,
 13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  *  See the License for the specific language governing permissions and
 15  *  limitations under the License.
 16  */
 17 
 18 package java.util;
 19 
 20 import java.io.IOException;
 21 import java.io.InvalidObjectException;
 22 import java.io.ObjectInputStream;
 23 import java.io.ObjectOutputStream;
 24 import java.io.Serializable;
 25 import java.lang.reflect.Array;
 26 import libcore.util.EmptyArray;
 27 
 28 /**
 29  * ArrayList is an implementation of {@link List}, backed by an array.
 30  * All optional operations including adding, removing, and replacing elements are supported.
 31  *
 32  * <p>All elements are permitted, including null.
 33  *
 34  * <p>This class is a good choice as your default {@code List} implementation.
 35  * {@link Vector} synchronizes all operations, but not necessarily in a way that's
 36  * meaningful to your application: synchronizing each call to {@code get}, for example, is not
 37  * equivalent to synchronizing the list and iterating over it (which is probably what you intended).
 38  * {@link java.util.concurrent.CopyOnWriteArrayList} is intended for the special case of very high
 39  * concurrency, frequent traversals, and very rare mutations.
 40  *
 41  * @param <E> The element type of this list.
 42  * @since 1.2
 43  */
 44 public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess {
 45     /**
 46      * The minimum amount by which the capacity of an ArrayList will increase.
 47      * This tuning parameter controls a time-space tradeoff. This value (12)
 48      * gives empirically good results and is arguably consistent with the
 49      * RI's specified default initial capacity of 10: instead of 10, we start
 50      * with 0 (sans allocation) and jump to 12.
 51      */
 52     private static final int MIN_CAPACITY_INCREMENT = 12;
 53 
 54     /**
 55      * The number of elements in this list.
 56      */
 57     int size;
 58 
 59     /**
 60      * The elements in this list, followed by nulls.
 61      */
 62     transient Object[] array;
 63 
 64     /**
 65      * Constructs a new instance of {@code ArrayList} with the specified
 66      * initial capacity.
 67      *
 68      * @param capacity
 69      *            the initial capacity of this {@code ArrayList}.
 70      */
 71     public ArrayList(int capacity) {
 72         if (capacity < 0) {
 73             throw new IllegalArgumentException();
 74         }
 75         array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
 76     }
 77 
 78     /**
 79      * Constructs a new {@code ArrayList} instance with zero initial capacity.
 80      */
 81     public ArrayList() {
 82         array = EmptyArray.OBJECT;
 83     }
 84 
 85     /**
 86      * Constructs a new instance of {@code ArrayList} containing the elements of
 87      * the specified collection.
 88      *
 89      * @param collection
 90      *            the collection of elements to add.
 91      */
 92     public ArrayList(Collection<? extends E> collection) {
 93         Object[] a = collection.toArray();
 94         if (a.getClass() != Object[].class) {
 95             Object[] newArray = new Object[a.length];
 96             System.arraycopy(a, 0, newArray, 0, a.length);
 97             a = newArray;
 98         }
 99         array = a;
100         size = a.length;
101     }
102 
103     /**
104      * Adds the specified object at the end of this {@code ArrayList}.
105      *
106      * @param object
107      *            the object to add.
108      * @return always true
109      */
110     @Override public boolean add(E object) {
111         Object[] a = array;
112         int s = size;
113         if (s == a.length) {
114             Object[] newArray = new Object[s +
115                     (s < (MIN_CAPACITY_INCREMENT / 2) ?
116                      MIN_CAPACITY_INCREMENT : s >> 1)];
117             System.arraycopy(a, 0, newArray, 0, s);
118             array = a = newArray;
119         }
120         a[s] = object;
121         size = s + 1;
122         modCount++;
123         return true;
124     }
125 
126     /**
127      * Inserts the specified object into this {@code ArrayList} at the specified
128      * location. The object is inserted before any previous element at the
129      * specified location. If the location is equal to the size of this
130      * {@code ArrayList}, the object is added at the end.
131      *
132      * @param index
133      *            the index at which to insert the object.
134      * @param object
135      *            the object to add.
136      * @throws IndexOutOfBoundsException
137      *             when {@code location < 0 || > size()}
138      */
139     @Override public void add(int index, E object) {
140         Object[] a = array;
141         int s = size;
142         if (index > s || index < 0) {
143             throwIndexOutOfBoundsException(index, s);
144         }
145 
146         if (s < a.length) {
147             System.arraycopy(a, index, a, index + 1, s - index);
148         } else {
149             // assert s == a.length;
150             Object[] newArray = new Object[newCapacity(s)];
151             System.arraycopy(a, 0, newArray, 0, index);
152             System.arraycopy(a, index, newArray, index + 1, s - index);
153             array = a = newArray;
154         }
155         a[index] = object;
156         size = s + 1;
157         modCount++;
158     }
159 
160     /**
161      * This method controls the growth of ArrayList capacities.  It represents
162      * a time-space tradeoff: we don't want to grow lists too frequently
163      * (which wastes time and fragments storage), but we don't want to waste
164      * too much space in unused excess capacity.
165      *
166      * NOTE: This method is inlined into {@link #add(Object)} for performance.
167      * If you change the method, change it there too!
168      */
169     private static int newCapacity(int currentCapacity) {
170         int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
171                 MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
172         return currentCapacity + increment;
173     }
174 
175     /**
176      * Adds the objects in the specified collection to this {@code ArrayList}.
177      *
178      * @param collection
179      *            the collection of objects.
180      * @return {@code true} if this {@code ArrayList} is modified, {@code false}
181      *         otherwise.
182      */
183     @Override public boolean addAll(Collection<? extends E> collection) {
184         Object[] newPart = collection.toArray();
185         int newPartSize = newPart.length;
186         if (newPartSize == 0) {
187             return false;
188         }
189         Object[] a = array;
190         int s = size;
191         int newSize = s + newPartSize; // If add overflows, arraycopy will fail
192         if (newSize > a.length) {
193             int newCapacity = newCapacity(newSize - 1);  // ~33% growth room
194             Object[] newArray = new Object[newCapacity];
195             System.arraycopy(a, 0, newArray, 0, s);
196             array = a = newArray;
197         }
198         System.arraycopy(newPart, 0, a, s, newPartSize);
199         size = newSize;
200         modCount++;
201         return true;
202     }
203 
204     /**
205      * Inserts the objects in the specified collection at the specified location
206      * in this List. The objects are added in the order they are returned from
207      * the collection's iterator.
208      *
209      * @param index
210      *            the index at which to insert.
211      * @param collection
212      *            the collection of objects.
213      * @return {@code true} if this {@code ArrayList} is modified, {@code false}
214      *         otherwise.
215      * @throws IndexOutOfBoundsException
216      *             when {@code location < 0 || > size()}
217      */
218     @Override
219     public boolean addAll(int index, Collection<? extends E> collection) {
220         int s = size;
221         if (index > s || index < 0) {
222             throwIndexOutOfBoundsException(index, s);
223         }
224         Object[] newPart = collection.toArray();
225         int newPartSize = newPart.length;
226         if (newPartSize == 0) {
227             return false;
228         }
229         Object[] a = array;
230         int newSize = s + newPartSize; // If add overflows, arraycopy will fail
231         if (newSize <= a.length) {
232              System.arraycopy(a, index, a, index + newPartSize, s - index);
233         } else {
234             int newCapacity = newCapacity(newSize - 1);  // ~33% growth room
235             Object[] newArray = new Object[newCapacity];
236             System.arraycopy(a, 0, newArray, 0, index);
237             System.arraycopy(a, index, newArray, index + newPartSize, s-index);
238             array = a = newArray;
239         }
240         System.arraycopy(newPart, 0, a, index, newPartSize);
241         size = newSize;
242         modCount++;
243         return true;
244     }
245 
246     /**
247      * This method was extracted to encourage VM to inline callers.
248      * TODO: when we have a VM that can actually inline, move the test in here too!
249      */
250     static IndexOutOfBoundsException throwIndexOutOfBoundsException(int index, int size) {
251         throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + size);
252     }
253 
254     /**
255      * Removes all elements from this {@code ArrayList}, leaving it empty.
256      *
257      * @see #isEmpty
258      * @see #size
259      */
260     @Override public void clear() {
261         if (size != 0) {
262             Arrays.fill(array, 0, size, null);
263             size = 0;
264             modCount++;
265         }
266     }
267 
268     /**
269      * Returns a new {@code ArrayList} with the same elements, the same size and
270      * the same capacity as this {@code ArrayList}.
271      *
272      * @return a shallow copy of this {@code ArrayList}
273      * @see java.lang.Cloneable
274      */
275     @Override public Object clone() {
276         try {
277             ArrayList<?> result = (ArrayList<?>) super.clone();
278             result.array = array.clone();
279             return result;
280         } catch (CloneNotSupportedException e) {
281            throw new AssertionError();
282         }
283     }
284 
285     /**
286      * Ensures that after this operation the {@code ArrayList} can hold the
287      * specified number of elements without further growing.
288      *
289      * @param minimumCapacity
290      *            the minimum capacity asked for.
291      */
292     public void ensureCapacity(int minimumCapacity) {
293         Object[] a = array;
294         if (a.length < minimumCapacity) {
295             Object[] newArray = new Object[minimumCapacity];
296             System.arraycopy(a, 0, newArray, 0, size);
297             array = newArray;
298             modCount++;
299         }
300     }
301 
302     @SuppressWarnings("unchecked") @Override public E get(int index) {
303         if (index >= size) {
304             throwIndexOutOfBoundsException(index, size);
305         }
306         return (E) array[index];
307     }
308 
309     /**
310      * Returns the number of elements in this {@code ArrayList}.
311      *
312      * @return the number of elements in this {@code ArrayList}.
313      */
314     @Override public int size() {
315         return size;
316     }
317 
318     @Override public boolean isEmpty() {
319         return size == 0;
320     }
321 
322     /**
323      * Searches this {@code ArrayList} for the specified object.
324      *
325      * @param object
326      *            the object to search for.
327      * @return {@code true} if {@code object} is an element of this
328      *         {@code ArrayList}, {@code false} otherwise
329      */
330     @Override public boolean contains(Object object) {
331         Object[] a = array;
332         int s = size;
333         if (object != null) {
334             for (int i = 0; i < s; i++) {
335                 if (object.equals(a[i])) {
336                     return true;
337                 }
338             }
339         } else {
340             for (int i = 0; i < s; i++) {
341                 if (a[i] == null) {
342                     return true;
343                 }
344             }
345         }
346         return false;
347     }
348 
349     @Override public int indexOf(Object object) {
350         Object[] a = array;
351         int s = size;
352         if (object != null) {
353             for (int i = 0; i < s; i++) {
354                 if (object.equals(a[i])) {
355                     return i;
356                 }
357             }
358         } else {
359             for (int i = 0; i < s; i++) {
360                 if (a[i] == null) {
361                     return i;
362                 }
363             }
364         }
365         return -1;
366     }
367 
368     @Override public int lastIndexOf(Object object) {
369         Object[] a = array;
370         if (object != null) {
371             for (int i = size - 1; i >= 0; i--) {
372                 if (object.equals(a[i])) {
373                     return i;
374                 }
375             }
376         } else {
377             for (int i = size - 1; i >= 0; i--) {
378                 if (a[i] == null) {
379                     return i;
380                 }
381             }
382         }
383         return -1;
384     }
385 
386     /**
387      * Removes the object at the specified location from this list.
388      *
389      * @param index
390      *            the index of the object to remove.
391      * @return the removed object.
392      * @throws IndexOutOfBoundsException
393      *             when {@code location < 0 || >= size()}
394      */
395     @Override public E remove(int index) {
396         Object[] a = array;
397         int s = size;
398         if (index >= s) {
399             throwIndexOutOfBoundsException(index, s);
400         }
401         @SuppressWarnings("unchecked") E result = (E) a[index];
402         System.arraycopy(a, index + 1, a, index, --s - index);
403         a[s] = null;  // Prevent memory leak
404         size = s;
405         modCount++;
406         return result;
407     }
408 
409     @Override public boolean remove(Object object) {
410         Object[] a = array;
411         int s = size;
412         if (object != null) {
413             for (int i = 0; i < s; i++) {
414                 if (object.equals(a[i])) {
415                     System.arraycopy(a, i + 1, a, i, --s - i);
416                     a[s] = null;  // Prevent memory leak
417                     size = s;
418                     modCount++;
419                     return true;
420                 }
421             }
422         } else {
423             for (int i = 0; i < s; i++) {
424                 if (a[i] == null) {
425                     System.arraycopy(a, i + 1, a, i, --s - i);
426                     a[s] = null;  // Prevent memory leak
427                     size = s;
428                     modCount++;
429                     return true;
430                 }
431             }
432         }
433         return false;
434     }
435 
436     @Override protected void removeRange(int fromIndex, int toIndex) {
437         if (fromIndex == toIndex) {
438             return;
439         }
440         Object[] a = array;
441         int s = size;
442         if (fromIndex >= s) {
443             throw new IndexOutOfBoundsException("fromIndex " + fromIndex
444                     + " >= size " + size);
445         }
446         if (toIndex > s) {
447             throw new IndexOutOfBoundsException("toIndex " + toIndex
448                     + " > size " + size);
449         }
450         if (fromIndex > toIndex) {
451             throw new IndexOutOfBoundsException("fromIndex " + fromIndex
452                     + " > toIndex " + toIndex);
453         }
454 
455         System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);
456         int rangeSize = toIndex - fromIndex;
457         Arrays.fill(a, s - rangeSize, s, null);
458         size = s - rangeSize;
459         modCount++;
460     }
461 
462     /**
463      * Replaces the element at the specified location in this {@code ArrayList}
464      * with the specified object.
465      *
466      * @param index
467      *            the index at which to put the specified object.
468      * @param object
469      *            the object to add.
470      * @return the previous element at the index.
471      * @throws IndexOutOfBoundsException
472      *             when {@code location < 0 || >= size()}
473      */
474     @Override public E set(int index, E object) {
475         Object[] a = array;
476         if (index >= size) {
477             throwIndexOutOfBoundsException(index, size);
478         }
479         @SuppressWarnings("unchecked") E result = (E) a[index];
480         a[index] = object;
481         return result;
482     }
483 
484     /**
485      * Returns a new array containing all elements contained in this
486      * {@code ArrayList}.
487      *
488      * @return an array of the elements from this {@code ArrayList}
489      */
490     @Override public Object[] toArray() {
491         int s = size;
492         Object[] result = new Object[s];
493         System.arraycopy(array, 0, result, 0, s);
494         return result;
495     }
496 
497     /**
498      * Returns an array containing all elements contained in this
499      * {@code ArrayList}. If the specified array is large enough to hold the
500      * elements, the specified array is used, otherwise an array of the same
501      * type is created. If the specified array is used and is larger than this
502      * {@code ArrayList}, the array element following the collection elements
503      * is set to null.
504      *
505      * @param contents
506      *            the array.
507      * @return an array of the elements from this {@code ArrayList}.
508      * @throws ArrayStoreException
509      *             when the type of an element in this {@code ArrayList} cannot
510      *             be stored in the type of the specified array.
511      */
512     @Override public <T> T[] toArray(T[] contents) {
513         int s = size;
514         if (contents.length < s) {
515             @SuppressWarnings("unchecked") T[] newArray
516                 = (T[]) Array.newInstance(contents.getClass().getComponentType(), s);
517             contents = newArray;
518         }
519         System.arraycopy(this.array, 0, contents, 0, s);
520         if (contents.length > s) {
521             contents[s] = null;
522         }
523         return contents;
524     }
525 
526     /**
527      * Sets the capacity of this {@code ArrayList} to be the same as the current
528      * size.
529      *
530      * @see #size
531      */
532     public void trimToSize() {
533         int s = size;
534         if (s == array.length) {
535             return;
536         }
537         if (s == 0) {
538             array = EmptyArray.OBJECT;
539         } else {
540             Object[] newArray = new Object[s];
541             System.arraycopy(array, 0, newArray, 0, s);
542             array = newArray;
543         }
544         modCount++;
545     }
546 
547     @Override public Iterator<E> iterator() {
548         return new ArrayListIterator();
549     }
550 
551     private class ArrayListIterator implements Iterator<E> {
552         /** Number of elements remaining in this iteration */
553         private int remaining = size;
554 
555         /** Index of element that remove() would remove, or -1 if no such elt */
556         private int removalIndex = -1;
557 
558         /** The expected modCount value */
559         private int expectedModCount = modCount;
560 
561         public boolean hasNext() {
562             return remaining != 0;
563         }
564 
565         @SuppressWarnings("unchecked") public E next() {
566             ArrayList<E> ourList = ArrayList.this;
567             int rem = remaining;
568             if (ourList.modCount != expectedModCount) {
569                 throw new ConcurrentModificationException();
570             }
571             if (rem == 0) {
572                 throw new NoSuchElementException();
573             }
574             remaining = rem - 1;
575             return (E) ourList.array[removalIndex = ourList.size - rem];
576         }
577 
578         public void remove() {
579             Object[] a = array;
580             int removalIdx = removalIndex;
581             if (modCount != expectedModCount) {
582                 throw new ConcurrentModificationException();
583             }
584             if (removalIdx < 0) {
585                 throw new IllegalStateException();
586             }
587             System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
588             a[--size] = null;  // Prevent memory leak
589             removalIndex = -1;
590             expectedModCount = ++modCount;
591         }
592     }
593 
594     @Override public int hashCode() {
595         Object[] a = array;
596         int hashCode = 1;
597         for (int i = 0, s = size; i < s; i++) {
598             Object e = a[i];
599             hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
600         }
601         return hashCode;
602     }
603 
604     @Override public boolean equals(Object o) {
605         if (o == this) {
606             return true;
607         }
608         if (!(o instanceof List)) {
609             return false;
610         }
611         List<?> that = (List<?>) o;
612         int s = size;
613         if (that.size() != s) {
614             return false;
615         }
616         Object[] a = array;
617         if (that instanceof RandomAccess) {
618             for (int i = 0; i < s; i++) {
619                 Object eThis = a[i];
620                 Object ethat = that.get(i);
621                 if (eThis == null ? ethat != null : !eThis.equals(ethat)) {
622                     return false;
623                 }
624             }
625         } else {  // Argument list is not random access; use its iterator
626             Iterator<?> it = that.iterator();
627             for (int i = 0; i < s; i++) {
628                 Object eThis = a[i];
629                 Object eThat = it.next();
630                 if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
631                     return false;
632                 }
633             }
634         }
635         return true;
636     }
637 
638     private static final long serialVersionUID = 8683452581122892189L;
639 
640     private void writeObject(ObjectOutputStream stream) throws IOException {
641         stream.defaultWriteObject();
642         stream.writeInt(array.length);
643         for (int i = 0; i < size; i++) {
644             stream.writeObject(array[i]);
645         }
646     }
647 
648     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
649         stream.defaultReadObject();
650         int cap = stream.readInt();
651         if (cap < size) {
652             throw new InvalidObjectException(
653                     "Capacity: " + cap + " < size: " + size);
654         }
655         array = (cap == 0 ? EmptyArray.OBJECT : new Object[cap]);
656         for (int i = 0; i < size; i++) {
657             array[i] = stream.readObject();
658         }
659     }
660  }
View Code

 

 1 package java.util;
 2 public abstract class Dictionary<K, V> {   
 3     public Dictionary() {
 4     }
 5     public abstract Enumeration<V> elements();
 6     public abstract V get(Object key);
 7     public abstract boolean isEmpty();
 8     public abstract Enumeration<K> keys();
 9     public abstract V put(K key, V value);
10     public abstract V remove(Object key);
11     public abstract int size();
12 }
View Code

Map Interface

 1 package java.util;
 2 
 3 public interface Map<K,V> {
 4 
 5     /**
 6      * {@code Map.Entry} is a key/value mapping contained in a {@code Map}.
 7      */
 8     public static interface Entry<K,V> {     
 9         public boolean equals(Object object);
10         public K getKey();
11         public V getValue();
12         public int hashCode();
13         public V setValue(V object);
14     };
15     public void clear();    
16     public boolean containsKey(Object key);
17     public boolean containsValue(Object value);
18     public Set<Map.Entry<K,V>> entrySet();
19     public boolean equals(Object object);
20     public V get(Object key);
21     public int hashCode();
22     public boolean isEmpty();
23     public Set<K> keySet();
24     public V put(K key, V value);
25     public void putAll(Map<? extends K,? extends V> map);
26     public V remove(Object key);
27     public int size();
28     public Collection<V> values();
29 }
View Code

SortedMap Interface

 1 package java.util;
 2 
 3 public interface SortedMap<K,V> extends Map<K,V> {
 4     
 5     public Comparator<? super K> comparator();
 6     public K firstKey();
 7     public SortedMap<K,V> headMap(K endKey);
 8     public K lastKey();
 9     public SortedMap<K,V> subMap(K startKey, K endKey);
10     public SortedMap<K,V> tailMap(K startKey);
11 }
View Code

AbstractMap

  1 package java.util;
  2 import java.io.Serializable;
  3 public abstract class AbstractMap<K, V> implements Map<K, V> {
  4 
  5     // Lazily initialized key set.
  6     Set<K> keySet;
  7     Collection<V> valuesCollection;
  8     public static class SimpleImmutableEntry<K, V>
  9             implements Map.Entry<K, V>, Serializable {
 10         private static final long serialVersionUID = 7138329143949025153L;
 11 
 12         private final K key;
 13         private final V value;
 14 
 15         public SimpleImmutableEntry(K theKey, V theValue) {
 16             key = theKey;
 17             value = theValue;
 18         }
 19         public SimpleImmutableEntry(Map.Entry<? extends K, ? extends V> copyFrom) {
 20             key = copyFrom.getKey();
 21             value = copyFrom.getValue();
 22         }
 23         public K getKey() {
 24             return key;
 25         }
 26         public V getValue() {
 27             return value;
 28         }
 29         public V setValue(V object) {
 30             throw new UnsupportedOperationException();
 31         }
 32         @Override 
 33         public boolean equals(Object object) {
 34             if (this == object) {
 35                 return true;
 36             }
 37             if (object instanceof Map.Entry) {
 38                 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
 39                 return (key == null ? entry.getKey() == null : key.equals(entry
 40                         .getKey()))
 41                         && (value == null ? entry.getValue() == null : value
 42                                 .equals(entry.getValue()));
 43             }
 44             return false;
 45         }
 46         @Override public int hashCode() {
 47             return (key == null ? 0 : key.hashCode())
 48                     ^ (value == null ? 0 : value.hashCode());
 49         }
 50         @Override public String toString() {
 51             return key + "=" + value;
 52         }
 53     }
 54     public static class SimpleEntry<K, V> implements Map.Entry<K, V>, Serializable {
 55         private static final long serialVersionUID = -8499721149061103585L;
 56 
 57         private final K key;
 58         private V value;
 59 
 60         public SimpleEntry(K theKey, V theValue) {
 61             key = theKey;
 62             value = theValue;
 63         }
 64         public SimpleEntry(Map.Entry<? extends K, ? extends V> copyFrom) {
 65             key = copyFrom.getKey();
 66             value = copyFrom.getValue();
 67         }
 68         public K getKey() {
 69             return key;
 70         }
 71         public V getValue() {
 72             return value;
 73         }
 74         public V setValue(V object) {
 75             V result = value;
 76             value = object;
 77             return result;
 78         }
 79         @Override 
 80         public boolean equals(Object object) {
 81             if (this == object) {
 82                 return true;
 83             }
 84             if (object instanceof Map.Entry) {
 85                 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
 86                 return (key == null ? entry.getKey() == null : key.equals(entry
 87                         .getKey()))
 88                         && (value == null ? entry.getValue() == null : value
 89                                 .equals(entry.getValue()));
 90             }
 91             return false;
 92         }
 93         @Override 
 94         public int hashCode() {
 95             return (key == null ? 0 : key.hashCode())
 96                     ^ (value == null ? 0 : value.hashCode());
 97         }
 98         @Override 
 99         public String toString() {
100             return key + "=" + value;
101         }
102     }
103     protected AbstractMap() {
104     }
105 
106     public void clear() {
107         entrySet().clear();
108     }
109 
110     public boolean containsKey(Object key) {
111         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
112         if (key != null) {
113             while (it.hasNext()) {
114                 if (key.equals(it.next().getKey())) {
115                     return true;
116                 }
117             }
118         } else {
119             while (it.hasNext()) {
120                 if (it.next().getKey() == null) {
121                     return true;
122                 }
123             }
124         }
125         return false;
126     }
127     public boolean containsValue(Object value) {
128         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
129         if (value != null) {
130             while (it.hasNext()) {
131                 if (value.equals(it.next().getValue())) {
132                     return true;
133                 }
134             }
135         } else {
136             while (it.hasNext()) {
137                 if (it.next().getValue() == null) {
138                     return true;
139                 }
140             }
141         }
142         return false;
143     }
144 
145     public abstract Set<Map.Entry<K, V>> entrySet();
146     @Override 
147     public boolean equals(Object object) {
148         if (this == object) {
149             return true;
150         }
151         if (object instanceof Map) {
152             Map<?, ?> map = (Map<?, ?>) object;
153             if (size() != map.size()) {
154                 return false;
155             }
156 
157             try {
158                 for (Entry<K, V> entry : entrySet()) {
159                     K key = entry.getKey();
160                     V mine = entry.getValue();
161                     Object theirs = map.get(key);
162                     if (mine == null) {
163                         if (theirs != null || !map.containsKey(key)) {
164                             return false;
165                         }
166                     } else if (!mine.equals(theirs)) {
167                         return false;
168                     }
169                 }
170             } catch (NullPointerException ignored) {
171                 return false;
172             } catch (ClassCastException ignored) {
173                 return false;
174             }
175             return true;
176         }
177         return false;
178     }
179     public V get(Object key) {
180         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
181         if (key != null) {
182             while (it.hasNext()) {
183                 Map.Entry<K, V> entry = it.next();
184                 if (key.equals(entry.getKey())) {
185                     return entry.getValue();
186                 }
187             }
188         } else {
189             while (it.hasNext()) {
190                 Map.Entry<K, V> entry = it.next();
191                 if (entry.getKey() == null) {
192                     return entry.getValue();
193                 }
194             }
195         }
196         return null;
197     }
198     @Override public int hashCode() {
199         int result = 0;
200         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
201         while (it.hasNext()) {
202             result += it.next().hashCode();
203         }
204         return result;
205     }
206     public boolean isEmpty() {
207         return size() == 0;
208     }
209     public Set<K> keySet() {
210         if (keySet == null) {
211             keySet = new AbstractSet<K>() {
212                 @Override public boolean contains(Object object) {
213                     return containsKey(object);
214                 }
215 
216                 @Override public int size() {
217                     return AbstractMap.this.size();
218                 }
219 
220                 @Override public Iterator<K> iterator() {
221                     return new Iterator<K>() {
222                         Iterator<Map.Entry<K, V>> setIterator = entrySet().iterator();
223 
224                         public boolean hasNext() {
225                             return setIterator.hasNext();
226                         }
227 
228                         public K next() {
229                             return setIterator.next().getKey();
230                         }
231 
232                         public void remove() {
233                             setIterator.remove();
234                         }
235                     };
236                 }
237             };
238         }
239         return keySet;
240     }
241     public V put(K key, V value) {
242         throw new UnsupportedOperationException();
243     }
244     public void putAll(Map<? extends K, ? extends V> map) {
245         for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
246             put(entry.getKey(), entry.getValue());
247         }
248     }
249     public V remove(Object key) {
250         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
251         if (key != null) {
252             while (it.hasNext()) {
253                 Map.Entry<K, V> entry = it.next();
254                 if (key.equals(entry.getKey())) {
255                     it.remove();
256                     return entry.getValue();
257                 }
258             }
259         } else {
260             while (it.hasNext()) {
261                 Map.Entry<K, V> entry = it.next();
262                 if (entry.getKey() == null) {
263                     it.remove();
264                     return entry.getValue();
265                 }
266             }
267         }
268         return null;
269     }
270     public int size() {
271         return entrySet().size();
272     }
273     @Override public String toString() {
274         if (isEmpty()) {
275             return "{}";
276         }
277 
278         StringBuilder buffer = new StringBuilder(size() * 28);
279         buffer.append('{');
280         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
281         while (it.hasNext()) {
282             Map.Entry<K, V> entry = it.next();
283             Object key = entry.getKey();
284             if (key != this) {
285                 buffer.append(key);
286             } else {
287                 buffer.append("(this Map)");
288             }
289             buffer.append('=');
290             Object value = entry.getValue();
291             if (value != this) {
292                 buffer.append(value);
293             } else {
294                 buffer.append("(this Map)");
295             }
296             if (it.hasNext()) {
297                 buffer.append(", ");
298             }
299         }
300         buffer.append('}');
301         return buffer.toString();
302     }
303     public Collection<V> values() {
304         if (valuesCollection == null) {
305             valuesCollection = new AbstractCollection<V>() {
306                 @Override public int size() {
307                     return AbstractMap.this.size();
308                 }
309 
310                 @Override public boolean contains(Object object) {
311                     return containsValue(object);
312                 }
313 
314                 @Override public Iterator<V> iterator() {
315                     return new Iterator<V>() {
316                         Iterator<Map.Entry<K, V>> setIterator = entrySet().iterator();
317 
318                         public boolean hasNext() {
319                             return setIterator.hasNext();
320                         }
321 
322                         public V next() {
323                             return setIterator.next().getValue();
324                         }
325 
326                         public void remove() {
327                             setIterator.remove();
328                         }
329                     };
330                 }
331             };
332         }
333         return valuesCollection;
334     }
335     @SuppressWarnings("unchecked")
336     @Override 
337     protected Object clone() throws CloneNotSupportedException {
338         AbstractMap<K, V> result = (AbstractMap<K, V>) super.clone();
339         result.keySet = null;
340         result.valuesCollection = null;
341         return result;
342     }
343 }
View Code

 HashMap

   1 package java.util;
   2 import java.io.IOException;
   3 import java.io.InvalidObjectException;
   4 import java.io.ObjectInputStream;
   5 import java.io.ObjectOutputStream;
   6 import java.io.ObjectStreamField;
   7 import java.io.Serializable;
   8 import java.util.Map.Entry;
   9 
  10 import libcore.util.Objects;
  11 
  12 /**
  13  * HashMap is an implementation of {@link Map}. All optional operations are supported.
  14  *
  15  * <p>All elements are permitted as keys or values, including null.
  16  *
  17  * <p>Note that the iteration order for HashMap is non-deterministic. If you want
  18  * deterministic iteration, use {@link LinkedHashMap}.
  19  *
  20  * <p>Note: the implementation of {@code HashMap} is not synchronized.
  21  * If one thread of several threads accessing an instance modifies the map
  22  * structurally, access to the map needs to be synchronized. A structural
  23  * modification is an operation that adds or removes an entry. Changes in
  24  * the value of an entry are not structural changes.
  25  *
  26  * <p>The {@code Iterator} created by calling the {@code iterator} method
  27  * may throw a {@code ConcurrentModificationException} if the map is structurally
  28  * changed while an iterator is used to iterate over the elements. Only the
  29  * {@code remove} method that is provided by the iterator allows for removal of
  30  * elements during iteration. It is not possible to guarantee that this
  31  * mechanism works in all cases of unsynchronized concurrent modification. It
  32  * should only be used for debugging purposes.
  33  *
  34  * @param <K> the type of keys maintained by this map
  35  * @param <V> the type of mapped values
  36  */
  37 public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
  38     /**
  39      * Min capacity (other than zero) for a HashMap. Must be a power of two
  40      * greater than 1 (and less than 1 << 30).
  41      */
  42     private static final int MINIMUM_CAPACITY = 4;
  43 
  44     /**
  45      * Max capacity for a HashMap. Must be a power of two >= MINIMUM_CAPACITY.
  46      */
  47     private static final int MAXIMUM_CAPACITY = 1 << 30;
  48 
  49     /**
  50      * An empty table shared by all zero-capacity maps (typically from default
  51      * constructor). It is never written to, and replaced on first put. Its size
  52      * is set to half the minimum, so that the first resize will create a
  53      * minimum-sized table.
  54      */
  55     private static final Entry[] EMPTY_TABLE
  56             = new HashMapEntry[MINIMUM_CAPACITY >>> 1];
  57 
  58     /**
  59      * The default load factor. Note that this implementation ignores the
  60      * load factor, but cannot do away with it entirely because it's
  61      * mentioned in the API.
  62      *
  63      * <p>Note that this constant has no impact on the behavior of the program,
  64      * but it is emitted as part of the serialized form. The load factor of
  65      * .75 is hardwired into the program, which uses cheap shifts in place of
  66      * expensive division.
  67      */
  68     static final float DEFAULT_LOAD_FACTOR = .75F;
  69 
  70     /**
  71      * The hash table. If this hash map contains a mapping for null, it is
  72      * not represented this hash table.
  73      */
  74     transient HashMapEntry<K, V>[] table;
  75 
  76     /**
  77      * The entry representing the null key, or null if there's no such mapping.
  78      */
  79     transient HashMapEntry<K, V> entryForNullKey;
  80 
  81     /**
  82      * The number of mappings in this hash map.
  83      */
  84     transient int size;
  85 
  86     /**
  87      * Incremented by "structural modifications" to allow (best effort)
  88      * detection of concurrent modification.
  89      */
  90     transient int modCount;
  91 
  92     /**
  93      * The table is rehashed when its size exceeds this threshold.
  94      * The value of this field is generally .75 * capacity, except when
  95      * the capacity is zero, as described in the EMPTY_TABLE declaration
  96      * above.
  97      */
  98     private transient int threshold;
  99 
 100     // Views - lazily initialized
 101     private transient Set<K> keySet;
 102     private transient Set<Entry<K, V>> entrySet;
 103     private transient Collection<V> values;
 104 
 105     /**
 106      * Constructs a new empty {@code HashMap} instance.
 107      */
 108     @SuppressWarnings("unchecked")
 109     public HashMap() {
 110         table = (HashMapEntry<K, V>[]) EMPTY_TABLE;
 111         threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
 112     }
 113 
 114     /**
 115      * Constructs a new {@code HashMap} instance with the specified capacity.
 116      *
 117      * @param capacity
 118      *            the initial capacity of this hash map.
 119      * @throws IllegalArgumentException
 120      *                when the capacity is less than zero.
 121      */
 122     public HashMap(int capacity) {
 123         if (capacity < 0) {
 124             throw new IllegalArgumentException("Capacity: " + capacity);
 125         }
 126 
 127         if (capacity == 0) {
 128             @SuppressWarnings("unchecked")
 129             HashMapEntry<K, V>[] tab = (HashMapEntry<K, V>[]) EMPTY_TABLE;
 130             table = tab;
 131             threshold = -1; // Forces first put() to replace EMPTY_TABLE
 132             return;
 133         }
 134 
 135         if (capacity < MINIMUM_CAPACITY) {
 136             capacity = MINIMUM_CAPACITY;
 137         } else if (capacity > MAXIMUM_CAPACITY) {
 138             capacity = MAXIMUM_CAPACITY;
 139         } else {
 140             capacity = roundUpToPowerOfTwo(capacity);
 141         }
 142         makeTable(capacity);
 143     }
 144 
 145     /**
 146      * Constructs a new {@code HashMap} instance with the specified capacity and
 147      * load factor.
 148      *
 149      * @param capacity
 150      *            the initial capacity of this hash map.
 151      * @param loadFactor
 152      *            the initial load factor.
 153      * @throws IllegalArgumentException
 154      *                when the capacity is less than zero or the load factor is
 155      *                less or equal to zero or NaN.
 156      */
 157     public HashMap(int capacity, float loadFactor) {
 158         this(capacity);
 159 
 160         if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
 161             throw new IllegalArgumentException("Load factor: " + loadFactor);
 162         }
 163 
 164         /*
 165          * Note that this implementation ignores loadFactor; it always uses
 166          * a load factor of 3/4. This simplifies the code and generally
 167          * improves performance.
 168          */
 169     }
 170 
 171     /**
 172      * Constructs a new {@code HashMap} instance containing the mappings from
 173      * the specified map.
 174      *
 175      * @param map
 176      *            the mappings to add.
 177      */
 178     public HashMap(Map<? extends K, ? extends V> map) {
 179         this(capacityForInitSize(map.size()));
 180         constructorPutAll(map);
 181     }
 182 
 183     /**
 184      * Inserts all of the elements of map into this HashMap in a manner
 185      * suitable for use by constructors and pseudo-constructors (i.e., clone,
 186      * readObject). Also used by LinkedHashMap.
 187      */
 188     final void constructorPutAll(Map<? extends K, ? extends V> map) {
 189         for (Entry<? extends K, ? extends V> e : map.entrySet()) {
 190             constructorPut(e.getKey(), e.getValue());
 191         }
 192     }
 193 
 194     /**
 195      * Returns an appropriate capacity for the specified initial size. Does
 196      * not round the result up to a power of two; the caller must do this!
 197      * The returned value will be between 0 and MAXIMUM_CAPACITY (inclusive).
 198      */
 199     static int capacityForInitSize(int size) {
 200         int result = (size >> 1) + size; // Multiply by 3/2 to allow for growth
 201 
 202         // boolean expr is equivalent to result >= 0 && result<MAXIMUM_CAPACITY
 203         return (result & ~(MAXIMUM_CAPACITY-1))==0 ? result : MAXIMUM_CAPACITY;
 204     }
 205 
 206     /**
 207      * Returns a shallow copy of this map.
 208      *
 209      * @return a shallow copy of this map.
 210      */
 211     @SuppressWarnings("unchecked")
 212     @Override public Object clone() {
 213         /*
 214          * This could be made more efficient. It unnecessarily hashes all of
 215          * the elements in the map.
 216          */
 217         HashMap<K, V> result;
 218         try {
 219             result = (HashMap<K, V>) super.clone();
 220         } catch (CloneNotSupportedException e) {
 221             throw new AssertionError(e);
 222         }
 223 
 224         // Restore clone to empty state, retaining our capacity and threshold
 225         result.makeTable(table.length);
 226         result.entryForNullKey = null;
 227         result.size = 0;
 228         result.keySet = null;
 229         result.entrySet = null;
 230         result.values = null;
 231 
 232         result.init(); // Give subclass a chance to initialize itself
 233         result.constructorPutAll(this); // Calls method overridden in subclass!!
 234         return result;
 235     }
 236 
 237     /**
 238      * This method is called from the pseudo-constructors (clone and readObject)
 239      * prior to invoking constructorPut/constructorPutAll, which invoke the
 240      * overridden constructorNewEntry method. Normally it is a VERY bad idea to
 241      * invoke an overridden method from a pseudo-constructor (Effective Java
 242      * Item 17). In this case it is unavoidable, and the init method provides a
 243      * workaround.
 244      */
 245     void init() { }
 246 
 247     /**
 248      * Returns whether this map is empty.
 249      *
 250      * @return {@code true} if this map has no elements, {@code false}
 251      *         otherwise.
 252      * @see #size()
 253      */
 254     @Override public boolean isEmpty() {
 255         return size == 0;
 256     }
 257 
 258     /**
 259      * Returns the number of elements in this map.
 260      *
 261      * @return the number of elements in this map.
 262      */
 263     @Override public int size() {
 264         return size;
 265     }
 266 
 267     /**
 268      * Returns the value of the mapping with the specified key.
 269      *
 270      * @param key
 271      *            the key.
 272      * @return the value of the mapping with the specified key, or {@code null}
 273      *         if no mapping for the specified key is found.
 274      */
 275     public V get(Object key) {
 276         if (key == null) {
 277             HashMapEntry<K, V> e = entryForNullKey;
 278             return e == null ? null : e.value;
 279         }
 280 
 281         // Doug Lea's supplemental secondaryHash function (inlined)
 282         int hash = key.hashCode();
 283         hash ^= (hash >>> 20) ^ (hash >>> 12);
 284         hash ^= (hash >>> 7) ^ (hash >>> 4);
 285 
 286         HashMapEntry<K, V>[] tab = table;
 287         for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)]; e != null; e = e.next) 
 288         {
 289             K eKey = e.key;
 290             if (eKey == key || (e.hash == hash && key.equals(eKey))) {
 291                 return e.value;
 292             }
 293         }
 294         return null;
 295     }
 296 
 297     /**
 298      * Returns whether this map contains the specified key.
 299      *
 300      * @param key
 301      *            the key to search for.
 302      * @return {@code true} if this map contains the specified key,
 303      *         {@code false} otherwise.
 304      */
 305     @Override public boolean containsKey(Object key) {
 306         if (key == null) {
 307             return entryForNullKey != null;
 308         }
 309 
 310         // Doug Lea's supplemental secondaryHash function (inlined)
 311         int hash = key.hashCode();
 312         hash ^= (hash >>> 20) ^ (hash >>> 12);
 313         hash ^= (hash >>> 7) ^ (hash >>> 4);
 314 
 315         HashMapEntry<K, V>[] tab = table;
 316         for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
 317                 e != null; e = e.next) {
 318             K eKey = e.key;
 319             if (eKey == key || (e.hash == hash && key.equals(eKey))) {
 320                 return true;
 321             }
 322         }
 323         return false;
 324     }
 325 
 326     /**
 327      * Returns whether this map contains the specified value.
 328      *
 329      * @param value
 330      *            the value to search for.
 331      * @return {@code true} if this map contains the specified value,
 332      *         {@code false} otherwise.
 333      */
 334     @Override public boolean containsValue(Object value) {
 335         HashMapEntry[] tab = table;
 336         int len = tab.length;
 337         if (value == null) {
 338             for (int i = 0; i < len; i++) {
 339                 for (HashMapEntry e = tab[i]; e != null; e = e.next) {
 340                     if (e.value == null) {
 341                         return true;
 342                     }
 343                 }
 344             }
 345             return entryForNullKey != null && entryForNullKey.value == null;
 346         }
 347 
 348         // value is non-null
 349         for (int i = 0; i < len; i++) {
 350             for (HashMapEntry e = tab[i]; e != null; e = e.next) {
 351                 if (value.equals(e.value)) {
 352                     return true;
 353                 }
 354             }
 355         }
 356         return entryForNullKey != null && value.equals(entryForNullKey.value);
 357     }
 358 
 359     /**
 360      * Maps the specified key to the specified value.
 361      *
 362      * @param key
 363      *            the key.
 364      * @param value
 365      *            the value.
 366      * @return the value of any previous mapping with the specified key or
 367      *         {@code null} if there was no such mapping.
 368      */
 369     @Override public V put(K key, V value) {
 370         if (key == null) {
 371             return putValueForNullKey(value);
 372         }
 373 
 374         int hash = secondaryHash(key.hashCode());
 375         HashMapEntry<K, V>[] tab = table;
 376         int index = hash & (tab.length - 1);
 377         for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
 378             if (e.hash == hash && key.equals(e.key)) {
 379                 preModify(e);
 380                 V oldValue = e.value;
 381                 e.value = value;
 382                 return oldValue;
 383             }
 384         }
 385 
 386         // No entry for (non-null) key is present; create one
 387         modCount++;
 388         if (size++ > threshold) {
 389             tab = doubleCapacity();
 390             index = hash & (tab.length - 1);
 391         }
 392         addNewEntry(key, value, hash, index);
 393         return null;
 394     }
 395 
 396     private V putValueForNullKey(V value) {
 397         HashMapEntry<K, V> entry = entryForNullKey;
 398         if (entry == null) {
 399             addNewEntryForNullKey(value);
 400             size++;
 401             modCount++;
 402             return null;
 403         } else {
 404             preModify(entry);
 405             V oldValue = entry.value;
 406             entry.value = value;
 407             return oldValue;
 408         }
 409     }
 410 
 411     /**
 412      * Give LinkedHashMap a chance to take action when we modify an existing
 413      * entry.
 414      *
 415      * @param e the entry we're about to modify.
 416      */
 417     void preModify(HashMapEntry<K, V> e) { }
 418 
 419     /**
 420      * This method is just like put, except that it doesn't do things that
 421      * are inappropriate or unnecessary for constructors and pseudo-constructors
 422      * (i.e., clone, readObject). In particular, this method does not check to
 423      * ensure that capacity is sufficient, and does not increment modCount.
 424      */
 425     private void constructorPut(K key, V value) {
 426         if (key == null) {
 427             HashMapEntry<K, V> entry = entryForNullKey;
 428             if (entry == null) {
 429                 entryForNullKey = constructorNewEntry(null, value, 0, null);
 430                 size++;
 431             } else {
 432                 entry.value = value;
 433             }
 434             return;
 435         }
 436 
 437         int hash = secondaryHash(key.hashCode());
 438         HashMapEntry<K, V>[] tab = table;
 439         int index = hash & (tab.length - 1);
 440         HashMapEntry<K, V> first = tab[index];
 441         for (HashMapEntry<K, V> e = first; e != null; e = e.next) {
 442             if (e.hash == hash && key.equals(e.key)) {
 443                 e.value = value;
 444                 return;
 445             }
 446         }
 447 
 448         // No entry for (non-null) key is present; create one
 449         tab[index] = constructorNewEntry(key, value, hash, first);
 450         size++;
 451     }
 452 
 453     /**
 454      * Creates a new entry for the given key, value, hash, and index and
 455      * inserts it into the hash table. This method is called by put
 456      * (and indirectly, putAll), and overridden by LinkedHashMap. The hash
 457      * must incorporate the secondary hash function.
 458      */
 459     void addNewEntry(K key, V value, int hash, int index) {
 460         table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);
 461     }
 462 
 463     /**
 464      * Creates a new entry for the null key, and the given value and
 465      * inserts it into the hash table. This method is called by put
 466      * (and indirectly, putAll), and overridden by LinkedHashMap.
 467      */
 468     void addNewEntryForNullKey(V value) {
 469         entryForNullKey = new HashMapEntry<K, V>(null, value, 0, null);
 470     }
 471 
 472     /**
 473      * Like newEntry, but does not perform any activity that would be
 474      * unnecessary or inappropriate for constructors. In this class, the
 475      * two methods behave identically; in LinkedHashMap, they differ.
 476      */
 477     HashMapEntry<K, V> constructorNewEntry(
 478             K key, V value, int hash, HashMapEntry<K, V> first) {
 479         return new HashMapEntry<K, V>(key, value, hash, first);
 480     }
 481 
 482     /**
 483      * Copies all the mappings in the specified map to this map. These mappings
 484      * will replace all mappings that this map had for any of the keys currently
 485      * in the given map.
 486      *
 487      * @param map
 488      *            the map to copy mappings from.
 489      */
 490     @Override public void putAll(Map<? extends K, ? extends V> map) {
 491         ensureCapacity(map.size());
 492         super.putAll(map);
 493     }
 494 
 495     /**
 496      * Ensures that the hash table has sufficient capacity to store the
 497      * specified number of mappings, with room to grow. If not, it increases the
 498      * capacity as appropriate. Like doubleCapacity, this method moves existing
 499      * entries to new buckets as appropriate. Unlike doubleCapacity, this method
 500      * can grow the table by factors of 2^n for n > 1. Hopefully, a single call
 501      * to this method will be faster than multiple calls to doubleCapacity.
 502      *
 503      *  <p>This method is called only by putAll.
 504      */
 505     private void ensureCapacity(int numMappings) {
 506         int newCapacity = roundUpToPowerOfTwo(capacityForInitSize(numMappings));
 507         HashMapEntry<K, V>[] oldTable = table;
 508         int oldCapacity = oldTable.length;
 509         if (newCapacity <= oldCapacity) {
 510             return;
 511         }
 512         if (newCapacity == oldCapacity * 2) {
 513             doubleCapacity();
 514             return;
 515         }
 516 
 517         // We're growing by at least 4x, rehash in the obvious way
 518         HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
 519         if (size != 0) {
 520             int newMask = newCapacity - 1;
 521             for (int i = 0; i < oldCapacity; i++) {
 522                 for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
 523                     HashMapEntry<K, V> oldNext = e.next;
 524                     int newIndex = e.hash & newMask;
 525                     HashMapEntry<K, V> newNext = newTable[newIndex];
 526                     newTable[newIndex] = e;
 527                     e.next = newNext;
 528                     e = oldNext;
 529                 }
 530             }
 531         }
 532     }
 533 
 534     /**
 535      * Allocate a table of the given capacity and set the threshold accordingly.
 536      * @param newCapacity must be a power of two
 537      */
 538     private HashMapEntry<K, V>[] makeTable(int newCapacity) {
 539         @SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable
 540                 = (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity];
 541         table = newTable;
 542         threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity
 543         return newTable;
 544     }
 545 
 546     /**
 547      * Doubles the capacity of the hash table. Existing entries are placed in
 548      * the correct bucket on the enlarged table. If the current capacity is,
 549      * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which
 550      * will be new unless we were already at MAXIMUM_CAPACITY.
 551      */
 552     private HashMapEntry<K, V>[] doubleCapacity() {
 553         HashMapEntry<K, V>[] oldTable = table;
 554         int oldCapacity = oldTable.length;
 555         if (oldCapacity == MAXIMUM_CAPACITY) {
 556             return oldTable;
 557         }
 558         int newCapacity = oldCapacity * 2;
 559         HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
 560         if (size == 0) {
 561             return newTable;
 562         }
 563 
 564         for (int j = 0; j < oldCapacity; j++) {
 565             /*
 566              * Rehash the bucket using the minimum number of field writes.
 567              * This is the most subtle and delicate code in the class.
 568              */
 569             HashMapEntry<K, V> e = oldTable[j];
 570             if (e == null) {
 571                 continue;
 572             }
 573             int highBit = e.hash & oldCapacity;
 574             HashMapEntry<K, V> broken = null;
 575             newTable[j | highBit] = e;
 576             for (HashMapEntry<K, V> n = e.next; n != null; e = n, n = n.next) {
 577                 int nextHighBit = n.hash & oldCapacity;
 578                 if (nextHighBit != highBit) {
 579                     if (broken == null)
 580                         newTable[j | nextHighBit] = n;
 581                     else
 582                         broken.next = n;
 583                     broken = e;
 584                     highBit = nextHighBit;
 585                 }
 586             }
 587             if (broken != null)
 588                 broken.next = null;
 589         }
 590         return newTable;
 591     }
 592 
 593     /**
 594      * Removes the mapping with the specified key from this map.
 595      *
 596      * @param key
 597      *            the key of the mapping to remove.
 598      * @return the value of the removed mapping or {@code null} if no mapping
 599      *         for the specified key was found.
 600      */
 601     @Override public V remove(Object key) {
 602         if (key == null) {
 603             return removeNullKey();
 604         }
 605         int hash = secondaryHash(key.hashCode());
 606         HashMapEntry<K, V>[] tab = table;
 607         int index = hash & (tab.length - 1);
 608         for (HashMapEntry<K, V> e = tab[index], prev = null;
 609                 e != null; prev = e, e = e.next) {
 610             if (e.hash == hash && key.equals(e.key)) {
 611                 if (prev == null) {
 612                     tab[index] = e.next;
 613                 } else {
 614                     prev.next = e.next;
 615                 }
 616                 modCount++;
 617                 size--;
 618                 postRemove(e);
 619                 return e.value;
 620             }
 621         }
 622         return null;
 623     }
 624 
 625     private V removeNullKey() {
 626         HashMapEntry<K, V> e = entryForNullKey;
 627         if (e == null) {
 628             return null;
 629         }
 630         entryForNullKey = null;
 631         modCount++;
 632         size--;
 633         postRemove(e);
 634         return e.value;
 635     }
 636 
 637     /**
 638      * Subclass overrides this method to unlink entry.
 639      */
 640     void postRemove(HashMapEntry<K, V> e) { }
 641 
 642     /**
 643      * Removes all mappings from this hash map, leaving it empty.
 644      *
 645      * @see #isEmpty
 646      * @see #size
 647      */
 648     @Override public void clear() {
 649         if (size != 0) {
 650             Arrays.fill(table, null);
 651             entryForNullKey = null;
 652             modCount++;
 653             size = 0;
 654         }
 655     }
 656 
 657     /**
 658      * Returns a set of the keys contained in this map. The set is backed by
 659      * this map so changes to one are reflected by the other. The set does not
 660      * support adding.
 661      *
 662      * @return a set of the keys.
 663      */
 664     @Override public Set<K> keySet() {
 665         Set<K> ks = keySet;
 666         return (ks != null) ? ks : (keySet = new KeySet());
 667     }
 668 
 669     /**
 670      * Returns a collection of the values contained in this map. The collection
 671      * is backed by this map so changes to one are reflected by the other. The
 672      * collection supports remove, removeAll, retainAll and clear operations,
 673      * and it does not support add or addAll operations.
 674      * <p>
 675      * This method returns a collection which is the subclass of
 676      * AbstractCollection. The iterator method of this subclass returns a
 677      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
 678      * method wraps the map's size method and the {@code contains} method wraps
 679      * the map's containsValue method.
 680      * </p>
 681      * <p>
 682      * The collection is created when this method is called for the first time
 683      * and returned in response to all subsequent calls. This method may return
 684      * different collections when multiple concurrent calls occur, since no
 685      * synchronization is performed.
 686      * </p>
 687      *
 688      * @return a collection of the values contained in this map.
 689      */
 690     @Override public Collection<V> values() {
 691         Collection<V> vs = values;
 692         return (vs != null) ? vs : (values = new Values());
 693     }
 694 
 695     /**
 696      * Returns a set containing all of the mappings in this map. Each mapping is
 697      * an instance of {@link Map.Entry}. As the set is backed by this map,
 698      * changes in one will be reflected in the other.
 699      *
 700      * @return a set of the mappings.
 701      */
 702     public Set<Entry<K, V>> entrySet() {
 703         Set<Entry<K, V>> es = entrySet;
 704         return (es != null) ? es : (entrySet = new EntrySet());
 705     }
 706 
 707     static class HashMapEntry<K, V> implements Entry<K, V> {
 708         final K key;
 709         V value;
 710         final int hash;
 711         HashMapEntry<K, V> next;
 712 
 713         HashMapEntry(K key, V value, int hash, HashMapEntry<K, V> next) {
 714             this.key = key;
 715             this.value = value;
 716             this.hash = hash;
 717             this.next = next;
 718         }
 719 
 720         public final K getKey() {
 721             return key;
 722         }
 723 
 724         public final V getValue() {
 725             return value;
 726         }
 727 
 728         public final V setValue(V value) {
 729             V oldValue = this.value;
 730             this.value = value;
 731             return oldValue;
 732         }
 733 
 734         @Override public final boolean equals(Object o) {
 735             if (!(o instanceof Entry)) {
 736                 return false;
 737             }
 738             Entry<?, ?> e = (Entry<?, ?>) o;
 739             return Objects.equal(e.getKey(), key)
 740                     && Objects.equal(e.getValue(), value);
 741         }
 742 
 743         @Override public final int hashCode() {
 744             return (key == null ? 0 : key.hashCode()) ^
 745                     (value == null ? 0 : value.hashCode());
 746         }
 747 
 748         @Override public final String toString() {
 749             return key + "=" + value;
 750         }
 751     }
 752 
 753     private abstract class HashIterator {
 754         int nextIndex;
 755         HashMapEntry<K, V> nextEntry = entryForNullKey;
 756         HashMapEntry<K, V> lastEntryReturned;
 757         int expectedModCount = modCount;
 758 
 759         HashIterator() {
 760             if (nextEntry == null) {
 761                 HashMapEntry<K, V>[] tab = table;
 762                 HashMapEntry<K, V> next = null;
 763                 while (next == null && nextIndex < tab.length) {
 764                     next = tab[nextIndex++];
 765                 }
 766                 nextEntry = next;
 767             }
 768         }
 769 
 770         public boolean hasNext() {
 771             return nextEntry != null;
 772         }
 773 
 774         HashMapEntry<K, V> nextEntry() {
 775             if (modCount != expectedModCount)
 776                 throw new ConcurrentModificationException();
 777             if (nextEntry == null)
 778                 throw new NoSuchElementException();
 779 
 780             HashMapEntry<K, V> entryToReturn = nextEntry;
 781             HashMapEntry<K, V>[] tab = table;
 782             HashMapEntry<K, V> next = entryToReturn.next;
 783             while (next == null && nextIndex < tab.length) {
 784                 next = tab[nextIndex++];
 785             }
 786             nextEntry = next;
 787             return lastEntryReturned = entryToReturn;
 788         }
 789 
 790         public void remove() {
 791             if (lastEntryReturned == null)
 792                 throw new IllegalStateException();
 793             if (modCount != expectedModCount)
 794                 throw new ConcurrentModificationException();
 795             HashMap.this.remove(lastEntryReturned.key);
 796             lastEntryReturned = null;
 797             expectedModCount = modCount;
 798         }
 799     }
 800 
 801     private final class KeyIterator extends HashIterator
 802             implements Iterator<K> {
 803         public K next() { return nextEntry().key; }
 804     }
 805 
 806     private final class ValueIterator extends HashIterator
 807             implements Iterator<V> {
 808         public V next() { return nextEntry().value; }
 809     }
 810 
 811     private final class EntryIterator extends HashIterator
 812             implements Iterator<Entry<K, V>> {
 813         public Entry<K, V> next() { return nextEntry(); }
 814     }
 815 
 816     /**
 817      * Returns true if this map contains the specified mapping.
 818      */
 819     private boolean containsMapping(Object key, Object value) {
 820         if (key == null) {
 821             HashMapEntry<K, V> e = entryForNullKey;
 822             return e != null && Objects.equal(value, e.value);
 823         }
 824 
 825         int hash = secondaryHash(key.hashCode());
 826         HashMapEntry<K, V>[] tab = table;
 827         int index = hash & (tab.length - 1);
 828         for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
 829             if (e.hash == hash && key.equals(e.key)) {
 830                 return Objects.equal(value, e.value);
 831             }
 832         }
 833         return false; // No entry for key
 834     }
 835 
 836     /**
 837      * Removes the mapping from key to value and returns true if this mapping
 838      * exists; otherwise, returns does nothing and returns false.
 839      */
 840     private boolean removeMapping(Object key, Object value) {
 841         if (key == null) {
 842             HashMapEntry<K, V> e = entryForNullKey;
 843             if (e == null || !Objects.equal(value, e.value)) {
 844                 return false;
 845             }
 846             entryForNullKey = null;
 847             modCount++;
 848             size--;
 849             postRemove(e);
 850             return true;
 851         }
 852 
 853         int hash = secondaryHash(key.hashCode());
 854         HashMapEntry<K, V>[] tab = table;
 855         int index = hash & (tab.length - 1);
 856         for (HashMapEntry<K, V> e = tab[index], prev = null;
 857                 e != null; prev = e, e = e.next) {
 858             if (e.hash == hash && key.equals(e.key)) {
 859                 if (!Objects.equal(value, e.value)) {
 860                     return false;  // Map has wrong value for key
 861                 }
 862                 if (prev == null) {
 863                     tab[index] = e.next;
 864                 } else {
 865                     prev.next = e.next;
 866                 }
 867                 modCount++;
 868                 size--;
 869                 postRemove(e);
 870                 return true;
 871             }
 872         }
 873         return false; // No entry for key
 874     }
 875 
 876     // Subclass (LinkedHashMap) overrides these for correct iteration order
 877     Iterator<K> newKeyIterator() { return new KeyIterator();   }
 878     Iterator<V> newValueIterator() { return new ValueIterator(); }
 879     Iterator<Entry<K, V>> newEntryIterator() { return new EntryIterator(); }
 880 
 881     private final class KeySet extends AbstractSet<K> {
 882         public Iterator<K> iterator() {
 883             return newKeyIterator();
 884         }
 885         public int size() {
 886             return size;
 887         }
 888         public boolean isEmpty() {
 889             return size == 0;
 890         }
 891         public boolean contains(Object o) {
 892             return containsKey(o);
 893         }
 894         public boolean remove(Object o) {
 895             int oldSize = size;
 896             HashMap.this.remove(o);
 897             return size != oldSize;
 898         }
 899         public void clear() {
 900             HashMap.this.clear();
 901         }
 902     }
 903 
 904     private final class Values extends AbstractCollection<V> {
 905         public Iterator<V> iterator() {
 906             return newValueIterator();
 907         }
 908         public int size() {
 909             return size;
 910         }
 911         public boolean isEmpty() {
 912             return size == 0;
 913         }
 914         public boolean contains(Object o) {
 915             return containsValue(o);
 916         }
 917         public void clear() {
 918             HashMap.this.clear();
 919         }
 920     }
 921 
 922     private final class EntrySet extends AbstractSet<Entry<K, V>> {
 923         public Iterator<Entry<K, V>> iterator() {
 924             return newEntryIterator();
 925         }
 926         public boolean contains(Object o) {
 927             if (!(o instanceof Entry))
 928                 return false;
 929             Entry<?, ?> e = (Entry<?, ?>) o;
 930             return containsMapping(e.getKey(), e.getValue());
 931         }
 932         public boolean remove(Object o) {
 933             if (!(o instanceof Entry))
 934                 return false;
 935             Entry<?, ?> e = (Entry<?, ?>)o;
 936             return removeMapping(e.getKey(), e.getValue());
 937         }
 938         public int size() {
 939             return size;
 940         }
 941         public boolean isEmpty() {
 942             return size == 0;
 943         }
 944         public void clear() {
 945             HashMap.this.clear();
 946         }
 947     }
 948 
 949     /**
 950      * Applies a supplemental hash function to a given hashCode, which defends
 951      * against poor quality hash functions. This is critical because HashMap
 952      * uses power-of-two length hash tables, that otherwise encounter collisions
 953      * for hashCodes that do not differ in lower or upper bits.
 954      */
 955     private static int secondaryHash(int h) {
 956         // Doug Lea's supplemental hash function
 957         h ^= (h >>> 20) ^ (h >>> 12);
 958         return h ^ (h >>> 7) ^ (h >>> 4);
 959     }
 960 
 961     /**
 962      * Returns the smallest power of two >= its argument, with several caveats:
 963      * If the argument is negative but not Integer.MIN_VALUE, the method returns
 964      * zero. If the argument is > 2^30 or equal to Integer.MIN_VALUE, the method
 965      * returns Integer.MIN_VALUE. If the argument is zero, the method returns
 966      * zero.
 967      */
 968     private static int roundUpToPowerOfTwo(int i) {
 969         i--; // If input is a power of two, shift its high-order bit right
 970 
 971         // "Smear" the high-order bit all the way to the right
 972         i |= i >>>  1;
 973         i |= i >>>  2;
 974         i |= i >>>  4;
 975         i |= i >>>  8;
 976         i |= i >>> 16;
 977 
 978         return i + 1;
 979     }
 980 
 981     private static final long serialVersionUID = 362498820763181265L;
 982 
 983     private static final ObjectStreamField[] serialPersistentFields = {
 984         new ObjectStreamField("loadFactor", float.class)
 985     };
 986 
 987     private void writeObject(ObjectOutputStream stream) throws IOException {
 988         // Emulate loadFactor field for other implementations to read
 989         ObjectOutputStream.PutField fields = stream.putFields();
 990         fields.put("loadFactor", DEFAULT_LOAD_FACTOR);
 991         stream.writeFields();
 992 
 993         stream.writeInt(table.length); // Capacity
 994         stream.writeInt(size);
 995         for (Entry<K, V> e : entrySet()) {
 996             stream.writeObject(e.getKey());
 997             stream.writeObject(e.getValue());
 998         }
 999     }
1000 
1001     private void readObject(ObjectInputStream stream) throws IOException,
1002             ClassNotFoundException {
1003         stream.defaultReadObject();
1004         int capacity = stream.readInt();
1005         if (capacity < 0) {
1006             throw new InvalidObjectException("Capacity: " + capacity);
1007         }
1008         if (capacity < MINIMUM_CAPACITY) {
1009             capacity = MINIMUM_CAPACITY;
1010         } else if (capacity > MAXIMUM_CAPACITY) {
1011             capacity = MAXIMUM_CAPACITY;
1012         } else {
1013             capacity = roundUpToPowerOfTwo(capacity);
1014         }
1015         makeTable(capacity);
1016 
1017         int size = stream.readInt();
1018         if (size < 0) {
1019             throw new InvalidObjectException("Size: " + size);
1020         }
1021 
1022         init(); // Give subclass (LinkedHashMap) a chance to initialize itself
1023         for (int i = 0; i < size; i++) {
1024             @SuppressWarnings("unchecked") K key = (K) stream.readObject();
1025             @SuppressWarnings("unchecked") V val = (V) stream.readObject();
1026             constructorPut(key, val);
1027         }
1028     }
1029 }
View Code

TreeMap

   1 package java.util;
   2 import java.io.IOException;
   3 import java.io.ObjectInputStream;
   4 import java.io.ObjectInputStream.GetField;
   5 import java.io.ObjectOutputStream;
   6 import java.io.ObjectStreamException;
   7 import java.io.Serializable;
   8 import static java.util.TreeMap.Bound.*;
   9 import static java.util.TreeMap.Relation.*;
  10 import libcore.util.Objects;
  11 /**
  12  * A map whose entries are sorted by their keys. All optional operations such as
  13  * {@link #put} and {@link #remove} are supported.
  14  *
  15  * <p>This map sorts keys using either a user-supplied comparator or the key's
  16  * natural order:
  17  * <ul>
  18  *   <li>User supplied comparators must be able to compare any pair of keys in
  19  *       this map. If a user-supplied comparator is in use, it will be returned
  20  *       by {@link #comparator}.
  21  *   <li>If no user-supplied comparator is supplied, keys will be sorted by
  22  *       their natural order. Keys must be <i>mutually comparable</i>: they must
  23  *       implement {@link Comparable} and {@link Comparable#compareTo
  24  *       compareTo()} must be able to compare each key with any other key in
  25  *       this map. In this case {@link #comparator} will return null.
  26  * </ul>
  27  * With either a comparator or a natural ordering, comparisons should be
  28  * <i>consistent with equals</i>. An ordering is consistent with equals if for
  29  * every pair of keys {@code a} and {@code b}, {@code a.equals(b)} if and only
  30  * if {@code compare(a, b) == 0}.
  31  *
  32  * <p>When the ordering is not consistent with equals the behavior of this
  33  * class is well defined but does not honor the contract specified by {@link
  34  * Map}. Consider a tree map of case-insensitive strings, an ordering that is
  35  * not consistent with equals: <pre>   {@code
  36  *   TreeMap<String, String> map = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
  37  *   map.put("a", "android");
  38  *
  39  *   // The Map API specifies that the next line should print "null" because
  40  *   // "a".equals("A") is false and there is no mapping for upper case "A".
  41  *   // But the case insensitive ordering says compare("a", "A") == 0. TreeMap
  42  *   // uses only comparators/comparable on keys and so this prints "android".
  43  *   System.out.println(map.get("A"));
  44  * }</pre>
  45  *
  46  * @since 1.2
  47  */
  48 public class TreeMap<K, V> extends AbstractMap<K, V>
  49         implements SortedMap<K, V>, NavigableMap<K, V>, Cloneable, Serializable {
  50 
  51     @SuppressWarnings("unchecked") // to avoid Comparable<Comparable<Comparable<...>>>
  52     private static final Comparator<Comparable> NATURAL_ORDER = new Comparator<Comparable>() {
  53         public int compare(Comparable a, Comparable b) {
  54             return a.compareTo(b);
  55         }
  56     };
  57 
  58     Comparator<? super K> comparator;
  59     Node<K, V> root;
  60     int size = 0;
  61     int modCount = 0;
  62 
  63     /**
  64      * Create a natural order, empty tree map whose keys must be mutually
  65      * comparable and non-null.
  66      */
  67     @SuppressWarnings("unchecked") // unsafe! this assumes K is comparable
  68     public TreeMap() {
  69         this.comparator = (Comparator<? super K>) NATURAL_ORDER;
  70     }
  71 
  72     /**
  73      * Create a natural order tree map populated with the key/value pairs of
  74      * {@code copyFrom}. This map's keys must be mutually comparable and
  75      * non-null.
  76      *
  77      * <p>Even if {@code copyFrom} is a {@code SortedMap}, the constructed map
  78      * <strong>will not</strong> use {@code copyFrom}'s ordering. This
  79      * constructor always creates a naturally-ordered map. Because the {@code
  80      * TreeMap} constructor overloads are ambiguous, prefer to construct a map
  81      * and populate it in two steps: <pre>   {@code
  82      *   TreeMap<String, Integer> customOrderedMap
  83      *       = new TreeMap<String, Integer>(copyFrom.comparator());
  84      *   customOrderedMap.putAll(copyFrom);
  85      * }</pre>
  86      */
  87     public TreeMap(Map<? extends K, ? extends V> copyFrom) {
  88         this();
  89         for (Map.Entry<? extends K, ? extends V> entry : copyFrom.entrySet()) {
  90             putInternal(entry.getKey(), entry.getValue());
  91         }
  92     }
  93 
  94     /**
  95      * Create a tree map ordered by {@code comparator}. This map's keys may only
  96      * be null if {@code comparator} permits.
  97      *
  98      * @param comparator the comparator to order elements with, or {@code null} to use the natural
  99      * ordering.
 100      */
 101     @SuppressWarnings("unchecked") // unsafe! if comparator is null, this assumes K is comparable
 102     public TreeMap(Comparator<? super K> comparator) {
 103         if (comparator != null) {
 104             this.comparator = comparator;
 105         } else {
 106             this.comparator = (Comparator<? super K>) NATURAL_ORDER;
 107         }
 108     }
 109 
 110     /**
 111      * Create a tree map with the ordering and key/value pairs of {@code
 112      * copyFrom}. This map's keys may only be null if the {@code copyFrom}'s
 113      * ordering permits.
 114      *
 115      * <p>The constructed map <strong>will always use</strong> {@code
 116      * copyFrom}'s ordering. Because the {@code TreeMap} constructor overloads
 117      * are ambigous, prefer to construct a map and populate it in two steps:
 118      * <pre>   {@code
 119      *   TreeMap<String, Integer> customOrderedMap
 120      *       = new TreeMap<String, Integer>(copyFrom.comparator());
 121      *   customOrderedMap.putAll(copyFrom);
 122      * }</pre>
 123      */
 124     @SuppressWarnings("unchecked") // if copyFrom's keys are comparable this map's keys must be also
 125     public TreeMap(SortedMap<K, ? extends V> copyFrom) {
 126         Comparator<? super K> sourceComparator = copyFrom.comparator();
 127         if (sourceComparator != null) {
 128             this.comparator = sourceComparator;
 129         } else {
 130             this.comparator = (Comparator<? super K>) NATURAL_ORDER;
 131         }
 132         for (Map.Entry<K, ? extends V> entry : copyFrom.entrySet()) {
 133             putInternal(entry.getKey(), entry.getValue());
 134         }
 135     }
 136 
 137     @Override public Object clone() {
 138         try {
 139             @SuppressWarnings("unchecked") // super.clone() must return the same type
 140             TreeMap<K, V> map = (TreeMap<K, V>) super.clone();
 141             map.root = root != null ? root.copy(null) : null;
 142             map.entrySet = null;
 143             map.keySet = null;
 144             return map;
 145         } catch (CloneNotSupportedException e) {
 146             throw new AssertionError();
 147         }
 148     }
 149 
 150     @Override public int size() {
 151         return size;
 152     }
 153 
 154     @Override public boolean isEmpty() {
 155         return size == 0;
 156     }
 157 
 158     @Override public V get(Object key) {
 159         Entry<K, V> entry = findByObject(key);
 160         return entry != null ? entry.getValue() : null;
 161     }
 162 
 163     @Override public boolean containsKey(Object key) {
 164         return findByObject(key) != null;
 165     }
 166 
 167     @Override public V put(K key, V value) {
 168         return putInternal(key, value);
 169     }
 170 
 171     @Override public void clear() {
 172         root = null;
 173         size = 0;
 174         modCount++;
 175     }
 176 
 177     @Override public V remove(Object key) {
 178         Node<K, V> node = removeInternalByKey(key);
 179         return node != null ? node.value : null;
 180     }
 181 
 182     /*
 183      * AVL methods
 184      */
 185 
 186     enum Relation {
 187         LOWER,
 188         FLOOR,
 189         EQUAL,
 190         CREATE,
 191         CEILING,
 192         HIGHER;
 193 
 194         /**
 195          * Returns a possibly-flipped relation for use in descending views.
 196          *
 197          * @param ascending false to flip; true to return this.
 198          */
 199         Relation forOrder(boolean ascending) {
 200             if (ascending) {
 201                 return this;
 202             }
 203 
 204             switch (this) {
 205                 case LOWER:
 206                     return HIGHER;
 207                 case FLOOR:
 208                     return CEILING;
 209                 case EQUAL:
 210                     return EQUAL;
 211                 case CEILING:
 212                     return FLOOR;
 213                 case HIGHER:
 214                     return LOWER;
 215                 default:
 216                     throw new IllegalStateException();
 217             }
 218         }
 219     }
 220 
 221     V putInternal(K key, V value) {
 222         Node<K, V> created = find(key, Relation.CREATE);
 223         V result = created.value;
 224         created.value = value;
 225         return result;
 226     }
 227 
 228     /**
 229      * Returns the node at or adjacent to the given key, creating it if requested.
 230      *
 231      * @throws ClassCastException if {@code key} and the tree's keys aren't mutually comparable.
 232      */
 233     Node<K, V> find(K key, Relation relation) {
 234         if (root == null) {
 235             if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) {
 236                 throw new ClassCastException(key.getClass().getName() + " is not Comparable"); // NullPointerException ok
 237             }
 238             if (relation == Relation.CREATE) {
 239                 root = new Node<K, V>(null, key);
 240                 size = 1;
 241                 modCount++;
 242                 return root;
 243             } else {
 244                 return null;
 245             }
 246         }
 247 
 248         /*
 249          * Micro-optimization: avoid polymorphic calls to Comparator.compare().
 250          * This is 10% faster for naturally ordered trees.
 251          */
 252         @SuppressWarnings("unchecked") // will throw a ClassCastException below if there's trouble
 253         Comparable<Object> comparableKey = (comparator == NATURAL_ORDER)
 254                 ? (Comparable<Object>) key
 255                 : null;
 256 
 257         Node<K, V> nearest = root;
 258         while (true) {
 259             int comparison = (comparableKey != null)
 260                     ? comparableKey.compareTo(nearest.key)
 261                     : comparator.compare(key, nearest.key);
 262 
 263             /*
 264              * We found the requested key.
 265              */
 266             if (comparison == 0) {
 267                 switch (relation) {
 268                     case LOWER:
 269                         return nearest.prev();
 270                     case FLOOR:
 271                     case EQUAL:
 272                     case CREATE:
 273                     case CEILING:
 274                         return nearest;
 275                     case HIGHER:
 276                         return nearest.next();
 277                 }
 278             }
 279 
 280             Node<K, V> child = (comparison < 0) ? nearest.left : nearest.right;
 281             if (child != null) {
 282                 nearest = child;
 283                 continue;
 284             }
 285 
 286             /*
 287              * We found a nearest node. Every key not in the tree has up to two
 288              * nearest nodes, one lower and one higher.
 289              */
 290 
 291             if (comparison < 0) { // nearest.key is higher
 292                 switch (relation) {
 293                     case LOWER:
 294                     case FLOOR:
 295                         return nearest.prev();
 296                     case CEILING:
 297                     case HIGHER:
 298                         return nearest;
 299                     case EQUAL:
 300                         return null;
 301                     case CREATE:
 302                         Node<K, V> created = new Node<K, V>(nearest, key);
 303                         nearest.left = created;
 304                         size++;
 305                         modCount++;
 306                         rebalance(nearest, true);
 307                         return created;
 308                 }
 309             } else { // comparison > 0, nearest.key is lower
 310                 switch (relation) {
 311                     case LOWER:
 312                     case FLOOR:
 313                         return nearest;
 314                     case CEILING:
 315                     case HIGHER:
 316                         return nearest.next();
 317                     case EQUAL:
 318                         return null;
 319                     case CREATE:
 320                         Node<K, V> created = new Node<K, V>(nearest, key);
 321                         nearest.right = created;
 322                         size++;
 323                         modCount++;
 324                         rebalance(nearest, true);
 325                         return created;
 326                 }
 327             }
 328         }
 329     }
 330 
 331     @SuppressWarnings("unchecked") // this method throws ClassCastExceptions!
 332     Node<K, V> findByObject(Object key) {
 333         return find((K) key, EQUAL);
 334     }
 335 
 336     /**
 337      * Returns this map's entry that has the same key and value as {@code
 338      * entry}, or null if this map has no such entry.
 339      *
 340      * <p>This method uses the comparator for key equality rather than {@code
 341      * equals}. If this map's comparator isn't consistent with equals (such as
 342      * {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code
 343      * contains()} will violate the collections API.
 344      */
 345     Node<K, V> findByEntry(Entry<?, ?> entry) {
 346         Node<K, V> mine = findByObject(entry.getKey());
 347         boolean valuesEqual = mine != null && Objects.equal(mine.value, entry.getValue());
 348         return valuesEqual ? mine : null;
 349     }
 350 
 351     /**
 352      * Removes {@code node} from this tree, rearranging the tree's structure as
 353      * necessary.
 354      */
 355     void removeInternal(Node<K, V> node) {
 356         Node<K, V> left = node.left;
 357         Node<K, V> right = node.right;
 358         Node<K, V> originalParent = node.parent;
 359         if (left != null && right != null) {
 360 
 361             /*
 362              * To remove a node with both left and right subtrees, move an
 363              * adjacent node from one of those subtrees into this node's place.
 364              *
 365              * Removing the adjacent node may change this node's subtrees. This
 366              * node may no longer have two subtrees once the adjacent node is
 367              * gone!
 368              */
 369 
 370             Node<K, V> adjacent = (left.height > right.height) ? left.last() : right.first();
 371             removeInternal(adjacent); // takes care of rebalance and size--
 372 
 373             int leftHeight = 0;
 374             left = node.left;
 375             if (left != null) {
 376                 leftHeight = left.height;
 377                 adjacent.left = left;
 378                 left.parent = adjacent;
 379                 node.left = null;
 380             }
 381             int rightHeight = 0;
 382             right = node.right;
 383             if (right != null) {
 384                 rightHeight = right.height;
 385                 adjacent.right = right;
 386                 right.parent = adjacent;
 387                 node.right = null;
 388             }
 389             adjacent.height = Math.max(leftHeight, rightHeight) + 1;
 390             replaceInParent(node, adjacent);
 391             return;
 392         } else if (left != null) {
 393             replaceInParent(node, left);
 394             node.left = null;
 395         } else if (right != null) {
 396             replaceInParent(node, right);
 397             node.right = null;
 398         } else {
 399             replaceInParent(node, null);
 400         }
 401 
 402         rebalance(originalParent, false);
 403         size--;
 404         modCount++;
 405     }
 406 
 407     Node<K, V> removeInternalByKey(Object key) {
 408         Node<K, V> node = findByObject(key);
 409         if (node != null) {
 410             removeInternal(node);
 411         }
 412         return node;
 413     }
 414 
 415     private void replaceInParent(Node<K, V> node, Node<K, V> replacement) {
 416         Node<K, V> parent = node.parent;
 417         node.parent = null;
 418         if (replacement != null) {
 419             replacement.parent = parent;
 420         }
 421 
 422         if (parent != null) {
 423             if (parent.left == node) {
 424                 parent.left = replacement;
 425             } else {
 426                 assert (parent.right == node);
 427                 parent.right = replacement;
 428             }
 429         } else {
 430             root = replacement;
 431         }
 432     }
 433 
 434     /**
 435      * Rebalances the tree by making any AVL rotations necessary between the
 436      * newly-unbalanced node and the tree's root.
 437      *
 438      * @param insert true if the node was unbalanced by an insert; false if it
 439      *     was by a removal.
 440      */
 441     private void rebalance(Node<K, V> unbalanced, boolean insert) {
 442         for (Node<K, V> node = unbalanced; node != null; node = node.parent) {
 443             Node<K, V> left = node.left;
 444             Node<K, V> right = node.right;
 445             int leftHeight = left != null ? left.height : 0;
 446             int rightHeight = right != null ? right.height : 0;
 447 
 448             int delta = leftHeight - rightHeight;
 449             if (delta == -2) {
 450                 Node<K, V> rightLeft = right.left;
 451                 Node<K, V> rightRight = right.right;
 452                 int rightRightHeight = rightRight != null ? rightRight.height : 0;
 453                 int rightLeftHeight = rightLeft != null ? rightLeft.height : 0;
 454 
 455                 int rightDelta = rightLeftHeight - rightRightHeight;
 456                 if (rightDelta == -1 || (rightDelta == 0 && !insert)) {
 457                     rotateLeft(node); // AVL right right
 458                 } else {
 459                     assert (rightDelta == 1);
 460                     rotateRight(right); // AVL right left
 461                     rotateLeft(node);
 462                 }
 463                 if (insert) {
 464                     break; // no further rotations will be necessary
 465                 }
 466 
 467             } else if (delta == 2) {
 468                 Node<K, V> leftLeft = left.left;
 469                 Node<K, V> leftRight = left.right;
 470                 int leftRightHeight = leftRight != null ? leftRight.height : 0;
 471                 int leftLeftHeight = leftLeft != null ? leftLeft.height : 0;
 472 
 473                 int leftDelta = leftLeftHeight - leftRightHeight;
 474                 if (leftDelta == 1 || (leftDelta == 0 && !insert)) {
 475                     rotateRight(node); // AVL left left
 476                 } else {
 477                     assert (leftDelta == -1);
 478                     rotateLeft(left); // AVL left right
 479                     rotateRight(node);
 480                 }
 481                 if (insert) {
 482                     break; // no further rotations will be necessary
 483                 }
 484 
 485             } else if (delta == 0) {
 486                 node.height = leftHeight + 1; // leftHeight == rightHeight
 487                 if (insert) {
 488                     break; // the insert caused balance, so rebalancing is done!
 489                 }
 490 
 491             } else {
 492                 assert (delta == -1 || delta == 1);
 493                 node.height = Math.max(leftHeight, rightHeight) + 1;
 494                 if (!insert) {
 495                     break; // the height hasn't changed, so rebalancing is done!
 496                 }
 497             }
 498         }
 499     }
 500 
 501     /**
 502      * Rotates the subtree so that its root's right child is the new root.
 503      */
 504     private void rotateLeft(Node<K, V> root) {
 505         Node<K, V> left = root.left;
 506         Node<K, V> pivot = root.right;
 507         Node<K, V> pivotLeft = pivot.left;
 508         Node<K, V> pivotRight = pivot.right;
 509 
 510         // move the pivot's left child to the root's right
 511         root.right = pivotLeft;
 512         if (pivotLeft != null) {
 513             pivotLeft.parent = root;
 514         }
 515 
 516         replaceInParent(root, pivot);
 517 
 518         // move the root to the pivot's left
 519         pivot.left = root;
 520         root.parent = pivot;
 521 
 522         // fix heights
 523         root.height = Math.max(left != null ? left.height : 0,
 524                 pivotLeft != null ? pivotLeft.height : 0) + 1;
 525         pivot.height = Math.max(root.height,
 526                 pivotRight != null ? pivotRight.height : 0) + 1;
 527     }
 528 
 529     /**
 530      * Rotates the subtree so that its root's left child is the new root.
 531      */
 532     private void rotateRight(Node<K, V> root) {
 533         Node<K, V> pivot = root.left;
 534         Node<K, V> right = root.right;
 535         Node<K, V> pivotLeft = pivot.left;
 536         Node<K, V> pivotRight = pivot.right;
 537 
 538         // move the pivot's right child to the root's left
 539         root.left = pivotRight;
 540         if (pivotRight != null) {
 541             pivotRight.parent = root;
 542         }
 543 
 544         replaceInParent(root, pivot);
 545 
 546         // move the root to the pivot's right
 547         pivot.right = root;
 548         root.parent = pivot;
 549 
 550         // fixup heights
 551         root.height = Math.max(right != null ? right.height : 0,
 552                 pivotRight != null ? pivotRight.height : 0) + 1;
 553         pivot.height = Math.max(root.height,
 554                 pivotLeft != null ? pivotLeft.height : 0) + 1;
 555     }
 556 
 557     /*
 558      * Navigable methods.
 559      */
 560 
 561     /**
 562      * Returns an immutable version of {@param entry}. Need this because we allow entry to be null,
 563      * in which case we return a null SimpleImmutableEntry.
 564      */
 565     private SimpleImmutableEntry<K, V> immutableCopy(Entry<K, V> entry) {
 566         return entry == null ? null : new SimpleImmutableEntry<K, V>(entry);
 567     }
 568 
 569     public Entry<K, V> firstEntry() {
 570         return immutableCopy(root == null ? null : root.first());
 571     }
 572 
 573     private Entry<K, V> internalPollFirstEntry() {
 574         if (root == null) {
 575             return null;
 576         }
 577         Node<K, V> result = root.first();
 578         removeInternal(result);
 579         return result;
 580     }
 581 
 582     public Entry<K, V> pollFirstEntry() {
 583         return immutableCopy(internalPollFirstEntry());
 584     }
 585 
 586     public K firstKey() {
 587         if (root == null) {
 588             throw new NoSuchElementException();
 589         }
 590         return root.first().getKey();
 591     }
 592 
 593     public Entry<K, V> lastEntry() {
 594         return immutableCopy(root == null ? null : root.last());
 595     }
 596 
 597     private Entry<K, V> internalPollLastEntry() {
 598         if (root == null) {
 599             return null;
 600         }
 601         Node<K, V> result = root.last();
 602         removeInternal(result);
 603         return result;
 604     }
 605 
 606     public Entry<K, V> pollLastEntry() {
 607         return immutableCopy(internalPollLastEntry());
 608     }
 609 
 610     public K lastKey() {
 611         if (root == null) {
 612             throw new NoSuchElementException();
 613         }
 614         return root.last().getKey();
 615     }
 616 
 617     public Entry<K, V> lowerEntry(K key) {
 618         return immutableCopy(find(key, LOWER));
 619     }
 620 
 621     public K lowerKey(K key) {
 622         Entry<K, V> entry = find(key, LOWER);
 623         return entry != null ? entry.getKey() : null;
 624     }
 625 
 626     public Entry<K, V> floorEntry(K key) {
 627         return immutableCopy(find(key, FLOOR));
 628     }
 629 
 630     public K floorKey(K key) {
 631         Entry<K, V> entry = find(key, FLOOR);
 632         return entry != null ? entry.getKey() : null;
 633     }
 634 
 635     public Entry<K, V> ceilingEntry(K key) {
 636         return immutableCopy(find(key, CEILING));
 637     }
 638 
 639     public K ceilingKey(K key) {
 640         Entry<K, V> entry = find(key, CEILING);
 641         return entry != null ? entry.getKey() : null;
 642     }
 643 
 644     public Entry<K, V> higherEntry(K key) {
 645         return immutableCopy(find(key, HIGHER));
 646     }
 647 
 648     public K higherKey(K key) {
 649         Entry<K, V> entry = find(key, HIGHER);
 650         return entry != null ? entry.getKey() : null;
 651     }
 652 
 653     public Comparator<? super K> comparator() {
 654         return comparator != NATURAL_ORDER ? comparator : null;
 655     }
 656 
 657     /*
 658      * View factory methods.
 659      */
 660 
 661     private EntrySet entrySet;
 662     private KeySet keySet;
 663 
 664     @Override public Set<Entry<K, V>> entrySet() {
 665         EntrySet result = entrySet;
 666         return result != null ? result : (entrySet = new EntrySet());
 667     }
 668 
 669     @Override public Set<K> keySet() {
 670         KeySet result = keySet;
 671         return result != null ? result : (keySet = new KeySet());
 672     }
 673 
 674     public NavigableSet<K> navigableKeySet() {
 675         KeySet result = keySet;
 676         return result != null ? result : (keySet = new KeySet());
 677     }
 678 
 679     public NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) {
 680         Bound fromBound = fromInclusive ? INCLUSIVE : EXCLUSIVE;
 681         Bound toBound = toInclusive ? INCLUSIVE : EXCLUSIVE;
 682         return new BoundedMap(true, from, fromBound, to, toBound);
 683     }
 684 
 685     public SortedMap<K, V> subMap(K fromInclusive, K toExclusive) {
 686         return new BoundedMap(true, fromInclusive, INCLUSIVE, toExclusive, EXCLUSIVE);
 687     }
 688 
 689     public NavigableMap<K, V> headMap(K to, boolean inclusive) {
 690         Bound toBound = inclusive ? INCLUSIVE : EXCLUSIVE;
 691         return new BoundedMap(true, null, NO_BOUND, to, toBound);
 692     }
 693 
 694     public SortedMap<K, V> headMap(K toExclusive) {
 695         return new BoundedMap(true, null, NO_BOUND, toExclusive, EXCLUSIVE);
 696     }
 697 
 698     public NavigableMap<K, V> tailMap(K from, boolean inclusive) {
 699         Bound fromBound = inclusive ? INCLUSIVE : EXCLUSIVE;
 700         return new BoundedMap(true, from, fromBound, null, NO_BOUND);
 701     }
 702 
 703     public SortedMap<K, V> tailMap(K fromInclusive) {
 704         return new BoundedMap(true, fromInclusive, INCLUSIVE, null, NO_BOUND);
 705     }
 706 
 707     public NavigableMap<K, V> descendingMap() {
 708         return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND);
 709     }
 710 
 711     public NavigableSet<K> descendingKeySet() {
 712         return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND).navigableKeySet();
 713     }
 714 
 715     static class Node<K, V> implements Map.Entry<K, V> {
 716         Node<K, V> parent;
 717         Node<K, V> left;
 718         Node<K, V> right;
 719         final K key;
 720         V value;
 721         int height;
 722 
 723         Node(Node<K, V> parent, K key) {
 724             this.parent = parent;
 725             this.key = key;
 726             this.height = 1;
 727         }
 728 
 729         Node<K, V> copy(Node<K, V> parent) {
 730             Node<K, V> result = new Node<K, V>(parent, key);
 731             if (left != null) {
 732                 result.left = left.copy(result);
 733             }
 734             if (right != null) {
 735                 result.right = right.copy(result);
 736             }
 737             result.value = value;
 738             result.height = height;
 739             return result;
 740         }
 741 
 742         public K getKey() {
 743             return key;
 744         }
 745 
 746         public V getValue() {
 747             return value;
 748         }
 749 
 750         public V setValue(V value) {
 751             V oldValue = this.value;
 752             this.value = value;
 753             return oldValue;
 754         }
 755 
 756         @Override public boolean equals(Object o) {
 757             if (o instanceof Map.Entry) {
 758                 Map.Entry other = (Map.Entry) o;
 759                 return (key == null ? other.getKey() == null : key.equals(other.getKey()))
 760                         && (value == null ? other.getValue() == null : value.equals(other.getValue()));
 761             }
 762             return false;
 763         }
 764 
 765         @Override public int hashCode() {
 766             return (key == null ? 0 : key.hashCode())
 767                     ^ (value == null ? 0 : value.hashCode());
 768         }
 769 
 770         @Override public String toString() {
 771             return key + "=" + value;
 772         }
 773 
 774         /**
 775          * Returns the next node in an inorder traversal, or null if this is the
 776          * last node in the tree.
 777          */
 778         Node<K, V> next() {
 779             if (right != null) {
 780                 return right.first();
 781             }
 782 
 783             Node<K, V> node = this;
 784             Node<K, V> parent = node.parent;
 785             while (parent != null) {
 786                 if (parent.left == node) {
 787                     return parent;
 788                 }
 789                 node = parent;
 790                 parent = node.parent;
 791             }
 792             return null;
 793         }
 794 
 795         /**
 796          * Returns the previous node in an inorder traversal, or null if this is
 797          * the first node in the tree.
 798          */
 799         public Node<K, V> prev() {
 800             if (left != null) {
 801                 return left.last();
 802             }
 803 
 804             Node<K, V> node = this;
 805             Node<K, V> parent = node.parent;
 806             while (parent != null) {
 807                 if (parent.right == node) {
 808                     return parent;
 809                 }
 810                 node = parent;
 811                 parent = node.parent;
 812             }
 813             return null;
 814         }
 815 
 816         /**
 817          * Returns the first node in this subtree.
 818          */
 819         public Node<K, V> first() {
 820             Node<K, V> node = this;
 821             Node<K, V> child = node.left;
 822             while (child != null) {
 823                 node = child;
 824                 child = node.left;
 825             }
 826             return node;
 827         }
 828 
 829         /**
 830          * Returns the last node in this subtree.
 831          */
 832         public Node<K, V> last() {
 833             Node<K, V> node = this;
 834             Node<K, V> child = node.right;
 835             while (child != null) {
 836                 node = child;
 837                 child = node.right;
 838             }
 839             return node;
 840         }
 841     }
 842 
 843     /**
 844      * Walk the nodes of the tree left-to-right or right-to-left. Note that in
 845      * descending iterations, {@code next} will return the previous node.
 846      */
 847     abstract class MapIterator<T> implements Iterator<T> {
 848         protected Node<K, V> next;
 849         protected Node<K, V> last;
 850         protected int expectedModCount = modCount;
 851 
 852         MapIterator(Node<K, V> next) {
 853             this.next = next;
 854         }
 855 
 856         public boolean hasNext() {
 857             return next != null;
 858         }
 859 
 860         protected Node<K, V> stepForward() {
 861             if (next == null) {
 862                 throw new NoSuchElementException();
 863             }
 864             if (modCount != expectedModCount) {
 865                 throw new ConcurrentModificationException();
 866             }
 867             last = next;
 868             next = next.next();
 869             return last;
 870         }
 871 
 872         protected Node<K, V> stepBackward() {
 873             if (next == null) {
 874                 throw new NoSuchElementException();
 875             }
 876             if (modCount != expectedModCount) {
 877                 throw new ConcurrentModificationException();
 878             }
 879             last = next;
 880             next = next.prev();
 881             return last;
 882         }
 883 
 884         public void remove() {
 885             if (last == null) {
 886                 throw new IllegalStateException();
 887             }
 888             removeInternal(last);
 889             expectedModCount = modCount;
 890             last = null;
 891         }
 892     }
 893 
 894     /*
 895      * View implementations.
 896      */
 897 
 898     class EntrySet extends AbstractSet<Map.Entry<K, V>> {
 899         @Override public int size() {
 900             return size;
 901         }
 902 
 903         @Override public Iterator<Entry<K, V>> iterator() {
 904             return new MapIterator<Entry<K, V>>(root == null ? null : root.first()) {
 905                 public Entry<K, V> next() {
 906                     return stepForward();
 907                 }
 908             };
 909         }
 910 
 911         @Override public boolean contains(Object o) {
 912             return o instanceof Entry && findByEntry((Entry<?, ?>) o) != null;
 913         }
 914 
 915         @Override public boolean remove(Object o) {
 916             if (!(o instanceof Entry)) {
 917                 return false;
 918             }
 919 
 920             Node<K, V> node = findByEntry((Entry<?, ?>) o);
 921             if (node == null) {
 922                 return false;
 923             }
 924             removeInternal(node);
 925             return true;
 926         }
 927 
 928         @Override public void clear() {
 929             TreeMap.this.clear();
 930         }
 931     }
 932 
 933     class KeySet extends AbstractSet<K> implements NavigableSet<K> {
 934         @Override public int size() {
 935             return size;
 936         }
 937 
 938         @Override public Iterator<K> iterator() {
 939             return new MapIterator<K>(root == null ? null : root.first()) {
 940                 public K next() {
 941                     return stepForward().key;
 942                 }
 943             };
 944         }
 945 
 946         public Iterator<K> descendingIterator() {
 947             return new MapIterator<K>(root == null ? null : root.last()) {
 948                 public K next() {
 949                     return stepBackward().key;
 950                 }
 951             };
 952         }
 953 
 954         @Override public boolean contains(Object o) {
 955             return containsKey(o);
 956         }
 957 
 958         @Override public boolean remove(Object key) {
 959             return removeInternalByKey(key) != null;
 960         }
 961 
 962         @Override public void clear() {
 963             TreeMap.this.clear();
 964         }
 965 
 966         public Comparator<? super K> comparator() {
 967             return TreeMap.this.comparator();
 968         }
 969 
 970         /*
 971          * Navigable methods.
 972          */
 973 
 974         public K first() {
 975             return firstKey();
 976         }
 977 
 978         public K last() {
 979             return lastKey();
 980         }
 981 
 982         public K lower(K key) {
 983             return lowerKey(key);
 984         }
 985 
 986         public K floor(K key) {
 987             return floorKey(key);
 988         }
 989 
 990         public K ceiling(K key) {
 991             return ceilingKey(key);
 992         }
 993 
 994         public K higher(K key) {
 995             return higherKey(key);
 996         }
 997 
 998         public K pollFirst() {
 999             Entry<K, V> entry = internalPollFirstEntry();
1000             return entry != null ? entry.getKey() : null;
1001         }
1002 
1003         public K pollLast() {
1004             Entry<K, V> entry = internalPollLastEntry();
1005             return entry != null ? entry.getKey() : null;
1006         }
1007 
1008         /*
1009          * View factory methods.
1010          */
1011 
1012         public NavigableSet<K> subSet(K from, boolean fromInclusive, K to, boolean toInclusive) {
1013             return TreeMap.this.subMap(from, fromInclusive, to, toInclusive).navigableKeySet();
1014         }
1015 
1016         public SortedSet<K> subSet(K fromInclusive, K toExclusive) {
1017             return TreeMap.this.subMap(fromInclusive, true, toExclusive, false).navigableKeySet();
1018         }
1019 
1020         public NavigableSet<K> headSet(K to, boolean inclusive) {
1021             return TreeMap.this.headMap(to, inclusive).navigableKeySet();
1022         }
1023 
1024         public SortedSet<K> headSet(K toExclusive) {
1025             return TreeMap.this.headMap(toExclusive, false).navigableKeySet();
1026         }
1027 
1028         public NavigableSet<K> tailSet(K from, boolean inclusive) {
1029             return TreeMap.this.tailMap(from, inclusive).navigableKeySet();
1030         }
1031 
1032         public SortedSet<K> tailSet(K fromInclusive) {
1033             return TreeMap.this.tailMap(fromInclusive, true).navigableKeySet();
1034         }
1035 
1036         public NavigableSet<K> descendingSet() {
1037             return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND).navigableKeySet();
1038         }
1039     }
1040 
1041     /*
1042      * Bounded views implementations.
1043      */
1044 
1045     enum Bound {
1046         INCLUSIVE {
1047             @Override public String leftCap(Object from) {
1048                 return "[" + from;
1049             }
1050             @Override public String rightCap(Object to) {
1051                 return to + "]";
1052             }
1053         },
1054         EXCLUSIVE {
1055             @Override public String leftCap(Object from) {
1056                 return "(" + from;
1057             }
1058             @Override public String rightCap(Object to) {
1059                 return to + ")";
1060             }
1061         },
1062         NO_BOUND {
1063             @Override public String leftCap(Object from) {
1064                 return ".";
1065             }
1066             @Override public String rightCap(Object to) {
1067                 return ".";
1068             }
1069         };
1070 
1071         public abstract String leftCap(Object from);
1072         public abstract String rightCap(Object to);
1073     }
1074 
1075     /**
1076      * A map with optional limits on its range.
1077      */
1078     final class BoundedMap extends AbstractMap<K, V> implements NavigableMap<K, V>, Serializable {
1079         private final transient boolean ascending;
1080         private final transient K from;
1081         private final transient Bound fromBound;
1082         private final transient K to;
1083         private final transient Bound toBound;
1084 
1085         BoundedMap(boolean ascending, K from, Bound fromBound, K to, Bound toBound) {
1086             /*
1087              * Validate the bounds. In addition to checking that from <= to, we
1088              * verify that the comparator supports our bound objects.
1089              */
1090             if (fromBound != NO_BOUND && toBound != NO_BOUND) {
1091                 if (comparator.compare(from, to) > 0) {
1092                     throw new IllegalArgumentException(from + " > " + to);
1093                 }
1094             } else if (fromBound != NO_BOUND) {
1095                 comparator.compare(from, from);
1096             } else if (toBound != NO_BOUND) {
1097                 comparator.compare(to, to);
1098             }
1099 
1100             this.ascending = ascending;
1101             this.from = from;
1102             this.fromBound = fromBound;
1103             this.to = to;
1104             this.toBound = toBound;
1105         }
1106 
1107         @Override public int size() {
1108             return count(entrySet().iterator());
1109         }
1110 
1111         @Override public boolean isEmpty() {
1112             return endpoint(true) == null;
1113         }
1114 
1115         @Override public V get(Object key) {
1116             return isInBounds(key) ? TreeMap.this.get(key) : null;
1117         }
1118 
1119         @Override public boolean containsKey(Object key) {
1120             return isInBounds(key) && TreeMap.this.containsKey(key);
1121         }
1122 
1123         @Override public V put(K key, V value) {
1124             if (!isInBounds(key)) {
1125                 throw outOfBounds(key, fromBound, toBound);
1126             }
1127             return putInternal(key, value);
1128         }
1129 
1130         @Override public V remove(Object key) {
1131             return isInBounds(key) ? TreeMap.this.remove(key) : null;
1132         }
1133 
1134         /**
1135          * Returns true if the key is in bounds.
1136          */
1137         @SuppressWarnings("unchecked") // this method throws ClassCastExceptions!
1138         private boolean isInBounds(Object key) {
1139             return isInBounds((K) key, fromBound, toBound);
1140         }
1141 
1142         /**
1143          * Returns true if the key is in bounds. Use this overload with
1144          * NO_BOUND to skip bounds checking on either end.
1145          */
1146         private boolean isInBounds(K key, Bound fromBound, Bound toBound) {
1147             if (fromBound == INCLUSIVE) {
1148                 if (comparator.compare(key, from) < 0) {
1149                     return false; // less than from
1150                 }
1151             } else if (fromBound == EXCLUSIVE) {
1152                 if (comparator.compare(key, from) <= 0) {
1153                     return false; // less than or equal to from
1154                 }
1155             }
1156 
1157             if (toBound == INCLUSIVE) {
1158                 if (comparator.compare(key, to) > 0) {
1159                     return false; // greater than 'to'
1160                 }
1161             } else if (toBound == EXCLUSIVE) {
1162                 if (comparator.compare(key, to) >= 0) {
1163                     return false; // greater than or equal to 'to'
1164                 }
1165             }
1166 
1167             return true;
1168         }
1169 
1170         /**
1171          * Returns the entry if it is in bounds, or null if it is out of bounds.
1172          */
1173         private Node<K, V> bound(Node<K, V> node, Bound fromBound, Bound toBound) {
1174             return node != null && isInBounds(node.getKey(), fromBound, toBound) ? node : null;
1175         }
1176 
1177         /*
1178          * Navigable methods.
1179          */
1180 
1181         public Entry<K, V> firstEntry() {
1182             return immutableCopy(endpoint(true));
1183         }
1184 
1185         public Entry<K, V> pollFirstEntry() {
1186             Node<K, V> result = endpoint(true);
1187             if (result != null) {
1188                 removeInternal(result);
1189             }
1190             return immutableCopy(result);
1191         }
1192 
1193         public K firstKey() {
1194             Entry<K, V> entry = endpoint(true);
1195             if (entry == null) {
1196                 throw new NoSuchElementException();
1197             }
1198             return entry.getKey();
1199         }
1200 
1201         public Entry<K, V> lastEntry() {
1202             return immutableCopy(endpoint(false));
1203         }
1204 
1205         public Entry<K, V> pollLastEntry() {
1206             Node<K, V> result = endpoint(false);
1207             if (result != null) {
1208                 removeInternal(result);
1209             }
1210             return immutableCopy(result);
1211         }
1212 
1213         public K lastKey() {
1214             Entry<K, V> entry = endpoint(false);
1215             if (entry == null) {
1216                 throw new NoSuchElementException();
1217             }
1218             return entry.getKey();
1219         }
1220 
1221         /**
1222          * @param first true for the first element, false for the last.
1223          */
1224         private Node<K, V> endpoint(boolean first) {
1225             Node<K, V> node;
1226             if (ascending == first) {
1227                 switch (fromBound) {
1228                     case NO_BOUND:
1229                         node = root == null ? null : root.first();
1230                         break;
1231                     case INCLUSIVE:
1232                         node = find(from, CEILING);
1233                         break;
1234                     case EXCLUSIVE:
1235                         node = find(from, HIGHER);
1236                         break;
1237                     default:
1238                         throw new AssertionError();
1239                 }
1240                 return bound(node, NO_BOUND, toBound);
1241             } else {
1242                 switch (toBound) {
1243                     case NO_BOUND:
1244                         node = root == null ? null : root.last();
1245                         break;
1246                     case INCLUSIVE:
1247                         node = find(to, FLOOR);
1248                         break;
1249                     case EXCLUSIVE:
1250                         node = find(to, LOWER);
1251                         break;
1252                     default:
1253                         throw new AssertionError();
1254                 }
1255                 return bound(node, fromBound, NO_BOUND);
1256             }
1257         }
1258 
1259         /**
1260          * Performs a find on the underlying tree after constraining it to the
1261          * bounds of this view. Examples:
1262          *
1263          *   bound is (A..C)
1264          *   findBounded(B, FLOOR) stays source.find(B, FLOOR)
1265          *
1266          *   bound is (A..C)
1267          *   findBounded(C, FLOOR) becomes source.find(C, LOWER)
1268          *
1269          *   bound is (A..C)
1270          *   findBounded(D, LOWER) becomes source.find(C, LOWER)
1271          *
1272          *   bound is (A..C]
1273          *   findBounded(D, FLOOR) becomes source.find(C, FLOOR)
1274          *
1275          *   bound is (A..C]
1276          *   findBounded(D, LOWER) becomes source.find(C, FLOOR)
1277          */
1278         private Entry<K, V> findBounded(K key, Relation relation) {
1279             relation = relation.forOrder(ascending);
1280             Bound fromBoundForCheck = fromBound;
1281             Bound toBoundForCheck = toBound;
1282 
1283             if (toBound != NO_BOUND && (relation == LOWER || relation == FLOOR)) {
1284                 int comparison = comparator.compare(to, key);
1285                 if (comparison <= 0) {
1286                     key = to;
1287                     if (toBound == EXCLUSIVE) {
1288                         relation = LOWER; // 'to' is too high
1289                     } else if (comparison < 0) {
1290                         relation = FLOOR; // we already went lower
1291                     }
1292                 }
1293                 toBoundForCheck = NO_BOUND; // we've already checked the upper bound
1294             }
1295 
1296             if (fromBound != NO_BOUND && (relation == CEILING || relation == HIGHER)) {
1297                 int comparison = comparator.compare(from, key);
1298                 if (comparison >= 0) {
1299                     key = from;
1300                     if (fromBound == EXCLUSIVE) {
1301                         relation = HIGHER; // 'from' is too low
1302                     } else if (comparison > 0) {
1303                         relation = CEILING; // we already went higher
1304                     }
1305                 }
1306                 fromBoundForCheck = NO_BOUND; // we've already checked the lower bound
1307             }
1308 
1309             return bound(find(key, relation), fromBoundForCheck, toBoundForCheck);
1310         }
1311 
1312         public Entry<K, V> lowerEntry(K key) {
1313             return immutableCopy(findBounded(key, LOWER));
1314         }
1315 
1316         public K lowerKey(K key) {
1317             Entry<K, V> entry = findBounded(key, LOWER);
1318             return entry != null ? entry.getKey() : null;
1319         }
1320 
1321         public Entry<K, V> floorEntry(K key) {
1322             return immutableCopy(findBounded(key, FLOOR));
1323         }
1324 
1325         public K floorKey(K key) {
1326             Entry<K, V> entry = findBounded(key, FLOOR);
1327             return entry != null ? entry.getKey() : null;
1328         }
1329 
1330         public Entry<K, V> ceilingEntry(K key) {
1331             return immutableCopy(findBounded(key, CEILING));
1332         }
1333 
1334         public K ceilingKey(K key) {
1335             Entry<K, V> entry = findBounded(key, CEILING);
1336             return entry != null ? entry.getKey() : null;
1337         }
1338 
1339         public Entry<K, V> higherEntry(K key) {
1340             return immutableCopy(findBounded(key, HIGHER));
1341         }
1342 
1343         public K higherKey(K key) {
1344             Entry<K, V> entry = findBounded(key, HIGHER);
1345             return entry != null ? entry.getKey() : null;
1346         }
1347 
1348         public Comparator<? super K> comparator() {
1349           if (ascending) {
1350             return TreeMap.this.comparator();
1351           } else {
1352             return Collections.reverseOrder(comparator);
1353           }
1354         }
1355 
1356         /*
1357          * View factory methods.
1358          */
1359 
1360         private transient BoundedEntrySet entrySet;
1361         private transient BoundedKeySet keySet;
1362 
1363         @Override public Set<Entry<K, V>> entrySet() {
1364             BoundedEntrySet result = entrySet;
1365             return result != null ? result : (entrySet = new BoundedEntrySet());
1366         }
1367 
1368         @Override public Set<K> keySet() {
1369             return navigableKeySet();
1370         }
1371 
1372         public NavigableSet<K> navigableKeySet() {
1373             BoundedKeySet result = keySet;
1374             return result != null ? result : (keySet = new BoundedKeySet());
1375         }
1376 
1377         public NavigableMap<K, V> descendingMap() {
1378             return new BoundedMap(!ascending, from, fromBound, to, toBound);
1379         }
1380 
1381         public NavigableSet<K> descendingKeySet() {
1382             return new BoundedMap(!ascending, from, fromBound, to, toBound).navigableKeySet();
1383         }
1384 
1385         public NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) {
1386             Bound fromBound = fromInclusive ? INCLUSIVE : EXCLUSIVE;
1387             Bound toBound = toInclusive ? INCLUSIVE : EXCLUSIVE;
1388             return subMap(from, fromBound, to, toBound);
1389         }
1390 
1391         public NavigableMap<K, V> subMap(K fromInclusive, K toExclusive) {
1392             return subMap(fromInclusive, INCLUSIVE, toExclusive, EXCLUSIVE);
1393         }
1394 
1395         public NavigableMap<K, V> headMap(K to, boolean inclusive) {
1396             Bound toBound = inclusive ? INCLUSIVE : EXCLUSIVE;
1397             return subMap(null, NO_BOUND, to, toBound);
1398         }
1399 
1400         public NavigableMap<K, V> headMap(K toExclusive) {
1401             return subMap(null, NO_BOUND, toExclusive, EXCLUSIVE);
1402         }
1403 
1404         public NavigableMap<K, V> tailMap(K from, boolean inclusive) {
1405             Bound fromBound = inclusive ? INCLUSIVE : EXCLUSIVE;
1406             return subMap(from, fromBound, null, NO_BOUND);
1407         }
1408 
1409         public NavigableMap<K, V> tailMap(K fromInclusive) {
1410             return subMap(fromInclusive, INCLUSIVE, null, NO_BOUND);
1411         }
1412 
1413         private NavigableMap<K, V> subMap(K from, Bound fromBound, K to, Bound toBound) {
1414             if (!ascending) {
1415                 K fromTmp = from;
1416                 Bound fromBoundTmp = fromBound;
1417                 from = to;
1418                 fromBound = toBound;
1419                 to = fromTmp;
1420                 toBound = fromBoundTmp;
1421             }
1422 
1423             /*
1424              * If both the current and requested bounds are exclusive, the isInBounds check must be
1425              * inclusive. For example, to create (C..F) from (A..F), the bound 'F' is in bounds.
1426              */
1427 
1428             if (fromBound == NO_BOUND) {
1429                 from = this.from;
1430                 fromBound = this.fromBound;
1431             } else {
1432                 Bound fromBoundToCheck = fromBound == this.fromBound ? INCLUSIVE : this.fromBound;
1433                 if (!isInBounds(from, fromBoundToCheck, this.toBound)) {
1434                     throw outOfBounds(to, fromBoundToCheck, this.toBound);
1435                 }
1436             }
1437 
1438             if (toBound == NO_BOUND) {
1439                 to = this.to;
1440                 toBound = this.toBound;
1441             } else {
1442                 Bound toBoundToCheck = toBound == this.toBound ? INCLUSIVE : this.toBound;
1443                 if (!isInBounds(to, this.fromBound, toBoundToCheck)) {
1444                     throw outOfBounds(to, this.fromBound, toBoundToCheck);
1445                 }
1446             }
1447 
1448             return new BoundedMap(ascending, from, fromBound, to, toBound);
1449         }
1450 
1451         private IllegalArgumentException outOfBounds(Object value, Bound fromBound, Bound toBound) {
1452             return new IllegalArgumentException(value + " not in range "
1453                     + fromBound.leftCap(from) + ".." + toBound.rightCap(to));
1454         }
1455 
1456         /*
1457          * Bounded view implementations.
1458          */
1459 
1460         abstract class BoundedIterator<T> extends MapIterator<T> {
1461             protected BoundedIterator(Node<K, V> next) {
1462                 super(next);
1463             }
1464 
1465             @Override protected Node<K, V> stepForward() {
1466                 Node<K, V> result = super.stepForward();
1467                 if (next != null && !isInBounds(next.key, NO_BOUND, toBound)) {
1468                     next = null;
1469                 }
1470                 return result;
1471             }
1472 
1473             @Override protected Node<K, V> stepBackward() {
1474                 Node<K, V> result = super.stepBackward();
1475                 if (next != null && !isInBounds(next.key, fromBound, NO_BOUND)) {
1476                     next = null;
1477                 }
1478                 return result;
1479             }
1480         }
1481 
1482         final class BoundedEntrySet extends AbstractSet<Entry<K, V>> {
1483             @Override public int size() {
1484                 return BoundedMap.this.size();
1485             }
1486 
1487             @Override public boolean isEmpty() {
1488                 return BoundedMap.this.isEmpty();
1489             }
1490 
1491             @Override public Iterator<Entry<K, V>> iterator() {
1492                 return new BoundedIterator<Entry<K, V>>(endpoint(true)) {
1493                     public Entry<K, V> next() {
1494                         return ascending ? stepForward() : stepBackward();
1495                     }
1496                 };
1497             }
1498 
1499             @Override public boolean contains(Object o) {
1500                 if (!(o instanceof Entry)) {
1501                     return false;
1502                 }
1503                 Entry<?, ?> entry = (Entry<?, ?>) o;
1504                 return isInBounds(entry.getKey()) && findByEntry(entry) != null;
1505             }
1506 
1507             @Override public boolean remove(Object o) {
1508                 if (!(o instanceof Entry)) {
1509                     return false;
1510                 }
1511                 Entry<?, ?> entry = (Entry<?, ?>) o;
1512                 return isInBounds(entry.getKey()) && TreeMap.this.entrySet().remove(entry);
1513             }
1514         }
1515 
1516         final class BoundedKeySet extends AbstractSet<K> implements NavigableSet<K> {
1517             @Override public int size() {
1518                 return BoundedMap.this.size();
1519             }
1520 
1521             @Override public boolean isEmpty() {
1522                 return BoundedMap.this.isEmpty();
1523             }
1524 
1525             @Override public Iterator<K> iterator() {
1526                 return new BoundedIterator<K>(endpoint(true)) {
1527                     public K next() {
1528                         return (ascending ? stepForward() : stepBackward()).key;
1529                     }
1530                 };
1531             }
1532 
1533             public Iterator<K> descendingIterator() {
1534                 return new BoundedIterator<K>(endpoint(false)) {
1535                     public K next() {
1536                         return (ascending ? stepBackward() : stepForward()).key;
1537                     }
1538                 };
1539             }
1540 
1541             @Override public boolean contains(Object key) {
1542                 return isInBounds(key) && findByObject(key) != null;
1543             }
1544 
1545             @Override public boolean remove(Object key) {
1546                 return isInBounds(key) && removeInternalByKey(key) != null;
1547             }
1548 
1549             /*
1550              * Navigable methods.
1551              */
1552 
1553             public K first() {
1554                 return firstKey();
1555             }
1556 
1557             public K pollFirst() {
1558                 Entry<K, ?> entry = pollFirstEntry();
1559                 return entry != null ? entry.getKey() : null;
1560             }
1561 
1562             public K last() {
1563                 return lastKey();
1564             }
1565 
1566             public K pollLast() {
1567                 Entry<K, ?> entry = pollLastEntry();
1568                 return entry != null ? entry.getKey() : null;
1569             }
1570 
1571             public K lower(K key) {
1572                 return lowerKey(key);
1573             }
1574 
1575             public K floor(K key) {
1576                 return floorKey(key);
1577             }
1578 
1579             public K ceiling(K key) {
1580                 return ceilingKey(key);
1581             }
1582 
1583             public K higher(K key) {
1584                 return higherKey(key);
1585             }
1586 
1587             public Comparator<? super K> comparator() {
1588                 return BoundedMap.this.comparator();
1589             }
1590 
1591             /*
1592              * View factory methods.
1593              */
1594 
1595             public NavigableSet<K> subSet(K from, boolean fromInclusive, K to, boolean toInclusive) {
1596                 return subMap(from, fromInclusive, to, toInclusive).navigableKeySet();
1597             }
1598 
1599             public SortedSet<K> subSet(K fromInclusive, K toExclusive) {
1600                 return subMap(fromInclusive, toExclusive).navigableKeySet();
1601             }
1602 
1603             public NavigableSet<K> headSet(K to, boolean inclusive) {
1604                 return headMap(to, inclusive).navigableKeySet();
1605             }
1606 
1607             public SortedSet<K> headSet(K toExclusive) {
1608                 return headMap(toExclusive).navigableKeySet();
1609             }
1610 
1611             public NavigableSet<K> tailSet(K from, boolean inclusive) {
1612                 return tailMap(from, inclusive).navigableKeySet();
1613             }
1614 
1615             public SortedSet<K> tailSet(K fromInclusive) {
1616                 return tailMap(fromInclusive).navigableKeySet();
1617             }
1618 
1619             public NavigableSet<K> descendingSet() {
1620                 return new BoundedMap(!ascending, from, fromBound, to, toBound).navigableKeySet();
1621             }
1622         }
1623 
1624         Object writeReplace() throws ObjectStreamException {
1625             return ascending
1626                     ? new AscendingSubMap<K, V>(TreeMap.this, from, fromBound, to, toBound)
1627                     : new DescendingSubMap<K, V>(TreeMap.this, from, fromBound, to, toBound);
1628         }
1629     }
1630 
1631     /**
1632      * Returns the number of elements in the iteration.
1633      */
1634     static int count(Iterator<?> iterator) {
1635         int count = 0;
1636         while (iterator.hasNext()) {
1637             iterator.next();
1638             count++;
1639         }
1640         return count;
1641     }
1642 
1643     /*
1644      * Serialization
1645      */
1646 
1647     private static final long serialVersionUID = 919286545866124006L;
1648 
1649     private void writeObject(ObjectOutputStream stream) throws IOException {
1650         stream.putFields().put("comparator", comparator != NATURAL_ORDER ? comparator : null);
1651         stream.writeFields();
1652         stream.writeInt(size);
1653         for (Map.Entry<K, V> entry : entrySet()) {
1654             stream.writeObject(entry.getKey());
1655             stream.writeObject(entry.getValue());
1656         }
1657     }
1658 
1659     @SuppressWarnings("unchecked") // we have to trust that keys are Ks and values are Vs
1660     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1661         GetField fields = stream.readFields();
1662         comparator = (Comparator<? super K>) fields.get("comparator", null);
1663         if (comparator == null) {
1664             comparator = (Comparator<? super K>) NATURAL_ORDER;
1665         }
1666         int size = stream.readInt();
1667         for (int i = 0; i < size; i++) {
1668             putInternal((K) stream.readObject(), (V) stream.readObject());
1669         }
1670     }
1671 
1672     static abstract class NavigableSubMap<K, V> extends AbstractMap<K, V> implements Serializable {
1673         private static final long serialVersionUID = -2102997345730753016L;
1674         TreeMap<K, V> m;
1675         Object lo;
1676         Object hi;
1677         boolean fromStart;
1678         boolean toEnd;
1679         boolean loInclusive;
1680         boolean hiInclusive;
1681 
1682         NavigableSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) {
1683             this.m = delegate;
1684             this.lo = from;
1685             this.hi = to;
1686             this.fromStart = fromBound == NO_BOUND;
1687             this.toEnd = toBound == NO_BOUND;
1688             this.loInclusive = fromBound == INCLUSIVE;
1689             this.hiInclusive = toBound == INCLUSIVE;
1690         }
1691 
1692         @Override public Set<Entry<K, V>> entrySet() {
1693             throw new UnsupportedOperationException();
1694         }
1695 
1696         @SuppressWarnings("unchecked") // we have to trust that the bounds are Ks
1697         protected Object readResolve() throws ObjectStreamException {
1698             Bound fromBound = fromStart ? NO_BOUND : (loInclusive ? INCLUSIVE : EXCLUSIVE);
1699             Bound toBound = toEnd ? NO_BOUND : (hiInclusive ? INCLUSIVE : EXCLUSIVE);
1700             boolean ascending = !(this instanceof DescendingSubMap);
1701             return m.new BoundedMap(ascending, (K) lo, fromBound, (K) hi, toBound);
1702         }
1703     }
1704 
1705     static class DescendingSubMap<K, V> extends NavigableSubMap<K, V> {
1706         private static final long serialVersionUID = 912986545866120460L;
1707         Comparator<K> reverseComparator;
1708         DescendingSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) {
1709             super(delegate, from, fromBound, to, toBound);
1710         }
1711     }
1712 
1713     static class AscendingSubMap<K, V> extends NavigableSubMap<K, V> {
1714         private static final long serialVersionUID = 912986545866124060L;
1715         AscendingSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) {
1716             super(delegate, from, fromBound, to, toBound);
1717         }
1718     }
1719 
1720     class SubMap extends AbstractMap<K, V> implements Serializable {
1721         private static final long serialVersionUID = -6520786458950516097L;
1722         Object fromKey;
1723         Object toKey;
1724         boolean fromStart;
1725         boolean toEnd;
1726 
1727         @Override public Set<Entry<K, V>> entrySet() {
1728             throw new UnsupportedOperationException();
1729         }
1730 
1731         @SuppressWarnings("unchecked") // we have to trust that the bounds are Ks
1732         protected Object readResolve() throws ObjectStreamException {
1733             Bound fromBound = fromStart ? NO_BOUND : INCLUSIVE;
1734             Bound toBound = toEnd ? NO_BOUND : EXCLUSIVE;
1735             return new BoundedMap(true, (K) fromKey, fromBound, (K) toKey, toBound);
1736         }
1737     }
1738 }
View Code

 

 

Implementations

Hash Table

Resizable Array

Balanced Tree

Linked List

Hash Table + Linked List

Interfaces

Set

HashSet

 

TreeSet

 

LinkedHashSet

List

 

ArrayList

 

LinkedList

 

Deque

 

ArrayDeque

 

LinkedList

 

Map

HashMap

 

TreeMap

 

LinkedHashMap

 

 

是否有序

是否允许重复

是否线程同步

Collection

 

List

ArrayList

Vector

LinkedList

Set

HashSet

TreeSet

Map

HashMap

<key, value>,

key不允许重复

TreeMap

Hashtable

How to use:http://www.cnblogs.com/kiant71/archive/2008/09/04/1752079.html

posted @ 2013-08-07 17:52  iDragon  阅读(306)  评论(0)    收藏  举报