zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    20165103 第四周查漏补缺
    20165103 2017-2018-2 《Java程序设计》第3周学习总结
    20165103 2017-2018-2 《Java程序设计》第2周学习总结
    20165103 2017-2018-2 《Java程序设计》第1周学习总结
    MySQL事务一致性理解
    mysql的事务四个特性以及 事务的四个隔离级别
    序列化和反序列化的简单理解
    内存溢出和内存泄漏的区别,产生原因以及解决方案
    oracle入门学习之oracle数据库结构
    Java微服务(Spring-boot+MyBatis+Maven)入门教程
  • 原文地址:https://www.cnblogs.com/iiiDragon/p/3243655.html
Copyright © 2011-2022 走看看