mirror of https://github.com/CyC2018/CS-Notes.git
add some source code
This commit is contained in:
parent
1ad01b547d
commit
3c8cea7382
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* This class implements the <tt>Set</tt> interface, backed by a hash table
|
||||
* (actually a <tt>HashMap</tt> instance). It makes no guarantees as to the
|
||||
* iteration order of the set; in particular, it does not guarantee that the
|
||||
* order will remain constant over time. This class permits the <tt>null</tt>
|
||||
* element.
|
||||
*
|
||||
* <p>This class offers constant time performance for the basic operations
|
||||
* (<tt>add</tt>, <tt>remove</tt>, <tt>contains</tt> and <tt>size</tt>),
|
||||
* assuming the hash function disperses the elements properly among the
|
||||
* buckets. Iterating over this set requires time proportional to the sum of
|
||||
* the <tt>HashSet</tt> instance's size (the number of elements) plus the
|
||||
* "capacity" of the backing <tt>HashMap</tt> instance (the number of
|
||||
* buckets). Thus, it's very important not to set the initial capacity too
|
||||
* high (or the load factor too low) if iteration performance is important.
|
||||
*
|
||||
* <p><strong>Note that this implementation is not synchronized.</strong>
|
||||
* If multiple threads access a hash set concurrently, and at least one of
|
||||
* the threads modifies the set, it <i>must</i> be synchronized externally.
|
||||
* This is typically accomplished by synchronizing on some object that
|
||||
* naturally encapsulates the set.
|
||||
*
|
||||
* If no such object exists, the set should be "wrapped" using the
|
||||
* {@link Collections#synchronizedSet Collections.synchronizedSet}
|
||||
* method. This is best done at creation time, to prevent accidental
|
||||
* unsynchronized access to the set:<pre>
|
||||
* Set s = Collections.synchronizedSet(new HashSet(...));</pre>
|
||||
*
|
||||
* <p>The iterators returned by this class's <tt>iterator</tt> method are
|
||||
* <i>fail-fast</i>: if the set is modified at any time after the iterator is
|
||||
* created, in any way except through the iterator's own <tt>remove</tt>
|
||||
* method, the Iterator throws a {@link ConcurrentModificationException}.
|
||||
* Thus, in the face of concurrent modification, the iterator fails quickly
|
||||
* and cleanly, rather than risking arbitrary, non-deterministic behavior at
|
||||
* an undetermined time in the future.
|
||||
*
|
||||
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
* as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
* presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
|
||||
* Therefore, it would be wrong to write a program that depended on this
|
||||
* exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
* should be used only to detect bugs.</i>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <E> the type of elements maintained by this set
|
||||
*
|
||||
* @author Josh Bloch
|
||||
* @author Neal Gafter
|
||||
* @see Collection
|
||||
* @see Set
|
||||
* @see TreeSet
|
||||
* @see HashMap
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class HashSet<E>
|
||||
extends AbstractSet<E>
|
||||
implements Set<E>, Cloneable, java.io.Serializable
|
||||
{
|
||||
static final long serialVersionUID = -5024744406713321676L;
|
||||
|
||||
private transient HashMap<E,Object> map;
|
||||
|
||||
// Dummy value to associate with an Object in the backing Map
|
||||
private static final Object PRESENT = new Object();
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
|
||||
* default initial capacity (16) and load factor (0.75).
|
||||
*/
|
||||
public HashSet() {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new set containing the elements in the specified
|
||||
* collection. The <tt>HashMap</tt> is created with default load factor
|
||||
* (0.75) and an initial capacity sufficient to contain the elements in
|
||||
* the specified collection.
|
||||
*
|
||||
* @param c the collection whose elements are to be placed into this set
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public HashSet(Collection<? extends E> c) {
|
||||
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
|
||||
* the specified initial capacity and the specified load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the hash map
|
||||
* @param loadFactor the load factor of the hash map
|
||||
* @throws IllegalArgumentException if the initial capacity is less
|
||||
* than zero, or if the load factor is nonpositive
|
||||
*/
|
||||
public HashSet(int initialCapacity, float loadFactor) {
|
||||
map = new HashMap<>(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
|
||||
* the specified initial capacity and default load factor (0.75).
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the hash table
|
||||
* @throws IllegalArgumentException if the initial capacity is less
|
||||
* than zero
|
||||
*/
|
||||
public HashSet(int initialCapacity) {
|
||||
map = new HashMap<>(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty linked hash set. (This package private
|
||||
* constructor is only used by LinkedHashSet.) The backing
|
||||
* HashMap instance is a LinkedHashMap with the specified initial
|
||||
* capacity and the specified load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the hash map
|
||||
* @param loadFactor the load factor of the hash map
|
||||
* @param dummy ignored (distinguishes this
|
||||
* constructor from other int, float constructor.)
|
||||
* @throws IllegalArgumentException if the initial capacity is less
|
||||
* than zero, or if the load factor is nonpositive
|
||||
*/
|
||||
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
|
||||
map = new LinkedHashMap<>(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set. The elements
|
||||
* are returned in no particular order.
|
||||
*
|
||||
* @return an Iterator over the elements in this set
|
||||
* @see ConcurrentModificationException
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return map.keySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set (its cardinality).
|
||||
*
|
||||
* @return the number of elements in this set (its cardinality)
|
||||
*/
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains no elements.
|
||||
*
|
||||
* @return <tt>true</tt> if this set contains no elements
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains the specified element.
|
||||
* More formally, returns <tt>true</tt> if and only if this set
|
||||
* contains an element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>.
|
||||
*
|
||||
* @param o element whose presence in this set is to be tested
|
||||
* @return <tt>true</tt> if this set contains the specified element
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return map.containsKey(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already present.
|
||||
* More formally, adds the specified element <tt>e</tt> to this set if
|
||||
* this set contains no element <tt>e2</tt> such that
|
||||
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
|
||||
* If this set already contains the element, the call leaves the set
|
||||
* unchanged and returns <tt>false</tt>.
|
||||
*
|
||||
* @param e element to be added to this set
|
||||
* @return <tt>true</tt> if this set did not already contain the specified
|
||||
* element
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return map.put(e, PRESENT)==null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from this set if it is present.
|
||||
* More formally, removes an element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>,
|
||||
* if this set contains such an element. Returns <tt>true</tt> if
|
||||
* this set contained the element (or equivalently, if this set
|
||||
* changed as a result of the call). (This set will not contain the
|
||||
* element once the call returns.)
|
||||
*
|
||||
* @param o object to be removed from this set, if present
|
||||
* @return <tt>true</tt> if the set contained the specified element
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return map.remove(o)==PRESENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
* The set will be empty after this call returns.
|
||||
*/
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of this <tt>HashSet</tt> instance: the elements
|
||||
* themselves are not cloned.
|
||||
*
|
||||
* @return a shallow copy of this set
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
HashSet<E> newSet = (HashSet<E>) super.clone();
|
||||
newSet.map = (HashMap<E, Object>) map.clone();
|
||||
return newSet;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the state of this <tt>HashSet</tt> instance to a stream (that is,
|
||||
* serialize it).
|
||||
*
|
||||
* @serialData The capacity of the backing <tt>HashMap</tt> instance
|
||||
* (int), and its load factor (float) are emitted, followed by
|
||||
* the size of the set (the number of elements it contains)
|
||||
* (int), followed by all of its elements (each an Object) in
|
||||
* no particular order.
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException {
|
||||
// Write out any hidden serialization magic
|
||||
s.defaultWriteObject();
|
||||
|
||||
// Write out HashMap capacity and load factor
|
||||
s.writeInt(map.capacity());
|
||||
s.writeFloat(map.loadFactor());
|
||||
|
||||
// Write out size
|
||||
s.writeInt(map.size());
|
||||
|
||||
// Write out all elements in the proper order.
|
||||
for (E e : map.keySet())
|
||||
s.writeObject(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitute the <tt>HashSet</tt> instance from a stream (that is,
|
||||
* deserialize it).
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
// Read in any hidden serialization magic
|
||||
s.defaultReadObject();
|
||||
|
||||
// Read in HashMap capacity and load factor and create backing HashMap
|
||||
int capacity = s.readInt();
|
||||
float loadFactor = s.readFloat();
|
||||
map = (((HashSet)this) instanceof LinkedHashSet ?
|
||||
new LinkedHashMap<E,Object>(capacity, loadFactor) :
|
||||
new HashMap<E,Object>(capacity, loadFactor));
|
||||
|
||||
// Read in size
|
||||
int size = s.readInt();
|
||||
|
||||
// Read in all elements in the proper order.
|
||||
for (int i=0; i<size; i++) {
|
||||
E e = (E) s.readObject();
|
||||
map.put(e, PRESENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* <p>Hash table and linked list implementation of the <tt>Map</tt> interface,
|
||||
* with predictable iteration order. This implementation differs from
|
||||
* <tt>HashMap</tt> in that it maintains a doubly-linked list running through
|
||||
* all of its entries. This linked list defines the iteration ordering,
|
||||
* which is normally the order in which keys were inserted into the map
|
||||
* (<i>insertion-order</i>). Note that insertion order is not affected
|
||||
* if a key is <i>re-inserted</i> into the map. (A key <tt>k</tt> is
|
||||
* reinserted into a map <tt>m</tt> if <tt>m.put(k, v)</tt> is invoked when
|
||||
* <tt>m.containsKey(k)</tt> would return <tt>true</tt> immediately prior to
|
||||
* the invocation.)
|
||||
*
|
||||
* <p>This implementation spares its clients from the unspecified, generally
|
||||
* chaotic ordering provided by {@link HashMap} (and {@link Hashtable}),
|
||||
* without incurring the increased cost associated with {@link TreeMap}. It
|
||||
* can be used to produce a copy of a map that has the same order as the
|
||||
* original, regardless of the original map's implementation:
|
||||
* <pre>
|
||||
* void foo(Map m) {
|
||||
* Map copy = new LinkedHashMap(m);
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
* This technique is particularly useful if a module takes a map on input,
|
||||
* copies it, and later returns results whose order is determined by that of
|
||||
* the copy. (Clients generally appreciate having things returned in the same
|
||||
* order they were presented.)
|
||||
*
|
||||
* <p>A special {@link #LinkedHashMap(int,float,boolean) constructor} is
|
||||
* provided to create a linked hash map whose order of iteration is the order
|
||||
* in which its entries were last accessed, from least-recently accessed to
|
||||
* most-recently (<i>access-order</i>). This kind of map is well-suited to
|
||||
* building LRU caches. Invoking the <tt>put</tt> or <tt>get</tt> method
|
||||
* results in an access to the corresponding entry (assuming it exists after
|
||||
* the invocation completes). The <tt>putAll</tt> method generates one entry
|
||||
* access for each mapping in the specified map, in the order that key-value
|
||||
* mappings are provided by the specified map's entry set iterator. <i>No
|
||||
* other methods generate entry accesses.</i> In particular, operations on
|
||||
* collection-views do <i>not</i> affect the order of iteration of the backing
|
||||
* map.
|
||||
*
|
||||
* <p>The {@link #removeEldestEntry(Map.Entry)} method may be overridden to
|
||||
* impose a policy for removing stale mappings automatically when new mappings
|
||||
* are added to the map.
|
||||
*
|
||||
* <p>This class provides all of the optional <tt>Map</tt> operations, and
|
||||
* permits null elements. Like <tt>HashMap</tt>, it provides constant-time
|
||||
* performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
|
||||
* <tt>remove</tt>), assuming the hash function disperses elements
|
||||
* properly among the buckets. Performance is likely to be just slightly
|
||||
* below that of <tt>HashMap</tt>, due to the added expense of maintaining the
|
||||
* linked list, with one exception: Iteration over the collection-views
|
||||
* of a <tt>LinkedHashMap</tt> requires time proportional to the <i>size</i>
|
||||
* of the map, regardless of its capacity. Iteration over a <tt>HashMap</tt>
|
||||
* is likely to be more expensive, requiring time proportional to its
|
||||
* <i>capacity</i>.
|
||||
*
|
||||
* <p>A linked hash map has two parameters that affect its performance:
|
||||
* <i>initial capacity</i> and <i>load factor</i>. They are defined precisely
|
||||
* as for <tt>HashMap</tt>. Note, however, that the penalty for choosing an
|
||||
* excessively high value for initial capacity is less severe for this class
|
||||
* than for <tt>HashMap</tt>, as iteration times for this class are unaffected
|
||||
* by capacity.
|
||||
*
|
||||
* <p><strong>Note that this implementation is not synchronized.</strong>
|
||||
* If multiple threads access a linked hash map concurrently, and at least
|
||||
* one of the threads modifies the map structurally, it <em>must</em> be
|
||||
* synchronized externally. This is typically accomplished by
|
||||
* synchronizing on some object that naturally encapsulates the map.
|
||||
*
|
||||
* If no such object exists, the map should be "wrapped" using the
|
||||
* {@link Collections#synchronizedMap Collections.synchronizedMap}
|
||||
* method. This is best done at creation time, to prevent accidental
|
||||
* unsynchronized access to the map:<pre>
|
||||
* Map m = Collections.synchronizedMap(new LinkedHashMap(...));</pre>
|
||||
*
|
||||
* A structural modification is any operation that adds or deletes one or more
|
||||
* mappings or, in the case of access-ordered linked hash maps, affects
|
||||
* iteration order. In insertion-ordered linked hash maps, merely changing
|
||||
* the value associated with a key that is already contained in the map is not
|
||||
* a structural modification. <strong>In access-ordered linked hash maps,
|
||||
* merely querying the map with <tt>get</tt> is a structural
|
||||
* modification.</strong>)
|
||||
*
|
||||
* <p>The iterators returned by the <tt>iterator</tt> method of the collections
|
||||
* returned by all of this class's collection view methods are
|
||||
* <em>fail-fast</em>: if the map is structurally modified at any time after
|
||||
* the iterator is created, in any way except through the iterator's own
|
||||
* <tt>remove</tt> method, the iterator will throw a {@link
|
||||
* ConcurrentModificationException}. Thus, in the face of concurrent
|
||||
* modification, the iterator fails quickly and cleanly, rather than risking
|
||||
* arbitrary, non-deterministic behavior at an undetermined time in the future.
|
||||
*
|
||||
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
* as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
* presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
|
||||
* Therefore, it would be wrong to write a program that depended on this
|
||||
* exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
* should be used only to detect bugs.</i>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
*
|
||||
* @author Josh Bloch
|
||||
* @see Object#hashCode()
|
||||
* @see Collection
|
||||
* @see Map
|
||||
* @see HashMap
|
||||
* @see TreeMap
|
||||
* @see Hashtable
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class LinkedHashMap<K,V>
|
||||
extends HashMap<K,V>
|
||||
implements Map<K,V>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 3801124242820219131L;
|
||||
|
||||
/**
|
||||
* The head of the doubly linked list.
|
||||
*/
|
||||
private transient Entry<K,V> header;
|
||||
|
||||
/**
|
||||
* The iteration ordering method for this linked hash map: <tt>true</tt>
|
||||
* for access-order, <tt>false</tt> for insertion-order.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
private final boolean accessOrder;
|
||||
|
||||
/**
|
||||
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
|
||||
* with the specified initial capacity and load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity
|
||||
* @param loadFactor the load factor
|
||||
* @throws IllegalArgumentException if the initial capacity is negative
|
||||
* or the load factor is nonpositive
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
|
||||
* with the specified initial capacity and a default load factor (0.75).
|
||||
*
|
||||
* @param initialCapacity the initial capacity
|
||||
* @throws IllegalArgumentException if the initial capacity is negative
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
|
||||
* with the default initial capacity (16) and load factor (0.75).
|
||||
*/
|
||||
public LinkedHashMap() {
|
||||
super();
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
|
||||
* the same mappings as the specified map. The <tt>LinkedHashMap</tt>
|
||||
* instance is created with a default load factor (0.75) and an initial
|
||||
* capacity sufficient to hold the mappings in the specified map.
|
||||
*
|
||||
* @param m the map whose mappings are to be placed in this map
|
||||
* @throws NullPointerException if the specified map is null
|
||||
*/
|
||||
public LinkedHashMap(Map<? extends K, ? extends V> m) {
|
||||
super(m);
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty <tt>LinkedHashMap</tt> instance with the
|
||||
* specified initial capacity, load factor and ordering mode.
|
||||
*
|
||||
* @param initialCapacity the initial capacity
|
||||
* @param loadFactor the load factor
|
||||
* @param accessOrder the ordering mode - <tt>true</tt> for
|
||||
* access-order, <tt>false</tt> for insertion-order
|
||||
* @throws IllegalArgumentException if the initial capacity is negative
|
||||
* or the load factor is nonpositive
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity,
|
||||
float loadFactor,
|
||||
boolean accessOrder) {
|
||||
super(initialCapacity, loadFactor);
|
||||
this.accessOrder = accessOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by superclass constructors and pseudoconstructors (clone,
|
||||
* readObject) before any entries are inserted into the map. Initializes
|
||||
* the chain.
|
||||
*/
|
||||
void init() {
|
||||
header = new Entry<>(-1, null, null, null);
|
||||
header.before = header.after = header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers all entries to new table array. This method is called
|
||||
* by superclass resize. It is overridden for performance, as it is
|
||||
* faster to iterate using our linked list.
|
||||
*/
|
||||
void transfer(HashMap.Entry[] newTable) {
|
||||
int newCapacity = newTable.length;
|
||||
for (Entry<K,V> e = header.after; e != header; e = e.after) {
|
||||
int index = indexFor(e.hash, newCapacity);
|
||||
e.next = newTable[index];
|
||||
newTable[index] = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this map maps one or more keys to the
|
||||
* specified value.
|
||||
*
|
||||
* @param value value whose presence in this map is to be tested
|
||||
* @return <tt>true</tt> if this map maps one or more keys to the
|
||||
* specified value
|
||||
*/
|
||||
public boolean containsValue(Object value) {
|
||||
// Overridden to take advantage of faster iterator
|
||||
if (value==null) {
|
||||
for (Entry e = header.after; e != header; e = e.after)
|
||||
if (e.value==null)
|
||||
return true;
|
||||
} else {
|
||||
for (Entry e = header.after; e != header; e = e.after)
|
||||
if (value.equals(e.value))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped,
|
||||
* or {@code null} if this map contains no mapping for the key.
|
||||
*
|
||||
* <p>More formally, if this map contains a mapping from a key
|
||||
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
|
||||
* key.equals(k))}, then this method returns {@code v}; otherwise
|
||||
* it returns {@code null}. (There can be at most one such mapping.)
|
||||
*
|
||||
* <p>A return value of {@code null} does not <i>necessarily</i>
|
||||
* indicate that the map contains no mapping for the key; it's also
|
||||
* possible that the map explicitly maps the key to {@code null}.
|
||||
* The {@link #containsKey containsKey} operation may be used to
|
||||
* distinguish these two cases.
|
||||
*/
|
||||
public V get(Object key) {
|
||||
Entry<K,V> e = (Entry<K,V>)getEntry(key);
|
||||
if (e == null)
|
||||
return null;
|
||||
e.recordAccess(this);
|
||||
return e.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the mappings from this map.
|
||||
* The map will be empty after this call returns.
|
||||
*/
|
||||
public void clear() {
|
||||
super.clear();
|
||||
header.before = header.after = header;
|
||||
}
|
||||
|
||||
/**
|
||||
* LinkedHashMap entry.
|
||||
*/
|
||||
private static class Entry<K,V> extends HashMap.Entry<K,V> {
|
||||
// These fields comprise the doubly linked list used for iteration.
|
||||
Entry<K,V> before, after;
|
||||
|
||||
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
|
||||
super(hash, key, value, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this entry from the linked list.
|
||||
*/
|
||||
private void remove() {
|
||||
before.after = after;
|
||||
after.before = before;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts this entry before the specified existing entry in the list.
|
||||
*/
|
||||
private void addBefore(Entry<K,V> existingEntry) {
|
||||
after = existingEntry;
|
||||
before = existingEntry.before;
|
||||
before.after = this;
|
||||
after.before = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked by the superclass whenever the value
|
||||
* of a pre-existing entry is read by Map.get or modified by Map.set.
|
||||
* If the enclosing Map is access-ordered, it moves the entry
|
||||
* to the end of the list; otherwise, it does nothing.
|
||||
*/
|
||||
void recordAccess(HashMap<K,V> m) {
|
||||
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
|
||||
if (lm.accessOrder) {
|
||||
lm.modCount++;
|
||||
remove();
|
||||
addBefore(lm.header);
|
||||
}
|
||||
}
|
||||
|
||||
void recordRemoval(HashMap<K,V> m) {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class LinkedHashIterator<T> implements Iterator<T> {
|
||||
Entry<K,V> nextEntry = header.after;
|
||||
Entry<K,V> lastReturned = null;
|
||||
|
||||
/**
|
||||
* The modCount value that the iterator believes that the backing
|
||||
* List should have. If this expectation is violated, the iterator
|
||||
* has detected concurrent modification.
|
||||
*/
|
||||
int expectedModCount = modCount;
|
||||
|
||||
public boolean hasNext() {
|
||||
return nextEntry != header;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (lastReturned == null)
|
||||
throw new IllegalStateException();
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
|
||||
LinkedHashMap.this.remove(lastReturned.key);
|
||||
lastReturned = null;
|
||||
expectedModCount = modCount;
|
||||
}
|
||||
|
||||
Entry<K,V> nextEntry() {
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
if (nextEntry == header)
|
||||
throw new NoSuchElementException();
|
||||
|
||||
Entry<K,V> e = lastReturned = nextEntry;
|
||||
nextEntry = e.after;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyIterator extends LinkedHashIterator<K> {
|
||||
public K next() { return nextEntry().getKey(); }
|
||||
}
|
||||
|
||||
private class ValueIterator extends LinkedHashIterator<V> {
|
||||
public V next() { return nextEntry().value; }
|
||||
}
|
||||
|
||||
private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
|
||||
public Map.Entry<K,V> next() { return nextEntry(); }
|
||||
}
|
||||
|
||||
// These Overrides alter the behavior of superclass view iterator() methods
|
||||
Iterator<K> newKeyIterator() { return new KeyIterator(); }
|
||||
Iterator<V> newValueIterator() { return new ValueIterator(); }
|
||||
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
|
||||
|
||||
/**
|
||||
* This override alters behavior of superclass put method. It causes newly
|
||||
* allocated entry to get inserted at the end of the linked list and
|
||||
* removes the eldest entry if appropriate.
|
||||
*/
|
||||
void addEntry(int hash, K key, V value, int bucketIndex) {
|
||||
createEntry(hash, key, value, bucketIndex);
|
||||
|
||||
// Remove eldest entry if instructed, else grow capacity if appropriate
|
||||
Entry<K,V> eldest = header.after;
|
||||
if (removeEldestEntry(eldest)) {
|
||||
removeEntryForKey(eldest.key);
|
||||
} else {
|
||||
if (size >= threshold)
|
||||
resize(2 * table.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This override differs from addEntry in that it doesn't resize the
|
||||
* table or remove the eldest entry.
|
||||
*/
|
||||
void createEntry(int hash, K key, V value, int bucketIndex) {
|
||||
HashMap.Entry<K,V> old = table[bucketIndex];
|
||||
Entry<K,V> e = new Entry<>(hash, key, value, old);
|
||||
table[bucketIndex] = e;
|
||||
e.addBefore(header);
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this map should remove its eldest entry.
|
||||
* This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
|
||||
* inserting a new entry into the map. It provides the implementor
|
||||
* with the opportunity to remove the eldest entry each time a new one
|
||||
* is added. This is useful if the map represents a cache: it allows
|
||||
* the map to reduce memory consumption by deleting stale entries.
|
||||
*
|
||||
* <p>Sample use: this override will allow the map to grow up to 100
|
||||
* entries and then delete the eldest entry each time a new entry is
|
||||
* added, maintaining a steady state of 100 entries.
|
||||
* <pre>
|
||||
* private static final int MAX_ENTRIES = 100;
|
||||
*
|
||||
* protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||
* return size() > MAX_ENTRIES;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>This method typically does not modify the map in any way,
|
||||
* instead allowing the map to modify itself as directed by its
|
||||
* return value. It <i>is</i> permitted for this method to modify
|
||||
* the map directly, but if it does so, it <i>must</i> return
|
||||
* <tt>false</tt> (indicating that the map should not attempt any
|
||||
* further modification). The effects of returning <tt>true</tt>
|
||||
* after modifying the map from within this method are unspecified.
|
||||
*
|
||||
* <p>This implementation merely returns <tt>false</tt> (so that this
|
||||
* map acts like a normal map - the eldest element is never removed).
|
||||
*
|
||||
* @param eldest The least recently inserted entry in the map, or if
|
||||
* this is an access-ordered map, the least recently accessed
|
||||
* entry. This is the entry that will be removed it this
|
||||
* method returns <tt>true</tt>. If the map was empty prior
|
||||
* to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
|
||||
* in this invocation, this will be the entry that was just
|
||||
* inserted; in other words, if the map contains a single
|
||||
* entry, the eldest entry is also the newest.
|
||||
* @return <tt>true</tt> if the eldest entry should be removed
|
||||
* from the map; <tt>false</tt> if it should be retained.
|
||||
*/
|
||||
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* <p>Hash table and linked list implementation of the <tt>Set</tt> interface,
|
||||
* with predictable iteration order. This implementation differs from
|
||||
* <tt>HashSet</tt> in that it maintains a doubly-linked list running through
|
||||
* all of its entries. This linked list defines the iteration ordering,
|
||||
* which is the order in which elements were inserted into the set
|
||||
* (<i>insertion-order</i>). Note that insertion order is <i>not</i> affected
|
||||
* if an element is <i>re-inserted</i> into the set. (An element <tt>e</tt>
|
||||
* is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
|
||||
* <tt>s.contains(e)</tt> would return <tt>true</tt> immediately prior to
|
||||
* the invocation.)
|
||||
*
|
||||
* <p>This implementation spares its clients from the unspecified, generally
|
||||
* chaotic ordering provided by {@link HashSet}, without incurring the
|
||||
* increased cost associated with {@link TreeSet}. It can be used to
|
||||
* produce a copy of a set that has the same order as the original, regardless
|
||||
* of the original set's implementation:
|
||||
* <pre>
|
||||
* void foo(Set s) {
|
||||
* Set copy = new LinkedHashSet(s);
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
* This technique is particularly useful if a module takes a set on input,
|
||||
* copies it, and later returns results whose order is determined by that of
|
||||
* the copy. (Clients generally appreciate having things returned in the same
|
||||
* order they were presented.)
|
||||
*
|
||||
* <p>This class provides all of the optional <tt>Set</tt> operations, and
|
||||
* permits null elements. Like <tt>HashSet</tt>, it provides constant-time
|
||||
* performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
|
||||
* <tt>remove</tt>), assuming the hash function disperses elements
|
||||
* properly among the buckets. Performance is likely to be just slightly
|
||||
* below that of <tt>HashSet</tt>, due to the added expense of maintaining the
|
||||
* linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
|
||||
* requires time proportional to the <i>size</i> of the set, regardless of
|
||||
* its capacity. Iteration over a <tt>HashSet</tt> is likely to be more
|
||||
* expensive, requiring time proportional to its <i>capacity</i>.
|
||||
*
|
||||
* <p>A linked hash set has two parameters that affect its performance:
|
||||
* <i>initial capacity</i> and <i>load factor</i>. They are defined precisely
|
||||
* as for <tt>HashSet</tt>. Note, however, that the penalty for choosing an
|
||||
* excessively high value for initial capacity is less severe for this class
|
||||
* than for <tt>HashSet</tt>, as iteration times for this class are unaffected
|
||||
* by capacity.
|
||||
*
|
||||
* <p><strong>Note that this implementation is not synchronized.</strong>
|
||||
* If multiple threads access a linked hash set concurrently, and at least
|
||||
* one of the threads modifies the set, it <em>must</em> be synchronized
|
||||
* externally. This is typically accomplished by synchronizing on some
|
||||
* object that naturally encapsulates the set.
|
||||
*
|
||||
* If no such object exists, the set should be "wrapped" using the
|
||||
* {@link Collections#synchronizedSet Collections.synchronizedSet}
|
||||
* method. This is best done at creation time, to prevent accidental
|
||||
* unsynchronized access to the set: <pre>
|
||||
* Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
|
||||
*
|
||||
* <p>The iterators returned by this class's <tt>iterator</tt> method are
|
||||
* <em>fail-fast</em>: if the set is modified at any time after the iterator
|
||||
* is created, in any way except through the iterator's own <tt>remove</tt>
|
||||
* method, the iterator will throw a {@link ConcurrentModificationException}.
|
||||
* Thus, in the face of concurrent modification, the iterator fails quickly
|
||||
* and cleanly, rather than risking arbitrary, non-deterministic behavior at
|
||||
* an undetermined time in the future.
|
||||
*
|
||||
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
* as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
* presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
|
||||
* Therefore, it would be wrong to write a program that depended on this
|
||||
* exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
* should be used only to detect bugs.</i>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <E> the type of elements maintained by this set
|
||||
*
|
||||
* @author Josh Bloch
|
||||
* @see Object#hashCode()
|
||||
* @see Collection
|
||||
* @see Set
|
||||
* @see HashSet
|
||||
* @see TreeSet
|
||||
* @see Hashtable
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class LinkedHashSet<E>
|
||||
extends HashSet<E>
|
||||
implements Set<E>, Cloneable, java.io.Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2851667679971038690L;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty linked hash set with the specified initial
|
||||
* capacity and load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the linked hash set
|
||||
* @param loadFactor the load factor of the linked hash set
|
||||
* @throws IllegalArgumentException if the initial capacity is less
|
||||
* than zero, or if the load factor is nonpositive
|
||||
*/
|
||||
public LinkedHashSet(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty linked hash set with the specified initial
|
||||
* capacity and the default load factor (0.75).
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the LinkedHashSet
|
||||
* @throws IllegalArgumentException if the initial capacity is less
|
||||
* than zero
|
||||
*/
|
||||
public LinkedHashSet(int initialCapacity) {
|
||||
super(initialCapacity, .75f, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty linked hash set with the default initial
|
||||
* capacity (16) and load factor (0.75).
|
||||
*/
|
||||
public LinkedHashSet() {
|
||||
super(16, .75f, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new linked hash set with the same elements as the
|
||||
* specified collection. The linked hash set is created with an initial
|
||||
* capacity sufficient to hold the elements in the specified collection
|
||||
* and the default load factor (0.75).
|
||||
*
|
||||
* @param c the collection whose elements are to be placed into
|
||||
* this set
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public LinkedHashSet(Collection<? extends E> c) {
|
||||
super(Math.max(2*c.size(), 11), .75f, true);
|
||||
addAll(c);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,775 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* An unbounded priority {@linkplain Queue queue} based on a priority heap.
|
||||
* The elements of the priority queue are ordered according to their
|
||||
* {@linkplain Comparable natural ordering}, or by a {@link Comparator}
|
||||
* provided at queue construction time, depending on which constructor is
|
||||
* used. A priority queue does not permit {@code null} elements.
|
||||
* A priority queue relying on natural ordering also does not permit
|
||||
* insertion of non-comparable objects (doing so may result in
|
||||
* {@code ClassCastException}).
|
||||
*
|
||||
* <p>The <em>head</em> of this queue is the <em>least</em> element
|
||||
* with respect to the specified ordering. If multiple elements are
|
||||
* tied for least value, the head is one of those elements -- ties are
|
||||
* broken arbitrarily. The queue retrieval operations {@code poll},
|
||||
* {@code remove}, {@code peek}, and {@code element} access the
|
||||
* element at the head of the queue.
|
||||
*
|
||||
* <p>A priority queue is unbounded, but has an internal
|
||||
* <i>capacity</i> governing the size of an array used to store the
|
||||
* elements on the queue. It is always at least as large as the queue
|
||||
* size. As elements are added to a priority queue, its capacity
|
||||
* grows automatically. The details of the growth policy are not
|
||||
* specified.
|
||||
*
|
||||
* <p>This class and its iterator implement all of the
|
||||
* <em>optional</em> methods of the {@link Collection} and {@link
|
||||
* Iterator} interfaces. The Iterator provided in method {@link
|
||||
* #iterator()} is <em>not</em> guaranteed to traverse the elements of
|
||||
* the priority queue in any particular order. If you need ordered
|
||||
* traversal, consider using {@code Arrays.sort(pq.toArray())}.
|
||||
*
|
||||
* <p> <strong>Note that this implementation is not synchronized.</strong>
|
||||
* Multiple threads should not access a {@code PriorityQueue}
|
||||
* instance concurrently if any of the threads modifies the queue.
|
||||
* Instead, use the thread-safe {@link
|
||||
* java.util.concurrent.PriorityBlockingQueue} class.
|
||||
*
|
||||
* <p>Implementation note: this implementation provides
|
||||
* O(log(n)) time for the enqueing and dequeing methods
|
||||
* ({@code offer}, {@code poll}, {@code remove()} and {@code add});
|
||||
* linear time for the {@code remove(Object)} and {@code contains(Object)}
|
||||
* methods; and constant time for the retrieval methods
|
||||
* ({@code peek}, {@code element}, and {@code size}).
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Josh Bloch, Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public class PriorityQueue<E> extends AbstractQueue<E>
|
||||
implements java.io.Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7720805057305804111L;
|
||||
|
||||
private static final int DEFAULT_INITIAL_CAPACITY = 11;
|
||||
|
||||
/**
|
||||
* Priority queue represented as a balanced binary heap: the two
|
||||
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
|
||||
* priority queue is ordered by comparator, or by the elements'
|
||||
* natural ordering, if comparator is null: For each node n in the
|
||||
* heap and each descendant d of n, n <= d. The element with the
|
||||
* lowest value is in queue[0], assuming the queue is nonempty.
|
||||
*/
|
||||
private transient Object[] queue;
|
||||
|
||||
/**
|
||||
* The number of elements in the priority queue.
|
||||
*/
|
||||
private int size = 0;
|
||||
|
||||
/**
|
||||
* The comparator, or null if priority queue uses elements'
|
||||
* natural ordering.
|
||||
*/
|
||||
private final Comparator<? super E> comparator;
|
||||
|
||||
/**
|
||||
* The number of times this priority queue has been
|
||||
* <i>structurally modified</i>. See AbstractList for gory details.
|
||||
*/
|
||||
private transient int modCount = 0;
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} with the default initial
|
||||
* capacity (11) that orders its elements according to their
|
||||
* {@linkplain Comparable natural ordering}.
|
||||
*/
|
||||
public PriorityQueue() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} with the specified initial
|
||||
* capacity that orders its elements according to their
|
||||
* {@linkplain Comparable natural ordering}.
|
||||
*
|
||||
* @param initialCapacity the initial capacity for this priority queue
|
||||
* @throws IllegalArgumentException if {@code initialCapacity} is less
|
||||
* than 1
|
||||
*/
|
||||
public PriorityQueue(int initialCapacity) {
|
||||
this(initialCapacity, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} with the specified initial capacity
|
||||
* that orders its elements according to the specified comparator.
|
||||
*
|
||||
* @param initialCapacity the initial capacity for this priority queue
|
||||
* @param comparator the comparator that will be used to order this
|
||||
* priority queue. If {@code null}, the {@linkplain Comparable
|
||||
* natural ordering} of the elements will be used.
|
||||
* @throws IllegalArgumentException if {@code initialCapacity} is
|
||||
* less than 1
|
||||
*/
|
||||
public PriorityQueue(int initialCapacity,
|
||||
Comparator<? super E> comparator) {
|
||||
// Note: This restriction of at least one is not actually needed,
|
||||
// but continues for 1.5 compatibility
|
||||
if (initialCapacity < 1)
|
||||
throw new IllegalArgumentException();
|
||||
this.queue = new Object[initialCapacity];
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} containing the elements in the
|
||||
* specified collection. If the specified collection is an instance of
|
||||
* a {@link SortedSet} or is another {@code PriorityQueue}, this
|
||||
* priority queue will be ordered according to the same ordering.
|
||||
* Otherwise, this priority queue will be ordered according to the
|
||||
* {@linkplain Comparable natural ordering} of its elements.
|
||||
*
|
||||
* @param c the collection whose elements are to be placed
|
||||
* into this priority queue
|
||||
* @throws ClassCastException if elements of the specified collection
|
||||
* cannot be compared to one another according to the priority
|
||||
* queue's ordering
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PriorityQueue(Collection<? extends E> c) {
|
||||
if (c instanceof SortedSet<?>) {
|
||||
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
|
||||
this.comparator = (Comparator<? super E>) ss.comparator();
|
||||
initElementsFromCollection(ss);
|
||||
}
|
||||
else if (c instanceof PriorityQueue<?>) {
|
||||
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
|
||||
this.comparator = (Comparator<? super E>) pq.comparator();
|
||||
initFromPriorityQueue(pq);
|
||||
}
|
||||
else {
|
||||
this.comparator = null;
|
||||
initFromCollection(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} containing the elements in the
|
||||
* specified priority queue. This priority queue will be
|
||||
* ordered according to the same ordering as the given priority
|
||||
* queue.
|
||||
*
|
||||
* @param c the priority queue whose elements are to be placed
|
||||
* into this priority queue
|
||||
* @throws ClassCastException if elements of {@code c} cannot be
|
||||
* compared to one another according to {@code c}'s
|
||||
* ordering
|
||||
* @throws NullPointerException if the specified priority queue or any
|
||||
* of its elements are null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PriorityQueue(PriorityQueue<? extends E> c) {
|
||||
this.comparator = (Comparator<? super E>) c.comparator();
|
||||
initFromPriorityQueue(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PriorityQueue} containing the elements in the
|
||||
* specified sorted set. This priority queue will be ordered
|
||||
* according to the same ordering as the given sorted set.
|
||||
*
|
||||
* @param c the sorted set whose elements are to be placed
|
||||
* into this priority queue
|
||||
* @throws ClassCastException if elements of the specified sorted
|
||||
* set cannot be compared to one another according to the
|
||||
* sorted set's ordering
|
||||
* @throws NullPointerException if the specified sorted set or any
|
||||
* of its elements are null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PriorityQueue(SortedSet<? extends E> c) {
|
||||
this.comparator = (Comparator<? super E>) c.comparator();
|
||||
initElementsFromCollection(c);
|
||||
}
|
||||
|
||||
private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
|
||||
if (c.getClass() == PriorityQueue.class) {
|
||||
this.queue = c.toArray();
|
||||
this.size = c.size();
|
||||
} else {
|
||||
initFromCollection(c);
|
||||
}
|
||||
}
|
||||
|
||||
private void initElementsFromCollection(Collection<? extends E> c) {
|
||||
Object[] a = c.toArray();
|
||||
// If c.toArray incorrectly doesn't return Object[], copy it.
|
||||
if (a.getClass() != Object[].class)
|
||||
a = Arrays.copyOf(a, a.length, Object[].class);
|
||||
int len = a.length;
|
||||
if (len == 1 || this.comparator != null)
|
||||
for (int i = 0; i < len; i++)
|
||||
if (a[i] == null)
|
||||
throw new NullPointerException();
|
||||
this.queue = a;
|
||||
this.size = a.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes queue array with elements from the given Collection.
|
||||
*
|
||||
* @param c the collection
|
||||
*/
|
||||
private void initFromCollection(Collection<? extends E> c) {
|
||||
initElementsFromCollection(c);
|
||||
heapify();
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Increases the capacity of the array.
|
||||
*
|
||||
* @param minCapacity the desired minimum capacity
|
||||
*/
|
||||
private void grow(int minCapacity) {
|
||||
int oldCapacity = queue.length;
|
||||
// Double size if small; else grow by 50%
|
||||
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
|
||||
(oldCapacity + 2) :
|
||||
(oldCapacity >> 1));
|
||||
// overflow-conscious code
|
||||
if (newCapacity - MAX_ARRAY_SIZE > 0)
|
||||
newCapacity = hugeCapacity(minCapacity);
|
||||
queue = Arrays.copyOf(queue, newCapacity);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||
Integer.MAX_VALUE :
|
||||
MAX_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this priority queue.
|
||||
*
|
||||
* @return {@code true} (as specified by {@link Collection#add})
|
||||
* @throws ClassCastException if the specified element cannot be
|
||||
* compared with elements currently in this priority queue
|
||||
* according to the priority queue's ordering
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return offer(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this priority queue.
|
||||
*
|
||||
* @return {@code true} (as specified by {@link Queue#offer})
|
||||
* @throws ClassCastException if the specified element cannot be
|
||||
* compared with elements currently in this priority queue
|
||||
* according to the priority queue's ordering
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean offer(E e) {
|
||||
if (e == null)
|
||||
throw new NullPointerException();
|
||||
modCount++;
|
||||
int i = size;
|
||||
if (i >= queue.length)
|
||||
grow(i + 1);
|
||||
size = i + 1;
|
||||
if (i == 0)
|
||||
queue[0] = e;
|
||||
else
|
||||
siftUp(i, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
public E peek() {
|
||||
if (size == 0)
|
||||
return null;
|
||||
return (E) queue[0];
|
||||
}
|
||||
|
||||
private int indexOf(Object o) {
|
||||
if (o != null) {
|
||||
for (int i = 0; i < size; i++)
|
||||
if (o.equals(queue[i]))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this queue,
|
||||
* if it is present. More formally, removes an element {@code e} such
|
||||
* that {@code o.equals(e)}, if this queue contains one or more such
|
||||
* elements. Returns {@code true} if and only if this queue contained
|
||||
* the specified element (or equivalently, if this queue changed as a
|
||||
* result of the call).
|
||||
*
|
||||
* @param o element to be removed from this queue, if present
|
||||
* @return {@code true} if this queue changed as a result of the call
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
int i = indexOf(o);
|
||||
if (i == -1)
|
||||
return false;
|
||||
else {
|
||||
removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of remove using reference equality, not equals.
|
||||
* Needed by iterator.remove.
|
||||
*
|
||||
* @param o element to be removed from this queue, if present
|
||||
* @return {@code true} if removed
|
||||
*/
|
||||
boolean removeEq(Object o) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (o == queue[i]) {
|
||||
removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this queue contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this queue contains
|
||||
* at least one element {@code e} such that {@code o.equals(e)}.
|
||||
*
|
||||
* @param o object to be checked for containment in this queue
|
||||
* @return {@code true} if this queue contains the specified element
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return indexOf(o) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue.
|
||||
* The elements are in no particular order.
|
||||
*
|
||||
* <p>The returned array will be "safe" in that no references to it are
|
||||
* maintained by this queue. (In other words, this method must allocate
|
||||
* a new array). The caller is thus free to modify the returned array.
|
||||
*
|
||||
* <p>This method acts as bridge between array-based and collection-based
|
||||
* APIs.
|
||||
*
|
||||
* @return an array containing all of the elements in this queue
|
||||
*/
|
||||
public Object[] toArray() {
|
||||
return Arrays.copyOf(queue, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue; the
|
||||
* runtime type of the returned array is that of the specified array.
|
||||
* The returned array elements are in no particular order.
|
||||
* If the queue fits in the specified array, it is returned therein.
|
||||
* Otherwise, a new array is allocated with the runtime type of the
|
||||
* specified array and the size of this queue.
|
||||
*
|
||||
* <p>If the queue fits in the specified array with room to spare
|
||||
* (i.e., the array has more elements than the queue), the element in
|
||||
* the array immediately following the end of the collection is set to
|
||||
* {@code null}.
|
||||
*
|
||||
* <p>Like the {@link #toArray()} method, this method acts as bridge between
|
||||
* array-based and collection-based APIs. Further, this method allows
|
||||
* precise control over the runtime type of the output array, and may,
|
||||
* under certain circumstances, be used to save allocation costs.
|
||||
*
|
||||
* <p>Suppose <tt>x</tt> is a queue known to contain only strings.
|
||||
* The following code can be used to dump the queue into a newly
|
||||
* allocated array of <tt>String</tt>:
|
||||
*
|
||||
* <pre>
|
||||
* String[] y = x.toArray(new String[0]);</pre>
|
||||
*
|
||||
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
|
||||
* <tt>toArray()</tt>.
|
||||
*
|
||||
* @param a the array into which the elements of the queue are to
|
||||
* be stored, if it is big enough; otherwise, a new array of the
|
||||
* same runtime type is allocated for this purpose.
|
||||
* @return an array containing all of the elements in this queue
|
||||
* @throws ArrayStoreException if the runtime type of the specified array
|
||||
* is not a supertype of the runtime type of every element in
|
||||
* this queue
|
||||
* @throws NullPointerException if the specified array is null
|
||||
*/
|
||||
public <T> T[] toArray(T[] a) {
|
||||
if (a.length < size)
|
||||
// Make a new array of a's runtime type, but my contents:
|
||||
return (T[]) Arrays.copyOf(queue, size, a.getClass());
|
||||
System.arraycopy(queue, 0, a, 0, size);
|
||||
if (a.length > size)
|
||||
a[size] = null;
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this queue. The iterator
|
||||
* does not return the elements in any particular order.
|
||||
*
|
||||
* @return an iterator over the elements in this queue
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return new Itr();
|
||||
}
|
||||
|
||||
private final class Itr implements Iterator<E> {
|
||||
/**
|
||||
* Index (into queue array) of element to be returned by
|
||||
* subsequent call to next.
|
||||
*/
|
||||
private int cursor = 0;
|
||||
|
||||
/**
|
||||
* Index of element returned by most recent call to next,
|
||||
* unless that element came from the forgetMeNot list.
|
||||
* Set to -1 if element is deleted by a call to remove.
|
||||
*/
|
||||
private int lastRet = -1;
|
||||
|
||||
/**
|
||||
* A queue of elements that were moved from the unvisited portion of
|
||||
* the heap into the visited portion as a result of "unlucky" element
|
||||
* removals during the iteration. (Unlucky element removals are those
|
||||
* that require a siftup instead of a siftdown.) We must visit all of
|
||||
* the elements in this list to complete the iteration. We do this
|
||||
* after we've completed the "normal" iteration.
|
||||
*
|
||||
* We expect that most iterations, even those involving removals,
|
||||
* will not need to store elements in this field.
|
||||
*/
|
||||
private ArrayDeque<E> forgetMeNot = null;
|
||||
|
||||
/**
|
||||
* Element returned by the most recent call to next iff that
|
||||
* element was drawn from the forgetMeNot list.
|
||||
*/
|
||||
private E lastRetElt = null;
|
||||
|
||||
/**
|
||||
* The modCount value that the iterator believes that the backing
|
||||
* Queue should have. If this expectation is violated, the iterator
|
||||
* has detected concurrent modification.
|
||||
*/
|
||||
private int expectedModCount = modCount;
|
||||
|
||||
public boolean hasNext() {
|
||||
return cursor < size ||
|
||||
(forgetMeNot != null && !forgetMeNot.isEmpty());
|
||||
}
|
||||
|
||||
public E next() {
|
||||
if (expectedModCount != modCount)
|
||||
throw new ConcurrentModificationException();
|
||||
if (cursor < size)
|
||||
return (E) queue[lastRet = cursor++];
|
||||
if (forgetMeNot != null) {
|
||||
lastRet = -1;
|
||||
lastRetElt = forgetMeNot.poll();
|
||||
if (lastRetElt != null)
|
||||
return lastRetElt;
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (expectedModCount != modCount)
|
||||
throw new ConcurrentModificationException();
|
||||
if (lastRet != -1) {
|
||||
E moved = PriorityQueue.this.removeAt(lastRet);
|
||||
lastRet = -1;
|
||||
if (moved == null)
|
||||
cursor--;
|
||||
else {
|
||||
if (forgetMeNot == null)
|
||||
forgetMeNot = new ArrayDeque<>();
|
||||
forgetMeNot.add(moved);
|
||||
}
|
||||
} else if (lastRetElt != null) {
|
||||
PriorityQueue.this.removeEq(lastRetElt);
|
||||
lastRetElt = null;
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
expectedModCount = modCount;
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this priority queue.
|
||||
* The queue will be empty after this call returns.
|
||||
*/
|
||||
public void clear() {
|
||||
modCount++;
|
||||
for (int i = 0; i < size; i++)
|
||||
queue[i] = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public E poll() {
|
||||
if (size == 0)
|
||||
return null;
|
||||
int s = --size;
|
||||
modCount++;
|
||||
E result = (E) queue[0];
|
||||
E x = (E) queue[s];
|
||||
queue[s] = null;
|
||||
if (s != 0)
|
||||
siftDown(0, x);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the ith element from queue.
|
||||
*
|
||||
* Normally this method leaves the elements at up to i-1,
|
||||
* inclusive, untouched. Under these circumstances, it returns
|
||||
* null. Occasionally, in order to maintain the heap invariant,
|
||||
* it must swap a later element of the list with one earlier than
|
||||
* i. Under these circumstances, this method returns the element
|
||||
* that was previously at the end of the list and is now at some
|
||||
* position before i. This fact is used by iterator.remove so as to
|
||||
* avoid missing traversing elements.
|
||||
*/
|
||||
private E removeAt(int i) {
|
||||
assert i >= 0 && i < size;
|
||||
modCount++;
|
||||
int s = --size;
|
||||
if (s == i) // removed last element
|
||||
queue[i] = null;
|
||||
else {
|
||||
E moved = (E) queue[s];
|
||||
queue[s] = null;
|
||||
siftDown(i, moved);
|
||||
if (queue[i] == moved) {
|
||||
siftUp(i, moved);
|
||||
if (queue[i] != moved)
|
||||
return moved;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts item x at position k, maintaining heap invariant by
|
||||
* promoting x up the tree until it is greater than or equal to
|
||||
* its parent, or is the root.
|
||||
*
|
||||
* To simplify and speed up coercions and comparisons. the
|
||||
* Comparable and Comparator versions are separated into different
|
||||
* methods that are otherwise identical. (Similarly for siftDown.)
|
||||
*
|
||||
* @param k the position to fill
|
||||
* @param x the item to insert
|
||||
*/
|
||||
private void siftUp(int k, E x) {
|
||||
if (comparator != null)
|
||||
siftUpUsingComparator(k, x);
|
||||
else
|
||||
siftUpComparable(k, x);
|
||||
}
|
||||
|
||||
private void siftUpComparable(int k, E x) {
|
||||
Comparable<? super E> key = (Comparable<? super E>) x;
|
||||
while (k > 0) {
|
||||
int parent = (k - 1) >>> 1;
|
||||
Object e = queue[parent];
|
||||
if (key.compareTo((E) e) >= 0)
|
||||
break;
|
||||
queue[k] = e;
|
||||
k = parent;
|
||||
}
|
||||
queue[k] = key;
|
||||
}
|
||||
|
||||
private void siftUpUsingComparator(int k, E x) {
|
||||
while (k > 0) {
|
||||
int parent = (k - 1) >>> 1;
|
||||
Object e = queue[parent];
|
||||
if (comparator.compare(x, (E) e) >= 0)
|
||||
break;
|
||||
queue[k] = e;
|
||||
k = parent;
|
||||
}
|
||||
queue[k] = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts item x at position k, maintaining heap invariant by
|
||||
* demoting x down the tree repeatedly until it is less than or
|
||||
* equal to its children or is a leaf.
|
||||
*
|
||||
* @param k the position to fill
|
||||
* @param x the item to insert
|
||||
*/
|
||||
private void siftDown(int k, E x) {
|
||||
if (comparator != null)
|
||||
siftDownUsingComparator(k, x);
|
||||
else
|
||||
siftDownComparable(k, x);
|
||||
}
|
||||
|
||||
private void siftDownComparable(int k, E x) {
|
||||
Comparable<? super E> key = (Comparable<? super E>)x;
|
||||
int half = size >>> 1; // loop while a non-leaf
|
||||
while (k < half) {
|
||||
int child = (k << 1) + 1; // assume left child is least
|
||||
Object c = queue[child];
|
||||
int right = child + 1;
|
||||
if (right < size &&
|
||||
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
|
||||
c = queue[child = right];
|
||||
if (key.compareTo((E) c) <= 0)
|
||||
break;
|
||||
queue[k] = c;
|
||||
k = child;
|
||||
}
|
||||
queue[k] = key;
|
||||
}
|
||||
|
||||
private void siftDownUsingComparator(int k, E x) {
|
||||
int half = size >>> 1;
|
||||
while (k < half) {
|
||||
int child = (k << 1) + 1;
|
||||
Object c = queue[child];
|
||||
int right = child + 1;
|
||||
if (right < size &&
|
||||
comparator.compare((E) c, (E) queue[right]) > 0)
|
||||
c = queue[child = right];
|
||||
if (comparator.compare(x, (E) c) <= 0)
|
||||
break;
|
||||
queue[k] = c;
|
||||
k = child;
|
||||
}
|
||||
queue[k] = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the heap invariant (described above) in the entire tree,
|
||||
* assuming nothing about the order of the elements prior to the call.
|
||||
*/
|
||||
private void heapify() {
|
||||
for (int i = (size >>> 1) - 1; i >= 0; i--)
|
||||
siftDown(i, (E) queue[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the comparator used to order the elements in this
|
||||
* queue, or {@code null} if this queue is sorted according to
|
||||
* the {@linkplain Comparable natural ordering} of its elements.
|
||||
*
|
||||
* @return the comparator used to order this queue, or
|
||||
* {@code null} if this queue is sorted according to the
|
||||
* natural ordering of its elements
|
||||
*/
|
||||
public Comparator<? super E> comparator() {
|
||||
return comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the state of the instance to a stream (that
|
||||
* is, serializes it).
|
||||
*
|
||||
* @serialData The length of the array backing the instance is
|
||||
* emitted (int), followed by all of its elements
|
||||
* (each an {@code Object}) in the proper order.
|
||||
* @param s the stream
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException{
|
||||
// Write out element count, and any hidden stuff
|
||||
s.defaultWriteObject();
|
||||
|
||||
// Write out array length, for compatibility with 1.5 version
|
||||
s.writeInt(Math.max(2, size + 1));
|
||||
|
||||
// Write out all elements in the "proper order".
|
||||
for (int i = 0; i < size; i++)
|
||||
s.writeObject(queue[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the {@code PriorityQueue} instance from a stream
|
||||
* (that is, deserializes it).
|
||||
*
|
||||
* @param s the stream
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
// Read in size, and any hidden stuff
|
||||
s.defaultReadObject();
|
||||
|
||||
// Read in (and discard) array length
|
||||
s.readInt();
|
||||
|
||||
queue = new Object[size];
|
||||
|
||||
// Read in all elements.
|
||||
for (int i = 0; i < size; i++)
|
||||
queue[i] = s.readObject();
|
||||
|
||||
// Elements are guaranteed to be in "proper order", but the
|
||||
// spec has never explained what that might be.
|
||||
heapify();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* A collection designed for holding elements prior to processing.
|
||||
* Besides basic {@link java.util.Collection Collection} operations,
|
||||
* queues provide additional insertion, extraction, and inspection
|
||||
* operations. Each of these methods exists in two forms: one throws
|
||||
* an exception if the operation fails, the other returns a special
|
||||
* value (either <tt>null</tt> or <tt>false</tt>, depending on the
|
||||
* operation). The latter form of the insert operation is designed
|
||||
* specifically for use with capacity-restricted <tt>Queue</tt>
|
||||
* implementations; in most implementations, insert operations cannot
|
||||
* fail.
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Returns special value</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #add add(e)}</td>
|
||||
* <td>{@link #offer offer(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #remove remove()}</td>
|
||||
* <td>{@link #poll poll()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #element element()}</td>
|
||||
* <td>{@link #peek peek()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Queues typically, but do not necessarily, order elements in a
|
||||
* FIFO (first-in-first-out) manner. Among the exceptions are
|
||||
* priority queues, which order elements according to a supplied
|
||||
* comparator, or the elements' natural ordering, and LIFO queues (or
|
||||
* stacks) which order the elements LIFO (last-in-first-out).
|
||||
* Whatever the ordering used, the <em>head</em> of the queue is that
|
||||
* element which would be removed by a call to {@link #remove() } or
|
||||
* {@link #poll()}. In a FIFO queue, all new elements are inserted at
|
||||
* the <em> tail</em> of the queue. Other kinds of queues may use
|
||||
* different placement rules. Every <tt>Queue</tt> implementation
|
||||
* must specify its ordering properties.
|
||||
*
|
||||
* <p>The {@link #offer offer} method inserts an element if possible,
|
||||
* otherwise returning <tt>false</tt>. This differs from the {@link
|
||||
* java.util.Collection#add Collection.add} method, which can fail to
|
||||
* add an element only by throwing an unchecked exception. The
|
||||
* <tt>offer</tt> method is designed for use when failure is a normal,
|
||||
* rather than exceptional occurrence, for example, in fixed-capacity
|
||||
* (or "bounded") queues.
|
||||
*
|
||||
* <p>The {@link #remove()} and {@link #poll()} methods remove and
|
||||
* return the head of the queue.
|
||||
* Exactly which element is removed from the queue is a
|
||||
* function of the queue's ordering policy, which differs from
|
||||
* implementation to implementation. The <tt>remove()</tt> and
|
||||
* <tt>poll()</tt> methods differ only in their behavior when the
|
||||
* queue is empty: the <tt>remove()</tt> method throws an exception,
|
||||
* while the <tt>poll()</tt> method returns <tt>null</tt>.
|
||||
*
|
||||
* <p>The {@link #element()} and {@link #peek()} methods return, but do
|
||||
* not remove, the head of the queue.
|
||||
*
|
||||
* <p>The <tt>Queue</tt> interface does not define the <i>blocking queue
|
||||
* methods</i>, which are common in concurrent programming. These methods,
|
||||
* which wait for elements to appear or for space to become available, are
|
||||
* defined in the {@link java.util.concurrent.BlockingQueue} interface, which
|
||||
* extends this interface.
|
||||
*
|
||||
* <p><tt>Queue</tt> implementations generally do not allow insertion
|
||||
* of <tt>null</tt> elements, although some implementations, such as
|
||||
* {@link LinkedList}, do not prohibit insertion of <tt>null</tt>.
|
||||
* Even in the implementations that permit it, <tt>null</tt> should
|
||||
* not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also
|
||||
* used as a special return value by the <tt>poll</tt> method to
|
||||
* indicate that the queue contains no elements.
|
||||
*
|
||||
* <p><tt>Queue</tt> implementations generally do not define
|
||||
* element-based versions of methods <tt>equals</tt> and
|
||||
* <tt>hashCode</tt> but instead inherit the identity based versions
|
||||
* from class <tt>Object</tt>, because element-based equality is not
|
||||
* always well-defined for queues with the same elements but different
|
||||
* ordering properties.
|
||||
*
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @see java.util.Collection
|
||||
* @see LinkedList
|
||||
* @see PriorityQueue
|
||||
* @see java.util.concurrent.LinkedBlockingQueue
|
||||
* @see java.util.concurrent.BlockingQueue
|
||||
* @see java.util.concurrent.ArrayBlockingQueue
|
||||
* @see java.util.concurrent.LinkedBlockingQueue
|
||||
* @see java.util.concurrent.PriorityBlockingQueue
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public interface Queue<E> extends Collection<E> {
|
||||
/**
|
||||
* Inserts the specified element into this queue if it is possible to do so
|
||||
* immediately without violating capacity restrictions, returning
|
||||
* <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
|
||||
* if no space is currently available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return <tt>true</tt> (as specified by {@link Collection#add})
|
||||
* @throws IllegalStateException if the element cannot be added at this
|
||||
* time due to capacity restrictions
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null and
|
||||
* this queue does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of this element
|
||||
* prevents it from being added to this queue
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue if it is possible to do
|
||||
* so immediately without violating capacity restrictions.
|
||||
* When using a capacity-restricted queue, this method is generally
|
||||
* preferable to {@link #add}, which can fail to insert an element only
|
||||
* by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return <tt>true</tt> if the element was added to this queue, else
|
||||
* <tt>false</tt>
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null and
|
||||
* this queue does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of this element
|
||||
* prevents it from being added to this queue
|
||||
*/
|
||||
boolean offer(E e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue. This method differs
|
||||
* from {@link #poll poll} only in that it throws an exception if this
|
||||
* queue is empty.
|
||||
*
|
||||
* @return the head of this queue
|
||||
* @throws NoSuchElementException if this queue is empty
|
||||
*/
|
||||
E remove();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue,
|
||||
* or returns <tt>null</tt> if this queue is empty.
|
||||
*
|
||||
* @return the head of this queue, or <tt>null</tt> if this queue is empty
|
||||
*/
|
||||
E poll();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue. This method
|
||||
* differs from {@link #peek peek} only in that it throws an exception
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @return the head of this queue
|
||||
* @throws NoSuchElementException if this queue is empty
|
||||
*/
|
||||
E element();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue,
|
||||
* or returns <tt>null</tt> if this queue is empty.
|
||||
*
|
||||
* @return the head of this queue, or <tt>null</tt> if this queue is empty
|
||||
*/
|
||||
E peek();
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* The <code>Stack</code> class represents a last-in-first-out
|
||||
* (LIFO) stack of objects. It extends class <tt>Vector</tt> with five
|
||||
* operations that allow a vector to be treated as a stack. The usual
|
||||
* <tt>push</tt> and <tt>pop</tt> operations are provided, as well as a
|
||||
* method to <tt>peek</tt> at the top item on the stack, a method to test
|
||||
* for whether the stack is <tt>empty</tt>, and a method to <tt>search</tt>
|
||||
* the stack for an item and discover how far it is from the top.
|
||||
* <p>
|
||||
* When a stack is first created, it contains no items.
|
||||
*
|
||||
* <p>A more complete and consistent set of LIFO stack operations is
|
||||
* provided by the {@link Deque} interface and its implementations, which
|
||||
* should be used in preference to this class. For example:
|
||||
* <pre> {@code
|
||||
* Deque<Integer> stack = new ArrayDeque<Integer>();}</pre>
|
||||
*
|
||||
* @author Jonathan Payne
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public
|
||||
class Stack<E> extends Vector<E> {
|
||||
/**
|
||||
* Creates an empty Stack.
|
||||
*/
|
||||
public Stack() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes an item onto the top of this stack. This has exactly
|
||||
* the same effect as:
|
||||
* <blockquote><pre>
|
||||
* addElement(item)</pre></blockquote>
|
||||
*
|
||||
* @param item the item to be pushed onto this stack.
|
||||
* @return the <code>item</code> argument.
|
||||
* @see java.util.Vector#addElement
|
||||
*/
|
||||
public E push(E item) {
|
||||
addElement(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the object at the top of this stack and returns that
|
||||
* object as the value of this function.
|
||||
*
|
||||
* @return The object at the top of this stack (the last item
|
||||
* of the <tt>Vector</tt> object).
|
||||
* @throws EmptyStackException if this stack is empty.
|
||||
*/
|
||||
public synchronized E pop() {
|
||||
E obj;
|
||||
int len = size();
|
||||
|
||||
obj = peek();
|
||||
removeElementAt(len - 1);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks at the object at the top of this stack without removing it
|
||||
* from the stack.
|
||||
*
|
||||
* @return the object at the top of this stack (the last item
|
||||
* of the <tt>Vector</tt> object).
|
||||
* @throws EmptyStackException if this stack is empty.
|
||||
*/
|
||||
public synchronized E peek() {
|
||||
int len = size();
|
||||
|
||||
if (len == 0)
|
||||
throw new EmptyStackException();
|
||||
return elementAt(len - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this stack is empty.
|
||||
*
|
||||
* @return <code>true</code> if and only if this stack contains
|
||||
* no items; <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean empty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 1-based position where an object is on this stack.
|
||||
* If the object <tt>o</tt> occurs as an item in this stack, this
|
||||
* method returns the distance from the top of the stack of the
|
||||
* occurrence nearest the top of the stack; the topmost item on the
|
||||
* stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>
|
||||
* method is used to compare <tt>o</tt> to the
|
||||
* items in this stack.
|
||||
*
|
||||
* @param o the desired object.
|
||||
* @return the 1-based position from the top of the stack where
|
||||
* the object is located; the return value <code>-1</code>
|
||||
* indicates that the object is not on the stack.
|
||||
*/
|
||||
public synchronized int search(Object o) {
|
||||
int i = lastIndexOf(o);
|
||||
|
||||
if (i >= 0) {
|
||||
return size() - i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** use serialVersionUID from JDK 1.0.2 for interoperability */
|
||||
private static final long serialVersionUID = 1224463164541339165L;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* A {@link NavigableSet} implementation based on a {@link TreeMap}.
|
||||
* The elements are ordered using their {@linkplain Comparable natural
|
||||
* ordering}, or by a {@link Comparator} provided at set creation
|
||||
* time, depending on which constructor is used.
|
||||
*
|
||||
* <p>This implementation provides guaranteed log(n) time cost for the basic
|
||||
* operations ({@code add}, {@code remove} and {@code contains}).
|
||||
*
|
||||
* <p>Note that the ordering maintained by a set (whether or not an explicit
|
||||
* comparator is provided) must be <i>consistent with equals</i> if it is to
|
||||
* correctly implement the {@code Set} interface. (See {@code Comparable}
|
||||
* or {@code Comparator} for a precise definition of <i>consistent with
|
||||
* equals</i>.) This is so because the {@code Set} interface is defined in
|
||||
* terms of the {@code equals} operation, but a {@code TreeSet} instance
|
||||
* performs all element comparisons using its {@code compareTo} (or
|
||||
* {@code compare}) method, so two elements that are deemed equal by this method
|
||||
* are, from the standpoint of the set, equal. The behavior of a set
|
||||
* <i>is</i> well-defined even if its ordering is inconsistent with equals; it
|
||||
* just fails to obey the general contract of the {@code Set} interface.
|
||||
*
|
||||
* <p><strong>Note that this implementation is not synchronized.</strong>
|
||||
* If multiple threads access a tree set concurrently, and at least one
|
||||
* of the threads modifies the set, it <i>must</i> be synchronized
|
||||
* externally. This is typically accomplished by synchronizing on some
|
||||
* object that naturally encapsulates the set.
|
||||
* If no such object exists, the set should be "wrapped" using the
|
||||
* {@link Collections#synchronizedSortedSet Collections.synchronizedSortedSet}
|
||||
* method. This is best done at creation time, to prevent accidental
|
||||
* unsynchronized access to the set: <pre>
|
||||
* SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));</pre>
|
||||
*
|
||||
* <p>The iterators returned by this class's {@code iterator} method are
|
||||
* <i>fail-fast</i>: if the set is modified at any time after the iterator is
|
||||
* created, in any way except through the iterator's own {@code remove}
|
||||
* method, the iterator will throw a {@link ConcurrentModificationException}.
|
||||
* Thus, in the face of concurrent modification, the iterator fails quickly
|
||||
* and cleanly, rather than risking arbitrary, non-deterministic behavior at
|
||||
* an undetermined time in the future.
|
||||
*
|
||||
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
* as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
* presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
* throw {@code ConcurrentModificationException} on a best-effort basis.
|
||||
* Therefore, it would be wrong to write a program that depended on this
|
||||
* exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
* should be used only to detect bugs.</i>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <E> the type of elements maintained by this set
|
||||
*
|
||||
* @author Josh Bloch
|
||||
* @see Collection
|
||||
* @see Set
|
||||
* @see HashSet
|
||||
* @see Comparable
|
||||
* @see Comparator
|
||||
* @see TreeMap
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class TreeSet<E> extends AbstractSet<E>
|
||||
implements NavigableSet<E>, Cloneable, java.io.Serializable
|
||||
{
|
||||
/**
|
||||
* The backing map.
|
||||
*/
|
||||
private transient NavigableMap<E,Object> m;
|
||||
|
||||
// Dummy value to associate with an Object in the backing Map
|
||||
private static final Object PRESENT = new Object();
|
||||
|
||||
/**
|
||||
* Constructs a set backed by the specified navigable map.
|
||||
*/
|
||||
TreeSet(NavigableMap<E,Object> m) {
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty tree set, sorted according to the
|
||||
* natural ordering of its elements. All elements inserted into
|
||||
* the set must implement the {@link Comparable} interface.
|
||||
* Furthermore, all such elements must be <i>mutually
|
||||
* comparable</i>: {@code e1.compareTo(e2)} must not throw a
|
||||
* {@code ClassCastException} for any elements {@code e1} and
|
||||
* {@code e2} in the set. If the user attempts to add an element
|
||||
* to the set that violates this constraint (for example, the user
|
||||
* attempts to add a string element to a set whose elements are
|
||||
* integers), the {@code add} call will throw a
|
||||
* {@code ClassCastException}.
|
||||
*/
|
||||
public TreeSet() {
|
||||
this(new TreeMap<E,Object>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty tree set, sorted according to the specified
|
||||
* comparator. All elements inserted into the set must be <i>mutually
|
||||
* comparable</i> by the specified comparator: {@code comparator.compare(e1,
|
||||
* e2)} must not throw a {@code ClassCastException} for any elements
|
||||
* {@code e1} and {@code e2} in the set. If the user attempts to add
|
||||
* an element to the set that violates this constraint, the
|
||||
* {@code add} call will throw a {@code ClassCastException}.
|
||||
*
|
||||
* @param comparator the comparator that will be used to order this set.
|
||||
* If {@code null}, the {@linkplain Comparable natural
|
||||
* ordering} of the elements will be used.
|
||||
*/
|
||||
public TreeSet(Comparator<? super E> comparator) {
|
||||
this(new TreeMap<>(comparator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new tree set containing the elements in the specified
|
||||
* collection, sorted according to the <i>natural ordering</i> of its
|
||||
* elements. All elements inserted into the set must implement the
|
||||
* {@link Comparable} interface. Furthermore, all such elements must be
|
||||
* <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
|
||||
* {@code ClassCastException} for any elements {@code e1} and
|
||||
* {@code e2} in the set.
|
||||
*
|
||||
* @param c collection whose elements will comprise the new set
|
||||
* @throws ClassCastException if the elements in {@code c} are
|
||||
* not {@link Comparable}, or are not mutually comparable
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public TreeSet(Collection<? extends E> c) {
|
||||
this();
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new tree set containing the same elements and
|
||||
* using the same ordering as the specified sorted set.
|
||||
*
|
||||
* @param s sorted set whose elements will comprise the new set
|
||||
* @throws NullPointerException if the specified sorted set is null
|
||||
*/
|
||||
public TreeSet(SortedSet<E> s) {
|
||||
this(s.comparator());
|
||||
addAll(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set in ascending order.
|
||||
*
|
||||
* @return an iterator over the elements in this set in ascending order
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return m.navigableKeySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set in descending order.
|
||||
*
|
||||
* @return an iterator over the elements in this set in descending order
|
||||
* @since 1.6
|
||||
*/
|
||||
public Iterator<E> descendingIterator() {
|
||||
return m.descendingKeySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
*/
|
||||
public NavigableSet<E> descendingSet() {
|
||||
return new TreeSet<>(m.descendingMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set (its cardinality).
|
||||
*
|
||||
* @return the number of elements in this set (its cardinality)
|
||||
*/
|
||||
public int size() {
|
||||
return m.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains no elements.
|
||||
*
|
||||
* @return {@code true} if this set contains no elements
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return m.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this set
|
||||
* contains an element {@code e} such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>.
|
||||
*
|
||||
* @param o object to be checked for containment in this set
|
||||
* @return {@code true} if this set contains the specified element
|
||||
* @throws ClassCastException if the specified object cannot be compared
|
||||
* with the elements currently in the set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return m.containsKey(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already present.
|
||||
* More formally, adds the specified element {@code e} to this set if
|
||||
* the set contains no element {@code e2} such that
|
||||
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
|
||||
* If this set already contains the element, the call leaves the set
|
||||
* unchanged and returns {@code false}.
|
||||
*
|
||||
* @param e element to be added to this set
|
||||
* @return {@code true} if this set did not already contain the specified
|
||||
* element
|
||||
* @throws ClassCastException if the specified object cannot be compared
|
||||
* with the elements currently in this set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return m.put(e, PRESENT)==null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from this set if it is present.
|
||||
* More formally, removes an element {@code e} such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>,
|
||||
* if this set contains such an element. Returns {@code true} if
|
||||
* this set contained the element (or equivalently, if this set
|
||||
* changed as a result of the call). (This set will not contain the
|
||||
* element once the call returns.)
|
||||
*
|
||||
* @param o object to be removed from this set, if present
|
||||
* @return {@code true} if this set contained the specified element
|
||||
* @throws ClassCastException if the specified object cannot be compared
|
||||
* with the elements currently in this set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return m.remove(o)==PRESENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
* The set will be empty after this call returns.
|
||||
*/
|
||||
public void clear() {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the elements in the specified collection to this set.
|
||||
*
|
||||
* @param c collection containing elements to be added to this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws ClassCastException if the elements provided cannot be compared
|
||||
* with the elements currently in the set
|
||||
* @throws NullPointerException if the specified collection is null or
|
||||
* if any element is null and this set uses natural ordering, or
|
||||
* its comparator does not permit null elements
|
||||
*/
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
// Use linear-time version if applicable
|
||||
if (m.size()==0 && c.size() > 0 &&
|
||||
c instanceof SortedSet &&
|
||||
m instanceof TreeMap) {
|
||||
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
|
||||
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
|
||||
Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
|
||||
Comparator<? super E> mc = map.comparator();
|
||||
if (cc==mc || (cc != null && cc.equals(mc))) {
|
||||
map.addAllForTreeSet(set, PRESENT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} or {@code toElement}
|
||||
* is null and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @since 1.6
|
||||
*/
|
||||
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
|
||||
E toElement, boolean toInclusive) {
|
||||
return new TreeSet<>(m.subMap(fromElement, fromInclusive,
|
||||
toElement, toInclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code toElement} is null and
|
||||
* this set uses natural ordering, or its comparator does
|
||||
* not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @since 1.6
|
||||
*/
|
||||
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
||||
return new TreeSet<>(m.headMap(toElement, inclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} is null and
|
||||
* this set uses natural ordering, or its comparator does
|
||||
* not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @since 1.6
|
||||
*/
|
||||
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
||||
return new TreeSet<>(m.tailMap(fromElement, inclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} or
|
||||
* {@code toElement} is null and this set uses natural ordering,
|
||||
* or its comparator does not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public SortedSet<E> subSet(E fromElement, E toElement) {
|
||||
return subSet(fromElement, true, toElement, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code toElement} is null
|
||||
* and this set uses natural ordering, or its comparator does
|
||||
* not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public SortedSet<E> headSet(E toElement) {
|
||||
return headSet(toElement, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} is null
|
||||
* and this set uses natural ordering, or its comparator does
|
||||
* not permit null elements
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public SortedSet<E> tailSet(E fromElement) {
|
||||
return tailSet(fromElement, true);
|
||||
}
|
||||
|
||||
public Comparator<? super E> comparator() {
|
||||
return m.comparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoSuchElementException {@inheritDoc}
|
||||
*/
|
||||
public E first() {
|
||||
return m.firstKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoSuchElementException {@inheritDoc}
|
||||
*/
|
||||
public E last() {
|
||||
return m.lastKey();
|
||||
}
|
||||
|
||||
// NavigableSet API methods
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
* @since 1.6
|
||||
*/
|
||||
public E lower(E e) {
|
||||
return m.lowerKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
* @since 1.6
|
||||
*/
|
||||
public E floor(E e) {
|
||||
return m.floorKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
* @since 1.6
|
||||
*/
|
||||
public E ceiling(E e) {
|
||||
return m.ceilingKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* and this set uses natural ordering, or its comparator
|
||||
* does not permit null elements
|
||||
* @since 1.6
|
||||
*/
|
||||
public E higher(E e) {
|
||||
return m.higherKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
*/
|
||||
public E pollFirst() {
|
||||
Map.Entry<E,?> e = m.pollFirstEntry();
|
||||
return (e == null) ? null : e.getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
*/
|
||||
public E pollLast() {
|
||||
Map.Entry<E,?> e = m.pollLastEntry();
|
||||
return (e == null) ? null : e.getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of this {@code TreeSet} instance. (The elements
|
||||
* themselves are not cloned.)
|
||||
*
|
||||
* @return a shallow copy of this set
|
||||
*/
|
||||
public Object clone() {
|
||||
TreeSet<E> clone = null;
|
||||
try {
|
||||
clone = (TreeSet<E>) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
clone.m = new TreeMap<>(m);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the state of the {@code TreeSet} instance to a stream (that is,
|
||||
* serialize it).
|
||||
*
|
||||
* @serialData Emits the comparator used to order this set, or
|
||||
* {@code null} if it obeys its elements' natural ordering
|
||||
* (Object), followed by the size of the set (the number of
|
||||
* elements it contains) (int), followed by all of its
|
||||
* elements (each an Object) in order (as determined by the
|
||||
* set's Comparator, or by the elements' natural ordering if
|
||||
* the set has no Comparator).
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException {
|
||||
// Write out any hidden stuff
|
||||
s.defaultWriteObject();
|
||||
|
||||
// Write out Comparator
|
||||
s.writeObject(m.comparator());
|
||||
|
||||
// Write out size
|
||||
s.writeInt(m.size());
|
||||
|
||||
// Write out all elements in the proper order.
|
||||
for (E e : m.keySet())
|
||||
s.writeObject(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitute the {@code TreeSet} instance from a stream (that is,
|
||||
* deserialize it).
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
// Read in any hidden stuff
|
||||
s.defaultReadObject();
|
||||
|
||||
// Read in Comparator
|
||||
Comparator<? super E> c = (Comparator<? super E>) s.readObject();
|
||||
|
||||
// Create backing TreeMap
|
||||
TreeMap<E,Object> tm;
|
||||
if (c==null)
|
||||
tm = new TreeMap<>();
|
||||
else
|
||||
tm = new TreeMap<>(c);
|
||||
m = tm;
|
||||
|
||||
// Read in size
|
||||
int size = s.readInt();
|
||||
|
||||
tm.readTreeSet(size, s, PRESENT);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -2479143000061671589L;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue