com.github.benmanes.caffeine.cache.LinkedDeque Maven / Gradle / Ivy
/*
* Copyright 2014 Ben Manes. All Rights Reserved.
*
* Licensed 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 com.github.benmanes.caffeine.cache;
import java.util.Comparator;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A linked list extension of the {@link Deque} interface where the link pointers are tightly
* integrated with the element. Linked deques have no capacity restrictions; they grow as necessary
* to support usage. They are not thread-safe; in the absence of external synchronization, they do
* not support concurrent access by multiple threads. Null elements are prohibited.
*
* Most LinkedDeque operations run in constant time by assuming that the element parameter
* is associated with the deque instance. Any usage that violates this assumption will result in
* non-deterministic behavior.
*
* An element can exist in only one instance of a deque implementation, but may exist in multiple
* implementations. Each implementation must define unique names for accessing and modifying its
* link pointers.
*
* The iterators returned by this class are not fail-fast: If the deque is modified
* at any time after the iterator is created, the iterator will be in an unknown state. Thus, in the
* face of concurrent modification, the iterator risks arbitrary, non-deterministic behavior at an
* undetermined time in the future.
*
* @author [email protected] (Ben Manes)
* @param the type of elements held in this collection
*/
interface LinkedDeque extends Deque {
/**
* Returns if the element is at the front of the deque.
*
* @param e the linked element
*/
boolean isFirst(E e);
/**
* Returns if the element is at the back of the deque.
*
* @param e the linked element
*/
boolean isLast(E e);
/**
* Moves the element to the front of the deque so that it becomes the first element.
*
* @param e the linked element
*/
void moveToFront(E e);
/**
* Moves the element to the back of the deque so that it becomes the last element.
*
* @param e the linked element
*/
void moveToBack(E e);
/**
* Retrieves the previous element or null if either the element is unlinked or the first
* element on the deque.
*/
@Nullable E getPrevious(E e);
/** Sets the previous element or null if there is no link. */
void setPrevious(E e, @Nullable E prev);
/**
* Retrieves the next element or null if either the element is unlinked or the last
* element on the deque.
*/
@Nullable E getNext(E e);
/** Sets the next element or null if there is no link. */
void setNext(E e, @Nullable E next);
@Override
PeekingIterator iterator();
@Override
PeekingIterator descendingIterator();
interface PeekingIterator extends Iterator {
/** Returns the next element in the iteration, without advancing the iteration. */
@Nullable E peek();
/** Returns an iterator that returns the first iteration followed by the second iteration. */
static PeekingIterator concat(PeekingIterator first, PeekingIterator second) {
return new PeekingIterator() {
@Override public boolean hasNext() {
return first.hasNext() || second.hasNext();
}
@Override public E next() {
if (first.hasNext()) {
return first.next();
} else if (second.hasNext()) {
return second.next();
}
throw new NoSuchElementException();
}
@Override public @Nullable E peek() {
return first.hasNext() ? first.peek() : second.peek();
}
};
}
/** Returns an iterator that selects the greater element from the backing iterators. */
static PeekingIterator comparing(PeekingIterator first,
PeekingIterator second, Comparator comparator) {
return new PeekingIterator() {
@Override public boolean hasNext() {
return first.hasNext() || second.hasNext();
}
@Override public E next() {
if (!first.hasNext()) {
return second.next();
} else if (!second.hasNext()) {
return first.next();
}
E o1 = first.peek();
E o2 = second.peek();
boolean greaterOrEqual = (comparator.compare(o1, o2) >= 0);
return greaterOrEqual ? first.next() : second.next();
}
@Override public @Nullable E peek() {
if (!first.hasNext()) {
return second.peek();
} else if (!second.hasNext()) {
return first.peek();
}
E o1 = first.peek();
E o2 = second.peek();
boolean greaterOrEqual = (comparator.compare(o1, o2) >= 0);
return greaterOrEqual ? first.peek() : second.peek();
}
};
}
}
}