Move more system contact info into recipient database
1) Move contact URI, contact photo URI, and custom label into recipient database, so there are no longer any contact DB queries during Recipient object loading. 2) Use a SoftHashMap so that any referenced Recipient objects can't get kicked out of the cache. 3) Don't load Recipient objects through the provider during sync. This was a super expensive thing to do, and blew up the cache. 4) Only apply changes to Recipient objects during sync if they are in the cache. Otherwise, there should be no outstanding references, and the changes are fine going exclusively to the DB.pull/1/head
parent
64c8b4b2ef
commit
7a5846a6d4
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* A <code><em>Soft</em>HashMap</code> is a memory-constrained map that stores its <em>values</em> in
|
||||
* {@link SoftReference SoftReference}s. (Contrast this with the JDK's
|
||||
* {@link WeakHashMap WeakHashMap}, which uses weak references for its <em>keys</em>, which is of little value if you
|
||||
* want the cache to auto-resize itself based on memory constraints).
|
||||
* <p/>
|
||||
* Having the values wrapped by soft references allows the cache to automatically reduce its size based on memory
|
||||
* limitations and garbage collection. This ensures that the cache will not cause memory leaks by holding strong
|
||||
* references to all of its values.
|
||||
* <p/>
|
||||
* This class is a generics-enabled Map based on initial ideas from Heinz Kabutz's and Sydney Redelinghuys's
|
||||
* <a href="http://www.javaspecialists.eu/archive/Issue015.html">publicly posted version (with their approval)</a>, with
|
||||
* continued modifications.
|
||||
* <p/>
|
||||
* This implementation is thread-safe and usable in concurrent environments.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public class SoftHashMap<K, V> implements Map<K, V> {
|
||||
|
||||
/**
|
||||
* The default value of the RETENTION_SIZE attribute, equal to 100.
|
||||
*/
|
||||
private static final int DEFAULT_RETENTION_SIZE = 100;
|
||||
|
||||
/**
|
||||
* The internal HashMap that will hold the SoftReference.
|
||||
*/
|
||||
private final Map<K, SoftValue<V, K>> map;
|
||||
|
||||
/**
|
||||
* The number of strong references to hold internally, that is, the number of instances to prevent
|
||||
* from being garbage collected automatically (unlike other soft references).
|
||||
*/
|
||||
private final int RETENTION_SIZE;
|
||||
|
||||
/**
|
||||
* The FIFO list of strong references (not to be garbage collected), order of last access.
|
||||
*/
|
||||
private final Queue<V> strongReferences; //guarded by 'strongReferencesLock'
|
||||
private final ReentrantLock strongReferencesLock;
|
||||
|
||||
/**
|
||||
* Reference queue for cleared SoftReference objects.
|
||||
*/
|
||||
private final ReferenceQueue<? super V> queue;
|
||||
|
||||
/**
|
||||
* Creates a new SoftHashMap with a default retention size size of
|
||||
* {@link #DEFAULT_RETENTION_SIZE DEFAULT_RETENTION_SIZE} (100 entries).
|
||||
*
|
||||
* @see #SoftHashMap(int)
|
||||
*/
|
||||
public SoftHashMap() {
|
||||
this(DEFAULT_RETENTION_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SoftHashMap with the specified retention size.
|
||||
* <p/>
|
||||
* The retention size (n) is the total number of most recent entries in the map that will be strongly referenced
|
||||
* (ie 'retained') to prevent them from being eagerly garbage collected. That is, the point of a SoftHashMap is to
|
||||
* allow the garbage collector to remove as many entries from this map as it desires, but there will always be (n)
|
||||
* elements retained after a GC due to the strong references.
|
||||
* <p/>
|
||||
* Note that in a highly concurrent environments the exact total number of strong references may differ slightly
|
||||
* than the actual <code>retentionSize</code> value. This number is intended to be a best-effort retention low
|
||||
* water mark.
|
||||
*
|
||||
* @param retentionSize the total number of most recent entries in the map that will be strongly referenced
|
||||
* (retained), preventing them from being eagerly garbage collected by the JVM.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public SoftHashMap(int retentionSize) {
|
||||
super();
|
||||
RETENTION_SIZE = Math.max(0, retentionSize);
|
||||
queue = new ReferenceQueue<V>();
|
||||
strongReferencesLock = new ReentrantLock();
|
||||
map = new ConcurrentHashMap<K, SoftValue<V, K>>();
|
||||
strongReferences = new ConcurrentLinkedQueue<V>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code SoftHashMap} backed by the specified {@code source}, with a default retention
|
||||
* size of {@link #DEFAULT_RETENTION_SIZE DEFAULT_RETENTION_SIZE} (100 entries).
|
||||
*
|
||||
* @param source the backing map to populate this {@code SoftHashMap}
|
||||
* @see #SoftHashMap(Map,int)
|
||||
*/
|
||||
public SoftHashMap(Map<K, V> source) {
|
||||
this(DEFAULT_RETENTION_SIZE);
|
||||
putAll(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code SoftHashMap} backed by the specified {@code source}, with the specified retention size.
|
||||
* <p/>
|
||||
* The retention size (n) is the total number of most recent entries in the map that will be strongly referenced
|
||||
* (ie 'retained') to prevent them from being eagerly garbage collected. That is, the point of a SoftHashMap is to
|
||||
* allow the garbage collector to remove as many entries from this map as it desires, but there will always be (n)
|
||||
* elements retained after a GC due to the strong references.
|
||||
* <p/>
|
||||
* Note that in a highly concurrent environments the exact total number of strong references may differ slightly
|
||||
* than the actual <code>retentionSize</code> value. This number is intended to be a best-effort retention low
|
||||
* water mark.
|
||||
*
|
||||
* @param source the backing map to populate this {@code SoftHashMap}
|
||||
* @param retentionSize the total number of most recent entries in the map that will be strongly referenced
|
||||
* (retained), preventing them from being eagerly garbage collected by the JVM.
|
||||
*/
|
||||
public SoftHashMap(Map<K, V> source, int retentionSize) {
|
||||
this(retentionSize);
|
||||
putAll(source);
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
processQueue();
|
||||
|
||||
V result = null;
|
||||
SoftValue<V, K> value = map.get(key);
|
||||
|
||||
if (value != null) {
|
||||
//unwrap the 'real' value from the SoftReference
|
||||
result = value.get();
|
||||
if (result == null) {
|
||||
//The wrapped value was garbage collected, so remove this entry from the backing map:
|
||||
//noinspection SuspiciousMethodCalls
|
||||
map.remove(key);
|
||||
} else {
|
||||
//Add this value to the beginning of the strong reference queue (FIFO).
|
||||
addToStrongReferences(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addToStrongReferences(V result) {
|
||||
strongReferencesLock.lock();
|
||||
try {
|
||||
strongReferences.add(result);
|
||||
trimStrongReferencesIfNecessary();
|
||||
} finally {
|
||||
strongReferencesLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Guarded by the strongReferencesLock in the addToStrongReferences method
|
||||
|
||||
private void trimStrongReferencesIfNecessary() {
|
||||
//trim the strong ref queue if necessary:
|
||||
while (strongReferences.size() > RETENTION_SIZE) {
|
||||
strongReferences.poll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the ReferenceQueue and removes garbage-collected SoftValue objects from the backing map
|
||||
* by looking them up using the SoftValue.key data member.
|
||||
*/
|
||||
private void processQueue() {
|
||||
SoftValue sv;
|
||||
while ((sv = (SoftValue) queue.poll()) != null) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
map.remove(sv.key); // we can access private data!
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
processQueue();
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
processQueue();
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
processQueue();
|
||||
Collection values = values();
|
||||
return values != null && values.contains(value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
if (m == null || m.isEmpty()) {
|
||||
processQueue();
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
processQueue();
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
processQueue();
|
||||
Collection<K> keys = map.keySet();
|
||||
if (keys.isEmpty()) {
|
||||
//noinspection unchecked
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
Collection<V> values = new ArrayList<V>(keys.size());
|
||||
for (K key : keys) {
|
||||
V v = get(key);
|
||||
if (v != null) {
|
||||
values.add(v);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entry, but wraps the value in a SoftValue instance to enable auto garbage collection.
|
||||
*/
|
||||
public V put(K key, V value) {
|
||||
processQueue(); // throw out garbage collected values first
|
||||
SoftValue<V, K> sv = new SoftValue<V, K>(value, key, queue);
|
||||
SoftValue<V, K> previous = map.put(key, sv);
|
||||
addToStrongReferences(value);
|
||||
return previous != null ? previous.get() : null;
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
processQueue(); // throw out garbage collected values first
|
||||
SoftValue<V, K> raw = map.remove(key);
|
||||
return raw != null ? raw.get() : null;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
strongReferencesLock.lock();
|
||||
try {
|
||||
strongReferences.clear();
|
||||
} finally {
|
||||
strongReferencesLock.unlock();
|
||||
}
|
||||
processQueue(); // throw out garbage collected values
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
processQueue(); // throw out garbage collected values first
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
processQueue(); // throw out garbage collected values first
|
||||
Collection<K> keys = map.keySet();
|
||||
if (keys.isEmpty()) {
|
||||
//noinspection unchecked
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
Map<K, V> kvPairs = new HashMap<K, V>(keys.size());
|
||||
for (K key : keys) {
|
||||
V v = get(key);
|
||||
if (v != null) {
|
||||
kvPairs.put(key, v);
|
||||
}
|
||||
}
|
||||
return kvPairs.entrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* We define our own subclass of SoftReference which contains
|
||||
* not only the value but also the key to make it easier to find
|
||||
* the entry in the HashMap after it's been garbage collected.
|
||||
*/
|
||||
private static class SoftValue<V, K> extends SoftReference<V> {
|
||||
|
||||
private final K key;
|
||||
|
||||
/**
|
||||
* Constructs a new instance, wrapping the value, key, and queue, as
|
||||
* required by the superclass.
|
||||
*
|
||||
* @param value the map value
|
||||
* @param key the map key
|
||||
* @param queue the soft reference queue to poll to determine if the entry had been reaped by the GC.
|
||||
*/
|
||||
private SoftValue(V value, K key, ReferenceQueue<? super V> queue) {
|
||||
super(value, queue);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,616 +0,0 @@
|
||||
/*
|
||||
* 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/licenses/publicdomain
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.util.deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A {@link Deque} that additionally supports blocking operations that wait
|
||||
* for the deque to become non-empty when retrieving an element, and wait for
|
||||
* space to become available in the deque when storing an element.
|
||||
*
|
||||
* <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
|
||||
* of handling operations that cannot be satisfied immediately, but may be
|
||||
* satisfied at some point in the future:
|
||||
* one throws an exception, the second returns a special value (either
|
||||
* <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
|
||||
* blocks the current thread indefinitely until the operation can succeed,
|
||||
* and the fourth blocks for only a given maximum time limit before giving
|
||||
* up. These methods are summarized in the following table:
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Blocks</em></td>
|
||||
* <td ALIGN=CENTER><em>Times out</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #addFirst addFirst(e)}</td>
|
||||
* <td>{@link #offerFirst offerFirst(e)}</td>
|
||||
* <td>{@link #putFirst putFirst(e)}</td>
|
||||
* <td>{@link #offerFirst offerFirst(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #removeFirst removeFirst()}</td>
|
||||
* <td>{@link #pollFirst pollFirst()}</td>
|
||||
* <td>{@link #takeFirst takeFirst()}</td>
|
||||
* <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #getFirst getFirst()}</td>
|
||||
* <td>{@link #peekFirst peekFirst()}</td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 5> <b>Last Element (Tail)</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Blocks</em></td>
|
||||
* <td ALIGN=CENTER><em>Times out</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #addLast addLast(e)}</td>
|
||||
* <td>{@link #offerLast offerLast(e)}</td>
|
||||
* <td>{@link #putLast putLast(e)}</td>
|
||||
* <td>{@link #offerLast offerLast(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #removeLast() removeLast()}</td>
|
||||
* <td>{@link #pollLast() pollLast()}</td>
|
||||
* <td>{@link #takeLast takeLast()}</td>
|
||||
* <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #getLast getLast()}</td>
|
||||
* <td>{@link #peekLast peekLast()}</td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
|
||||
* does not permit null elements, and may (or may not) be
|
||||
* capacity-constrained.
|
||||
*
|
||||
* <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
|
||||
* <tt>BlockingQueue</tt>. The methods inherited from the
|
||||
* <tt>BlockingQueue</tt> interface are precisely equivalent to
|
||||
* <tt>BlockingDeque</tt> methods as indicated in the following table:
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
|
||||
* <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #add add(e)}</td>
|
||||
* <td>{@link #addLast addLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #offer offer(e)}</td>
|
||||
* <td>{@link #offerLast offerLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #put put(e)}</td>
|
||||
* <td>{@link #putLast putLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #offer offer(e, time, unit)}</td>
|
||||
* <td>{@link #offerLast offerLast(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Remove</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #remove() remove()}</td>
|
||||
* <td>{@link #removeFirst() removeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #poll() poll()}</td>
|
||||
* <td>{@link #pollFirst() pollFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #take() take()}</td>
|
||||
* <td>{@link #takeFirst() takeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
|
||||
* <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Examine</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #element() element()}</td>
|
||||
* <td>{@link #getFirst() getFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #peek() peek()}</td>
|
||||
* <td>{@link #peekFirst() peekFirst()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Memory consistency effects: As with other concurrent
|
||||
* collections, actions in a thread prior to placing an object into a
|
||||
* {@code BlockingDeque}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions subsequent to the access or removal of that element from
|
||||
* the {@code BlockingDeque} in another thread.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
|
||||
/*
|
||||
* We have "diamond" multiple interface inheritance here, and that
|
||||
* introduces ambiguities. Methods might end up with different
|
||||
* specs depending on the branch chosen by javadoc. Thus a lot of
|
||||
* methods specs here are copied from superinterfaces.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* throwing an <tt>IllegalStateException</tt> if no space is currently
|
||||
* available. When using a capacity-restricted deque, it is generally
|
||||
* preferable to use {@link #offerFirst offerFirst}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void addFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* throwing an <tt>IllegalStateException</tt> if no space is currently
|
||||
* available. When using a capacity-restricted deque, it is generally
|
||||
* preferable to use {@link #offerLast offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void addLast(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* returning <tt>true</tt> upon success and <tt>false</tt> if no space is
|
||||
* currently available.
|
||||
* When using a capacity-restricted deque, this method is generally
|
||||
* preferable to the {@link #addFirst addFirst} method, which can
|
||||
* fail to insert an element only by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
boolean offerFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* returning <tt>true</tt> upon success and <tt>false</tt> if no space is
|
||||
* currently available.
|
||||
* When using a capacity-restricted deque, this method is generally
|
||||
* preferable to the {@link #addLast addLast} method, which can
|
||||
* fail to insert an element only by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
boolean offerLast(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque,
|
||||
* waiting if necessary for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void putFirst(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque,
|
||||
* waiting if necessary for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void putLast(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque,
|
||||
* waiting up to the specified wait time if necessary for space to
|
||||
* become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* <tt>unit</tt>
|
||||
* @param unit a <tt>TimeUnit</tt> determining how to interpret the
|
||||
* <tt>timeout</tt> parameter
|
||||
* @return <tt>true</tt> if successful, or <tt>false</tt> if
|
||||
* the specified waiting time elapses before space is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerFirst(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque,
|
||||
* waiting up to the specified wait time if necessary for space to
|
||||
* become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* <tt>unit</tt>
|
||||
* @param unit a <tt>TimeUnit</tt> determining how to interpret the
|
||||
* <tt>timeout</tt> parameter
|
||||
* @return <tt>true</tt> if successful, or <tt>false</tt> if
|
||||
* the specified waiting time elapses before space is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerLast(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque, waiting
|
||||
* if necessary until an element becomes available.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E takeFirst() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque, waiting
|
||||
* if necessary until an element becomes available.
|
||||
*
|
||||
* @return the tail of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E takeLast() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque, waiting
|
||||
* up to the specified wait time if necessary for an element to
|
||||
* become available.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* <tt>unit</tt>
|
||||
* @param unit a <tt>TimeUnit</tt> determining how to interpret the
|
||||
* <tt>timeout</tt> parameter
|
||||
* @return the head of this deque, or <tt>null</tt> if the specified
|
||||
* waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E pollFirst(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque, waiting
|
||||
* up to the specified wait time if necessary for an element to
|
||||
* become available.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* <tt>unit</tt>
|
||||
* @param unit a <tt>TimeUnit</tt> determining how to interpret the
|
||||
* <tt>timeout</tt> parameter
|
||||
* @return the tail of this deque, or <tt>null</tt> if the specified
|
||||
* waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E pollLast(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element <tt>e</tt> such that
|
||||
* <tt>o.equals(e)</tt> (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null (optional)
|
||||
*/
|
||||
boolean removeFirstOccurrence(Object o);
|
||||
|
||||
/**
|
||||
* Removes the last occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the last element <tt>e</tt> such that
|
||||
* <tt>o.equals(e)</tt> (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null (optional)
|
||||
*/
|
||||
boolean removeLastOccurrence(Object o);
|
||||
|
||||
// *** BlockingQueue methods ***
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) 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.
|
||||
* When using a capacity-restricted deque, it is generally preferable to
|
||||
* use {@link #offer offer}.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addLast addLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) if it is possible to do so
|
||||
* immediately without violating capacity restrictions, returning
|
||||
* <tt>true</tt> upon success and <tt>false</tt> if no space is currently
|
||||
* available. When using a capacity-restricted deque, this method is
|
||||
* generally preferable to the {@link #add} method, which can fail to
|
||||
* insert an element only by throwing an exception.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #offerLast offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offer(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque), waiting if necessary for
|
||||
* space to become available.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #putLast putLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void put(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque), waiting up to the
|
||||
* specified wait time if necessary for space to become available.
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #offerLast offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return <tt>true</tt> if the element was added to this deque, else
|
||||
* <tt>false</tt>
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offer(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque).
|
||||
* This method differs from {@link #poll poll} only in that it
|
||||
* throws an exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #removeFirst() removeFirst}.
|
||||
*
|
||||
* @return the head of the queue represented by this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E remove();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), or returns
|
||||
* <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #pollFirst()}.
|
||||
*
|
||||
* @return the head of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E poll();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), waiting if
|
||||
* necessary until an element becomes available.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #takeFirst() takeFirst}.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E take() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), waiting up to the
|
||||
* specified wait time if necessary for an element to become available.
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #pollFirst(long,TimeUnit) pollFirst}.
|
||||
*
|
||||
* @return the head of this deque, or <tt>null</tt> if the
|
||||
* specified waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E poll(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of the queue represented by
|
||||
* this deque (in other words, the first element of this deque).
|
||||
* This method differs from {@link #peek peek} only in that it throws an
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #getFirst() getFirst}.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E element();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of the queue represented by
|
||||
* this deque (in other words, the first element of this deque), or
|
||||
* returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #peekFirst() peekFirst}.
|
||||
*
|
||||
* @return the head of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E peek();
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element <tt>e</tt> such that
|
||||
* <tt>o.equals(e)</tt> (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #removeFirstOccurrence removeFirstOccurrence}.
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if this deque changed as a result of the call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null (optional)
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this deque contains the specified element.
|
||||
* More formally, returns <tt>true</tt> if and only if this deque contains
|
||||
* at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
|
||||
*
|
||||
* @param o object to be checked for containment in this deque
|
||||
* @return <tt>true</tt> if this deque contains the specified element
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null (optional)
|
||||
*/
|
||||
public boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this deque.
|
||||
*
|
||||
* @return the number of elements in this deque
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this deque in proper sequence.
|
||||
* The elements will be returned in order from first (head) to last (tail).
|
||||
*
|
||||
* @return an iterator over the elements in this deque in proper sequence
|
||||
*/
|
||||
Iterator<E> iterator();
|
||||
|
||||
// *** Stack methods ***
|
||||
|
||||
/**
|
||||
* Pushes an element onto the stack represented by this deque. In other
|
||||
* words, inserts the element at the front of this deque unless it would
|
||||
* violate capacity restrictions.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addFirst addFirst}.
|
||||
*
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void push(E e);
|
||||
}
|
@ -1,555 +0,0 @@
|
||||
/*
|
||||
* Written by Doug Lea and Josh Bloch with assistance from members of
|
||||
* JCP JSR-166 Expert Group and released to the public domain, as explained
|
||||
* at http://creativecommons.org/licenses/publicdomain
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.util.deque;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
// BEGIN android-note
|
||||
// removed link to collections framework docs
|
||||
// changed {@link #offer(Object)} to {@link #offer} to satisfy DroidDoc
|
||||
// END android-note
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at
|
||||
* both ends. The name <i>deque</i> is short for "double ended queue"
|
||||
* and is usually pronounced "deck". Most <tt>Deque</tt>
|
||||
* implementations place no fixed limits on the number of elements
|
||||
* they may contain, but this interface supports capacity-restricted
|
||||
* deques as well as those with no fixed size limit.
|
||||
*
|
||||
* <p>This interface defines methods to access the elements at both
|
||||
* ends of the deque. Methods are provided to insert, remove, and
|
||||
* examine the element. 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>Deque</tt> implementations; in most implementations, insert
|
||||
* operations cannot fail.
|
||||
*
|
||||
* <p>The twelve methods described above are summarized in the
|
||||
* following table:
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #addFirst addFirst(e)}</td>
|
||||
* <td>{@link #offerFirst offerFirst(e)}</td>
|
||||
* <td>{@link #addLast addLast(e)}</td>
|
||||
* <td>{@link #offerLast offerLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #removeFirst removeFirst()}</td>
|
||||
* <td>{@link #pollFirst pollFirst()}</td>
|
||||
* <td>{@link #removeLast removeLast()}</td>
|
||||
* <td>{@link #pollLast pollLast()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #getFirst getFirst()}</td>
|
||||
* <td>{@link #peekFirst peekFirst()}</td>
|
||||
* <td>{@link #getLast getLast()}</td>
|
||||
* <td>{@link #peekLast peekLast()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>This interface extends the {@link Queue} interface. When a deque is
|
||||
* used as a queue, FIFO (First-In-First-Out) behavior results. Elements are
|
||||
* added at the end of the deque and removed from the beginning. The methods
|
||||
* inherited from the <tt>Queue</tt> interface are precisely equivalent to
|
||||
* <tt>Deque</tt> methods as indicated in the following table:
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER> <b><tt>Queue</tt> Method</b></td>
|
||||
* <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#add add(e)}</td>
|
||||
* <td>{@link #addLast addLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#offer offer(e)}</td>
|
||||
* <td>{@link #offerLast offerLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#remove remove()}</td>
|
||||
* <td>{@link #removeFirst removeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#poll poll()}</td>
|
||||
* <td>{@link #pollFirst pollFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#element element()}</td>
|
||||
* <td>{@link #getFirst getFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link java.util.Queue#peek peek()}</td>
|
||||
* <td>{@link #peek peekFirst()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Deques can also be used as LIFO (Last-In-First-Out) stacks. This
|
||||
* interface should be used in preference to the legacy {@link Stack} class.
|
||||
* When a deque is used as a stack, elements are pushed and popped from the
|
||||
* beginning of the deque. Stack methods are precisely equivalent to
|
||||
* <tt>Deque</tt> methods as indicated in the table below:
|
||||
*
|
||||
* <p>
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER> <b>Stack Method</b></td>
|
||||
* <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #push push(e)}</td>
|
||||
* <td>{@link #addFirst addFirst(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #pop pop()}</td>
|
||||
* <td>{@link #removeFirst removeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #peek peek()}</td>
|
||||
* <td>{@link #peekFirst peekFirst()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Note that the {@link #peek peek} method works equally well when
|
||||
* a deque is used as a queue or a stack; in either case, elements are
|
||||
* drawn from the beginning of the deque.
|
||||
*
|
||||
* <p>This interface provides two methods to remove interior
|
||||
* elements, {@link #removeFirstOccurrence removeFirstOccurrence} and
|
||||
* {@link #removeLastOccurrence removeLastOccurrence}.
|
||||
*
|
||||
* <p>Unlike the {@link List} interface, this interface does not
|
||||
* provide support for indexed access to elements.
|
||||
*
|
||||
* <p>While <tt>Deque</tt> implementations are not strictly required
|
||||
* to prohibit the insertion of null elements, they are strongly
|
||||
* encouraged to do so. Users of any <tt>Deque</tt> implementations
|
||||
* that do allow null elements are strongly encouraged <i>not</i> to
|
||||
* take advantage of the ability to insert nulls. This is so because
|
||||
* <tt>null</tt> is used as a special return value by various methods
|
||||
* to indicated that the deque is empty.
|
||||
*
|
||||
* <p><tt>Deque</tt> implementations generally do not define
|
||||
* element-based versions of the <tt>equals</tt> and <tt>hashCode</tt>
|
||||
* methods, but instead inherit the identity-based versions from class
|
||||
* <tt>Object</tt>.
|
||||
*
|
||||
* @author Doug Lea
|
||||
* @author Josh Bloch
|
||||
* @since 1.6
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
|
||||
public interface Deque<E> extends Queue<E> {
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions.
|
||||
* When using a capacity-restricted deque, it is generally preferable to
|
||||
* use method {@link #offerFirst}.
|
||||
*
|
||||
* @param e the element to 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 deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void addFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions.
|
||||
* When using a capacity-restricted deque, it is generally preferable to
|
||||
* use method {@link #offerLast}.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #add}.
|
||||
*
|
||||
* @param e the element to 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 deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void addLast(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque unless it would
|
||||
* violate capacity restrictions. When using a capacity-restricted deque,
|
||||
* this method is generally preferable to the {@link #addFirst} method,
|
||||
* 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 deque, else
|
||||
* <tt>false</tt>
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque unless it would
|
||||
* violate capacity restrictions. When using a capacity-restricted deque,
|
||||
* this method is generally preferable to the {@link #addLast} method,
|
||||
* 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 deque, else
|
||||
* <tt>false</tt>
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerLast(E e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque. This method
|
||||
* differs from {@link #pollFirst pollFirst} only in that it throws an
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque. This method
|
||||
* differs from {@link #pollLast pollLast} only in that it throws an
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* @return the tail of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque,
|
||||
* or returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* @return the head of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E pollFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque,
|
||||
* or returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* @return the tail of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E pollLast();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the first element of this deque.
|
||||
*
|
||||
* This method differs from {@link #peekFirst peekFirst} only in that it
|
||||
* throws an exception if this deque is empty.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the last element of this deque.
|
||||
* This method differs from {@link #peekLast peekLast} only in that it
|
||||
* throws an exception if this deque is empty.
|
||||
*
|
||||
* @return the tail of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E getLast();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the first element of this deque,
|
||||
* or returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* @return the head of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E peekFirst();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the last element of this deque,
|
||||
* or returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* @return the tail of this deque, or <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E peekLast();
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>
|
||||
* (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements (optional)
|
||||
*/
|
||||
boolean removeFirstOccurrence(Object o);
|
||||
|
||||
/**
|
||||
* Removes the last occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the last element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>
|
||||
* (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements (optional)
|
||||
*/
|
||||
boolean removeLastOccurrence(Object o);
|
||||
|
||||
// *** Queue methods ***
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) 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.
|
||||
* When using a capacity-restricted deque, it is generally preferable to
|
||||
* use {@link #offer offer}.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addLast}.
|
||||
*
|
||||
* @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 deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) if it is possible to do so
|
||||
* immediately without violating capacity restrictions, returning
|
||||
* <tt>true</tt> upon success and <tt>false</tt> if no space is currently
|
||||
* available. When using a capacity-restricted deque, this method is
|
||||
* generally preferable to the {@link #add} method, which can fail to
|
||||
* insert an element only by throwing an exception.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return <tt>true</tt> if the element was added to this deque, else
|
||||
* <tt>false</tt>
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offer(E e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque).
|
||||
* This method differs from {@link #poll poll} only in that it throws an
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #removeFirst()}.
|
||||
*
|
||||
* @return the head of the queue represented by this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E remove();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), or returns
|
||||
* <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #pollFirst()}.
|
||||
*
|
||||
* @return the first element of this deque, or <tt>null</tt> if
|
||||
* this deque is empty
|
||||
*/
|
||||
E poll();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of the queue represented by
|
||||
* this deque (in other words, the first element of this deque).
|
||||
* This method differs from {@link #peek peek} only in that it throws an
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #getFirst()}.
|
||||
*
|
||||
* @return the head of the queue represented by this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E element();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of the queue represented by
|
||||
* this deque (in other words, the first element of this deque), or
|
||||
* returns <tt>null</tt> if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #peekFirst()}.
|
||||
*
|
||||
* @return the head of the queue represented by this deque, or
|
||||
* <tt>null</tt> if this deque is empty
|
||||
*/
|
||||
E peek();
|
||||
|
||||
|
||||
// *** Stack methods ***
|
||||
|
||||
/**
|
||||
* Pushes an element onto the stack represented by this deque (in other
|
||||
* words, at the head of this deque) 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.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addFirst}.
|
||||
*
|
||||
* @param e the element to push
|
||||
* @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 deque
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void push(E e);
|
||||
|
||||
/**
|
||||
* Pops an element from the stack represented by this deque. In other
|
||||
* words, removes and returns the first element of this deque.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #removeFirst()}.
|
||||
*
|
||||
* @return the element at the front of this deque (which is the top
|
||||
* of the stack represented by this deque)
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E pop();
|
||||
|
||||
|
||||
// *** Collection methods ***
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>
|
||||
* (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* <p>This method is equivalent to {@link #removeFirstOccurrence}.
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements (optional)
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this deque contains the specified element.
|
||||
* More formally, returns <tt>true</tt> if and only if this deque contains
|
||||
* at least one element <tt>e</tt> such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>.
|
||||
*
|
||||
* @param o element whose presence in this deque is to be tested
|
||||
* @return <tt>true</tt> if this deque contains the specified element
|
||||
* @throws ClassCastException if the type of the specified element
|
||||
* is incompatible with this deque (optional)
|
||||
* @throws NullPointerException if the specified element is null and this
|
||||
* deque does not permit null elements (optional)
|
||||
*/
|
||||
boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this deque.
|
||||
*
|
||||
* @return the number of elements in this deque
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this deque in proper sequence.
|
||||
* The elements will be returned in order from first (head) to last (tail).
|
||||
*
|
||||
* @return an iterator over the elements in this deque in proper sequence
|
||||
*/
|
||||
Iterator<E> iterator();
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this deque in reverse
|
||||
* sequential order. The elements will be returned in order from
|
||||
* last (tail) to first (head).
|
||||
*
|
||||
* @return an iterator over the elements in this deque in reverse
|
||||
* sequence
|
||||
*/
|
||||
Iterator<E> descendingIterator();
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue