@TOC

基础知识概述

基础知识:集合、泛型、异常、反射、注解、内部类、序列化。

集合框架概述

接口:Collection接口、Map接口。Java集合框架图,如下:

Java基础知识概述 - 图1

Collections,提供了对集合进行排序、遍历等多种算法实现;
Arrays,提供了大量的静态方法,用来实现数组常见的操作;
自定义的集合类型,那么类需要有Comparable或者Comparator接口的支持;
Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法;
ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口;

Iterator接口

    迭代器(Iterator)主要用来操作java中的集合对象(Collection),迭代器提供了统一的语法进行集合对象(Collection)遍历操作,无需关心集合对象内部的实现方式,
    Iterator只能向前移,无法后退;

  1. public interface Iterator<E> {
  2. boolean hasNext();//判断是否还有下一个对象,如果有,则返回true,否则false
  3. E next();//返回集合的下个值,此方法只能在hasNext方法返回true时调用
  4. void remove();//删除集合的当前值,此方法也只能在hasNext方法返回true时调用
  5. }

Iterable接口

    jdk1.5之后新增了Iterable接口用于支持foreach循环,所有实现Iterable接口的对象都可以实现foreach循环操作。

  1. public interface Iterable<T> {
  2. Iterator<T> iterator();//返回集合的Iterator对象
  3. default void forEach(Consumer<? super T> action) {// JDK1.8 新增遍历方式
  4. Objects.requireNonNull(action);
  5. for (T t : this) {
  6. action.accept(t);
  7. }
  8. }
  9. default Spliterator<T> spliterator() {// 可分割迭代器
  10. return Spliterators.spliteratorUnknownSize(iterator(), 0);
  11. }
  12. }

Collection接口

    Collection接口是所有集合类的根节点,Collection表示一种规则,所有实现了Collection接口的类遵循这种规则。
    一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许有重复的元素(例如List),但是另一些则不允许有重复的元素,即可为无序的(如Set)。
    所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有参数的构造函数用于创建一个具有与其参数相同元素的新的Collection。实际上,后者允许用户复制任何Collection,以生产所需实现类型的一个等效Collection。尽管无法强制执行此约定(因为接口不能包含构造方法),但是Java平台库中所有通用的Collection实现都遵从它。
    JDK不提供此接口的任何直接实现—-它会提供更为具体的子接口(如Set和List)。

  1. public interface Collection<E> extends Iterable<E> {
  2. // Query Operations
  3. int size();//返回集合中元素的个数
  4. boolean isEmpty();//判断集合是否为空集合,为空返回true
  5. boolean contains(Object o);//判断集合中是否存在指定元素,存在返回true
  6. Iterator<E> iterator();//返回集合遍历的迭代器
  7. Object[] toArray();//集合转变成数组
  8. <T> T[] toArray(T[] a);//将指定集合转变成相应的数组
  9. // Modification Operations
  10. boolean add(E e);//往集合中添加元素,添加成功返回true
  11. boolean remove(Object o);//从集合中删除指定的元素,删除成功返回true
  12. // Bulk Operations
  13. boolean containsAll(Collection<?> c);//判断集合中是否包含集合c,包含则返回true
  14. boolean addAll(Collection<? extends E> c);//将集合c添加到集合中,添加成功返回true
  15. boolean removeAll(Collection<?> c);//从集合中删除集合c,删除成功返回true
  16. default boolean removeIf(Predicate<? super E> filter) {//删除集合中符合条件的元素,删除成功返回true(从1.8开始提供)
  17. Objects.requireNonNull(filter);
  18. boolean removed = false;
  19. final Iterator<E> each = iterator();
  20. while (each.hasNext()) {
  21. if (filter.test(each.next())) {
  22. each.remove();
  23. removed = true;
  24. }
  25. }
  26. return removed;
  27. }
  28. boolean retainAll(Collection<?> c);//保留集合中集合c从中的元素
  29. void clear();//清空集合中的所有元素
  30. // Comparison and hashing
  31. boolean equals(Object o);//判断对象是否和对象o内容一致,是则返回true
  32. int hashCode();//计算对象的哈希码值
  33. @Override
  34. default Spliterator<E> spliterator() {//(从1.8开始提供)
  35. return Spliterators.spliterator(this, 0);
  36. }
  37. default Stream<E> stream() {//(从1.8开始提供)
  38. return StreamSupport.stream(spliterator(), false);
  39. }
  40. default Stream<E> parallelStream() {//(从1.8开始提供)
  41. return StreamSupport.stream(spliterator(), true);
  42. }
  43. }

    AbstractCollection抽象类,Collection接口的骨架实现类,最小化实现了Collection接口所需要实现的工作量,主要作用是方便其他类实现Collection。
    AbstractCollection抽象类,实现了Collection中除了iterator()和size()之外的所有(公共)方法。其他集合想要实现Collection,通过继承AbstractCollection抽象类,以及覆写iterator()和size() 即可。

Map接口

    Map接口,储存一键-值对的对象接口,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。
    给定一个键和一个值,你可以将该值存储在一个Map对象。可以通过键来访问对应的值。
    当访问的值不存在的时候,方法就会抛出一个 NoSuchElementException 异常。
    当对象的类型和 Map 里元素类型不兼容的时候,就会抛出一个 ClassCastException 异常。
    当在不允许使用 Null 对象的 Map (例如,TreeMap)中使用 Null 对象,会抛出一个 NullPointerException 异常。
    当尝试修改一个只读的 Map 时,会抛出一个 UnsupportedOperationException 异常。
    基本上所有的 Map 接口实现类都使用 put() 方法存入数据、用get() 方法去除数据,使用 entrySet/keySet 迭代获取 Map 数据。

  1. public interface Map<K,V> {
  2. // Query Operations
  3. int size();//返回map中Map.Entry的个数
  4. boolean isEmpty();//判断map是否为空map,为空返回true
  5. boolean containsKey(Object key);//判断map中是否存在指定key,存在返回true
  6. boolean containsValue(Object value);//判断map中是否存在指定value,存在返回true
  7. V get(Object key);//获取指定键(key)所对应的值(value)
  8. // Modification Operations
  9. /*
  10. *若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中
  11. *若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值
  12. */
  13. V put(K key, V value);//将指定的键与值对应起来,并添加到集合中
  14. V remove(Object key);//根据指定的键(key)删除元素,返回被删除元素的值(value)
  15. // Bulk Operations
  16. void putAll(Map<? extends K, ? extends V> m);//从指定映射中将所有映射关系复制到此映射中(可选操作)
  17. void clear();//移除map的所有映射
  18. // Views
  19. /*
  20. *通过键找值,来实现的遍历
  21. *1.调用 Map 集合的方法 keySet,将所有的键(key对象)存储到Set集合中
  22. *2.遍历 Set 集合,获取出 Set 集合中的所有元素 ( Map 中的键(key对象))
  23. *3.调用 Map 集合 get 方法,通过键(key对象)获取到值(value对象)
  24. */
  25. Set<K> keySet();//将所有的键(key对象)存储到Set集合中
  26. Collection<V> values();//将所有的值(value对象)存储到集合数组中
  27. Set<Map.Entry<K, V>> entrySet();//将所有的Map.Entry存储到Set集合中,
  28. interface Entry<K,V> {//1.2,嵌套接口,将键值对的对应关系封装成了对象,即键值对对象
  29. K getKey();//获取map的键(key对象)
  30. V getValue();//获取map的值(value对象)
  31. V setValue(V value);//存储map的值(value对象)
  32. boolean equals(Object o);//判断键(key对象)或值(value对象)是否与对象o内容一致
  33. int hashCode();//计算键(key对象)的哈希码值
  34. public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {//1.8,compareTo(),key对象比较
  35. return (Comparator<Map.Entry<K, V>> & Serializable)
  36. (c1, c2) -> c1.getKey().compareTo(c2.getKey());
  37. }
  38. public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {//1.8,compareTo(),value对象比较
  39. return (Comparator<Map.Entry<K, V>> & Serializable)
  40. (c1, c2) -> c1.getValue().compareTo(c2.getValue());
  41. }
  42. public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {//1.8,(比较器cmp).compare(),key对象比较
  43. Objects.requireNonNull(cmp);
  44. return (Comparator<Map.Entry<K, V>> & Serializable)
  45. (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
  46. }
  47. public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {//1.8,(比较器cmp).compare(),value对象比较
  48. Objects.requireNonNull(cmp);
  49. return (Comparator<Map.Entry<K, V>> & Serializable)
  50. (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
  51. }
  52. }
  53. // Comparison and hashing
  54. boolean equals(Object o);//比较指定对象与此 Map 的等价性
  55. int hashCode();//返回此 Map 的哈希码
  56. // Defaultable methods
  57. default V getOrDefault(Object key, V defaultValue) {//1.8,
  58. V v;
  59. return (((v = get(key)) != null) || containsKey(key))
  60. ? v
  61. : defaultValue;
  62. }
  63. default void forEach(BiConsumer<? super K, ? super V> action) {//1.8,
  64. Objects.requireNonNull(action);
  65. for (Map.Entry<K, V> entry : entrySet()) {
  66. K k;
  67. V v;
  68. try {
  69. k = entry.getKey();
  70. v = entry.getValue();
  71. } catch(IllegalStateException ise) {
  72. // this usually means the entry is no longer in the map.
  73. throw new ConcurrentModificationException(ise);
  74. }
  75. action.accept(k, v);
  76. }
  77. }
  78. default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {//1.8
  79. Objects.requireNonNull(function);
  80. for (Map.Entry<K, V> entry : entrySet()) {
  81. K k;
  82. V v;
  83. try {
  84. k = entry.getKey();
  85. v = entry.getValue();
  86. } catch(IllegalStateException ise) {
  87. // this usually means the entry is no longer in the map.
  88. throw new ConcurrentModificationException(ise);
  89. }
  90. // ise thrown from function is not a cme.
  91. v = function.apply(k, v);
  92. try {
  93. entry.setValue(v);
  94. } catch(IllegalStateException ise) {
  95. // this usually means the entry is no longer in the map.
  96. throw new ConcurrentModificationException(ise);
  97. }
  98. }
  99. }
  100. default V putIfAbsent(K key, V value) {//1.8
  101. V v = get(key);
  102. if (v == null) {
  103. v = put(key, value);
  104. }
  105. return v;
  106. }
  107. default boolean remove(Object key, Object value) {//1.8,从 Map 中删除键和关联的值
  108. Object curValue = get(key);
  109. if (!Objects.equals(curValue, value) ||
  110. (curValue == null && !containsKey(key))) {
  111. return false;
  112. }
  113. remove(key);
  114. return true;
  115. }
  116. default boolean replace(K key, V oldValue, V newValue) {//1.8
  117. Object curValue = get(key);
  118. if (!Objects.equals(curValue, oldValue) ||
  119. (curValue == null && !containsKey(key))) {
  120. return false;
  121. }
  122. put(key, newValue);
  123. return true;
  124. }
  125. default V replace(K key, V value) {//1.8
  126. V curValue;
  127. if (((curValue = get(key)) != null) || containsKey(key)) {
  128. curValue = put(key, value);
  129. }
  130. return curValue;
  131. }
  132. default V computeIfAbsent(K key,
  133. Function<? super K, ? extends V> mappingFunction) {//1.8
  134. Objects.requireNonNull(mappingFunction);
  135. V v;
  136. if ((v = get(key)) == null) {
  137. V newValue;
  138. if ((newValue = mappingFunction.apply(key)) != null) {
  139. put(key, newValue);
  140. return newValue;
  141. }
  142. }
  143. return v;
  144. }
  145. default V computeIfPresent(K key,
  146. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {//1.8
  147. Objects.requireNonNull(remappingFunction);
  148. V oldValue;
  149. if ((oldValue = get(key)) != null) {
  150. V newValue = remappingFunction.apply(key, oldValue);
  151. if (newValue != null) {
  152. put(key, newValue);
  153. return newValue;
  154. } else {
  155. remove(key);
  156. return null;
  157. }
  158. } else {
  159. return null;
  160. }
  161. }
  162. default V compute(K key,
  163. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {//1.8
  164. Objects.requireNonNull(remappingFunction);
  165. V oldValue = get(key);
  166. V newValue = remappingFunction.apply(key, oldValue);
  167. if (newValue == null) {
  168. // delete mapping
  169. if (oldValue != null || containsKey(key)) {
  170. // something to remove
  171. remove(key);
  172. return null;
  173. } else {
  174. // nothing to do. Leave things as they were.
  175. return null;
  176. }
  177. } else {
  178. // add or replace old mapping
  179. put(key, newValue);
  180. return newValue;
  181. }
  182. }
  183. default V merge(K key, V value,
  184. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {//(从1.8提供)
  185. Objects.requireNonNull(remappingFunction);
  186. Objects.requireNonNull(value);
  187. V oldValue = get(key);
  188. V newValue = (oldValue == null) ? value :
  189. remappingFunction.apply(oldValue, value);
  190. if(newValue == null) {
  191. remove(key);
  192. } else {
  193. put(key, newValue);
  194. }
  195. return newValue;
  196. }
  197. }

    AbstractMap抽象类,除了entrySet()这个方法定义为抽象的,Map接口中的其它方法(公共方法)都已经给出实现。需要注意的是,实现了keySet()方法,巧妙使用entrySet()的迭代器遍历,不需要每次新增都遍历所有entry。
    AbstractMap抽象类,包含了Map.Entry接口的两个静态内部实现类:SimpleEntry和SimpleImmutableEntry。不可变,为事实不可变,因为它不提供setValue方法。
    AbstractMap抽象类,包含两个字段:keySet和values,分别存储键集合和值集合。这两个字段是transient修饰的,子类决定如何去序列化。

Collections工具类

    Collections是一个操作集合的工具类。
    常见方法:
1.对list集合排序:sort(list);sort(list,comparator);
2.对list进行二分法查找:int binarySearch(list,key);int binarySearch(list,key,Comparator);
3.按照指定比较器进行排序:max(Collection); max(Collection,comparator); min(Collection); min(Collection,comparator);
4.对list集合进行反转: reverse(list);
5.将不同步的集合变为同步的集合: Set synchronizedSet(SET s); Map synchronizedMaP(Map m);List synchronizedList(List list);

  1. public class Collections {
  2. private Collections() {}
  3. // Algorithms
  4. private static final int BINARYSEARCH_THRESHOLD = 5000;
  5. private static final int REVERSE_THRESHOLD = 18;
  6. private static final int SHUFFLE_THRESHOLD = 5;
  7. private static final int FILL_THRESHOLD = 25;
  8. private static final int ROTATE_THRESHOLD = 100;
  9. private static final int COPY_THRESHOLD = 10;
  10. private static final int REPLACEALL_THRESHOLD = 11;
  11. private static final int INDEXOFSUBLIST_THRESHOLD = 35;
  12. @SuppressWarnings("unchecked")
  13. public static <T extends Comparable<? super T>> void sort(List<T> list) {
  14. list.sort(null);
  15. }
  16. @SuppressWarnings({"unchecked", "rawtypes"})
  17. public static <T> void sort(List<T> list, Comparator<? super T> c) {
  18. list.sort(c);
  19. }
  20. public static <T>
  21. int binarySearch(List<? extends Comparable<? super T>> list, T key) {
  22. if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
  23. return Collections.indexedBinarySearch(list, key);
  24. else
  25. return Collections.iteratorBinarySearch(list, key);
  26. }
  27. private static <T>
  28. int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
  29. int low = 0;
  30. int high = list.size()-1;
  31. while (low <= high) {
  32. int mid = (low + high) >>> 1;
  33. Comparable<? super T> midVal = list.get(mid);
  34. int cmp = midVal.compareTo(key);
  35. if (cmp < 0)
  36. low = mid + 1;
  37. else if (cmp > 0)
  38. high = mid - 1;
  39. else
  40. return mid; // key found
  41. }
  42. return -(low + 1); // key not found
  43. }
  44. private static <T>
  45. int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
  46. {
  47. int low = 0;
  48. int high = list.size()-1;
  49. ListIterator<? extends Comparable<? super T>> i = list.listIterator();
  50. while (low <= high) {
  51. int mid = (low + high) >>> 1;
  52. Comparable<? super T> midVal = get(i, mid);
  53. int cmp = midVal.compareTo(key);
  54. if (cmp < 0)
  55. low = mid + 1;
  56. else if (cmp > 0)
  57. high = mid - 1;
  58. else
  59. return mid; // key found
  60. }
  61. return -(low + 1); // key not found
  62. }
  63. /**
  64. * Gets the ith element from the given list by repositioning the specified
  65. * list listIterator.
  66. */
  67. private static <T> T get(ListIterator<? extends T> i, int index) {
  68. T obj = null;
  69. int pos = i.nextIndex();
  70. if (pos <= index) {
  71. do {
  72. obj = i.next();
  73. } while (pos++ < index);
  74. } else {
  75. do {
  76. obj = i.previous();
  77. } while (--pos > index);
  78. }
  79. return obj;
  80. }
  81. /**
  82. * Searches the specified list for the specified object using the binary
  83. * search algorithm. The list must be sorted into ascending order
  84. * according to the specified comparator (as by the
  85. * {@link #sort(List, Comparator) sort(List, Comparator)}
  86. * method), prior to making this call. If it is
  87. * not sorted, the results are undefined. If the list contains multiple
  88. * elements equal to the specified object, there is no guarantee which one
  89. * will be found.
  90. *
  91. * <p>This method runs in log(n) time for a "random access" list (which
  92. * provides near-constant-time positional access). If the specified list
  93. * does not implement the {@link RandomAccess} interface and is large,
  94. * this method will do an iterator-based binary search that performs
  95. * O(n) link traversals and O(log n) element comparisons.
  96. *
  97. * @param <T> the class of the objects in the list
  98. * @param list the list to be searched.
  99. * @param key the key to be searched for.
  100. * @param c the comparator by which the list is ordered.
  101. * A <tt>null</tt> value indicates that the elements'
  102. * {@linkplain Comparable natural ordering} should be used.
  103. * @return the index of the search key, if it is contained in the list;
  104. * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
  105. * <i>insertion point</i> is defined as the point at which the
  106. * key would be inserted into the list: the index of the first
  107. * element greater than the key, or <tt>list.size()</tt> if all
  108. * elements in the list are less than the specified key. Note
  109. * that this guarantees that the return value will be &gt;= 0 if
  110. * and only if the key is found.
  111. * @throws ClassCastException if the list contains elements that are not
  112. * <i>mutually comparable</i> using the specified comparator,
  113. * or the search key is not mutually comparable with the
  114. * elements of the list using this comparator.
  115. */
  116. @SuppressWarnings("unchecked")
  117. public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {
  118. if (c==null)
  119. return binarySearch((List<? extends Comparable<? super T>>) list, key);
  120. if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
  121. return Collections.indexedBinarySearch(list, key, c);
  122. else
  123. return Collections.iteratorBinarySearch(list, key, c);
  124. }
  125. private static <T> int indexedBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
  126. int low = 0;
  127. int high = l.size()-1;
  128. while (low <= high) {
  129. int mid = (low + high) >>> 1;
  130. T midVal = l.get(mid);
  131. int cmp = c.compare(midVal, key);
  132. if (cmp < 0)
  133. low = mid + 1;
  134. else if (cmp > 0)
  135. high = mid - 1;
  136. else
  137. return mid; // key found
  138. }
  139. return -(low + 1); // key not found
  140. }
  141. private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
  142. int low = 0;
  143. int high = l.size()-1;
  144. ListIterator<? extends T> i = l.listIterator();
  145. while (low <= high) {
  146. int mid = (low + high) >>> 1;
  147. T midVal = get(i, mid);
  148. int cmp = c.compare(midVal, key);
  149. if (cmp < 0)
  150. low = mid + 1;
  151. else if (cmp > 0)
  152. high = mid - 1;
  153. else
  154. return mid; // key found
  155. }
  156. return -(low + 1); // key not found
  157. }
  158. /**
  159. * Reverses the order of the elements in the specified list.<p>
  160. *
  161. * This method runs in linear time.
  162. *
  163. * @param list the list whose elements are to be reversed.
  164. * @throws UnsupportedOperationException if the specified list or
  165. * its list-iterator does not support the <tt>set</tt> operation.
  166. */
  167. @SuppressWarnings({"rawtypes", "unchecked"})
  168. public static void reverse(List<?> list) {
  169. int size = list.size();
  170. if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
  171. for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
  172. swap(list, i, j);
  173. } else {
  174. // instead of using a raw type here, it's possible to capture
  175. // the wildcard but it will require a call to a supplementary
  176. // private method
  177. ListIterator fwd = list.listIterator();
  178. ListIterator rev = list.listIterator(size);
  179. for (int i=0, mid=list.size()>>1; i<mid; i++) {
  180. Object tmp = fwd.next();
  181. fwd.set(rev.previous());
  182. rev.set(tmp);
  183. }
  184. }
  185. }
  186. /**
  187. * Randomly permutes the specified list using a default source of
  188. * randomness. All permutations occur with approximately equal
  189. * likelihood.
  190. *
  191. * <p>The hedge "approximately" is used in the foregoing description because
  192. * default source of randomness is only approximately an unbiased source
  193. * of independently chosen bits. If it were a perfect source of randomly
  194. * chosen bits, then the algorithm would choose permutations with perfect
  195. * uniformity.
  196. *
  197. * <p>This implementation traverses the list backwards, from the last
  198. * element up to the second, repeatedly swapping a randomly selected element
  199. * into the "current position". Elements are randomly selected from the
  200. * portion of the list that runs from the first element to the current
  201. * position, inclusive.
  202. *
  203. * <p>This method runs in linear time. If the specified list does not
  204. * implement the {@link RandomAccess} interface and is large, this
  205. * implementation dumps the specified list into an array before shuffling
  206. * it, and dumps the shuffled array back into the list. This avoids the
  207. * quadratic behavior that would result from shuffling a "sequential
  208. * access" list in place.
  209. *
  210. * @param list the list to be shuffled.
  211. * @throws UnsupportedOperationException if the specified list or
  212. * its list-iterator does not support the <tt>set</tt> operation.
  213. */
  214. public static void shuffle(List<?> list) {
  215. Random rnd = r;
  216. if (rnd == null)
  217. r = rnd = new Random(); // harmless race.
  218. shuffle(list, rnd);
  219. }
  220. private static Random r;
  221. /**
  222. * Randomly permute the specified list using the specified source of
  223. * randomness. All permutations occur with equal likelihood
  224. * assuming that the source of randomness is fair.<p>
  225. *
  226. * This implementation traverses the list backwards, from the last element
  227. * up to the second, repeatedly swapping a randomly selected element into
  228. * the "current position". Elements are randomly selected from the
  229. * portion of the list that runs from the first element to the current
  230. * position, inclusive.<p>
  231. *
  232. * This method runs in linear time. If the specified list does not
  233. * implement the {@link RandomAccess} interface and is large, this
  234. * implementation dumps the specified list into an array before shuffling
  235. * it, and dumps the shuffled array back into the list. This avoids the
  236. * quadratic behavior that would result from shuffling a "sequential
  237. * access" list in place.
  238. *
  239. * @param list the list to be shuffled.
  240. * @param rnd the source of randomness to use to shuffle the list.
  241. * @throws UnsupportedOperationException if the specified list or its
  242. * list-iterator does not support the <tt>set</tt> operation.
  243. */
  244. @SuppressWarnings({"rawtypes", "unchecked"})
  245. public static void shuffle(List<?> list, Random rnd) {
  246. int size = list.size();
  247. if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
  248. for (int i=size; i>1; i--)
  249. swap(list, i-1, rnd.nextInt(i));
  250. } else {
  251. Object arr[] = list.toArray();
  252. // Shuffle array
  253. for (int i=size; i>1; i--)
  254. swap(arr, i-1, rnd.nextInt(i));
  255. // Dump array back into list
  256. // instead of using a raw type here, it's possible to capture
  257. // the wildcard but it will require a call to a supplementary
  258. // private method
  259. ListIterator it = list.listIterator();
  260. for (int i=0; i<arr.length; i++) {
  261. it.next();
  262. it.set(arr[i]);
  263. }
  264. }
  265. }
  266. /**
  267. * Swaps the elements at the specified positions in the specified list.
  268. * (If the specified positions are equal, invoking this method leaves
  269. * the list unchanged.)
  270. *
  271. * @param list The list in which to swap elements.
  272. * @param i the index of one element to be swapped.
  273. * @param j the index of the other element to be swapped.
  274. * @throws IndexOutOfBoundsException if either <tt>i</tt> or <tt>j</tt>
  275. * is out of range (i &lt; 0 || i &gt;= list.size()
  276. * || j &lt; 0 || j &gt;= list.size()).
  277. * @since 1.4
  278. */
  279. @SuppressWarnings({"rawtypes", "unchecked"})
  280. public static void swap(List<?> list, int i, int j) {
  281. // instead of using a raw type here, it's possible to capture
  282. // the wildcard but it will require a call to a supplementary
  283. // private method
  284. final List l = list;
  285. l.set(i, l.set(j, l.get(i)));
  286. }
  287. /**
  288. * Swaps the two specified elements in the specified array.
  289. */
  290. private static void swap(Object[] arr, int i, int j) {
  291. Object tmp = arr[i];
  292. arr[i] = arr[j];
  293. arr[j] = tmp;
  294. }
  295. /**
  296. * Replaces all of the elements of the specified list with the specified
  297. * element. <p>
  298. *
  299. * This method runs in linear time.
  300. *
  301. * @param <T> the class of the objects in the list
  302. * @param list the list to be filled with the specified element.
  303. * @param obj The element with which to fill the specified list.
  304. * @throws UnsupportedOperationException if the specified list or its
  305. * list-iterator does not support the <tt>set</tt> operation.
  306. */
  307. public static <T> void fill(List<? super T> list, T obj) {
  308. int size = list.size();
  309. if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
  310. for (int i=0; i<size; i++)
  311. list.set(i, obj);
  312. } else {
  313. ListIterator<? super T> itr = list.listIterator();
  314. for (int i=0; i<size; i++) {
  315. itr.next();
  316. itr.set(obj);
  317. }
  318. }
  319. }
  320. /**
  321. * Copies all of the elements from one list into another. After the
  322. * operation, the index of each copied element in the destination list
  323. * will be identical to its index in the source list. The destination
  324. * list must be at least as long as the source list. If it is longer, the
  325. * remaining elements in the destination list are unaffected. <p>
  326. *
  327. * This method runs in linear time.
  328. *
  329. * @param <T> the class of the objects in the lists
  330. * @param dest The destination list.
  331. * @param src The source list.
  332. * @throws IndexOutOfBoundsException if the destination list is too small
  333. * to contain the entire source List.
  334. * @throws UnsupportedOperationException if the destination list's
  335. * list-iterator does not support the <tt>set</tt> operation.
  336. */
  337. public static <T> void copy(List<? super T> dest, List<? extends T> src) {
  338. int srcSize = src.size();
  339. if (srcSize > dest.size())
  340. throw new IndexOutOfBoundsException("Source does not fit in dest");
  341. if (srcSize < COPY_THRESHOLD ||
  342. (src instanceof RandomAccess && dest instanceof RandomAccess)) {
  343. for (int i=0; i<srcSize; i++)
  344. dest.set(i, src.get(i));
  345. } else {
  346. ListIterator<? super T> di=dest.listIterator();
  347. ListIterator<? extends T> si=src.listIterator();
  348. for (int i=0; i<srcSize; i++) {
  349. di.next();
  350. di.set(si.next());
  351. }
  352. }
  353. }
  354. /**
  355. * Returns the minimum element of the given collection, according to the
  356. * <i>natural ordering</i> of its elements. All elements in the
  357. * collection must implement the <tt>Comparable</tt> interface.
  358. * Furthermore, all elements in the collection must be <i>mutually
  359. * comparable</i> (that is, <tt>e1.compareTo(e2)</tt> must not throw a
  360. * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
  361. * <tt>e2</tt> in the collection).<p>
  362. *
  363. * This method iterates over the entire collection, hence it requires
  364. * time proportional to the size of the collection.
  365. *
  366. * @param <T> the class of the objects in the collection
  367. * @param coll the collection whose minimum element is to be determined.
  368. * @return the minimum element of the given collection, according
  369. * to the <i>natural ordering</i> of its elements.
  370. * @throws ClassCastException if the collection contains elements that are
  371. * not <i>mutually comparable</i> (for example, strings and
  372. * integers).
  373. * @throws NoSuchElementException if the collection is empty.
  374. * @see Comparable
  375. */
  376. public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
  377. Iterator<? extends T> i = coll.iterator();
  378. T candidate = i.next();
  379. while (i.hasNext()) {
  380. T next = i.next();
  381. if (next.compareTo(candidate) < 0)
  382. candidate = next;
  383. }
  384. return candidate;
  385. }
  386. /**
  387. * Returns the minimum element of the given collection, according to the
  388. * order induced by the specified comparator. All elements in the
  389. * collection must be <i>mutually comparable</i> by the specified
  390. * comparator (that is, <tt>comp.compare(e1, e2)</tt> must not throw a
  391. * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
  392. * <tt>e2</tt> in the collection).<p>
  393. *
  394. * This method iterates over the entire collection, hence it requires
  395. * time proportional to the size of the collection.
  396. *
  397. * @param <T> the class of the objects in the collection
  398. * @param coll the collection whose minimum element is to be determined.
  399. * @param comp the comparator with which to determine the minimum element.
  400. * A <tt>null</tt> value indicates that the elements' <i>natural
  401. * ordering</i> should be used.
  402. * @return the minimum element of the given collection, according
  403. * to the specified comparator.
  404. * @throws ClassCastException if the collection contains elements that are
  405. * not <i>mutually comparable</i> using the specified comparator.
  406. * @throws NoSuchElementException if the collection is empty.
  407. * @see Comparable
  408. */
  409. @SuppressWarnings({"unchecked", "rawtypes"})
  410. public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {
  411. if (comp==null)
  412. return (T)min((Collection) coll);
  413. Iterator<? extends T> i = coll.iterator();
  414. T candidate = i.next();
  415. while (i.hasNext()) {
  416. T next = i.next();
  417. if (comp.compare(next, candidate) < 0)
  418. candidate = next;
  419. }
  420. return candidate;
  421. }
  422. /**
  423. * Returns the maximum element of the given collection, according to the
  424. * <i>natural ordering</i> of its elements. All elements in the
  425. * collection must implement the <tt>Comparable</tt> interface.
  426. * Furthermore, all elements in the collection must be <i>mutually
  427. * comparable</i> (that is, <tt>e1.compareTo(e2)</tt> must not throw a
  428. * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
  429. * <tt>e2</tt> in the collection).<p>
  430. *
  431. * This method iterates over the entire collection, hence it requires
  432. * time proportional to the size of the collection.
  433. *
  434. * @param <T> the class of the objects in the collection
  435. * @param coll the collection whose maximum element is to be determined.
  436. * @return the maximum element of the given collection, according
  437. * to the <i>natural ordering</i> of its elements.
  438. * @throws ClassCastException if the collection contains elements that are
  439. * not <i>mutually comparable</i> (for example, strings and
  440. * integers).
  441. * @throws NoSuchElementException if the collection is empty.
  442. * @see Comparable
  443. */
  444. public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
  445. Iterator<? extends T> i = coll.iterator();
  446. T candidate = i.next();
  447. while (i.hasNext()) {
  448. T next = i.next();
  449. if (next.compareTo(candidate) > 0)
  450. candidate = next;
  451. }
  452. return candidate;
  453. }
  454. /**
  455. * Returns the maximum element of the given collection, according to the
  456. * order induced by the specified comparator. All elements in the
  457. * collection must be <i>mutually comparable</i> by the specified
  458. * comparator (that is, <tt>comp.compare(e1, e2)</tt> must not throw a
  459. * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
  460. * <tt>e2</tt> in the collection).<p>
  461. *
  462. * This method iterates over the entire collection, hence it requires
  463. * time proportional to the size of the collection.
  464. *
  465. * @param <T> the class of the objects in the collection
  466. * @param coll the collection whose maximum element is to be determined.
  467. * @param comp the comparator with which to determine the maximum element.
  468. * A <tt>null</tt> value indicates that the elements' <i>natural
  469. * ordering</i> should be used.
  470. * @return the maximum element of the given collection, according
  471. * to the specified comparator.
  472. * @throws ClassCastException if the collection contains elements that are
  473. * not <i>mutually comparable</i> using the specified comparator.
  474. * @throws NoSuchElementException if the collection is empty.
  475. * @see Comparable
  476. */
  477. @SuppressWarnings({"unchecked", "rawtypes"})
  478. public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
  479. if (comp==null)
  480. return (T)max((Collection) coll);
  481. Iterator<? extends T> i = coll.iterator();
  482. T candidate = i.next();
  483. while (i.hasNext()) {
  484. T next = i.next();
  485. if (comp.compare(next, candidate) > 0)
  486. candidate = next;
  487. }
  488. return candidate;
  489. }
  490. /**
  491. * Rotates the elements in the specified list by the specified distance.
  492. * After calling this method, the element at index <tt>i</tt> will be
  493. * the element previously at index <tt>(i - distance)</tt> mod
  494. * <tt>list.size()</tt>, for all values of <tt>i</tt> between <tt>0</tt>
  495. * and <tt>list.size()-1</tt>, inclusive. (This method has no effect on
  496. * the size of the list.)
  497. *
  498. * <p>For example, suppose <tt>list</tt> comprises<tt> [t, a, n, k, s]</tt>.
  499. * After invoking <tt>Collections.rotate(list, 1)</tt> (or
  500. * <tt>Collections.rotate(list, -4)</tt>), <tt>list</tt> will comprise
  501. * <tt>[s, t, a, n, k]</tt>.
  502. *
  503. * <p>Note that this method can usefully be applied to sublists to
  504. * move one or more elements within a list while preserving the
  505. * order of the remaining elements. For example, the following idiom
  506. * moves the element at index <tt>j</tt> forward to position
  507. * <tt>k</tt> (which must be greater than or equal to <tt>j</tt>):
  508. *
  509. <pre>
  510. * Collections.rotate(list.subList(j, k+1), -1);
  511. * </pre>
  512. * To make this concrete, suppose <tt>list</tt> comprises
  513. * <tt>[a, b, c, d, e]</tt>. To move the element at index <tt>1</tt>
  514. * (<tt>b</tt>) forward two positions, perform the following invocation:
  515. *
  516. <pre>
  517. * Collections.rotate(l.subList(1, 4), -1);
  518. * </pre>
  519. * The resulting list is <tt>[a, c, d, b, e]</tt>.
  520. *
  521. * <p>To move more than one element forward, increase the absolute value
  522. * of the rotation distance. To move elements backward, use a positive
  523. * shift distance.
  524. *
  525. * <p>If the specified list is small or implements the {@link
  526. * RandomAccess} interface, this implementation exchanges the first
  527. * element into the location it should go, and then repeatedly exchanges
  528. * the displaced element into the location it should go until a displaced
  529. * element is swapped into the first element. If necessary, the process
  530. * is repeated on the second and successive elements, until the rotation
  531. * is complete. If the specified list is large and doesn't implement the
  532. * <tt>RandomAccess</tt> interface, this implementation breaks the
  533. * list into two sublist views around index <tt>-distance mod size</tt>.
  534. * Then the {@link #reverse(List)} method is invoked on each sublist view,
  535. * and finally it is invoked on the entire list. For a more complete
  536. * description of both algorithms, see Section 2.3 of Jon Bentley's
  537. * <i>Programming Pearls</i> (Addison-Wesley, 1986).
  538. *
  539. * @param list the list to be rotated.
  540. * @param distance the distance to rotate the list. There are no
  541. * constraints on this value; it may be zero, negative, or
  542. * greater than <tt>list.size()</tt>.
  543. * @throws UnsupportedOperationException if the specified list or
  544. * its list-iterator does not support the <tt>set</tt> operation.
  545. * @since 1.4
  546. */
  547. public static void rotate(List<?> list, int distance) {
  548. if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
  549. rotate1(list, distance);
  550. else
  551. rotate2(list, distance);
  552. }
  553. private static <T> void rotate1(List<T> list, int distance) {
  554. int size = list.size();
  555. if (size == 0)
  556. return;
  557. distance = distance % size;
  558. if (distance < 0)
  559. distance += size;
  560. if (distance == 0)
  561. return;
  562. for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
  563. T displaced = list.get(cycleStart);
  564. int i = cycleStart;
  565. do {
  566. i += distance;
  567. if (i >= size)
  568. i -= size;
  569. displaced = list.set(i, displaced);
  570. nMoved ++;
  571. } while (i != cycleStart);
  572. }
  573. }
  574. private static void rotate2(List<?> list, int distance) {
  575. int size = list.size();
  576. if (size == 0)
  577. return;
  578. int mid = -distance % size;
  579. if (mid < 0)
  580. mid += size;
  581. if (mid == 0)
  582. return;
  583. reverse(list.subList(0, mid));
  584. reverse(list.subList(mid, size));
  585. reverse(list);
  586. }
  587. /**
  588. * Replaces all occurrences of one specified value in a list with another.
  589. * More formally, replaces with <tt>newVal</tt> each element <tt>e</tt>
  590. * in <tt>list</tt> such that
  591. * <tt>(oldVal==null ? e==null : oldVal.equals(e))</tt>.
  592. * (This method has no effect on the size of the list.)
  593. *
  594. * @param <T> the class of the objects in the list
  595. * @param list the list in which replacement is to occur.
  596. * @param oldVal the old value to be replaced.
  597. * @param newVal the new value with which <tt>oldVal</tt> is to be
  598. * replaced.
  599. * @return <tt>true</tt> if <tt>list</tt> contained one or more elements
  600. * <tt>e</tt> such that
  601. * <tt>(oldVal==null ? e==null : oldVal.equals(e))</tt>.
  602. * @throws UnsupportedOperationException if the specified list or
  603. * its list-iterator does not support the <tt>set</tt> operation.
  604. * @since 1.4
  605. */
  606. public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {
  607. boolean result = false;
  608. int size = list.size();
  609. if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) {
  610. if (oldVal==null) {
  611. for (int i=0; i<size; i++) {
  612. if (list.get(i)==null) {
  613. list.set(i, newVal);
  614. result = true;
  615. }
  616. }
  617. } else {
  618. for (int i=0; i<size; i++) {
  619. if (oldVal.equals(list.get(i))) {
  620. list.set(i, newVal);
  621. result = true;
  622. }
  623. }
  624. }
  625. } else {
  626. ListIterator<T> itr=list.listIterator();
  627. if (oldVal==null) {
  628. for (int i=0; i<size; i++) {
  629. if (itr.next()==null) {
  630. itr.set(newVal);
  631. result = true;
  632. }
  633. }
  634. } else {
  635. for (int i=0; i<size; i++) {
  636. if (oldVal.equals(itr.next())) {
  637. itr.set(newVal);
  638. result = true;
  639. }
  640. }
  641. }
  642. }
  643. return result;
  644. }
  645. /**
  646. * Returns the starting position of the first occurrence of the specified
  647. * target list within the specified source list, or -1 if there is no
  648. * such occurrence. More formally, returns the lowest index <tt>i</tt>
  649. * such that {@code source.subList(i, i+target.size()).equals(target)},
  650. * or -1 if there is no such index. (Returns -1 if
  651. * {@code target.size() > source.size()})
  652. *
  653. * <p>This implementation uses the "brute force" technique of scanning
  654. * over the source list, looking for a match with the target at each
  655. * location in turn.
  656. *
  657. * @param source the list in which to search for the first occurrence
  658. * of <tt>target</tt>.
  659. * @param target the list to search for as a subList of <tt>source</tt>.
  660. * @return the starting position of the first occurrence of the specified
  661. * target list within the specified source list, or -1 if there
  662. * is no such occurrence.
  663. * @since 1.4
  664. */
  665. public static int indexOfSubList(List<?> source, List<?> target) {
  666. int sourceSize = source.size();
  667. int targetSize = target.size();
  668. int maxCandidate = sourceSize - targetSize;
  669. if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
  670. (source instanceof RandomAccess&&target instanceof RandomAccess)) {
  671. nextCand:
  672. for (int candidate = 0; candidate <= maxCandidate; candidate++) {
  673. for (int i=0, j=candidate; i<targetSize; i++, j++)
  674. if (!eq(target.get(i), source.get(j)))
  675. continue nextCand; // Element mismatch, try next cand
  676. return candidate; // All elements of candidate matched target
  677. }
  678. } else { // Iterator version of above algorithm
  679. ListIterator<?> si = source.listIterator();
  680. nextCand:
  681. for (int candidate = 0; candidate <= maxCandidate; candidate++) {
  682. ListIterator<?> ti = target.listIterator();
  683. for (int i=0; i<targetSize; i++) {
  684. if (!eq(ti.next(), si.next())) {
  685. // Back up source iterator to next candidate
  686. for (int j=0; j<i; j++)
  687. si.previous();
  688. continue nextCand;
  689. }
  690. }
  691. return candidate;
  692. }
  693. }
  694. return -1; // No candidate matched the target
  695. }
  696. /**
  697. * Returns the starting position of the last occurrence of the specified
  698. * target list within the specified source list, or -1 if there is no such
  699. * occurrence. More formally, returns the highest index <tt>i</tt>
  700. * such that {@code source.subList(i, i+target.size()).equals(target)},
  701. * or -1 if there is no such index. (Returns -1 if
  702. * {@code target.size() > source.size()})
  703. *
  704. * <p>This implementation uses the "brute force" technique of iterating
  705. * over the source list, looking for a match with the target at each
  706. * location in turn.
  707. *
  708. * @param source the list in which to search for the last occurrence
  709. * of <tt>target</tt>.
  710. * @param target the list to search for as a subList of <tt>source</tt>.
  711. * @return the starting position of the last occurrence of the specified
  712. * target list within the specified source list, or -1 if there
  713. * is no such occurrence.
  714. * @since 1.4
  715. */
  716. public static int lastIndexOfSubList(List<?> source, List<?> target) {
  717. int sourceSize = source.size();
  718. int targetSize = target.size();
  719. int maxCandidate = sourceSize - targetSize;
  720. if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
  721. source instanceof RandomAccess) { // Index access version
  722. nextCand:
  723. for (int candidate = maxCandidate; candidate >= 0; candidate--) {
  724. for (int i=0, j=candidate; i<targetSize; i++, j++)
  725. if (!eq(target.get(i), source.get(j)))
  726. continue nextCand; // Element mismatch, try next cand
  727. return candidate; // All elements of candidate matched target
  728. }
  729. } else { // Iterator version of above algorithm
  730. if (maxCandidate < 0)
  731. return -1;
  732. ListIterator<?> si = source.listIterator(maxCandidate);
  733. nextCand:
  734. for (int candidate = maxCandidate; candidate >= 0; candidate--) {
  735. ListIterator<?> ti = target.listIterator();
  736. for (int i=0; i<targetSize; i++) {
  737. if (!eq(ti.next(), si.next())) {
  738. if (candidate != 0) {
  739. // Back up source iterator to next candidate
  740. for (int j=0; j<=i+1; j++)
  741. si.previous();
  742. }
  743. continue nextCand;
  744. }
  745. }
  746. return candidate;
  747. }
  748. }
  749. return -1; // No candidate matched the target
  750. }
  751. // Unmodifiable Wrappers
  752. /**
  753. * Returns an unmodifiable view of the specified collection. This method
  754. * allows modules to provide users with "read-only" access to internal
  755. * collections. Query operations on the returned collection "read through"
  756. * to the specified collection, and attempts to modify the returned
  757. * collection, whether direct or via its iterator, result in an
  758. * <tt>UnsupportedOperationException</tt>.<p>
  759. *
  760. * The returned collection does <i>not</i> pass the hashCode and equals
  761. * operations through to the backing collection, but relies on
  762. * <tt>Object</tt>'s <tt>equals</tt> and <tt>hashCode</tt> methods. This
  763. * is necessary to preserve the contracts of these operations in the case
  764. * that the backing collection is a set or a list.<p>
  765. *
  766. * The returned collection will be serializable if the specified collection
  767. * is serializable.
  768. *
  769. * @param <T> the class of the objects in the collection
  770. * @param c the collection for which an unmodifiable view is to be
  771. * returned.
  772. * @return an unmodifiable view of the specified collection.
  773. */
  774. public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
  775. return new UnmodifiableCollection<>(c);
  776. }
  777. /**
  778. * @serial include
  779. */
  780. static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
  781. private static final long serialVersionUID = 1820017752578914078L;
  782. final Collection<? extends E> c;
  783. UnmodifiableCollection(Collection<? extends E> c) {
  784. if (c==null)
  785. throw new NullPointerException();
  786. this.c = c;
  787. }
  788. public int size() {return c.size();}
  789. public boolean isEmpty() {return c.isEmpty();}
  790. public boolean contains(Object o) {return c.contains(o);}
  791. public Object[] toArray() {return c.toArray();}
  792. public <T> T[] toArray(T[] a) {return c.toArray(a);}
  793. public String toString() {return c.toString();}
  794. public Iterator<E> iterator() {
  795. return new Iterator<E>() {
  796. private final Iterator<? extends E> i = c.iterator();
  797. public boolean hasNext() {return i.hasNext();}
  798. public E next() {return i.next();}
  799. public void remove() {
  800. throw new UnsupportedOperationException();
  801. }
  802. @Override
  803. public void forEachRemaining(Consumer<? super E> action) {
  804. // Use backing collection version
  805. i.forEachRemaining(action);
  806. }
  807. };
  808. }
  809. public boolean add(E e) {
  810. throw new UnsupportedOperationException();
  811. }
  812. public boolean remove(Object o) {
  813. throw new UnsupportedOperationException();
  814. }
  815. public boolean containsAll(Collection<?> coll) {
  816. return c.containsAll(coll);
  817. }
  818. public boolean addAll(Collection<? extends E> coll) {
  819. throw new UnsupportedOperationException();
  820. }
  821. public boolean removeAll(Collection<?> coll) {
  822. throw new UnsupportedOperationException();
  823. }
  824. public boolean retainAll(Collection<?> coll) {
  825. throw new UnsupportedOperationException();
  826. }
  827. public void clear() {
  828. throw new UnsupportedOperationException();
  829. }
  830. // Override default methods in Collection
  831. @Override
  832. public void forEach(Consumer<? super E> action) {
  833. c.forEach(action);
  834. }
  835. @Override
  836. public boolean removeIf(Predicate<? super E> filter) {
  837. throw new UnsupportedOperationException();
  838. }
  839. @SuppressWarnings("unchecked")
  840. @Override
  841. public Spliterator<E> spliterator() {
  842. return (Spliterator<E>)c.spliterator();
  843. }
  844. @SuppressWarnings("unchecked")
  845. @Override
  846. public Stream<E> stream() {
  847. return (Stream<E>)c.stream();
  848. }
  849. @SuppressWarnings("unchecked")
  850. @Override
  851. public Stream<E> parallelStream() {
  852. return (Stream<E>)c.parallelStream();
  853. }
  854. }
  855. /**
  856. * Returns an unmodifiable view of the specified set. This method allows
  857. * modules to provide users with "read-only" access to internal sets.
  858. * Query operations on the returned set "read through" to the specified
  859. * set, and attempts to modify the returned set, whether direct or via its
  860. * iterator, result in an <tt>UnsupportedOperationException</tt>.<p>
  861. *
  862. * The returned set will be serializable if the specified set
  863. * is serializable.
  864. *
  865. * @param <T> the class of the objects in the set
  866. * @param s the set for which an unmodifiable view is to be returned.
  867. * @return an unmodifiable view of the specified set.
  868. */
  869. public static <T> Set<T> unmodifiableSet(Set<? extends T> s) {
  870. return new UnmodifiableSet<>(s);
  871. }
  872. /**
  873. * @serial include
  874. */
  875. static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
  876. implements Set<E>, Serializable {
  877. private static final long serialVersionUID = -9215047833775013803L;
  878. UnmodifiableSet(Set<? extends E> s) {super(s);}
  879. public boolean equals(Object o) {return o == this || c.equals(o);}
  880. public int hashCode() {return c.hashCode();}
  881. }
  882. /**
  883. * Returns an unmodifiable view of the specified sorted set. This method
  884. * allows modules to provide users with "read-only" access to internal
  885. * sorted sets. Query operations on the returned sorted set "read
  886. * through" to the specified sorted set. Attempts to modify the returned
  887. * sorted set, whether direct, via its iterator, or via its
  888. * <tt>subSet</tt>, <tt>headSet</tt>, or <tt>tailSet</tt> views, result in
  889. * an <tt>UnsupportedOperationException</tt>.<p>
  890. *
  891. * The returned sorted set will be serializable if the specified sorted set
  892. * is serializable.
  893. *
  894. * @param <T> the class of the objects in the set
  895. * @param s the sorted set for which an unmodifiable view is to be
  896. * returned.
  897. * @return an unmodifiable view of the specified sorted set.
  898. */
  899. public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s) {
  900. return new UnmodifiableSortedSet<>(s);
  901. }
  902. /**
  903. * @serial include
  904. */
  905. static class UnmodifiableSortedSet<E>
  906. extends UnmodifiableSet<E>
  907. implements SortedSet<E>, Serializable {
  908. private static final long serialVersionUID = -4929149591599911165L;
  909. private final SortedSet<E> ss;
  910. UnmodifiableSortedSet(SortedSet<E> s) {super(s); ss = s;}
  911. public Comparator<? super E> comparator() {return ss.comparator();}
  912. public SortedSet<E> subSet(E fromElement, E toElement) {
  913. return new UnmodifiableSortedSet<>(ss.subSet(fromElement,toElement));
  914. }
  915. public SortedSet<E> headSet(E toElement) {
  916. return new UnmodifiableSortedSet<>(ss.headSet(toElement));
  917. }
  918. public SortedSet<E> tailSet(E fromElement) {
  919. return new UnmodifiableSortedSet<>(ss.tailSet(fromElement));
  920. }
  921. public E first() {return ss.first();}
  922. public E last() {return ss.last();}
  923. }
  924. /**
  925. * Returns an unmodifiable view of the specified navigable set. This method
  926. * allows modules to provide users with "read-only" access to internal
  927. * navigable sets. Query operations on the returned navigable set "read
  928. * through" to the specified navigable set. Attempts to modify the returned
  929. * navigable set, whether direct, via its iterator, or via its
  930. * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in
  931. * an {@code UnsupportedOperationException}.<p>
  932. *
  933. * The returned navigable set will be serializable if the specified
  934. * navigable set is serializable.
  935. *
  936. * @param <T> the class of the objects in the set
  937. * @param s the navigable set for which an unmodifiable view is to be
  938. * returned
  939. * @return an unmodifiable view of the specified navigable set
  940. * @since 1.8
  941. */
  942. public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s) {
  943. return new UnmodifiableNavigableSet<>(s);
  944. }
  945. /**
  946. * Wraps a navigable set and disables all of the mutative operations.
  947. *
  948. * @param <E> type of elements
  949. * @serial include
  950. */
  951. static class UnmodifiableNavigableSet<E>
  952. extends UnmodifiableSortedSet<E>
  953. implements NavigableSet<E>, Serializable {
  954. private static final long serialVersionUID = -6027448201786391929L;
  955. /**
  956. * A singleton empty unmodifiable navigable set used for
  957. * {@link #emptyNavigableSet()}.
  958. *
  959. * @param <E> type of elements, if there were any, and bounds
  960. */
  961. private static class EmptyNavigableSet<E> extends UnmodifiableNavigableSet<E>
  962. implements Serializable {
  963. private static final long serialVersionUID = -6291252904449939134L;
  964. public EmptyNavigableSet() {
  965. super(new TreeSet<E>());
  966. }
  967. private Object readResolve() { return EMPTY_NAVIGABLE_SET; }
  968. }
  969. @SuppressWarnings("rawtypes")
  970. private static final NavigableSet<?> EMPTY_NAVIGABLE_SET =
  971. new EmptyNavigableSet<>();
  972. /**
  973. * The instance we are protecting.
  974. */
  975. private final NavigableSet<E> ns;
  976. UnmodifiableNavigableSet(NavigableSet<E> s) {super(s); ns = s;}
  977. public E lower(E e) { return ns.lower(e); }
  978. public E floor(E e) { return ns.floor(e); }
  979. public E ceiling(E e) { return ns.ceiling(e); }
  980. public E higher(E e) { return ns.higher(e); }
  981. public E pollFirst() { throw new UnsupportedOperationException(); }
  982. public E pollLast() { throw new UnsupportedOperationException(); }
  983. public NavigableSet<E> descendingSet()
  984. { return new UnmodifiableNavigableSet<>(ns.descendingSet()); }
  985. public Iterator<E> descendingIterator()
  986. { return descendingSet().iterator(); }
  987. public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
  988. return new UnmodifiableNavigableSet<>(
  989. ns.subSet(fromElement, fromInclusive, toElement, toInclusive));
  990. }
  991. public NavigableSet<E> headSet(E toElement, boolean inclusive) {
  992. return new UnmodifiableNavigableSet<>(
  993. ns.headSet(toElement, inclusive));
  994. }
  995. public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
  996. return new UnmodifiableNavigableSet<>(
  997. ns.tailSet(fromElement, inclusive));
  998. }
  999. }
  1000. /**
  1001. * Returns an unmodifiable view of the specified list. This method allows
  1002. * modules to provide users with "read-only" access to internal
  1003. * lists. Query operations on the returned list "read through" to the
  1004. * specified list, and attempts to modify the returned list, whether
  1005. * direct or via its iterator, result in an
  1006. * <tt>UnsupportedOperationException</tt>.<p>
  1007. *
  1008. * The returned list will be serializable if the specified list
  1009. * is serializable. Similarly, the returned list will implement
  1010. * {@link RandomAccess} if the specified list does.
  1011. *
  1012. * @param <T> the class of the objects in the list
  1013. * @param list the list for which an unmodifiable view is to be returned.
  1014. * @return an unmodifiable view of the specified list.
  1015. */
  1016. public static <T> List<T> unmodifiableList(List<? extends T> list) {
  1017. return (list instanceof RandomAccess ?
  1018. new UnmodifiableRandomAccessList<>(list) :
  1019. new UnmodifiableList<>(list));
  1020. }
  1021. /**
  1022. * @serial include
  1023. */
  1024. static class UnmodifiableList<E> extends UnmodifiableCollection<E>
  1025. implements List<E> {
  1026. private static final long serialVersionUID = -283967356065247728L;
  1027. final List<? extends E> list;
  1028. UnmodifiableList(List<? extends E> list) {
  1029. super(list);
  1030. this.list = list;
  1031. }
  1032. public boolean equals(Object o) {return o == this || list.equals(o);}
  1033. public int hashCode() {return list.hashCode();}
  1034. public E get(int index) {return list.get(index);}
  1035. public E set(int index, E element) {
  1036. throw new UnsupportedOperationException();
  1037. }
  1038. public void add(int index, E element) {
  1039. throw new UnsupportedOperationException();
  1040. }
  1041. public E remove(int index) {
  1042. throw new UnsupportedOperationException();
  1043. }
  1044. public int indexOf(Object o) {return list.indexOf(o);}
  1045. public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
  1046. public boolean addAll(int index, Collection<? extends E> c) {
  1047. throw new UnsupportedOperationException();
  1048. }
  1049. @Override
  1050. public void replaceAll(UnaryOperator<E> operator) {
  1051. throw new UnsupportedOperationException();
  1052. }
  1053. @Override
  1054. public void sort(Comparator<? super E> c) {
  1055. throw new UnsupportedOperationException();
  1056. }
  1057. public ListIterator<E> listIterator() {return listIterator(0);}
  1058. public ListIterator<E> listIterator(final int index) {
  1059. return new ListIterator<E>() {
  1060. private final ListIterator<? extends E> i
  1061. = list.listIterator(index);
  1062. public boolean hasNext() {return i.hasNext();}
  1063. public E next() {return i.next();}
  1064. public boolean hasPrevious() {return i.hasPrevious();}
  1065. public E previous() {return i.previous();}
  1066. public int nextIndex() {return i.nextIndex();}
  1067. public int previousIndex() {return i.previousIndex();}
  1068. public void remove() {
  1069. throw new UnsupportedOperationException();
  1070. }
  1071. public void set(E e) {
  1072. throw new UnsupportedOperationException();
  1073. }
  1074. public void add(E e) {
  1075. throw new UnsupportedOperationException();
  1076. }
  1077. @Override
  1078. public void forEachRemaining(Consumer<? super E> action) {
  1079. i.forEachRemaining(action);
  1080. }
  1081. };
  1082. }
  1083. public List<E> subList(int fromIndex, int toIndex) {
  1084. return new UnmodifiableList<>(list.subList(fromIndex, toIndex));
  1085. }
  1086. /**
  1087. * UnmodifiableRandomAccessList instances are serialized as
  1088. * UnmodifiableList instances to allow them to be deserialized
  1089. * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList).
  1090. * This method inverts the transformation. As a beneficial
  1091. * side-effect, it also grafts the RandomAccess marker onto
  1092. * UnmodifiableList instances that were serialized in pre-1.4 JREs.
  1093. *
  1094. * Note: Unfortunately, UnmodifiableRandomAccessList instances
  1095. * serialized in 1.4.1 and deserialized in 1.4 will become
  1096. * UnmodifiableList instances, as this method was missing in 1.4.
  1097. */
  1098. private Object readResolve() {
  1099. return (list instanceof RandomAccess
  1100. ? new UnmodifiableRandomAccessList<>(list)
  1101. : this);
  1102. }
  1103. }
  1104. /**
  1105. * @serial include
  1106. */
  1107. static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E>
  1108. implements RandomAccess
  1109. {
  1110. UnmodifiableRandomAccessList(List<? extends E> list) {
  1111. super(list);
  1112. }
  1113. public List<E> subList(int fromIndex, int toIndex) {
  1114. return new UnmodifiableRandomAccessList<>(
  1115. list.subList(fromIndex, toIndex));
  1116. }
  1117. private static final long serialVersionUID = -2542308836966382001L;
  1118. /**
  1119. * Allows instances to be deserialized in pre-1.4 JREs (which do
  1120. * not have UnmodifiableRandomAccessList). UnmodifiableList has
  1121. * a readResolve method that inverts this transformation upon
  1122. * deserialization.
  1123. */
  1124. private Object writeReplace() {
  1125. return new UnmodifiableList<>(list);
  1126. }
  1127. }
  1128. /**
  1129. * Returns an unmodifiable view of the specified map. This method
  1130. * allows modules to provide users with "read-only" access to internal
  1131. * maps. Query operations on the returned map "read through"
  1132. * to the specified map, and attempts to modify the returned
  1133. * map, whether direct or via its collection views, result in an
  1134. * <tt>UnsupportedOperationException</tt>.<p>
  1135. *
  1136. * The returned map will be serializable if the specified map
  1137. * is serializable.
  1138. *
  1139. * @param <K> the class of the map keys
  1140. * @param <V> the class of the map values
  1141. * @param m the map for which an unmodifiable view is to be returned.
  1142. * @return an unmodifiable view of the specified map.
  1143. */
  1144. public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
  1145. return new UnmodifiableMap<>(m);
  1146. }
  1147. /**
  1148. * @serial include
  1149. */
  1150. private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
  1151. private static final long serialVersionUID = -1034234728574286014L;
  1152. private final Map<? extends K, ? extends V> m;
  1153. UnmodifiableMap(Map<? extends K, ? extends V> m) {
  1154. if (m==null)
  1155. throw new NullPointerException();
  1156. this.m = m;
  1157. }
  1158. public int size() {return m.size();}
  1159. public boolean isEmpty() {return m.isEmpty();}
  1160. public boolean containsKey(Object key) {return m.containsKey(key);}
  1161. public boolean containsValue(Object val) {return m.containsValue(val);}
  1162. public V get(Object key) {return m.get(key);}
  1163. public V put(K key, V value) {
  1164. throw new UnsupportedOperationException();
  1165. }
  1166. public V remove(Object key) {
  1167. throw new UnsupportedOperationException();
  1168. }
  1169. public void putAll(Map<? extends K, ? extends V> m) {
  1170. throw new UnsupportedOperationException();
  1171. }
  1172. public void clear() {
  1173. throw new UnsupportedOperationException();
  1174. }
  1175. private transient Set<K> keySet;
  1176. private transient Set<Map.Entry<K,V>> entrySet;
  1177. private transient Collection<V> values;
  1178. public Set<K> keySet() {
  1179. if (keySet==null)
  1180. keySet = unmodifiableSet(m.keySet());
  1181. return keySet;
  1182. }
  1183. public Set<Map.Entry<K,V>> entrySet() {
  1184. if (entrySet==null)
  1185. entrySet = new UnmodifiableEntrySet<>(m.entrySet());
  1186. return entrySet;
  1187. }
  1188. public Collection<V> values() {
  1189. if (values==null)
  1190. values = unmodifiableCollection(m.values());
  1191. return values;
  1192. }
  1193. public boolean equals(Object o) {return o == this || m.equals(o);}
  1194. public int hashCode() {return m.hashCode();}
  1195. public String toString() {return m.toString();}
  1196. // Override default methods in Map
  1197. @Override
  1198. @SuppressWarnings("unchecked")
  1199. public V getOrDefault(Object k, V defaultValue) {
  1200. // Safe cast as we don't change the value
  1201. return ((Map<K, V>)m).getOrDefault(k, defaultValue);
  1202. }
  1203. @Override
  1204. public void forEach(BiConsumer<? super K, ? super V> action) {
  1205. m.forEach(action);
  1206. }
  1207. @Override
  1208. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  1209. throw new UnsupportedOperationException();
  1210. }
  1211. @Override
  1212. public V putIfAbsent(K key, V value) {
  1213. throw new UnsupportedOperationException();
  1214. }
  1215. @Override
  1216. public boolean remove(Object key, Object value) {
  1217. throw new UnsupportedOperationException();
  1218. }
  1219. @Override
  1220. public boolean replace(K key, V oldValue, V newValue) {
  1221. throw new UnsupportedOperationException();
  1222. }
  1223. @Override
  1224. public V replace(K key, V value) {
  1225. throw new UnsupportedOperationException();
  1226. }
  1227. @Override
  1228. public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
  1229. throw new UnsupportedOperationException();
  1230. }
  1231. @Override
  1232. public V computeIfPresent(K key,
  1233. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  1234. throw new UnsupportedOperationException();
  1235. }
  1236. @Override
  1237. public V compute(K key,
  1238. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  1239. throw new UnsupportedOperationException();
  1240. }
  1241. @Override
  1242. public V merge(K key, V value,
  1243. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  1244. throw new UnsupportedOperationException();
  1245. }
  1246. /**
  1247. * We need this class in addition to UnmodifiableSet as
  1248. * Map.Entries themselves permit modification of the backing Map
  1249. * via their setValue operation. This class is subtle: there are
  1250. * many possible attacks that must be thwarted.
  1251. *
  1252. * @serial include
  1253. */
  1254. static class UnmodifiableEntrySet<K,V>
  1255. extends UnmodifiableSet<Map.Entry<K,V>> {
  1256. private static final long serialVersionUID = 7854390611657943733L;
  1257. @SuppressWarnings({"unchecked", "rawtypes"})
  1258. UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
  1259. // Need to cast to raw in order to work around a limitation in the type system
  1260. super((Set)s);
  1261. }
  1262. static <K, V> Consumer<Map.Entry<K, V>> entryConsumer(Consumer<? super Entry<K, V>> action) {
  1263. return e -> action.accept(new UnmodifiableEntry<>(e));
  1264. }
  1265. public void forEach(Consumer<? super Entry<K, V>> action) {
  1266. Objects.requireNonNull(action);
  1267. c.forEach(entryConsumer(action));
  1268. }
  1269. static final class UnmodifiableEntrySetSpliterator<K, V>
  1270. implements Spliterator<Entry<K,V>> {
  1271. final Spliterator<Map.Entry<K, V>> s;
  1272. UnmodifiableEntrySetSpliterator(Spliterator<Entry<K, V>> s) {
  1273. this.s = s;
  1274. }
  1275. @Override
  1276. public boolean tryAdvance(Consumer<? super Entry<K, V>> action) {
  1277. Objects.requireNonNull(action);
  1278. return s.tryAdvance(entryConsumer(action));
  1279. }
  1280. @Override
  1281. public void forEachRemaining(Consumer<? super Entry<K, V>> action) {
  1282. Objects.requireNonNull(action);
  1283. s.forEachRemaining(entryConsumer(action));
  1284. }
  1285. @Override
  1286. public Spliterator<Entry<K, V>> trySplit() {
  1287. Spliterator<Entry<K, V>> split = s.trySplit();
  1288. return split == null
  1289. ? null
  1290. : new UnmodifiableEntrySetSpliterator<>(split);
  1291. }
  1292. @Override
  1293. public long estimateSize() {
  1294. return s.estimateSize();
  1295. }
  1296. @Override
  1297. public long getExactSizeIfKnown() {
  1298. return s.getExactSizeIfKnown();
  1299. }
  1300. @Override
  1301. public int characteristics() {
  1302. return s.characteristics();
  1303. }
  1304. @Override
  1305. public boolean hasCharacteristics(int characteristics) {
  1306. return s.hasCharacteristics(characteristics);
  1307. }
  1308. @Override
  1309. public Comparator<? super Entry<K, V>> getComparator() {
  1310. return s.getComparator();
  1311. }
  1312. }
  1313. @SuppressWarnings("unchecked")
  1314. public Spliterator<Entry<K,V>> spliterator() {
  1315. return new UnmodifiableEntrySetSpliterator<>(
  1316. (Spliterator<Map.Entry<K, V>>) c.spliterator());
  1317. }
  1318. @Override
  1319. public Stream<Entry<K,V>> stream() {
  1320. return StreamSupport.stream(spliterator(), false);
  1321. }
  1322. @Override
  1323. public Stream<Entry<K,V>> parallelStream() {
  1324. return StreamSupport.stream(spliterator(), true);
  1325. }
  1326. public Iterator<Map.Entry<K,V>> iterator() {
  1327. return new Iterator<Map.Entry<K,V>>() {
  1328. private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
  1329. public boolean hasNext() {
  1330. return i.hasNext();
  1331. }
  1332. public Map.Entry<K,V> next() {
  1333. return new UnmodifiableEntry<>(i.next());
  1334. }
  1335. public void remove() {
  1336. throw new UnsupportedOperationException();
  1337. }
  1338. };
  1339. }
  1340. @SuppressWarnings("unchecked")
  1341. public Object[] toArray() {
  1342. Object[] a = c.toArray();
  1343. for (int i=0; i<a.length; i++)
  1344. a[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)a[i]);
  1345. return a;
  1346. }
  1347. @SuppressWarnings("unchecked")
  1348. public <T> T[] toArray(T[] a) {
  1349. // We don't pass a to c.toArray, to avoid window of
  1350. // vulnerability wherein an unscrupulous multithreaded client
  1351. // could get his hands on raw (unwrapped) Entries from c.
  1352. Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
  1353. for (int i=0; i<arr.length; i++)
  1354. arr[i] = new UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)arr[i]);
  1355. if (arr.length > a.length)
  1356. return (T[])arr;
  1357. System.arraycopy(arr, 0, a, 0, arr.length);
  1358. if (a.length > arr.length)
  1359. a[arr.length] = null;
  1360. return a;
  1361. }
  1362. /**
  1363. * This method is overridden to protect the backing set against
  1364. * an object with a nefarious equals function that senses
  1365. * that the equality-candidate is Map.Entry and calls its
  1366. * setValue method.
  1367. */
  1368. public boolean contains(Object o) {
  1369. if (!(o instanceof Map.Entry))
  1370. return false;
  1371. return c.contains(
  1372. new UnmodifiableEntry<>((Map.Entry<?,?>) o));
  1373. }
  1374. /**
  1375. * The next two methods are overridden to protect against
  1376. * an unscrupulous List whose contains(Object o) method senses
  1377. * when o is a Map.Entry, and calls o.setValue.
  1378. */
  1379. public boolean containsAll(Collection<?> coll) {
  1380. for (Object e : coll) {
  1381. if (!contains(e)) // Invokes safe contains() above
  1382. return false;
  1383. }
  1384. return true;
  1385. }
  1386. public boolean equals(Object o) {
  1387. if (o == this)
  1388. return true;
  1389. if (!(o instanceof Set))
  1390. return false;
  1391. Set<?> s = (Set<?>) o;
  1392. if (s.size() != c.size())
  1393. return false;
  1394. return containsAll(s); // Invokes safe containsAll() above
  1395. }
  1396. /**
  1397. * This "wrapper class" serves two purposes: it prevents
  1398. * the client from modifying the backing Map, by short-circuiting
  1399. * the setValue method, and it protects the backing Map against
  1400. * an ill-behaved Map.Entry that attempts to modify another
  1401. * Map Entry when asked to perform an equality check.
  1402. */
  1403. private static class UnmodifiableEntry<K,V> implements Map.Entry<K,V> {
  1404. private Map.Entry<? extends K, ? extends V> e;
  1405. UnmodifiableEntry(Map.Entry<? extends K, ? extends V> e)
  1406. {this.e = Objects.requireNonNull(e);}
  1407. public K getKey() {return e.getKey();}
  1408. public V getValue() {return e.getValue();}
  1409. public V setValue(V value) {
  1410. throw new UnsupportedOperationException();
  1411. }
  1412. public int hashCode() {return e.hashCode();}
  1413. public boolean equals(Object o) {
  1414. if (this == o)
  1415. return true;
  1416. if (!(o instanceof Map.Entry))
  1417. return false;
  1418. Map.Entry<?,?> t = (Map.Entry<?,?>)o;
  1419. return eq(e.getKey(), t.getKey()) &&
  1420. eq(e.getValue(), t.getValue());
  1421. }
  1422. public String toString() {return e.toString();}
  1423. }
  1424. }
  1425. }
  1426. /**
  1427. * Returns an unmodifiable view of the specified sorted map. This method
  1428. * allows modules to provide users with "read-only" access to internal
  1429. * sorted maps. Query operations on the returned sorted map "read through"
  1430. * to the specified sorted map. Attempts to modify the returned
  1431. * sorted map, whether direct, via its collection views, or via its
  1432. * <tt>subMap</tt>, <tt>headMap</tt>, or <tt>tailMap</tt> views, result in
  1433. * an <tt>UnsupportedOperationException</tt>.<p>
  1434. *
  1435. * The returned sorted map will be serializable if the specified sorted map
  1436. * is serializable.
  1437. *
  1438. * @param <K> the class of the map keys
  1439. * @param <V> the class of the map values
  1440. * @param m the sorted map for which an unmodifiable view is to be
  1441. * returned.
  1442. * @return an unmodifiable view of the specified sorted map.
  1443. */
  1444. public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m) {
  1445. return new UnmodifiableSortedMap<>(m);
  1446. }
  1447. /**
  1448. * @serial include
  1449. */
  1450. static class UnmodifiableSortedMap<K,V>
  1451. extends UnmodifiableMap<K,V>
  1452. implements SortedMap<K,V>, Serializable {
  1453. private static final long serialVersionUID = -8806743815996713206L;
  1454. private final SortedMap<K, ? extends V> sm;
  1455. UnmodifiableSortedMap(SortedMap<K, ? extends V> m) {super(m); sm = m; }
  1456. public Comparator<? super K> comparator() { return sm.comparator(); }
  1457. public SortedMap<K,V> subMap(K fromKey, K toKey)
  1458. { return new UnmodifiableSortedMap<>(sm.subMap(fromKey, toKey)); }
  1459. public SortedMap<K,V> headMap(K toKey)
  1460. { return new UnmodifiableSortedMap<>(sm.headMap(toKey)); }
  1461. public SortedMap<K,V> tailMap(K fromKey)
  1462. { return new UnmodifiableSortedMap<>(sm.tailMap(fromKey)); }
  1463. public K firstKey() { return sm.firstKey(); }
  1464. public K lastKey() { return sm.lastKey(); }
  1465. }
  1466. /**
  1467. * Returns an unmodifiable view of the specified navigable map. This method
  1468. * allows modules to provide users with "read-only" access to internal
  1469. * navigable maps. Query operations on the returned navigable map "read
  1470. * through" to the specified navigable map. Attempts to modify the returned
  1471. * navigable map, whether direct, via its collection views, or via its
  1472. * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in
  1473. * an {@code UnsupportedOperationException}.<p>
  1474. *
  1475. * The returned navigable map will be serializable if the specified
  1476. * navigable map is serializable.
  1477. *
  1478. * @param <K> the class of the map keys
  1479. * @param <V> the class of the map values
  1480. * @param m the navigable map for which an unmodifiable view is to be
  1481. * returned
  1482. * @return an unmodifiable view of the specified navigable map
  1483. * @since 1.8
  1484. */
  1485. public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m) {
  1486. return new UnmodifiableNavigableMap<>(m);
  1487. }
  1488. /**
  1489. * @serial include
  1490. */
  1491. static class UnmodifiableNavigableMap<K,V>
  1492. extends UnmodifiableSortedMap<K,V>
  1493. implements NavigableMap<K,V>, Serializable {
  1494. private static final long serialVersionUID = -4858195264774772197L;
  1495. /**
  1496. * A class for the {@link EMPTY_NAVIGABLE_MAP} which needs readResolve
  1497. * to preserve singleton property.
  1498. *
  1499. * @param <K> type of keys, if there were any, and of bounds
  1500. * @param <V> type of values, if there were any
  1501. */
  1502. private static class EmptyNavigableMap<K,V> extends UnmodifiableNavigableMap<K,V>
  1503. implements Serializable {
  1504. private static final long serialVersionUID = -2239321462712562324L;
  1505. EmptyNavigableMap() { super(new TreeMap<K,V>()); }
  1506. @Override
  1507. public NavigableSet<K> navigableKeySet()
  1508. { return emptyNavigableSet(); }
  1509. private Object readResolve() { return EMPTY_NAVIGABLE_MAP; }
  1510. }
  1511. /**
  1512. * Singleton for {@link emptyNavigableMap()} which is also immutable.
  1513. */
  1514. private static final EmptyNavigableMap<?,?> EMPTY_NAVIGABLE_MAP =
  1515. new EmptyNavigableMap<>();
  1516. /**
  1517. * The instance we wrap and protect.
  1518. */
  1519. private final NavigableMap<K, ? extends V> nm;
  1520. UnmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
  1521. {super(m); nm = m;}
  1522. public K lowerKey(K key) { return nm.lowerKey(key); }
  1523. public K floorKey(K key) { return nm.floorKey(key); }
  1524. public K ceilingKey(K key) { return nm.ceilingKey(key); }
  1525. public K higherKey(K key) { return nm.higherKey(key); }
  1526. @SuppressWarnings("unchecked")
  1527. public Entry<K, V> lowerEntry(K key) {
  1528. Entry<K,V> lower = (Entry<K, V>) nm.lowerEntry(key);
  1529. return (null != lower)
  1530. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(lower)
  1531. : null;
  1532. }
  1533. @SuppressWarnings("unchecked")
  1534. public Entry<K, V> floorEntry(K key) {
  1535. Entry<K,V> floor = (Entry<K, V>) nm.floorEntry(key);
  1536. return (null != floor)
  1537. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(floor)
  1538. : null;
  1539. }
  1540. @SuppressWarnings("unchecked")
  1541. public Entry<K, V> ceilingEntry(K key) {
  1542. Entry<K,V> ceiling = (Entry<K, V>) nm.ceilingEntry(key);
  1543. return (null != ceiling)
  1544. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(ceiling)
  1545. : null;
  1546. }
  1547. @SuppressWarnings("unchecked")
  1548. public Entry<K, V> higherEntry(K key) {
  1549. Entry<K,V> higher = (Entry<K, V>) nm.higherEntry(key);
  1550. return (null != higher)
  1551. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(higher)
  1552. : null;
  1553. }
  1554. @SuppressWarnings("unchecked")
  1555. public Entry<K, V> firstEntry() {
  1556. Entry<K,V> first = (Entry<K, V>) nm.firstEntry();
  1557. return (null != first)
  1558. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(first)
  1559. : null;
  1560. }
  1561. @SuppressWarnings("unchecked")
  1562. public Entry<K, V> lastEntry() {
  1563. Entry<K,V> last = (Entry<K, V>) nm.lastEntry();
  1564. return (null != last)
  1565. ? new UnmodifiableEntrySet.UnmodifiableEntry<>(last)
  1566. : null;
  1567. }
  1568. public Entry<K, V> pollFirstEntry()
  1569. { throw new UnsupportedOperationException(); }
  1570. public Entry<K, V> pollLastEntry()
  1571. { throw new UnsupportedOperationException(); }
  1572. public NavigableMap<K, V> descendingMap()
  1573. { return unmodifiableNavigableMap(nm.descendingMap()); }
  1574. public NavigableSet<K> navigableKeySet()
  1575. { return unmodifiableNavigableSet(nm.navigableKeySet()); }
  1576. public NavigableSet<K> descendingKeySet()
  1577. { return unmodifiableNavigableSet(nm.descendingKeySet()); }
  1578. public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
  1579. return unmodifiableNavigableMap(
  1580. nm.subMap(fromKey, fromInclusive, toKey, toInclusive));
  1581. }
  1582. public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
  1583. { return unmodifiableNavigableMap(nm.headMap(toKey, inclusive)); }
  1584. public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
  1585. { return unmodifiableNavigableMap(nm.tailMap(fromKey, inclusive)); }
  1586. }
  1587. // Synch Wrappers
  1588. /**
  1589. * Returns a synchronized (thread-safe) collection backed by the specified
  1590. * collection. In order to guarantee serial access, it is critical that
  1591. * <strong>all</strong> access to the backing collection is accomplished
  1592. * through the returned collection.<p>
  1593. *
  1594. * It is imperative that the user manually synchronize on the returned
  1595. * collection when traversing it via {@link Iterator}, {@link Spliterator}
  1596. * or {@link Stream}:
  1597. *
  1598. <pre>
  1599. * Collection c = Collections.synchronizedCollection(myCollection);
  1600. * ...
  1601. * synchronized (c) {
  1602. * Iterator i = c.iterator(); // Must be in the synchronized block
  1603. * while (i.hasNext())
  1604. * foo(i.next());
  1605. * }
  1606. * </pre>
  1607. * Failure to follow this advice may result in non-deterministic behavior.
  1608. *
  1609. * <p>The returned collection does <i>not</i> pass the {@code hashCode}
  1610. * and {@code equals} operations through to the backing collection, but
  1611. * relies on {@code Object}'s equals and hashCode methods. This is
  1612. * necessary to preserve the contracts of these operations in the case
  1613. * that the backing collection is a set or a list.<p>
  1614. *
  1615. * The returned collection will be serializable if the specified collection
  1616. * is serializable.
  1617. *
  1618. * @param <T> the class of the objects in the collection
  1619. * @param c the collection to be "wrapped" in a synchronized collection.
  1620. * @return a synchronized view of the specified collection.
  1621. */
  1622. public static <T> Collection<T> synchronizedCollection(Collection<T> c) {
  1623. return new SynchronizedCollection<>(c);
  1624. }
  1625. static <T> Collection<T> synchronizedCollection(Collection<T> c, Object mutex) {
  1626. return new SynchronizedCollection<>(c, mutex);
  1627. }
  1628. /**
  1629. * @serial include
  1630. */
  1631. static class SynchronizedCollection<E> implements Collection<E>, Serializable {
  1632. private static final long serialVersionUID = 3053995032091335093L;
  1633. final Collection<E> c; // Backing Collection
  1634. final Object mutex; // Object on which to synchronize
  1635. SynchronizedCollection(Collection<E> c) {
  1636. this.c = Objects.requireNonNull(c);
  1637. mutex = this;
  1638. }
  1639. SynchronizedCollection(Collection<E> c, Object mutex) {
  1640. this.c = Objects.requireNonNull(c);
  1641. this.mutex = Objects.requireNonNull(mutex);
  1642. }
  1643. public int size() {
  1644. synchronized (mutex) {return c.size();}
  1645. }
  1646. public boolean isEmpty() {
  1647. synchronized (mutex) {return c.isEmpty();}
  1648. }
  1649. public boolean contains(Object o) {
  1650. synchronized (mutex) {return c.contains(o);}
  1651. }
  1652. public Object[] toArray() {
  1653. synchronized (mutex) {return c.toArray();}
  1654. }
  1655. public <T> T[] toArray(T[] a) {
  1656. synchronized (mutex) {return c.toArray(a);}
  1657. }
  1658. public Iterator<E> iterator() {
  1659. return c.iterator(); // Must be manually synched by user!
  1660. }
  1661. public boolean add(E e) {
  1662. synchronized (mutex) {return c.add(e);}
  1663. }
  1664. public boolean remove(Object o) {
  1665. synchronized (mutex) {return c.remove(o);}
  1666. }
  1667. public boolean containsAll(Collection<?> coll) {
  1668. synchronized (mutex) {return c.containsAll(coll);}
  1669. }
  1670. public boolean addAll(Collection<? extends E> coll) {
  1671. synchronized (mutex) {return c.addAll(coll);}
  1672. }
  1673. public boolean removeAll(Collection<?> coll) {
  1674. synchronized (mutex) {return c.removeAll(coll);}
  1675. }
  1676. public boolean retainAll(Collection<?> coll) {
  1677. synchronized (mutex) {return c.retainAll(coll);}
  1678. }
  1679. public void clear() {
  1680. synchronized (mutex) {c.clear();}
  1681. }
  1682. public String toString() {
  1683. synchronized (mutex) {return c.toString();}
  1684. }
  1685. // Override default methods in Collection
  1686. @Override
  1687. public void forEach(Consumer<? super E> consumer) {
  1688. synchronized (mutex) {c.forEach(consumer);}
  1689. }
  1690. @Override
  1691. public boolean removeIf(Predicate<? super E> filter) {
  1692. synchronized (mutex) {return c.removeIf(filter);}
  1693. }
  1694. @Override
  1695. public Spliterator<E> spliterator() {
  1696. return c.spliterator(); // Must be manually synched by user!
  1697. }
  1698. @Override
  1699. public Stream<E> stream() {
  1700. return c.stream(); // Must be manually synched by user!
  1701. }
  1702. @Override
  1703. public Stream<E> parallelStream() {
  1704. return c.parallelStream(); // Must be manually synched by user!
  1705. }
  1706. private void writeObject(ObjectOutputStream s) throws IOException {
  1707. synchronized (mutex) {s.defaultWriteObject();}
  1708. }
  1709. }
  1710. /**
  1711. * Returns a synchronized (thread-safe) set backed by the specified
  1712. * set. In order to guarantee serial access, it is critical that
  1713. * <strong>all</strong> access to the backing set is accomplished
  1714. * through the returned set.<p>
  1715. *
  1716. * It is imperative that the user manually synchronize on the returned
  1717. * set when iterating over it:
  1718. *
  1719. <pre>
  1720. * Set s = Collections.synchronizedSet(new HashSet());
  1721. * ...
  1722. * synchronized (s) {
  1723. * Iterator i = s.iterator(); // Must be in the synchronized block
  1724. * while (i.hasNext())
  1725. * foo(i.next());
  1726. * }
  1727. * </pre>
  1728. * Failure to follow this advice may result in non-deterministic behavior.
  1729. *
  1730. * <p>The returned set will be serializable if the specified set is
  1731. * serializable.
  1732. *
  1733. * @param <T> the class of the objects in the set
  1734. * @param s the set to be "wrapped" in a synchronized set.
  1735. * @return a synchronized view of the specified set.
  1736. */
  1737. public static <T> Set<T> synchronizedSet(Set<T> s) {
  1738. return new SynchronizedSet<>(s);
  1739. }
  1740. static <T> Set<T> synchronizedSet(Set<T> s, Object mutex) {
  1741. return new SynchronizedSet<>(s, mutex);
  1742. }
  1743. /**
  1744. * @serial include
  1745. */
  1746. static class SynchronizedSet<E>
  1747. extends SynchronizedCollection<E>
  1748. implements Set<E> {
  1749. private static final long serialVersionUID = 487447009682186044L;
  1750. SynchronizedSet(Set<E> s) {
  1751. super(s);
  1752. }
  1753. SynchronizedSet(Set<E> s, Object mutex) {
  1754. super(s, mutex);
  1755. }
  1756. public boolean equals(Object o) {
  1757. if (this == o)
  1758. return true;
  1759. synchronized (mutex) {return c.equals(o);}
  1760. }
  1761. public int hashCode() {
  1762. synchronized (mutex) {return c.hashCode();}
  1763. }
  1764. }
  1765. /**
  1766. * Returns a synchronized (thread-safe) sorted set backed by the specified
  1767. * sorted set. In order to guarantee serial access, it is critical that
  1768. * <strong>all</strong> access to the backing sorted set is accomplished
  1769. * through the returned sorted set (or its views).<p>
  1770. *
  1771. * It is imperative that the user manually synchronize on the returned
  1772. * sorted set when iterating over it or any of its <tt>subSet</tt>,
  1773. * <tt>headSet</tt>, or <tt>tailSet</tt> views.
  1774. *
  1775. <pre>
  1776. * SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
  1777. * ...
  1778. * synchronized (s) {
  1779. * Iterator i = s.iterator(); // Must be in the synchronized block
  1780. * while (i.hasNext())
  1781. * foo(i.next());
  1782. * }
  1783. * </pre>
  1784. * or:
  1785. *
  1786. <pre>
  1787. * SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
  1788. * SortedSet s2 = s.headSet(foo);
  1789. * ...
  1790. * synchronized (s) { // Note: s, not s2!!!
  1791. * Iterator i = s2.iterator(); // Must be in the synchronized block
  1792. * while (i.hasNext())
  1793. * foo(i.next());
  1794. * }
  1795. * </pre>
  1796. * Failure to follow this advice may result in non-deterministic behavior.
  1797. *
  1798. * <p>The returned sorted set will be serializable if the specified
  1799. * sorted set is serializable.
  1800. *
  1801. * @param <T> the class of the objects in the set
  1802. * @param s the sorted set to be "wrapped" in a synchronized sorted set.
  1803. * @return a synchronized view of the specified sorted set.
  1804. */
  1805. public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s) {
  1806. return new SynchronizedSortedSet<>(s);
  1807. }
  1808. /**
  1809. * @serial include
  1810. */
  1811. static class SynchronizedSortedSet<E>
  1812. extends SynchronizedSet<E>
  1813. implements SortedSet<E>
  1814. {
  1815. private static final long serialVersionUID = 8695801310862127406L;
  1816. private final SortedSet<E> ss;
  1817. SynchronizedSortedSet(SortedSet<E> s) {
  1818. super(s);
  1819. ss = s;
  1820. }
  1821. SynchronizedSortedSet(SortedSet<E> s, Object mutex) {
  1822. super(s, mutex);
  1823. ss = s;
  1824. }
  1825. public Comparator<? super E> comparator() {
  1826. synchronized (mutex) {return ss.comparator();}
  1827. }
  1828. public SortedSet<E> subSet(E fromElement, E toElement) {
  1829. synchronized (mutex) {
  1830. return new SynchronizedSortedSet<>(
  1831. ss.subSet(fromElement, toElement), mutex);
  1832. }
  1833. }
  1834. public SortedSet<E> headSet(E toElement) {
  1835. synchronized (mutex) {
  1836. return new SynchronizedSortedSet<>(ss.headSet(toElement), mutex);
  1837. }
  1838. }
  1839. public SortedSet<E> tailSet(E fromElement) {
  1840. synchronized (mutex) {
  1841. return new SynchronizedSortedSet<>(ss.tailSet(fromElement),mutex);
  1842. }
  1843. }
  1844. public E first() {
  1845. synchronized (mutex) {return ss.first();}
  1846. }
  1847. public E last() {
  1848. synchronized (mutex) {return ss.last();}
  1849. }
  1850. }
  1851. /**
  1852. * Returns a synchronized (thread-safe) navigable set backed by the
  1853. * specified navigable set. In order to guarantee serial access, it is
  1854. * critical that <strong>all</strong> access to the backing navigable set is
  1855. * accomplished through the returned navigable set (or its views).<p>
  1856. *
  1857. * It is imperative that the user manually synchronize on the returned
  1858. * navigable set when iterating over it or any of its {@code subSet},
  1859. * {@code headSet}, or {@code tailSet} views.
  1860. *
  1861. <pre>
  1862. * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
  1863. * ...
  1864. * synchronized (s) {
  1865. * Iterator i = s.iterator(); // Must be in the synchronized block
  1866. * while (i.hasNext())
  1867. * foo(i.next());
  1868. * }
  1869. * </pre>
  1870. * or:
  1871. *
  1872. <pre>
  1873. * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
  1874. * NavigableSet s2 = s.headSet(foo, true);
  1875. * ...
  1876. * synchronized (s) { // Note: s, not s2!!!
  1877. * Iterator i = s2.iterator(); // Must be in the synchronized block
  1878. * while (i.hasNext())
  1879. * foo(i.next());
  1880. * }
  1881. * </pre>
  1882. * Failure to follow this advice may result in non-deterministic behavior.
  1883. *
  1884. * <p>The returned navigable set will be serializable if the specified
  1885. * navigable set is serializable.
  1886. *
  1887. * @param <T> the class of the objects in the set
  1888. * @param s the navigable set to be "wrapped" in a synchronized navigable
  1889. * set
  1890. * @return a synchronized view of the specified navigable set
  1891. * @since 1.8
  1892. */
  1893. public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) {
  1894. return new SynchronizedNavigableSet<>(s);
  1895. }
  1896. /**
  1897. * @serial include
  1898. */
  1899. static class SynchronizedNavigableSet<E>
  1900. extends SynchronizedSortedSet<E>
  1901. implements NavigableSet<E>
  1902. {
  1903. private static final long serialVersionUID = -5505529816273629798L;
  1904. private final NavigableSet<E> ns;
  1905. SynchronizedNavigableSet(NavigableSet<E> s) {
  1906. super(s);
  1907. ns = s;
  1908. }
  1909. SynchronizedNavigableSet(NavigableSet<E> s, Object mutex) {
  1910. super(s, mutex);
  1911. ns = s;
  1912. }
  1913. public E lower(E e) { synchronized (mutex) {return ns.lower(e);} }
  1914. public E floor(E e) { synchronized (mutex) {return ns.floor(e);} }
  1915. public E ceiling(E e) { synchronized (mutex) {return ns.ceiling(e);} }
  1916. public E higher(E e) { synchronized (mutex) {return ns.higher(e);} }
  1917. public E pollFirst() { synchronized (mutex) {return ns.pollFirst();} }
  1918. public E pollLast() { synchronized (mutex) {return ns.pollLast();} }
  1919. public NavigableSet<E> descendingSet() {
  1920. synchronized (mutex) {
  1921. return new SynchronizedNavigableSet<>(ns.descendingSet(), mutex);
  1922. }
  1923. }
  1924. public Iterator<E> descendingIterator()
  1925. { synchronized (mutex) { return descendingSet().iterator(); } }
  1926. public NavigableSet<E> subSet(E fromElement, E toElement) {
  1927. synchronized (mutex) {
  1928. return new SynchronizedNavigableSet<>(ns.subSet(fromElement, true, toElement, false), mutex);
  1929. }
  1930. }
  1931. public NavigableSet<E> headSet(E toElement) {
  1932. synchronized (mutex) {
  1933. return new SynchronizedNavigableSet<>(ns.headSet(toElement, false), mutex);
  1934. }
  1935. }
  1936. public NavigableSet<E> tailSet(E fromElement) {
  1937. synchronized (mutex) {
  1938. return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex);
  1939. }
  1940. }
  1941. public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
  1942. synchronized (mutex) {
  1943. return new SynchronizedNavigableSet<>(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
  1944. }
  1945. }
  1946. public NavigableSet<E> headSet(E toElement, boolean inclusive) {
  1947. synchronized (mutex) {
  1948. return new SynchronizedNavigableSet<>(ns.headSet(toElement, inclusive), mutex);
  1949. }
  1950. }
  1951. public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
  1952. synchronized (mutex) {
  1953. return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex);
  1954. }
  1955. }
  1956. }
  1957. /**
  1958. * Returns a synchronized (thread-safe) list backed by the specified
  1959. * list. In order to guarantee serial access, it is critical that
  1960. * <strong>all</strong> access to the backing list is accomplished
  1961. * through the returned list.<p>
  1962. *
  1963. * It is imperative that the user manually synchronize on the returned
  1964. * list when iterating over it:
  1965. *
  1966. <pre>
  1967. * List list = Collections.synchronizedList(new ArrayList());
  1968. * ...
  1969. * synchronized (list) {
  1970. * Iterator i = list.iterator(); // Must be in synchronized block
  1971. * while (i.hasNext())
  1972. * foo(i.next());
  1973. * }
  1974. * </pre>
  1975. * Failure to follow this advice may result in non-deterministic behavior.
  1976. *
  1977. * <p>The returned list will be serializable if the specified list is
  1978. * serializable.
  1979. *
  1980. * @param <T> the class of the objects in the list
  1981. * @param list the list to be "wrapped" in a synchronized list.
  1982. * @return a synchronized view of the specified list.
  1983. */
  1984. public static <T> List<T> synchronizedList(List<T> list) {
  1985. return (list instanceof RandomAccess ?
  1986. new SynchronizedRandomAccessList<>(list) :
  1987. new SynchronizedList<>(list));
  1988. }
  1989. static <T> List<T> synchronizedList(List<T> list, Object mutex) {
  1990. return (list instanceof RandomAccess ?
  1991. new SynchronizedRandomAccessList<>(list, mutex) :
  1992. new SynchronizedList<>(list, mutex));
  1993. }
  1994. /**
  1995. * @serial include
  1996. */
  1997. static class SynchronizedList<E>
  1998. extends SynchronizedCollection<E>
  1999. implements List<E> {
  2000. private static final long serialVersionUID = -7754090372962971524L;
  2001. final List<E> list;
  2002. SynchronizedList(List<E> list) {
  2003. super(list);
  2004. this.list = list;
  2005. }
  2006. SynchronizedList(List<E> list, Object mutex) {
  2007. super(list, mutex);
  2008. this.list = list;
  2009. }
  2010. public boolean equals(Object o) {
  2011. if (this == o)
  2012. return true;
  2013. synchronized (mutex) {return list.equals(o);}
  2014. }
  2015. public int hashCode() {
  2016. synchronized (mutex) {return list.hashCode();}
  2017. }
  2018. public E get(int index) {
  2019. synchronized (mutex) {return list.get(index);}
  2020. }
  2021. public E set(int index, E element) {
  2022. synchronized (mutex) {return list.set(index, element);}
  2023. }
  2024. public void add(int index, E element) {
  2025. synchronized (mutex) {list.add(index, element);}
  2026. }
  2027. public E remove(int index) {
  2028. synchronized (mutex) {return list.remove(index);}
  2029. }
  2030. public int indexOf(Object o) {
  2031. synchronized (mutex) {return list.indexOf(o);}
  2032. }
  2033. public int lastIndexOf(Object o) {
  2034. synchronized (mutex) {return list.lastIndexOf(o);}
  2035. }
  2036. public boolean addAll(int index, Collection<? extends E> c) {
  2037. synchronized (mutex) {return list.addAll(index, c);}
  2038. }
  2039. public ListIterator<E> listIterator() {
  2040. return list.listIterator(); // Must be manually synched by user
  2041. }
  2042. public ListIterator<E> listIterator(int index) {
  2043. return list.listIterator(index); // Must be manually synched by user
  2044. }
  2045. public List<E> subList(int fromIndex, int toIndex) {
  2046. synchronized (mutex) {
  2047. return new SynchronizedList<>(list.subList(fromIndex, toIndex),
  2048. mutex);
  2049. }
  2050. }
  2051. @Override
  2052. public void replaceAll(UnaryOperator<E> operator) {
  2053. synchronized (mutex) {list.replaceAll(operator);}
  2054. }
  2055. @Override
  2056. public void sort(Comparator<? super E> c) {
  2057. synchronized (mutex) {list.sort(c);}
  2058. }
  2059. /**
  2060. * SynchronizedRandomAccessList instances are serialized as
  2061. * SynchronizedList instances to allow them to be deserialized
  2062. * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
  2063. * This method inverts the transformation. As a beneficial
  2064. * side-effect, it also grafts the RandomAccess marker onto
  2065. * SynchronizedList instances that were serialized in pre-1.4 JREs.
  2066. *
  2067. * Note: Unfortunately, SynchronizedRandomAccessList instances
  2068. * serialized in 1.4.1 and deserialized in 1.4 will become
  2069. * SynchronizedList instances, as this method was missing in 1.4.
  2070. */
  2071. private Object readResolve() {
  2072. return (list instanceof RandomAccess
  2073. ? new SynchronizedRandomAccessList<>(list)
  2074. : this);
  2075. }
  2076. }
  2077. /**
  2078. * @serial include
  2079. */
  2080. static class SynchronizedRandomAccessList<E>
  2081. extends SynchronizedList<E>
  2082. implements RandomAccess {
  2083. SynchronizedRandomAccessList(List<E> list) {
  2084. super(list);
  2085. }
  2086. SynchronizedRandomAccessList(List<E> list, Object mutex) {
  2087. super(list, mutex);
  2088. }
  2089. public List<E> subList(int fromIndex, int toIndex) {
  2090. synchronized (mutex) {
  2091. return new SynchronizedRandomAccessList<>(
  2092. list.subList(fromIndex, toIndex), mutex);
  2093. }
  2094. }
  2095. private static final long serialVersionUID = 1530674583602358482L;
  2096. /**
  2097. * Allows instances to be deserialized in pre-1.4 JREs (which do
  2098. * not have SynchronizedRandomAccessList). SynchronizedList has
  2099. * a readResolve method that inverts this transformation upon
  2100. * deserialization.
  2101. */
  2102. private Object writeReplace() {
  2103. return new SynchronizedList<>(list);
  2104. }
  2105. }
  2106. /**
  2107. * Returns a synchronized (thread-safe) map backed by the specified
  2108. * map. In order to guarantee serial access, it is critical that
  2109. * <strong>all</strong> access to the backing map is accomplished
  2110. * through the returned map.<p>
  2111. *
  2112. * It is imperative that the user manually synchronize on the returned
  2113. * map when iterating over any of its collection views:
  2114. *
  2115. <pre>
  2116. * Map m = Collections.synchronizedMap(new HashMap());
  2117. * ...
  2118. * Set s = m.keySet(); // Needn't be in synchronized block
  2119. * ...
  2120. * synchronized (m) { // Synchronizing on m, not s!
  2121. * Iterator i = s.iterator(); // Must be in synchronized block
  2122. * while (i.hasNext())
  2123. * foo(i.next());
  2124. * }
  2125. * </pre>
  2126. * Failure to follow this advice may result in non-deterministic behavior.
  2127. *
  2128. * <p>The returned map will be serializable if the specified map is
  2129. * serializable.
  2130. *
  2131. * @param <K> the class of the map keys
  2132. * @param <V> the class of the map values
  2133. * @param m the map to be "wrapped" in a synchronized map.
  2134. * @return a synchronized view of the specified map.
  2135. */
  2136. public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
  2137. return new SynchronizedMap<>(m);
  2138. }
  2139. /**
  2140. * @serial include
  2141. */
  2142. private static class SynchronizedMap<K,V>
  2143. implements Map<K,V>, Serializable {
  2144. private static final long serialVersionUID = 1978198479659022715L;
  2145. private final Map<K,V> m; // Backing Map
  2146. final Object mutex; // Object on which to synchronize
  2147. SynchronizedMap(Map<K,V> m) {
  2148. this.m = Objects.requireNonNull(m);
  2149. mutex = this;
  2150. }
  2151. SynchronizedMap(Map<K,V> m, Object mutex) {
  2152. this.m = m;
  2153. this.mutex = mutex;
  2154. }
  2155. public int size() {
  2156. synchronized (mutex) {return m.size();}
  2157. }
  2158. public boolean isEmpty() {
  2159. synchronized (mutex) {return m.isEmpty();}
  2160. }
  2161. public boolean containsKey(Object key) {
  2162. synchronized (mutex) {return m.containsKey(key);}
  2163. }
  2164. public boolean containsValue(Object value) {
  2165. synchronized (mutex) {return m.containsValue(value);}
  2166. }
  2167. public V get(Object key) {
  2168. synchronized (mutex) {return m.get(key);}
  2169. }
  2170. public V put(K key, V value) {
  2171. synchronized (mutex) {return m.put(key, value);}
  2172. }
  2173. public V remove(Object key) {
  2174. synchronized (mutex) {return m.remove(key);}
  2175. }
  2176. public void putAll(Map<? extends K, ? extends V> map) {
  2177. synchronized (mutex) {m.putAll(map);}
  2178. }
  2179. public void clear() {
  2180. synchronized (mutex) {m.clear();}
  2181. }
  2182. private transient Set<K> keySet;
  2183. private transient Set<Map.Entry<K,V>> entrySet;
  2184. private transient Collection<V> values;
  2185. public Set<K> keySet() {
  2186. synchronized (mutex) {
  2187. if (keySet==null)
  2188. keySet = new SynchronizedSet<>(m.keySet(), mutex);
  2189. return keySet;
  2190. }
  2191. }
  2192. public Set<Map.Entry<K,V>> entrySet() {
  2193. synchronized (mutex) {
  2194. if (entrySet==null)
  2195. entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
  2196. return entrySet;
  2197. }
  2198. }
  2199. public Collection<V> values() {
  2200. synchronized (mutex) {
  2201. if (values==null)
  2202. values = new SynchronizedCollection<>(m.values(), mutex);
  2203. return values;
  2204. }
  2205. }
  2206. public boolean equals(Object o) {
  2207. if (this == o)
  2208. return true;
  2209. synchronized (mutex) {return m.equals(o);}
  2210. }
  2211. public int hashCode() {
  2212. synchronized (mutex) {return m.hashCode();}
  2213. }
  2214. public String toString() {
  2215. synchronized (mutex) {return m.toString();}
  2216. }
  2217. // Override default methods in Map
  2218. @Override
  2219. public V getOrDefault(Object k, V defaultValue) {
  2220. synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
  2221. }
  2222. @Override
  2223. public void forEach(BiConsumer<? super K, ? super V> action) {
  2224. synchronized (mutex) {m.forEach(action);}
  2225. }
  2226. @Override
  2227. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  2228. synchronized (mutex) {m.replaceAll(function);}
  2229. }
  2230. @Override
  2231. public V putIfAbsent(K key, V value) {
  2232. synchronized (mutex) {return m.putIfAbsent(key, value);}
  2233. }
  2234. @Override
  2235. public boolean remove(Object key, Object value) {
  2236. synchronized (mutex) {return m.remove(key, value);}
  2237. }
  2238. @Override
  2239. public boolean replace(K key, V oldValue, V newValue) {
  2240. synchronized (mutex) {return m.replace(key, oldValue, newValue);}
  2241. }
  2242. @Override
  2243. public V replace(K key, V value) {
  2244. synchronized (mutex) {return m.replace(key, value);}
  2245. }
  2246. @Override
  2247. public V computeIfAbsent(K key,
  2248. Function<? super K, ? extends V> mappingFunction) {
  2249. synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
  2250. }
  2251. @Override
  2252. public V computeIfPresent(K key,
  2253. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  2254. synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
  2255. }
  2256. @Override
  2257. public V compute(K key,
  2258. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  2259. synchronized (mutex) {return m.compute(key, remappingFunction);}
  2260. }
  2261. @Override
  2262. public V merge(K key, V value,
  2263. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  2264. synchronized (mutex) {return m.merge(key, value, remappingFunction);}
  2265. }
  2266. private void writeObject(ObjectOutputStream s) throws IOException {
  2267. synchronized (mutex) {s.defaultWriteObject();}
  2268. }
  2269. }
  2270. /**
  2271. * Returns a synchronized (thread-safe) sorted map backed by the specified
  2272. * sorted map. In order to guarantee serial access, it is critical that
  2273. * <strong>all</strong> access to the backing sorted map is accomplished
  2274. * through the returned sorted map (or its views).<p>
  2275. *
  2276. * It is imperative that the user manually synchronize on the returned
  2277. * sorted map when iterating over any of its collection views, or the
  2278. * collections views of any of its <tt>subMap</tt>, <tt>headMap</tt> or
  2279. * <tt>tailMap</tt> views.
  2280. *
  2281. <pre>
  2282. * SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
  2283. * ...
  2284. * Set s = m.keySet(); // Needn't be in synchronized block
  2285. * ...
  2286. * synchronized (m) { // Synchronizing on m, not s!
  2287. * Iterator i = s.iterator(); // Must be in synchronized block
  2288. * while (i.hasNext())
  2289. * foo(i.next());
  2290. * }
  2291. * </pre>
  2292. * or:
  2293. *
  2294. <pre>
  2295. * SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
  2296. * SortedMap m2 = m.subMap(foo, bar);
  2297. * ...
  2298. * Set s2 = m2.keySet(); // Needn't be in synchronized block
  2299. * ...
  2300. * synchronized (m) { // Synchronizing on m, not m2 or s2!
  2301. * Iterator i = s.iterator(); // Must be in synchronized block
  2302. * while (i.hasNext())
  2303. * foo(i.next());
  2304. * }
  2305. * </pre>
  2306. * Failure to follow this advice may result in non-deterministic behavior.
  2307. *
  2308. * <p>The returned sorted map will be serializable if the specified
  2309. * sorted map is serializable.
  2310. *
  2311. * @param <K> the class of the map keys
  2312. * @param <V> the class of the map values
  2313. * @param m the sorted map to be "wrapped" in a synchronized sorted map.
  2314. * @return a synchronized view of the specified sorted map.
  2315. */
  2316. public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m) {
  2317. return new SynchronizedSortedMap<>(m);
  2318. }
  2319. /**
  2320. * @serial include
  2321. */
  2322. static class SynchronizedSortedMap<K,V>
  2323. extends SynchronizedMap<K,V>
  2324. implements SortedMap<K,V>
  2325. {
  2326. private static final long serialVersionUID = -8798146769416483793L;
  2327. private final SortedMap<K,V> sm;
  2328. SynchronizedSortedMap(SortedMap<K,V> m) {
  2329. super(m);
  2330. sm = m;
  2331. }
  2332. SynchronizedSortedMap(SortedMap<K,V> m, Object mutex) {
  2333. super(m, mutex);
  2334. sm = m;
  2335. }
  2336. public Comparator<? super K> comparator() {
  2337. synchronized (mutex) {return sm.comparator();}
  2338. }
  2339. public SortedMap<K,V> subMap(K fromKey, K toKey) {
  2340. synchronized (mutex) {
  2341. return new SynchronizedSortedMap<>(
  2342. sm.subMap(fromKey, toKey), mutex);
  2343. }
  2344. }
  2345. public SortedMap<K,V> headMap(K toKey) {
  2346. synchronized (mutex) {
  2347. return new SynchronizedSortedMap<>(sm.headMap(toKey), mutex);
  2348. }
  2349. }
  2350. public SortedMap<K,V> tailMap(K fromKey) {
  2351. synchronized (mutex) {
  2352. return new SynchronizedSortedMap<>(sm.tailMap(fromKey),mutex);
  2353. }
  2354. }
  2355. public K firstKey() {
  2356. synchronized (mutex) {return sm.firstKey();}
  2357. }
  2358. public K lastKey() {
  2359. synchronized (mutex) {return sm.lastKey();}
  2360. }
  2361. }
  2362. /**
  2363. * Returns a synchronized (thread-safe) navigable map backed by the
  2364. * specified navigable map. In order to guarantee serial access, it is
  2365. * critical that <strong>all</strong> access to the backing navigable map is
  2366. * accomplished through the returned navigable map (or its views).<p>
  2367. *
  2368. * It is imperative that the user manually synchronize on the returned
  2369. * navigable map when iterating over any of its collection views, or the
  2370. * collections views of any of its {@code subMap}, {@code headMap} or
  2371. * {@code tailMap} views.
  2372. *
  2373. <pre>
  2374. * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
  2375. * ...
  2376. * Set s = m.keySet(); // Needn't be in synchronized block
  2377. * ...
  2378. * synchronized (m) { // Synchronizing on m, not s!
  2379. * Iterator i = s.iterator(); // Must be in synchronized block
  2380. * while (i.hasNext())
  2381. * foo(i.next());
  2382. * }
  2383. * </pre>
  2384. * or:
  2385. *
  2386. <pre>
  2387. * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
  2388. * NavigableMap m2 = m.subMap(foo, true, bar, false);
  2389. * ...
  2390. * Set s2 = m2.keySet(); // Needn't be in synchronized block
  2391. * ...
  2392. * synchronized (m) { // Synchronizing on m, not m2 or s2!
  2393. * Iterator i = s.iterator(); // Must be in synchronized block
  2394. * while (i.hasNext())
  2395. * foo(i.next());
  2396. * }
  2397. * </pre>
  2398. * Failure to follow this advice may result in non-deterministic behavior.
  2399. *
  2400. * <p>The returned navigable map will be serializable if the specified
  2401. * navigable map is serializable.
  2402. *
  2403. * @param <K> the class of the map keys
  2404. * @param <V> the class of the map values
  2405. * @param m the navigable map to be "wrapped" in a synchronized navigable
  2406. * map
  2407. * @return a synchronized view of the specified navigable map.
  2408. * @since 1.8
  2409. */
  2410. public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) {
  2411. return new SynchronizedNavigableMap<>(m);
  2412. }
  2413. /**
  2414. * A synchronized NavigableMap.
  2415. *
  2416. * @serial include
  2417. */
  2418. static class SynchronizedNavigableMap<K,V>
  2419. extends SynchronizedSortedMap<K,V>
  2420. implements NavigableMap<K,V>
  2421. {
  2422. private static final long serialVersionUID = 699392247599746807L;
  2423. private final NavigableMap<K,V> nm;
  2424. SynchronizedNavigableMap(NavigableMap<K,V> m) {
  2425. super(m);
  2426. nm = m;
  2427. }
  2428. SynchronizedNavigableMap(NavigableMap<K,V> m, Object mutex) {
  2429. super(m, mutex);
  2430. nm = m;
  2431. }
  2432. public Entry<K, V> lowerEntry(K key)
  2433. { synchronized (mutex) { return nm.lowerEntry(key); } }
  2434. public K lowerKey(K key)
  2435. { synchronized (mutex) { return nm.lowerKey(key); } }
  2436. public Entry<K, V> floorEntry(K key)
  2437. { synchronized (mutex) { return nm.floorEntry(key); } }
  2438. public K floorKey(K key)
  2439. { synchronized (mutex) { return nm.floorKey(key); } }
  2440. public Entry<K, V> ceilingEntry(K key)
  2441. { synchronized (mutex) { return nm.ceilingEntry(key); } }
  2442. public K ceilingKey(K key)
  2443. { synchronized (mutex) { return nm.ceilingKey(key); } }
  2444. public Entry<K, V> higherEntry(K key)
  2445. { synchronized (mutex) { return nm.higherEntry(key); } }
  2446. public K higherKey(K key)
  2447. { synchronized (mutex) { return nm.higherKey(key); } }
  2448. public Entry<K, V> firstEntry()
  2449. { synchronized (mutex) { return nm.firstEntry(); } }
  2450. public Entry<K, V> lastEntry()
  2451. { synchronized (mutex) { return nm.lastEntry(); } }
  2452. public Entry<K, V> pollFirstEntry()
  2453. { synchronized (mutex) { return nm.pollFirstEntry(); } }
  2454. public Entry<K, V> pollLastEntry()
  2455. { synchronized (mutex) { return nm.pollLastEntry(); } }
  2456. public NavigableMap<K, V> descendingMap() {
  2457. synchronized (mutex) {
  2458. return
  2459. new SynchronizedNavigableMap<>(nm.descendingMap(), mutex);
  2460. }
  2461. }
  2462. public NavigableSet<K> keySet() {
  2463. return navigableKeySet();
  2464. }
  2465. public NavigableSet<K> navigableKeySet() {
  2466. synchronized (mutex) {
  2467. return new SynchronizedNavigableSet<>(nm.navigableKeySet(), mutex);
  2468. }
  2469. }
  2470. public NavigableSet<K> descendingKeySet() {
  2471. synchronized (mutex) {
  2472. return new SynchronizedNavigableSet<>(nm.descendingKeySet(), mutex);
  2473. }
  2474. }
  2475. public SortedMap<K,V> subMap(K fromKey, K toKey) {
  2476. synchronized (mutex) {
  2477. return new SynchronizedNavigableMap<>(
  2478. nm.subMap(fromKey, true, toKey, false), mutex);
  2479. }
  2480. }
  2481. public SortedMap<K,V> headMap(K toKey) {
  2482. synchronized (mutex) {
  2483. return new SynchronizedNavigableMap<>(nm.headMap(toKey, false), mutex);
  2484. }
  2485. }
  2486. public SortedMap<K,V> tailMap(K fromKey) {
  2487. synchronized (mutex) {
  2488. return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex);
  2489. }
  2490. }
  2491. public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
  2492. synchronized (mutex) {
  2493. return new SynchronizedNavigableMap<>(
  2494. nm.subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
  2495. }
  2496. }
  2497. public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
  2498. synchronized (mutex) {
  2499. return new SynchronizedNavigableMap<>(
  2500. nm.headMap(toKey, inclusive), mutex);
  2501. }
  2502. }
  2503. public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
  2504. synchronized (mutex) {
  2505. return new SynchronizedNavigableMap<>(
  2506. nm.tailMap(fromKey, inclusive), mutex);
  2507. }
  2508. }
  2509. }
  2510. // Dynamically typesafe collection wrappers
  2511. /**
  2512. * Returns a dynamically typesafe view of the specified collection.
  2513. * Any attempt to insert an element of the wrong type will result in an
  2514. * immediate {@link ClassCastException}. Assuming a collection
  2515. * contains no incorrectly typed elements prior to the time a
  2516. * dynamically typesafe view is generated, and that all subsequent
  2517. * access to the collection takes place through the view, it is
  2518. * <i>guaranteed</i> that the collection cannot contain an incorrectly
  2519. * typed element.
  2520. *
  2521. * <p>The generics mechanism in the language provides compile-time
  2522. * (static) type checking, but it is possible to defeat this mechanism
  2523. * with unchecked casts. Usually this is not a problem, as the compiler
  2524. * issues warnings on all such unchecked operations. There are, however,
  2525. * times when static type checking alone is not sufficient. For example,
  2526. * suppose a collection is passed to a third-party library and it is
  2527. * imperative that the library code not corrupt the collection by
  2528. * inserting an element of the wrong type.
  2529. *
  2530. * <p>Another use of dynamically typesafe views is debugging. Suppose a
  2531. * program fails with a {@code ClassCastException}, indicating that an
  2532. * incorrectly typed element was put into a parameterized collection.
  2533. * Unfortunately, the exception can occur at any time after the erroneous
  2534. * element is inserted, so it typically provides little or no information
  2535. * as to the real source of the problem. If the problem is reproducible,
  2536. * one can quickly determine its source by temporarily modifying the
  2537. * program to wrap the collection with a dynamically typesafe view.
  2538. * For example, this declaration:
  2539. *
  2540. <pre> {@code
  2541. * Collection<String> c = new HashSet<>();
  2542. * }</pre>
  2543. * may be replaced temporarily by this one:
  2544. *
  2545. <pre> {@code
  2546. * Collection<String> c = Collections.checkedCollection(
  2547. * new HashSet<>(), String.class);
  2548. * }</pre>
  2549. * Running the program again will cause it to fail at the point where
  2550. * an incorrectly typed element is inserted into the collection, clearly
  2551. * identifying the source of the problem. Once the problem is fixed, the
  2552. * modified declaration may be reverted back to the original.
  2553. *
  2554. * <p>The returned collection does <i>not</i> pass the hashCode and equals
  2555. * operations through to the backing collection, but relies on
  2556. * {@code Object}'s {@code equals} and {@code hashCode} methods. This
  2557. * is necessary to preserve the contracts of these operations in the case
  2558. * that the backing collection is a set or a list.
  2559. *
  2560. * <p>The returned collection will be serializable if the specified
  2561. * collection is serializable.
  2562. *
  2563. * <p>Since {@code null} is considered to be a value of any reference
  2564. * type, the returned collection permits insertion of null elements
  2565. * whenever the backing collection does.
  2566. *
  2567. * @param <E> the class of the objects in the collection
  2568. * @param c the collection for which a dynamically typesafe view is to be
  2569. * returned
  2570. * @param type the type of element that {@code c} is permitted to hold
  2571. * @return a dynamically typesafe view of the specified collection
  2572. * @since 1.5
  2573. */
  2574. public static <E> Collection<E> checkedCollection(Collection<E> c,
  2575. Class<E> type) {
  2576. return new CheckedCollection<>(c, type);
  2577. }
  2578. @SuppressWarnings("unchecked")
  2579. static <T> T[] zeroLengthArray(Class<T> type) {
  2580. return (T[]) Array.newInstance(type, 0);
  2581. }
  2582. /**
  2583. * @serial include
  2584. */
  2585. static class CheckedCollection<E> implements Collection<E>, Serializable {
  2586. private static final long serialVersionUID = 1578914078182001775L;
  2587. final Collection<E> c;
  2588. final Class<E> type;
  2589. @SuppressWarnings("unchecked")
  2590. E typeCheck(Object o) {
  2591. if (o != null && !type.isInstance(o))
  2592. throw new ClassCastException(badElementMsg(o));
  2593. return (E) o;
  2594. }
  2595. private String badElementMsg(Object o) {
  2596. return "Attempt to insert " + o.getClass() +
  2597. " element into collection with element type " + type;
  2598. }
  2599. CheckedCollection(Collection<E> c, Class<E> type) {
  2600. this.c = Objects.requireNonNull(c, "c");
  2601. this.type = Objects.requireNonNull(type, "type");
  2602. }
  2603. public int size() { return c.size(); }
  2604. public boolean isEmpty() { return c.isEmpty(); }
  2605. public boolean contains(Object o) { return c.contains(o); }
  2606. public Object[] toArray() { return c.toArray(); }
  2607. public <T> T[] toArray(T[] a) { return c.toArray(a); }
  2608. public String toString() { return c.toString(); }
  2609. public boolean remove(Object o) { return c.remove(o); }
  2610. public void clear() { c.clear(); }
  2611. public boolean containsAll(Collection<?> coll) {
  2612. return c.containsAll(coll);
  2613. }
  2614. public boolean removeAll(Collection<?> coll) {
  2615. return c.removeAll(coll);
  2616. }
  2617. public boolean retainAll(Collection<?> coll) {
  2618. return c.retainAll(coll);
  2619. }
  2620. public Iterator<E> iterator() {
  2621. // JDK-6363904 - unwrapped iterator could be typecast to
  2622. // ListIterator with unsafe set()
  2623. final Iterator<E> it = c.iterator();
  2624. return new Iterator<E>() {
  2625. public boolean hasNext() { return it.hasNext(); }
  2626. public E next() { return it.next(); }
  2627. public void remove() { it.remove(); }};
  2628. }
  2629. public boolean add(E e) { return c.add(typeCheck(e)); }
  2630. private E[] zeroLengthElementArray; // Lazily initialized
  2631. private E[] zeroLengthElementArray() {
  2632. return zeroLengthElementArray != null ? zeroLengthElementArray :
  2633. (zeroLengthElementArray = zeroLengthArray(type));
  2634. }
  2635. @SuppressWarnings("unchecked")
  2636. Collection<E> checkedCopyOf(Collection<? extends E> coll) {
  2637. Object[] a;
  2638. try {
  2639. E[] z = zeroLengthElementArray();
  2640. a = coll.toArray(z);
  2641. // Defend against coll violating the toArray contract
  2642. if (a.getClass() != z.getClass())
  2643. a = Arrays.copyOf(a, a.length, z.getClass());
  2644. } catch (ArrayStoreException ignore) {
  2645. // To get better and consistent diagnostics,
  2646. // we call typeCheck explicitly on each element.
  2647. // We call clone() to defend against coll retaining a
  2648. // reference to the returned array and storing a bad
  2649. // element into it after it has been type checked.
  2650. a = coll.toArray().clone();
  2651. for (Object o : a)
  2652. typeCheck(o);
  2653. }
  2654. // A slight abuse of the type system, but safe here.
  2655. return (Collection<E>) Arrays.asList(a);
  2656. }
  2657. public boolean addAll(Collection<? extends E> coll) {
  2658. // Doing things this way insulates us from concurrent changes
  2659. // in the contents of coll and provides all-or-nothing
  2660. // semantics (which we wouldn't get if we type-checked each
  2661. // element as we added it)
  2662. return c.addAll(checkedCopyOf(coll));
  2663. }
  2664. // Override default methods in Collection
  2665. @Override
  2666. public void forEach(Consumer<? super E> action) {c.forEach(action);}
  2667. @Override
  2668. public boolean removeIf(Predicate<? super E> filter) {
  2669. return c.removeIf(filter);
  2670. }
  2671. @Override
  2672. public Spliterator<E> spliterator() {return c.spliterator();}
  2673. @Override
  2674. public Stream<E> stream() {return c.stream();}
  2675. @Override
  2676. public Stream<E> parallelStream() {return c.parallelStream();}
  2677. }
  2678. /**
  2679. * Returns a dynamically typesafe view of the specified queue.
  2680. * Any attempt to insert an element of the wrong type will result in
  2681. * an immediate {@link ClassCastException}. Assuming a queue contains
  2682. * no incorrectly typed elements prior to the time a dynamically typesafe
  2683. * view is generated, and that all subsequent access to the queue
  2684. * takes place through the view, it is <i>guaranteed</i> that the
  2685. * queue cannot contain an incorrectly typed element.
  2686. *
  2687. * <p>A discussion of the use of dynamically typesafe views may be
  2688. * found in the documentation for the {@link #checkedCollection
  2689. * checkedCollection} method.
  2690. *
  2691. * <p>The returned queue will be serializable if the specified queue
  2692. * is serializable.
  2693. *
  2694. * <p>Since {@code null} is considered to be a value of any reference
  2695. * type, the returned queue permits insertion of {@code null} elements
  2696. * whenever the backing queue does.
  2697. *
  2698. * @param <E> the class of the objects in the queue
  2699. * @param queue the queue for which a dynamically typesafe view is to be
  2700. * returned
  2701. * @param type the type of element that {@code queue} is permitted to hold
  2702. * @return a dynamically typesafe view of the specified queue
  2703. * @since 1.8
  2704. */
  2705. public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
  2706. return new CheckedQueue<>(queue, type);
  2707. }
  2708. /**
  2709. * @serial include
  2710. */
  2711. static class CheckedQueue<E>
  2712. extends CheckedCollection<E>
  2713. implements Queue<E>, Serializable
  2714. {
  2715. private static final long serialVersionUID = 1433151992604707767L;
  2716. final Queue<E> queue;
  2717. CheckedQueue(Queue<E> queue, Class<E> elementType) {
  2718. super(queue, elementType);
  2719. this.queue = queue;
  2720. }
  2721. public E element() {return queue.element();}
  2722. public boolean equals(Object o) {return o == this || c.equals(o);}
  2723. public int hashCode() {return c.hashCode();}
  2724. public E peek() {return queue.peek();}
  2725. public E poll() {return queue.poll();}
  2726. public E remove() {return queue.remove();}
  2727. public boolean offer(E e) {return queue.offer(typeCheck(e));}
  2728. }
  2729. /**
  2730. * Returns a dynamically typesafe view of the specified set.
  2731. * Any attempt to insert an element of the wrong type will result in
  2732. * an immediate {@link ClassCastException}. Assuming a set contains
  2733. * no incorrectly typed elements prior to the time a dynamically typesafe
  2734. * view is generated, and that all subsequent access to the set
  2735. * takes place through the view, it is <i>guaranteed</i> that the
  2736. * set cannot contain an incorrectly typed element.
  2737. *
  2738. * <p>A discussion of the use of dynamically typesafe views may be
  2739. * found in the documentation for the {@link #checkedCollection
  2740. * checkedCollection} method.
  2741. *
  2742. * <p>The returned set will be serializable if the specified set is
  2743. * serializable.
  2744. *
  2745. * <p>Since {@code null} is considered to be a value of any reference
  2746. * type, the returned set permits insertion of null elements whenever
  2747. * the backing set does.
  2748. *
  2749. * @param <E> the class of the objects in the set
  2750. * @param s the set for which a dynamically typesafe view is to be
  2751. * returned
  2752. * @param type the type of element that {@code s} is permitted to hold
  2753. * @return a dynamically typesafe view of the specified set
  2754. * @since 1.5
  2755. */
  2756. public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
  2757. return new CheckedSet<>(s, type);
  2758. }
  2759. /**
  2760. * @serial include
  2761. */
  2762. static class CheckedSet<E> extends CheckedCollection<E>
  2763. implements Set<E>, Serializable
  2764. {
  2765. private static final long serialVersionUID = 4694047833775013803L;
  2766. CheckedSet(Set<E> s, Class<E> elementType) { super(s, elementType); }
  2767. public boolean equals(Object o) { return o == this || c.equals(o); }
  2768. public int hashCode() { return c.hashCode(); }
  2769. }
  2770. /**
  2771. * Returns a dynamically typesafe view of the specified sorted set.
  2772. * Any attempt to insert an element of the wrong type will result in an
  2773. * immediate {@link ClassCastException}. Assuming a sorted set
  2774. * contains no incorrectly typed elements prior to the time a
  2775. * dynamically typesafe view is generated, and that all subsequent
  2776. * access to the sorted set takes place through the view, it is
  2777. * <i>guaranteed</i> that the sorted set cannot contain an incorrectly
  2778. * typed element.
  2779. *
  2780. * <p>A discussion of the use of dynamically typesafe views may be
  2781. * found in the documentation for the {@link #checkedCollection
  2782. * checkedCollection} method.
  2783. *
  2784. * <p>The returned sorted set will be serializable if the specified sorted
  2785. * set is serializable.
  2786. *
  2787. * <p>Since {@code null} is considered to be a value of any reference
  2788. * type, the returned sorted set permits insertion of null elements
  2789. * whenever the backing sorted set does.
  2790. *
  2791. * @param <E> the class of the objects in the set
  2792. * @param s the sorted set for which a dynamically typesafe view is to be
  2793. * returned
  2794. * @param type the type of element that {@code s} is permitted to hold
  2795. * @return a dynamically typesafe view of the specified sorted set
  2796. * @since 1.5
  2797. */
  2798. public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
  2799. Class<E> type) {
  2800. return new CheckedSortedSet<>(s, type);
  2801. }
  2802. /**
  2803. * @serial include
  2804. */
  2805. static class CheckedSortedSet<E> extends CheckedSet<E>
  2806. implements SortedSet<E>, Serializable
  2807. {
  2808. private static final long serialVersionUID = 1599911165492914959L;
  2809. private final SortedSet<E> ss;
  2810. CheckedSortedSet(SortedSet<E> s, Class<E> type) {
  2811. super(s, type);
  2812. ss = s;
  2813. }
  2814. public Comparator<? super E> comparator() { return ss.comparator(); }
  2815. public E first() { return ss.first(); }
  2816. public E last() { return ss.last(); }
  2817. public SortedSet<E> subSet(E fromElement, E toElement) {
  2818. return checkedSortedSet(ss.subSet(fromElement,toElement), type);
  2819. }
  2820. public SortedSet<E> headSet(E toElement) {
  2821. return checkedSortedSet(ss.headSet(toElement), type);
  2822. }
  2823. public SortedSet<E> tailSet(E fromElement) {
  2824. return checkedSortedSet(ss.tailSet(fromElement), type);
  2825. }
  2826. }
  2827. /**
  2828. * Returns a dynamically typesafe view of the specified navigable set.
  2829. * Any attempt to insert an element of the wrong type will result in an
  2830. * immediate {@link ClassCastException}. Assuming a navigable set
  2831. * contains no incorrectly typed elements prior to the time a
  2832. * dynamically typesafe view is generated, and that all subsequent
  2833. * access to the navigable set takes place through the view, it is
  2834. * <em>guaranteed</em> that the navigable set cannot contain an incorrectly
  2835. * typed element.
  2836. *
  2837. * <p>A discussion of the use of dynamically typesafe views may be
  2838. * found in the documentation for the {@link #checkedCollection
  2839. * checkedCollection} method.
  2840. *
  2841. * <p>The returned navigable set will be serializable if the specified
  2842. * navigable set is serializable.
  2843. *
  2844. * <p>Since {@code null} is considered to be a value of any reference
  2845. * type, the returned navigable set permits insertion of null elements
  2846. * whenever the backing sorted set does.
  2847. *
  2848. * @param <E> the class of the objects in the set
  2849. * @param s the navigable set for which a dynamically typesafe view is to be
  2850. * returned
  2851. * @param type the type of element that {@code s} is permitted to hold
  2852. * @return a dynamically typesafe view of the specified navigable set
  2853. * @since 1.8
  2854. */
  2855. public static <E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s,
  2856. Class<E> type) {
  2857. return new CheckedNavigableSet<>(s, type);
  2858. }
  2859. /**
  2860. * @serial include
  2861. */
  2862. static class CheckedNavigableSet<E> extends CheckedSortedSet<E>
  2863. implements NavigableSet<E>, Serializable
  2864. {
  2865. private static final long serialVersionUID = -5429120189805438922L;
  2866. private final NavigableSet<E> ns;
  2867. CheckedNavigableSet(NavigableSet<E> s, Class<E> type) {
  2868. super(s, type);
  2869. ns = s;
  2870. }
  2871. public E lower(E e) { return ns.lower(e); }
  2872. public E floor(E e) { return ns.floor(e); }
  2873. public E ceiling(E e) { return ns.ceiling(e); }
  2874. public E higher(E e) { return ns.higher(e); }
  2875. public E pollFirst() { return ns.pollFirst(); }
  2876. public E pollLast() {return ns.pollLast(); }
  2877. public NavigableSet<E> descendingSet()
  2878. { return checkedNavigableSet(ns.descendingSet(), type); }
  2879. public Iterator<E> descendingIterator()
  2880. {return checkedNavigableSet(ns.descendingSet(), type).iterator(); }
  2881. public NavigableSet<E> subSet(E fromElement, E toElement) {
  2882. return checkedNavigableSet(ns.subSet(fromElement, true, toElement, false), type);
  2883. }
  2884. public NavigableSet<E> headSet(E toElement) {
  2885. return checkedNavigableSet(ns.headSet(toElement, false), type);
  2886. }
  2887. public NavigableSet<E> tailSet(E fromElement) {
  2888. return checkedNavigableSet(ns.tailSet(fromElement, true), type);
  2889. }
  2890. public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
  2891. return checkedNavigableSet(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), type);
  2892. }
  2893. public NavigableSet<E> headSet(E toElement, boolean inclusive) {
  2894. return checkedNavigableSet(ns.headSet(toElement, inclusive), type);
  2895. }
  2896. public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
  2897. return checkedNavigableSet(ns.tailSet(fromElement, inclusive), type);
  2898. }
  2899. }
  2900. /**
  2901. * Returns a dynamically typesafe view of the specified list.
  2902. * Any attempt to insert an element of the wrong type will result in
  2903. * an immediate {@link ClassCastException}. Assuming a list contains
  2904. * no incorrectly typed elements prior to the time a dynamically typesafe
  2905. * view is generated, and that all subsequent access to the list
  2906. * takes place through the view, it is <i>guaranteed</i> that the
  2907. * list cannot contain an incorrectly typed element.
  2908. *
  2909. * <p>A discussion of the use of dynamically typesafe views may be
  2910. * found in the documentation for the {@link #checkedCollection
  2911. * checkedCollection} method.
  2912. *
  2913. * <p>The returned list will be serializable if the specified list
  2914. * is serializable.
  2915. *
  2916. * <p>Since {@code null} is considered to be a value of any reference
  2917. * type, the returned list permits insertion of null elements whenever
  2918. * the backing list does.
  2919. *
  2920. * @param <E> the class of the objects in the list
  2921. * @param list the list for which a dynamically typesafe view is to be
  2922. * returned
  2923. * @param type the type of element that {@code list} is permitted to hold
  2924. * @return a dynamically typesafe view of the specified list
  2925. * @since 1.5
  2926. */
  2927. public static <E> List<E> checkedList(List<E> list, Class<E> type) {
  2928. return (list instanceof RandomAccess ?
  2929. new CheckedRandomAccessList<>(list, type) :
  2930. new CheckedList<>(list, type));
  2931. }
  2932. /**
  2933. * @serial include
  2934. */
  2935. static class CheckedList<E>
  2936. extends CheckedCollection<E>
  2937. implements List<E>
  2938. {
  2939. private static final long serialVersionUID = 65247728283967356L;
  2940. final List<E> list;
  2941. CheckedList(List<E> list, Class<E> type) {
  2942. super(list, type);
  2943. this.list = list;
  2944. }
  2945. public boolean equals(Object o) { return o == this || list.equals(o); }
  2946. public int hashCode() { return list.hashCode(); }
  2947. public E get(int index) { return list.get(index); }
  2948. public E remove(int index) { return list.remove(index); }
  2949. public int indexOf(Object o) { return list.indexOf(o); }
  2950. public int lastIndexOf(Object o) { return list.lastIndexOf(o); }
  2951. public E set(int index, E element) {
  2952. return list.set(index, typeCheck(element));
  2953. }
  2954. public void add(int index, E element) {
  2955. list.add(index, typeCheck(element));
  2956. }
  2957. public boolean addAll(int index, Collection<? extends E> c) {
  2958. return list.addAll(index, checkedCopyOf(c));
  2959. }
  2960. public ListIterator<E> listIterator() { return listIterator(0); }
  2961. public ListIterator<E> listIterator(final int index) {
  2962. final ListIterator<E> i = list.listIterator(index);
  2963. return new ListIterator<E>() {
  2964. public boolean hasNext() { return i.hasNext(); }
  2965. public E next() { return i.next(); }
  2966. public boolean hasPrevious() { return i.hasPrevious(); }
  2967. public E previous() { return i.previous(); }
  2968. public int nextIndex() { return i.nextIndex(); }
  2969. public int previousIndex() { return i.previousIndex(); }
  2970. public void remove() { i.remove(); }
  2971. public void set(E e) {
  2972. i.set(typeCheck(e));
  2973. }
  2974. public void add(E e) {
  2975. i.add(typeCheck(e));
  2976. }
  2977. @Override
  2978. public void forEachRemaining(Consumer<? super E> action) {
  2979. i.forEachRemaining(action);
  2980. }
  2981. };
  2982. }
  2983. public List<E> subList(int fromIndex, int toIndex) {
  2984. return new CheckedList<>(list.subList(fromIndex, toIndex), type);
  2985. }
  2986. /**
  2987. * {@inheritDoc}
  2988. *
  2989. * @throws ClassCastException if the class of an element returned by the
  2990. * operator prevents it from being added to this collection. The
  2991. * exception may be thrown after some elements of the list have
  2992. * already been replaced.
  2993. */
  2994. @Override
  2995. public void replaceAll(UnaryOperator<E> operator) {
  2996. Objects.requireNonNull(operator);
  2997. list.replaceAll(e -> typeCheck(operator.apply(e)));
  2998. }
  2999. @Override
  3000. public void sort(Comparator<? super E> c) {
  3001. list.sort(c);
  3002. }
  3003. }
  3004. /**
  3005. * @serial include
  3006. */
  3007. static class CheckedRandomAccessList<E> extends CheckedList<E>
  3008. implements RandomAccess
  3009. {
  3010. private static final long serialVersionUID = 1638200125423088369L;
  3011. CheckedRandomAccessList(List<E> list, Class<E> type) {
  3012. super(list, type);
  3013. }
  3014. public List<E> subList(int fromIndex, int toIndex) {
  3015. return new CheckedRandomAccessList<>(
  3016. list.subList(fromIndex, toIndex), type);
  3017. }
  3018. }
  3019. /**
  3020. * Returns a dynamically typesafe view of the specified map.
  3021. * Any attempt to insert a mapping whose key or value have the wrong
  3022. * type will result in an immediate {@link ClassCastException}.
  3023. * Similarly, any attempt to modify the value currently associated with
  3024. * a key will result in an immediate {@link ClassCastException},
  3025. * whether the modification is attempted directly through the map
  3026. * itself, or through a {@link Map.Entry} instance obtained from the
  3027. * map's {@link Map#entrySet() entry set} view.
  3028. *
  3029. * <p>Assuming a map contains no incorrectly typed keys or values
  3030. * prior to the time a dynamically typesafe view is generated, and
  3031. * that all subsequent access to the map takes place through the view
  3032. * (or one of its collection views), it is <i>guaranteed</i> that the
  3033. * map cannot contain an incorrectly typed key or value.
  3034. *
  3035. * <p>A discussion of the use of dynamically typesafe views may be
  3036. * found in the documentation for the {@link #checkedCollection
  3037. * checkedCollection} method.
  3038. *
  3039. * <p>The returned map will be serializable if the specified map is
  3040. * serializable.
  3041. *
  3042. * <p>Since {@code null} is considered to be a value of any reference
  3043. * type, the returned map permits insertion of null keys or values
  3044. * whenever the backing map does.
  3045. *
  3046. * @param <K> the class of the map keys
  3047. * @param <V> the class of the map values
  3048. * @param m the map for which a dynamically typesafe view is to be
  3049. * returned
  3050. * @param keyType the type of key that {@code m} is permitted to hold
  3051. * @param valueType the type of value that {@code m} is permitted to hold
  3052. * @return a dynamically typesafe view of the specified map
  3053. * @since 1.5
  3054. */
  3055. public static <K, V> Map<K, V> checkedMap(Map<K, V> m,
  3056. Class<K> keyType,
  3057. Class<V> valueType) {
  3058. return new CheckedMap<>(m, keyType, valueType);
  3059. }
  3060. /**
  3061. * @serial include
  3062. */
  3063. private static class CheckedMap<K,V>
  3064. implements Map<K,V>, Serializable
  3065. {
  3066. private static final long serialVersionUID = 5742860141034234728L;
  3067. private final Map<K, V> m;
  3068. final Class<K> keyType;
  3069. final Class<V> valueType;
  3070. private void typeCheck(Object key, Object value) {
  3071. if (key != null && !keyType.isInstance(key))
  3072. throw new ClassCastException(badKeyMsg(key));
  3073. if (value != null && !valueType.isInstance(value))
  3074. throw new ClassCastException(badValueMsg(value));
  3075. }
  3076. private BiFunction<? super K, ? super V, ? extends V> typeCheck(
  3077. BiFunction<? super K, ? super V, ? extends V> func) {
  3078. Objects.requireNonNull(func);
  3079. return (k, v) -> {
  3080. V newValue = func.apply(k, v);
  3081. typeCheck(k, newValue);
  3082. return newValue;
  3083. };
  3084. }
  3085. private String badKeyMsg(Object key) {
  3086. return "Attempt to insert " + key.getClass() +
  3087. " key into map with key type " + keyType;
  3088. }
  3089. private String badValueMsg(Object value) {
  3090. return "Attempt to insert " + value.getClass() +
  3091. " value into map with value type " + valueType;
  3092. }
  3093. CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
  3094. this.m = Objects.requireNonNull(m);
  3095. this.keyType = Objects.requireNonNull(keyType);
  3096. this.valueType = Objects.requireNonNull(valueType);
  3097. }
  3098. public int size() { return m.size(); }
  3099. public boolean isEmpty() { return m.isEmpty(); }
  3100. public boolean containsKey(Object key) { return m.containsKey(key); }
  3101. public boolean containsValue(Object v) { return m.containsValue(v); }
  3102. public V get(Object key) { return m.get(key); }
  3103. public V remove(Object key) { return m.remove(key); }
  3104. public void clear() { m.clear(); }
  3105. public Set<K> keySet() { return m.keySet(); }
  3106. public Collection<V> values() { return m.values(); }
  3107. public boolean equals(Object o) { return o == this || m.equals(o); }
  3108. public int hashCode() { return m.hashCode(); }
  3109. public String toString() { return m.toString(); }
  3110. public V put(K key, V value) {
  3111. typeCheck(key, value);
  3112. return m.put(key, value);
  3113. }
  3114. @SuppressWarnings("unchecked")
  3115. public void putAll(Map<? extends K, ? extends V> t) {
  3116. // Satisfy the following goals:
  3117. // - good diagnostics in case of type mismatch
  3118. // - all-or-nothing semantics
  3119. // - protection from malicious t
  3120. // - correct behavior if t is a concurrent map
  3121. Object[] entries = t.entrySet().toArray();
  3122. List<Map.Entry<K,V>> checked = new ArrayList<>(entries.length);
  3123. for (Object o : entries) {
  3124. Map.Entry<?,?> e = (Map.Entry<?,?>) o;
  3125. Object k = e.getKey();
  3126. Object v = e.getValue();
  3127. typeCheck(k, v);
  3128. checked.add(
  3129. new AbstractMap.SimpleImmutableEntry<>((K)k, (V)v));
  3130. }
  3131. for (Map.Entry<K,V> e : checked)
  3132. m.put(e.getKey(), e.getValue());
  3133. }
  3134. private transient Set<Map.Entry<K,V>> entrySet;
  3135. public Set<Map.Entry<K,V>> entrySet() {
  3136. if (entrySet==null)
  3137. entrySet = new CheckedEntrySet<>(m.entrySet(), valueType);
  3138. return entrySet;
  3139. }
  3140. // Override default methods in Map
  3141. @Override
  3142. public void forEach(BiConsumer<? super K, ? super V> action) {
  3143. m.forEach(action);
  3144. }
  3145. @Override
  3146. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  3147. m.replaceAll(typeCheck(function));
  3148. }
  3149. @Override
  3150. public V putIfAbsent(K key, V value) {
  3151. typeCheck(key, value);
  3152. return m.putIfAbsent(key, value);
  3153. }
  3154. @Override
  3155. public boolean remove(Object key, Object value) {
  3156. return m.remove(key, value);
  3157. }
  3158. @Override
  3159. public boolean replace(K key, V oldValue, V newValue) {
  3160. typeCheck(key, newValue);
  3161. return m.replace(key, oldValue, newValue);
  3162. }
  3163. @Override
  3164. public V replace(K key, V value) {
  3165. typeCheck(key, value);
  3166. return m.replace(key, value);
  3167. }
  3168. @Override
  3169. public V computeIfAbsent(K key,
  3170. Function<? super K, ? extends V> mappingFunction) {
  3171. Objects.requireNonNull(mappingFunction);
  3172. return m.computeIfAbsent(key, k -> {
  3173. V value = mappingFunction.apply(k);
  3174. typeCheck(k, value);
  3175. return value;
  3176. });
  3177. }
  3178. @Override
  3179. public V computeIfPresent(K key,
  3180. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  3181. return m.computeIfPresent(key, typeCheck(remappingFunction));
  3182. }
  3183. @Override
  3184. public V compute(K key,
  3185. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  3186. return m.compute(key, typeCheck(remappingFunction));
  3187. }
  3188. @Override
  3189. public V merge(K key, V value,
  3190. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  3191. Objects.requireNonNull(remappingFunction);
  3192. return m.merge(key, value, (v1, v2) -> {
  3193. V newValue = remappingFunction.apply(v1, v2);
  3194. typeCheck(null, newValue);
  3195. return newValue;
  3196. });
  3197. }
  3198. /**
  3199. * We need this class in addition to CheckedSet as Map.Entry permits
  3200. * modification of the backing Map via the setValue operation. This
  3201. * class is subtle: there are many possible attacks that must be
  3202. * thwarted.
  3203. *
  3204. * @serial exclude
  3205. */
  3206. static class CheckedEntrySet<K,V> implements Set<Map.Entry<K,V>> {
  3207. private final Set<Map.Entry<K,V>> s;
  3208. private final Class<V> valueType;
  3209. CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
  3210. this.s = s;
  3211. this.valueType = valueType;
  3212. }
  3213. public int size() { return s.size(); }
  3214. public boolean isEmpty() { return s.isEmpty(); }
  3215. public String toString() { return s.toString(); }
  3216. public int hashCode() { return s.hashCode(); }
  3217. public void clear() { s.clear(); }
  3218. public boolean add(Map.Entry<K, V> e) {
  3219. throw new UnsupportedOperationException();
  3220. }
  3221. public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
  3222. throw new UnsupportedOperationException();
  3223. }
  3224. public Iterator<Map.Entry<K,V>> iterator() {
  3225. final Iterator<Map.Entry<K, V>> i = s.iterator();
  3226. final Class<V> valueType = this.valueType;
  3227. return new Iterator<Map.Entry<K,V>>() {
  3228. public boolean hasNext() { return i.hasNext(); }
  3229. public void remove() { i.remove(); }
  3230. public Map.Entry<K,V> next() {
  3231. return checkedEntry(i.next(), valueType);
  3232. }
  3233. };
  3234. }
  3235. @SuppressWarnings("unchecked")
  3236. public Object[] toArray() {
  3237. Object[] source = s.toArray();
  3238. /*
  3239. * Ensure that we don't get an ArrayStoreException even if
  3240. * s.toArray returns an array of something other than Object
  3241. */
  3242. Object[] dest = (CheckedEntry.class.isInstance(
  3243. source.getClass().getComponentType()) ? source :
  3244. new Object[source.length]);
  3245. for (int i = 0; i < source.length; i++)
  3246. dest[i] = checkedEntry((Map.Entry<K,V>)source[i],
  3247. valueType);
  3248. return dest;
  3249. }
  3250. @SuppressWarnings("unchecked")
  3251. public <T> T[] toArray(T[] a) {
  3252. // We don't pass a to s.toArray, to avoid window of
  3253. // vulnerability wherein an unscrupulous multithreaded client
  3254. // could get his hands on raw (unwrapped) Entries from s.
  3255. T[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
  3256. for (int i=0; i<arr.length; i++)
  3257. arr[i] = (T) checkedEntry((Map.Entry<K,V>)arr[i],
  3258. valueType);
  3259. if (arr.length > a.length)
  3260. return arr;
  3261. System.arraycopy(arr, 0, a, 0, arr.length);
  3262. if (a.length > arr.length)
  3263. a[arr.length] = null;
  3264. return a;
  3265. }
  3266. /**
  3267. * This method is overridden to protect the backing set against
  3268. * an object with a nefarious equals function that senses
  3269. * that the equality-candidate is Map.Entry and calls its
  3270. * setValue method.
  3271. */
  3272. public boolean contains(Object o) {
  3273. if (!(o instanceof Map.Entry))
  3274. return false;
  3275. Map.Entry<?,?> e = (Map.Entry<?,?>) o;
  3276. return s.contains(
  3277. (e instanceof CheckedEntry) ? e : checkedEntry(e, valueType));
  3278. }
  3279. /**
  3280. * The bulk collection methods are overridden to protect
  3281. * against an unscrupulous collection whose contains(Object o)
  3282. * method senses when o is a Map.Entry, and calls o.setValue.
  3283. */
  3284. public boolean containsAll(Collection<?> c) {
  3285. for (Object o : c)
  3286. if (!contains(o)) // Invokes safe contains() above
  3287. return false;
  3288. return true;
  3289. }
  3290. public boolean remove(Object o) {
  3291. if (!(o instanceof Map.Entry))
  3292. return false;
  3293. return s.remove(new AbstractMap.SimpleImmutableEntry
  3294. <>((Map.Entry<?,?>)o));
  3295. }
  3296. public boolean removeAll(Collection<?> c) {
  3297. return batchRemove(c, false);
  3298. }
  3299. public boolean retainAll(Collection<?> c) {
  3300. return batchRemove(c, true);
  3301. }
  3302. private boolean batchRemove(Collection<?> c, boolean complement) {
  3303. Objects.requireNonNull(c);
  3304. boolean modified = false;
  3305. Iterator<Map.Entry<K,V>> it = iterator();
  3306. while (it.hasNext()) {
  3307. if (c.contains(it.next()) != complement) {
  3308. it.remove();
  3309. modified = true;
  3310. }
  3311. }
  3312. return modified;
  3313. }
  3314. public boolean equals(Object o) {
  3315. if (o == this)
  3316. return true;
  3317. if (!(o instanceof Set))
  3318. return false;
  3319. Set<?> that = (Set<?>) o;
  3320. return that.size() == s.size()
  3321. && containsAll(that); // Invokes safe containsAll() above
  3322. }
  3323. static <K,V,T> CheckedEntry<K,V,T> checkedEntry(Map.Entry<K,V> e,
  3324. Class<T> valueType) {
  3325. return new CheckedEntry<>(e, valueType);
  3326. }
  3327. /**
  3328. * This "wrapper class" serves two purposes: it prevents
  3329. * the client from modifying the backing Map, by short-circuiting
  3330. * the setValue method, and it protects the backing Map against
  3331. * an ill-behaved Map.Entry that attempts to modify another
  3332. * Map.Entry when asked to perform an equality check.
  3333. */
  3334. private static class CheckedEntry<K,V,T> implements Map.Entry<K,V> {
  3335. private final Map.Entry<K, V> e;
  3336. private final Class<T> valueType;
  3337. CheckedEntry(Map.Entry<K, V> e, Class<T> valueType) {
  3338. this.e = Objects.requireNonNull(e);
  3339. this.valueType = Objects.requireNonNull(valueType);
  3340. }
  3341. public K getKey() { return e.getKey(); }
  3342. public V getValue() { return e.getValue(); }
  3343. public int hashCode() { return e.hashCode(); }
  3344. public String toString() { return e.toString(); }
  3345. public V setValue(V value) {
  3346. if (value != null && !valueType.isInstance(value))
  3347. throw new ClassCastException(badValueMsg(value));
  3348. return e.setValue(value);
  3349. }
  3350. private String badValueMsg(Object value) {
  3351. return "Attempt to insert " + value.getClass() +
  3352. " value into map with value type " + valueType;
  3353. }
  3354. public boolean equals(Object o) {
  3355. if (o == this)
  3356. return true;
  3357. if (!(o instanceof Map.Entry))
  3358. return false;
  3359. return e.equals(new AbstractMap.SimpleImmutableEntry
  3360. <>((Map.Entry<?,?>)o));
  3361. }
  3362. }
  3363. }
  3364. }
  3365. /**
  3366. * Returns a dynamically typesafe view of the specified sorted map.
  3367. * Any attempt to insert a mapping whose key or value have the wrong
  3368. * type will result in an immediate {@link ClassCastException}.
  3369. * Similarly, any attempt to modify the value currently associated with
  3370. * a key will result in an immediate {@link ClassCastException},
  3371. * whether the modification is attempted directly through the map
  3372. * itself, or through a {@link Map.Entry} instance obtained from the
  3373. * map's {@link Map#entrySet() entry set} view.
  3374. *
  3375. * <p>Assuming a map contains no incorrectly typed keys or values
  3376. * prior to the time a dynamically typesafe view is generated, and
  3377. * that all subsequent access to the map takes place through the view
  3378. * (or one of its collection views), it is <i>guaranteed</i> that the
  3379. * map cannot contain an incorrectly typed key or value.
  3380. *
  3381. * <p>A discussion of the use of dynamically typesafe views may be
  3382. * found in the documentation for the {@link #checkedCollection
  3383. * checkedCollection} method.
  3384. *
  3385. * <p>The returned map will be serializable if the specified map is
  3386. * serializable.
  3387. *
  3388. * <p>Since {@code null} is considered to be a value of any reference
  3389. * type, the returned map permits insertion of null keys or values
  3390. * whenever the backing map does.
  3391. *
  3392. * @param <K> the class of the map keys
  3393. * @param <V> the class of the map values
  3394. * @param m the map for which a dynamically typesafe view is to be
  3395. * returned
  3396. * @param keyType the type of key that {@code m} is permitted to hold
  3397. * @param valueType the type of value that {@code m} is permitted to hold
  3398. * @return a dynamically typesafe view of the specified map
  3399. * @since 1.5
  3400. */
  3401. public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K, V> m,
  3402. Class<K> keyType,
  3403. Class<V> valueType) {
  3404. return new CheckedSortedMap<>(m, keyType, valueType);
  3405. }
  3406. /**
  3407. * @serial include
  3408. */
  3409. static class CheckedSortedMap<K,V> extends CheckedMap<K,V>
  3410. implements SortedMap<K,V>, Serializable
  3411. {
  3412. private static final long serialVersionUID = 1599671320688067438L;
  3413. private final SortedMap<K, V> sm;
  3414. CheckedSortedMap(SortedMap<K, V> m,
  3415. Class<K> keyType, Class<V> valueType) {
  3416. super(m, keyType, valueType);
  3417. sm = m;
  3418. }
  3419. public Comparator<? super K> comparator() { return sm.comparator(); }
  3420. public K firstKey() { return sm.firstKey(); }
  3421. public K lastKey() { return sm.lastKey(); }
  3422. public SortedMap<K,V> subMap(K fromKey, K toKey) {
  3423. return checkedSortedMap(sm.subMap(fromKey, toKey),
  3424. keyType, valueType);
  3425. }
  3426. public SortedMap<K,V> headMap(K toKey) {
  3427. return checkedSortedMap(sm.headMap(toKey), keyType, valueType);
  3428. }
  3429. public SortedMap<K,V> tailMap(K fromKey) {
  3430. return checkedSortedMap(sm.tailMap(fromKey), keyType, valueType);
  3431. }
  3432. }
  3433. /**
  3434. * Returns a dynamically typesafe view of the specified navigable map.
  3435. * Any attempt to insert a mapping whose key or value have the wrong
  3436. * type will result in an immediate {@link ClassCastException}.
  3437. * Similarly, any attempt to modify the value currently associated with
  3438. * a key will result in an immediate {@link ClassCastException},
  3439. * whether the modification is attempted directly through the map
  3440. * itself, or through a {@link Map.Entry} instance obtained from the
  3441. * map's {@link Map#entrySet() entry set} view.
  3442. *
  3443. * <p>Assuming a map contains no incorrectly typed keys or values
  3444. * prior to the time a dynamically typesafe view is generated, and
  3445. * that all subsequent access to the map takes place through the view
  3446. * (or one of its collection views), it is <em>guaranteed</em> that the
  3447. * map cannot contain an incorrectly typed key or value.
  3448. *
  3449. * <p>A discussion of the use of dynamically typesafe views may be
  3450. * found in the documentation for the {@link #checkedCollection
  3451. * checkedCollection} method.
  3452. *
  3453. * <p>The returned map will be serializable if the specified map is
  3454. * serializable.
  3455. *
  3456. * <p>Since {@code null} is considered to be a value of any reference
  3457. * type, the returned map permits insertion of null keys or values
  3458. * whenever the backing map does.
  3459. *
  3460. * @param <K> type of map keys
  3461. * @param <V> type of map values
  3462. * @param m the map for which a dynamically typesafe view is to be
  3463. * returned
  3464. * @param keyType the type of key that {@code m} is permitted to hold
  3465. * @param valueType the type of value that {@code m} is permitted to hold
  3466. * @return a dynamically typesafe view of the specified map
  3467. * @since 1.8
  3468. */
  3469. public static <K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m,
  3470. Class<K> keyType,
  3471. Class<V> valueType) {
  3472. return new CheckedNavigableMap<>(m, keyType, valueType);
  3473. }
  3474. /**
  3475. * @serial include
  3476. */
  3477. static class CheckedNavigableMap<K,V> extends CheckedSortedMap<K,V>
  3478. implements NavigableMap<K,V>, Serializable
  3479. {
  3480. private static final long serialVersionUID = -4852462692372534096L;
  3481. private final NavigableMap<K, V> nm;
  3482. CheckedNavigableMap(NavigableMap<K, V> m,
  3483. Class<K> keyType, Class<V> valueType) {
  3484. super(m, keyType, valueType);
  3485. nm = m;
  3486. }
  3487. public Comparator<? super K> comparator() { return nm.comparator(); }
  3488. public K firstKey() { return nm.firstKey(); }
  3489. public K lastKey() { return nm.lastKey(); }
  3490. public Entry<K, V> lowerEntry(K key) {
  3491. Entry<K,V> lower = nm.lowerEntry(key);
  3492. return (null != lower)
  3493. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(lower, valueType)
  3494. : null;
  3495. }
  3496. public K lowerKey(K key) { return nm.lowerKey(key); }
  3497. public Entry<K, V> floorEntry(K key) {
  3498. Entry<K,V> floor = nm.floorEntry(key);
  3499. return (null != floor)
  3500. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(floor, valueType)
  3501. : null;
  3502. }
  3503. public K floorKey(K key) { return nm.floorKey(key); }
  3504. public Entry<K, V> ceilingEntry(K key) {
  3505. Entry<K,V> ceiling = nm.ceilingEntry(key);
  3506. return (null != ceiling)
  3507. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(ceiling, valueType)
  3508. : null;
  3509. }
  3510. public K ceilingKey(K key) { return nm.ceilingKey(key); }
  3511. public Entry<K, V> higherEntry(K key) {
  3512. Entry<K,V> higher = nm.higherEntry(key);
  3513. return (null != higher)
  3514. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(higher, valueType)
  3515. : null;
  3516. }
  3517. public K higherKey(K key) { return nm.higherKey(key); }
  3518. public Entry<K, V> firstEntry() {
  3519. Entry<K,V> first = nm.firstEntry();
  3520. return (null != first)
  3521. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(first, valueType)
  3522. : null;
  3523. }
  3524. public Entry<K, V> lastEntry() {
  3525. Entry<K,V> last = nm.lastEntry();
  3526. return (null != last)
  3527. ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(last, valueType)
  3528. : null;
  3529. }
  3530. public Entry<K, V> pollFirstEntry() {
  3531. Entry<K,V> entry = nm.pollFirstEntry();
  3532. return (null == entry)
  3533. ? null
  3534. : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
  3535. }
  3536. public Entry<K, V> pollLastEntry() {
  3537. Entry<K,V> entry = nm.pollLastEntry();
  3538. return (null == entry)
  3539. ? null
  3540. : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
  3541. }
  3542. public NavigableMap<K, V> descendingMap() {
  3543. return checkedNavigableMap(nm.descendingMap(), keyType, valueType);
  3544. }
  3545. public NavigableSet<K> keySet() {
  3546. return navigableKeySet();
  3547. }
  3548. public NavigableSet<K> navigableKeySet() {
  3549. return checkedNavigableSet(nm.navigableKeySet(), keyType);
  3550. }
  3551. public NavigableSet<K> descendingKeySet() {
  3552. return checkedNavigableSet(nm.descendingKeySet(), keyType);
  3553. }
  3554. @Override
  3555. public NavigableMap<K,V> subMap(K fromKey, K toKey) {
  3556. return checkedNavigableMap(nm.subMap(fromKey, true, toKey, false),
  3557. keyType, valueType);
  3558. }
  3559. @Override
  3560. public NavigableMap<K,V> headMap(K toKey) {
  3561. return checkedNavigableMap(nm.headMap(toKey, false), keyType, valueType);
  3562. }
  3563. @Override
  3564. public NavigableMap<K,V> tailMap(K fromKey) {
  3565. return checkedNavigableMap(nm.tailMap(fromKey, true), keyType, valueType);
  3566. }
  3567. public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
  3568. return checkedNavigableMap(nm.subMap(fromKey, fromInclusive, toKey, toInclusive), keyType, valueType);
  3569. }
  3570. public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
  3571. return checkedNavigableMap(nm.headMap(toKey, inclusive), keyType, valueType);
  3572. }
  3573. public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
  3574. return checkedNavigableMap(nm.tailMap(fromKey, inclusive), keyType, valueType);
  3575. }
  3576. }
  3577. // Empty collections
  3578. /**
  3579. * Returns an iterator that has no elements. More precisely,
  3580. *
  3581. * <ul>
  3582. * <li>{@link Iterator#hasNext hasNext} always returns {@code
  3583. * false}.</li>
  3584. * <li>{@link Iterator#next next} always throws {@link
  3585. * NoSuchElementException}.</li>
  3586. * <li>{@link Iterator#remove remove} always throws {@link
  3587. * IllegalStateException}.</li>
  3588. * </ul>
  3589. *
  3590. * <p>Implementations of this method are permitted, but not
  3591. * required, to return the same object from multiple invocations.
  3592. *
  3593. * @param <T> type of elements, if there were any, in the iterator
  3594. * @return an empty iterator
  3595. * @since 1.7
  3596. */
  3597. @SuppressWarnings("unchecked")
  3598. public static <T> Iterator<T> emptyIterator() {
  3599. return (Iterator<T>) EmptyIterator.EMPTY_ITERATOR;
  3600. }
  3601. private static class EmptyIterator<E> implements Iterator<E> {
  3602. static final EmptyIterator<Object> EMPTY_ITERATOR
  3603. = new EmptyIterator<>();
  3604. public boolean hasNext() { return false; }
  3605. public E next() { throw new NoSuchElementException(); }
  3606. public void remove() { throw new IllegalStateException(); }
  3607. @Override
  3608. public void forEachRemaining(Consumer<? super E> action) {
  3609. Objects.requireNonNull(action);
  3610. }
  3611. }
  3612. /**
  3613. * Returns a list iterator that has no elements. More precisely,
  3614. *
  3615. * <ul>
  3616. * <li>{@link Iterator#hasNext hasNext} and {@link
  3617. * ListIterator#hasPrevious hasPrevious} always return {@code
  3618. * false}.</li>
  3619. * <li>{@link Iterator#next next} and {@link ListIterator#previous
  3620. * previous} always throw {@link NoSuchElementException}.</li>
  3621. * <li>{@link Iterator#remove remove} and {@link ListIterator#set
  3622. * set} always throw {@link IllegalStateException}.</li>
  3623. * <li>{@link ListIterator#add add} always throws {@link
  3624. * UnsupportedOperationException}.</li>
  3625. * <li>{@link ListIterator#nextIndex nextIndex} always returns
  3626. * {@code 0}.</li>
  3627. * <li>{@link ListIterator#previousIndex previousIndex} always
  3628. * returns {@code -1}.</li>
  3629. * </ul>
  3630. *
  3631. * <p>Implementations of this method are permitted, but not
  3632. * required, to return the same object from multiple invocations.
  3633. *
  3634. * @param <T> type of elements, if there were any, in the iterator
  3635. * @return an empty list iterator
  3636. * @since 1.7
  3637. */
  3638. @SuppressWarnings("unchecked")
  3639. public static <T> ListIterator<T> emptyListIterator() {
  3640. return (ListIterator<T>) EmptyListIterator.EMPTY_ITERATOR;
  3641. }
  3642. private static class EmptyListIterator<E>
  3643. extends EmptyIterator<E>
  3644. implements ListIterator<E>
  3645. {
  3646. static final EmptyListIterator<Object> EMPTY_ITERATOR
  3647. = new EmptyListIterator<>();
  3648. public boolean hasPrevious() { return false; }
  3649. public E previous() { throw new NoSuchElementException(); }
  3650. public int nextIndex() { return 0; }
  3651. public int previousIndex() { return -1; }
  3652. public void set(E e) { throw new IllegalStateException(); }
  3653. public void add(E e) { throw new UnsupportedOperationException(); }
  3654. }
  3655. /**
  3656. * Returns an enumeration that has no elements. More precisely,
  3657. *
  3658. * <ul>
  3659. * <li>{@link Enumeration#hasMoreElements hasMoreElements} always
  3660. * returns {@code false}.</li>
  3661. * <li> {@link Enumeration#nextElement nextElement} always throws
  3662. * {@link NoSuchElementException}.</li>
  3663. * </ul>
  3664. *
  3665. * <p>Implementations of this method are permitted, but not
  3666. * required, to return the same object from multiple invocations.
  3667. *
  3668. * @param <T> the class of the objects in the enumeration
  3669. * @return an empty enumeration
  3670. * @since 1.7
  3671. */
  3672. @SuppressWarnings("unchecked")
  3673. public static <T> Enumeration<T> emptyEnumeration() {
  3674. return (Enumeration<T>) EmptyEnumeration.EMPTY_ENUMERATION;
  3675. }
  3676. private static class EmptyEnumeration<E> implements Enumeration<E> {
  3677. static final EmptyEnumeration<Object> EMPTY_ENUMERATION
  3678. = new EmptyEnumeration<>();
  3679. public boolean hasMoreElements() { return false; }
  3680. public E nextElement() { throw new NoSuchElementException(); }
  3681. }
  3682. /**
  3683. * The empty set (immutable). This set is serializable.
  3684. *
  3685. * @see #emptySet()
  3686. */
  3687. @SuppressWarnings("rawtypes")
  3688. public static final Set EMPTY_SET = new EmptySet<>();
  3689. /**
  3690. * Returns an empty set (immutable). This set is serializable.
  3691. * Unlike the like-named field, this method is parameterized.
  3692. *
  3693. * <p>This example illustrates the type-safe way to obtain an empty set:
  3694. *
  3695. <pre>
  3696. * Set&lt;String&gt; s = Collections.emptySet();
  3697. * </pre>
  3698. * @implNote Implementations of this method need not create a separate
  3699. * {@code Set} object for each call. Using this method is likely to have
  3700. * comparable cost to using the like-named field. (Unlike this method, the
  3701. * field does not provide type safety.)
  3702. *
  3703. * @param <T> the class of the objects in the set
  3704. * @return the empty set
  3705. *
  3706. * @see #EMPTY_SET
  3707. * @since 1.5
  3708. */
  3709. @SuppressWarnings("unchecked")
  3710. public static final <T> Set<T> emptySet() {
  3711. return (Set<T>) EMPTY_SET;
  3712. }
  3713. /**
  3714. * @serial include
  3715. */
  3716. private static class EmptySet<E>
  3717. extends AbstractSet<E>
  3718. implements Serializable
  3719. {
  3720. private static final long serialVersionUID = 1582296315990362920L;
  3721. public Iterator<E> iterator() { return emptyIterator(); }
  3722. public int size() {return 0;}
  3723. public boolean isEmpty() {return true;}
  3724. public boolean contains(Object obj) {return false;}
  3725. public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
  3726. public Object[] toArray() { return new Object[0]; }
  3727. public <T> T[] toArray(T[] a) {
  3728. if (a.length > 0)
  3729. a[0] = null;
  3730. return a;
  3731. }
  3732. // Override default methods in Collection
  3733. @Override
  3734. public void forEach(Consumer<? super E> action) {
  3735. Objects.requireNonNull(action);
  3736. }
  3737. @Override
  3738. public boolean removeIf(Predicate<? super E> filter) {
  3739. Objects.requireNonNull(filter);
  3740. return false;
  3741. }
  3742. @Override
  3743. public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
  3744. // Preserves singleton property
  3745. private Object readResolve() {
  3746. return EMPTY_SET;
  3747. }
  3748. }
  3749. /**
  3750. * Returns an empty sorted set (immutable). This set is serializable.
  3751. *
  3752. * <p>This example illustrates the type-safe way to obtain an empty
  3753. * sorted set:
  3754. *
  3755. <pre> {@code
  3756. * SortedSet<String> s = Collections.emptySortedSet();
  3757. * }</pre>
  3758. *
  3759. * @implNote Implementations of this method need not create a separate
  3760. * {@code SortedSet} object for each call.
  3761. *
  3762. * @param <E> type of elements, if there were any, in the set
  3763. * @return the empty sorted set
  3764. * @since 1.8
  3765. */
  3766. @SuppressWarnings("unchecked")
  3767. public static <E> SortedSet<E> emptySortedSet() {
  3768. return (SortedSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
  3769. }
  3770. /**
  3771. * Returns an empty navigable set (immutable). This set is serializable.
  3772. *
  3773. * <p>This example illustrates the type-safe way to obtain an empty
  3774. * navigable set:
  3775. *
  3776. <pre> {@code
  3777. * NavigableSet<String> s = Collections.emptyNavigableSet();
  3778. * }</pre>
  3779. *
  3780. * @implNote Implementations of this method need not
  3781. * create a separate {@code NavigableSet} object for each call.
  3782. *
  3783. * @param <E> type of elements, if there were any, in the set
  3784. * @return the empty navigable set
  3785. * @since 1.8
  3786. */
  3787. @SuppressWarnings("unchecked")
  3788. public static <E> NavigableSet<E> emptyNavigableSet() {
  3789. return (NavigableSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
  3790. }
  3791. /**
  3792. * The empty list (immutable). This list is serializable.
  3793. *
  3794. * @see #emptyList()
  3795. */
  3796. @SuppressWarnings("rawtypes")
  3797. public static final List EMPTY_LIST = new EmptyList<>();
  3798. /**
  3799. * Returns an empty list (immutable). This list is serializable.
  3800. *
  3801. * <p>This example illustrates the type-safe way to obtain an empty list:
  3802. *
  3803. <pre>
  3804. * List&lt;String&gt; s = Collections.emptyList();
  3805. * </pre>
  3806. *
  3807. * @implNote
  3808. * Implementations of this method need not create a separate <tt>List</tt>
  3809. * object for each call. Using this method is likely to have comparable
  3810. * cost to using the like-named field. (Unlike this method, the field does
  3811. * not provide type safety.)
  3812. *
  3813. * @param <T> type of elements, if there were any, in the list
  3814. * @return an empty immutable list
  3815. *
  3816. * @see #EMPTY_LIST
  3817. * @since 1.5
  3818. */
  3819. @SuppressWarnings("unchecked")
  3820. public static final <T> List<T> emptyList() {
  3821. return (List<T>) EMPTY_LIST;
  3822. }
  3823. /**
  3824. * @serial include
  3825. */
  3826. private static class EmptyList<E>
  3827. extends AbstractList<E>
  3828. implements RandomAccess, Serializable {
  3829. private static final long serialVersionUID = 8842843931221139166L;
  3830. public Iterator<E> iterator() {
  3831. return emptyIterator();
  3832. }
  3833. public ListIterator<E> listIterator() {
  3834. return emptyListIterator();
  3835. }
  3836. public int size() {return 0;}
  3837. public boolean isEmpty() {return true;}
  3838. public boolean contains(Object obj) {return false;}
  3839. public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
  3840. public Object[] toArray() { return new Object[0]; }
  3841. public <T> T[] toArray(T[] a) {
  3842. if (a.length > 0)
  3843. a[0] = null;
  3844. return a;
  3845. }
  3846. public E get(int index) {
  3847. throw new IndexOutOfBoundsException("Index: "+index);
  3848. }
  3849. public boolean equals(Object o) {
  3850. return (o instanceof List) && ((List<?>)o).isEmpty();
  3851. }
  3852. public int hashCode() { return 1; }
  3853. @Override
  3854. public boolean removeIf(Predicate<? super E> filter) {
  3855. Objects.requireNonNull(filter);
  3856. return false;
  3857. }
  3858. @Override
  3859. public void replaceAll(UnaryOperator<E> operator) {
  3860. Objects.requireNonNull(operator);
  3861. }
  3862. @Override
  3863. public void sort(Comparator<? super E> c) {
  3864. }
  3865. // Override default methods in Collection
  3866. @Override
  3867. public void forEach(Consumer<? super E> action) {
  3868. Objects.requireNonNull(action);
  3869. }
  3870. @Override
  3871. public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
  3872. // Preserves singleton property
  3873. private Object readResolve() {
  3874. return EMPTY_LIST;
  3875. }
  3876. }
  3877. /**
  3878. * The empty map (immutable). This map is serializable.
  3879. *
  3880. * @see #emptyMap()
  3881. * @since 1.3
  3882. */
  3883. @SuppressWarnings("rawtypes")
  3884. public static final Map EMPTY_MAP = new EmptyMap<>();
  3885. /**
  3886. * Returns an empty map (immutable). This map is serializable.
  3887. *
  3888. * <p>This example illustrates the type-safe way to obtain an empty map:
  3889. *
  3890. <pre>
  3891. * Map&lt;String, Date&gt; s = Collections.emptyMap();
  3892. * </pre>
  3893. * @implNote Implementations of this method need not create a separate
  3894. * {@code Map} object for each call. Using this method is likely to have
  3895. * comparable cost to using the like-named field. (Unlike this method, the
  3896. * field does not provide type safety.)
  3897. *
  3898. * @param <K> the class of the map keys
  3899. * @param <V> the class of the map values
  3900. * @return an empty map
  3901. * @see #EMPTY_MAP
  3902. * @since 1.5
  3903. */
  3904. @SuppressWarnings("unchecked")
  3905. public static final <K,V> Map<K,V> emptyMap() {
  3906. return (Map<K,V>) EMPTY_MAP;
  3907. }
  3908. /**
  3909. * Returns an empty sorted map (immutable). This map is serializable.
  3910. *
  3911. * <p>This example illustrates the type-safe way to obtain an empty map:
  3912. *
  3913. <pre> {@code
  3914. * SortedMap<String, Date> s = Collections.emptySortedMap();
  3915. * }</pre>
  3916. *
  3917. * @implNote Implementations of this method need not create a separate
  3918. * {@code SortedMap} object for each call.
  3919. *
  3920. * @param <K> the class of the map keys
  3921. * @param <V> the class of the map values
  3922. * @return an empty sorted map
  3923. * @since 1.8
  3924. */
  3925. @SuppressWarnings("unchecked")
  3926. public static final <K,V> SortedMap<K,V> emptySortedMap() {
  3927. return (SortedMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
  3928. }
  3929. /**
  3930. * Returns an empty navigable map (immutable). This map is serializable.
  3931. *
  3932. * <p>This example illustrates the type-safe way to obtain an empty map:
  3933. *
  3934. <pre> {@code
  3935. * NavigableMap<String, Date> s = Collections.emptyNavigableMap();
  3936. * }</pre>
  3937. *
  3938. * @implNote Implementations of this method need not create a separate
  3939. * {@code NavigableMap} object for each call.
  3940. *
  3941. * @param <K> the class of the map keys
  3942. * @param <V> the class of the map values
  3943. * @return an empty navigable map
  3944. * @since 1.8
  3945. */
  3946. @SuppressWarnings("unchecked")
  3947. public static final <K,V> NavigableMap<K,V> emptyNavigableMap() {
  3948. return (NavigableMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
  3949. }
  3950. /**
  3951. * @serial include
  3952. */
  3953. private static class EmptyMap<K,V>
  3954. extends AbstractMap<K,V>
  3955. implements Serializable
  3956. {
  3957. private static final long serialVersionUID = 6428348081105594320L;
  3958. public int size() {return 0;}
  3959. public boolean isEmpty() {return true;}
  3960. public boolean containsKey(Object key) {return false;}
  3961. public boolean containsValue(Object value) {return false;}
  3962. public V get(Object key) {return null;}
  3963. public Set<K> keySet() {return emptySet();}
  3964. public Collection<V> values() {return emptySet();}
  3965. public Set<Map.Entry<K,V>> entrySet() {return emptySet();}
  3966. public boolean equals(Object o) {
  3967. return (o instanceof Map) && ((Map<?,?>)o).isEmpty();
  3968. }
  3969. public int hashCode() {return 0;}
  3970. // Override default methods in Map
  3971. @Override
  3972. @SuppressWarnings("unchecked")
  3973. public V getOrDefault(Object k, V defaultValue) {
  3974. return defaultValue;
  3975. }
  3976. @Override
  3977. public void forEach(BiConsumer<? super K, ? super V> action) {
  3978. Objects.requireNonNull(action);
  3979. }
  3980. @Override
  3981. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  3982. Objects.requireNonNull(function);
  3983. }
  3984. @Override
  3985. public V putIfAbsent(K key, V value) {
  3986. throw new UnsupportedOperationException();
  3987. }
  3988. @Override
  3989. public boolean remove(Object key, Object value) {
  3990. throw new UnsupportedOperationException();
  3991. }
  3992. @Override
  3993. public boolean replace(K key, V oldValue, V newValue) {
  3994. throw new UnsupportedOperationException();
  3995. }
  3996. @Override
  3997. public V replace(K key, V value) {
  3998. throw new UnsupportedOperationException();
  3999. }
  4000. @Override
  4001. public V computeIfAbsent(K key,
  4002. Function<? super K, ? extends V> mappingFunction) {
  4003. throw new UnsupportedOperationException();
  4004. }
  4005. @Override
  4006. public V computeIfPresent(K key,
  4007. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  4008. throw new UnsupportedOperationException();
  4009. }
  4010. @Override
  4011. public V compute(K key,
  4012. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  4013. throw new UnsupportedOperationException();
  4014. }
  4015. @Override
  4016. public V merge(K key, V value,
  4017. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  4018. throw new UnsupportedOperationException();
  4019. }
  4020. // Preserves singleton property
  4021. private Object readResolve() {
  4022. return EMPTY_MAP;
  4023. }
  4024. }
  4025. // Singleton collections
  4026. /**
  4027. * Returns an immutable set containing only the specified object.
  4028. * The returned set is serializable.
  4029. *
  4030. * @param <T> the class of the objects in the set
  4031. * @param o the sole object to be stored in the returned set.
  4032. * @return an immutable set containing only the specified object.
  4033. */
  4034. public static <T> Set<T> singleton(T o) {
  4035. return new SingletonSet<>(o);
  4036. }
  4037. static <E> Iterator<E> singletonIterator(final E e) {
  4038. return new Iterator<E>() {
  4039. private boolean hasNext = true;
  4040. public boolean hasNext() {
  4041. return hasNext;
  4042. }
  4043. public E next() {
  4044. if (hasNext) {
  4045. hasNext = false;
  4046. return e;
  4047. }
  4048. throw new NoSuchElementException();
  4049. }
  4050. public void remove() {
  4051. throw new UnsupportedOperationException();
  4052. }
  4053. @Override
  4054. public void forEachRemaining(Consumer<? super E> action) {
  4055. Objects.requireNonNull(action);
  4056. if (hasNext) {
  4057. action.accept(e);
  4058. hasNext = false;
  4059. }
  4060. }
  4061. };
  4062. }
  4063. /**
  4064. * Creates a {@code Spliterator} with only the specified element
  4065. *
  4066. * @param <T> Type of elements
  4067. * @return A singleton {@code Spliterator}
  4068. */
  4069. static <T> Spliterator<T> singletonSpliterator(final T element) {
  4070. return new Spliterator<T>() {
  4071. long est = 1;
  4072. @Override
  4073. public Spliterator<T> trySplit() {
  4074. return null;
  4075. }
  4076. @Override
  4077. public boolean tryAdvance(Consumer<? super T> consumer) {
  4078. Objects.requireNonNull(consumer);
  4079. if (est > 0) {
  4080. est--;
  4081. consumer.accept(element);
  4082. return true;
  4083. }
  4084. return false;
  4085. }
  4086. @Override
  4087. public void forEachRemaining(Consumer<? super T> consumer) {
  4088. tryAdvance(consumer);
  4089. }
  4090. @Override
  4091. public long estimateSize() {
  4092. return est;
  4093. }
  4094. @Override
  4095. public int characteristics() {
  4096. int value = (element != null) ? Spliterator.NONNULL : 0;
  4097. return value | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE |
  4098. Spliterator.DISTINCT | Spliterator.ORDERED;
  4099. }
  4100. };
  4101. }
  4102. /**
  4103. * @serial include
  4104. */
  4105. private static class SingletonSet<E>
  4106. extends AbstractSet<E>
  4107. implements Serializable
  4108. {
  4109. private static final long serialVersionUID = 3193687207550431679L;
  4110. private final E element;
  4111. SingletonSet(E e) {element = e;}
  4112. public Iterator<E> iterator() {
  4113. return singletonIterator(element);
  4114. }
  4115. public int size() {return 1;}
  4116. public boolean contains(Object o) {return eq(o, element);}
  4117. // Override default methods for Collection
  4118. @Override
  4119. public void forEach(Consumer<? super E> action) {
  4120. action.accept(element);
  4121. }
  4122. @Override
  4123. public Spliterator<E> spliterator() {
  4124. return singletonSpliterator(element);
  4125. }
  4126. @Override
  4127. public boolean removeIf(Predicate<? super E> filter) {
  4128. throw new UnsupportedOperationException();
  4129. }
  4130. }
  4131. /**
  4132. * Returns an immutable list containing only the specified object.
  4133. * The returned list is serializable.
  4134. *
  4135. * @param <T> the class of the objects in the list
  4136. * @param o the sole object to be stored in the returned list.
  4137. * @return an immutable list containing only the specified object.
  4138. * @since 1.3
  4139. */
  4140. public static <T> List<T> singletonList(T o) {
  4141. return new SingletonList<>(o);
  4142. }
  4143. /**
  4144. * @serial include
  4145. */
  4146. private static class SingletonList<E>
  4147. extends AbstractList<E>
  4148. implements RandomAccess, Serializable {
  4149. private static final long serialVersionUID = 3093736618740652951L;
  4150. private final E element;
  4151. SingletonList(E obj) {element = obj;}
  4152. public Iterator<E> iterator() {
  4153. return singletonIterator(element);
  4154. }
  4155. public int size() {return 1;}
  4156. public boolean contains(Object obj) {return eq(obj, element);}
  4157. public E get(int index) {
  4158. if (index != 0)
  4159. throw new IndexOutOfBoundsException("Index: "+index+", Size: 1");
  4160. return element;
  4161. }
  4162. // Override default methods for Collection
  4163. @Override
  4164. public void forEach(Consumer<? super E> action) {
  4165. action.accept(element);
  4166. }
  4167. @Override
  4168. public boolean removeIf(Predicate<? super E> filter) {
  4169. throw new UnsupportedOperationException();
  4170. }
  4171. @Override
  4172. public void replaceAll(UnaryOperator<E> operator) {
  4173. throw new UnsupportedOperationException();
  4174. }
  4175. @Override
  4176. public void sort(Comparator<? super E> c) {
  4177. }
  4178. @Override
  4179. public Spliterator<E> spliterator() {
  4180. return singletonSpliterator(element);
  4181. }
  4182. }
  4183. /**
  4184. * Returns an immutable map, mapping only the specified key to the
  4185. * specified value. The returned map is serializable.
  4186. *
  4187. * @param <K> the class of the map keys
  4188. * @param <V> the class of the map values
  4189. * @param key the sole key to be stored in the returned map.
  4190. * @param value the value to which the returned map maps <tt>key</tt>.
  4191. * @return an immutable map containing only the specified key-value
  4192. * mapping.
  4193. * @since 1.3
  4194. */
  4195. public static <K,V> Map<K,V> singletonMap(K key, V value) {
  4196. return new SingletonMap<>(key, value);
  4197. }
  4198. /**
  4199. * @serial include
  4200. */
  4201. private static class SingletonMap<K,V>
  4202. extends AbstractMap<K,V>
  4203. implements Serializable {
  4204. private static final long serialVersionUID = -6979724477215052911L;
  4205. private final K k;
  4206. private final V v;
  4207. SingletonMap(K key, V value) {
  4208. k = key;
  4209. v = value;
  4210. }
  4211. public int size() {return 1;}
  4212. public boolean isEmpty() {return false;}
  4213. public boolean containsKey(Object key) {return eq(key, k);}
  4214. public boolean containsValue(Object value) {return eq(value, v);}
  4215. public V get(Object key) {return (eq(key, k) ? v : null);}
  4216. private transient Set<K> keySet;
  4217. private transient Set<Map.Entry<K,V>> entrySet;
  4218. private transient Collection<V> values;
  4219. public Set<K> keySet() {
  4220. if (keySet==null)
  4221. keySet = singleton(k);
  4222. return keySet;
  4223. }
  4224. public Set<Map.Entry<K,V>> entrySet() {
  4225. if (entrySet==null)
  4226. entrySet = Collections.<Map.Entry<K,V>>singleton(
  4227. new SimpleImmutableEntry<>(k, v));
  4228. return entrySet;
  4229. }
  4230. public Collection<V> values() {
  4231. if (values==null)
  4232. values = singleton(v);
  4233. return values;
  4234. }
  4235. // Override default methods in Map
  4236. @Override
  4237. public V getOrDefault(Object key, V defaultValue) {
  4238. return eq(key, k) ? v : defaultValue;
  4239. }
  4240. @Override
  4241. public void forEach(BiConsumer<? super K, ? super V> action) {
  4242. action.accept(k, v);
  4243. }
  4244. @Override
  4245. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  4246. throw new UnsupportedOperationException();
  4247. }
  4248. @Override
  4249. public V putIfAbsent(K key, V value) {
  4250. throw new UnsupportedOperationException();
  4251. }
  4252. @Override
  4253. public boolean remove(Object key, Object value) {
  4254. throw new UnsupportedOperationException();
  4255. }
  4256. @Override
  4257. public boolean replace(K key, V oldValue, V newValue) {
  4258. throw new UnsupportedOperationException();
  4259. }
  4260. @Override
  4261. public V replace(K key, V value) {
  4262. throw new UnsupportedOperationException();
  4263. }
  4264. @Override
  4265. public V computeIfAbsent(K key,
  4266. Function<? super K, ? extends V> mappingFunction) {
  4267. throw new UnsupportedOperationException();
  4268. }
  4269. @Override
  4270. public V computeIfPresent(K key,
  4271. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  4272. throw new UnsupportedOperationException();
  4273. }
  4274. @Override
  4275. public V compute(K key,
  4276. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  4277. throw new UnsupportedOperationException();
  4278. }
  4279. @Override
  4280. public V merge(K key, V value,
  4281. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  4282. throw new UnsupportedOperationException();
  4283. }
  4284. }
  4285. // Miscellaneous
  4286. /**
  4287. * Returns an immutable list consisting of <tt>n</tt> copies of the
  4288. * specified object. The newly allocated data object is tiny (it contains
  4289. * a single reference to the data object). This method is useful in
  4290. * combination with the <tt>List.addAll</tt> method to grow lists.
  4291. * The returned list is serializable.
  4292. *
  4293. * @param <T> the class of the object to copy and of the objects
  4294. * in the returned list.
  4295. * @param n the number of elements in the returned list.
  4296. * @param o the element to appear repeatedly in the returned list.
  4297. * @return an immutable list consisting of <tt>n</tt> copies of the
  4298. * specified object.
  4299. * @throws IllegalArgumentException if {@code n < 0}
  4300. * @see List#addAll(Collection)
  4301. * @see List#addAll(int, Collection)
  4302. */
  4303. public static <T> List<T> nCopies(int n, T o) {
  4304. if (n < 0)
  4305. throw new IllegalArgumentException("List length = " + n);
  4306. return new CopiesList<>(n, o);
  4307. }
  4308. /**
  4309. * @serial include
  4310. */
  4311. private static class CopiesList<E>
  4312. extends AbstractList<E>
  4313. implements RandomAccess, Serializable
  4314. {
  4315. private static final long serialVersionUID = 2739099268398711800L;
  4316. final int n;
  4317. final E element;
  4318. CopiesList(int n, E e) {
  4319. assert n >= 0;
  4320. this.n = n;
  4321. element = e;
  4322. }
  4323. public int size() {
  4324. return n;
  4325. }
  4326. public boolean contains(Object obj) {
  4327. return n != 0 && eq(obj, element);
  4328. }
  4329. public int indexOf(Object o) {
  4330. return contains(o) ? 0 : -1;
  4331. }
  4332. public int lastIndexOf(Object o) {
  4333. return contains(o) ? n - 1 : -1;
  4334. }
  4335. public E get(int index) {
  4336. if (index < 0 || index >= n)
  4337. throw new IndexOutOfBoundsException("Index: "+index+
  4338. ", Size: "+n);
  4339. return element;
  4340. }
  4341. public Object[] toArray() {
  4342. final Object[] a = new Object[n];
  4343. if (element != null)
  4344. Arrays.fill(a, 0, n, element);
  4345. return a;
  4346. }
  4347. @SuppressWarnings("unchecked")
  4348. public <T> T[] toArray(T[] a) {
  4349. final int n = this.n;
  4350. if (a.length < n) {
  4351. a = (T[])java.lang.reflect.Array
  4352. .newInstance(a.getClass().getComponentType(), n);
  4353. if (element != null)
  4354. Arrays.fill(a, 0, n, element);
  4355. } else {
  4356. Arrays.fill(a, 0, n, element);
  4357. if (a.length > n)
  4358. a[n] = null;
  4359. }
  4360. return a;
  4361. }
  4362. public List<E> subList(int fromIndex, int toIndex) {
  4363. if (fromIndex < 0)
  4364. throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
  4365. if (toIndex > n)
  4366. throw new IndexOutOfBoundsException("toIndex = " + toIndex);
  4367. if (fromIndex > toIndex)
  4368. throw new IllegalArgumentException("fromIndex(" + fromIndex +
  4369. ") > toIndex(" + toIndex + ")");
  4370. return new CopiesList<>(toIndex - fromIndex, element);
  4371. }
  4372. // Override default methods in Collection
  4373. @Override
  4374. public Stream<E> stream() {
  4375. return IntStream.range(0, n).mapToObj(i -> element);
  4376. }
  4377. @Override
  4378. public Stream<E> parallelStream() {
  4379. return IntStream.range(0, n).parallel().mapToObj(i -> element);
  4380. }
  4381. @Override
  4382. public Spliterator<E> spliterator() {
  4383. return stream().spliterator();
  4384. }
  4385. }
  4386. /**
  4387. * Returns a comparator that imposes the reverse of the <em>natural
  4388. * ordering</em> on a collection of objects that implement the
  4389. * {@code Comparable} interface. (The natural ordering is the ordering
  4390. * imposed by the objects' own {@code compareTo} method.) This enables a
  4391. * simple idiom for sorting (or maintaining) collections (or arrays) of
  4392. * objects that implement the {@code Comparable} interface in
  4393. * reverse-natural-order. For example, suppose {@code a} is an array of
  4394. * strings. Then:
  4395. <pre>
  4396. * Arrays.sort(a, Collections.reverseOrder());
  4397. * </pre> sorts the array in reverse-lexicographic (alphabetical) order.<p>
  4398. *
  4399. * The returned comparator is serializable.
  4400. *
  4401. * @param <T> the class of the objects compared by the comparator
  4402. * @return A comparator that imposes the reverse of the <i>natural
  4403. * ordering</i> on a collection of objects that implement
  4404. * the <tt>Comparable</tt> interface.
  4405. * @see Comparable
  4406. */
  4407. @SuppressWarnings("unchecked")
  4408. public static <T> Comparator<T> reverseOrder() {
  4409. return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
  4410. }
  4411. /**
  4412. * @serial include
  4413. */
  4414. private static class ReverseComparator
  4415. implements Comparator<Comparable<Object>>, Serializable {
  4416. private static final long serialVersionUID = 7207038068494060240L;
  4417. static final ReverseComparator REVERSE_ORDER
  4418. = new ReverseComparator();
  4419. public int compare(Comparable<Object> c1, Comparable<Object> c2) {
  4420. return c2.compareTo(c1);
  4421. }
  4422. private Object readResolve() { return Collections.reverseOrder(); }
  4423. @Override
  4424. public Comparator<Comparable<Object>> reversed() {
  4425. return Comparator.naturalOrder();
  4426. }
  4427. }
  4428. /**
  4429. * Returns a comparator that imposes the reverse ordering of the specified
  4430. * comparator. If the specified comparator is {@code null}, this method is
  4431. * equivalent to {@link #reverseOrder()} (in other words, it returns a
  4432. * comparator that imposes the reverse of the <em>natural ordering</em> on
  4433. * a collection of objects that implement the Comparable interface).
  4434. *
  4435. * <p>The returned comparator is serializable (assuming the specified
  4436. * comparator is also serializable or {@code null}).
  4437. *
  4438. * @param <T> the class of the objects compared by the comparator
  4439. * @param cmp a comparator who's ordering is to be reversed by the returned
  4440. * comparator or {@code null}
  4441. * @return A comparator that imposes the reverse ordering of the
  4442. * specified comparator.
  4443. * @since 1.5
  4444. */
  4445. public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {
  4446. if (cmp == null)
  4447. return reverseOrder();
  4448. if (cmp instanceof ReverseComparator2)
  4449. return ((ReverseComparator2<T>)cmp).cmp;
  4450. return new ReverseComparator2<>(cmp);
  4451. }
  4452. /**
  4453. * @serial include
  4454. */
  4455. private static class ReverseComparator2<T> implements Comparator<T>,
  4456. Serializable
  4457. {
  4458. private static final long serialVersionUID = 4374092139857L;
  4459. /**
  4460. * The comparator specified in the static factory. This will never
  4461. * be null, as the static factory returns a ReverseComparator
  4462. * instance if its argument is null.
  4463. *
  4464. * @serial
  4465. */
  4466. final Comparator<T> cmp;
  4467. ReverseComparator2(Comparator<T> cmp) {
  4468. assert cmp != null;
  4469. this.cmp = cmp;
  4470. }
  4471. public int compare(T t1, T t2) {
  4472. return cmp.compare(t2, t1);
  4473. }
  4474. public boolean equals(Object o) {
  4475. return (o == this) ||
  4476. (o instanceof ReverseComparator2 &&
  4477. cmp.equals(((ReverseComparator2)o).cmp));
  4478. }
  4479. public int hashCode() {
  4480. return cmp.hashCode() ^ Integer.MIN_VALUE;
  4481. }
  4482. @Override
  4483. public Comparator<T> reversed() {
  4484. return cmp;
  4485. }
  4486. }
  4487. /**
  4488. * Returns an enumeration over the specified collection. This provides
  4489. * interoperability with legacy APIs that require an enumeration
  4490. * as input.
  4491. *
  4492. * @param <T> the class of the objects in the collection
  4493. * @param c the collection for which an enumeration is to be returned.
  4494. * @return an enumeration over the specified collection.
  4495. * @see Enumeration
  4496. */
  4497. public static <T> Enumeration<T> enumeration(final Collection<T> c) {
  4498. return new Enumeration<T>() {
  4499. private final Iterator<T> i = c.iterator();
  4500. public boolean hasMoreElements() {
  4501. return i.hasNext();
  4502. }
  4503. public T nextElement() {
  4504. return i.next();
  4505. }
  4506. };
  4507. }
  4508. /**
  4509. * Returns an array list containing the elements returned by the
  4510. * specified enumeration in the order they are returned by the
  4511. * enumeration. This method provides interoperability between
  4512. * legacy APIs that return enumerations and new APIs that require
  4513. * collections.
  4514. *
  4515. * @param <T> the class of the objects returned by the enumeration
  4516. * @param e enumeration providing elements for the returned
  4517. * array list
  4518. * @return an array list containing the elements returned
  4519. * by the specified enumeration.
  4520. * @since 1.4
  4521. * @see Enumeration
  4522. * @see ArrayList
  4523. */
  4524. public static <T> ArrayList<T> list(Enumeration<T> e) {
  4525. ArrayList<T> l = new ArrayList<>();
  4526. while (e.hasMoreElements())
  4527. l.add(e.nextElement());
  4528. return l;
  4529. }
  4530. /**
  4531. * Returns true if the specified arguments are equal, or both null.
  4532. *
  4533. * NB: Do not replace with Object.equals until JDK-8015417 is resolved.
  4534. */
  4535. static boolean eq(Object o1, Object o2) {
  4536. return o1==null ? o2==null : o1.equals(o2);
  4537. }
  4538. /**
  4539. * Returns the number of elements in the specified collection equal to the
  4540. * specified object. More formally, returns the number of elements
  4541. * <tt>e</tt> in the collection such that
  4542. * <tt>(o == null ? e == null : o.equals(e))</tt>.
  4543. *
  4544. * @param c the collection in which to determine the frequency
  4545. * of <tt>o</tt>
  4546. * @param o the object whose frequency is to be determined
  4547. * @return the number of elements in {@code c} equal to {@code o}
  4548. * @throws NullPointerException if <tt>c</tt> is null
  4549. * @since 1.5
  4550. */
  4551. public static int frequency(Collection<?> c, Object o) {
  4552. int result = 0;
  4553. if (o == null) {
  4554. for (Object e : c)
  4555. if (e == null)
  4556. result++;
  4557. } else {
  4558. for (Object e : c)
  4559. if (o.equals(e))
  4560. result++;
  4561. }
  4562. return result;
  4563. }
  4564. /**
  4565. * Returns {@code true} if the two specified collections have no
  4566. * elements in common.
  4567. *
  4568. * <p>Care must be exercised if this method is used on collections that
  4569. * do not comply with the general contract for {@code Collection}.
  4570. * Implementations may elect to iterate over either collection and test
  4571. * for containment in the other collection (or to perform any equivalent
  4572. * computation). If either collection uses a nonstandard equality test
  4573. * (as does a {@link SortedSet} whose ordering is not <em>compatible with
  4574. * equals</em>, or the key set of an {@link IdentityHashMap}), both
  4575. * collections must use the same nonstandard equality test, or the
  4576. * result of this method is undefined.
  4577. *
  4578. * <p>Care must also be exercised when using collections that have
  4579. * restrictions on the elements that they may contain. Collection
  4580. * implementations are allowed to throw exceptions for any operation
  4581. * involving elements they deem ineligible. For absolute safety the
  4582. * specified collections should contain only elements which are
  4583. * eligible elements for both collections.
  4584. *
  4585. * <p>Note that it is permissible to pass the same collection in both
  4586. * parameters, in which case the method will return {@code true} if and
  4587. * only if the collection is empty.
  4588. *
  4589. * @param c1 a collection
  4590. * @param c2 a collection
  4591. * @return {@code true} if the two specified collections have no
  4592. * elements in common.
  4593. * @throws NullPointerException if either collection is {@code null}.
  4594. * @throws NullPointerException if one collection contains a {@code null}
  4595. * element and {@code null} is not an eligible element for the other collection.
  4596. * (<a href="Collection.html#optional-restrictions">optional</a>)
  4597. * @throws ClassCastException if one collection contains an element that is
  4598. * of a type which is ineligible for the other collection.
  4599. * (<a href="Collection.html#optional-restrictions">optional</a>)
  4600. * @since 1.5
  4601. */
  4602. public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
  4603. // The collection to be used for contains(). Preference is given to
  4604. // the collection who's contains() has lower O() complexity.
  4605. Collection<?> contains = c2;
  4606. // The collection to be iterated. If the collections' contains() impl
  4607. // are of different O() complexity, the collection with slower
  4608. // contains() will be used for iteration. For collections who's
  4609. // contains() are of the same complexity then best performance is
  4610. // achieved by iterating the smaller collection.
  4611. Collection<?> iterate = c1;
  4612. // Performance optimization cases. The heuristics:
  4613. // 1. Generally iterate over c1.
  4614. // 2. If c1 is a Set then iterate over c2.
  4615. // 3. If either collection is empty then result is always true.
  4616. // 4. Iterate over the smaller Collection.
  4617. if (c1 instanceof Set) {
  4618. // Use c1 for contains as a Set's contains() is expected to perform
  4619. // better than O(N/2)
  4620. iterate = c2;
  4621. contains = c1;
  4622. } else if (!(c2 instanceof Set)) {
  4623. // Both are mere Collections. Iterate over smaller collection.
  4624. // Example: If c1 contains 3 elements and c2 contains 50 elements and
  4625. // assuming contains() requires ceiling(N/2) comparisons then
  4626. // checking for all c1 elements in c2 would require 75 comparisons
  4627. // (3 * ceiling(50/2)) vs. checking all c2 elements in c1 requiring
  4628. // 100 comparisons (50 * ceiling(3/2)).
  4629. int c1size = c1.size();
  4630. int c2size = c2.size();
  4631. if (c1size == 0 || c2size == 0) {
  4632. // At least one collection is empty. Nothing will match.
  4633. return true;
  4634. }
  4635. if (c1size > c2size) {
  4636. iterate = c2;
  4637. contains = c1;
  4638. }
  4639. }
  4640. for (Object e : iterate) {
  4641. if (contains.contains(e)) {
  4642. // Found a common element. Collections are not disjoint.
  4643. return false;
  4644. }
  4645. }
  4646. // No common elements were found.
  4647. return true;
  4648. }
  4649. /**
  4650. * Adds all of the specified elements to the specified collection.
  4651. * Elements to be added may be specified individually or as an array.
  4652. * The behavior of this convenience method is identical to that of
  4653. * <tt>c.addAll(Arrays.asList(elements))</tt>, but this method is likely
  4654. * to run significantly faster under most implementations.
  4655. *
  4656. * <p>When elements are specified individually, this method provides a
  4657. * convenient way to add a few elements to an existing collection:
  4658. *
  4659. <pre>
  4660. * Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon");
  4661. * </pre>
  4662. *
  4663. * @param <T> the class of the elements to add and of the collection
  4664. * @param c the collection into which <tt>elements</tt> are to be inserted
  4665. * @param elements the elements to insert into <tt>c</tt>
  4666. * @return <tt>true</tt> if the collection changed as a result of the call
  4667. * @throws UnsupportedOperationException if <tt>c</tt> does not support
  4668. * the <tt>add</tt> operation
  4669. * @throws NullPointerException if <tt>elements</tt> contains one or more
  4670. * null values and <tt>c</tt> does not permit null elements, or
  4671. * if <tt>c</tt> or <tt>elements</tt> are <tt>null</tt>
  4672. * @throws IllegalArgumentException if some property of a value in
  4673. * <tt>elements</tt> prevents it from being added to <tt>c</tt>
  4674. * @see Collection#addAll(Collection)
  4675. * @since 1.5
  4676. */
  4677. @SafeVarargs
  4678. public static <T> boolean addAll(Collection<? super T> c, T... elements) {
  4679. boolean result = false;
  4680. for (T element : elements)
  4681. result |= c.add(element);
  4682. return result;
  4683. }
  4684. public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {//1.6
  4685. return new SetFromMap<>(map);
  4686. }
  4687. private static class SetFromMap<E> extends AbstractSet<E>
  4688. implements Set<E>, Serializable
  4689. {
  4690. private final Map<E, Boolean> m; // The backing map
  4691. private transient Set<E> s; // Its keySet
  4692. SetFromMap(Map<E, Boolean> map) {
  4693. if (!map.isEmpty())
  4694. throw new IllegalArgumentException("Map is non-empty");
  4695. m = map;
  4696. s = map.keySet();
  4697. }
  4698. public void clear() { m.clear(); }
  4699. public int size() { return m.size(); }
  4700. public boolean isEmpty() { return m.isEmpty(); }
  4701. public boolean contains(Object o) { return m.containsKey(o); }
  4702. public boolean remove(Object o) { return m.remove(o) != null; }
  4703. public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
  4704. public Iterator<E> iterator() { return s.iterator(); }
  4705. public Object[] toArray() { return s.toArray(); }
  4706. public <T> T[] toArray(T[] a) { return s.toArray(a); }
  4707. public String toString() { return s.toString(); }
  4708. public int hashCode() { return s.hashCode(); }
  4709. public boolean equals(Object o) { return o == this || s.equals(o); }
  4710. public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
  4711. public boolean removeAll(Collection<?> c) {return s.removeAll(c);}
  4712. public boolean retainAll(Collection<?> c) {return s.retainAll(c);}
  4713. @Override
  4714. public void forEach(Consumer<? super E> action) {
  4715. s.forEach(action);
  4716. }
  4717. @Override
  4718. public boolean removeIf(Predicate<? super E> filter) {
  4719. return s.removeIf(filter);
  4720. }
  4721. @Override
  4722. public Spliterator<E> spliterator() {return s.spliterator();}
  4723. @Override
  4724. public Stream<E> stream() {return s.stream();}
  4725. @Override
  4726. public Stream<E> parallelStream() {return s.parallelStream();}
  4727. private static final long serialVersionUID = 2454657854757543876L;
  4728. private void readObject(java.io.ObjectInputStream stream)
  4729. throws IOException, ClassNotFoundException
  4730. {
  4731. stream.defaultReadObject();
  4732. s = m.keySet();
  4733. }
  4734. }
  4735. public static <T> Queue<T> asLifoQueue(Deque<T> deque) {//1.6
  4736. return new AsLIFOQueue<>(deque);
  4737. }
  4738. static class AsLIFOQueue<E> extends AbstractQueue<E>
  4739. implements Queue<E>, Serializable {
  4740. private static final long serialVersionUID = 1802017725587941708L;
  4741. private final Deque<E> q;
  4742. AsLIFOQueue(Deque<E> q) { this.q = q; }
  4743. public boolean add(E e) { q.addFirst(e); return true; }
  4744. public boolean offer(E e) { return q.offerFirst(e); }
  4745. public E poll() { return q.pollFirst(); }
  4746. public E remove() { return q.removeFirst(); }
  4747. public E peek() { return q.peekFirst(); }
  4748. public E element() { return q.getFirst(); }
  4749. public void clear() { q.clear(); }
  4750. public int size() { return q.size(); }
  4751. public boolean isEmpty() { return q.isEmpty(); }
  4752. public boolean contains(Object o) { return q.contains(o); }
  4753. public boolean remove(Object o) { return q.remove(o); }
  4754. public Iterator<E> iterator() { return q.iterator(); }
  4755. public Object[] toArray() { return q.toArray(); }
  4756. public <T> T[] toArray(T[] a) { return q.toArray(a); }
  4757. public String toString() { return q.toString(); }
  4758. public boolean containsAll(Collection<?> c) {return q.containsAll(c);}
  4759. public boolean removeAll(Collection<?> c) {return q.removeAll(c);}
  4760. public boolean retainAll(Collection<?> c) {return q.retainAll(c);}
  4761. @Override
  4762. public void forEach(Consumer<? super E> action) {q.forEach(action);}
  4763. @Override
  4764. public boolean removeIf(Predicate<? super E> filter) {
  4765. return q.removeIf(filter);
  4766. }
  4767. @Override
  4768. public Spliterator<E> spliterator() {return q.spliterator();}
  4769. @Override
  4770. public Stream<E> stream() {return q.stream();}
  4771. @Override
  4772. public Stream<E> parallelStream() {return q.parallelStream();}
  4773. }
  4774. }

Arrays工具类

    Arrays是一个操作数组的工具类。
    常见方法:
1.二分查找:binarySearch(int[]); binarySearch(double[]);
2.数组排序:sort(int []); sort(char[]);
3.将数组变成字符串:toString(int []);
4.复制数组:copyOf(int/boolean…[] original,int newLength);
5.复制部分数组:copyOfRange(int/float[]… original, int from, int to);
6.比较两个数组是否相同:equals(int[],int[]);
7.将数组变为集合:List asList(T[]);

public class Arrays {
    private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;

    private Arrays() {}

    static final class NaturalOrder implements Comparator<Object> {
        @SuppressWarnings("unchecked")
        public int compare(Object first, Object second) {
            return ((Comparable<Object>)first).compareTo(second);
        }
        static final NaturalOrder INSTANCE = new NaturalOrder();
    }

    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > arrayLength) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
    }

    public static void sort(int[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(int[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void sort(long[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(long[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void sort(short[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(short[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void sort(char[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(char[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void sort(byte[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1);
    }

    public static void sort(byte[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
    }

    public static void sort(float[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(float[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void sort(double[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

    public static void sort(double[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
    }

    public static void parallelSort(byte[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1);
        else
            new ArraysParallelSortHelpers.FJByte.Sorter
                (null, a, new byte[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(byte[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
        else
            new ArraysParallelSortHelpers.FJByte.Sorter
                (null, a, new byte[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(char[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJChar.Sorter
                (null, a, new char[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(char[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJChar.Sorter
                (null, a, new char[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(short[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJShort.Sorter
                (null, a, new short[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(short[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJShort.Sorter
                (null, a, new short[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(int[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJInt.Sorter
                (null, a, new int[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(int[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJInt.Sorter
                (null, a, new int[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(long[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJLong.Sorter
                (null, a, new long[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(long[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJLong.Sorter
                (null, a, new long[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(float[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJFloat.Sorter
                (null, a, new float[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(float[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJFloat.Sorter
                (null, a, new float[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(double[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJDouble.Sorter
                (null, a, new double[n], 0, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    public static void parallelSort(double[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJDouble.Sorter
                (null, a, new double[n], fromIndex, n, 0,
                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g).invoke();
    }

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> void parallelSort(T[] a) {//1.8
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJObject.Sorter<T>
                (null, a,
                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
    }

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>>
    void parallelSort(T[] a, int fromIndex, int toIndex) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            TimSort.sort(a, fromIndex, toIndex, NaturalOrder.INSTANCE, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJObject.Sorter<T>
                (null, a,
                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
    }

    @SuppressWarnings("unchecked")
    public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) {//1.8
        if (cmp == null)
            cmp = NaturalOrder.INSTANCE;
        int n = a.length, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            TimSort.sort(a, 0, n, cmp, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJObject.Sorter<T>
                (null, a,
                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
    }

    @SuppressWarnings("unchecked")
    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
                                        Comparator<? super T> cmp) {//1.8
        rangeCheck(a.length, fromIndex, toIndex);
        if (cmp == null)
            cmp = NaturalOrder.INSTANCE;
        int n = toIndex - fromIndex, p, g;
        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
        else
            new ArraysParallelSortHelpers.FJObject.Sorter<T>
                (null, a,
                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
    }

    //Sorting of complex type arrays.
    static final class LegacyMergeSort {
        private static final boolean userRequested =
            java.security.AccessController.doPrivileged(
                new sun.security.action.GetBooleanAction(
                    "java.util.Arrays.useLegacyMergeSort")).booleanValue();
    }

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

    private static void legacyMergeSort(Object[] a) {
        Object[] aux = a.clone();
        mergeSort(aux, a, 0, a.length, 0);
    }

    public static void sort(Object[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, fromIndex, toIndex);
        else
            ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
    }

    private static void legacyMergeSort(Object[] a,
                                        int fromIndex, int toIndex) {
        Object[] aux = copyOfRange(a, fromIndex, toIndex);
        mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
    }

    private static final int INSERTIONSORT_THRESHOLD = 7;

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        int length = high - low;

        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

    private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }

    private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
        T[] aux = a.clone();
        if (c==null)
            mergeSort(aux, a, 0, a.length, 0);
        else
            mergeSort(aux, a, 0, a.length, 0, c);
    }

    public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                Comparator<? super T> c) {
        if (c == null) {
            sort(a, fromIndex, toIndex);
        } else {
            rangeCheck(a.length, fromIndex, toIndex);
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, fromIndex, toIndex, c);
            else
                TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
        }
    }

    private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
                                            Comparator<? super T> c) {
        T[] aux = copyOfRange(a, fromIndex, toIndex);
        if (c==null)
            mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
        else
            mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low, int high, int off,
                                  Comparator c) {
        int length = high - low;
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

    // Parallel prefix
    public static <T> void parallelPrefix(T[] array, BinaryOperator<T> op) {//1.8
        Objects.requireNonNull(op);
        if (array.length > 0)
            new ArrayPrefixHelpers.CumulateTask<>
                    (null, op, array, 0, array.length).invoke();
    }

    public static <T> void parallelPrefix(T[] array, int fromIndex,
                                          int toIndex, BinaryOperator<T> op) {//1.8
        Objects.requireNonNull(op);
        rangeCheck(array.length, fromIndex, toIndex);
        if (fromIndex < toIndex)
            new ArrayPrefixHelpers.CumulateTask<>
                    (null, op, array, fromIndex, toIndex).invoke();
    }

    public static void parallelPrefix(long[] array, LongBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        if (array.length > 0)
            new ArrayPrefixHelpers.LongCumulateTask
                    (null, op, array, 0, array.length).invoke();
    }

    public static void parallelPrefix(long[] array, int fromIndex,
                                      int toIndex, LongBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        rangeCheck(array.length, fromIndex, toIndex);
        if (fromIndex < toIndex)
            new ArrayPrefixHelpers.LongCumulateTask
                    (null, op, array, fromIndex, toIndex).invoke();
    }

    public static void parallelPrefix(double[] array, DoubleBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        if (array.length > 0)
            new ArrayPrefixHelpers.DoubleCumulateTask
                    (null, op, array, 0, array.length).invoke();
    }

    public static void parallelPrefix(double[] array, int fromIndex,
                                      int toIndex, DoubleBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        rangeCheck(array.length, fromIndex, toIndex);
        if (fromIndex < toIndex)
            new ArrayPrefixHelpers.DoubleCumulateTask
                    (null, op, array, fromIndex, toIndex).invoke();
    }

    public static void parallelPrefix(int[] array, IntBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        if (array.length > 0)
            new ArrayPrefixHelpers.IntCumulateTask
                    (null, op, array, 0, array.length).invoke();
    }

    public static void parallelPrefix(int[] array, int fromIndex,
                                      int toIndex, IntBinaryOperator op) {//1.8
        Objects.requireNonNull(op);
        rangeCheck(array.length, fromIndex, toIndex);
        if (fromIndex < toIndex)
            new ArrayPrefixHelpers.IntCumulateTask
                    (null, op, array, fromIndex, toIndex).invoke();
    }

    // Searching
    public static int binarySearch(long[] a, long key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(long[] a, int fromIndex, int toIndex,
                                   long key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(long[] a, int fromIndex, int toIndex,
                                     long key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            long midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(int[] a, int key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(int[] a, int fromIndex, int toIndex,
                                   int key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(short[] a, short key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(short[] a, int fromIndex, int toIndex,
                                   short key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(short[] a, int fromIndex, int toIndex,
                                     short key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            short midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(char[] a, char key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(char[] a, int fromIndex, int toIndex,
                                   char key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    // Like public version, but without range checks.
    private static int binarySearch0(char[] a, int fromIndex, int toIndex,
                                     char key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            char midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(byte[] a, byte key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(byte[] a, int fromIndex, int toIndex,
                                   byte key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(byte[] a, int fromIndex, int toIndex,
                                     byte key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            byte midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(double[] a, double key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(double[] a, int fromIndex, int toIndex,
                                   double key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(double[] a, int fromIndex, int toIndex,
                                     double key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            double midVal = a[mid];

            if (midVal < key)
                low = mid + 1;  // Neither val is NaN, thisVal is smaller
            else if (midVal > key)
                high = mid - 1; // Neither val is NaN, thisVal is larger
            else {
                long midBits = Double.doubleToLongBits(midVal);
                long keyBits = Double.doubleToLongBits(key);
                if (midBits == keyBits)     // Values are equal
                    return mid;             // Key found
                else if (midBits < keyBits) // (-0.0, 0.0) or (!NaN, NaN)
                    low = mid + 1;
                else                        // (0.0, -0.0) or (NaN, !NaN)
                    high = mid - 1;
            }
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(float[] a, float key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(float[] a, int fromIndex, int toIndex,
                                   float key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(float[] a, int fromIndex, int toIndex,
                                     float key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            float midVal = a[mid];

            if (midVal < key)
                low = mid + 1;  // Neither val is NaN, thisVal is smaller
            else if (midVal > key)
                high = mid - 1; // Neither val is NaN, thisVal is larger
            else {
                int midBits = Float.floatToIntBits(midVal);
                int keyBits = Float.floatToIntBits(key);
                if (midBits == keyBits)     // Values are equal
                    return mid;             // Key found
                else if (midBits < keyBits) // (-0.0, 0.0) or (!NaN, NaN)
                    low = mid + 1;
                else                        // (0.0, -0.0) or (NaN, !NaN)
                    high = mid - 1;
            }
        }
        return -(low + 1);  // key not found.
    }

    public static int binarySearch(Object[] a, Object key) {
        return binarySearch0(a, 0, a.length, key);
    }

    public static int binarySearch(Object[] a, int fromIndex, int toIndex,
                                   Object key) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
                                     Object key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            @SuppressWarnings("rawtypes")
            Comparable midVal = (Comparable)a[mid];
            @SuppressWarnings("unchecked")
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c) {
        return binarySearch0(a, 0, a.length, key, c);
    }

    public static <T> int binarySearch(T[] a, int fromIndex, int toIndex,
                                       T key, Comparator<? super T> c) {//1.6
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key, c);
    }

    private static <T> int binarySearch0(T[] a, int fromIndex, int toIndex,
                                         T key, Comparator<? super T> c) {
        if (c == null) {
            return binarySearch0(a, fromIndex, toIndex, key);
        }
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            T midVal = a[mid];
            int cmp = c.compare(midVal, key);
            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

    // Equality Testing
    public static boolean equals(long[] a, long[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(int[] a, int[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(short[] a, short a2[]) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(char[] a, char[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(byte[] a, byte[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(boolean[] a, boolean[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static boolean equals(double[] a, double[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (Double.doubleToLongBits(a[i])!=Double.doubleToLongBits(a2[i]))
                return false;

        return true;
    }

    public static boolean equals(float[] a, float[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (Float.floatToIntBits(a[i])!=Float.floatToIntBits(a2[i]))
                return false;

        return true;
    }

    public static boolean equals(Object[] a, Object[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++) {
            Object o1 = a[i];
            Object o2 = a2[i];
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }

        return true;
    }

    // Filling
    public static void fill(long[] a, long val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(long[] a, int fromIndex, int toIndex, long val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(int[] a, int val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(int[] a, int fromIndex, int toIndex, int val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(short[] a, short val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(short[] a, int fromIndex, int toIndex, short val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(char[] a, char val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(char[] a, int fromIndex, int toIndex, char val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(byte[] a, byte val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(byte[] a, int fromIndex, int toIndex, byte val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(boolean[] a, boolean val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(boolean[] a, int fromIndex, int toIndex,
                            boolean val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(double[] a, double val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(double[] a, int fromIndex, int toIndex,double val){
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(float[] a, float val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(float[] a, int fromIndex, int toIndex, float val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    public static void fill(Object[] a, Object val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

    public static void fill(Object[] a, int fromIndex, int toIndex, Object val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
    }

    // Cloning
    @SuppressWarnings("unchecked")
    public static <T> T[] copyOf(T[] original, int newLength) {//1.6
        return (T[]) copyOf(original, newLength, original.getClass());
    }

    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {//1.6
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static byte[] copyOf(byte[] original, int newLength) {//1.6
        byte[] copy = new byte[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static short[] copyOf(short[] original, int newLength) {//1.6
        short[] copy = new short[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static int[] copyOf(int[] original, int newLength) {//1.6
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static long[] copyOf(long[] original, int newLength) {//1.6
        long[] copy = new long[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static char[] copyOf(char[] original, int newLength) {//1.6
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static float[] copyOf(float[] original, int newLength) {//1.6
        float[] copy = new float[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static double[] copyOf(double[] original, int newLength) {//1.6
        double[] copy = new double[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    public static boolean[] copyOf(boolean[] original, int newLength) {//1.6
        boolean[] copy = new boolean[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    @SuppressWarnings("unchecked")
    public static <T> T[] copyOfRange(T[] original, int from, int to) {//1.6
        return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass());
    }

    public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static byte[] copyOfRange(byte[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        byte[] copy = new byte[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static short[] copyOfRange(short[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        short[] copy = new short[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static int[] copyOfRange(int[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        int[] copy = new int[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static long[] copyOfRange(long[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        long[] copy = new long[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static char[] copyOfRange(char[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static float[] copyOfRange(float[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        float[] copy = new float[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static double[] copyOfRange(double[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        double[] copy = new double[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    public static boolean[] copyOfRange(boolean[] original, int from, int to) {//1.6
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        boolean[] copy = new boolean[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    // Misc
    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {//成员内部类
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }
    }

    public static int hashCode(long a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (long element : a) {
            int elementHash = (int)(element ^ (element >>> 32));
            result = 31 * result + elementHash;
        }

        return result;
    }

    public static int hashCode(int a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (int element : a)
            result = 31 * result + element;

        return result;
    }

    public static int hashCode(short a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (short element : a)
            result = 31 * result + element;

        return result;
    }

    public static int hashCode(char a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (char element : a)
            result = 31 * result + element;

        return result;
    }

    public static int hashCode(byte a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (byte element : a)
            result = 31 * result + element;

        return result;
    }

    public static int hashCode(boolean a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (boolean element : a)
            result = 31 * result + (element ? 1231 : 1237);

        return result;
    }

    public static int hashCode(float a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (float element : a)
            result = 31 * result + Float.floatToIntBits(element);

        return result;
    }

    public static int hashCode(double a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;
        for (double element : a) {
            long bits = Double.doubleToLongBits(element);
            result = 31 * result + (int)(bits ^ (bits >>> 32));
        }
        return result;
    }

    public static int hashCode(Object a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }

    public static int deepHashCode(Object a[]) {//1.5
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a) {
            int elementHash = 0;
            if (element instanceof Object[])
                elementHash = deepHashCode((Object[]) element);
            else if (element instanceof byte[])
                elementHash = hashCode((byte[]) element);
            else if (element instanceof short[])
                elementHash = hashCode((short[]) element);
            else if (element instanceof int[])
                elementHash = hashCode((int[]) element);
            else if (element instanceof long[])
                elementHash = hashCode((long[]) element);
            else if (element instanceof char[])
                elementHash = hashCode((char[]) element);
            else if (element instanceof float[])
                elementHash = hashCode((float[]) element);
            else if (element instanceof double[])
                elementHash = hashCode((double[]) element);
            else if (element instanceof boolean[])
                elementHash = hashCode((boolean[]) element);
            else if (element != null)
                elementHash = element.hashCode();

            result = 31 * result + elementHash;
        }

        return result;
    }

    public static boolean deepEquals(Object[] a1, Object[] a2) {//1.5
        if (a1 == a2)
            return true;
        if (a1 == null || a2==null)
            return false;
        int length = a1.length;
        if (a2.length != length)
            return false;

        for (int i = 0; i < length; i++) {
            Object e1 = a1[i];
            Object e2 = a2[i];

            if (e1 == e2)
                continue;
            if (e1 == null)
                return false;

            // Figure out whether the two elements are equal
            boolean eq = deepEquals0(e1, e2);

            if (!eq)
                return false;
        }
        return true;
    }

    static boolean deepEquals0(Object e1, Object e2) {
        assert e1 != null;
        boolean eq;
        if (e1 instanceof Object[] && e2 instanceof Object[])
            eq = deepEquals ((Object[]) e1, (Object[]) e2);
        else if (e1 instanceof byte[] && e2 instanceof byte[])
            eq = equals((byte[]) e1, (byte[]) e2);
        else if (e1 instanceof short[] && e2 instanceof short[])
            eq = equals((short[]) e1, (short[]) e2);
        else if (e1 instanceof int[] && e2 instanceof int[])
            eq = equals((int[]) e1, (int[]) e2);
        else if (e1 instanceof long[] && e2 instanceof long[])
            eq = equals((long[]) e1, (long[]) e2);
        else if (e1 instanceof char[] && e2 instanceof char[])
            eq = equals((char[]) e1, (char[]) e2);
        else if (e1 instanceof float[] && e2 instanceof float[])
            eq = equals((float[]) e1, (float[]) e2);
        else if (e1 instanceof double[] && e2 instanceof double[])
            eq = equals((double[]) e1, (double[]) e2);
        else if (e1 instanceof boolean[] && e2 instanceof boolean[])
            eq = equals((boolean[]) e1, (boolean[]) e2);
        else
            eq = e1.equals(e2);
        return eq;
    }

    public static String toString(long[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(int[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(short[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(char[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(byte[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(boolean[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(float[] a) {//1.5
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(double[] a) {//1.5
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String toString(Object[] a) {//1.5
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

    public static String deepToString(Object[] a) {//1.5
        if (a == null)
            return "null";

        int bufLen = 20 * a.length;
        if (a.length != 0 && bufLen <= 0)
            bufLen = Integer.MAX_VALUE;
        StringBuilder buf = new StringBuilder(bufLen);
        deepToString(a, buf, new HashSet<Object[]>());
        return buf.toString();
    }

    private static void deepToString(Object[] a, StringBuilder buf,
                                     Set<Object[]> dejaVu) {
        if (a == null) {
            buf.append("null");
            return;
        }
        int iMax = a.length - 1;
        if (iMax == -1) {
            buf.append("[]");
            return;
        }

        dejaVu.add(a);
        buf.append('[');
        for (int i = 0; ; i++) {

            Object element = a[i];
            if (element == null) {
                buf.append("null");
            } else {
                Class<?> eClass = element.getClass();

                if (eClass.isArray()) {
                    if (eClass == byte[].class)
                        buf.append(toString((byte[]) element));
                    else if (eClass == short[].class)
                        buf.append(toString((short[]) element));
                    else if (eClass == int[].class)
                        buf.append(toString((int[]) element));
                    else if (eClass == long[].class)
                        buf.append(toString((long[]) element));
                    else if (eClass == char[].class)
                        buf.append(toString((char[]) element));
                    else if (eClass == float[].class)
                        buf.append(toString((float[]) element));
                    else if (eClass == double[].class)
                        buf.append(toString((double[]) element));
                    else if (eClass == boolean[].class)
                        buf.append(toString((boolean[]) element));
                    else { // element is an array of object references
                        if (dejaVu.contains(element))
                            buf.append("[...]");
                        else
                            deepToString((Object[])element, buf, dejaVu);
                    }
                } else {  // element is non-null and not an array
                    buf.append(element.toString());
                }
            }
            if (i == iMax)
                break;
            buf.append(", ");
        }
        buf.append(']');
        dejaVu.remove(a);
    }

    public static <T> void setAll(T[] array, IntFunction<? extends T> generator) {//1.8
        Objects.requireNonNull(generator);
        for (int i = 0; i < array.length; i++)
            array[i] = generator.apply(i);
    }

    public static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) {//1.8
        Objects.requireNonNull(generator);
        IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.apply(i); });
    }

    public static void setAll(int[] array, IntUnaryOperator generator) {//1.8
        Objects.requireNonNull(generator);
        for (int i = 0; i < array.length; i++)
            array[i] = generator.applyAsInt(i);
    }

    public static void parallelSetAll(int[] array, IntUnaryOperator generator) {//1.8
        Objects.requireNonNull(generator);
        IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); });
    }

    public static void setAll(long[] array, IntToLongFunction generator) {//1.8
        Objects.requireNonNull(generator);
        for (int i = 0; i < array.length; i++)
            array[i] = generator.applyAsLong(i);
    }

    public static void parallelSetAll(long[] array, IntToLongFunction generator) {//1.8
        Objects.requireNonNull(generator);
        IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsLong(i); });
    }

    public static void setAll(double[] array, IntToDoubleFunction generator) {//1.8
        Objects.requireNonNull(generator);
        for (int i = 0; i < array.length; i++)
            array[i] = generator.applyAsDouble(i);
    }

    public static void parallelSetAll(double[] array, IntToDoubleFunction generator) {//1.8
        Objects.requireNonNull(generator);
        IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsDouble(i); });
    }

    public static <T> Spliterator<T> spliterator(T[] array) {//1.8
        return Spliterators.spliterator(array,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static <T> Spliterator<T> spliterator(T[] array, int startInclusive, int endExclusive) {//1.8
        return Spliterators.spliterator(array, startInclusive, endExclusive,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfInt spliterator(int[] array) {//1.8
        return Spliterators.spliterator(array,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfInt spliterator(int[] array, int startInclusive, int endExclusive) {//1.8
        return Spliterators.spliterator(array, startInclusive, endExclusive,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfLong spliterator(long[] array) {//1.8
        return Spliterators.spliterator(array,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfLong spliterator(long[] array, int startInclusive, int endExclusive) {//1.8
        return Spliterators.spliterator(array, startInclusive, endExclusive,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfDouble spliterator(double[] array) {//1.8
        return Spliterators.spliterator(array,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static Spliterator.OfDouble spliterator(double[] array, int startInclusive, int endExclusive) {//1.8
        return Spliterators.spliterator(array, startInclusive, endExclusive,
                                        Spliterator.ORDERED | Spliterator.IMMUTABLE);
    }

    public static <T> Stream<T> stream(T[] array) {//1.8
        return stream(array, 0, array.length);
    }

    public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {//1.8
        return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
    }

    public static IntStream stream(int[] array) {//1.8
        return stream(array, 0, array.length);
    }

    public static IntStream stream(int[] array, int startInclusive, int endExclusive) {//1.8
        return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
    }

    public static LongStream stream(long[] array) {//1.8
        return stream(array, 0, array.length);
    }

    public static LongStream stream(long[] array, int startInclusive, int endExclusive) {//1.8
        return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
    }

    public static DoubleStream stream(double[] array) {//1.8
        return stream(array, 0, array.length);
    }

    public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {//1.8
        return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
    }
}

序列化

序列化:将对象写入到IO流中
反序列化:从IO流中恢复对象
    意义:序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
    使用场景:所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。通常建议:程序创建的每个JavaBean类都实现Serializeable接口。
从 JVM 的角度看,Serializeable就是一个标记接口而已。

public interface Serializable {//1.1
}

    序列化使用方式:实现Serializable接口,显示的定义serialVersionUID
    Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

拷贝

    1.java的类型分为两大类,一类为primitive,如int,另一类为引用类型,如String,Object等等。java的引用类型都是存储在堆上的。
    primitive类型的拷贝的确能做到相等且隔离。引用类型的拷贝相对复杂,分浅拷贝(shallow clone)深拷贝(deep clone)
    2.浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,以及它所包含的所有对象的引用地址,而不拷贝对象包含的引用指向的对象(这是 java 中的浅拷贝,其他语言的浅拷贝貌似是直接拷贝引用,即新引用和旧引用指向同一对象)。
    3.深拷贝不仅拷贝对象本身和对象中的基本变量,而且拷贝对象包含的引用指向的所有对象,简单来说,即复制原型中对象的内存copy。
    有名的GoF设计模式里有一个模式为原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。简单的说就是clone一个对象实例。使得clone出来的copy和原有的对象一模一样。
    注意:对于常量池方式创建的 String 类型,会针对原值克隆,不存在引用地址一说,对于其他不可变类,如 LocalDate,也是一样
clone 方法定义在 Object 类中:

    protected native Object clone() throws CloneNotSupportedException;

    1. 声明实现Cloneable接口。从 JVM 的角度看,Cloneable 就是一个标记接口而已。

    public interface Cloneable {//1.0
    }

    2. 如果父类的clone实现没有问题的话,调用super.clone拿到一个对象,在该对象的内存存储中,所有父类定义的field都已经clone好了,该类中的primitive和不可变类型引用也克隆好了,可变类型引用都是浅copy;如果父类的clone实现有问题,覆写一个新的clone逻辑。
    3. 把浅copy的引用指向原型对象新的克隆体。
    缺点· 手工维护clone的调用链;· 如果class的field是个final的可变类,第三步没有办法做了。

异常

Java基础知识概述 - 图2

public class Throwable implements Serializable {
    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -3042686055658047285L;
    private transient Object backtrace;//本机代码在此插槽中保存了一些堆栈回溯的指示
    private String detailMessage;
    private static class SentinelHolder {
        public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =
            new StackTraceElement("", "", null, Integer.MIN_VALUE);
        public static final StackTraceElement[] STACK_TRACE_SENTINEL =
            new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
    }
    private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];//空栈的共享值
    private Throwable cause = this;//1.4,当前对象为cause
    private StackTraceElement[] stackTrace = UNASSIGNED_STACK;//1.4
    private static final List<Throwable> SUPPRESSED_SENTINEL =
        Collections.unmodifiableList(new ArrayList<Throwable>(0));//设置此静态字段会引入一个可接受的值,对一些java.util类的初始化依赖

    private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;//1.7,
    private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";//尝试抑制空异常的消息。
    private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted";//试图压抑自己的讯息。
    private static final String CAUSE_CAPTION = "Caused by: ";//标记原因异常堆栈跟踪的标题
    private static final String SUPPRESSED_CAPTION = "Suppressed: ";//用于标记抑制的异常堆栈跟踪的标题

    public Throwable() {
        fillInStackTrace();
    }

    public Throwable(String message) {
        fillInStackTrace();
        detailMessage = message;
    }

    public Throwable(String message, Throwable cause) {//1.4
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }

    public Throwable(Throwable cause) {//1.4
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }

    protected Throwable(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {//1.7
        if (writableStackTrace) {
            fillInStackTrace();
        } else {
            stackTrace = null;
        }
        detailMessage = message;
        this.cause = cause;
        if (!enableSuppression)
            suppressedExceptions = null;
    }

    public String getMessage() {//返回此 throwable 的详细消息字符串
        return detailMessage;
    }

    public String getLocalizedMessage() {//1.1,创建此 throwable 的本地化描述
        return getMessage();
    }

    public synchronized Throwable getCause() {//1.4,返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。
        return (cause==this ? null : cause);
    }

    public synchronized Throwable initCause(Throwable cause) {//1.4,将此 throwable 的 cause 初始化为指定值
        if (this.cause != this)
            throw new IllegalStateException("Can't overwrite cause with " +
                                            Objects.toString(cause, "a null"), this);
        if (cause == this)
            throw new IllegalArgumentException("Self-causation not permitted", this);
        this.cause = cause;
        return this;
    }

    public String toString() {//返回此 throwable 的简短描述。
        String s = getClass().getName();
        String message = getLocalizedMessage();
        return (message != null) ? (s + ": " + message) : s;
    }

    public void printStackTrace() {//将此 throwable 及其追踪输出至标准错误流
        printStackTrace(System.err);
    }

    public void printStackTrace(PrintStream s) {//将此 throwable 及其追踪输出到指定的输出流
        printStackTrace(new WrappedPrintStream(s));
    }

    private void printStackTrace(PrintStreamOrWriter s) {
        // Guard against malicious overrides of Throwable.equals by
        // using a Set with identity equality semantics.
        Set<Throwable> dejaVu =
            Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
        dejaVu.add(this);

        synchronized (s.lock()) {
            // Print our stack trace
            s.println(this);
            StackTraceElement[] trace = getOurStackTrace();
            for (StackTraceElement traceElement : trace)
                s.println("\tat " + traceElement);

            // Print suppressed exceptions, if any
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);

            // Print cause, if any
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
        }
    }

    private void printEnclosedStackTrace(PrintStreamOrWriter s,
                                         StackTraceElement[] enclosingTrace,
                                         String caption,
                                         String prefix,
                                         Set<Throwable> dejaVu) {
        assert Thread.holdsLock(s.lock());
        if (dejaVu.contains(this)) {
            s.println("\t[CIRCULAR REFERENCE:" + this + "]");
        } else {
            dejaVu.add(this);
            // Compute number of frames in common between this and enclosing trace
            StackTraceElement[] trace = getOurStackTrace();
            int m = trace.length - 1;
            int n = enclosingTrace.length - 1;
            while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
                m--; n--;
            }
            int framesInCommon = trace.length - 1 - m;

            // Print our stack trace
            s.println(prefix + caption + this);
            for (int i = 0; i <= m; i++)
                s.println(prefix + "\tat " + trace[i]);
            if (framesInCommon != 0)
                s.println(prefix + "\t... " + framesInCommon + " more");

            // Print suppressed exceptions, if any
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
                                           prefix +"\t", dejaVu);

            // Print cause, if any
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
        }
    }

    public void printStackTrace(PrintWriter s) {//1.1,将此 throwable 及其追踪输出到指定的 PrintWriter
        printStackTrace(new WrappedPrintWriter(s));
    }

    private abstract static class PrintStreamOrWriter {
        /** Returns the object to be locked when using this StreamOrWriter */
        abstract Object lock();

        /** Prints the specified string as a line on this StreamOrWriter */
        abstract void println(Object o);
    }

    private static class WrappedPrintStream extends PrintStreamOrWriter {
        private final PrintStream printStream;

        WrappedPrintStream(PrintStream printStream) {
            this.printStream = printStream;
        }

        Object lock() {
            return printStream;
        }

        void println(Object o) {
            printStream.println(o);
        }
    }

    private static class WrappedPrintWriter extends PrintStreamOrWriter {
        private final PrintWriter printWriter;

        WrappedPrintWriter(PrintWriter printWriter) {
            this.printWriter = printWriter;
        }

        Object lock() {
            return printWriter;
        }

        void println(Object o) {
            printWriter.println(o);
        }
    }

    public synchronized Throwable fillInStackTrace() {
        if (stackTrace != null ||
            backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0);
            stackTrace = UNASSIGNED_STACK;
        }
        return this;
    }

    private native Throwable fillInStackTrace(int dummy);//在异常堆栈跟踪中填充。

    public StackTraceElement[] getStackTrace() {//1.4,提供编程访问由 printStackTrace() 输出的堆栈跟踪信息。
        return getOurStackTrace().clone();
    }

    private synchronized StackTraceElement[] getOurStackTrace() {
        // Initialize stack trace field with information from
        // backtrace if this is the first call to this method
        if (stackTrace == UNASSIGNED_STACK ||
            (stackTrace == null && backtrace != null) /* Out of protocol state */) {
            int depth = getStackTraceDepth();
            stackTrace = new StackTraceElement[depth];
            for (int i=0; i < depth; i++)
                stackTrace[i] = getStackTraceElement(i);
        } else if (stackTrace == null) {
            return UNASSIGNED_STACK;
        }
        return stackTrace;
    }

    public void setStackTrace(StackTraceElement[] stackTrace) {//1.4,设置将由 getStackTrace() 返回,并由 printStackTrace() 和相关方法输出的堆栈跟踪元素。
        // Validate argument
        StackTraceElement[] defensiveCopy = stackTrace.clone();
        for (int i = 0; i < defensiveCopy.length; i++) {
            if (defensiveCopy[i] == null)
                throw new NullPointerException("stackTrace[" + i + "]");
        }

        synchronized (this) {
            if (this.stackTrace == null && // Immutable stack
                backtrace == null) // Test for out of protocol state
                return;
            this.stackTrace = defensiveCopy;
        }
    }

    native int getStackTraceDepth();

    native StackTraceElement getStackTraceElement(int index);

    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();     // read in all fields
        if (suppressedExceptions != null) {
            List<Throwable> suppressed = null;
            if (suppressedExceptions.isEmpty()) {
                // Use the sentinel for a zero-length list
                suppressed = SUPPRESSED_SENTINEL;
            } else { // Copy Throwables to new list
                suppressed = new ArrayList<>(1);
                for (Throwable t : suppressedExceptions) {
                    // Enforce constraints on suppressed exceptions in
                    // case of corrupt or malicious stream.
                    if (t == null)
                        throw new NullPointerException(NULL_CAUSE_MESSAGE);
                    if (t == this)
                        throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
                    suppressed.add(t);
                }
            }
            suppressedExceptions = suppressed;
        } // else a null suppressedExceptions field remains null


        if (stackTrace != null) {
            if (stackTrace.length == 0) {
                stackTrace = UNASSIGNED_STACK.clone();
            }  else if (stackTrace.length == 1 &&
                        // Check for the marker of an immutable stack trace
                        SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
                stackTrace = null;
            } else { // Verify stack trace elements are non-null.
                for(StackTraceElement ste : stackTrace) {
                    if (ste == null)
                        throw new NullPointerException("null StackTraceElement in serial stream. ");
                }
            }
        } else {
            stackTrace = UNASSIGNED_STACK.clone();
        }
    }

    private synchronized void writeObject(ObjectOutputStream s)
        throws IOException {

        getOurStackTrace();

        StackTraceElement[] oldStackTrace = stackTrace;
        try {
            if (stackTrace == null)
                stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
            s.defaultWriteObject();
        } finally {
            stackTrace = oldStackTrace;
        }
    }

    public final synchronized void addSuppressed(Throwable exception) {//1.7
        if (exception == this)
            throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);

        if (exception == null)
            throw new NullPointerException(NULL_CAUSE_MESSAGE);

        if (suppressedExceptions == null) // Suppressed exceptions not recorded
            return;

        if (suppressedExceptions == SUPPRESSED_SENTINEL)
            suppressedExceptions = new ArrayList<>(1);

        suppressedExceptions.add(exception);
    }

    private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];

    public final synchronized Throwable[] getSuppressed() {//1.7
        if (suppressedExceptions == SUPPRESSED_SENTINEL ||
            suppressedExceptions == null)
            return EMPTY_THROWABLE_ARRAY;
        else
            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
    }
}

Java异常栈

    看Exception异常的时候,发生异常的方法会在最上层,中间还有其他的调用层次,main方法会在最下层。这其实是栈的结构,先进后出的。

Java异常中的Error

    Error一般表示编译时或者系统错误,虚拟机相关的错误,系统崩溃(例如:我们开发中有时会遇到的OutOfMemoryError)等。这种错误无法恢复或不可捕获,将导致应用程序中断,通常应用程序无法处理这些错误,因此也不应该试图用catch来进行捕获。

Java异常中的Exception

public class Exception extends Throwable {
    static final long serialVersionUID = -3387516993124229948L;

    public Exception() {
        super();
    }

    public Exception(String message) {
        super(message);
    }

    public Exception(String message, Throwable cause) {//1.4
        super(message, cause);
    }

    public Exception(Throwable cause) {//1.4
        super(cause);
    }

    protected Exception(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {//1.7
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

1.Java中的受检查异常
    写IO操作的代码,对File或者Stream进行操作的时候一定需要使用try-catch包起来,否则编译会失败,这是因为这些异常类型是受检查的异常类型。编译器在编译时,对于受检异常必须进行try…catch或throws处理,否则无法通过编译。常见的受检查异常包括:IO操作、ClassNotFoundException、线程操作等,以及自定义业务异常。
2.Java中的非受检查异常(运行时异常)
    RuntimeException及其子类都统称为非受检查异常,例如:NullPointExecrption、NumberFormatException(字符串转换为数字)、ArrayIndexOutOfBoundsException(数组越界)、ClassCastException(类型转换错误)、ArithmeticException(算术错误)等。

Java的异常处理

throws关键字 方法层,捕捉,不处理
throw关键字 逻辑层,捕捉,处理

try{
    ///可能会抛出异常的代码
}catch(Exception e1){
    //处理Type1类型异常的代码
}catch(Exception e2){
    //处理Type2类型异常的代码
}finally{
    //资源关闭代码(一定会被执行),除内存以外的资源恢复到它们的初始状态
}

泛型

    泛型的出现,为了在编译时提供更严格的类型检查,并支持泛型编程,解决了类型安全问题。泛型具有以下优点:
    1.编译时的强类型检查
    泛型要求在声明时指定实际数据类型,Java 编译器在编译时会对泛型代码做强类型检查,并在代码违反类型安全时发出告警。早发现,早治理,把隐患扼杀于摇篮,在编译时发现并修复错误所付出的代价远比在运行时小。
    2.避免了类型转换
    3.泛型编程可以实现通用算法
    通过使用泛型,程序员可以实现通用算法,这些算法可以处理不同类型的集合,可以自定义,并且类型安全且易于阅读。
    通过设定不同的类型,可以往集合里面存储不同类型的数据类型(而且只能存储设定的数据类型,这是泛型的优势之一)。“泛型”简单的意思就是泛指的类型(参数化类型)。最典型的的例子就是ArrayList,这个集合我们无论传递什么数据类型,它都能很好的工作,主要有泛型接口泛型类泛型方法

类型擦除

    Java 泛型是使用类型擦除来实现的,使用泛型时,任何具体的类型信息都被擦除了。
    1.把泛型中的所有类型参数替换为 Object,如果指定类型边界,则使用类型边界来替换。因此,生成的字节码仅包含普通的类,接口和方法。
    2.擦除出现的类型声明,即去掉 <> 的内容。比如 T get() 方法声明就变成了 Object get() ;List< String> 就变成了 List。如有必要,插入类型转换以保持类型安全。
    3.生成桥接方法以保留扩展泛型类型中的多态性。类型擦除确保不为参数化类型创建新类;因此,泛型不会产生运行时开销。
    泛型不能用于显式地引用运行时类型的操作之中,例如:转型、instanceof 操作和 new 表达式。因为所有关于参数的类型信息都丢失了。正是由于泛型是基于类型擦除实现的,所以,泛型类型无法向上转型(用子类实例去初始化父类,这是面向对象中多态的重要表现)。比如,List< Interger> 却并非继承了 List< Object>。这是因为,泛型类并没有自己独有的 Class 类对象,并不存在 List< Object>.class 或是 List< Interger>.class,Java 编译器会将二者都视为 List.class。

泛型通配符(?)

    类型边界可以对泛型的类型参数设置限制条件
    上界通配符缩小类型参数的类型范围,<? extends Number>
    下界通配符将未知类型限制为该类型的特定类型或超类类型。<? super Number>
    无界通配符有两种应用场景:1.可以使用 Object 类中提供的功能来实现的方法。2.使用不依赖于类型参数的泛型类中的方法。<?>
    泛型不能向上转型。但是,我们可以通过使用通配符来向上转型。

使用泛型的建议

1.消除类型检查告警
2.List 优先于数组
3.优先考虑使用泛型来提高代码通用性
4.优先考虑泛型方法来限定泛型的范围
5.利用有限制通配符来提升 API 的灵活性
6.优先考虑类型安全的异构容器

反射

    1.一种 动态(运行时)访问、检测 & 修改它本身的能力
    2.动态(运行时)获取类的完整结构信息(变量和方法) & 调用对象的方法
     静态编译:在编译时确定类型 & 绑定对象。如常见的使用new关键字创建对象
     动态编译:运行时确定类型 & 绑定对象。动态编译体现了Java的灵活性、多态特性 & 降低类之间的藕合性
    3.反射机制的实现 主要通过 操作java.lang.Class类 ,步骤如下:
     · 获取目标类型的Class对象;
     · 通过 Class 对象分别获取Constructor类对象、Method类对象 和 Field 类对象;
     · 通过 Constructor类对象、Method类对象 和 Field类对象分别获取类的构造函数、方法&属性的具体信息,并进行后续操作。

注解

    注解不是必须的,但了解注解有助于我们深入理解某些第三方框架(比如,Lombok),提高工作效率。

注解定义

    Java注解又称为标注,是Java从1.5开始支持加入源码的特殊语法元数据;Java中的类、方法、变量、参数、包都可以被注解。这里提到的元数据是描述数据的数据,和业务逻辑无关,所以当你查看注解类时,发现里面没有任何逻辑处理
    注解的逻辑实现是元数据的用户来处理的,注解仅仅提供它定义的属性(类/方法/变量/参数/包)的信息,注解的用户来读取这些信息并实现必要的逻辑。
    · 当使用java中的注解(比如@Override、@Deprecated、@SuppressWarnings)。JVM就是用户,它在字节码层面工作。
    · 如果是自定义的注解。比如,第三方框架ActiveAndroid,它的用户是每个使用注解的类,所有使用注解的类都需要继承Model.java,在Model.java的构造方法中通过反射来获取注解类中的每个属性。
    1.注解仅仅是元数据,和业务逻辑无关,所以当你查看注解类时,发现里面没有任何逻辑处理;
    2.javadoc中的@author、@version、@param、@return、@deprecated、@hide、@throws、@exception、@see是标记,并不是注解;

注解的作用

    1.格式检查:告诉编译器信息,比如被@Override标记的方法如果不是父类的某个方法,IDE会报错;
    2.减少配置:运行时动态处理,得到注解信息,实现代替配置文件的功能;
    3.减少重复工作:比如第三方框架xUtils,通过注解@ViewInject减少对findViewById的调用,类似的还有(JUnit、ActiveAndroid等);

内部类

    定义在另一个类中的类

内部类存在主要原因

1.内部类方法可以访问该类定义所在作用域中的数据,包括被 private 修饰的私有数据
2.内部类可以对同一包中的其他类隐藏起来
3.内部类可以实现 java 单继承的缺陷
4.当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现

    · 创建内部类的时刻并不依赖于外部类的创建
    · 内部类是一个相对独立的实体,与外部类不是is-a关系

内部类分类

1.静态内部类、非静态内部类(成员内部类)
2.局部内部类(方法里边的内部类)
    · 局部内类不允许使用访问权限修饰符 public private protected 均不允许
    · 局部内部类对外完全隐藏,除了创建这个类的方法可以访问它其他的地方是不允许访问的。
    · 局部内部类与成员内部类不同之处是他可以引用成员变量,但该成员必须声明为 final,内部不允许修改基本数据类型变量的值,内部不允许修改引用指向的对象(对象本身是可以被就修改的)。
3.匿名内部类(方法里边,没有类名的内部类)
    · 匿名内部类是没有访问修饰符的。
    · 匿名内部类必须继承一个抽象类或者实现一个接口
    · 匿名内部类中不能存在任何静态成员或方法
    · 匿名内部类是没有构造方法的,因为它没有类名。
    · 与局部内部相同匿名内部类也可以引用局部变量。此变量也必须声明为 final(匿名内部类是没有访问修饰符的。)