Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Signifies that a public API (public class, method or field) is subject to
* incompatible changes, or even removal, in a future release. An API bearing
* this annotation is exempt from any compatibility guarantees made by its
* containing library. Note that the presence of this annotation implies nothing
* about the quality or performance of the API in question, only the fact that
* it is not "API-frozen."
*
* <p>
* It is generally safe for <i>applications</i> to depend on beta APIs, at the
* cost of some extra work during upgrades. However it is generally inadvisable
* for <i>libraries</i> (which get included on users' CLASSPATHs, outside the
* library developers' control) to do so.
*
*
* @author Kevin Bourrillion
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD,
ElementType.TYPE })
@Documented
@GwtCompatible
public @interface Beta {
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The presence of this annotation on a type indicates that the type may be used
* with the <a href="http://code.google.com/webtoolkit/">Google Web Toolkit</a>
* (GWT). When applied to a method, the return type of the method is GWT
* compatible. It's useful to indicate that an instance created by factory
* methods has a GWT serializable type. In the following example,
*
* <pre style="code">
* {@literal @}GwtCompatible
* class Lists {
* ...
* {@literal @}GwtCompatible(serializable = true)
* static &lt;E> List&lt;E> newArrayList(E... elements) {
* ...
* }
* }
* </pre>
* <p>
* The return value of {@code Lists.newArrayList(E[])} has GWT serializable
* type. It is also useful in specifying contracts of interface methods. In the
* following example,
*
* <pre style="code">
* {@literal @}GwtCompatible
* interface ListFactory {
* ...
* {@literal @}GwtCompatible(serializable = true)
* &lt;E> List&lt;E> newArrayList(E... elements);
* }
* </pre>
* <p>
* The {@code newArrayList(E[])} method of all implementations of {@code
* ListFactory} is expected to return a value with a GWT serializable type.
*
* <p>
* Note that a {@code GwtCompatible} type may have some {@link GwtIncompatible}
* methods.
*
* @author Charles Fry
* @author Hayward Chan
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@GwtCompatible
public @interface GwtCompatible {
/**
* When {@code true}, the annotated type or the type of the method return value
* is GWT serializable.
*
* @see <a href=
* "http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html#DevGuideSerializableTypes">
* Documentation about GWT serialization</a>
*/
boolean serializable() default false;
/**
* When {@code true}, the annotated type is emulated in GWT. The emulated source
* (also known as super-source) is different from the implementation used by the
* JVM.
*
* @see <a href=
* "http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModules">
* Documentation about GWT emulated source</a>
*/
boolean emulated() default false;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The presence of this annotation on a method indicates that the method may
* <em>not</em> be used with the
* <a href="http://code.google.com/webtoolkit/">Google Web Toolkit</a> (GWT),
* even though its type is annotated as {@link GwtCompatible} and accessible in
* GWT. They can cause GWT compilation errors or simply unexpected exceptions
* when used in GWT.
*
* <p>
* Note that this annotation should only be applied to methods, fields, or inner
* classes of types which are annotated as {@link GwtCompatible}.
*
* @author Charles Fry
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD })
@Documented
@GwtCompatible
public @interface GwtIncompatible {
/**
* Describes why the annotated element is incompatible with GWT. Since this is
* generally due to a dependence on a type/method which GWT doesn't support, it
* is sufficient to simply reference the unsupported type/method. E.g.
* "Class.isInstance".
*/
String value();
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2006 The Guava Authors
*
* 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.google.common.annotations;
/**
* Annotates a program element that exists, or is more widely visible than
* otherwise necessary, only for use in test code.
*
* @author Johannes Henkel
*/
@GwtCompatible
public @interface VisibleForTesting {
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.
*/
/**
* Common annotation types. This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*/
package com.google.common.annotations;

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of an {@link Optional} not containing a reference.
*/
@GwtCompatible
final class Absent<T> extends Optional<T> {
static final Absent<Object> INSTANCE = new Absent<Object>();
@SuppressWarnings("unchecked") // implementation is "fully variant"
static <T> Optional<T> withType() {
return (Optional<T>) INSTANCE;
}
private Absent() {
}
@Override
public boolean isPresent() {
return false;
}
@Override
public T get() {
throw new IllegalStateException("Optional.get() cannot be called on an absent value");
}
@Override
public T or(T defaultValue) {
return checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
}
@SuppressWarnings("unchecked") // safe covariant cast
@Override
public Optional<T> or(Optional<? extends T> secondChoice) {
return (Optional<T>) checkNotNull(secondChoice);
}
@Override
public T or(Supplier<? extends T> supplier) {
return checkNotNull(supplier.get(), "use Optional.orNull() instead of a Supplier that returns null");
}
@Override
@Nullable
public T orNull() {
return null;
}
@Override
public Set<T> asSet() {
return Collections.emptySet();
}
@Override
public <V> Optional<V> transform(Function<? super T, V> function) {
checkNotNull(function);
return Optional.absent();
}
@Override
public boolean equals(@Nullable Object object) {
return object == this;
}
@Override
public int hashCode() {
return 0x598df91c;
}
@Override
public String toString() {
return "Optional.absent()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkState;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.google.common.annotations.GwtCompatible;
/**
* Note this class is a copy of
* {@link com.google.common.collect.AbstractIterator} (for dependency reasons).
*/
@GwtCompatible
abstract class AbstractIterator<T> implements Iterator<T> {
private State state = State.NOT_READY;
protected AbstractIterator() {
}
private enum State {
READY, NOT_READY, DONE, FAILED,
}
private T next;
protected abstract T computeNext();
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case DONE:
return false;
case READY:
return true;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
@Override
public final void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,669 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.CheckReturnValue;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static methods pertaining to ASCII characters (those in the range of values
* {@code 0x00} through {@code 0x7F}), and to strings containing such
* characters.
*
* <p>
* ASCII utilities also exist in other classes of this package:
* <ul>
* <!-- TODO(kevinb): how can we make this not produce a warning when building
* gwt javadoc? -->
* <li>{@link Charsets#US_ASCII} specifies the {@code Charset} of ASCII
* characters.
* <li>{@link CharMatcher#ASCII} matches ASCII characters and provides text
* processing methods which operate only on the ASCII characters of a string.
* </ul>
*
* @author Craig Berry
* @author Gregory Kick
* @since 7.0
*/
@GwtCompatible
public final class Ascii {
private Ascii() {
}
/* The ASCII control characters, per RFC 20. */
/**
* Null ('\0'): The all-zeros character which may serve to accomplish time fill
* and media fill. Normally used as a C string terminator.
* <p>
* Although RFC 20 names this as "Null", note that it is distinct from the C/C++
* "NULL" pointer.
*
* @since 8.0
*/
public static final byte NUL = 0;
/**
* Start of Heading: A communication control character used at the beginning of
* a sequence of characters which constitute a machine-sensible address or
* routing information. Such a sequence is referred to as the "heading." An STX
* character has the effect of terminating a heading.
*
* @since 8.0
*/
public static final byte SOH = 1;
/**
* Start of Text: A communication control character which precedes a sequence of
* characters that is to be treated as an entity and entirely transmitted
* through to the ultimate destination. Such a sequence is referred to as
* "text." STX may be used to terminate a sequence of characters started by SOH.
*
* @since 8.0
*/
public static final byte STX = 2;
/**
* End of Text: A communication control character used to terminate a sequence
* of characters started with STX and transmitted as an entity.
*
* @since 8.0
*/
public static final byte ETX = 3;
/**
* End of Transmission: A communication control character used to indicate the
* conclusion of a transmission, which may have contained one or more texts and
* any associated headings.
*
* @since 8.0
*/
public static final byte EOT = 4;
/**
* Enquiry: A communication control character used in data communication systems
* as a request for a response from a remote station. It may be used as a "Who
* Are You" (WRU) to obtain identification, or may be used to obtain station
* status, or both.
*
* @since 8.0
*/
public static final byte ENQ = 5;
/**
* Acknowledge: A communication control character transmitted by a receiver as
* an affirmative response to a sender.
*
* @since 8.0
*/
public static final byte ACK = 6;
/**
* Bell ('\a'): A character for use when there is a need to call for human
* attention. It may control alarm or attention devices.
*
* @since 8.0
*/
public static final byte BEL = 7;
/**
* Backspace ('\b'): A format effector which controls the movement of the
* printing position one printing space backward on the same printing line.
* (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte BS = 8;
/**
* Horizontal Tabulation ('\t'): A format effector which controls the movement
* of the printing position to the next in a series of predetermined positions
* along the printing line. (Applicable also to display devices and the skip
* function on punched cards.)
*
* @since 8.0
*/
public static final byte HT = 9;
/**
* Line Feed ('\n'): A format effector which controls the movement of the
* printing position to the next printing line. (Applicable also to display
* devices.) Where appropriate, this character may have the meaning "New Line"
* (NL), a format effector which controls the movement of the printing point to
* the first printing position on the next printing line. Use of this convention
* requires agreement between sender and recipient of data.
*
* @since 8.0
*/
public static final byte LF = 10;
/**
* Alternate name for {@link #LF}. ({@code LF} is preferred.)
*
* @since 8.0
*/
public static final byte NL = 10;
/**
* Vertical Tabulation ('\v'): A format effector which controls the movement of
* the printing position to the next in a series of predetermined printing
* lines. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte VT = 11;
/**
* Form Feed ('\f'): A format effector which controls the movement of the
* printing position to the first pre-determined printing line on the next form
* or page. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte FF = 12;
/**
* Carriage Return ('\r'): A format effector which controls the movement of the
* printing position to the first printing position on the same printing line.
* (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte CR = 13;
/**
* Shift Out: A control character indicating that the code combinations which
* follow shall be interpreted as outside of the character set of the standard
* code table until a Shift In character is reached.
*
* @since 8.0
*/
public static final byte SO = 14;
/**
* Shift In: A control character indicating that the code combinations which
* follow shall be interpreted according to the standard code table.
*
* @since 8.0
*/
public static final byte SI = 15;
/**
* Data Link Escape: A communication control character which will change the
* meaning of a limited number of contiguously following characters. It is used
* exclusively to provide supplementary controls in data communication networks.
*
* @since 8.0
*/
public static final byte DLE = 16;
/**
* Device Control 1. Characters for the control of ancillary devices associated
* with data processing or telecommunication systems, more especially switching
* devices "on" or "off." (If a single "stop" control is required to interrupt
* or turn off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC1 = 17; // aka XON
/**
* Transmission On: Although originally defined as DC1, this ASCII control
* character is now better known as the XON code used for software flow control
* in serial communications. The main use is restarting the transmission after
* the communication has been stopped by the XOFF control code.
*
* @since 8.0
*/
public static final byte XON = 17; // aka DC1
/**
* Device Control 2. Characters for the control of ancillary devices associated
* with data processing or telecommunication systems, more especially switching
* devices "on" or "off." (If a single "stop" control is required to interrupt
* or turn off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC2 = 18;
/**
* Device Control 3. Characters for the control of ancillary devices associated
* with data processing or telecommunication systems, more especially switching
* devices "on" or "off." (If a single "stop" control is required to interrupt
* or turn off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC3 = 19; // aka XOFF
/**
* Transmission off. See {@link #XON} for explanation.
*
* @since 8.0
*/
public static final byte XOFF = 19; // aka DC3
/**
* Device Control 4. Characters for the control of ancillary devices associated
* with data processing or telecommunication systems, more especially switching
* devices "on" or "off." (If a single "stop" control is required to interrupt
* or turn off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC4 = 20;
/**
* Negative Acknowledge: A communication control character transmitted by a
* receiver as a negative response to the sender.
*
* @since 8.0
*/
public static final byte NAK = 21;
/**
* Synchronous Idle: A communication control character used by a synchronous
* transmission system in the absence of any other character to provide a signal
* from which synchronism may be achieved or retained.
*
* @since 8.0
*/
public static final byte SYN = 22;
/**
* End of Transmission Block: A communication control character used to indicate
* the end of a block of data for communication purposes. ETB is used for
* blocking data where the block structure is not necessarily related to the
* processing format.
*
* @since 8.0
*/
public static final byte ETB = 23;
/**
* Cancel: A control character used to indicate that the data with which it is
* sent is in error or is to be disregarded.
*
* @since 8.0
*/
public static final byte CAN = 24;
/**
* End of Medium: A control character associated with the sent data which may be
* used to identify the physical end of the medium, or the end of the used, or
* wanted, portion of information recorded on a medium. (The position of this
* character does not necessarily correspond to the physical end of the medium.)
*
* @since 8.0
*/
public static final byte EM = 25;
/**
* Substitute: A character that may be substituted for a character which is
* determined to be invalid or in error.
*
* @since 8.0
*/
public static final byte SUB = 26;
/**
* Escape: A control character intended to provide code extension (supplementary
* characters) in general information interchange. The Escape character itself
* is a prefix affecting the interpretation of a limited number of contiguously
* following characters.
*
* @since 8.0
*/
public static final byte ESC = 27;
/**
* File Separator: These four information separators may be used within data in
* optional fashion, except that their hierarchical relationship shall be: FS is
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
* and length of a File, Group, Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte FS = 28;
/**
* Group Separator: These four information separators may be used within data in
* optional fashion, except that their hierarchical relationship shall be: FS is
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
* and length of a File, Group, Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte GS = 29;
/**
* Record Separator: These four information separators may be used within data
* in optional fashion, except that their hierarchical relationship shall be: FS
* is the most inclusive, then GS, then RS, and US is least inclusive. (The
* content and length of a File, Group, Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte RS = 30;
/**
* Unit Separator: These four information separators may be used within data in
* optional fashion, except that their hierarchical relationship shall be: FS is
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
* and length of a File, Group, Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte US = 31;
/**
* Space: A normally non-printing graphic character used to separate words. It
* is also a format effector which controls the movement of the printing
* position, one printing position forward. (Applicable also to display
* devices.)
*
* @since 8.0
*/
public static final byte SP = 32;
/**
* Alternate name for {@link #SP}.
*
* @since 8.0
*/
public static final byte SPACE = 32;
/**
* Delete: This character is used primarily to "erase" or "obliterate" erroneous
* or unwanted characters in perforated tape.
*
* @since 8.0
*/
public static final byte DEL = 127;
/**
* The minimum value of an ASCII character.
*
* @since 9.0 (was type {@code int} before 12.0)
*/
public static final char MIN = 0;
/**
* The maximum value of an ASCII character.
*
* @since 9.0 (was type {@code int} before 12.0)
*/
public static final char MAX = 127;
/**
* Returns a copy of the input string in which all
* {@linkplain #isUpperCase(char) uppercase ASCII characters} have been
* converted to lowercase. All other characters are copied without modification.
*/
public static String toLowerCase(String string) {
int length = string.length();
for (int i = 0; i < length; i++) {
if (isUpperCase(string.charAt(i))) {
char[] chars = string.toCharArray();
for (; i < length; i++) {
char c = chars[i];
if (isUpperCase(c)) {
chars[i] = (char) (c ^ 0x20);
}
}
return String.valueOf(chars);
}
}
return string;
}
/**
* Returns a copy of the input character sequence in which all
* {@linkplain #isUpperCase(char) uppercase ASCII characters} have been
* converted to lowercase. All other characters are copied without modification.
*
* @since 14.0
*/
public static String toLowerCase(CharSequence chars) {
if (chars instanceof String) {
return toLowerCase((String) chars);
}
int length = chars.length();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(toLowerCase(chars.charAt(i)));
}
return builder.toString();
}
/**
* If the argument is an {@linkplain #isUpperCase(char) uppercase ASCII
* character} returns the lowercase equivalent. Otherwise returns the argument.
*/
public static char toLowerCase(char c) {
return isUpperCase(c) ? (char) (c ^ 0x20) : c;
}
/**
* Returns a copy of the input string in which all
* {@linkplain #isLowerCase(char) lowercase ASCII characters} have been
* converted to uppercase. All other characters are copied without modification.
*/
public static String toUpperCase(String string) {
int length = string.length();
for (int i = 0; i < length; i++) {
if (isLowerCase(string.charAt(i))) {
char[] chars = string.toCharArray();
for (; i < length; i++) {
char c = chars[i];
if (isLowerCase(c)) {
chars[i] = (char) (c & 0x5f);
}
}
return String.valueOf(chars);
}
}
return string;
}
/**
* Returns a copy of the input character sequence in which all
* {@linkplain #isLowerCase(char) lowercase ASCII characters} have been
* converted to uppercase. All other characters are copied without modification.
*
* @since 14.0
*/
public static String toUpperCase(CharSequence chars) {
if (chars instanceof String) {
return toUpperCase((String) chars);
}
int length = chars.length();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(toUpperCase(chars.charAt(i)));
}
return builder.toString();
}
/**
* If the argument is a {@linkplain #isLowerCase(char) lowercase ASCII
* character} returns the uppercase equivalent. Otherwise returns the argument.
*/
public static char toUpperCase(char c) {
return isLowerCase(c) ? (char) (c & 0x5f) : c;
}
/**
* Indicates whether {@code c} is one of the twenty-six lowercase ASCII
* alphabetic characters between {@code 'a'} and {@code 'z'} inclusive. All
* others (including non-ASCII characters) return {@code false}.
*/
public static boolean isLowerCase(char c) {
// Note: This was benchmarked against the alternate expression "(char)(c - 'a')
// < 26" (Nov '13)
// and found to perform at least as well, or better.
return (c >= 'a') && (c <= 'z');
}
/**
* Indicates whether {@code c} is one of the twenty-six uppercase ASCII
* alphabetic characters between {@code 'A'} and {@code 'Z'} inclusive. All
* others (including non-ASCII characters) return {@code false}.
*/
public static boolean isUpperCase(char c) {
return (c >= 'A') && (c <= 'Z');
}
/**
* Truncates the given character sequence to the given maximum length. If the
* length of the sequence is greater than {@code maxLength}, the returned string
* will be exactly {@code maxLength} chars in length and will end with the given
* {@code truncationIndicator}. Otherwise, the sequence will be returned as a
* string with no changes to the content.
*
* <p>
* Examples:
*
* <pre>
* {@code
* Ascii.truncate("foobar", 7, "..."); // returns "foobar"
* Ascii.truncate("foobar", 5, "..."); // returns "fo..." }
* </pre>
*
* <p>
* <b>Note:</b> This method <i>may</i> work with certain non-ASCII text but is
* not safe for use with arbitrary Unicode text. It is mostly intended for use
* with text that is known to be safe for use with it (such as all-ASCII text)
* and for simple debugging text. When using this method, consider the
* following:
*
* <ul>
* <li>it may split surrogate pairs</li>
* <li>it may split characters and combining characters</li>
* <li>it does not consider word boundaries</li>
* <li>if truncating for display to users, there are other considerations that
* must be taken into account</li>
* <li>the appropriate truncation indicator may be locale-dependent</li>
* <li>it is safe to use non-ASCII characters in the truncation indicator</li>
* </ul>
*
*
* @throws IllegalArgumentException if {@code maxLength} is less than the length
* of {@code truncationIndicator}
* @since 16.0
*/
@Beta
@CheckReturnValue
public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
checkNotNull(seq);
// length to truncate the sequence to, not including the truncation indicator
int truncationLength = maxLength - truncationIndicator.length();
// in this worst case, this allows a maxLength equal to the length of the
// truncationIndicator,
// meaning that a string will be truncated to just the truncation indicator
// itself
checkArgument(truncationLength >= 0, "maxLength (%s) must be >= length of the truncation indicator (%s)",
maxLength, truncationIndicator.length());
if (seq.length() <= maxLength) {
String string = seq.toString();
if (string.length() <= maxLength) {
return string;
}
// if the length of the toString() result was > maxLength for some reason,
// truncate that
seq = string;
}
return new StringBuilder(maxLength).append(seq, 0, truncationLength).append(truncationIndicator).toString();
}
/**
* Indicates whether the contents of the given character sequences {@code s1}
* and {@code s2} are equal, ignoring the case of any ASCII alphabetic
* characters between {@code 'a'} and {@code 'z'} or {@code 'A'} and {@code 'Z'}
* inclusive.
*
* <p>
* This method is significantly faster than {@link String#equalsIgnoreCase} and
* should be used in preference if at least one of the parameters is known to
* contain only ASCII characters.
*
* <p>
* Note however that this method does not always behave identically to
* expressions such as:
* <ul>
* <li>{@code string.toUpperCase().equals("UPPER CASE ASCII")}
* <li>{@code string.toLowerCase().equals("lower case ascii")}
* </ul>
* <p>
* due to case-folding of some non-ASCII characters (which does not occur in
* {@link String#equalsIgnoreCase}). However in almost all cases that ASCII
* strings are used, the author probably wanted the behavior provided by this
* method rather than the subtle and sometimes surprising behavior of
* {@code toUpperCase()} and {@code toLowerCase()}.
*
* @since 16.0
*/
@Beta
public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) {
// Calling length() is the null pointer check (so do it before we can exit
// early).
int length = s1.length();
if (s1 == s2) {
return true;
}
if (length != s2.length()) {
return false;
}
for (int i = 0; i < length; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 == c2) {
continue;
}
int alphaIndex = getAlphaIndex(c1);
// This was also benchmarked using '&' to avoid branching (but always evaluate
// the rhs),
// however this showed no obvious improvement.
if (alphaIndex < 26 && alphaIndex == getAlphaIndex(c2)) {
continue;
}
return false;
}
return true;
}
/**
* Returns the non-negative index value of the alpha character {@code c},
* regardless of case. Ie, 'a'/'A' returns 0 and 'z'/'Z' returns 25. Non-alpha
* characters return a value of 26 or greater.
*/
private static int getAlphaIndex(char c) {
// Fold upper-case ASCII to lower-case and make zero-indexed and unsigned (by
// casting to char).
return (char) ((c | 0x20) - 'a');
}
}

View File

@ -0,0 +1,228 @@
/*
* Copyright (C) 2006 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Utility class for converting between various ASCII case formats. Behavior is
* undefined for non-ASCII input.
*
* @author Mike Bostock
* @since 1.0
*/
@GwtCompatible
public enum CaseFormat {
/**
* Hyphenated variable naming convention, e.g., "lower-hyphen".
*/
LOWER_HYPHEN(CharMatcher.is('-'), "-") {
@Override
String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_UNDERSCORE) {
return s.replace('-', '_');
}
if (format == UPPER_UNDERSCORE) {
return Ascii.toUpperCase(s.replace('-', '_'));
}
return super.convert(format, s);
}
},
/**
* C++ variable naming convention, e.g., "lower_underscore".
*/
LOWER_UNDERSCORE(CharMatcher.is('_'), "_") {
@Override
String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return s.replace('_', '-');
}
if (format == UPPER_UNDERSCORE) {
return Ascii.toUpperCase(s);
}
return super.convert(format, s);
}
},
/**
* Java variable naming convention, e.g., "lowerCamel".
*/
LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
@Override
String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
/**
* Java and C++ class naming convention, e.g., "UpperCamel".
*/
UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
@Override
String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
/**
* Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
*/
UPPER_UNDERSCORE(CharMatcher.is('_'), "_") {
@Override
String normalizeWord(String word) {
return Ascii.toUpperCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return Ascii.toLowerCase(s.replace('_', '-'));
}
if (format == LOWER_UNDERSCORE) {
return Ascii.toLowerCase(s);
}
return super.convert(format, s);
}
};
private final CharMatcher wordBoundary;
private final String wordSeparator;
CaseFormat(CharMatcher wordBoundary, String wordSeparator) {
this.wordBoundary = wordBoundary;
this.wordSeparator = wordSeparator;
}
/**
* Converts the specified {@code String str} from this format to the specified
* {@code format}. A "best effort" approach is taken; if {@code str} does not
* conform to the assumed format, then the behavior of this method is undefined
* but we make a reasonable effort at converting anyway.
*/
public final String to(CaseFormat format, String str) {
checkNotNull(format);
checkNotNull(str);
return (format == this) ? str : convert(format, str);
}
/**
* Enum values can override for performance reasons.
*/
String convert(CaseFormat format, String s) {
// deal with camel conversion
StringBuilder out = null;
int i = 0;
int j = -1;
while ((j = wordBoundary.indexIn(s, ++j)) != -1) {
if (i == 0) {
// include some extra space for separators
out = new StringBuilder(s.length() + 4 * wordSeparator.length());
out.append(format.normalizeFirstWord(s.substring(i, j)));
} else {
out.append(format.normalizeWord(s.substring(i, j)));
}
out.append(format.wordSeparator);
i = j + wordSeparator.length();
}
return (i == 0) ? format.normalizeFirstWord(s) : out.append(format.normalizeWord(s.substring(i))).toString();
}
/**
* Returns a {@code Converter} that converts strings from this format to
* {@code targetFormat}.
*
* @since 16.0
*/
@Beta
public Converter<String, String> converterTo(CaseFormat targetFormat) {
return new StringConverter(this, targetFormat);
}
private static final class StringConverter extends Converter<String, String> implements Serializable {
private final CaseFormat sourceFormat;
private final CaseFormat targetFormat;
StringConverter(CaseFormat sourceFormat, CaseFormat targetFormat) {
this.sourceFormat = checkNotNull(sourceFormat);
this.targetFormat = checkNotNull(targetFormat);
}
@Override
protected String doForward(String s) {
// TODO(kevinb): remove null boilerplate (convert() will do it automatically)
return s == null ? null : sourceFormat.to(targetFormat, s);
}
@Override
protected String doBackward(String s) {
// TODO(kevinb): remove null boilerplate (convert() will do it automatically)
return s == null ? null : targetFormat.to(sourceFormat, s);
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof StringConverter) {
StringConverter that = (StringConverter) object;
return sourceFormat.equals(that.sourceFormat) && targetFormat.equals(that.targetFormat);
}
return false;
}
@Override
public int hashCode() {
return sourceFormat.hashCode() ^ targetFormat.hashCode();
}
@Override
public String toString() {
return sourceFormat + ".converterTo(" + targetFormat + ")";
}
private static final long serialVersionUID = 0L;
}
abstract String normalizeWord(String word);
private String normalizeFirstWord(String word) {
return (this == LOWER_CAMEL) ? Ascii.toLowerCase(word) : normalizeWord(word);
}
private static String firstCharOnlyToUpper(String word) {
return (word.isEmpty()) ? word
: new StringBuilder(word.length()).append(Ascii.toUpperCase(word.charAt(0)))
.append(Ascii.toLowerCase(word.substring(1))).toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.nio.charset.Charset;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Contains constant definitions for the six standard {@link Charset} instances,
* which are guaranteed to be supported by all Java platform implementations.
*
* <p>
* Assuming you're free to choose, note that <b>{@link #UTF_8} is widely
* preferred</b>.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Charsets">
* {@code Charsets}</a>.
*
* @author Mike Bostock
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Charsets {
private Charsets() {
}
/**
* UTF-8: eight-bit UCS Transformation Format.
*
*/
public static final Charset UTF_8 = Charset.forName("UTF-8");
/*
* Please do not add new Charset references to this class, unless those
* character encodings are part of the set required to be supported by all Java
* platform implementations! Any Charsets initialized here may cause unexpected
* delays when this class is loaded. See the Charset Javadocs for the list of
* built-in character encodings.
*/
}

View File

@ -0,0 +1,528 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Iterator;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A function from {@code A} to {@code B} with an associated <i>reverse</i>
* function from {@code B} to {@code A}; used for converting back and forth
* between <i>different representations of the same information</i>.
*
* <h3>Invertibility</h3>
*
* <p>
* The reverse operation <b>may</b> be a strict <i>inverse</i> (meaning that
* {@code
* converter.reverse().convert(converter.convert(a)).equals(a)} is always true).
* However, it is very common (perhaps <i>more</i> common) for round-trip
* conversion to be <i>lossy</i>. Consider an example round-trip using
* {@link com.google.common.primitives.Doubles#stringConverter}:
*
* <ol>
* <li>{@code stringConverter().convert("1.00")} returns the {@code Double}
* value {@code 1.0}
* <li>{@code stringConverter().reverse().convert(1.0)} returns the string
* {@code "1.0"} -- <i>not</i> the same string ({@code "1.00"}) we started with
* </ol>
*
* <p>
* Note that it should still be the case that the round-tripped and original
* objects are <i>similar</i>.
*
* <h3>Nullability</h3>
*
* <p>
* A converter always converts {@code null} to {@code null} and non-null
* references to non-null references. It would not make sense to consider
* {@code null} and a non-null reference to be "different representations of the
* same information", since one is distinguishable from <i>missing</i>
* information and the other is not. The {@link #convert} method handles this
* null behavior for all converters; implementations of {@link #doForward} and
* {@link #doBackward} are guaranteed to never be passed {@code null}, and must
* never return {@code null}.
*
*
* <h3>Common ways to use</h3>
*
* <p>
* Getting a converter:
*
* <ul>
* <li>Use a provided converter implementation, such as
* {@link Enums#stringConverter},
* {@link com.google.common.primitives.Ints#stringConverter
* Ints.stringConverter} or the {@linkplain #reverse reverse} views of these.
* <li>Convert between specific preset values using
* {@link com.google.common.collect.Maps#asConverter Maps.asConverter}. For
* example, use this to create a "fake" converter for a unit test. It is
* unnecessary (and confusing) to <i>mock</i> the {@code Converter} type using a
* mocking framework.
* <li>Otherwise, extend this class and implement its {@link #doForward} and
* {@link #doBackward} methods.
* </ul>
*
* <p>
* Using a converter:
*
* <ul>
* <li>Convert one instance in the "forward" direction using
* {@code converter.convert(a)}.
* <li>Convert multiple instances "forward" using
* {@code converter.convertAll(as)}.
* <li>Convert in the "backward" direction using
* {@code converter.reverse().convert(b)} or {@code
* converter.reverse().convertAll(bs)}.
* <li>Use {@code converter} or {@code converter.reverse()} anywhere a
* {@link Function} is accepted
* <li><b>Do not</b> call {@link #doForward} or {@link #doBackward} directly;
* these exist only to be overridden.
* </ul>
*
* @author Mike Ward
* @author Kurt Alfred Kluever
* @author Gregory Kick
* @since 16.0
*/
@Beta
@GwtCompatible
public abstract class Converter<A, B> implements Function<A, B> {
private final boolean handleNullAutomatically;
// We lazily cache the reverse view to avoid allocating on every call to
// reverse().
private transient Converter<B, A> reverse;
/** Constructor for use by subclasses. */
protected Converter() {
this(true);
}
/**
* Constructor used only by {@code LegacyConverter} to suspend automatic
* null-handling.
*/
Converter(boolean handleNullAutomatically) {
this.handleNullAutomatically = handleNullAutomatically;
}
// SPI methods (what subclasses must implement)
/**
* Returns a representation of {@code a} as an instance of type {@code B}. If
* {@code a} cannot be converted, an unchecked exception (such as
* {@link IllegalArgumentException}) should be thrown.
*
* @param a the instance to convert; will never be null
* @return the converted instance; <b>must not</b> be null
*/
protected abstract B doForward(A a);
/**
* Returns a representation of {@code b} as an instance of type {@code A}. If
* {@code b} cannot be converted, an unchecked exception (such as
* {@link IllegalArgumentException}) should be thrown.
*
* @param b the instance to convert; will never be null
* @return the converted instance; <b>must not</b> be null
* @throws UnsupportedOperationException if backward conversion is not
* implemented; this should be very rare.
* Note that if backward conversion is not
* only unimplemented but
* unimplement<i>able</i> (for example,
* consider a
* {@code Converter<Chicken, ChickenNugget>}),
* then this is not logically a
* {@code Converter} at all, and should
* just implement {@link Function}.
*/
protected abstract A doBackward(B b);
// API (consumer-side) methods
/**
* Returns a representation of {@code a} as an instance of type {@code B}.
*
* @return the converted value; is null <i>if and only if</i> {@code a} is null
*/
@Nullable
public final B convert(@Nullable A a) {
return correctedDoForward(a);
}
@Nullable
B correctedDoForward(@Nullable A a) {
if (handleNullAutomatically) {
// TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
return a == null ? null : checkNotNull(doForward(a));
} else {
return doForward(a);
}
}
@Nullable
A correctedDoBackward(@Nullable B b) {
if (handleNullAutomatically) {
// TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
return b == null ? null : checkNotNull(doBackward(b));
} else {
return doBackward(b);
}
}
/**
* Returns an iterable that applies {@code convert} to each element of
* {@code fromIterable}. The conversion is done lazily.
*
* <p>
* The returned iterable's iterator supports {@code remove()} if the input
* iterator does. After a successful {@code remove()} call, {@code fromIterable}
* no longer contains the corresponding element.
*/
public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
checkNotNull(fromIterable, "fromIterable");
return new Iterable<B>() {
@Override
public Iterator<B> iterator() {
return new Iterator<B>() {
private final Iterator<? extends A> fromIterator = fromIterable.iterator();
@Override
public boolean hasNext() {
return fromIterator.hasNext();
}
@Override
public B next() {
return convert(fromIterator.next());
}
@Override
public void remove() {
fromIterator.remove();
}
};
}
};
}
/**
* Returns the reversed view of this converter, which converts
* {@code this.convert(a)} back to a value roughly equivalent to {@code a}.
*
* <p>
* The returned converter is serializable if {@code this} converter is.
*/
// TODO(user): Make this method final
public Converter<B, A> reverse() {
Converter<B, A> result = reverse;
return (result == null) ? reverse = new ReverseConverter<A, B>(this) : result;
}
private static final class ReverseConverter<A, B> extends Converter<B, A> implements Serializable {
final Converter<A, B> original;
ReverseConverter(Converter<A, B> original) {
this.original = original;
}
/*
* These gymnastics are a little confusing. Basically this class has neither
* legacy nor non-legacy behavior; it just needs to let the behavior of the
* backing converter shine through. So, we override the correctedDo* methods,
* after which the do* methods should never be reached.
*/
@Override
protected A doForward(B b) {
throw new AssertionError();
}
@Override
protected B doBackward(A a) {
throw new AssertionError();
}
@Override
@Nullable
A correctedDoForward(@Nullable B b) {
return original.correctedDoBackward(b);
}
@Override
@Nullable
B correctedDoBackward(@Nullable A a) {
return original.correctedDoForward(a);
}
@Override
public Converter<A, B> reverse() {
return original;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ReverseConverter) {
ReverseConverter<?, ?> that = (ReverseConverter<?, ?>) object;
return this.original.equals(that.original);
}
return false;
}
@Override
public int hashCode() {
return ~original.hashCode();
}
@Override
public String toString() {
return original + ".reverse()";
}
private static final long serialVersionUID = 0L;
}
/**
* Returns a converter whose {@code convert} method applies
* {@code secondConverter} to the result of this converter. Its {@code reverse}
* method applies the converters in reverse order.
*
* <p>
* The returned converter is serializable if {@code this} converter and
* {@code secondConverter} are.
*/
public <C> Converter<A, C> andThen(Converter<B, C> secondConverter) {
return new ConverterComposition<A, B, C>(this, checkNotNull(secondConverter));
}
private static final class ConverterComposition<A, B, C> extends Converter<A, C> implements Serializable {
final Converter<A, B> first;
final Converter<B, C> second;
ConverterComposition(Converter<A, B> first, Converter<B, C> second) {
this.first = first;
this.second = second;
}
/*
* These gymnastics are a little confusing. Basically this class has neither
* legacy nor non-legacy behavior; it just needs to let the behaviors of the
* backing converters shine through (which might even differ from each other!).
* So, we override the correctedDo* methods, after which the do* methods should
* never be reached.
*/
@Override
protected C doForward(A a) {
throw new AssertionError();
}
@Override
protected A doBackward(C c) {
throw new AssertionError();
}
@Override
@Nullable
C correctedDoForward(@Nullable A a) {
return second.correctedDoForward(first.correctedDoForward(a));
}
@Override
@Nullable
A correctedDoBackward(@Nullable C c) {
return first.correctedDoBackward(second.correctedDoBackward(c));
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ConverterComposition) {
ConverterComposition<?, ?, ?> that = (ConverterComposition<?, ?, ?>) object;
return this.first.equals(that.first) && this.second.equals(that.second);
}
return false;
}
@Override
public int hashCode() {
return 31 * first.hashCode() + second.hashCode();
}
@Override
public String toString() {
return first + ".andThen(" + second + ")";
}
private static final long serialVersionUID = 0L;
}
/**
* @deprecated Provided to satisfy the {@code Function} interface; use
* {@link #convert} instead.
*/
@Deprecated
@Override
@Nullable
public final B apply(@Nullable A a) {
return convert(a);
}
/**
* Indicates whether another object is equal to this converter.
*
* <p>
* Most implementations will have no reason to override the behavior of
* {@link Object#equals}. However, an implementation may also choose to return
* {@code true} whenever {@code object} is a {@link Converter} that it considers
* <i>interchangeable</i> with this one. "Interchangeable" <i>typically</i>
* means that {@code Objects.equal(this.convert(a), that.convert(a))} is true
* for all {@code a} of type {@code A} (and similarly for {@code reverse}). Note
* that a {@code false} result from this method does not imply that the
* converters are known <i>not</i> to be interchangeable.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
// Static converters
/**
* Returns a converter based on <i>existing</i> forward and backward functions.
* Note that it is unnecessary to create <i>new</i> classes implementing
* {@code Function} just to pass them in here. Instead, simply subclass
* {@code Converter} and implement its {@link #doForward} and
* {@link #doBackward} methods directly.
*
* <p>
* These functions will never be passed {@code null} and must not under any
* circumstances return {@code null}. If a value cannot be converted, the
* function should throw an unchecked exception (typically, but not necessarily,
* {@link IllegalArgumentException}).
*
* <p>
* The returned converter is serializable if both provided functions are.
*
* @since 17.0
*/
public static <A, B> Converter<A, B> from(Function<? super A, ? extends B> forwardFunction,
Function<? super B, ? extends A> backwardFunction) {
return new FunctionBasedConverter<A, B>(forwardFunction, backwardFunction);
}
private static final class FunctionBasedConverter<A, B> extends Converter<A, B> implements Serializable {
private final Function<? super A, ? extends B> forwardFunction;
private final Function<? super B, ? extends A> backwardFunction;
private FunctionBasedConverter(Function<? super A, ? extends B> forwardFunction,
Function<? super B, ? extends A> backwardFunction) {
this.forwardFunction = checkNotNull(forwardFunction);
this.backwardFunction = checkNotNull(backwardFunction);
}
@Override
protected B doForward(A a) {
return forwardFunction.apply(a);
}
@Override
protected A doBackward(B b) {
return backwardFunction.apply(b);
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof FunctionBasedConverter) {
FunctionBasedConverter<?, ?> that = (FunctionBasedConverter<?, ?>) object;
return this.forwardFunction.equals(that.forwardFunction)
&& this.backwardFunction.equals(that.backwardFunction);
}
return false;
}
@Override
public int hashCode() {
return forwardFunction.hashCode() * 31 + backwardFunction.hashCode();
}
@Override
public String toString() {
return "Converter.from(" + forwardFunction + ", " + backwardFunction + ")";
}
}
/**
* Returns a serializable converter that always converts or reverses an object
* to itself.
*/
@SuppressWarnings("unchecked") // implementation is "fully variant"
public static <T> Converter<T, T> identity() {
return (IdentityConverter<T>) IdentityConverter.INSTANCE;
}
/**
* A converter that always converts or reverses an object to itself. Note that T
* is now a "pass-through type".
*/
private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable {
static final IdentityConverter INSTANCE = new IdentityConverter();
@Override
protected T doForward(T t) {
return t;
}
@Override
protected T doBackward(T t) {
return t;
}
@Override
public IdentityConverter<T> reverse() {
return this;
}
@Override
public <S> Converter<T, S> andThen(Converter<T, S> otherConverter) {
return checkNotNull(otherConverter, "otherConverter");
}
/*
* We *could* override convertAll() to return its input, but it's a rather
* pointless optimization and opened up a weird type-safety problem.
*/
@Override
public String toString() {
return "Converter.identity()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0L;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* This class provides default values for all Java types, as defined by the JLS.
*
* @author Ben Yu
* @since 1.0
*/
public final class Defaults {
private Defaults() {
}
private static final Map<Class<?>, Object> DEFAULTS;
static {
// Only add to this map via put(Map, Class<T>, T)
Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
put(map, boolean.class, false);
put(map, char.class, '\0');
put(map, byte.class, (byte) 0);
put(map, short.class, (short) 0);
put(map, int.class, 0);
put(map, long.class, 0L);
put(map, float.class, 0f);
put(map, double.class, 0d);
DEFAULTS = Collections.unmodifiableMap(map);
}
private static <T> void put(Map<Class<?>, Object> map, Class<T> type, T value) {
map.put(type, value);
}
/**
* Returns the default value of {@code type} as defined by JLS --- {@code 0} for
* numbers, {@code
* false} for {@code boolean} and {@code '\0'} for {@code char}. For
* non-primitive types and {@code void}, null is returned.
*/
public static <T> T defaultValue(Class<T> type) {
// Primitives.wrap(type).cast(...) would avoid the warning, but we can't use
// that from here
@SuppressWarnings("unchecked") // the put method enforces this key-value relationship
T t = (T) DEFAULTS.get(checkNotNull(type));
return t;
}
}

View File

@ -0,0 +1,197 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Utility methods for working with {@link Enum} instances.
*
* @author Steve McKay
*
* @since 9.0
*/
@GwtCompatible(emulated = true)
@Beta
public final class Enums {
private Enums() {
}
/**
* Returns a {@link Function} that maps an {@link Enum} name to the associated
* {@code Enum} constant. The {@code Function} will return {@code null} if the
* {@code Enum} constant does not exist.
*
* @param enumClass the {@link Class} of the {@code Enum} declaring the constant
* values
* @deprecated Use {@link Enums#stringConverter} instead. Note that the string
* converter has slightly different behavior: it throws
* {@link IllegalArgumentException} if the enum constant does not
* exist rather than returning {@code null}. It also converts
* {@code null} to {@code null} rather than throwing
* {@link NullPointerException}. This method is scheduled for
* removal in Guava 18.0.
*/
@Deprecated
public static <T extends Enum<T>> Function<String, T> valueOfFunction(Class<T> enumClass) {
return new ValueOfFunction<T>(enumClass);
}
/**
* A {@link Function} that maps an {@link Enum} name to the associated constant,
* or {@code null} if the constant does not exist.
*/
private static final class ValueOfFunction<T extends Enum<T>> implements Function<String, T>, Serializable {
private final Class<T> enumClass;
private ValueOfFunction(Class<T> enumClass) {
this.enumClass = checkNotNull(enumClass);
}
@Override
public T apply(String value) {
try {
return Enum.valueOf(enumClass, value);
} catch (IllegalArgumentException e) {
return null;
}
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof ValueOfFunction && enumClass.equals(((ValueOfFunction) obj).enumClass);
}
@Override
public int hashCode() {
return enumClass.hashCode();
}
@Override
public String toString() {
return "Enums.valueOf(" + enumClass + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns an optional enum constant for the given type, using
* {@link Enum#valueOf}. If the constant does not exist, {@link Optional#absent}
* is returned. A common use case is for parsing user input or falling back to a
* default enum constant. For example,
* {@code Enums.getIfPresent(Country.class, countryInput).or(Country.DEFAULT);}
*
* @since 12.0
*/
public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
checkNotNull(enumClass);
checkNotNull(value);
return Platform.getEnumIfPresent(enumClass, value);
}
@GwtIncompatible("java.lang.ref.WeakReference")
private static final Map<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>> enumConstantCache = new HashMap<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>();
@GwtIncompatible("java.lang.ref.WeakReference")
private static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> populateCache(Class<T> enumClass) {
Map<String, WeakReference<? extends Enum<?>>> result = new HashMap<String, WeakReference<? extends Enum<?>>>();
for (T enumInstance : EnumSet.allOf(enumClass)) {
result.put(enumInstance.name(), new WeakReference<Enum<?>>(enumInstance));
}
enumConstantCache.put(enumClass, result);
return result;
}
@GwtIncompatible("java.lang.ref.WeakReference")
static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> getEnumConstants(Class<T> enumClass) {
synchronized (enumConstantCache) {
Map<String, WeakReference<? extends Enum<?>>> constants = enumConstantCache.get(enumClass);
if (constants == null) {
constants = populateCache(enumClass);
}
return constants;
}
}
/**
* Returns a converter that converts between strings and {@code enum} values of
* type {@code enumClass} using {@link Enum#valueOf(Class, String)} and
* {@link Enum#name()}. The converter will throw an
* {@code IllegalArgumentException} if the argument is not the name of any enum
* constant in the specified enum.
*
* @since 16.0
*/
public static <T extends Enum<T>> Converter<String, T> stringConverter(final Class<T> enumClass) {
return new StringConverter<T>(enumClass);
}
private static final class StringConverter<T extends Enum<T>> extends Converter<String, T> implements Serializable {
private final Class<T> enumClass;
StringConverter(Class<T> enumClass) {
this.enumClass = checkNotNull(enumClass);
}
@Override
protected T doForward(String value) {
return Enum.valueOf(enumClass, value);
}
@Override
protected String doBackward(T enumValue) {
return enumValue.name();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof StringConverter) {
StringConverter<?> that = (StringConverter<?>) object;
return this.enumClass.equals(that.enumClass);
}
return false;
}
@Override
public int hashCode() {
return enumClass.hashCode();
}
@Override
public String toString() {
return "Enums.stringConverter(" + enumClass.getName() + ".class)";
}
private static final long serialVersionUID = 0L;
}
}

View File

@ -0,0 +1,409 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A strategy for determining whether two instances are considered equivalent.
* Examples of equivalences are the {@linkplain #identity() identity
* equivalence} and {@linkplain #equals equals equivalence}.
*
* @author Bob Lee
* @author Ben Yu
* @author Gregory Kick
* @since 10.0
* (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
* >mostly source-compatible</a> since 4.0)
*/
@GwtCompatible
public abstract class Equivalence<T> {
/**
* Constructor for use by subclasses.
*/
protected Equivalence() {
}
/**
* Returns {@code true} if the given objects are considered equivalent.
*
* <p>
* The {@code equivalent} method implements an equivalence relation on object
* references:
*
* <ul>
* <li>It is <i>reflexive</i>: for any reference {@code x}, including null,
* {@code
* equivalent(x, x)} returns {@code true}.
* <li>It is <i>symmetric</i>: for any references {@code x} and {@code y},
* {@code
* equivalent(x, y) == equivalent(y, x)}.
* <li>It is <i>transitive</i>: for any references {@code x}, {@code y}, and
* {@code z}, if {@code equivalent(x, y)} returns {@code true} and
* {@code equivalent(y, z)} returns {@code
* true}, then {@code equivalent(x, z)} returns {@code true}.
* <li>It is <i>consistent</i>: for any references {@code x} and {@code y},
* multiple invocations of {@code equivalent(x, y)} consistently return
* {@code true} or consistently return {@code
* false} (provided that neither {@code x} nor {@code y} is modified).
* </ul>
*/
public final boolean equivalent(@Nullable T a, @Nullable T b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
return doEquivalent(a, b);
}
/**
* Returns {@code true} if {@code a} and {@code b} are considered equivalent.
*
* <p>
* Called by {@link #equivalent}. {@code a} and {@code b} are not the same
* object and are not nulls.
*
* @since 10.0 (previously, subclasses would override equivalent())
*/
protected abstract boolean doEquivalent(T a, T b);
/**
* Returns a hash code for {@code t}.
*
* <p>
* The {@code hash} has the following properties:
* <ul>
* <li>It is <i>consistent</i>: for any reference {@code x}, multiple
* invocations of {@code hash(x}} consistently return the same value provided
* {@code x} remains unchanged according to the definition of the equivalence.
* The hash need not remain consistent from one execution of an application to
* another execution of the same application.
* <li>It is <i>distributable across equivalence</i>: for any references
* {@code x} and {@code y}, if {@code equivalent(x, y)}, then
* {@code hash(x) == hash(y)}. It is <i>not</i> necessary that the hash be
* distributable across <i>inequivalence</i>. If {@code equivalence(x, y)} is
* false, {@code hash(x) == hash(y)} may still be true.
* <li>{@code hash(null)} is {@code 0}.
* </ul>
*/
public final int hash(@Nullable T t) {
if (t == null) {
return 0;
}
return doHash(t);
}
/**
* Returns a hash code for non-null object {@code t}.
*
* <p>
* Called by {@link #hash}.
*
* @since 10.0 (previously, subclasses would override hash())
*/
protected abstract int doHash(T t);
/**
* Returns a new equivalence relation for {@code F} which evaluates equivalence
* by first applying {@code function} to the argument, then evaluating using
* {@code this}. That is, for any pair of non-null objects {@code x} and
* {@code y}, {@code
* equivalence.onResultOf(function).equivalent(a, b)} is true if and only if
* {@code
* equivalence.equivalent(function.apply(a), function.apply(b))} is true.
*
* <p>
* For example:
*
* <pre>
* {
* &#64;code
* Equivalence<Person> SAME_AGE = Equivalence.equals().onResultOf(GET_PERSON_AGE);
* }
* </pre>
*
* <p>
* {@code function} will never be invoked with a null value.
*
* <p>
* Note that {@code function} must be consistent according to {@code this}
* equivalence relation. That is, invoking {@link Function#apply} multiple times
* for a given value must return equivalent results. For example,
* {@code Equivalence.identity().onResultOf(Functions.toStringFunction())} is
* broken because it's not guaranteed that {@link Object#toString}) always
* returns the same string instance.
*
* @since 10.0
*/
public final <F> Equivalence<F> onResultOf(Function<F, ? extends T> function) {
return new FunctionalEquivalence<F, T>(function, this);
}
/**
* Returns a wrapper of {@code reference} that implements
* {@link Wrapper#equals(Object) Object.equals()} such that
* {@code wrap(a).equals(wrap(b))} if and only if {@code equivalent(a, b)}.
*
* @since 10.0
*/
public final <S extends T> Wrapper<S> wrap(@Nullable S reference) {
return new Wrapper<S>(this, reference);
}
/**
* Wraps an object so that {@link #equals(Object)} and {@link #hashCode()}
* delegate to an {@link Equivalence}.
*
* <p>
* For example, given an {@link Equivalence} for {@link String strings} named
* {@code equiv} that tests equivalence using their lengths:
*
* <pre>
* {@code
* equiv.wrap("a").equals(equiv.wrap("b")) // true
* equiv.wrap("a").equals(equiv.wrap("hello")) // false}
* </pre>
*
* <p>
* Note in particular that an equivalence wrapper is never equal to the object
* it wraps.
*
* <pre>
* {@code
* equiv.wrap(obj).equals(obj) // always false}
* </pre>
*
* @since 10.0
*/
public static final class Wrapper<T> implements Serializable {
private final Equivalence<? super T> equivalence;
@Nullable
private final T reference;
private Wrapper(Equivalence<? super T> equivalence, @Nullable T reference) {
this.equivalence = checkNotNull(equivalence);
this.reference = reference;
}
/** Returns the (possibly null) reference wrapped by this instance. */
@Nullable
public T get() {
return reference;
}
/**
* Returns {@code true} if {@link Equivalence#equivalent(Object, Object)}
* applied to the wrapped references is {@code true} and both wrappers use the
* {@link Object#equals(Object) same} equivalence.
*/
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Wrapper) {
Wrapper<?> that = (Wrapper<?>) obj; // note: not necessarily a Wrapper<T>
if (this.equivalence.equals(that.equivalence)) {
/*
* We'll accept that as sufficient "proof" that either equivalence should be
* able to handle either reference, so it's safe to circumvent compile-time type
* checking.
*/
@SuppressWarnings("unchecked")
Equivalence<Object> equivalence = (Equivalence<Object>) this.equivalence;
return equivalence.equivalent(this.reference, that.reference);
}
}
return false;
}
/**
* Returns the result of {@link Equivalence#hash(Object)} applied to the wrapped
* reference.
*/
@Override
public int hashCode() {
return equivalence.hash(reference);
}
/**
* Returns a string representation for this equivalence wrapper. The form of
* this string representation is not specified.
*/
@Override
public String toString() {
return equivalence + ".wrap(" + reference + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns an equivalence over iterables based on the equivalence of their
* elements. More specifically, two iterables are considered equivalent if they
* both contain the same number of elements, and each pair of corresponding
* elements is equivalent according to {@code this}. Null iterables are
* equivalent to one another.
*
* <p>
* Note that this method performs a similar function for equivalences as
* {@link com.google.common.collect.Ordering#lexicographical} does for
* orderings.
*
* @since 10.0
*/
@GwtCompatible(serializable = true)
public final <S extends T> Equivalence<Iterable<S>> pairwise() {
// Ideally, the returned equivalence would support Iterable<? extends T>.
// However,
// the need for this is so rare that it's not worth making callers deal with the
// ugly wildcard.
return new PairwiseEquivalence<S>(this);
}
/**
* Returns a predicate that evaluates to true if and only if the input is
* equivalent to {@code target} according to this equivalence relation.
*
* @since 10.0
*/
@Beta
public final Predicate<T> equivalentTo(@Nullable T target) {
return new EquivalentToPredicate<T>(this, target);
}
private static final class EquivalentToPredicate<T> implements Predicate<T>, Serializable {
private final Equivalence<T> equivalence;
@Nullable
private final T target;
EquivalentToPredicate(Equivalence<T> equivalence, @Nullable T target) {
this.equivalence = checkNotNull(equivalence);
this.target = target;
}
@Override
public boolean apply(@Nullable T input) {
return equivalence.equivalent(input, target);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof EquivalentToPredicate) {
EquivalentToPredicate<?> that = (EquivalentToPredicate<?>) obj;
return equivalence.equals(that.equivalence) && Objects.equal(target, that.target);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(equivalence, target);
}
@Override
public String toString() {
return equivalence + ".equivalentTo(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns an equivalence that delegates to {@link Object#equals} and
* {@link Object#hashCode}. {@link Equivalence#equivalent} returns {@code true}
* if both values are null, or if neither value is null and
* {@link Object#equals} returns {@code true}. {@link Equivalence#hash} returns
* {@code 0} if passed a null value.
*
* @since 13.0
* @since 8.0 (in Equivalences with null-friendly behavior)
* @since 4.0 (in Equivalences)
*/
public static Equivalence<Object> equals() {
return Equals.INSTANCE;
}
/**
* Returns an equivalence that uses {@code ==} to compare values and
* {@link System#identityHashCode(Object)} to compute the hash code.
* {@link Equivalence#equivalent} returns {@code true} if {@code a == b},
* including in the case that a and b are both null.
*
* @since 13.0
* @since 4.0 (in Equivalences)
*/
public static Equivalence<Object> identity() {
return Identity.INSTANCE;
}
static final class Equals extends Equivalence<Object> implements Serializable {
static final Equals INSTANCE = new Equals();
@Override
protected boolean doEquivalent(Object a, Object b) {
return a.equals(b);
}
@Override
public int doHash(Object o) {
return o.hashCode();
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
static final class Identity extends Equivalence<Object> implements Serializable {
static final Identity INSTANCE = new Identity();
@Override
protected boolean doEquivalent(Object a, Object b) {
return false;
}
@Override
protected int doHash(Object o) {
return System.identityHashCode(o);
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
/**
* Phantom reference with a {@code finalizeReferent()} method which a background
* thread invokes after the garbage collector reclaims the referent. This is a
* simpler alternative to using a {@link ReferenceQueue}.
*
* <p>
* Unlike a normal phantom reference, this reference will be cleared
* automatically.
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
public abstract class FinalizablePhantomReference<T> extends PhantomReference<T> implements FinalizableReference {
/**
* Constructs a new finalizable phantom reference.
*
* @param referent to phantom reference
* @param queue that should finalize the referent
*/
protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
/**
* Implemented by references that have code to run after garbage collection of
* their referents.
*
* @see FinalizableReferenceQueue
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
public interface FinalizableReference {
/**
* Invoked on a background thread after the referent has been garbage collected
* unless security restrictions prevented starting a background thread, in which
* case this method is invoked when new references are created.
*/
void finalizeReferent();
}

View File

@ -0,0 +1,371 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
/**
* A reference queue with an associated background thread that dequeues
* references and invokes {@link FinalizableReference#finalizeReferent()} on
* them.
*
* <p>
* Keep a strong reference to this object until all of the associated referents
* have been finalized. If this object is garbage collected earlier, the backing
* thread will not invoke {@code
* finalizeReferent()} on the remaining references.
*
* <p>
* As an example of how this is used, imagine you have a class {@code MyServer}
* that creates a a {@link java.net.ServerSocket ServerSocket}, and you would
* like to ensure that the {@code ServerSocket} is closed even if the
* {@code MyServer} object is garbage-collected without calling its
* {@code close} method. You <em>could</em> use a finalizer to accomplish this,
* but that has a number of well-known problems. Here is how you might use this
* class instead:
*
* <pre>
* public class MyServer implements Closeable {
* private static final FinalizableReferenceQueue frq = new FinalizableReferenceQueue();
* // You might also share this between several objects.
*
* private static final Set&lt;Reference&lt;?>> references = Sets.newConcurrentHashSet();
* // This ensures that the FinalizablePhantomReference itself is not garbage-collected.
*
* private final ServerSocket serverSocket;
*
* private MyServer(...) {
* ...
* this.serverSocket = new ServerSocket(...);
* ...
* }
*
* public static MyServer create(...) {
* MyServer myServer = new MyServer(...);
* final ServerSocket serverSocket = myServer.serverSocket;
* Reference&lt;?> reference = new FinalizablePhantomReference&lt;MyServer>(myServer, frq) {
* &#64;Override public void finalizeReferent() {
* references.remove(this):
* if (!serverSocket.isClosed()) {
* ...log a message about how nobody called close()...
* try {
* serverSocket.close();
* } catch (IOException e) {
* ...
* }
* }
* }
* };
* references.add(reference);
* return myServer;
* }
*
* &#64;Override public void close() {
* serverSocket.close();
* }
* }
* </pre>
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
public class FinalizableReferenceQueue implements Closeable {
/*
* The Finalizer thread keeps a phantom reference to this object. When the
* client (for example, a map built by MapMaker) no longer has a strong
* reference to this object, the garbage collector will reclaim it and enqueue
* the phantom reference. The enqueued reference will trigger the Finalizer to
* stop.
*
* If this library is loaded in the system class loader,
* FinalizableReferenceQueue can load Finalizer directly with no problems.
*
* If this library is loaded in an application class loader, it's important that
* Finalizer not have a strong reference back to the class loader. Otherwise,
* you could have a graph like this:
*
* Finalizer Thread runs instance of -> Finalizer.class loaded by -> Application
* class loader which loaded -> ReferenceMap.class which has a static ->
* FinalizableReferenceQueue instance
*
* Even if no other references to classes from the application class loader
* remain, the Finalizer thread keeps an indirect strong reference to the queue
* in ReferenceMap, which keeps the Finalizer running, and as a result, the
* application class loader can never be reclaimed.
*
* This means that dynamically loaded web applications and OSGi bundles can't be
* unloaded.
*
* If the library is loaded in an application class loader, we try to break the
* cycle by loading Finalizer in its own independent class loader:
*
* System class loader -> Application class loader -> ReferenceMap ->
* FinalizableReferenceQueue -> etc. -> Decoupled class loader -> Finalizer
*
* Now, Finalizer no longer keeps an indirect strong reference to the static
* FinalizableReferenceQueue field in ReferenceMap. The application class loader
* can be reclaimed at which point the Finalizer thread will stop and its
* decoupled class loader can also be reclaimed.
*
* If any of this fails along the way, we fall back to loading Finalizer
* directly in the application class loader.
*/
private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName());
private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer";
/** Reference to Finalizer.startFinalizer(). */
private static final Method startFinalizer;
static {
Class<?> finalizer = loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader());
startFinalizer = getStartFinalizer(finalizer);
}
/**
* The actual reference queue that our background thread will poll.
*/
final ReferenceQueue<Object> queue;
final PhantomReference<Object> frqRef;
/**
* Whether or not the background thread started successfully.
*/
final boolean threadStarted;
/**
* Constructs a new queue.
*/
public FinalizableReferenceQueue() {
// We could start the finalizer lazily, but I'd rather it blow up early.
queue = new ReferenceQueue<Object>();
frqRef = new PhantomReference<Object>(this, queue);
boolean threadStarted = false;
try {
startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef);
threadStarted = true;
} catch (IllegalAccessException impossible) {
throw new AssertionError(impossible); // startFinalizer() is public
} catch (Throwable t) {
logger.log(Level.INFO, "Failed to start reference finalizer thread."
+ " Reference cleanup will only occur when new references are created.", t);
}
this.threadStarted = threadStarted;
}
@Override
public void close() {
frqRef.enqueue();
cleanUp();
}
/**
* Repeatedly dequeues references from the queue and invokes
* {@link FinalizableReference#finalizeReferent()} on them until the queue is
* empty. This method is a no-op if the background thread was created
* successfully.
*/
void cleanUp() {
if (threadStarted) {
return;
}
Reference<?> reference;
while ((reference = queue.poll()) != null) {
/*
* This is for the benefit of phantom references. Weak and soft references will
* have already been cleared by this point.
*/
reference.clear();
try {
((FinalizableReference) reference).finalizeReferent();
} catch (Throwable t) {
logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
}
}
}
/**
* Iterates through the given loaders until it finds one that can load
* Finalizer.
*
* @return Finalizer.class
*/
private static Class<?> loadFinalizer(FinalizerLoader... loaders) {
for (FinalizerLoader loader : loaders) {
Class<?> finalizer = loader.loadFinalizer();
if (finalizer != null) {
return finalizer;
}
}
throw new AssertionError();
}
/**
* Loads Finalizer.class.
*/
interface FinalizerLoader {
/**
* Returns Finalizer.class or null if this loader shouldn't or can't load it.
*
* @throws SecurityException if we don't have the appropriate privileges
*/
Class<?> loadFinalizer();
}
/**
* Tries to load Finalizer from the system class loader. If Finalizer is in the
* system class path, we needn't create a separate loader.
*/
static class SystemLoader implements FinalizerLoader {
// This is used by the ClassLoader-leak test in FinalizableReferenceQueueTest to
// disable
// finding Finalizer on the system class path even if it is there.
@VisibleForTesting
static boolean disabled;
@Override
public Class<?> loadFinalizer() {
if (disabled) {
return null;
}
ClassLoader systemLoader;
try {
systemLoader = ClassLoader.getSystemClassLoader();
} catch (SecurityException e) {
logger.info("Not allowed to access system class loader.");
return null;
}
if (systemLoader != null) {
try {
return systemLoader.loadClass(FINALIZER_CLASS_NAME);
} catch (ClassNotFoundException e) {
// Ignore. Finalizer is simply in a child class loader.
return null;
}
} else {
return null;
}
}
}
/**
* Try to load Finalizer in its own class loader. If Finalizer's thread had a
* direct reference to our class loader (which could be that of a dynamically
* loaded web application or OSGi bundle), it would prevent our class loader
* from getting garbage collected.
*/
static class DecoupledLoader implements FinalizerLoader {
private static final String LOADING_ERROR = "Could not load Finalizer in its own class loader."
+ "Loading Finalizer in the current class loader instead. As a result, you will not be able"
+ "to garbage collect this class loader. To support reclaiming this class loader, either"
+ "resolve the underlying issue, or move Google Collections to your system class path.";
@Override
public Class<?> loadFinalizer() {
try {
/*
* We use URLClassLoader because it's the only concrete class loader
* implementation in the JDK. If we used our own ClassLoader subclass, Finalizer
* would indirectly reference this class loader:
*
* Finalizer.class -> CustomClassLoader -> CustomClassLoader.class -> This class
* loader
*
* System class loader will (and must) be the parent.
*/
ClassLoader finalizerLoader = newLoader(getBaseUrl());
return finalizerLoader.loadClass(FINALIZER_CLASS_NAME);
} catch (Exception e) {
logger.log(Level.WARNING, LOADING_ERROR, e);
return null;
}
}
/**
* Gets URL for base of path containing Finalizer.class.
*/
URL getBaseUrl() throws IOException {
// Find URL pointing to Finalizer.class file.
String finalizerPath = FINALIZER_CLASS_NAME.replace('.', '/') + ".class";
URL finalizerUrl = getClass().getClassLoader().getResource(finalizerPath);
if (finalizerUrl == null) {
throw new FileNotFoundException(finalizerPath);
}
// Find URL pointing to base of class path.
String urlString = finalizerUrl.toString();
if (!urlString.endsWith(finalizerPath)) {
throw new IOException("Unsupported path style: " + urlString);
}
urlString = urlString.substring(0, urlString.length() - finalizerPath.length());
return new URL(finalizerUrl, urlString);
}
/** Creates a class loader with the given base URL as its classpath. */
URLClassLoader newLoader(URL base) {
// We use the bootstrap class loader as the parent because Finalizer by design
// uses
// only standard Java classes. That also means that
// FinalizableReferenceQueueTest
// doesn't pick up the wrong version of the Finalizer class.
return new URLClassLoader(new URL[] { base }, null);
}
}
/**
* Loads Finalizer directly using the current class loader. We won't be able to
* garbage collect this class loader, but at least the world doesn't end.
*/
static class DirectLoader implements FinalizerLoader {
@Override
public Class<?> loadFinalizer() {
try {
return Class.forName(FINALIZER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
}
}
/**
* Looks up Finalizer.startFinalizer().
*/
static Method getStartFinalizer(Class<?> finalizer) {
try {
return finalizer.getMethod("startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
/**
* Soft reference with a {@code finalizeReferent()} method which a background
* thread invokes after the garbage collector reclaims the referent. This is a
* simpler alternative to using a {@link ReferenceQueue}.
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
public abstract class FinalizableSoftReference<T> extends SoftReference<T> implements FinalizableReference {
/**
* Constructs a new finalizable soft reference.
*
* @param referent to softly reference
* @param queue that should finalize the referent
*/
protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* Weak reference with a {@code finalizeReferent()} method which a background
* thread invokes after the garbage collector reclaims the referent. This is a
* simpler alternative to using a {@link ReferenceQueue}.
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
public abstract class FinalizableWeakReference<T> extends WeakReference<T> implements FinalizableReference {
/**
* Constructs a new finalizable weak reference.
*
* @param referent to weakly reference
* @param queue that should finalize the referent
*/
protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Determines an output value based on an input value.
*
* <p>
* The {@link Functions} class provides common functions and related utilites.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use
* of {@code
* Function}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface Function<F, T> {
/**
* Returns the result of applying this function to {@code input}. This method is
* <i>generally expected</i>, but not absolutely required, to have the following
* properties:
*
* <ul>
* <li>Its execution does not cause any observable side effects.
* <li>The computation is <i>consistent with equals</i>; that is,
* {@link Objects#equal Objects.equal}{@code (a, b)} implies that
* {@code Objects.equal(function.apply(a),
* function.apply(b))}.
* </ul>
*
* @throws NullPointerException if {@code input} is null and this function does
* not accept null arguments
*/
@Nullable
T apply(@Nullable F input);
/**
* Indicates whether another object is equal to this function.
*
* <p>
* Most implementations will have no reason to override the behavior of
* {@link Object#equals}. However, an implementation may also choose to return
* {@code true} whenever {@code object} is a {@link Function} that it considers
* <i>interchangeable</i> with this one. "Interchangeable" <i>typically</i>
* means that {@code Objects.equal(this.apply(f), that.apply(f))} is true for
* all {@code f} of type {@code F}. Note that a {@code false} result from this
* method does not imply that the functions are known <i>not</i> to be
* interchangeable.
*/
@Override
boolean equals(@Nullable Object object);
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Equivalence applied on functional result.
*
* @author Bob Lee
* @since 10.0
*/
@Beta
@GwtCompatible
final class FunctionalEquivalence<F, T> extends Equivalence<F> implements Serializable {
private static final long serialVersionUID = 0;
private final Function<F, ? extends T> function;
private final Equivalence<T> resultEquivalence;
FunctionalEquivalence(Function<F, ? extends T> function, Equivalence<T> resultEquivalence) {
this.function = checkNotNull(function);
this.resultEquivalence = checkNotNull(resultEquivalence);
}
@Override
protected boolean doEquivalent(F a, F b) {
return resultEquivalence.equivalent(function.apply(a), function.apply(b));
}
@Override
protected int doHash(F a) {
return resultEquivalence.hash(function.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof FunctionalEquivalence) {
FunctionalEquivalence<?, ?> that = (FunctionalEquivalence<?, ?>) obj;
return function.equals(that.function) && resultEquivalence.equals(that.resultEquivalence);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, resultEquivalence);
}
@Override
public String toString() {
return resultEquivalence + ".onResultOf(" + function + ")";
}
}

View File

@ -0,0 +1,403 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code Function} instances.
*
* <p>
* All methods return serializable functions as long as they're given
* serializable parameters.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use
* of {@code
* Function}</a>.
*
* @author Mike Bostock
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Functions {
private Functions() {
}
/**
* Returns a function that calls {@code toString()} on its argument. The
* function does not accept nulls; it will throw a {@link NullPointerException}
* when applied to {@code null}.
*
* <p>
* <b>Warning:</b> The returned function may not be <i>consistent with
* equals</i> (as documented at {@link Function#apply}). For example, this
* function yields different results for the two equal instances
* {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}.
*/
public static Function<Object, String> toStringFunction() {
return ToStringFunction.INSTANCE;
}
// enum singleton pattern
private enum ToStringFunction implements Function<Object, String> {
INSTANCE;
@Override
public String apply(Object o) {
checkNotNull(o); // eager for GWT.
return o.toString();
}
@Override
public String toString() {
return "toString";
}
}
/**
* Returns the identity function.
*/
// implementation is "fully variant"; E has become a "pass-through" type
@SuppressWarnings("unchecked")
public static <E> Function<E, E> identity() {
return (Function<E, E>) IdentityFunction.INSTANCE;
}
// enum singleton pattern
private enum IdentityFunction implements Function<Object, Object> {
INSTANCE;
@Override
@Nullable
public Object apply(@Nullable Object o) {
return o;
}
@Override
public String toString() {
return "identity";
}
}
/**
* Returns a function which performs a map lookup. The returned function throws
* an {@link IllegalArgumentException} if given a key that does not exist in the
* map. See also {@link #forMap(Map, Object)}, which returns a default value in
* this case.
*
* <p>
* Note: if {@code map} is a {@link com.google.common.collect.BiMap BiMap} (or
* can be one), you can use {@link com.google.common.collect.Maps#asConverter
* Maps.asConverter} instead to get a function that also supports reverse
* conversion.
*/
public static <K, V> Function<K, V> forMap(Map<K, V> map) {
return new FunctionForMapNoDefault<K, V>(map);
}
private static class FunctionForMapNoDefault<K, V> implements Function<K, V>, Serializable {
final Map<K, V> map;
FunctionForMapNoDefault(Map<K, V> map) {
this.map = checkNotNull(map);
}
@Override
public V apply(@Nullable K key) {
V result = map.get(key);
checkArgument(result != null || map.containsKey(key), "Key '%s' not present in map", key);
return result;
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof FunctionForMapNoDefault) {
FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
return map.equals(that.map);
}
return false;
}
@Override
public int hashCode() {
return map.hashCode();
}
@Override
public String toString() {
return "forMap(" + map + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function which performs a map lookup with a default value. The
* function created by this method returns {@code defaultValue} for all inputs
* that do not belong to the map's key set. See also {@link #forMap(Map)}, which
* throws an exception in this case.
*
* @param map source map that determines the function behavior
* @param defaultValue the value to return for inputs that aren't map keys
* @return function that returns {@code map.get(a)} when {@code a} is a key, or
* {@code
* defaultValue} otherwise
*/
public static <K, V> Function<K, V> forMap(Map<K, ? extends V> map, @Nullable V defaultValue) {
return new ForMapWithDefault<K, V>(map, defaultValue);
}
private static class ForMapWithDefault<K, V> implements Function<K, V>, Serializable {
final Map<K, ? extends V> map;
final V defaultValue;
ForMapWithDefault(Map<K, ? extends V> map, @Nullable V defaultValue) {
this.map = checkNotNull(map);
this.defaultValue = defaultValue;
}
@Override
public V apply(@Nullable K key) {
V result = map.get(key);
return (result != null || map.containsKey(key)) ? result : defaultValue;
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof ForMapWithDefault) {
ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o;
return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(map, defaultValue);
}
@Override
public String toString() {
return "forMap(" + map + ", defaultValue=" + defaultValue + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the composition of two functions. For {@code f: A->B} and
* {@code g: B->C}, composition is defined as the function h such that
* {@code h(a) == g(f(a))} for each {@code a}.
*
* @param g the second function to apply
* @param f the first function to apply
* @return the composition of {@code f} and {@code g}
* @see <a href="//en.wikipedia.org/wiki/Function_composition">function
* composition</a>
*/
public static <A, B, C> Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) {
return new FunctionComposition<A, B, C>(g, f);
}
private static class FunctionComposition<A, B, C> implements Function<A, C>, Serializable {
private final Function<B, C> g;
private final Function<A, ? extends B> f;
public FunctionComposition(Function<B, C> g, Function<A, ? extends B> f) {
this.g = checkNotNull(g);
this.f = checkNotNull(f);
}
@Override
public C apply(@Nullable A a) {
return g.apply(f.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof FunctionComposition) {
FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
return f.equals(that.f) && g.equals(that.g);
}
return false;
}
@Override
public int hashCode() {
return f.hashCode() ^ g.hashCode();
}
@Override
public String toString() {
return g + "(" + f + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Creates a function that returns the same boolean output as the given
* predicate for all inputs.
*
* <p>
* The returned function is <i>consistent with equals</i> (as documented at
* {@link Function#apply}) if and only if {@code predicate} is itself consistent
* with equals.
*/
public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate) {
return new PredicateFunction<T>(predicate);
}
/** @see Functions#forPredicate */
private static class PredicateFunction<T> implements Function<T, Boolean>, Serializable {
private final Predicate<T> predicate;
private PredicateFunction(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
@Override
public Boolean apply(@Nullable T t) {
return predicate.apply(t);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof PredicateFunction) {
PredicateFunction<?> that = (PredicateFunction<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
@Override
public int hashCode() {
return predicate.hashCode();
}
@Override
public String toString() {
return "forPredicate(" + predicate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Creates a function that returns {@code value} for any input.
*
* @param value the constant value for the function to return
* @return a function that always returns {@code value}
*/
public static <E> Function<Object, E> constant(@Nullable E value) {
return new ConstantFunction<E>(value);
}
private static class ConstantFunction<E> implements Function<Object, E>, Serializable {
private final E value;
public ConstantFunction(@Nullable E value) {
this.value = value;
}
@Override
public E apply(@Nullable Object from) {
return value;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof ConstantFunction) {
ConstantFunction<?> that = (ConstantFunction<?>) obj;
return Objects.equal(value, that.value);
}
return false;
}
@Override
public int hashCode() {
return (value == null) ? 0 : value.hashCode();
}
@Override
public String toString() {
return "constant(" + value + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function that always returns the result of invoking
* {@link Supplier#get} on {@code
* supplier}, regardless of its input.
*
* @since 10.0
*/
@Beta
public static <T> Function<Object, T> forSupplier(Supplier<T> supplier) {
return new SupplierFunction<T>(supplier);
}
/** @see Functions#forSupplier */
private static class SupplierFunction<T> implements Function<Object, T>, Serializable {
private final Supplier<T> supplier;
private SupplierFunction(Supplier<T> supplier) {
this.supplier = checkNotNull(supplier);
}
@Override
public T apply(@Nullable Object input) {
return supplier.get();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierFunction) {
SupplierFunction<?> that = (SupplierFunction<?>) obj;
return this.supplier.equals(that.supplier);
}
return false;
}
@Override
public int hashCode() {
return supplier.hashCode();
}
@Override
public String toString() {
return "forSupplier(" + supplier + ")";
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,501 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* An object which joins pieces of text (specified as an array,
* {@link Iterable}, varargs or even a {@link Map}) with a separator. It either
* appends the results to an {@link Appendable} or returns them as a
* {@link String}. Example:
*
* <pre>
* {@code
*
* Joiner joiner = Joiner.on("; ").skipNulls();
* . . .
* return joiner.join("Harry", null, "Ron", "Hermione");}
* </pre>
*
* <p>
* This returns the string {@code "Harry; Ron; Hermione"}. Note that all input
* elements are converted to strings using {@link Object#toString()} before
* being appended.
*
* <p>
* If neither {@link #skipNulls()} nor {@link #useForNull(String)} is specified,
* the joining methods will throw {@link NullPointerException} if any given
* element is null.
*
* <p>
* <b>Warning: joiner instances are always immutable</b>; a configuration method
* such as {@code
* useForNull} has no effect on the instance it is invoked on! You must store
* and use the new joiner instance returned by the method. This makes joiners
* thread-safe, and safe to store as {@code
* static final} constants.
*
* <pre>
* {
* &#64;code
*
* // Bad! Do not do this!
* Joiner joiner = Joiner.on(',');
* joiner.skipNulls(); // does nothing!
* return joiner.join("wrong", null, "wrong");
* }
* </pre>
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Joiner">{@code Joiner}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public class Joiner {
/**
* Returns a joiner which automatically places {@code separator} between
* consecutive elements.
*/
public static Joiner on(String separator) {
return new Joiner(separator);
}
/**
* Returns a joiner which automatically places {@code separator} between
* consecutive elements.
*/
public static Joiner on(char separator) {
return new Joiner(String.valueOf(separator));
}
private final String separator;
private Joiner(String separator) {
this.separator = checkNotNull(separator);
}
private Joiner(Joiner prototype) {
this.separator = prototype.separator;
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code appendable}.
*/
public <A extends Appendable> A appendTo(A appendable, Iterable<?> parts) throws IOException {
return appendTo(appendable, parts.iterator());
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code appendable}.
*
* @since 11.0
*/
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
checkNotNull(appendable);
if (parts.hasNext()) {
appendable.append(toString(parts.next()));
while (parts.hasNext()) {
appendable.append(separator);
appendable.append(toString(parts.next()));
}
}
return appendable;
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code appendable}.
*/
public final <A extends Appendable> A appendTo(A appendable, Object[] parts) throws IOException {
return appendTo(appendable, Arrays.asList(parts));
}
/**
* Appends to {@code appendable} the string representation of each of the
* remaining arguments.
*/
public final <A extends Appendable> A appendTo(A appendable, @Nullable Object first, @Nullable Object second,
Object... rest) throws IOException {
return appendTo(appendable, iterable(first, second, rest));
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code builder}. Identical
* to {@link #appendTo(Appendable, Iterable)}, except that it does not throw
* {@link IOException}.
*/
public final StringBuilder appendTo(StringBuilder builder, Iterable<?> parts) {
return appendTo(builder, parts.iterator());
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code builder}. Identical
* to {@link #appendTo(Appendable, Iterable)}, except that it does not throw
* {@link IOException}.
*
* @since 11.0
*/
public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
try {
appendTo((Appendable) builder, parts);
} catch (IOException impossible) {
throw new AssertionError(impossible);
}
return builder;
}
/**
* Appends the string representation of each of {@code parts}, using the
* previously configured separator between each, to {@code builder}. Identical
* to {@link #appendTo(Appendable, Iterable)}, except that it does not throw
* {@link IOException}.
*/
public final StringBuilder appendTo(StringBuilder builder, Object[] parts) {
return appendTo(builder, Arrays.asList(parts));
}
/**
* Appends to {@code builder} the string representation of each of the remaining
* arguments. Identical to
* {@link #appendTo(Appendable, Object, Object, Object...)}, except that it does
* not throw {@link IOException}.
*/
public final StringBuilder appendTo(StringBuilder builder, @Nullable Object first, @Nullable Object second,
Object... rest) {
return appendTo(builder, iterable(first, second, rest));
}
/**
* Returns a string containing the string representation of each of
* {@code parts}, using the previously configured separator between each.
*/
public final String join(Iterable<?> parts) {
return join(parts.iterator());
}
/**
* Returns a string containing the string representation of each of
* {@code parts}, using the previously configured separator between each.
*
* @since 11.0
*/
public final String join(Iterator<?> parts) {
return appendTo(new StringBuilder(), parts).toString();
}
/**
* Returns a string containing the string representation of each of
* {@code parts}, using the previously configured separator between each.
*/
public final String join(Object[] parts) {
return join(Arrays.asList(parts));
}
/**
* Returns a string containing the string representation of each argument, using
* the previously configured separator between each.
*/
public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
return join(iterable(first, second, rest));
}
/**
* Returns a joiner with the same behavior as this one, except automatically
* substituting {@code
* nullText} for any provided null elements.
*/
@CheckReturnValue
public Joiner useForNull(final String nullText) {
checkNotNull(nullText);
return new Joiner(this) {
@Override
CharSequence toString(@Nullable Object part) {
return (part == null) ? nullText : Joiner.this.toString(part);
}
@Override
public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified useForNull");
}
@Override
public Joiner skipNulls() {
throw new UnsupportedOperationException("already specified useForNull");
}
};
}
/**
* Returns a joiner with the same behavior as this joiner, except automatically
* skipping over any provided null elements.
*/
@CheckReturnValue
public Joiner skipNulls() {
return new Joiner(this) {
@Override
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
checkNotNull(appendable, "appendable");
checkNotNull(parts, "parts");
while (parts.hasNext()) {
Object part = parts.next();
if (part != null) {
appendable.append(Joiner.this.toString(part));
break;
}
}
while (parts.hasNext()) {
Object part = parts.next();
if (part != null) {
appendable.append(separator);
appendable.append(Joiner.this.toString(part));
}
}
return appendable;
}
@Override
public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified skipNulls");
}
@Override
public MapJoiner withKeyValueSeparator(String kvs) {
throw new UnsupportedOperationException("can't use .skipNulls() with maps");
}
};
}
/**
* Returns a {@code MapJoiner} using the given key-value separator, and the same
* configuration as this {@code Joiner} otherwise.
*/
@CheckReturnValue
public MapJoiner withKeyValueSeparator(String keyValueSeparator) {
return new MapJoiner(this, keyValueSeparator);
}
/**
* An object that joins map entries in the same manner as {@code Joiner} joins
* iterables and arrays. Like {@code Joiner}, it is thread-safe and immutable.
*
* <p>
* In addition to operating on {@code Map} instances, {@code MapJoiner} can
* operate on {@code
* Multimap} entries in two distinct modes:
*
* <ul>
* <li>To output a separate entry for each key-value pair, pass
* {@code multimap.entries()} to a {@code MapJoiner} method that accepts entries
* as input, and receive output of the form {@code key1=A&key1=B&key2=C}.
* <li>To output a single entry for each key, pass {@code multimap.asMap()} to a
* {@code MapJoiner} method that accepts a map as input, and receive output of
* the form {@code
* key1=[A, B]&key2=C}.
* </ul>
*
* @since 2.0 (imported from Google Collections Library)
*/
public static final class MapJoiner {
private final Joiner joiner;
private final String keyValueSeparator;
private MapJoiner(Joiner joiner, String keyValueSeparator) {
this.joiner = joiner; // only "this" is ever passed, so don't checkNotNull
this.keyValueSeparator = checkNotNull(keyValueSeparator);
}
/**
* Appends the string representation of each entry of {@code map}, using the
* previously configured separator and key-value separator, to
* {@code appendable}.
*/
public <A extends Appendable> A appendTo(A appendable, Map<?, ?> map) throws IOException {
return appendTo(appendable, map.entrySet());
}
/**
* Appends the string representation of each entry of {@code map}, using the
* previously configured separator and key-value separator, to {@code builder}.
* Identical to {@link #appendTo(Appendable, Map)}, except that it does not
* throw {@link IOException}.
*/
public StringBuilder appendTo(StringBuilder builder, Map<?, ?> map) {
return appendTo(builder, map.entrySet());
}
/**
* Returns a string containing the string representation of each entry of
* {@code map}, using the previously configured separator and key-value
* separator.
*/
public String join(Map<?, ?> map) {
return join(map.entrySet());
}
/**
* Appends the string representation of each entry in {@code entries}, using the
* previously configured separator and key-value separator, to
* {@code appendable}.
*
* @since 10.0
*/
@Beta
public <A extends Appendable> A appendTo(A appendable, Iterable<? extends Entry<?, ?>> entries)
throws IOException {
return appendTo(appendable, entries.iterator());
}
/**
* Appends the string representation of each entry in {@code entries}, using the
* previously configured separator and key-value separator, to
* {@code appendable}.
*
* @since 11.0
*/
@Beta
public <A extends Appendable> A appendTo(A appendable, Iterator<? extends Entry<?, ?>> parts)
throws IOException {
checkNotNull(appendable);
if (parts.hasNext()) {
Entry<?, ?> entry = parts.next();
appendable.append(joiner.toString(entry.getKey()));
appendable.append(keyValueSeparator);
appendable.append(joiner.toString(entry.getValue()));
while (parts.hasNext()) {
appendable.append(joiner.separator);
Entry<?, ?> e = parts.next();
appendable.append(joiner.toString(e.getKey()));
appendable.append(keyValueSeparator);
appendable.append(joiner.toString(e.getValue()));
}
}
return appendable;
}
/**
* Appends the string representation of each entry in {@code entries}, using the
* previously configured separator and key-value separator, to {@code builder}.
* Identical to {@link #appendTo(Appendable, Iterable)}, except that it does not
* throw {@link IOException}.
*
* @since 10.0
*/
@Beta
public StringBuilder appendTo(StringBuilder builder, Iterable<? extends Entry<?, ?>> entries) {
return appendTo(builder, entries.iterator());
}
/**
* Appends the string representation of each entry in {@code entries}, using the
* previously configured separator and key-value separator, to {@code builder}.
* Identical to {@link #appendTo(Appendable, Iterable)}, except that it does not
* throw {@link IOException}.
*
* @since 11.0
*/
@Beta
public StringBuilder appendTo(StringBuilder builder, Iterator<? extends Entry<?, ?>> entries) {
try {
appendTo((Appendable) builder, entries);
} catch (IOException impossible) {
throw new AssertionError(impossible);
}
return builder;
}
/**
* Returns a string containing the string representation of each entry in
* {@code entries}, using the previously configured separator and key-value
* separator.
*
* @since 10.0
*/
@Beta
public String join(Iterable<? extends Entry<?, ?>> entries) {
return join(entries.iterator());
}
/**
* Returns a string containing the string representation of each entry in
* {@code entries}, using the previously configured separator and key-value
* separator.
*
* @since 11.0
*/
@Beta
public String join(Iterator<? extends Entry<?, ?>> entries) {
return appendTo(new StringBuilder(), entries).toString();
}
/**
* Returns a map joiner with the same behavior as this one, except automatically
* substituting {@code nullText} for any provided null keys or values.
*/
@CheckReturnValue
public MapJoiner useForNull(String nullText) {
return new MapJoiner(joiner.useForNull(nullText), keyValueSeparator);
}
}
CharSequence toString(Object part) {
checkNotNull(part); // checkNotNull for GWT (do not optimize).
return (part instanceof CharSequence) ? (CharSequence) part : part.toString();
}
private static Iterable<Object> iterable(final Object first, final Object second, final Object[] rest) {
checkNotNull(rest);
return new AbstractList<Object>() {
@Override
public int size() {
return rest.length + 2;
}
@Override
public Object get(int index) {
switch (index) {
case 0:
return first;
case 1:
return second;
default:
return rest[index - 2];
}
}
};
}
}

View File

@ -0,0 +1,448 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Helper functions that can operate on any {@code Object}.
*
* <p>
* See the Guava User Guide on <a href=
* "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
* {@code Object} methods with {@code Objects}</a>.
*
* @author Laurence Gonsalves
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Objects {
private Objects() {
}
/**
* Determines whether two possibly-null objects are equal. Returns:
*
* <ul>
* <li>{@code true} if {@code a} and {@code b} are both null.
* <li>{@code true} if {@code a} and {@code b} are both non-null and they are
* equal according to {@link Object#equals(Object)}.
* <li>{@code false} in all other situations.
* </ul>
*
* <p>
* This assumes that any non-null objects passed to this function conform to the
* {@code equals()} contract.
*/
@CheckReturnValue
public static boolean equal(@Nullable Object a, @Nullable Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Generates a hash code for multiple values. The hash code is generated by
* calling {@link Arrays#hashCode(Object[])}. Note that array arguments to this
* method, with the exception of a single Object array, do not get any special
* handling; their hash codes are based on identity and not contents.
*
* <p>
* This is useful for implementing {@link Object#hashCode()}. For example, in an
* object that has three properties, {@code x}, {@code y}, and {@code z}, one
* could write:
*
* <pre>
* {@code
* public int hashCode() {
* return Objects.hashCode(getX(), getY(), getZ());
* }}
* </pre>
*
* <p>
* <b>Warning</b>: When a single object is supplied, the returned hash code does
* not equal the hash code of that object.
*/
public static int hashCode(@Nullable Object... objects) {
return Arrays.hashCode(objects);
}
/**
* Creates an instance of {@link ToStringHelper}.
*
* <p>
* This is helpful for implementing {@link Object#toString()}. Specification by
* example:
*
* <pre>
* {@code
* // Returns "ClassName{}"
* Objects.toStringHelper(this)
* .toString();
*
* // Returns "ClassName{x=1}"
* Objects.toStringHelper(this)
* .add("x", 1)
* .toString();
*
* // Returns "MyObject{x=1}"
* Objects.toStringHelper("MyObject")
* .add("x", 1)
* .toString();
*
* // Returns "ClassName{x=1, y=foo}"
* Objects.toStringHelper(this)
* .add("x", 1)
* .add("y", "foo")
* .toString();
*
* // Returns "ClassName{x=1}"
* Objects.toStringHelper(this)
* .omitNullValues()
* .add("x", 1)
* .add("y", null)
* .toString();
* }}
* </pre>
*
* <p>
* Note that in GWT, class names are often obfuscated.
*
* @param self the object to generate the string for (typically {@code this}),
* used only for its class name
* @since 2.0
*/
public static ToStringHelper toStringHelper(Object self) {
return new ToStringHelper(simpleName(self.getClass()));
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as
* {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
* instead of using an instance's {@link Object#getClass()}.
*
* <p>
* Note that in GWT, class names are often obfuscated.
*
* @param clazz the {@link Class} of the instance
* @since 7.0 (source-compatible since 2.0)
*/
public static ToStringHelper toStringHelper(Class<?> clazz) {
return new ToStringHelper(simpleName(clazz));
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as
* {@link Objects#toStringHelper(Object)}, but using {@code className} instead
* of using an instance's {@link Object#getClass()}.
*
* @param className the name of the instance type
* @since 7.0 (source-compatible since 2.0)
*/
public static ToStringHelper toStringHelper(String className) {
return new ToStringHelper(className);
}
/**
* {@link Class#getSimpleName()} is not GWT compatible yet, so we provide our
* own implementation.
*/
private static String simpleName(Class<?> clazz) {
String name = clazz.getName();
// the nth anonymous class has a class name ending in "Outer$n"
// and local inner classes have names ending in "Outer.$1Inner"
name = name.replaceAll("\\$[0-9]+", "\\$");
// we want the name of the inner class all by its lonesome
int start = name.lastIndexOf('$');
// if this isn't an inner class, just find the start of the
// top level class name.
if (start == -1) {
start = name.lastIndexOf('.');
}
return name.substring(start + 1);
}
/**
* Returns the first of two given parameters that is not {@code null}, if either
* is, or otherwise throws a {@link NullPointerException}.
*
* <p>
* <b>Note:</b> if {@code first} is represented as an {@link Optional}, this can
* be accomplished with {@linkplain Optional#or(Object) first.or(second)}. That
* approach also allows for lazy evaluation of the fallback instance, using
* {@linkplain Optional#or(Supplier) first.or(Supplier)}.
*
* @return {@code first} if {@code first} is not {@code null}, or {@code second}
* if {@code first} is {@code null} and {@code second} is not
* {@code null}
* @throws NullPointerException if both {@code first} and {@code second} were
* {@code null}
* @since 3.0
*/
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
return first != null ? first : checkNotNull(second);
}
/**
* Support class for {@link Objects#toStringHelper}.
*
* @author Jason Lee
* @since 2.0
*/
public static final class ToStringHelper {
private final String className;
private ValueHolder holderHead = new ValueHolder();
private ValueHolder holderTail = holderHead;
private boolean omitNullValues = false;
/**
* Use {@link Objects#toStringHelper(Object)} to create an instance.
*/
private ToStringHelper(String className) {
this.className = checkNotNull(className);
}
/**
* Configures the {@link ToStringHelper} so {@link #toString()} will ignore
* properties with null value. The order of calling this method, relative to the
* {@code add()}/{@code addValue()} methods, is not significant.
*
* @since 12.0
*/
public ToStringHelper omitNullValues() {
omitNullValues = true;
return this;
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
* If {@code value} is {@code null}, the string {@code "null"} is used, unless
* {@link #omitNullValues()} is called, in which case this name/value pair will
* not be added.
*/
public ToStringHelper add(String name, @Nullable Object value) {
return addHolder(name, value);
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, boolean value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, char value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, double value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, float value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, int value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value} format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, long value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, Object)} instead and
* give value a readable name.
*/
public ToStringHelper addValue(@Nullable Object value) {
return addHolder(value);
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, boolean)} instead and
* give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(boolean value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, char)} instead and give
* value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(char value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, double)} instead and
* give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(double value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, float)} instead and give
* value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(float value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, int)} instead and give
* value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(int value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>
* It is strongly encouraged to use {@link #add(String, long)} instead and give
* value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(long value) {
return addHolder(String.valueOf(value));
}
/**
* Returns a string in the format specified by
* {@link Objects#toStringHelper(Object)}.
*
* <p>
* After calling this method, you can keep adding more properties to later call
* toString() again and get a more complete representation of the same object;
* but properties cannot be removed, so this only allows limited reuse of the
* helper instance. The helper allows duplication of properties (multiple
* name/value pairs with the same name can be added).
*/
@Override
public String toString() {
// create a copy to keep it consistent in case value changes
boolean omitNullValuesSnapshot = omitNullValues;
String nextSeparator = "";
StringBuilder builder = new StringBuilder(32).append(className).append('{');
for (ValueHolder valueHolder = holderHead.next; valueHolder != null; valueHolder = valueHolder.next) {
if (!omitNullValuesSnapshot || valueHolder.value != null) {
builder.append(nextSeparator);
nextSeparator = ", ";
if (valueHolder.name != null) {
builder.append(valueHolder.name).append('=');
}
builder.append(valueHolder.value);
}
}
return builder.append('}').toString();
}
private ValueHolder addHolder() {
ValueHolder valueHolder = new ValueHolder();
holderTail = holderTail.next = valueHolder;
return valueHolder;
}
private ToStringHelper addHolder(@Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
return this;
}
private ToStringHelper addHolder(String name, @Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
valueHolder.name = checkNotNull(name);
return this;
}
private static final class ValueHolder {
String name;
Object value;
ValueHolder next;
}
}
}

View File

@ -0,0 +1,265 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* An immutable object that may contain a non-null reference to another object.
* Each instance of this type either contains a non-null reference, or contains
* nothing (in which case we say that the reference is "absent"); it is never
* said to "contain {@code
* null}".
*
* <p>
* A non-null {@code Optional<T>} reference can be used as a replacement for a
* nullable {@code T} reference. It allows you to represent "a {@code T} that
* must be present" and a "a {@code T} that might be absent" as two distinct
* types in your program, which can aid clarity.
*
* <p>
* Some uses of this class include
*
* <ul>
* <li>As a method return type, as an alternative to returning {@code null} to
* indicate that no value was available
* <li>To distinguish between "unknown" (for example, not present in a map) and
* "known to have no value" (present in the map, with value
* {@code Optional.absent()})
* <li>To wrap nullable references for storage in a collection that does not
* support {@code null} (though there are <a href=
* "http://code.google.com/p/guava-libraries/wiki/LivingWithNullHostileCollections">
* several other approaches to this</a> that should be considered first)
* </ul>
*
* <p>
* A common alternative to using this class is to find or create a suitable
* <a href="http://en.wikipedia.org/wiki/Null_Object_pattern">null object</a>
* for the type in question.
*
* <p>
* This class is not intended as a direct analogue of any existing "option" or
* "maybe" construct from other programming environments, though it may bear
* some similarities.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional">
* using {@code Optional}</a>.
*
* @param <T> the type of instance that can be contained. {@code Optional} is
* naturally covariant on this type, so it is safe to cast an
* {@code Optional<T>} to {@code
* Optional<S>} for any supertype {@code S} of {@code T}.
* @author Kurt Alfred Kluever
* @author Kevin Bourrillion
* @since 10.0
*/
@GwtCompatible(serializable = true)
public abstract class Optional<T> implements Serializable {
/**
* Returns an {@code Optional} instance with no contained reference.
*/
public static <T> Optional<T> absent() {
return Absent.withType();
}
/**
* Returns an {@code Optional} instance containing the given non-null reference.
*/
public static <T> Optional<T> of(T reference) {
return new Present<T>(checkNotNull(reference));
}
/**
* If {@code nullableReference} is non-null, returns an {@code Optional}
* instance containing that reference; otherwise returns
* {@link Optional#absent}.
*/
public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
return (nullableReference == null) ? Optional.<T>absent() : new Present<T>(nullableReference);
}
Optional() {
}
/**
* Returns {@code true} if this holder contains a (non-null) instance.
*/
public abstract boolean isPresent();
/**
* Returns the contained instance, which must be present. If the instance might
* be absent, use {@link #or(Object)} or {@link #orNull} instead.
*
* @throws IllegalStateException if the instance is absent ({@link #isPresent}
* returns {@code false})
*/
public abstract T get();
/**
* Returns the contained instance if it is present; {@code defaultValue}
* otherwise. If no default value should be required because the instance is
* known to be present, use {@link #get()} instead. For a default value of
* {@code null}, use {@link #orNull}.
*
* <p>
* Note about generics: The signature {@code public T or(T defaultValue)} is
* overly restrictive. However, the ideal signature,
* {@code public <S super T> S or(S)}, is not legal Java. As a result, some
* sensible operations involving subtypes are compile errors:
*
* <pre>
* {@code
*
* Optional<Integer> optionalInt = getSomeOptionalInt();
* Number value = optionalInt.or(0.5); // error
*
* FluentIterable<? extends Number> numbers = getSomeNumbers();
* Optional<? extends Number> first = numbers.first();
* Number value = first.or(0.5); // error}
* </pre>
*
* <p>
* As a workaround, it is always safe to cast an {@code Optional<? extends T>}
* to {@code
* Optional<T>}. Casting either of the above example {@code Optional} instances
* to {@code
* Optional<Number>} (where {@code Number} is the desired output type) solves
* the problem:
*
* <pre>
* {@code
*
* Optional<Number> optionalInt = (Optional) getSomeOptionalInt();
* Number value = optionalInt.or(0.5); // fine
*
* FluentIterable<? extends Number> numbers = getSomeNumbers();
* Optional<Number> first = (Optional) numbers.first();
* Number value = first.or(0.5); // fine}
* </pre>
*/
public abstract T or(T defaultValue);
/**
* Returns this {@code Optional} if it has a value present; {@code secondChoice}
* otherwise.
*/
public abstract Optional<T> or(Optional<? extends T> secondChoice);
/**
* Returns the contained instance if it is present; {@code supplier.get()}
* otherwise. If the supplier returns {@code null}, a
* {@link NullPointerException} is thrown.
*
* @throws NullPointerException if the supplier returns {@code null}
*/
@Beta
public abstract T or(Supplier<? extends T> supplier);
/**
* Returns the contained instance if it is present; {@code null} otherwise. If
* the instance is known to be present, use {@link #get()} instead.
*/
@Nullable
public abstract T orNull();
/**
* Returns an immutable singleton {@link Set} whose only element is the
* contained instance if it is present; an empty immutable {@link Set}
* otherwise.
*
* @since 11.0
*/
public abstract Set<T> asSet();
/**
* If the instance is present, it is transformed with the given
* {@link Function}; otherwise, {@link Optional#absent} is returned. If the
* function returns {@code null}, a {@link NullPointerException} is thrown.
*
* @throws NullPointerException if the function returns {@code null}
*
* @since 12.0
*/
public abstract <V> Optional<V> transform(Function<? super T, V> function);
/**
* Returns {@code true} if {@code object} is an {@code Optional} instance, and
* either the contained references are {@linkplain Object#equals equal} to each
* other or both are absent. Note that {@code Optional} instances of differing
* parameterized types can be equal.
*/
@Override
public abstract boolean equals(@Nullable Object object);
/**
* Returns a hash code for this instance.
*/
@Override
public abstract int hashCode();
/**
* Returns a string representation for this instance. The form of this string
* representation is unspecified.
*/
@Override
public abstract String toString();
/**
* Returns the value of each present instance from the supplied
* {@code optionals}, in order, skipping over occurrences of
* {@link Optional#absent}. Iterators are unmodifiable and are evaluated lazily.
*
* @since 11.0 (generics widened in 13.0)
*/
@Beta
public static <T> Iterable<T> presentInstances(final Iterable<? extends Optional<? extends T>> optionals) {
checkNotNull(optionals);
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
private final Iterator<? extends Optional<? extends T>> iterator = checkNotNull(
optionals.iterator());
@Override
protected T computeNext() {
while (iterator.hasNext()) {
Optional<? extends T> optional = iterator.next();
if (optional.isPresent()) {
return optional.get();
}
}
return endOfData();
}
};
}
};
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import java.io.Serializable;
import java.util.Iterator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
@GwtCompatible(serializable = true)
final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>> implements Serializable {
final Equivalence<? super T> elementEquivalence;
PairwiseEquivalence(Equivalence<? super T> elementEquivalence) {
this.elementEquivalence = Preconditions.checkNotNull(elementEquivalence);
}
@Override
protected boolean doEquivalent(Iterable<T> iterableA, Iterable<T> iterableB) {
Iterator<T> iteratorA = iterableA.iterator();
Iterator<T> iteratorB = iterableB.iterator();
while (iteratorA.hasNext() && iteratorB.hasNext()) {
if (!elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) {
return false;
}
}
return !iteratorA.hasNext() && !iteratorB.hasNext();
}
@Override
protected int doHash(Iterable<T> iterable) {
int hash = 78721;
for (T element : iterable) {
hash = hash * 24943 + elementEquivalence.hash(element);
}
return hash;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof PairwiseEquivalence) {
PairwiseEquivalence<?> that = (PairwiseEquivalence<?>) object;
return this.elementEquivalence.equals(that.elementEquivalence);
}
return false;
}
@Override
public int hashCode() {
return elementEquivalence.hashCode() ^ 0x46a3eb07;
}
@Override
public String toString() {
return elementEquivalence + ".pairwise()";
}
private static final long serialVersionUID = 1;
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.base;
import java.lang.ref.WeakReference;
import com.google.common.annotations.GwtCompatible;
/**
* Methods factored out so that they can be emulated differently in GWT.
*
* @author Jesse Wilson
*/
@GwtCompatible(emulated = true)
final class Platform {
private Platform() {
}
/** Calls {@link System#nanoTime()}. */
static long systemNanoTime() {
return System.nanoTime();
}
static CharMatcher precomputeCharMatcher(CharMatcher matcher) {
return matcher.precomputedInternal();
}
static <T extends Enum<T>> Optional<T> getEnumIfPresent(Class<T> enumClass, String value) {
WeakReference<? extends Enum<?>> ref = Enums.getEnumConstants(enumClass).get(value);
return ref == null ? Optional.<T>absent() : Optional.of(enumClass.cast(ref.get()));
}
}

View File

@ -0,0 +1,505 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Static convenience methods that help a method or constructor check whether it
* was invoked correctly (whether its <i>preconditions</i> have been met). These
* methods generally accept a {@code boolean} expression which is expected to be
* {@code true} (or in the case of {@code
* checkNotNull}, an object reference which is expected to be non-null). When
* {@code false} (or {@code null}) is passed instead, the {@code Preconditions}
* method throws an unchecked exception, which helps the calling method
* communicate to <i>its</i> caller that <i>that</i> caller has made a mistake.
* Example:
*
* <pre>
* {@code
*
* /**
* * Returns the positive square root of the given value.
* *
* * @throws IllegalArgumentException if the value is negative
* *}{@code /
* public static double sqrt(double value) {
* Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
* // calculate the square root
* }
*
* void exampleBadCaller() {
* double d = sqrt(-1.0);
* }}
* </pre>
*
* In this example, {@code checkArgument} throws an
* {@code IllegalArgumentException} to indicate that {@code exampleBadCaller}
* made an error in <i>its</i> call to {@code sqrt}.
*
* <h3>Warning about performance</h3>
*
* <p>
* The goal of this class is to improve readability of code, but in some
* circumstances this may come at a significant performance cost. Remember that
* parameter values for message construction must all be computed eagerly, and
* autoboxing and varargs array creation may happen as well, even when the
* precondition check then succeeds (as it should almost always do in
* production). In some circumstances these wasted CPU cycles and allocations
* can add up to a real problem. Performance-sensitive precondition checks can
* always be converted to the customary form:
*
* <pre>
* {@code
*
* if (value < 0.0) {
* throw new IllegalArgumentException("negative value: " + value);
* }}
* </pre>
*
* <h3>Other types of preconditions</h3>
*
* <p>
* Not every type of precondition failure is supported by these methods.
* Continue to throw standard JDK exceptions such as
* {@link java.util.NoSuchElementException} or
* {@link UnsupportedOperationException} in the situations they are intended
* for.
*
* <h3>Non-preconditions</h3>
*
* <p>
* It is of course possible to use the methods of this class to check for
* invalid conditions which are <i>not the caller's fault</i>. Doing so is
* <b>not recommended</b> because it is misleading to future readers of the code
* and of stack traces. See <a href=
* "http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for more advice.
*
* <h3>{@code java.util.Objects.requireNonNull()}</h3>
*
* <p>
* Projects which use {@code com.google.common} should generally avoid the use
* of {@link java.util.Objects#requireNonNull(Object)}. Instead, use whichever
* of {@link #checkNotNull(Object)} or {@link Verify#verifyNotNull(Object)} is
* appropriate to the situation. (The same goes for the message-accepting
* overloads.)
*
* <h3>Only {@code %s} is supported</h3>
*
* <p>
* In {@code Preconditions} error message template strings, only the
* {@code "%s"} specifier is supported, not the full range of
* {@link java.util.Formatter} specifiers. However, note that if the number of
* arguments does not match the number of occurrences of {@code "%s"} in the
* format string, {@code Preconditions} will still behave as expected, and will
* still include all argument values in the error message; the message will
* simply not be formatted exactly as intended.
*
* <h3>More information</h3>
*
* <p>
* See the Guava User Guide on <a href=
* "http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained">using
* {@code
* Preconditions}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Preconditions {
private Preconditions() {
}
/**
* Ensures the truth of an expression involving one or more parameters to the
* calling method.
*
* @param expression a boolean expression
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the
* calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be
* converted to a string using
* {@link String#valueOf(Object)}
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the
* calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing
* each {@code %s} placeholder in the template with
* an argument. These are matched by position - the
* first {@code %s} gets {@code
* errorMessageArgs[0]} , etc. Unmatched arguments will be appended to
* the formatted message in square braces. Unmatched
* placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings
* using {@link String#valueOf(Object)}.
* @throws IllegalArgumentException if {@code expression} is false
* @throws NullPointerException if the check fails and either
* {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let
* this happen)
*/
public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
}
/**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be
* converted to a string using
* {@link String#valueOf(Object)}
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression, @Nullable Object errorMessage) {
if (!expression) {
throw new IllegalStateException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing
* each {@code %s} placeholder in the template with
* an argument. These are matched by position - the
* first {@code %s} gets {@code
* errorMessageArgs[0]} , etc. Unmatched arguments will be appended to
* the formatted message in square braces. Unmatched
* placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings
* using {@link String#valueOf(Object)}.
* @throws IllegalStateException if {@code expression} is false
* @throws NullPointerException if the check fails and either
* {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let
* this happen)
*/
public static void checkState(boolean expression, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures that an object reference passed as a parameter to the calling method
* is not null.
*
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method
* is not null.
*
* @param reference an object reference
* @param errorMessage the exception message to use if the check fails; will be
* converted to a string using
* {@link String#valueOf(Object)}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method
* is not null.
*
* @param reference an object reference
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing
* each {@code %s} placeholder in the template with
* an argument. These are matched by position - the
* first {@code %s} gets {@code
* errorMessageArgs[0]} , etc. Unmatched arguments will be appended to
* the formatted message in square braces. Unmatched
* placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings
* using {@link String#valueOf(Object)}.
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (reference == null) {
// If either of these parameters is null, the right thing happens anyway
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
}
return reference;
}
/*
* All recent hotspots (as of 2009) *really* like to have the natural code
*
* if (guardExpression) { throw new BadException(messageExpression); }
*
* refactored so that messageExpression is moved to a separate String-returning
* method.
*
* if (guardExpression) { throw new BadException(badMsg(...)); }
*
* The alternative natural refactorings into void or Exception-returning methods
* are much slower. This is a big deal - we're talking factors of 2-8 in
* microbenchmarks, not just 10-20%. (This is a hotspot optimizer bug, which
* should be fixed, but that's a separate, big project).
*
* The coding pattern above is heavily used in java.util, e.g. in ArrayList.
* There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
*
* But the methods in this class want to throw different exceptions, depending
* on the args, so it appears that this pattern is not directly applicable. But
* we can use the ridiculous, devious trick of throwing an exception in the
* middle of the construction of another exception. Hotspot is fine with that.
*/
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list
* or string of size {@code size}. An element index may range from zero,
* inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list
* or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less
* than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkElementIndex(int index, int size) {
return checkElementIndex(index, size, "index");
}
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list
* or string of size {@code size}. An element index may range from zero,
* inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list
* or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less
* than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkElementIndex(int index, int size, @Nullable String desc) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
}
return index;
}
private static String badElementIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index >= size
return format("%s (%s) must be less than size (%s)", desc, index, size);
}
}
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array,
* list or string of size {@code size}. A position index may range from zero to
* {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list
* or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater
* than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkPositionIndex(int index, int size) {
return checkPositionIndex(index, size, "index");
}
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array,
* list or string of size {@code size}. A position index may range from zero to
* {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list
* or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater
* than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkPositionIndex(int index, int size, @Nullable String desc) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
}
return index;
}
private static String badPositionIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index > size
return format("%s (%s) must not be greater than size (%s)", desc, index, size);
}
}
/**
* Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
* in an array, list or string of size {@code size}, and are in order. A
* position index may range from zero to {@code size}, inclusive.
*
* @param start a user-supplied index identifying a starting position in an
* array, list or string
* @param end a user-supplied index identifying a ending position in an array,
* list or string
* @param size the size of that array, list or string
* @throws IndexOutOfBoundsException if either index is negative or is greater
* than {@code size}, or if {@code end} is
* less than {@code start}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static void checkPositionIndexes(int start, int end, int size) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (start < 0 || end < start || end > size) {
throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
}
}
private static String badPositionIndexes(int start, int end, int size) {
if (start < 0 || start > size) {
return badPositionIndex(start, size, "start index");
}
if (end < 0 || end > size) {
return badPositionIndex(end, size, "end index");
}
// end < start
return format("end index (%s) must not be less than start index (%s)", end, start);
}
/**
* Substitutes each {@code %s} in {@code template} with an argument. These are
* matched by position: the first {@code %s} gets {@code args[0]}, etc. If there
* are more arguments than placeholders, the unmatched arguments will be
* appended to the end of the formatted message in square braces.
*
* @param template a non-null string containing 0 or more {@code %s}
* placeholders.
* @param args the arguments to be substituted into the message template.
* Arguments are converted to strings using
* {@link String#valueOf(Object)}. Arguments can be null.
*/
// Note that this is somewhat-improperly used from Verify.java as well.
static String format(String template, @Nullable Object... args) {
template = String.valueOf(template); // null -> "null"
// start substituting the arguments into the '%s' placeholders
StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
int templateStart = 0;
int i = 0;
while (i < args.length) {
int placeholderStart = template.indexOf("%s", templateStart);
if (placeholderStart == -1) {
break;
}
builder.append(template.substring(templateStart, placeholderStart));
builder.append(args[i++]);
templateStart = placeholderStart + 2;
}
builder.append(template.substring(templateStart));
// if we run out of placeholders, append the extra args in square braces
if (i < args.length) {
builder.append(" [");
builder.append(args[i++]);
while (i < args.length) {
builder.append(", ");
builder.append(args[i++]);
}
builder.append(']');
}
return builder.toString();
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Determines a true or false value for a given input.
*
* <p>
* The {@link Predicates} class provides common predicates and related
* utilities.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use
* of {@code
* Predicate}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface Predicate<T> {
/**
* Returns the result of applying this predicate to {@code input}. This method
* is <i>generally expected</i>, but not absolutely required, to have the
* following properties:
*
* <ul>
* <li>Its execution does not cause any observable side effects.
* <li>The computation is <i>consistent with equals</i>; that is,
* {@link Objects#equal Objects.equal}{@code (a, b)} implies that
* {@code predicate.apply(a) ==
* predicate.apply(b))}.
* </ul>
*
* @throws NullPointerException if {@code input} is null and this predicate does
* not accept null arguments
*/
boolean apply(@Nullable T input);
/**
* Indicates whether another object is equal to this predicate.
*
* <p>
* Most implementations will have no reason to override the behavior of
* {@link Object#equals}. However, an implementation may also choose to return
* {@code true} whenever {@code object} is a {@link Predicate} that it considers
* <i>interchangeable</i> with this one. "Interchangeable" <i>typically</i>
* means that {@code this.apply(t) == that.apply(t)} for all {@code t} of type
* {@code T}). Note that a {@code false} result from this method does not imply
* that the predicates are known <i>not</i> to be interchangeable.
*/
@Override
boolean equals(@Nullable Object object);
}

View File

@ -0,0 +1,710 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Static utility methods pertaining to {@code Predicate} instances.
*
* <p>
* All methods returns serializable predicates as long as they're given
* serializable parameters.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use
* of {@code Predicate}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class Predicates {
private Predicates() {
}
// TODO(kevinb): considering having these implement a VisitablePredicate
// interface which specifies an accept(PredicateVisitor) method.
/**
* Returns a predicate that always evaluates to {@code true}.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysTrue() {
return ObjectPredicate.ALWAYS_TRUE.withNarrowedType();
}
/**
* Returns a predicate that always evaluates to {@code false}.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysFalse() {
return ObjectPredicate.ALWAYS_FALSE.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is null.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> isNull() {
return ObjectPredicate.IS_NULL.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is not null.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> notNull() {
return ObjectPredicate.NOT_NULL.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the given predicate
* evaluates to {@code false}.
*/
public static <T> Predicate<T> not(Predicate<T> predicate) {
return new NotPredicate<T>(predicate);
}
/**
* Returns a predicate that evaluates to {@code true} if each of its components
* evaluates to {@code true}. The components are evaluated in order, and
* evaluation will be "short-circuited" as soon as a false predicate is found.
* It defensively copies the iterable passed in, so future changes to it won't
* alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if each of its components
* evaluates to {@code true}. The components are evaluated in order, and
* evaluation will be "short-circuited" as soon as a false predicate is found.
* It defensively copies the array passed in, so future changes to it won't
* alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
public static <T> Predicate<T> and(Predicate<? super T>... components) {
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if both of its components
* evaluate to {@code true}. The components are evaluated in order, and
* evaluation will be "short-circuited" as soon as a false predicate is found.
*/
public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
return new AndPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* Returns a predicate that evaluates to {@code true} if any one of its
* components evaluates to {@code true}. The components are evaluated in order,
* and evaluation will be "short-circuited" as soon as a true predicate is
* found. It defensively copies the iterable passed in, so future changes to it
* won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if any one of its
* components evaluates to {@code true}. The components are evaluated in order,
* and evaluation will be "short-circuited" as soon as a true predicate is
* found. It defensively copies the array passed in, so future changes to it
* won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
public static <T> Predicate<T> or(Predicate<? super T>... components) {
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if either of its
* components evaluates to {@code true}. The components are evaluated in order,
* and evaluation will be "short-circuited" as soon as a true predicate is
* found.
*/
public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
return new OrPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* Returns a predicate that evaluates to {@code true} if the object being tested
* {@code equals()} the given target or both are null.
*/
public static <T> Predicate<T> equalTo(@Nullable T target) {
return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
}
/**
* Returns a predicate that evaluates to {@code true} if the object being tested
* is an instance of the given class. If the object being tested is {@code null}
* this predicate evaluates to {@code false}.
*
* <p>
* If you want to filter an {@code Iterable} to narrow its type, consider using
* {@link com.google.common.collect.Iterables#filter(Iterable, Class)} in
* preference.
*
* <p>
* <b>Warning:</b> contrary to the typical assumptions about predicates (as
* documented at {@link Predicate#apply}), the returned predicate may not be
* <i>consistent with equals</i>. For example, {@code
* instanceOf(ArrayList.class)} will yield different results for the two equal
* instances {@code Lists.newArrayList(1)} and {@code Arrays.asList(1)}.
*/
@GwtIncompatible("Class.isInstance")
public static Predicate<Object> instanceOf(Class<?> clazz) {
return new InstanceOfPredicate(clazz);
}
/**
* Returns a predicate that evaluates to {@code true} if the class being tested
* is assignable from the given class. The returned predicate does not allow
* null inputs.
*
* @since 10.0
*/
@GwtIncompatible("Class.isAssignableFrom")
@Beta
public static Predicate<Class<?>> assignableFrom(Class<?> clazz) {
return new AssignableFromPredicate(clazz);
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is a member of the given collection. It does not defensively
* copy the collection passed in, so future changes to it will alter the
* behavior of the predicate.
*
* <p>
* This method can technically accept any {@code Collection<?>}, but using a
* typed collection helps prevent bugs. This approach doesn't block any
* potential users since it is always possible to use {@code
* Predicates.<Object>in()}.
*
* @param target the collection that may contain the function input
*/
public static <T> Predicate<T> in(Collection<? extends T> target) {
return new InPredicate<T>(target);
}
/**
* Returns the composition of a function and a predicate. For every {@code x},
* the generated predicate returns {@code predicate(function(x))}.
*
* @return the composition of the provided function and predicate
*/
public static <A, B> Predicate<A> compose(Predicate<B> predicate, Function<A, ? extends B> function) {
return new CompositionPredicate<A, B>(predicate, function);
}
/**
* Returns a predicate that evaluates to {@code true} if the
* {@code CharSequence} being tested contains any match for the given regular
* expression pattern. The test used is equivalent to
* {@code Pattern.compile(pattern).matcher(arg).find()}
*
* @throws java.util.regex.PatternSyntaxException if the pattern is invalid
* @since 3.0
*/
@GwtIncompatible(value = "java.util.regex.Pattern")
public static Predicate<CharSequence> containsPattern(String pattern) {
return new ContainsPatternFromStringPredicate(pattern);
}
/**
* Returns a predicate that evaluates to {@code true} if the
* {@code CharSequence} being tested contains any match for the given regular
* expression pattern. The test used is equivalent to
* {@code pattern.matcher(arg).find()}
*
* @since 3.0
*/
@GwtIncompatible(value = "java.util.regex.Pattern")
public static Predicate<CharSequence> contains(Pattern pattern) {
return new ContainsPatternPredicate(pattern);
}
// End public API, begin private implementation classes.
// Package private for GWT serialization.
enum ObjectPredicate implements Predicate<Object> {
/** @see Predicates#alwaysTrue() */
ALWAYS_TRUE {
@Override
public boolean apply(@Nullable Object o) {
return true;
}
@Override
public String toString() {
return "Predicates.alwaysTrue()";
}
},
/** @see Predicates#alwaysFalse() */
ALWAYS_FALSE {
@Override
public boolean apply(@Nullable Object o) {
return false;
}
@Override
public String toString() {
return "Predicates.alwaysFalse()";
}
},
/** @see Predicates#isNull() */
IS_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o == null;
}
@Override
public String toString() {
return "Predicates.isNull()";
}
},
/** @see Predicates#notNull() */
NOT_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o != null;
}
@Override
public String toString() {
return "Predicates.notNull()";
}
};
@SuppressWarnings("unchecked") // safe contravariant cast
<T> Predicate<T> withNarrowedType() {
return (Predicate<T>) this;
}
}
/** @see Predicates#not(Predicate) */
private static class NotPredicate<T> implements Predicate<T>, Serializable {
final Predicate<T> predicate;
NotPredicate(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
@Override
public boolean apply(@Nullable T t) {
return !predicate.apply(t);
}
@Override
public int hashCode() {
return ~predicate.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate<?> that = (NotPredicate<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
@Override
public String toString() {
return "Predicates.not(" + predicate.toString() + ")";
}
private static final long serialVersionUID = 0;
}
private static final Joiner COMMA_JOINER = Joiner.on(',');
/** @see Predicates#and(Iterable) */
private static class AndPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private AndPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (!components.get(i).apply(t)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with OrPredicate
return components.hashCode() + 0x12472c2c;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate<?> that = (AndPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#or(Iterable) */
private static class OrPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private OrPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (components.get(i).apply(t)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with AndPredicate
return components.hashCode() + 0x053c91cf;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate<?> that = (OrPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return "Predicates.or(" + COMMA_JOINER.join(components) + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#equalTo(Object) */
private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
private final T target;
private IsEqualToPredicate(T target) {
this.target = target;
}
@Override
public boolean apply(T t) {
return target.equals(t);
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof IsEqualToPredicate) {
IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public String toString() {
return "Predicates.equalTo(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#instanceOf(Class) */
@GwtIncompatible("Class.isInstance")
private static class InstanceOfPredicate implements Predicate<Object>, Serializable {
private final Class<?> clazz;
private InstanceOfPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(@Nullable Object o) {
return clazz.isInstance(o);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InstanceOfPredicate) {
InstanceOfPredicate that = (InstanceOfPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.instanceOf(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#assignableFrom(Class) */
@GwtIncompatible("Class.isAssignableFrom")
private static class AssignableFromPredicate implements Predicate<Class<?>>, Serializable {
private final Class<?> clazz;
private AssignableFromPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(Class<?> input) {
return clazz.isAssignableFrom(input);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof AssignableFromPredicate) {
AssignableFromPredicate that = (AssignableFromPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.assignableFrom(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#in(Collection) */
private static class InPredicate<T> implements Predicate<T>, Serializable {
private final Collection<?> target;
private InPredicate(Collection<?> target) {
this.target = checkNotNull(target);
}
@Override
public boolean apply(@Nullable T t) {
try {
return target.contains(t);
} catch (NullPointerException e) {
return false;
} catch (ClassCastException e) {
return false;
}
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InPredicate) {
InPredicate<?> that = (InPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public String toString() {
return "Predicates.in(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#compose(Predicate, Function) */
private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
final Predicate<B> p;
final Function<A, ? extends B> f;
private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) {
this.p = checkNotNull(p);
this.f = checkNotNull(f);
}
@Override
public boolean apply(@Nullable A a) {
return p.apply(f.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof CompositionPredicate) {
CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
return f.equals(that.f) && p.equals(that.p);
}
return false;
}
@Override
public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
@Override
public String toString() {
return p.toString() + "(" + f.toString() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#contains(Pattern) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
final Pattern pattern;
ContainsPatternPredicate(Pattern pattern) {
this.pattern = checkNotNull(pattern);
}
@Override
public boolean apply(CharSequence t) {
return pattern.matcher(t).find();
}
@Override
public int hashCode() {
// Pattern uses Object.hashCode, so we have to reach
// inside to build a hashCode consistent with equals.
return Objects.hashCode(pattern.pattern(), pattern.flags());
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof ContainsPatternPredicate) {
ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
// Pattern uses Object (identity) equality, so we have to reach
// inside to compare individual fields.
return Objects.equal(pattern.pattern(), that.pattern.pattern())
&& Objects.equal(pattern.flags(), that.pattern.flags());
}
return false;
}
@Override
public String toString() {
String patternString = Objects.toStringHelper(pattern).add("pattern", pattern.pattern())
.add("pattern.flags", pattern.flags()).toString();
return "Predicates.contains(" + patternString + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#containsPattern(String) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
ContainsPatternFromStringPredicate(String string) {
super(Pattern.compile(string));
}
@Override
public String toString() {
return "Predicates.containsPattern(" + pattern.pattern() + ")";
}
private static final long serialVersionUID = 0;
}
private static <T> List<Predicate<? super T>> asList(Predicate<? super T> first, Predicate<? super T> second) {
// TODO(kevinb): understand why we still get a warning despite @SafeVarargs!
return Arrays.<Predicate<? super T>>asList(first, second);
}
private static <T> List<T> defensiveCopy(T... array) {
return defensiveCopy(Arrays.asList(array));
}
static <T> List<T> defensiveCopy(Iterable<T> iterable) {
ArrayList<T> list = new ArrayList<T>();
for (T element : iterable) {
list.add(checkNotNull(element));
}
return list;
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of an {@link Optional} containing a reference.
*/
@GwtCompatible
final class Present<T> extends Optional<T> {
private final T reference;
Present(T reference) {
this.reference = reference;
}
@Override
public boolean isPresent() {
return true;
}
@Override
public T get() {
return reference;
}
@Override
public T or(T defaultValue) {
checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
return reference;
}
@Override
public Optional<T> or(Optional<? extends T> secondChoice) {
checkNotNull(secondChoice);
return this;
}
@Override
public T or(Supplier<? extends T> supplier) {
checkNotNull(supplier);
return reference;
}
@Override
public T orNull() {
return reference;
}
@Override
public Set<T> asSet() {
return Collections.singleton(reference);
}
@Override
public <V> Optional<V> transform(Function<? super T, V> function) {
return new Present<V>(checkNotNull(function.apply(reference),
"the Function passed to Optional.transform() must not return null."));
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Present) {
Present<?> other = (Present<?>) object;
return reference.equals(other.reference);
}
return false;
}
@Override
public int hashCode() {
return 0x598df91c + reference.hashCode();
}
@Override
public String toString() {
return "Optional.of(" + reference + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.base;
import java.util.BitSet;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher.FastMatcher;
/**
* An immutable version of CharMatcher for smallish sets of characters that uses
* a hash table with linear probing to check for matches.
*
* @author Christopher Swenson
*/
@GwtIncompatible("no precomputation is done in GWT")
final class SmallCharMatcher extends FastMatcher {
static final int MAX_SIZE = 1023;
private final char[] table;
private final boolean containsZero;
private final long filter;
private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) {
super(description);
this.table = table;
this.filter = filter;
this.containsZero = containsZero;
}
private static final int C1 = 0xcc9e2d51;
private static final int C2 = 0x1b873593;
/*
* This method was rewritten in Java from an intermediate step of the Murmur
* hash function in
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which
* contained the following header:
*
* MurmurHash3 was written by Austin Appleby, and is placed in the public
* domain. The author hereby disclaims copyright to this source code.
*/
static int smear(int hashCode) {
return C2 * Integer.rotateLeft(hashCode * C1, 15);
}
private boolean checkFilter(int c) {
return 1 == (1 & (filter >> c));
}
// This is all essentially copied from ImmutableSet, but we have to duplicate
// because
// of dependencies.
// Represents how tightly we can pack things, as a maximum.
private static final double DESIRED_LOAD_FACTOR = 0.5;
/**
* Returns an array size suitable for the backing array of a hash table that
* uses open addressing with linear probing in its implementation. The returned
* size is the smallest power of two that can hold setSize elements with the
* desired load factor.
*/
@VisibleForTesting
static int chooseTableSize(int setSize) {
if (setSize == 1) {
return 2;
}
// Correct the size for open addressing to match desired load factor.
// Round up to the next highest power of 2.
int tableSize = Integer.highestOneBit(setSize - 1) << 1;
while (tableSize * DESIRED_LOAD_FACTOR < setSize) {
tableSize <<= 1;
}
return tableSize;
}
static CharMatcher from(BitSet chars, String description) {
// Compute the filter.
long filter = 0;
int size = chars.cardinality();
boolean containsZero = chars.get(0);
// Compute the hash table.
char[] table = new char[chooseTableSize(size)];
int mask = table.length - 1;
for (int c = chars.nextSetBit(0); c != -1; c = chars.nextSetBit(c + 1)) {
// Compute the filter at the same time.
filter |= 1L << c;
int index = smear(c) & mask;
while (true) {
// Check for empty.
if (table[index] == 0) {
table[index] = (char) c;
break;
}
// Linear probing.
index = (index + 1) & mask;
}
}
return new SmallCharMatcher(table, filter, containsZero, description);
}
@Override
public boolean matches(char c) {
if (c == 0) {
return containsZero;
}
if (!checkFilter(c)) {
return false;
}
int mask = table.length - 1;
int startingIndex = smear(c) & mask;
int index = startingIndex;
do {
// Check for empty.
if (table[index] == 0) {
return false;
// Check for match.
} else if (table[index] == c) {
return true;
} else {
// Linear probing.
index = (index + 1) & mask;
}
// Check to see if we wrapped around the whole table.
} while (index != startingIndex);
return false;
}
@Override
void setBits(BitSet table) {
if (containsZero) {
table.set(0);
}
for (char c : this.table) {
if (c != 0) {
table.set(c);
}
}
}
}

View File

@ -0,0 +1,650 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.CheckReturnValue;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Extracts non-overlapping substrings from an input string, typically by
* recognizing appearances of a <i>separator</i> sequence. This separator can be
* specified as a single {@linkplain #on(char) character}, fixed
* {@linkplain #on(String) string}, {@linkplain #onPattern regular expression}
* or {@link #on(CharMatcher) CharMatcher} instance. Or, instead of using a
* separator at all, a splitter can extract adjacent substrings of a given
* {@linkplain #fixedLength fixed length}.
*
* <p>
* For example, this expression:
*
* <pre>
* {@code
*
* Splitter.on(',').split("foo,bar,qux")}
* </pre>
*
* ... produces an {@code Iterable} containing {@code "foo"}, {@code "bar"} and
* {@code "qux"}, in that order.
*
* <p>
* By default, {@code Splitter}'s behavior is simplistic and unassuming. The
* following expression:
*
* <pre>
* {@code
*
* Splitter.on(',').split(" foo,,, bar ,")}
* </pre>
*
* ... yields the substrings {@code [" foo", "", "", " bar ", ""]}. If this is
* not the desired behavior, use configuration methods to obtain a <i>new</i>
* splitter instance with modified behavior:
*
* <pre>
* {
* &#64;code
*
* private static final Splitter MY_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
* }
* </pre>
*
* <p>
* Now {@code MY_SPLITTER.split("foo,,, bar ,")} returns just {@code ["foo",
* "bar"]}. Note that the order in which these configuration methods are called
* is never significant.
*
* <p>
* <b>Warning:</b> Splitter instances are immutable. Invoking a configuration
* method has no effect on the receiving instance; you must store and use the
* new splitter instance it returns instead.
*
* <pre>
* {
* &#64;code
*
* // Do NOT do this
* Splitter splitter = Splitter.on('/');
* splitter.trimResults(); // does nothing!
* return splitter.split("wrong / wrong / wrong");
* }
* </pre>
*
* <p>
* For separator-based splitters that do not use {@code omitEmptyStrings}, an
* input string containing {@code n} occurrences of the separator naturally
* yields an iterable of size {@code n + 1}. So if the separator does not occur
* anywhere in the input, a single substring is returned containing the entire
* input. Consequently, all splitters split the empty string to {@code [""]}
* (note: even fixed-length splitters).
*
* <p>
* Splitter instances are thread-safe immutable, and are therefore safe to store
* as {@code static final} constants.
*
* <p>
* The {@link Joiner} class provides the inverse operation to splitting, but
* note that a round-trip between the two should be assumed to be lossy.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Splitter">
* {@code Splitter}</a>.
*
* @author Julien Silland
* @author Jesse Wilson
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Splitter {
private final CharMatcher trimmer;
private final boolean omitEmptyStrings;
private final Strategy strategy;
private final int limit;
private Splitter(Strategy strategy) {
this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
}
private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
this.strategy = strategy;
this.omitEmptyStrings = omitEmptyStrings;
this.trimmer = trimmer;
this.limit = limit;
}
/**
* Returns a splitter that uses the given single-character separator. For
* example, {@code Splitter.on(',').split("foo,,bar")} returns an iterable
* containing {@code ["foo", "", "bar"]}.
*
* @param separator the character to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
public static Splitter on(char separator) {
return on(CharMatcher.is(separator));
}
/**
* Returns a splitter that considers any single character matched by the given
* {@code CharMatcher} to be a separator. For example, {@code
* Splitter.on(CharMatcher.anyOf(";,")).split("foo,;bar,quux")} returns an
* iterable containing {@code ["foo", "", "bar", "quux"]}.
*
* @param separatorMatcher a {@link CharMatcher} that determines whether a
* character is a separator
* @return a splitter, with default settings, that uses this matcher
*/
public static Splitter on(final CharMatcher separatorMatcher) {
checkNotNull(separatorMatcher);
return new Splitter(new Strategy() {
@Override
public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
int separatorStart(int start) {
return separatorMatcher.indexIn(toSplit, start);
}
@Override
int separatorEnd(int separatorPosition) {
return separatorPosition + 1;
}
};
}
});
}
/**
* Returns a splitter that uses the given fixed string as a separator. For
* example, {@code Splitter.on(", ").split("foo, bar,baz")} returns an iterable
* containing {@code ["foo", "bar,baz"]}.
*
* @param separator the literal, nonempty string to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
public static Splitter on(final String separator) {
checkArgument(separator.length() != 0, "The separator may not be the empty string.");
return new Splitter(new Strategy() {
@Override
public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
int separatorLength = separator.length();
positions: for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
for (int i = 0; i < separatorLength; i++) {
if (toSplit.charAt(i + p) != separator.charAt(i)) {
continue positions;
}
}
return p;
}
return -1;
}
@Override
public int separatorEnd(int separatorPosition) {
return separatorPosition + separator.length();
}
};
}
});
}
/**
* Returns a splitter that considers any subsequence matching {@code
* pattern} to be a separator. For example, {@code
* Splitter.on(Pattern.compile("\r?\n")).split(entireFile)} splits a string into
* lines whether it uses DOS-style or UNIX-style line terminators.
*
* @param separatorPattern the pattern that determines whether a subsequence is
* a separator. This pattern may not match the empty
* string.
* @return a splitter, with default settings, that uses this pattern
* @throws IllegalArgumentException if {@code separatorPattern} matches the
* empty string
*/
@GwtIncompatible("java.util.regex")
public static Splitter on(final Pattern separatorPattern) {
checkNotNull(separatorPattern);
checkArgument(!separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s",
separatorPattern);
return new Splitter(new Strategy() {
@Override
public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
final Matcher matcher = separatorPattern.matcher(toSplit);
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
return matcher.find(start) ? matcher.start() : -1;
}
@Override
public int separatorEnd(int separatorPosition) {
return matcher.end();
}
};
}
});
}
/**
* Returns a splitter that considers any subsequence matching a given pattern
* (regular expression) to be a separator. For example, {@code
* Splitter.onPattern("\r?\n").split(entireFile)} splits a string into lines
* whether it uses DOS-style or UNIX-style line terminators. This is equivalent
* to {@code Splitter.on(Pattern.compile(pattern))}.
*
* @param separatorPattern the pattern that determines whether a subsequence is
* a separator. This pattern may not match the empty
* string.
* @return a splitter, with default settings, that uses this pattern
* @throws java.util.regex.PatternSyntaxException if {@code separatorPattern} is
* a malformed expression
* @throws IllegalArgumentException if {@code separatorPattern}
* matches the empty string
*/
@GwtIncompatible("java.util.regex")
public static Splitter onPattern(String separatorPattern) {
return on(Pattern.compile(separatorPattern));
}
/**
* Returns a splitter that divides strings into pieces of the given length. For
* example, {@code Splitter.fixedLength(2).split("abcde")} returns an iterable
* containing {@code ["ab", "cd", "e"]}. The last piece can be smaller than
* {@code length} but will never be empty.
*
* <p>
* <b>Exception:</b> for consistency with separator-based splitters, {@code
* split("")} does not yield an empty iterable, but an iterable containing
* {@code ""}. This is the only case in which {@code
* Iterables.size(split(input))} does not equal {@code
* IntMath.divide(input.length(), length, CEILING)}. To avoid this behavior, use
* {@code omitEmptyStrings}.
*
* @param length the desired length of pieces after splitting, a positive
* integer
* @return a splitter, with default settings, that can split into fixed sized
* pieces
* @throws IllegalArgumentException if {@code length} is zero or negative
*/
public static Splitter fixedLength(final int length) {
checkArgument(length > 0, "The length may not be less than 1");
return new Splitter(new Strategy() {
@Override
public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
int nextChunkStart = start + length;
return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
}
@Override
public int separatorEnd(int separatorPosition) {
return separatorPosition;
}
};
}
});
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* automatically omits empty strings from the results. For example, {@code
* Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an iterable
* containing only {@code ["a", "b", "c"]}.
*
* <p>
* If either {@code trimResults} option is also specified when creating a
* splitter, that splitter always trims results first before checking for
* emptiness. So, for example, {@code
* Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns an
* empty iterable.
*
* <p>
* Note that it is ordinarily not possible for {@link #split(CharSequence)} to
* return an empty iterable, but when using this option, it can (if the input
* sequence consists of nothing but separators).
*
* @return a splitter with the desired configuration
*/
@CheckReturnValue
public Splitter omitEmptyStrings() {
return new Splitter(strategy, true, trimmer, limit);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter but
* stops splitting after it reaches the limit. The limit defines the maximum
* number of items returned by the iterator.
*
* <p>
* For example, {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an
* iterable containing {@code ["a", "b", "c,d"]}. When omitting empty strings,
* the omitted strings do no count. Hence,
* {@code Splitter.on(',').limit(3).omitEmptyStrings().split("a,,,b,,,c,d")}
* returns an iterable containing {@code ["a", "b", "c,d"}. When trim is
* requested, all entries, including the last are trimmed. Hence
* {@code Splitter.on(',').limit(3).trimResults().split(" a , b , c , d ")}
* results in @{code ["a", "b", "c , d"]}.
*
* @param limit the maximum number of items returns
* @return a splitter with the desired configuration
* @since 9.0
*/
@CheckReturnValue
public Splitter limit(int limit) {
checkArgument(limit > 0, "must be greater than zero: %s", limit);
return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* automatically removes leading and trailing {@linkplain CharMatcher#WHITESPACE
* whitespace} from each returned substring; equivalent to
* {@code trimResults(CharMatcher.WHITESPACE)}. For example, {@code
* Splitter.on(',').trimResults().split(" a, b ,c ")} returns an iterable
* containing {@code ["a", "b", "c"]}.
*
* @return a splitter with the desired configuration
*/
@CheckReturnValue
public Splitter trimResults() {
return trimResults(CharMatcher.WHITESPACE);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* removes all leading or trailing characters matching the given {@code
* CharMatcher} from each returned substring. For example, {@code
* Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__")}
* returns an iterable containing {@code ["a ", "b_ ", "c"]}.
*
* @param trimmer a {@link CharMatcher} that determines whether a character
* should be removed from the beginning/end of a subsequence
* @return a splitter with the desired configuration
*/
// TODO(kevinb): throw if a trimmer was already specified!
@CheckReturnValue
public Splitter trimResults(CharMatcher trimmer) {
checkNotNull(trimmer);
return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}
/**
* Splits {@code sequence} into string components and makes them available
* through an {@link Iterator}, which may be lazily evaluated. If you want an
* eagerly computed {@link List}, use {@link #splitToList(CharSequence)}.
*
* @param sequence the sequence of characters to split
* @return an iteration over the segments split from the parameter.
*/
public Iterable<String> split(final CharSequence sequence) {
checkNotNull(sequence);
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return splittingIterator(sequence);
}
@Override
public String toString() {
return Joiner.on(", ").appendTo(new StringBuilder().append('['), this).append(']').toString();
}
};
}
private Iterator<String> splittingIterator(CharSequence sequence) {
return strategy.iterator(this, sequence);
}
/**
* Splits {@code sequence} into string components and returns them as an
* immutable list. If you want an {@link Iterable} which may be lazily
* evaluated, use {@link #split(CharSequence)}.
*
* @param sequence the sequence of characters to split
* @return an immutable list of the segments split from the parameter
* @since 15.0
*/
@Beta
public List<String> splitToList(CharSequence sequence) {
checkNotNull(sequence);
Iterator<String> iterator = splittingIterator(sequence);
List<String> result = new ArrayList<String>();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return Collections.unmodifiableList(result);
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified separator.
*
* @since 10.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(String separator) {
return withKeyValueSeparator(on(separator));
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified separator.
*
* @since 14.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(char separator) {
return withKeyValueSeparator(on(separator));
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified key-value
* splitter.
*
* @since 10.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
return new MapSplitter(this, keyValueSplitter);
}
/**
* An object that splits strings into maps as {@code Splitter} splits iterables
* and lists. Like {@code Splitter}, it is thread-safe and immutable.
*
* @since 10.0
*/
@Beta
public static final class MapSplitter {
private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
private final Splitter outerSplitter;
private final Splitter entrySplitter;
private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) {
this.outerSplitter = outerSplitter; // only "this" is passed
this.entrySplitter = checkNotNull(entrySplitter);
}
/**
* Splits {@code sequence} into substrings, splits each substring into an entry,
* and returns an unmodifiable map with each of the entries. For example, <code>
* Splitter.on(';').trimResults().withKeyValueSeparator("=>")
* .split("a=>b ; c=>b")
* </code> will return a mapping from {@code "a"} to {@code "b"} and {@code "c"}
* to {@code b}.
*
* <p>
* The returned map preserves the order of the entries from {@code sequence}.
*
* @throws IllegalArgumentException if the specified sequence does not split
* into valid map entries, or if there are
* duplicate keys
*/
public Map<String, String> split(CharSequence sequence) {
Map<String, String> map = new LinkedHashMap<String, String>();
for (String entry : outerSplitter.split(sequence)) {
Iterator<String> entryFields = entrySplitter.splittingIterator(entry);
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String key = entryFields.next();
checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String value = entryFields.next();
map.put(key, value);
checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
}
return Collections.unmodifiableMap(map);
}
}
private interface Strategy {
Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
}
private abstract static class SplittingIterator extends AbstractIterator<String> {
final CharSequence toSplit;
final CharMatcher trimmer;
final boolean omitEmptyStrings;
/**
* Returns the first index in {@code toSplit} at or after {@code start} that
* contains the separator.
*/
abstract int separatorStart(int start);
/**
* Returns the first index in {@code toSplit} after {@code
* separatorPosition} that does not contain a separator. This method is only
* invoked after a call to {@code separatorStart}.
*/
abstract int separatorEnd(int separatorPosition);
int offset = 0;
int limit;
protected SplittingIterator(Splitter splitter, CharSequence toSplit) {
this.trimmer = splitter.trimmer;
this.omitEmptyStrings = splitter.omitEmptyStrings;
this.limit = splitter.limit;
this.toSplit = toSplit;
}
@Override
protected String computeNext() {
/*
* The returned string will be from the end of the last match to the beginning
* of the next one. nextStart is the start position of the returned substring,
* while offset is the place to start looking for a separator.
*/
int nextStart = offset;
while (offset != -1) {
int start = nextStart;
int end;
int separatorPosition = separatorStart(offset);
if (separatorPosition == -1) {
end = toSplit.length();
offset = -1;
} else {
end = separatorPosition;
offset = separatorEnd(separatorPosition);
}
if (offset == nextStart) {
/*
* This occurs when some pattern has an empty match, even if it doesn't match
* the empty string -- for example, if it requires lookahead or the like. The
* offset must be increased to look for separators beyond this point, without
* changing the start position of the next returned substring -- so nextStart
* stays the same.
*/
offset++;
if (offset >= toSplit.length()) {
offset = -1;
}
continue;
}
while (start < end && trimmer.matches(toSplit.charAt(start))) {
start++;
}
while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
end--;
}
if (omitEmptyStrings && start == end) {
// Don't include the (unused) separator in next split string.
nextStart = offset;
continue;
}
if (limit == 1) {
// The limit has been reached, return the rest of the string as the
// final item. This is tested after empty string removal so that
// empty strings do not count towards the limit.
end = toSplit.length();
offset = -1;
// Since we may have changed the end, we need to trim it again.
while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
end--;
}
} else {
limit--;
}
return toSplit.subSequence(start, end).toString();
}
return endOfData();
}
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
/**
* Represents a {@linkplain System#getProperties() standard system property}.
*
* @author Kurt Alfred Kluever
* @since 15.0
*/
@Beta
@GwtIncompatible("java.lang.System#getProperty")
public enum StandardSystemProperty {
/** Java Runtime Environment version. */
JAVA_VERSION("java.version"),
/** Java Runtime Environment vendor. */
JAVA_VENDOR("java.vendor"),
/** Java vendor URL. */
JAVA_VENDOR_URL("java.vendor.url"),
/** Java installation directory. */
JAVA_HOME("java.home"),
/** Java Virtual Machine specification version. */
JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"),
/** Java Virtual Machine specification vendor. */
JAVA_VM_SPECIFICATION_VENDOR("java.vm.specification.vendor"),
/** Java Virtual Machine specification name. */
JAVA_VM_SPECIFICATION_NAME("java.vm.specification.name"),
/** Java Virtual Machine implementation version. */
JAVA_VM_VERSION("java.vm.version"),
/** Java Virtual Machine implementation vendor. */
JAVA_VM_VENDOR("java.vm.vendor"),
/** Java Virtual Machine implementation name. */
JAVA_VM_NAME("java.vm.name"),
/** Java Runtime Environment specification version. */
JAVA_SPECIFICATION_VERSION("java.specification.version"),
/** Java Runtime Environment specification vendor. */
JAVA_SPECIFICATION_VENDOR("java.specification.vendor"),
/** Java Runtime Environment specification name. */
JAVA_SPECIFICATION_NAME("java.specification.name"),
/** Java class format version number. */
JAVA_CLASS_VERSION("java.class.version"),
/** Java class path. */
JAVA_CLASS_PATH("java.class.path"),
/** List of paths to search when loading libraries. */
JAVA_LIBRARY_PATH("java.library.path"),
/** Default temp file path. */
JAVA_IO_TMPDIR("java.io.tmpdir"),
/** Name of JIT compiler to use. */
JAVA_COMPILER("java.compiler"),
/** Path of extension directory or directories. */
JAVA_EXT_DIRS("java.ext.dirs"),
/** Operating system name. */
OS_NAME("os.name"),
/** Operating system architecture. */
OS_ARCH("os.arch"),
/** Operating system version. */
OS_VERSION("os.version"),
/** File separator ("/" on UNIX). */
FILE_SEPARATOR("file.separator"),
/** Path separator (":" on UNIX). */
PATH_SEPARATOR("path.separator"),
/** Line separator ("\n" on UNIX). */
LINE_SEPARATOR("line.separator"),
/** User's account name. */
USER_NAME("user.name"),
/** User's home directory. */
USER_HOME("user.home"),
/** User's current working directory. */
USER_DIR("user.dir");
private final String key;
private StandardSystemProperty(String key) {
this.key = key;
}
/**
* Returns the key used to lookup this system property.
*/
public String key() {
return key;
}
/**
* Returns the current value for this system property by delegating to
* {@link System#getProperty(String)}.
*/
public String value() {
return System.getProperty(key);
}
/**
* Returns a string representation of this system property.
*/
@Override
public String toString() {
return key() + "=" + value();
}
}

View File

@ -0,0 +1,240 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Formatter;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* Static utility methods pertaining to {@code String} or {@code CharSequence}
* instances.
*
* @author Kevin Bourrillion
* @since 3.0
*/
@GwtCompatible
public final class Strings {
private Strings() {
}
/**
* Returns the given string if it is non-null; the empty string otherwise.
*
* @param string the string to test and possibly return
* @return {@code string} itself if it is non-null; {@code ""} if it is null
*/
public static String nullToEmpty(@Nullable String string) {
return (string == null) ? "" : string;
}
/**
* Returns the given string if it is nonempty; {@code null} otherwise.
*
* @param string the string to test and possibly return
* @return {@code string} itself if it is nonempty; {@code null} if it is empty
* or null
*/
public static @Nullable String emptyToNull(@Nullable String string) {
return isNullOrEmpty(string) ? null : string;
}
/**
* Returns {@code true} if the given string is null or is the empty string.
*
* <p>
* Consider normalizing your string references with {@link #nullToEmpty}. If you
* do, you can use {@link String#isEmpty()} instead of this method, and you
* won't need special null-safe forms of methods like {@link String#toUpperCase}
* either. Or, if you'd like to normalize "in the other direction," converting
* empty strings to {@code null}, you can use {@link #emptyToNull}.
*
* @param string a string reference to check
* @return {@code true} if the string is null or is the empty string
*/
public static boolean isNullOrEmpty(@Nullable String string) {
return string == null || string.length() == 0; // string.isEmpty() in Java 6
}
/**
* Returns a string, of length at least {@code minLength}, consisting of
* {@code string} prepended with as many copies of {@code padChar} as are
* necessary to reach that length. For example,
*
* <ul>
* <li>{@code padStart("7", 3, '0')} returns {@code "007"}
* <li>{@code padStart("2010", 3, '0')} returns {@code "2010"}
* </ul>
*
* <p>
* See {@link Formatter} for a richer set of formatting capabilities.
*
* @param string the string which should appear at the end of the result
* @param minLength the minimum length the resulting string must have. Can be
* zero or negative, in which case the input string is always
* returned.
* @param padChar the character to insert at the beginning of the result until
* the minimum length is reached
* @return the padded string
*/
public static String padStart(String string, int minLength, char padChar) {
checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
StringBuilder sb = new StringBuilder(minLength);
for (int i = string.length(); i < minLength; i++) {
sb.append(padChar);
}
sb.append(string);
return sb.toString();
}
/**
* Returns a string, of length at least {@code minLength}, consisting of
* {@code string} appended with as many copies of {@code padChar} as are
* necessary to reach that length. For example,
*
* <ul>
* <li>{@code padEnd("4.", 5, '0')} returns {@code "4.000"}
* <li>{@code padEnd("2010", 3, '!')} returns {@code "2010"}
* </ul>
*
* <p>
* See {@link Formatter} for a richer set of formatting capabilities.
*
* @param string the string which should appear at the beginning of the
* result
* @param minLength the minimum length the resulting string must have. Can be
* zero or negative, in which case the input string is always
* returned.
* @param padChar the character to append to the end of the result until the
* minimum length is reached
* @return the padded string
*/
public static String padEnd(String string, int minLength, char padChar) {
checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
StringBuilder sb = new StringBuilder(minLength);
sb.append(string);
for (int i = string.length(); i < minLength; i++) {
sb.append(padChar);
}
return sb.toString();
}
/**
* Returns a string consisting of a specific number of concatenated copies of an
* input string. For example, {@code repeat("hey", 3)} returns the string
* {@code "heyheyhey"}.
*
* @param string any non-null string
* @param count the number of times to repeat it; a nonnegative integer
* @return a string containing {@code string} repeated {@code count} times (the
* empty string if {@code count} is zero)
* @throws IllegalArgumentException if {@code count} is negative
*/
public static String repeat(String string, int count) {
checkNotNull(string); // eager for GWT.
if (count <= 1) {
checkArgument(count >= 0, "invalid count: %s", count);
return (count == 0) ? "" : string;
}
// IF YOU MODIFY THE CODE HERE, you must update StringsRepeatBenchmark
final int len = string.length();
final long longSize = (long) len * (long) count;
final int size = (int) longSize;
if (size != longSize) {
throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
}
final char[] array = new char[size];
string.getChars(0, len, array, 0);
int n;
for (n = len; n < size - n; n <<= 1) {
System.arraycopy(array, 0, array, n, n);
}
System.arraycopy(array, 0, array, n, size - n);
return new String(array);
}
/**
* Returns the longest string {@code prefix} such that
* {@code a.toString().startsWith(prefix) && b.toString().startsWith(prefix)},
* taking care not to split surrogate pairs. If {@code a} and {@code b} have no
* common prefix, returns the empty string.
*
* @since 11.0
*/
public static String commonPrefix(CharSequence a, CharSequence b) {
checkNotNull(a);
checkNotNull(b);
int maxPrefixLength = Math.min(a.length(), b.length());
int p = 0;
while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
p++;
}
if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
p--;
}
return a.subSequence(0, p).toString();
}
/**
* Returns the longest string {@code suffix} such that
* {@code a.toString().endsWith(suffix) && b.toString().endsWith(suffix)},
* taking care not to split surrogate pairs. If {@code a} and {@code b} have no
* common suffix, returns the empty string.
*
* @since 11.0
*/
public static String commonSuffix(CharSequence a, CharSequence b) {
checkNotNull(a);
checkNotNull(b);
int maxSuffixLength = Math.min(a.length(), b.length());
int s = 0;
while (s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
s++;
}
if (validSurrogatePairAt(a, a.length() - s - 1) || validSurrogatePairAt(b, b.length() - s - 1)) {
s--;
}
return a.subSequence(a.length() - s, a.length()).toString();
}
/**
* True when a valid surrogate pair starts at the given {@code index} in the
* given {@code string}. Out-of-range indexes return false.
*/
@VisibleForTesting
static boolean validSurrogatePairAt(CharSequence string, int index) {
return index >= 0 && index <= (string.length() - 2) && Character.isHighSurrogate(string.charAt(index))
&& Character.isLowSurrogate(string.charAt(index + 1));
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import com.google.common.annotations.GwtCompatible;
/**
* A class that can supply objects of a single type. Semantically, this could be
* a factory, generator, builder, closure, or something else entirely. No
* guarantees are implied by this interface.
*
* @author Harry Heymann
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface Supplier<T> {
/**
* Retrieves an instance of the appropriate type. The returned object may or may
* not be a new instance, depending on the implementation.
*
* @return an instance of the appropriate type
*/
T get();
}

View File

@ -0,0 +1,322 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* Useful suppliers.
*
* <p>
* All methods return serializable suppliers as long as they're given
* serializable parameters.
*
* @author Laurence Gonsalves
* @author Harry Heymann
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Suppliers {
private Suppliers() {
}
/**
* Returns a new supplier which is the composition of the provided function and
* supplier. In other words, the new supplier's value will be computed by
* retrieving the value from {@code supplier}, and then applying
* {@code function} to that value. Note that the resulting supplier will not
* call {@code supplier} or invoke {@code function} until it is called.
*/
public static <F, T> Supplier<T> compose(Function<? super F, T> function, Supplier<F> supplier) {
Preconditions.checkNotNull(function);
Preconditions.checkNotNull(supplier);
return new SupplierComposition<F, T>(function, supplier);
}
private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
final Function<? super F, T> function;
final Supplier<F> supplier;
SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
this.function = function;
this.supplier = supplier;
}
@Override
public T get() {
return function.apply(supplier.get());
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierComposition) {
SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
return function.equals(that.function) && supplier.equals(that.supplier);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, supplier);
}
@Override
public String toString() {
return "Suppliers.compose(" + function + ", " + supplier + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier which caches the instance retrieved during the first call
* to {@code get()} and returns that value on subsequent calls to {@code get()}.
* See: <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>
* The returned supplier is thread-safe. The supplier's serialized form does not
* contain the cached value, which will be recalculated when {@code
* get()} is called on the reserialized instance.
*
* <p>
* If {@code delegate} is an instance created by an earlier call to {@code
* memoize}, it is returned directly.
*/
public static <T> Supplier<T> memoize(Supplier<T> delegate) {
return (delegate instanceof MemoizingSupplier) ? delegate
: new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
}
@VisibleForTesting
static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
return value;
}
@Override
public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier that caches the instance supplied by the delegate and
* removes the cached value after the specified time has passed. Subsequent
* calls to {@code get()} return the cached value if the expiration time has not
* passed. After the expiration time, a new value is retrieved, cached, and
* returned. See:
* <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>
* The returned supplier is thread-safe. The supplier's serialized form does not
* contain the cached value, which will be recalculated when {@code
* get()} is called on the reserialized instance.
*
* @param duration the length of time after a value is created that it should
* stop being returned by subsequent {@code get()} calls
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is not positive
* @since 2.0
*/
public static <T> Supplier<T> memoizeWithExpiration(Supplier<T> delegate, long duration, TimeUnit unit) {
return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
}
@VisibleForTesting
static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
final long durationNanos;
transient volatile T value;
// The special value 0 means "not yet initialized".
transient volatile long expirationNanos;
ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
this.delegate = Preconditions.checkNotNull(delegate);
this.durationNanos = unit.toNanos(duration);
Preconditions.checkArgument(duration > 0);
}
@Override
public T get() {
// Another variant of Double Checked Locking.
//
// We use two volatile reads. We could reduce this to one by
// putting our fields into a holder class, but (at least on x86)
// the extra memory consumption and indirection are more
// expensive than the extra volatile reads.
long nanos = expirationNanos;
long now = Platform.systemNanoTime();
if (nanos == 0 || now - nanos >= 0) {
synchronized (this) {
if (nanos == expirationNanos) { // recheck for lost race
T t = delegate.get();
value = t;
nanos = now + durationNanos;
// In the very unlikely event that nanos is 0, set it to 1;
// no one will notice 1 ns of tardiness.
expirationNanos = (nanos == 0) ? 1 : nanos;
return t;
}
}
}
return value;
}
@Override
public String toString() {
// This is a little strange if the unit the user provided was not NANOS,
// but we don't want to store the unit just for toString
return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier that always supplies {@code instance}.
*/
public static <T> Supplier<T> ofInstance(@Nullable T instance) {
return new SupplierOfInstance<T>(instance);
}
private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
final T instance;
SupplierOfInstance(@Nullable T instance) {
this.instance = instance;
}
@Override
public T get() {
return instance;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierOfInstance) {
SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
return Objects.equal(instance, that.instance);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(instance);
}
@Override
public String toString() {
return "Suppliers.ofInstance(" + instance + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier whose {@code get()} method synchronizes on
* {@code delegate} before calling it, making it thread-safe.
*/
public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
}
private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
ThreadSafeSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
synchronized (delegate) {
return delegate.get();
}
}
@Override
public String toString() {
return "Suppliers.synchronizedSupplier(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function that accepts a supplier and returns the result of invoking
* {@link Supplier#get} on that supplier.
*
* @since 8.0
*/
@Beta
public static <T> Function<Supplier<T>, T> supplierFunction() {
@SuppressWarnings("unchecked") // implementation is "fully variant"
SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
return sf;
}
private interface SupplierFunction<T> extends Function<Supplier<T>, T> {
}
private enum SupplierFunctionImpl implements SupplierFunction<Object> {
INSTANCE;
// Note: This makes T a "pass-through type"
@Override
public Object apply(Supplier<Object> input) {
return input.get();
}
@Override
public String toString() {
return "Suppliers.supplierFunction()";
}
}
}

View File

@ -0,0 +1,226 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
/**
* Static utility methods pertaining to instances of {@link Throwable}.
*
* <p>
* See the Guava User Guide entry on
* <a href= "http://code.google.com/p/guava-libraries/wiki/ThrowablesExplained">
* Throwables</a>.
*
* @author Kevin Bourrillion
* @author Ben Yu
* @since 1.0
*/
public final class Throwables {
private Throwables() {
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance
* of {@code declaredType}. Example usage:
*
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfInstanceOf(t, IOException.class);
* Throwables.propagateIfInstanceOf(t, SQLException.class);
* throw Throwables.propagate(t);
* }
* </pre>
*/
public static <X extends Throwable> void propagateIfInstanceOf(@Nullable Throwable throwable, Class<X> declaredType)
throws X {
// Check for null is needed to avoid frequent JNI calls to isInstance().
if (throwable != null && declaredType.isInstance(throwable)) {
throw declaredType.cast(throwable);
}
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance
* of {@link RuntimeException} or {@link Error}. Example usage:
*
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfPossible(t);
* throw new RuntimeException("unexpected", t);
* }
* </pre>
*/
public static void propagateIfPossible(@Nullable Throwable throwable) {
propagateIfInstanceOf(throwable, Error.class);
propagateIfInstanceOf(throwable, RuntimeException.class);
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance
* of {@link RuntimeException}, {@link Error}, or {@code declaredType}. Example
* usage:
*
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfPossible(t, OtherException.class);
* throw new RuntimeException("unexpected", t);
* }
* </pre>
*
* @param throwable the Throwable to possibly propagate
* @param declaredType the single checked exception type declared by the calling
* method
*/
public static <X extends Throwable> void propagateIfPossible(@Nullable Throwable throwable, Class<X> declaredType)
throws X {
propagateIfInstanceOf(throwable, declaredType);
propagateIfPossible(throwable);
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance
* of {@link RuntimeException}, {@link Error}, {@code declaredType1}, or
* {@code declaredType2}. In the unlikely case that you have three or more
* declared checked exception types, you can handle them all by invoking these
* methods repeatedly. See usage example in
* {@link #propagateIfPossible(Throwable, Class)}.
*
* @param throwable the Throwable to possibly propagate
* @param declaredType1 any checked exception type declared by the calling
* method
* @param declaredType2 any other checked exception type declared by the calling
* method
*/
public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible(@Nullable Throwable throwable,
Class<X1> declaredType1, Class<X2> declaredType2) throws X1, X2 {
checkNotNull(declaredType2);
propagateIfInstanceOf(throwable, declaredType1);
propagateIfPossible(throwable, declaredType2);
}
/**
* Propagates {@code throwable} as-is if it is an instance of
* {@link RuntimeException} or {@link Error}, or else as a last resort, wraps it
* in a {@code RuntimeException} then propagates.
* <p>
* This method always throws an exception. The {@code RuntimeException} return
* type is only for client code to make Java type system happy in case a return
* value is required by the enclosing method. Example usage:
*
* <pre>
* T doSomething() {
* try {
* return someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* return handle(e);
* } catch (Throwable t) {
* throw Throwables.propagate(t);
* }
* }
* </pre>
*
* @param throwable the Throwable to propagate
* @return nothing will ever be returned; this return type is only for your
* convenience, as illustrated in the example above
*/
public static RuntimeException propagate(Throwable throwable) {
propagateIfPossible(checkNotNull(throwable));
throw new RuntimeException(throwable);
}
/**
* Returns the innermost cause of {@code throwable}. The first throwable in a
* chain provides context from when the error or exception was initially
* detected. Example usage:
*
* <pre>
* assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
* </pre>
*/
public static Throwable getRootCause(Throwable throwable) {
Throwable cause;
while ((cause = throwable.getCause()) != null) {
throwable = cause;
}
return throwable;
}
/**
* Gets a {@code Throwable} cause chain as a list. The first entry in the list
* will be {@code throwable} followed by its cause hierarchy. Note that this is
* a snapshot of the cause chain and will not reflect any subsequent changes to
* the cause chain.
*
* <p>
* Here's an example of how it can be used to find specific types of exceptions
* in the cause chain:
*
* <pre>
* Iterables.filter(Throwables.getCausalChain(e), IOException.class));
* </pre>
*
* @param throwable the non-null {@code Throwable} to extract causes from
* @return an unmodifiable list containing the cause chain starting with
* {@code throwable}
*/
@Beta // TODO(kevinb): decide best return type
public static List<Throwable> getCausalChain(Throwable throwable) {
checkNotNull(throwable);
List<Throwable> causes = new ArrayList<Throwable>(4);
while (throwable != null) {
causes.add(throwable);
throwable = throwable.getCause();
}
return Collections.unmodifiableList(causes);
}
/**
* Returns a string containing the result of {@link Throwable#toString()
* toString()}, followed by the full, recursive stack trace of
* {@code throwable}. Note that you probably should not be parsing the resulting
* string; if you need programmatic access to the stack frames, you can call
* {@link Throwable#getStackTrace()}.
*/
public static String getStackTraceAsString(Throwable throwable) {
return EagRuntime.getStackTrace(throwable);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A time source; returns a time value representing the number of nanoseconds
* elapsed since some fixed but arbitrary point in time. Note that most users
* should use {@link Stopwatch} instead of interacting with this class directly.
*
* <p>
* <b>Warning:</b> this interface can only be used to measure elapsed time, not
* wall time.
*
* @author Kevin Bourrillion
* @since 10.0
* (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
* >mostly source-compatible</a> since 9.0)
*/
@Beta
@GwtCompatible
public abstract class Ticker {
/**
* Constructor for use by subclasses.
*/
protected Ticker() {
}
/**
* Returns the number of nanoseconds elapsed since this ticker's fixed point of
* reference.
*/
public abstract long read();
/**
* A ticker that reads the current time using {@link System#nanoTime}.
*
* @since 10.0
*/
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
private static final Ticker SYSTEM_TICKER = new Ticker() {
@Override
public long read() {
return Platform.systemNanoTime();
}
};
}

View File

@ -0,0 +1,206 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Low-level, high-performance utility methods related to the
* {@linkplain Charsets#UTF_8 UTF-8} character encoding. UTF-8 is defined in
* section D92 of
* <a href="http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf">The Unicode
* Standard Core Specification, Chapter 3</a>.
*
* <p>
* The variant of UTF-8 implemented by this class is the restricted definition
* of UTF-8 introduced in Unicode 3.1. One implication of this is that it
* rejects
* <a href="http://www.unicode.org/versions/corrigendum1.html">"non-shortest
* form"</a> byte sequences, even though the JDK decoder may accept them.
*
* @author Martin Buchholz
* @author Clément Roux
* @since 16.0
*/
@Beta
@GwtCompatible
public final class Utf8 {
/**
* Returns the number of bytes in the UTF-8-encoded form of {@code sequence}.
* For a string, this method is equivalent to
* {@code string.getBytes(UTF_8).length}, but is more efficient in both time and
* space.
*
* @throws IllegalArgumentException if {@code sequence} contains ill-formed
* UTF-16 (unpaired surrogates)
*/
public static int encodedLength(CharSequence sequence) {
// Warning to maintainers: this implementation is highly optimized.
int utf16Length = sequence.length();
int utf8Length = utf16Length;
int i = 0;
// This loop optimizes for pure ASCII.
while (i < utf16Length && sequence.charAt(i) < 0x80) {
i++;
}
// This loop optimizes for chars less than 0x800.
for (; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += ((0x7f - c) >>> 31); // branch free!
} else {
utf8Length += encodedLengthGeneral(sequence, i);
break;
}
}
if (utf8Length < utf16Length) {
// Necessary and sufficient condition for overflow because of maximum 3x
// expansion
throw new IllegalArgumentException("UTF-8 length does not fit in int: " + (utf8Length + (1L << 32)));
}
return utf8Length;
}
private static int encodedLengthGeneral(CharSequence sequence, int start) {
int utf16Length = sequence.length();
int utf8Length = 0;
for (int i = start; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += (0x7f - c) >>> 31; // branch free!
} else {
utf8Length += 2;
// jdk7+: if (Character.isSurrogate(c)) {
if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
// Check that we have a well-formed surrogate pair.
int cp = Character.codePointAt(sequence, i);
if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
throw new IllegalArgumentException("Unpaired surrogate at index " + i);
}
i++;
}
}
}
return utf8Length;
}
/**
* Returns {@code true} if {@code bytes} is a <i>well-formed</i> UTF-8 byte
* sequence according to Unicode 6.0. Note that this is a stronger criterion
* than simply whether the bytes can be decoded. For example, some versions of
* the JDK decoder will accept "non-shortest form" byte sequences, but encoding
* never reproduces these. Such byte sequences are <i>not</i> considered
* well-formed.
*
* <p>
* This method returns {@code true} if and only if
* {@code Arrays.equals(bytes, new
* String(bytes, UTF_8).getBytes(UTF_8))} does, but is more efficient in both
* time and space.
*/
public static boolean isWellFormed(byte[] bytes) {
return isWellFormed(bytes, 0, bytes.length);
}
/**
* Returns whether the given byte array slice is a well-formed UTF-8 byte
* sequence, as defined by {@link #isWellFormed(byte[])}. Note that this can be
* false even when {@code
* isWellFormed(bytes)} is true.
*
* @param bytes the input buffer
* @param off the offset in the buffer of the first byte to read
* @param len the number of bytes to read from the buffer
*/
public static boolean isWellFormed(byte[] bytes, int off, int len) {
int end = off + len;
checkPositionIndexes(off, end, bytes.length);
// Look for the first non-ASCII character.
for (int i = off; i < end; i++) {
if (bytes[i] < 0) {
return isWellFormedSlowPath(bytes, i, end);
}
}
return true;
}
private static boolean isWellFormedSlowPath(byte[] bytes, int off, int end) {
int index = off;
while (true) {
int byte1;
// Optimize for interior runs of ASCII bytes.
do {
if (index >= end) {
return true;
}
} while ((byte1 = bytes[index++]) >= 0);
if (byte1 < (byte) 0xE0) {
// Two-byte form.
if (index == end) {
return false;
}
// Simultaneously check for illegal trailing-byte in leading position
// and overlong 2-byte form.
if (byte1 < (byte) 0xC2 || bytes[index++] > (byte) 0xBF) {
return false;
}
} else if (byte1 < (byte) 0xF0) {
// Three-byte form.
if (index + 1 >= end) {
return false;
}
int byte2 = bytes[index++];
if (byte2 > (byte) 0xBF
// Overlong? 5 most significant bits must not all be zero.
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
// Check for illegal surrogate codepoints.
|| (byte1 == (byte) 0xED && (byte) 0xA0 <= byte2)
// Third byte trailing-byte test.
|| bytes[index++] > (byte) 0xBF) {
return false;
}
} else {
// Four-byte form.
if (index + 2 >= end) {
return false;
}
int byte2 = bytes[index++];
if (byte2 > (byte) 0xBF
// Check that 1 <= plane <= 16. Tricky optimized form of:
// if (byte1 > (byte) 0xF4
// || byte1 == (byte) 0xF0 && byte2 < (byte) 0x90
// || byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
// Third byte trailing-byte test
|| bytes[index++] > (byte) 0xBF
// Fourth byte trailing-byte test
|| bytes[index++] > (byte) 0xBF) {
return false;
}
}
}
}
private Utf8() {
}
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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.google.common.base;
import static com.google.common.base.Preconditions.format;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static convenience methods that serve the same purpose as Java language
* <a href=
* "http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html">
* assertions</a>, except that they are always enabled. These methods should be
* used instead of Java assertions whenever there is a chance the check may fail
* "in real life". Example:
*
* <pre>
* {
* &#64;code
*
* Bill bill = remoteService.getLastUnpaidBill();
*
* // In case bug 12345 happens again we'd rather just die
* Verify.verify(bill.status() == Status.UNPAID, "Unexpected bill status: %s", bill.status());
* }
* </pre>
*
* <h3>Comparison to alternatives</h3>
*
* <p>
* <b>Note:</b> In some cases the differences explained below can be subtle.
* When it's unclear which approach to use, <b>don't worry</b> too much about
* it; just pick something that seems reasonable and it will be fine.
*
* <ul>
* <li>If checking whether the <i>caller</i> has violated your method or
* constructor's contract (such as by passing an invalid argument), use the
* utilities of the {@link Preconditions} class instead.
*
* <li>If checking an <i>impossible</i> condition (which <i>cannot</i> happen
* unless your own class or its <i>trusted</i> dependencies is badly broken),
* this is what ordinary Java assertions are for. Note that assertions are not
* enabled by default; they are essentially considered "compiled comments."
*
* <li>An explicit {@code if/throw} (as illustrated above) is always acceptable;
* we still recommend using our {@link VerifyException} exception type. Throwing
* a plain {@link RuntimeException} is frowned upon.
*
* <li>Use of {@link java.util.Objects#requireNonNull(Object)} is generally
* discouraged, since {@link #verifyNotNull(Object)} and
* {@link Preconditions#checkNotNull(Object)} perform the same function with
* more clarity.
* </ul>
*
* <h3>Warning about performance</h3>
*
* <p>
* Remember that parameter values for message construction must all be computed
* eagerly, and autoboxing and varargs array creation may happen as well, even
* when the verification succeeds and the message ends up unneeded.
* Performance-sensitive verification checks should continue to use usual form:
*
* <pre>
* {
* &#64;code
*
* Bill bill = remoteService.getLastUnpaidBill();
* if (bill.status() != Status.UNPAID) {
* throw new VerifyException("Unexpected bill status: " + bill.status());
* }
* }
* </pre>
*
* <h3>Only {@code %s} is supported</h3>
*
* <p>
* As with {@link Preconditions} error message template strings, only the
* {@code "%s"} specifier is supported, not the full range of
* {@link java.util.Formatter} specifiers. However, note that if the number of
* arguments does not match the number of occurrences of {@code "%s"} in the
* format string, {@code Verify} will still behave as expected, and will still
* include all argument values in the error message; the message will simply not
* be formatted exactly as intended.
*
* <h3>More information</h3>
*
* See <a href=
* "http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for advice on when this class
* should be used.
*
* @since 17.0
*/
@Beta
@GwtCompatible
public final class Verify {
/**
* Ensures that {@code expression} is {@code true}, throwing a
* {@code VerifyException} with no message otherwise.
*/
public static void verify(boolean expression) {
if (!expression) {
throw new VerifyException();
}
}
/**
* Ensures that {@code expression} is {@code true}, throwing a
* {@code VerifyException} with a custom message otherwise.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing
* each {@code %s} placeholder in the template with
* an argument. These are matched by position - the
* first {@code %s} gets
* {@code errorMessageArgs[0]}, etc. Unmatched
* arguments will be appended to the formatted
* message in square braces. Unmatched placeholders
* will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings
* using {@link String#valueOf(Object)}.
* @throws VerifyException if {@code expression} is {@code false}
*/
public static void verify(boolean expression, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new VerifyException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures that {@code reference} is non-null, throwing a
* {@code VerifyException} with a default message otherwise.
*
* @return {@code reference}, guaranteed to be non-null, for convenience
*/
public static <T> T verifyNotNull(@Nullable T reference) {
return verifyNotNull(reference, "expected a non-null reference");
}
/**
* Ensures that {@code reference} is non-null, throwing a
* {@code VerifyException} with a custom message otherwise.
*
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing
* each {@code %s} placeholder in the template with
* an argument. These are matched by position - the
* first {@code %s} gets
* {@code errorMessageArgs[0]}, etc. Unmatched
* arguments will be appended to the formatted
* message in square braces. Unmatched placeholders
* will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings
* using {@link String#valueOf(Object)}.
* @return {@code reference}, guaranteed to be non-null, for convenience
*/
public static <T> T verifyNotNull(@Nullable T reference, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
verify(reference != null, errorMessageTemplate, errorMessageArgs);
return reference;
}
// TODO(kevinb): consider <T> T verifySingleton(Iterable<T>) to take over for
// Iterables.getOnlyElement()
private Verify() {
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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.google.common.base;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Exception thrown upon the failure of a <a href=
* "http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">verification
* check</a>, including those performed by the convenience methods of the
* {@link Verify} class.
*
* @since 17.0
*/
@Beta
@GwtCompatible
public class VerifyException extends RuntimeException {
/** Constructs a {@code VerifyException} with no message. */
public VerifyException() {
}
/** Constructs a {@code VerifyException} with the message {@code message}. */
public VerifyException(@Nullable String message) {
super(message);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.
*/
/**
* Basic utility libraries and interfaces.
*
* <p>
* This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* <h2>Contents</h2>
*
* <h3>String-related utilities</h3>
*
* <ul>
* <li>{@link com.google.common.base.Ascii}
* <li>{@link com.google.common.base.CaseFormat}
* <li>{@link com.google.common.base.CharMatcher}
* <li>{@link com.google.common.base.Charsets}
* <li>{@link com.google.common.base.Joiner}
* <li>{@link com.google.common.base.Splitter}
* <li>{@link com.google.common.base.Strings}
* </ul>
*
* <h3>Function types</h3>
*
* <ul>
* <li>{@link com.google.common.base.Function},
* {@link com.google.common.base.Functions}
* <li>{@link com.google.common.base.Predicate},
* {@link com.google.common.base.Predicates}
* <li>{@link com.google.common.base.Equivalence}
* <li>{@link com.google.common.base.Converter}
* <li>{@link com.google.common.base.Supplier},
* {@link com.google.common.base.Suppliers}
* </ul>
*
* <h3>Other</h3>
*
* <ul>
* <li>{@link com.google.common.base.Defaults}
* <li>{@link com.google.common.base.Enums}
* <li>{@link com.google.common.base.Objects}
* <li>{@link com.google.common.base.Optional}
* <li>{@link com.google.common.base.Preconditions}
* <li>{@link com.google.common.base.Stopwatch}
* <li>{@link com.google.common.base.Throwables}
* </ul>
*
*/
@ParametersAreNonnullByDefault
package com.google.common.base;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@ -0,0 +1,441 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
/**
* A general-purpose bimap implementation using any two backing {@code Map}
* instances.
*
* <p>
* Note that this class contains {@code equals()} calls that keep it from
* supporting {@code IdentityHashMap} backing maps.
*
* @author Kevin Bourrillion
* @author Mike Bostock
*/
@GwtCompatible(emulated = true)
abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
private transient Map<K, V> delegate;
transient AbstractBiMap<V, K> inverse;
/** Package-private constructor for creating a map-backed bimap. */
AbstractBiMap(Map<K, V> forward, Map<V, K> backward) {
setDelegates(forward, backward);
}
/** Private constructor for inverse bimap. */
private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) {
delegate = backward;
inverse = forward;
}
@Override
protected Map<K, V> delegate() {
return delegate;
}
/**
* Returns its input, or throws an exception if this is not a valid key.
*/
K checkKey(@Nullable K key) {
return key;
}
/**
* Returns its input, or throws an exception if this is not a valid value.
*/
V checkValue(@Nullable V value) {
return value;
}
/**
* Specifies the delegate maps going in each direction. Called by the
* constructor and by subclasses during deserialization.
*/
void setDelegates(Map<K, V> forward, Map<V, K> backward) {
checkState(delegate == null);
checkState(inverse == null);
checkArgument(forward.isEmpty());
checkArgument(backward.isEmpty());
checkArgument(forward != backward);
delegate = forward;
inverse = new Inverse<V, K>(backward, this);
}
void setInverse(AbstractBiMap<V, K> inverse) {
this.inverse = inverse;
}
// Query Operations (optimizations)
@Override
public boolean containsValue(@Nullable Object value) {
return inverse.containsKey(value);
}
// Modification Operations
@Override
public V put(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, false);
}
@Override
public V forcePut(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, true);
}
private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) {
checkKey(key);
checkValue(value);
boolean containedKey = containsKey(key);
if (containedKey && Objects.equal(value, get(key))) {
return value;
}
if (force) {
inverse().remove(value);
} else {
checkArgument(!containsValue(value), "value already present: %s", value);
}
V oldValue = delegate.put(key, value);
updateInverseMap(key, containedKey, oldValue, value);
return oldValue;
}
private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
@Override
public V remove(@Nullable Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
private V removeFromBothMaps(Object key) {
V oldValue = delegate.remove(key);
removeFromInverseMap(oldValue);
return oldValue;
}
private void removeFromInverseMap(V oldValue) {
inverse.delegate.remove(oldValue);
}
// Bulk Operations
@Override
public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void clear() {
delegate.clear();
inverse.delegate.clear();
}
// Views
@Override
public BiMap<V, K> inverse() {
return inverse;
}
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
private class KeySet extends ForwardingSet<K> {
@Override
protected Set<K> delegate() {
return delegate.keySet();
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
removeFromBothMaps(key);
return true;
}
@Override
public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
@Override
public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
@Override
public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
@Override
public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the iteration
* order so that it is consistent with the forward map.
*/
Set<V> result = valueSet;
return (result == null) ? valueSet = new ValueSet() : result;
}
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
@Override
protected Set<V> delegate() {
return valuesDelegate;
}
@Override
public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public String toString() {
return standardToString();
}
}
private transient Set<Entry<K, V>> entrySet;
@Override
public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
@Override
protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
// safe because esDelgate.contains(object).
Entry<?, ?> entry = (Entry<?, ?>) object;
inverse.delegate.remove(entry.getValue());
/*
* Remove the mapping in inverse before removing from esDelegate because if
* entry is part of esDelegate, entry might be invalidated after the mapping is
* removed from esDelegate.
*/
esDelegate.remove(entry);
return true;
}
@Override
public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
@Override
protected Entry<K, V> delegate() {
return finalEntry;
}
@Override
public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Objects.equal(value, getValue())) {
return value;
}
checkArgument(!containsValue(value), "value already present: %s", value);
V oldValue = finalEntry.setValue(value);
checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
@Override
public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
removeFromInverseMap(value);
}
};
}
// See java.util.Collections.CheckedEntrySet for details on attacks.
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override
public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** The inverse of any other {@code AbstractBiMap} subclass. */
private static class Inverse<K, V> extends AbstractBiMap<K, V> {
private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) {
super(backward, forward);
}
/*
* Serialization stores the forward bimap, the inverse of this inverse.
* Deserialization calls inverse() on the forward bimap and returns that
* inverse.
*
* If a bimap and its inverse are serialized together, the deserialized
* instances have inverse() methods that return the other.
*/
@Override
K checkKey(K key) {
return inverse.checkValue(key);
}
@Override
V checkValue(V value) {
return inverse.checkKey(value);
}
/**
* @serialData the forward bimap
*/
@GwtIncompatible("java.io.ObjectOuputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(inverse());
}
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
setInverse((AbstractBiMap<V, K>) stream.readObject());
}
@GwtIncompatible("Not needed in the emulated source.")
Object readResolve() {
return inverse().inverse();
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkPositionIndex;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@link ListIterator}
* interface across a fixed number of elements that may be retrieved by
* position. It does not support {@link #remove}, {@link #set}, or {@link #add}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
private final int size;
private int position;
/**
* Returns the element with the specified index. This method is called by
* {@link #next()}.
*/
protected abstract E get(int index);
/**
* Constructs an iterator across a sequence of the given size whose initial
* position is 0. That is, the first call to {@link #next()} will return the
* first element (or throw {@link NoSuchElementException} if {@code size} is
* zero).
*
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size) {
this(size, 0);
}
/**
* Constructs an iterator across a sequence of the given size with the given
* initial position. That is, the first call to {@link #nextIndex()} will return
* {@code position}, and the first call to {@link #next()} will return the
* element at that index, if available. Calls to {@link #previous()} can
* retrieve the preceding {@code position} elements.
*
* @throws IndexOutOfBoundsException if {@code position} is negative or is
* greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size, int position) {
checkPositionIndex(position, size);
this.size = size;
this.position = position;
}
@Override
public final boolean hasNext() {
return position < size;
}
@Override
public final E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return get(position++);
}
@Override
public final int nextIndex() {
return position;
}
@Override
public final boolean hasPrevious() {
return position > 0;
}
@Override
public final E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
return get(--position);
}
@Override
public final int previousIndex() {
return position - 1;
}
}

View File

@ -0,0 +1,189 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkState;
import java.util.NoSuchElementException;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface, to make this interface easier to implement for certain types of
* data sources.
*
* <p>
* {@code Iterator} requires its implementations to support querying the
* end-of-data status without changing the iterator's state, using the
* {@link #hasNext} method. But many data sources, such as
* {@link java.io.Reader#read()}, do not expose this information; the only way
* to discover whether there is any data left is by trying to retrieve it. These
* types of data sources are ordinarily difficult to write iterators for. But
* using this class, one must implement only the {@link #computeNext} method,
* and invoke the {@link #endOfData} method when appropriate.
*
* <p>
* Another example is an iterator that skips over null elements in a backing
* iterator. This could be implemented as:
*
* <pre>
* {@code
*
* public static Iterator<String> skipNulls(final Iterator<String> in) {
* return new AbstractIterator<String>() {
* protected String computeNext() {
* while (in.hasNext()) {
* String s = in.next();
* if (s != null) {
* return s;
* }
* }
* return endOfData();
* }
* };
* }}
* </pre>
*
* <p>
* This class supports iterators that include null elements.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
// When making changes to this class, please also update the copy at
// com.google.common.base.AbstractIterator
@GwtCompatible
public abstract class AbstractIterator<T> extends UnmodifiableIterator<T> {
private State state = State.NOT_READY;
/** Constructor for use by subclasses. */
protected AbstractIterator() {
}
private enum State {
/** We have computed the next element and haven't returned it yet. */
READY,
/** We haven't yet computed or have already returned the element. */
NOT_READY,
/** We have reached the end of the data and are finished. */
DONE,
/** We've suffered an exception and are kaput. */
FAILED,
}
private T next;
/**
* Returns the next element. <b>Note:</b> the implementation must call
* {@link #endOfData()} when there are no elements left in the iteration.
* Failure to do so could result in an infinite loop.
*
* <p>
* The initial invocation of {@link #hasNext()} or {@link #next()} calls this
* method, as does the first invocation of {@code hasNext} or {@code
* next} following each successful call to {@code next}. Once the implementation
* either invokes {@code endOfData} or throws an exception, {@code computeNext}
* is guaranteed to never be called again.
*
* <p>
* If this method throws an exception, it will propagate outward to the
* {@code hasNext} or {@code next} invocation that invoked this method. Any
* further attempts to use the iterator will result in an
* {@link IllegalStateException}.
*
* <p>
* The implementation of this method may not invoke the {@code hasNext},
* {@code next}, or {@link #peek()} methods on this instance; if it does, an
* {@code IllegalStateException} will result.
*
* @return the next element if there was one. If {@code endOfData} was called
* during execution, the return value will be ignored.
* @throws RuntimeException if any unrecoverable error happens. This exception
* will propagate outward to the {@code hasNext()},
* {@code next()}, or {@code peek()} invocation that
* invoked this method. Any further attempts to use the
* iterator will result in an
* {@link IllegalStateException}.
*/
protected abstract T computeNext();
/**
* Implementations of {@link #computeNext} <b>must</b> invoke this method when
* there are no elements left in the iteration.
*
* @return {@code null}; a convenience so your {@code computeNext}
* implementation can use the simple statement
* {@code return endOfData();}
*/
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case DONE:
return false;
case READY:
return true;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
/**
* Returns the next element in the iteration without advancing the iteration,
* according to the contract of {@link PeekingIterator#peek()}.
*
* <p>
* Implementations of {@code AbstractIterator} that wish to expose this
* functionality should implement {@code PeekingIterator}.
*/
public final T peek() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return next;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link ListMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned
* collections into {@code Lists}. The {@link #createCollection} method must
* return a {@code
* List}.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
abstract class AbstractListMultimap<K, V> extends AbstractMapBasedMultimap<K, V> implements ListMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractListMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract List<V> createCollection();
@Override
List<V> createUnmodifiableEmptyCollection() {
return ImmutableList.of();
}
// Following Javadoc copied from ListMultimap.
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> get(@Nullable K key) {
return (List<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> removeAll(@Nullable Object key) {
return (List<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} always
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* {@inheritDoc}
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link List} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>
* Two {@code ListMultimap} instances are equal if, for each key, they contain
* the same values in the same order. If the value orderings disagree, the
* multimaps will not be considered equal.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 6588350623831699109L;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,305 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.primitives.Ints;
/**
* Basic implementation of {@code Multiset<E>} backed by an instance of {@code
* Map<E, Count>}.
*
* <p>
* For serialization to work, the subclass must specify explicit {@code
* readObject} and {@code writeObject} methods.
*
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
private transient Map<E, Count> backingMap;
/*
* Cache the size for efficiency. Using a long lets us avoid the need for
* overflow checking and ensures that size() will function correctly even if the
* multiset had once been larger than Integer.MAX_VALUE.
*/
private transient long size;
/** Standard constructor. */
protected AbstractMapBasedMultiset(Map<E, Count> backingMap) {
this.backingMap = checkNotNull(backingMap);
this.size = super.size();
}
/** Used during deserialization only. The backing map must be empty. */
void setBackingMap(Map<E, Count> backingMap) {
this.backingMap = backingMap;
}
// Required Implementations
/**
* {@inheritDoc}
*
* <p>
* Invoking {@link Multiset.Entry#getCount} on an entry in the returned set
* always returns the current count of that element in the multiset, as opposed
* to the count at the time the entry was retrieved.
*/
@Override
public Set<Multiset.Entry<E>> entrySet() {
return super.entrySet();
}
@Override
Iterator<Entry<E>> entryIterator() {
final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
return new Iterator<Multiset.Entry<E>>() {
Map.Entry<E, Count> toRemove;
@Override
public boolean hasNext() {
return backingEntries.hasNext();
}
@Override
public Multiset.Entry<E> next() {
final Map.Entry<E, Count> mapEntry = backingEntries.next();
toRemove = mapEntry;
return new Multisets.AbstractEntry<E>() {
@Override
public E getElement() {
return mapEntry.getKey();
}
@Override
public int getCount() {
Count count = mapEntry.getValue();
if (count == null || count.get() == 0) {
Count frequency = backingMap.get(getElement());
if (frequency != null) {
return frequency.get();
}
}
return (count == null) ? 0 : count.get();
}
};
}
@Override
public void remove() {
checkRemove(toRemove != null);
size -= toRemove.getValue().getAndSet(0);
backingEntries.remove();
toRemove = null;
}
};
}
@Override
public void clear() {
for (Count frequency : backingMap.values()) {
frequency.set(0);
}
backingMap.clear();
size = 0L;
}
@Override
int distinctElements() {
return backingMap.size();
}
// Optimizations - Query Operations
@Override
public int size() {
return Ints.saturatedCast(size);
}
@Override
public Iterator<E> iterator() {
return new MapBasedMultisetIterator();
}
/*
* Not subclassing AbstractMultiset$MultisetIterator because next() needs to
* retrieve the Map.Entry<E, Count> entry, which can then be used for a more
* efficient remove() call.
*/
private class MapBasedMultisetIterator implements Iterator<E> {
final Iterator<Map.Entry<E, Count>> entryIterator;
Map.Entry<E, Count> currentEntry;
int occurrencesLeft;
boolean canRemove;
MapBasedMultisetIterator() {
this.entryIterator = backingMap.entrySet().iterator();
}
@Override
public boolean hasNext() {
return occurrencesLeft > 0 || entryIterator.hasNext();
}
@Override
public E next() {
if (occurrencesLeft == 0) {
currentEntry = entryIterator.next();
occurrencesLeft = currentEntry.getValue().get();
}
occurrencesLeft--;
canRemove = true;
return currentEntry.getKey();
}
@Override
public void remove() {
checkRemove(canRemove);
int frequency = currentEntry.getValue().get();
if (frequency <= 0) {
throw new ConcurrentModificationException();
}
if (currentEntry.getValue().addAndGet(-1) == 0) {
entryIterator.remove();
}
size--;
canRemove = false;
}
}
@Override
public int count(@Nullable Object element) {
Count frequency = Maps.safeGet(backingMap, element);
return (frequency == null) ? 0 : frequency.get();
}
// Optional Operations - Modification Operations
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the call would result in more than
* {@link Integer#MAX_VALUE} occurrences of
* {@code element} in this multiset.
*/
@Override
public int add(@Nullable E element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
int oldCount;
if (frequency == null) {
oldCount = 0;
backingMap.put(element, new Count(occurrences));
} else {
oldCount = frequency.get();
long newCount = (long) oldCount + (long) occurrences;
checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount);
frequency.getAndAdd(occurrences);
}
size += occurrences;
return oldCount;
}
@Override
public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
if (frequency == null) {
return 0;
}
int oldCount = frequency.get();
int numberRemoved;
if (oldCount > occurrences) {
numberRemoved = occurrences;
} else {
numberRemoved = oldCount;
backingMap.remove(element);
}
frequency.addAndGet(-numberRemoved);
size -= numberRemoved;
return oldCount;
}
// Roughly a 33% performance improvement over AbstractMultiset.setCount().
@Override
public int setCount(@Nullable E element, int count) {
checkNonnegative(count, "count");
Count existingCounter;
int oldCount;
if (count == 0) {
existingCounter = backingMap.remove(element);
oldCount = getAndSet(existingCounter, count);
} else {
existingCounter = backingMap.get(element);
oldCount = getAndSet(existingCounter, count);
if (existingCounter == null) {
backingMap.put(element, new Count(count));
}
}
size += (count - oldCount);
return oldCount;
}
private static int getAndSet(Count i, int count) {
if (i == null) {
return 0;
}
return i.getAndSet(count);
}
// Don't allow default serialization.
@GwtIncompatible("java.io.ObjectStreamException")
@SuppressWarnings("unused") // actually used during deserialization
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("Stream data required");
}
@GwtIncompatible("not needed in emulated source.")
private static final long serialVersionUID = -2250766705698539974L;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* Implementation of the {@code equals}, {@code hashCode}, and {@code toString}
* methods of {@code Entry}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
@Override
public abstract K getKey();
@Override
public abstract V getValue();
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue());
}
return false;
}
@Override
public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* Returns a string representation of the form {@code {key}={value}}.
*/
@Override
public String toString() {
return getKey() + "=" + getValue();
}
}

View File

@ -0,0 +1,249 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A skeleton {@code Multimap} implementation, not necessarily in terms of a
* {@code Map}.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean containsValue(@Nullable Object value) {
for (Collection<V> collection : asMap().values()) {
if (collection.contains(value)) {
return true;
}
}
return false;
}
@Override
public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.contains(value);
}
@Override
public boolean remove(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.remove(value);
}
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return get(key).add(value);
}
@Override
public boolean putAll(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
// make sure we only call values.iterator() once
// and we only call get(key) if values is nonempty
if (values instanceof Collection) {
Collection<? extends V> valueCollection = (Collection<? extends V>) values;
return !valueCollection.isEmpty() && get(key).addAll(valueCollection);
} else {
Iterator<? extends V> valueItr = values.iterator();
return valueItr.hasNext() && Iterators.addAll(get(key), valueItr);
}
}
@Override
public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
boolean changed = false;
for (Map.Entry<? extends K, ? extends V> entry : multimap.entries()) {
changed |= put(entry.getKey(), entry.getValue());
}
return changed;
}
@Override
public Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
Collection<V> result = removeAll(key);
putAll(key, values);
return result;
}
private transient Collection<Entry<K, V>> entries;
@Override
public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
return (result == null) ? entries = createEntries() : result;
}
Collection<Entry<K, V>> createEntries() {
if (this instanceof SetMultimap) {
return new EntrySet();
} else {
return new Entries();
}
}
private class Entries extends Multimaps.Entries<K, V> {
@Override
Multimap<K, V> multimap() {
return AbstractMultimap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
}
private class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
return Sets.hashCodeImpl(this);
}
@Override
public boolean equals(@Nullable Object obj) {
return Sets.equalsImpl(this, obj);
}
}
abstract Iterator<Entry<K, V>> entryIterator();
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(asMap());
}
private transient Multiset<K> keys;
@Override
public Multiset<K> keys() {
Multiset<K> result = keys;
return (result == null) ? keys = createKeys() : result;
}
Multiset<K> createKeys() {
return new Multimaps.Keys<K, V>(this);
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valueIterator();
}
@Override
public int size() {
return AbstractMultimap.this.size();
}
@Override
public boolean contains(@Nullable Object o) {
return AbstractMultimap.this.containsValue(o);
}
@Override
public void clear() {
AbstractMultimap.this.clear();
}
}
Iterator<V> valueIterator() {
return Maps.valueIterator(entries().iterator());
}
private transient Map<K, Collection<V>> asMap;
@Override
public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = asMap;
return (result == null) ? asMap = createAsMap() : result;
}
abstract Map<K, Collection<V>> createAsMap();
// Comparison and hashing
@Override
public boolean equals(@Nullable Object object) {
return Multimaps.equalsImpl(this, object);
}
/**
* Returns the hash code for this multimap.
*
* <p>
* The hash code of a multimap is defined as the hash code of the map view, as
* returned by {@link Multimap#asMap}.
*
* @see Map#hashCode
*/
@Override
public int hashCode() {
return asMap().hashCode();
}
/**
* Returns a string representation of the multimap, generated by calling
* {@code toString} on the map returned by {@link Multimap#asMap}.
*
* @return a string representation of the multimap
*/
@Override
public String toString() {
return asMap().toString();
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.collect.Multisets.setCountImpl;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* This class provides a skeletal implementation of the {@link Multiset}
* interface. A new multiset implementation can be created easily by extending
* this class and implementing the {@link Multiset#entrySet()} method, plus
* optionally overriding {@link #add(Object, int)} and
* {@link #remove(Object, int)} to enable modifications to the multiset.
*
* <p>
* The {@link #count} and {@link #size} implementations all iterate across the
* set returned by {@link Multiset#entrySet()}, as do many methods acting on the
* set returned by {@link #elementSet()}. Override those methods for better
* performance.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultiset<E> extends AbstractCollection<E> implements Multiset<E> {
// Query Operations
@Override
public int size() {
return Multisets.sizeImpl(this);
}
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
@Override
public boolean contains(@Nullable Object element) {
return count(element) > 0;
}
@Override
public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@Override
public int count(@Nullable Object element) {
for (Entry<E> entry : entrySet()) {
if (Objects.equal(entry.getElement(), element)) {
return entry.getCount();
}
}
return 0;
}
// Modification Operations
@Override
public boolean add(@Nullable E element) {
add(element, 1);
return true;
}
@Override
public int add(@Nullable E element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(@Nullable Object element) {
return remove(element, 1) > 0;
}
@Override
public int remove(@Nullable Object element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public int setCount(@Nullable E element, int count) {
return setCountImpl(this, element, count);
}
@Override
public boolean setCount(@Nullable E element, int oldCount, int newCount) {
return setCountImpl(this, element, oldCount, newCount);
}
// Bulk Operations
/**
* {@inheritDoc}
*
* <p>
* This implementation is highly efficient when {@code elementsToAdd} is itself
* a {@link Multiset}.
*/
@Override
public boolean addAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
@Override
public boolean removeAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
@Override
public boolean retainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
@Override
public void clear() {
Iterators.clear(entryIterator());
}
// Views
private transient Set<E> elementSet;
@Override
public Set<E> elementSet() {
Set<E> result = elementSet;
if (result == null) {
elementSet = result = createElementSet();
}
return result;
}
/**
* Creates a new instance of this multiset's element set, which will be returned
* by {@link #elementSet()}.
*/
Set<E> createElementSet() {
return new ElementSet();
}
class ElementSet extends Multisets.ElementSet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
}
abstract Iterator<Entry<E>> entryIterator();
abstract int distinctElements();
private transient Set<Entry<E>> entrySet;
@Override
public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
class EntrySet extends Multisets.EntrySet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
@Override
public Iterator<Entry<E>> iterator() {
return entryIterator();
}
@Override
public int size() {
return distinctElements();
}
}
Set<Entry<E>> createEntrySet() {
return new EntrySet();
}
// Object methods
/**
* {@inheritDoc}
*
* <p>
* This implementation returns {@code true} if {@code object} is a multiset of
* the same size and if, for each element, the two multisets have the same
* count.
*/
@Override
public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
/**
* {@inheritDoc}
*
* <p>
* This implementation returns the hash code of {@link Multiset#entrySet()}.
*/
@Override
public int hashCode() {
return entrySet().hashCode();
}
/**
* {@inheritDoc}
*
* <p>
* This implementation returns the result of invoking {@code toString} on
* {@link Multiset#entrySet()}.
*/
@Override
public String toString() {
return entrySet().toString();
}
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import javax.annotation.Nullable;
/**
* Skeletal implementation of {@link NavigableMap}.
*
* @author Louis Wasserman
*/
abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements NavigableMap<K, V> {
@Override
@Nullable
public abstract V get(@Nullable Object key);
@Override
@Nullable
public Entry<K, V> firstEntry() {
return Iterators.getNext(entryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> lastEntry() {
return Iterators.getNext(descendingEntryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> pollFirstEntry() {
return Iterators.pollNext(entryIterator());
}
@Override
@Nullable
public Entry<K, V> pollLastEntry() {
return Iterators.pollNext(descendingEntryIterator());
}
@Override
public K firstKey() {
Entry<K, V> entry = firstEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
public K lastKey() {
Entry<K, V> entry = lastEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
@Nullable
public Entry<K, V> lowerEntry(K key) {
return headMap(key, false).lastEntry();
}
@Override
@Nullable
public Entry<K, V> floorEntry(K key) {
return headMap(key, true).lastEntry();
}
@Override
@Nullable
public Entry<K, V> ceilingEntry(K key) {
return tailMap(key, true).firstEntry();
}
@Override
@Nullable
public Entry<K, V> higherEntry(K key) {
return tailMap(key, false).firstEntry();
}
@Override
public K lowerKey(K key) {
return Maps.keyOrNull(lowerEntry(key));
}
@Override
public K floorKey(K key) {
return Maps.keyOrNull(floorEntry(key));
}
@Override
public K ceilingKey(K key) {
return Maps.keyOrNull(ceilingEntry(key));
}
@Override
public K higherKey(K key) {
return Maps.keyOrNull(higherEntry(key));
}
abstract Iterator<Entry<K, V>> entryIterator();
abstract Iterator<Entry<K, V>> descendingEntryIterator();
@Override
public SortedMap<K, V> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
@Override
public SortedMap<K, V> headMap(K toKey) {
return headMap(toKey, false);
}
@Override
public SortedMap<K, V> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
@Override
public NavigableSet<K> navigableKeySet() {
return new Maps.NavigableKeySet<K, V>(this);
}
@Override
public Set<K> keySet() {
return navigableKeySet();
}
@Override
public abstract int size();
@Override
public Set<Entry<K, V>> entrySet() {
return new Maps.EntrySet<K, V>() {
@Override
Map<K, V> map() {
return AbstractNavigableMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
};
}
@Override
public NavigableSet<K> descendingKeySet() {
return descendingMap().navigableKeySet();
}
@Override
public NavigableMap<K, V> descendingMap() {
return new DescendingMap();
}
private final class DescendingMap extends Maps.DescendingMap<K, V> {
@Override
NavigableMap<K, V> forward() {
return AbstractNavigableMap.this;
}
@Override
Iterator<Entry<K, V>> entryIterator() {
return descendingEntryIterator();
}
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import javax.annotation.Nullable;
/**
* A skeletal implementation of {@code RangeSet}.
*
* @author Louis Wasserman
*/
abstract class AbstractRangeSet<C extends Comparable> implements RangeSet<C> {
AbstractRangeSet() {
}
@Override
public boolean contains(C value) {
return rangeContaining(value) != null;
}
@Override
public abstract Range<C> rangeContaining(C value);
@Override
public boolean isEmpty() {
return asRanges().isEmpty();
}
@Override
public void add(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
remove(Range.<C>all());
}
@Override
public boolean enclosesAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
if (!encloses(range)) {
return false;
}
}
return true;
}
@Override
public void addAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
add(range);
}
}
@Override
public void removeAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
remove(range);
}
}
@Override
public abstract boolean encloses(Range<C> otherRange);
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof RangeSet) {
RangeSet<?> other = (RangeSet<?>) obj;
return this.asRanges().equals(other.asRanges());
}
return false;
}
@Override
public final int hashCode() {
return asRanges().hashCode();
}
@Override
public final String toString() {
return asRanges().toString();
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.collect;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface for sequences whose next element can always be derived from the
* previous element. Null elements are not supported, nor is the
* {@link #remove()} method.
*
* <p>
* Example:
*
* <pre>
* {
* &#64;code
*
* Iterator<Integer> powersOfTwo = new AbstractSequentialIterator<Integer>(1) {
* protected Integer computeNext(Integer previous) {
* return (previous == 1 << 30) ? null : previous * 2;
* }
* };
* }
* </pre>
*
* @author Chris Povirk
* @since 12.0 (in Guava as {@code AbstractLinkedIterator} since 8.0)
*/
@GwtCompatible
public abstract class AbstractSequentialIterator<T> extends UnmodifiableIterator<T> {
private T nextOrNull;
/**
* Creates a new iterator with the given first element, or, if {@code
* firstOrNull} is null, creates a new empty iterator.
*/
protected AbstractSequentialIterator(@Nullable T firstOrNull) {
this.nextOrNull = firstOrNull;
}
/**
* Returns the element that follows {@code previous}, or returns {@code null} if
* no elements remain. This method is invoked during each call to
* {@link #next()} in order to compute the result of a <i>future</i> call to
* {@code next()}.
*/
protected abstract T computeNext(T previous);
@Override
public final boolean hasNext() {
return nextOrNull != null;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return nextOrNull;
} finally {
nextOrNull = computeNext(nextOrNull);
}
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link SetMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned
* collections into {@code Sets}. The {@link #createCollection} method must
* return a {@code Set}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V> implements SetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractSetMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract Set<V> createCollection();
@Override
Set<V> createUnmodifiableEmptyCollection() {
return ImmutableSet.of();
}
// Following Javadoc copied from SetMultimap.
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<V> get(@Nullable K key) {
return (Set<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<V> removeAll(@Nullable Object key) {
return (Set<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*
* <p>
* Any duplicates in {@code values} will be stored in the multimap once.
*/
@Override
public Set<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
/**
* {@inheritDoc}
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link Set} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} if the method increased the size of the multimap, or
* {@code false} if the multimap already contained the key-value pair
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>
* Two {@code SetMultimap} instances are equal if, for each key, they contain
* the same values. Equality does not depend on the ordering of keys or values.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 7431625294878419160L;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.SortedMap;
import java.util.SortedSet;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of a {@link SortedSetMultimap} with a sorted key set.
*
* This superclass allows {@code TreeMultimap} to override methods to return
* navigable set and map types in non-GWT only, while GWT code will inherit the
* SortedMap/SortedSet overrides.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractSortedKeySortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
AbstractSortedKeySortedSetMultimap(SortedMap<K, Collection<V>> map) {
super(map);
}
@Override
public SortedMap<K, Collection<V>> asMap() {
return (SortedMap<K, Collection<V>>) super.asMap();
}
@Override
SortedMap<K, Collection<V>> backingMap() {
return (SortedMap<K, Collection<V>>) super.backingMap();
}
@Override
public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@link SortedMultiset}
* interface.
*
* <p>
* The {@link #count} and {@link #size} implementations all iterate across the
* set returned by {@link Multiset#entrySet()}, as do many methods acting on the
* set returned by {@link #elementSet()}. Override those methods for better
* performance.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements SortedMultiset<E> {
@GwtTransient
final Comparator<? super E> comparator;
// needed for serialization
@SuppressWarnings("unchecked")
AbstractSortedMultiset() {
this((Comparator) Ordering.natural());
}
AbstractSortedMultiset(Comparator<? super E> comparator) {
this.comparator = checkNotNull(comparator);
}
@Override
public NavigableSet<E> elementSet() {
return (NavigableSet<E>) super.elementSet();
}
@Override
NavigableSet<E> createElementSet() {
return new SortedMultisets.NavigableElementSet<E>(this);
}
@Override
public Comparator<? super E> comparator() {
return comparator;
}
@Override
public Entry<E> firstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> lastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> pollFirstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public Entry<E> pollLastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public SortedMultiset<E> subMultiset(@Nullable E fromElement, BoundType fromBoundType, @Nullable E toElement,
BoundType toBoundType) {
// These are checked elsewhere, but NullPointerTester wants them checked
// eagerly.
checkNotNull(fromBoundType);
checkNotNull(toBoundType);
return tailMultiset(fromElement, fromBoundType).headMultiset(toElement, toBoundType);
}
abstract Iterator<Entry<E>> descendingEntryIterator();
Iterator<E> descendingIterator() {
return Multisets.iteratorImpl(descendingMultiset());
}
private transient SortedMultiset<E> descendingMultiset;
@Override
public SortedMultiset<E> descendingMultiset() {
SortedMultiset<E> result = descendingMultiset;
return (result == null) ? descendingMultiset = createDescendingMultiset() : result;
}
SortedMultiset<E> createDescendingMultiset() {
return new DescendingMultiset<E>() {
@Override
SortedMultiset<E> forwardMultiset() {
return AbstractSortedMultiset.this;
}
@Override
Iterator<Entry<E>> entryIterator() {
return descendingEntryIterator();
}
@Override
public Iterator<E> iterator() {
return descendingIterator();
}
};
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedSet;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link SortedSetMultimap} interface. It's a
* wrapper around {@link AbstractMapBasedMultimap} that converts the returned
* collections into sorted sets. The {@link #createCollection} method must
* return a {@code SortedSet}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractSortedSetMultimap<K, V> extends AbstractSetMultimap<K, V> implements SortedSetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractSortedSetMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract SortedSet<V> createCollection();
@Override
SortedSet<V> createUnmodifiableEmptyCollection() {
Comparator<? super V> comparator = valueComparator();
if (comparator == null) {
return Collections.unmodifiableSortedSet(createCollection());
} else {
return ImmutableSortedSet.emptySet(valueComparator());
}
}
// Following Javadoc copied from Multimap and SortedSetMultimap.
/**
* Returns a collection view of all values associated with a key. If no mappings
* in the multimap have the provided key, an empty collection is returned.
*
* <p>
* Changes to the returned collection will update the underlying multimap, and
* vice versa.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*/
@Override
public SortedSet<V> get(@Nullable K key) {
return (SortedSet<V>) super.get(key);
}
/**
* Removes all values associated with a given key. The returned collection is
* immutable.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*/
@Override
public SortedSet<V> removeAll(@Nullable Object key) {
return (SortedSet<V>) super.removeAll(key);
}
/**
* Stores a collection of values with the same key, replacing any existing
* values for that key. The returned collection is immutable.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*
* <p>
* Any duplicates in {@code values} will be stored in the multimap once.
*/
@Override
public SortedSet<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (SortedSet<V>) super.replaceValues(key, values);
}
/**
* Returns a map view that associates each key with the corresponding values in
* the multimap. Changes to the returned map, such as element removal, will
* update the underlying multimap. The map does not support {@code setValue} on
* its entries, {@code put}, or {@code putAll}.
*
* <p>
* When passed a key that is present in the map, {@code
* asMap().get(Object)} has the same behavior as {@link #get}, returning a live
* collection. When passed a key that is not present, however, {@code
* asMap().get(Object)} returns {@code null} instead of an empty collection.
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link SortedSet} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* {@inheritDoc}
*
* Consequently, the values do not follow their natural ordering or the ordering
* of the value comparator.
*/
@Override
public Collection<V> values() {
return super.values();
}
private static final long serialVersionUID = 430848587173315748L;
}

View File

@ -0,0 +1,220 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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.google.common.collect;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Skeletal, implementation-agnostic implementation of the {@link Table}
* interface.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
@Override
public boolean containsRow(@Nullable Object rowKey) {
return Maps.safeContainsKey(rowMap(), rowKey);
}
@Override
public boolean containsColumn(@Nullable Object columnKey) {
return Maps.safeContainsKey(columnMap(), columnKey);
}
@Override
public Set<R> rowKeySet() {
return rowMap().keySet();
}
@Override
public Set<C> columnKeySet() {
return columnMap().keySet();
}
@Override
public boolean containsValue(@Nullable Object value) {
for (Map<C, V> row : rowMap().values()) {
if (row.containsValue(value)) {
return true;
}
}
return false;
}
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return row != null && Maps.safeContainsKey(row, columnKey);
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeGet(row, columnKey);
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public void clear() {
Iterators.clear(cellSet().iterator());
}
@Override
public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeRemove(row, columnKey);
}
@Override
public V put(R rowKey, C columnKey, V value) {
return row(rowKey).put(columnKey, value);
}
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
for (Table.Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
}
private transient Set<Cell<R, C, V>> cellSet;
@Override
public Set<Cell<R, C, V>> cellSet() {
Set<Cell<R, C, V>> result = cellSet;
return (result == null) ? cellSet = createCellSet() : result;
}
Set<Cell<R, C, V>> createCellSet() {
return new CellSet();
}
abstract Iterator<Table.Cell<R, C, V>> cellIterator();
class CellSet extends AbstractSet<Cell<R, C, V>> {
@Override
public boolean contains(Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Collections2.safeContains(row.entrySet(),
Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Collections2.safeRemove(row.entrySet(),
Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public Iterator<Table.Cell<R, C, V>> iterator() {
return cellIterator();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
Iterator<V> valuesIterator() {
return new TransformedIterator<Cell<R, C, V>, V>(cellSet().iterator()) {
@Override
V transform(Cell<R, C, V> cell) {
return cell.getValue();
}
};
}
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valuesIterator();
}
@Override
public boolean contains(Object o) {
return containsValue(o);
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
@Override
public boolean equals(@Nullable Object obj) {
return Tables.equalsImpl(this, obj);
}
@Override
public int hashCode() {
return cellSet().hashCode();
}
/**
* Returns the string representation {@code rowMap().toString()}.
*/
@Override
public String toString() {
return rowMap().toString();
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An ordering that treats all references as equals, even nulls.
*
* @author Emily Soldal
*/
@GwtCompatible(serializable = true)
final class AllEqualOrdering extends Ordering<Object> implements Serializable {
static final AllEqualOrdering INSTANCE = new AllEqualOrdering();
@Override
public int compare(@Nullable Object left, @Nullable Object right) {
return 0;
}
@Override
public <E> List<E> sortedCopy(Iterable<E> iterable) {
return Lists.newArrayList(iterable);
}
@Override
public <E> ImmutableList<E> immutableSortedCopy(Iterable<E> iterable) {
return ImmutableList.copyOf(iterable);
}
@SuppressWarnings("unchecked")
@Override
public <S> Ordering<S> reverse() {
return (Ordering<S>) this;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "Ordering.allEqual()";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* Implementation of {@code Multimap} that uses an {@code ArrayList} to store
* the values for a given key. A {@link HashMap} associates each key with an
* {@link ArrayList} of values.
*
* <p>
* When iterating through the collections supplied by this class, the ordering
* of values for a given key agrees with the order in which the values were
* added.
*
* <p>
* This multimap allows duplicate key-value pairs. After adding a new key-value
* pair equal to an existing key-value pair, the {@code
* ArrayListMultimap} will contain entries for both the new value and the old
* value.
*
* <p>
* Keys and values may be null. All optional multimap methods are supported, and
* all returned views are modifiable.
*
* <p>
* The lists returned by {@link #get}, {@link #removeAll}, and
* {@link #replaceValues} all implement {@link net.lax1dude.eaglercraft.v1_8.RandomAccess}.
*
* <p>
* This class is not threadsafe when any concurrent operations update the
* multimap. Concurrent read operations will work correctly. To allow concurrent
* update operations, wrap your multimap with a call to
* {@link Multimaps#synchronizedListMultimap}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(serializable = true, emulated = true)
public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
// Default from ArrayList
private static final int DEFAULT_VALUES_PER_KEY = 3;
@VisibleForTesting
transient int expectedValuesPerKey;
/**
* Creates a new, empty {@code ArrayListMultimap} with the default initial
* capacities.
*/
public static <K, V> ArrayListMultimap<K, V> create() {
return new ArrayListMultimap<K, V>();
}
/**
* Constructs an empty {@code ArrayListMultimap} with enough capacity to hold
* the specified numbers of keys and values without resizing.
*
* @param expectedKeys the expected number of distinct keys
* @param expectedValuesPerKey the expected average number of values per key
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
/**
* Constructs an {@code ArrayListMultimap} with the same mappings as the
* specified multimap.
*
* @param multimap the multimap whose contents are copied to this multimap
*/
public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new ArrayListMultimap<K, V>(multimap);
}
private ArrayListMultimap() {
super(new HashMap<K, Collection<V>>());
expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
}
private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) {
super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(expectedKeys));
checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
this.expectedValuesPerKey = expectedValuesPerKey;
}
private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
this(multimap.keySet().size(),
(multimap instanceof ArrayListMultimap) ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
: DEFAULT_VALUES_PER_KEY);
putAll(multimap);
}
/**
* Creates a new, empty {@code ArrayList} to hold the collection of values for
* an arbitrary key.
*/
@Override
List<V> createCollection() {
return new ArrayList<V>(expectedValuesPerKey);
}
/**
* Reduces the memory used by this {@code ArrayListMultimap}, if feasible.
*/
public void trimToSize() {
for (Collection<V> collection : backingMap().values()) {
ArrayList<V> arrayList = (ArrayList<V>) collection;
arrayList.trimToSize();
}
}
/**
* @serialData expectedValuesPerKey, number of distinct keys, and then for each
* distinct key: the key, number of values for that key, and the
* key's values
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(expectedValuesPerKey);
Serialization.writeMultimap(this, stream);
}
@GwtIncompatible("java.io.ObjectOutputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
expectedValuesPerKey = stream.readInt();
int distinctKeys = Serialization.readCount(stream);
Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
setMap(map);
Serialization.populateMultimap(this, stream, distinctKeys);
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,793 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
/**
* Fixed-size {@link Table} implementation backed by a two-dimensional array.
*
* <p>
* The allowed row and column keys must be supplied when the table is created.
* The table always contains a mapping for every row key / column pair. The
* value corresponding to a given row and column is null unless another value is
* provided.
*
* <p>
* The table's size is constant: the product of the number of supplied row keys
* and the number of supplied column keys. The {@code remove} and {@code
* clear} methods are not supported by the table or its views. The
* {@link #erase} and {@link #eraseAll} methods may be used instead.
*
* <p>
* The ordering of the row and column keys provided when the table is
* constructed determines the iteration ordering across rows and columns in the
* table's views. None of the view iterators support {@link Iterator#remove}. If
* the table is modified after an iterator is created, the iterator remains
* valid.
*
* <p>
* This class requires less memory than the {@link HashBasedTable} and
* {@link TreeBasedTable} implementations, except when the table is sparse.
*
* <p>
* Null row keys or column keys are not permitted.
*
* <p>
* This class provides methods involving the underlying array structure, where
* the array indices correspond to the position of a row or column in the lists
* of allowed keys and values. See the {@link #at}, {@link #set},
* {@link #toArray}, {@link #rowKeyList}, and {@link #columnKeyList} methods for
* more details.
*
* <p>
* Note that this implementation is not synchronized. If multiple threads access
* the same cell of an {@code ArrayTable} concurrently and one of the threads
* modifies its value, there is no guarantee that the new value will be fully
* visible to the other threads. To guarantee that modifications are visible,
* synchronize access to the table. Unlike other {@code Table} implementations,
* synchronization is unnecessary between a thread that writes to one cell and a
* thread that reads from another.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
* {@code Table}</a>.
*
* @author Jared Levy
* @since 10.0
*/
@Beta
@GwtCompatible(emulated = true)
public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements Serializable {
/**
* Creates an empty {@code ArrayTable}.
*
* @param rowKeys row keys that may be stored in the generated table
* @param columnKeys column keys that may be stored in the generated table
* @throws NullPointerException if any of the provided keys is null
* @throws IllegalArgumentException if {@code rowKeys} or {@code columnKeys}
* contains duplicates or is empty
*/
public static <R, C, V> ArrayTable<R, C, V> create(Iterable<? extends R> rowKeys,
Iterable<? extends C> columnKeys) {
return new ArrayTable<R, C, V>(rowKeys, columnKeys);
}
/*
* TODO(jlevy): Add factory methods taking an Enum class, instead of an
* iterable, to specify the allowed row keys and/or column keys. Note that
* custom serialization logic is needed to support different enum sizes during
* serialization and deserialization.
*/
/**
* Creates an {@code ArrayTable} with the mappings in the provided table.
*
* <p>
* If {@code table} includes a mapping with row key {@code r} and a separate
* mapping with column key {@code c}, the returned table contains a mapping with
* row key {@code r} and column key {@code c}. If that row key / column key pair
* in not in {@code table}, the pair maps to {@code null} in the generated
* table.
*
* <p>
* The returned table allows subsequent {@code put} calls with the row keys in
* {@code table.rowKeySet()} and the column keys in {@code
* table.columnKeySet()}. Calling {@link #put} with other keys leads to an
* {@code IllegalArgumentException}.
*
* <p>
* The ordering of {@code table.rowKeySet()} and {@code
* table.columnKeySet()} determines the row and column iteration ordering of the
* returned table.
*
* @throws NullPointerException if {@code table} has a null key
* @throws IllegalArgumentException if the provided table is empty
*/
public static <R, C, V> ArrayTable<R, C, V> create(Table<R, C, V> table) {
return (table instanceof ArrayTable<?, ?, ?>) ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
: new ArrayTable<R, C, V>(table);
}
private final ImmutableList<R> rowList;
private final ImmutableList<C> columnList;
// TODO(jlevy): Add getters returning rowKeyToIndex and columnKeyToIndex?
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final V[][] array;
private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
this.rowList = ImmutableList.copyOf(rowKeys);
this.columnList = ImmutableList.copyOf(columnKeys);
checkArgument(!rowList.isEmpty());
checkArgument(!columnList.isEmpty());
/*
* TODO(jlevy): Support empty rowKeys or columnKeys? If we do, when columnKeys
* is empty but rowKeys isn't, the table is empty but containsRow() can return
* true and rowKeySet() isn't empty.
*/
rowKeyToIndex = index(rowList);
columnKeyToIndex = index(columnList);
@SuppressWarnings("unchecked")
V[][] tmpArray = (V[][]) new Object[rowList.size()][columnList.size()];
array = tmpArray;
// Necessary because in GWT the arrays are initialized with "undefined" instead
// of null.
eraseAll();
}
private static <E> ImmutableMap<E, Integer> index(List<E> list) {
ImmutableMap.Builder<E, Integer> columnBuilder = ImmutableMap.builder();
for (int i = 0; i < list.size(); i++) {
columnBuilder.put(list.get(i), i);
}
return columnBuilder.build();
}
private ArrayTable(Table<R, C, V> table) {
this(table.rowKeySet(), table.columnKeySet());
putAll(table);
}
private ArrayTable(ArrayTable<R, C, V> table) {
rowList = table.rowList;
columnList = table.columnList;
rowKeyToIndex = table.rowKeyToIndex;
columnKeyToIndex = table.columnKeyToIndex;
@SuppressWarnings("unchecked")
V[][] copy = (V[][]) new Object[rowList.size()][columnList.size()];
array = copy;
// Necessary because in GWT the arrays are initialized with "undefined" instead
// of null.
eraseAll();
for (int i = 0; i < rowList.size(); i++) {
System.arraycopy(table.array[i], 0, copy[i], 0, table.array[i].length);
}
}
private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
private final ImmutableMap<K, Integer> keyIndex;
private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
this.keyIndex = keyIndex;
}
@Override
public Set<K> keySet() {
return keyIndex.keySet();
}
K getKey(int index) {
return keyIndex.keySet().asList().get(index);
}
abstract String getKeyRole();
@Nullable
abstract V getValue(int index);
@Nullable
abstract V setValue(int index, V newValue);
@Override
public int size() {
return keyIndex.size();
}
@Override
public boolean isEmpty() {
return keyIndex.isEmpty();
}
@Override
protected Set<Entry<K, V>> createEntrySet() {
return new Maps.EntrySet<K, V>() {
@Override
Map<K, V> map() {
return ArrayMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
protected Entry<K, V> get(final int index) {
return new AbstractMapEntry<K, V>() {
@Override
public K getKey() {
return ArrayMap.this.getKey(index);
}
@Override
public V getValue() {
return ArrayMap.this.getValue(index);
}
@Override
public V setValue(V value) {
return ArrayMap.this.setValue(index, value);
}
};
}
};
}
};
}
// TODO(user): consider an optimized values() implementation
@Override
public boolean containsKey(@Nullable Object key) {
return keyIndex.containsKey(key);
}
@Override
public V get(@Nullable Object key) {
Integer index = keyIndex.get(key);
if (index == null) {
return null;
} else {
return getValue(index);
}
}
@Override
public V put(K key, V value) {
Integer index = keyIndex.get(key);
if (index == null) {
throw new IllegalArgumentException(getKeyRole() + " " + key + " not in " + keyIndex.keySet());
}
return setValue(index, value);
}
@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
}
/**
* Returns, as an immutable list, the row keys provided when the table was
* constructed, including those that are mapped to null values only.
*/
public ImmutableList<R> rowKeyList() {
return rowList;
}
/**
* Returns, as an immutable list, the column keys provided when the table was
* constructed, including those that are mapped to null values only.
*/
public ImmutableList<C> columnKeyList() {
return columnList;
}
/**
* Returns the value corresponding to the specified row and column indices. The
* same value is returned by {@code
* get(rowKeyList().get(rowIndex), columnKeyList().get(columnIndex))}, but this
* method runs more quickly.
*
* @param rowIndex position of the row key in {@link #rowKeyList()}
* @param columnIndex position of the row key in {@link #columnKeyList()}
* @return the value with the specified row and column
* @throws IndexOutOfBoundsException if either index is negative, {@code
* rowIndex} is greater then or equal to the number of
* allowed row keys, or {@code columnIndex} is
* greater then or equal to the number of
* allowed column keys
*/
public V at(int rowIndex, int columnIndex) {
// In GWT array access never throws IndexOutOfBoundsException.
checkElementIndex(rowIndex, rowList.size());
checkElementIndex(columnIndex, columnList.size());
return array[rowIndex][columnIndex];
}
/**
* Associates {@code value} with the specified row and column indices. The logic
* {@code
* put(rowKeyList().get(rowIndex), columnKeyList().get(columnIndex), value)} has
* the same behavior, but this method runs more quickly.
*
* @param rowIndex position of the row key in {@link #rowKeyList()}
* @param columnIndex position of the row key in {@link #columnKeyList()}
* @param value value to store in the table
* @return the previous value with the specified row and column
* @throws IndexOutOfBoundsException if either index is negative, {@code
* rowIndex} is greater then or equal to the number of
* allowed row keys, or {@code columnIndex} is
* greater then or equal to the number of
* allowed column keys
*/
public V set(int rowIndex, int columnIndex, @Nullable V value) {
// In GWT array access never throws IndexOutOfBoundsException.
checkElementIndex(rowIndex, rowList.size());
checkElementIndex(columnIndex, columnList.size());
V oldValue = array[rowIndex][columnIndex];
array[rowIndex][columnIndex] = value;
return oldValue;
}
/**
* Returns a two-dimensional array with the table contents. The row and column
* indices correspond to the positions of the row and column in the iterables
* provided during table construction. If the table lacks a mapping for a given
* row and column, the corresponding array element is null.
*
* <p>
* Subsequent table changes will not modify the array, and vice versa.
*
* @param valueClass class of values stored in the returned array
*/
@GwtIncompatible("reflection")
public V[][] toArray(Class<V> valueClass) {
// Can change to use varargs in JDK 1.6 if we want
@SuppressWarnings("unchecked") // TODO: safe?
V[][] copy = (V[][]) Array.newInstance(valueClass, new int[] { rowList.size(), columnList.size() });
for (int i = 0; i < rowList.size(); i++) {
System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
}
return copy;
}
/**
* Not supported. Use {@link #eraseAll} instead.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #eraseAll}
*/
@Override
@Deprecated
public void clear() {
throw new UnsupportedOperationException();
}
/**
* Associates the value {@code null} with every pair of allowed row and column
* keys.
*/
public void eraseAll() {
for (V[] row : array) {
Arrays.fill(row, null);
}
}
/**
* Returns {@code true} if the provided keys are among the keys provided when
* the table was constructed.
*/
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return containsRow(rowKey) && containsColumn(columnKey);
}
/**
* Returns {@code true} if the provided column key is among the column keys
* provided when the table was constructed.
*/
@Override
public boolean containsColumn(@Nullable Object columnKey) {
return columnKeyToIndex.containsKey(columnKey);
}
/**
* Returns {@code true} if the provided row key is among the row keys provided
* when the table was constructed.
*/
@Override
public boolean containsRow(@Nullable Object rowKey) {
return rowKeyToIndex.containsKey(rowKey);
}
@Override
public boolean containsValue(@Nullable Object value) {
for (V[] row : array) {
for (V element : row) {
if (Objects.equal(value, element)) {
return true;
}
}
}
return false;
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
}
/**
* Always returns {@code false}.
*/
@Override
public boolean isEmpty() {
return false;
}
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if {@code rowKey} is not in
* {@link #rowKeySet()} or {@code columnKey} is
* not in {@link #columnKeySet()}.
*/
@Override
public V put(R rowKey, C columnKey, @Nullable V value) {
checkNotNull(rowKey);
checkNotNull(columnKey);
Integer rowIndex = rowKeyToIndex.get(rowKey);
checkArgument(rowIndex != null, "Row %s not in %s", rowKey, rowList);
Integer columnIndex = columnKeyToIndex.get(columnKey);
checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
return set(rowIndex, columnIndex, value);
}
/*
* TODO(jlevy): Consider creating a merge() method, similar to putAll() but
* copying non-null values only.
*/
/**
* {@inheritDoc}
*
* <p>
* If {@code table} is an {@code ArrayTable}, its null values will be stored in
* this table, possibly replacing values that were previously non-null.
*
* @throws NullPointerException if {@code table} has a null key
* @throws IllegalArgumentException if any of the provided table's row keys or
* column keys is not in {@link #rowKeySet()}
* or {@link #columnKeySet()}
*/
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
super.putAll(table);
}
/**
* Not supported. Use {@link #erase} instead.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #erase}
*/
@Override
@Deprecated
public V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
/**
* Associates the value {@code null} with the specified keys, assuming both keys
* are valid. If either key is null or isn't among the keys provided during
* construction, this method has no effect.
*
* <p>
* This method is equivalent to {@code put(rowKey, columnKey, null)} when both
* provided keys are valid.
*
* @param rowKey row key of mapping to be erased
* @param columnKey column key of mapping to be erased
* @return the value previously associated with the keys, or {@code null} if no
* mapping existed for the keys
*/
public V erase(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
if (rowIndex == null || columnIndex == null) {
return null;
}
return set(rowIndex, columnIndex, null);
}
// TODO(jlevy): Add eraseRow and eraseColumn methods?
@Override
public int size() {
return rowList.size() * columnList.size();
}
/**
* Returns an unmodifiable set of all row key / column key / value triplets.
* Changes to the table will update the returned set.
*
* <p>
* The returned set's iterator traverses the mappings with the first row key,
* the mappings with the second row key, and so on.
*
* <p>
* The value in the returned cells may change if the table subsequently changes.
*
* @return set of table cells consisting of row key / column key / value
* triplets
*/
@Override
public Set<Cell<R, C, V>> cellSet() {
return super.cellSet();
}
@Override
Iterator<Cell<R, C, V>> cellIterator() {
return new AbstractIndexedListIterator<Cell<R, C, V>>(size()) {
@Override
protected Cell<R, C, V> get(final int index) {
return new Tables.AbstractCell<R, C, V>() {
final int rowIndex = index / columnList.size();
final int columnIndex = index % columnList.size();
@Override
public R getRowKey() {
return rowList.get(rowIndex);
}
@Override
public C getColumnKey() {
return columnList.get(columnIndex);
}
@Override
public V getValue() {
return at(rowIndex, columnIndex);
}
};
}
};
}
/**
* Returns a view of all mappings that have the given column key. If the column
* key isn't in {@link #columnKeySet()}, an empty immutable map is returned.
*
* <p>
* Otherwise, for each row key in {@link #rowKeySet()}, the returned map
* associates the row key with the corresponding value in the table. Changes to
* the returned map will update the underlying table, and vice versa.
*
* @param columnKey key of column to search for in the table
* @return the corresponding map from row keys to values
*/
@Override
public Map<R, V> column(C columnKey) {
checkNotNull(columnKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
}
private class Column extends ArrayMap<R, V> {
final int columnIndex;
Column(int columnIndex) {
super(rowKeyToIndex);
this.columnIndex = columnIndex;
}
@Override
String getKeyRole() {
return "Row";
}
@Override
V getValue(int index) {
return at(index, columnIndex);
}
@Override
V setValue(int index, V newValue) {
return set(index, columnIndex, newValue);
}
}
/**
* Returns an immutable set of the valid column keys, including those that are
* associated with null values only.
*
* @return immutable set of column keys
*/
@Override
public ImmutableSet<C> columnKeySet() {
return columnKeyToIndex.keySet();
}
private transient ColumnMap columnMap;
@Override
public Map<C, Map<R, V>> columnMap() {
ColumnMap map = columnMap;
return (map == null) ? columnMap = new ColumnMap() : map;
}
private class ColumnMap extends ArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnKeyToIndex);
}
@Override
String getKeyRole() {
return "Column";
}
@Override
Map<R, V> getValue(int index) {
return new Column(index);
}
@Override
Map<R, V> setValue(int index, Map<R, V> newValue) {
throw new UnsupportedOperationException();
}
@Override
public Map<R, V> put(C key, Map<R, V> value) {
throw new UnsupportedOperationException();
}
}
/**
* Returns a view of all mappings that have the given row key. If the row key
* isn't in {@link #rowKeySet()}, an empty immutable map is returned.
*
* <p>
* Otherwise, for each column key in {@link #columnKeySet()}, the returned map
* associates the column key with the corresponding value in the table. Changes
* to the returned map will update the underlying table, and vice versa.
*
* @param rowKey key of row to search for in the table
* @return the corresponding map from column keys to values
*/
@Override
public Map<C, V> row(R rowKey) {
checkNotNull(rowKey);
Integer rowIndex = rowKeyToIndex.get(rowKey);
return (rowIndex == null) ? ImmutableMap.<C, V>of() : new Row(rowIndex);
}
private class Row extends ArrayMap<C, V> {
final int rowIndex;
Row(int rowIndex) {
super(columnKeyToIndex);
this.rowIndex = rowIndex;
}
@Override
String getKeyRole() {
return "Column";
}
@Override
V getValue(int index) {
return at(rowIndex, index);
}
@Override
V setValue(int index, V newValue) {
return set(rowIndex, index, newValue);
}
}
/**
* Returns an immutable set of the valid row keys, including those that are
* associated with null values only.
*
* @return immutable set of row keys
*/
@Override
public ImmutableSet<R> rowKeySet() {
return rowKeyToIndex.keySet();
}
private transient RowMap rowMap;
@Override
public Map<R, Map<C, V>> rowMap() {
RowMap map = rowMap;
return (map == null) ? rowMap = new RowMap() : map;
}
private class RowMap extends ArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowKeyToIndex);
}
@Override
String getKeyRole() {
return "Row";
}
@Override
Map<C, V> getValue(int index) {
return new Row(index);
}
@Override
Map<C, V> setValue(int index, Map<C, V> newValue) {
throw new UnsupportedOperationException();
}
@Override
public Map<C, V> put(R key, Map<C, V> value) {
throw new UnsupportedOperationException();
}
}
/**
* Returns an unmodifiable collection of all values, which may contain
* duplicates. Changes to the table will update the returned collection.
*
* <p>
* The returned collection's iterator traverses the values of the first row key,
* the values of the second row key, and so on.
*
* @return collection of values
*/
@Override
public Collection<V> values() {
return super.values();
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A bimap (or "bidirectional map") is a map that preserves the uniqueness of
* its values as well as that of its keys. This constraint enables bimaps to
* support an "inverse view", which is another bimap containing the same entries
* as this bimap but with reversed keys and values.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface BiMap<K, V> extends Map<K, V> {
// Modification Operations
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the given value is already bound to a
* different key in this bimap. The bimap will
* remain unmodified in this event. To avoid
* this exception, call {@link #forcePut}
* instead.
*/
@Override
V put(@Nullable K key, @Nullable V value);
/**
* An alternate form of {@code put} that silently removes any existing entry
* with the value {@code value} before proceeding with the {@link #put}
* operation. If the bimap previously contained the provided key-value mapping,
* this method has no effect.
*
* <p>
* Note that a successful call to this method could cause the size of the bimap
* to increase by one, stay the same, or even decrease by one.
*
* <p>
* <b>Warning:</b> If an existing entry with this value is removed, the key for
* that entry is discarded and not returned.
*
* @param key the key with which the specified value is to be associated
* @param value the value to be associated with the specified key
* @return the value which was previously associated with the key, which may be
* {@code null}, or {@code null} if there was no previous entry
*/
V forcePut(@Nullable K key, @Nullable V value);
// Bulk Operations
/**
* {@inheritDoc}
*
* <p>
* <b>Warning:</b> the results of calling this method may vary depending on the
* iteration order of {@code map}.
*
* @throws IllegalArgumentException if an attempt to {@code put} any entry
* fails. Note that some map entries may have
* been added to the bimap before the exception
* was thrown.
*/
@Override
void putAll(Map<? extends K, ? extends V> map);
// Views
/**
* {@inheritDoc}
*
* <p>
* Because a bimap has unique values, this method returns a {@link Set}, instead
* of the {@link java.util.Collection} specified in the {@link Map} interface.
*/
@Override
Set<V> values();
/**
* Returns the inverse view of this bimap, which maps each of this bimap's
* values to its associated key. The two bimaps are backed by the same data; any
* changes to one will appear in the other.
*
* <p>
* <b>Note:</b>There is no guaranteed correspondence between the iteration order
* of a bimap and that of its inverse.
*
* @return the inverse view of this bimap
*/
BiMap<V, K> inverse();
}

View File

@ -0,0 +1,213 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.Deque;
import java.util.Iterator;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Optional;
/**
* A variant of {@link TreeTraverser} for binary trees, providing additional
* traversals specific to binary trees.
*
* @author Louis Wasserman
* @since 15.0
*/
@Beta
@GwtCompatible(emulated = true)
public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
// TODO(user): make this GWT-compatible when we've checked in ArrayDeque and
// BitSet emulation
/**
* Returns the left child of the specified node, or {@link Optional#absent()} if
* the specified node has no left child.
*/
public abstract Optional<T> leftChild(T root);
/**
* Returns the right child of the specified node, or {@link Optional#absent()}
* if the specified node has no right child.
*/
public abstract Optional<T> rightChild(T root);
/**
* Returns the children of this node, in left-to-right order.
*/
@Override
public final Iterable<T> children(final T root) {
checkNotNull(root);
return new FluentIterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
boolean doneLeft;
boolean doneRight;
@Override
protected T computeNext() {
if (!doneLeft) {
doneLeft = true;
Optional<T> left = leftChild(root);
if (left.isPresent()) {
return left.get();
}
}
if (!doneRight) {
doneRight = true;
Optional<T> right = rightChild(root);
if (right.isPresent()) {
return right.get();
}
}
return endOfData();
}
};
}
};
}
@Override
UnmodifiableIterator<T> preOrderIterator(T root) {
return new PreOrderIterator(root);
}
/*
* Optimized implementation of preOrderIterator for binary trees.
*/
private final class PreOrderIterator extends UnmodifiableIterator<T> implements PeekingIterator<T> {
private final Deque<T> stack;
PreOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
stack.addLast(root);
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public T next() {
T result = stack.removeLast();
pushIfPresent(stack, rightChild(result));
pushIfPresent(stack, leftChild(result));
return result;
}
@Override
public T peek() {
return stack.getLast();
}
}
@Override
UnmodifiableIterator<T> postOrderIterator(T root) {
return new PostOrderIterator(root);
}
/*
* Optimized implementation of postOrderIterator for binary trees.
*/
private final class PostOrderIterator extends UnmodifiableIterator<T> {
private final Deque<T> stack;
private final BitSet hasExpanded;
PostOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
stack.addLast(root);
this.hasExpanded = new BitSet();
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public T next() {
while (true) {
T node = stack.getLast();
boolean expandedNode = hasExpanded.get(stack.size() - 1);
if (expandedNode) {
stack.removeLast();
hasExpanded.clear(stack.size());
return node;
} else {
hasExpanded.set(stack.size() - 1);
pushIfPresent(stack, rightChild(node));
pushIfPresent(stack, leftChild(node));
}
}
}
}
// TODO(user): see if any significant optimizations are possible for
// breadthFirstIterator
public final FluentIterable<T> inOrderTraversal(final T root) {
checkNotNull(root);
return new FluentIterable<T>() {
@Override
public UnmodifiableIterator<T> iterator() {
return new InOrderIterator(root);
}
};
}
private final class InOrderIterator extends AbstractIterator<T> {
private final Deque<T> stack;
private final BitSet hasExpandedLeft;
InOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
this.hasExpandedLeft = new BitSet();
stack.addLast(root);
}
@Override
protected T computeNext() {
while (!stack.isEmpty()) {
T node = stack.getLast();
if (hasExpandedLeft.get(stack.size() - 1)) {
stack.removeLast();
hasExpandedLeft.clear(stack.size());
pushIfPresent(stack, rightChild(node));
return node;
} else {
hasExpandedLeft.set(stack.size() - 1);
pushIfPresent(stack, leftChild(node));
}
}
return endOfData();
}
}
private static <T> void pushIfPresent(Deque<T> stack, Optional<T> node) {
if (node.isPresent()) {
stack.addLast(node.get());
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Indicates whether an endpoint of some range is contained in the range itself
* ("closed") or not ("open"). If a range is unbounded on a side, it is neither
* open nor closed on that side; the bound simply does not exist.
*
* @since 10.0
*/
@GwtCompatible
public enum BoundType {
/**
* The endpoint value <i>is not</i> considered part of the set ("exclusive").
*/
OPEN {
@Override
BoundType flip() {
return CLOSED;
}
},
/**
* The endpoint value <i>is</i> considered part of the set ("inclusive").
*/
CLOSED {
@Override
BoundType flip() {
return OPEN;
}
};
/**
* Returns the bound type corresponding to a boolean value for inclusivity.
*/
static BoundType forBoolean(boolean inclusive) {
return inclusive ? CLOSED : OPEN;
}
abstract BoundType flip();
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Objects;
/**
* An ordering that orders elements by applying an order to the result of a
* function on those elements.
*/
@GwtCompatible(serializable = true)
final class ByFunctionOrdering<F, T> extends Ordering<F> implements Serializable {
final Function<F, ? extends T> function;
final Ordering<T> ordering;
ByFunctionOrdering(Function<F, ? extends T> function, Ordering<T> ordering) {
this.function = checkNotNull(function);
this.ordering = checkNotNull(ordering);
}
@Override
public int compare(F left, F right) {
return ordering.compare(function.apply(left), function.apply(right));
}
@Override
public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
if (object instanceof ByFunctionOrdering) {
ByFunctionOrdering<?, ?> that = (ByFunctionOrdering<?, ?>) object;
return this.function.equals(that.function) && this.ordering.equals(that.ordering);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, ordering);
}
@Override
public String toString() {
return ordering + ".onResultOf(" + function + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkElementIndex;
import java.util.AbstractList;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.math.IntMath;
/**
* Implementation of {@link Lists#cartesianProduct(List)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class CartesianList<E> extends AbstractList<List<E>> implements RandomAccess {
private transient final ImmutableList<List<E>> axes;
private transient final int[] axesSizeProduct;
static <E> List<List<E>> create(List<? extends List<? extends E>> lists) {
ImmutableList.Builder<List<E>> axesBuilder = new ImmutableList.Builder<List<E>>(lists.size());
for (List<? extends E> list : lists) {
List<E> copy = ImmutableList.copyOf(list);
if (copy.isEmpty()) {
return ImmutableList.of();
}
axesBuilder.add(copy);
}
return new CartesianList<E>(axesBuilder.build());
}
CartesianList(ImmutableList<List<E>> axes) {
this.axes = axes;
int[] axesSizeProduct = new int[axes.size() + 1];
axesSizeProduct[axes.size()] = 1;
try {
for (int i = axes.size() - 1; i >= 0; i--) {
axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[i + 1], axes.get(i).size());
}
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Cartesian product too large; must have size at most Integer.MAX_VALUE");
}
this.axesSizeProduct = axesSizeProduct;
}
private int getAxisIndexForProductIndex(int index, int axis) {
return (index / axesSizeProduct[axis + 1]) % axes.get(axis).size();
}
@Override
public ImmutableList<E> get(final int index) {
checkElementIndex(index, size());
return new ImmutableList<E>() {
@Override
public int size() {
return axes.size();
}
@Override
public E get(int axis) {
checkElementIndex(axis, size());
int axisIndex = getAxisIndexForProductIndex(index, axis);
return axes.get(axis).get(axisIndex);
}
@Override
boolean isPartialView() {
return true;
}
};
}
@Override
public int size() {
return axesSizeProduct[0];
}
@Override
public boolean contains(@Nullable Object o) {
if (!(o instanceof List)) {
return false;
}
List<?> list = (List<?>) o;
if (list.size() != axes.size()) {
return false;
}
ListIterator<?> itr = list.listIterator();
while (itr.hasNext()) {
int index = itr.nextIndex();
if (!axes.get(index).contains(itr.next())) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A map, each entry of which maps a Java
* <a href="http://tinyurl.com/2cmwkz">raw type</a> to an instance of that type.
* In addition to implementing {@code Map}, the additional type-safe operations
* {@link #putInstance} and {@link #getInstance} are available.
*
* <p>
* Like any other {@code Map<Class, Object>}, this map may contain entries for
* primitive types, and a primitive type and its corresponding wrapper type may
* map to different values.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
* {@code ClassToInstanceMap}</a>.
*
* <p>
* To map a generic type to an instance of that type, use
* {@link com.google.common.reflect.TypeToInstanceMap} instead.
*
* @param <B> the common supertype that all entries must share; often this is
* simply {@link Object}
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface ClassToInstanceMap<B> extends Map<Class<? extends B>, B> {
/**
* Returns the value the specified class is mapped to, or {@code null} if no
* entry for this class is present. This will only return a value that was bound
* to this specific class, not a value that may have been bound to a subtype.
*/
<T extends B> T getInstance(Class<T> type);
/**
* Maps the specified class to the specified value. Does <i>not</i> associate
* this value with any of the class's supertypes.
*
* @return the value previously associated with this class (possibly {@code
* null}), or {@code null} if there was no previous entry.
*/
<T extends B> T putInstance(Class<T> type, @Nullable T value);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
/**
* Precondition checks useful in collection implementations.
*/
@GwtCompatible
final class CollectPreconditions {
static void checkEntryNotNull(Object key, Object value) {
if (key == null) {
throw new NullPointerException("null key in entry: null=" + value);
} else if (value == null) {
throw new NullPointerException("null value in entry: " + key + "=null");
}
}
static int checkNonnegative(int value, String name) {
if (value < 0) {
throw new IllegalArgumentException(name + " cannot be negative but was: " + value);
}
return value;
}
/**
* Precondition tester for {@code Iterator.remove()} that throws an exception
* with a consistent error message.
*/
static void checkRemove(boolean canRemove) {
checkState(canRemove, "no calls to next() since the last call to remove()");
}
}

View File

@ -0,0 +1,695 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.math.LongMath.binomial;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
/**
* Provides static methods for working with {@code Collection} instances.
*
* @author Chris Povirk
* @author Mike Bostock
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Collections2 {
private Collections2() {
}
/**
* Returns the elements of {@code unfiltered} that satisfy a predicate. The
* returned collection is a live view of {@code unfiltered}; changes to one
* affect the other.
*
* <p>
* The resulting collection's iterator does not support {@code remove()}, but
* all other collection methods are supported. When given an element that
* doesn't satisfy the predicate, the collection's {@code add()} and {@code
* addAll()} methods throw an {@link IllegalArgumentException}. When methods
* such as {@code removeAll()} and {@code clear()} are called on the filtered
* collection, only elements that satisfy the filter will be removed from the
* underlying collection.
*
* <p>
* The returned collection isn't threadsafe or serializable, even if
* {@code unfiltered} is.
*
* <p>
* Many of the filtered collection's methods, such as {@code size()}, iterate
* across every element in the underlying collection and determine which
* elements satisfy the filter. When a live view is <i>not</i> needed, it may be
* faster to copy {@code Iterables.filter(unfiltered, predicate)} and use the
* copy.
*
* <p>
* <b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as
* documented at {@link Predicate#apply}. Do not provide a predicate such as
* {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent with
* equals. (See {@link Iterables#filter(Iterable, Class)} for related
* functionality.)
*/
// TODO(kevinb): how can we omit that Iterables link when building gwt
// javadoc?
public static <E> Collection<E> filter(Collection<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredCollection) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
}
return new FilteredCollection<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
/**
* Delegates to {@link Collection#contains}. Returns {@code false} if the
* {@code contains} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeContains(Collection<?> collection, @Nullable Object object) {
checkNotNull(collection);
try {
return collection.contains(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* Delegates to {@link Collection#remove}. Returns {@code false} if the
* {@code remove} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeRemove(Collection<?> collection, @Nullable Object object) {
checkNotNull(collection);
try {
return collection.remove(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
static class FilteredCollection<E> extends AbstractCollection<E> {
final Collection<E> unfiltered;
final Predicate<? super E> predicate;
FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
return new FilteredCollection<E>(unfiltered, Predicates.<E>and(predicate, newPredicate));
// .<E> above needed to compile in JDK 5
}
@Override
public boolean add(E element) {
checkArgument(predicate.apply(element));
return unfiltered.add(element);
}
@Override
public boolean addAll(Collection<? extends E> collection) {
for (E element : collection) {
checkArgument(predicate.apply(element));
}
return unfiltered.addAll(collection);
}
@Override
public void clear() {
Iterables.removeIf(unfiltered, predicate);
}
@Override
public boolean contains(@Nullable Object element) {
if (safeContains(unfiltered, element)) {
@SuppressWarnings("unchecked") // element is in unfiltered, so it must be an E
E e = (E) element;
return predicate.apply(e);
}
return false;
}
@Override
public boolean containsAll(Collection<?> collection) {
return containsAllImpl(this, collection);
}
@Override
public boolean isEmpty() {
return !Iterables.any(unfiltered, predicate);
}
@Override
public Iterator<E> iterator() {
return Iterators.filter(unfiltered.iterator(), predicate);
}
@Override
public boolean remove(Object element) {
return contains(element) && unfiltered.remove(element);
}
@Override
public boolean removeAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, (Predicate<E>)in(collection)));
}
@Override
public boolean retainAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, (Predicate<E>)not(in(collection))));
}
@Override
public int size() {
return Iterators.size(iterator());
}
@Override
public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
@Override
public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
/**
* Returns a collection that applies {@code function} to each element of
* {@code fromCollection}. The returned collection is a live view of {@code
* fromCollection}; changes to one affect the other.
*
* <p>
* The returned collection's {@code add()} and {@code addAll()} methods throw an
* {@link UnsupportedOperationException}. All other collection methods are
* supported, as long as {@code fromCollection} supports them.
*
* <p>
* The returned collection isn't threadsafe or serializable, even if
* {@code fromCollection} is.
*
* <p>
* When a live view is <i>not</i> needed, it may be faster to copy the
* transformed collection and use the copy.
*
* <p>
* If the input {@code Collection} is known to be a {@code List}, consider
* {@link Lists#transform}. If only an {@code Iterable} is available, use
* {@link Iterables#transform}.
*/
public static <F, T> Collection<T> transform(Collection<F> fromCollection, Function<? super F, T> function) {
return new TransformedCollection<F, T>(fromCollection, function);
}
static class TransformedCollection<F, T> extends AbstractCollection<T> {
final Collection<F> fromCollection;
final Function<? super F, ? extends T> function;
TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function) {
this.fromCollection = checkNotNull(fromCollection);
this.function = checkNotNull(function);
}
@Override
public void clear() {
fromCollection.clear();
}
@Override
public boolean isEmpty() {
return fromCollection.isEmpty();
}
@Override
public Iterator<T> iterator() {
return Iterators.transform(fromCollection.iterator(), function);
}
@Override
public int size() {
return fromCollection.size();
}
}
/**
* Returns {@code true} if the collection {@code self} contains all of the
* elements in the collection {@code c}.
*
* <p>
* This method iterates over the specified collection {@code c}, checking each
* element returned by the iterator in turn to see if it is contained in the
* specified collection {@code self}. If all elements are so contained,
* {@code true} is returned, otherwise {@code false}.
*
* @param self a collection which might contain all elements in {@code c}
* @param c a collection whose elements might be contained by {@code self}
*/
static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
return Iterables.all(c, Predicates.in(self));
}
/**
* An implementation of {@link Collection#toString()}.
*/
static String toStringImpl(final Collection<?> collection) {
StringBuilder sb = newStringBuilderForCollection(collection.size()).append('[');
STANDARD_JOINER.appendTo(sb, Iterables.transform(collection, new Function<Object, Object>() {
@Override
public Object apply(Object input) {
return input == collection ? "(this Collection)" : input;
}
}));
return sb.append(']').toString();
}
/**
* Returns best-effort-sized StringBuilder based on the given collection size.
*/
static StringBuilder newStringBuilderForCollection(int size) {
checkNonnegative(size, "size");
return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
}
/**
* Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
*/
static <T> Collection<T> cast(Iterable<T> iterable) {
return (Collection<T>) iterable;
}
static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null");
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable}.
*
* <p>
* <i>Notes:</i> This is an implementation of the algorithm for Lexicographical
* Permutations Generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2. The iteration order
* follows the lexicographical order. This means that the first permutation will
* be in ascending order, and the last will be in descending order.
*
* <p>
* Duplicate elements are considered equal. For example, the list [1, 1] will
* have only one permutation, instead of two. This is why the elements have to
* implement {@link Comparable}.
*
* <p>
* An empty iterable has only one permutation, which is an empty list.
*
* <p>
* This method is equivalent to
* {@code Collections2.orderedPermutations(list, Ordering.natural())}.
*
* @param elements the original iterable whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException if the specified iterable is null or has any
* null elements.
* @since 12.0
*/
@Beta
public static <E extends Comparable<? super E>> Collection<List<E>> orderedPermutations(Iterable<E> elements) {
return orderedPermutations(elements, Ordering.natural());
}
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable} using the specified {@link Comparator} for establishing the
* lexicographical ordering.
*
* <p>
* Examples:
*
* <pre>
* {@code
*
* for (List<String> perm : orderedPermutations(asList("b", "c", "a"))) {
* println(perm);
* }
* // -> ["a", "b", "c"]
* // -> ["a", "c", "b"]
* // -> ["b", "a", "c"]
* // -> ["b", "c", "a"]
* // -> ["c", "a", "b"]
* // -> ["c", "b", "a"]
*
* for (List<Integer> perm : orderedPermutations(asList(1, 2, 2, 1))) {
* println(perm);
* }
* // -> [1, 1, 2, 2]
* // -> [1, 2, 1, 2]
* // -> [1, 2, 2, 1]
* // -> [2, 1, 1, 2]
* // -> [2, 1, 2, 1]
* // -> [2, 2, 1, 1]}
* </pre>
*
* <p>
* <i>Notes:</i> This is an implementation of the algorithm for Lexicographical
* Permutations Generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2. The iteration order
* follows the lexicographical order. This means that the first permutation will
* be in ascending order, and the last will be in descending order.
*
* <p>
* Elements that compare equal are considered equal and no new permutations are
* created by swapping them.
*
* <p>
* An empty iterable has only one permutation, which is an empty list.
*
* @param elements the original iterable whose elements have to be permuted.
* @param comparator a comparator for the iterable's elements.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException If the specified iterable is null, has any null
* elements, or if the specified comparator is
* null.
* @since 12.0
*/
@Beta
public static <E> Collection<List<E>> orderedPermutations(Iterable<E> elements, Comparator<? super E> comparator) {
return new OrderedPermutationCollection<E>(elements, comparator);
}
private static final class OrderedPermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
final Comparator<? super E> comparator;
final int size;
OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator) {
this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
this.comparator = comparator;
this.size = calculateSize(inputList, comparator);
}
/**
* The number of permutations with repeated elements is calculated as follows:
* <ul>
* <li>For an empty list, it is 1 (base case).</li>
* <li>When r numbers are added to a list of n-r elements, the number of
* permutations is increased by a factor of (n choose r).</li>
* </ul>
*/
private static <E> int calculateSize(List<E> sortedInputList, Comparator<? super E> comparator) {
long permutations = 1;
int n = 1;
int r = 1;
while (n < sortedInputList.size()) {
int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n));
if (comparison < 0) {
// We move to the next non-repeated element.
permutations *= binomial(n, r);
r = 0;
if (!isPositiveInt(permutations)) {
return Integer.MAX_VALUE;
}
}
n++;
r++;
}
permutations *= binomial(n, r);
if (!isPositiveInt(permutations)) {
return Integer.MAX_VALUE;
}
return (int) permutations;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Iterator<List<E>> iterator() {
return new OrderedPermutationIterator<E>(inputList, comparator);
}
@Override
public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
}
return false;
}
@Override
public String toString() {
return "orderedPermutationCollection(" + inputList + ")";
}
}
private static final class OrderedPermutationIterator<E> extends AbstractIterator<List<E>> {
List<E> nextPermutation;
final Comparator<? super E> comparator;
OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator) {
this.nextPermutation = Lists.newArrayList(list);
this.comparator = comparator;
}
@Override
protected List<E> computeNext() {
if (nextPermutation == null) {
return endOfData();
}
ImmutableList<E> next = ImmutableList.copyOf(nextPermutation);
calculateNextPermutation();
return next;
}
void calculateNextPermutation() {
int j = findNextJ();
if (j == -1) {
nextPermutation = null;
return;
}
int l = findNextL(j);
Collections.swap(nextPermutation, j, l);
int n = nextPermutation.size();
Collections.reverse(nextPermutation.subList(j + 1, n));
}
int findNextJ() {
for (int k = nextPermutation.size() - 2; k >= 0; k--) {
if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) {
return k;
}
}
return -1;
}
int findNextL(int j) {
E ak = nextPermutation.get(j);
for (int l = nextPermutation.size() - 1; l > j; l--) {
if (comparator.compare(ak, nextPermutation.get(l)) < 0) {
return l;
}
}
throw new AssertionError("this statement should be unreachable");
}
}
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Collection}.
*
* <p>
* <i>Notes:</i> This is an implementation of the Plain Changes algorithm for
* permutations generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2.
*
* <p>
* If the input list contains equal elements, some of the generated permutations
* will be equal.
*
* <p>
* An empty collection has only one permutation, which is an empty list.
*
* @param elements the original collection whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original collection.
* @throws NullPointerException if the specified collection is null or has any
* null elements.
* @since 12.0
*/
@Beta
public static <E> Collection<List<E>> permutations(Collection<E> elements) {
return new PermutationCollection<E>(ImmutableList.copyOf(elements));
}
private static final class PermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
PermutationCollection(ImmutableList<E> input) {
this.inputList = input;
}
@Override
public int size() {
return IntMath.factorial(inputList.size());
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Iterator<List<E>> iterator() {
return new PermutationIterator<E>(inputList);
}
@Override
public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
}
return false;
}
@Override
public String toString() {
return "permutations(" + inputList + ")";
}
}
private static class PermutationIterator<E> extends AbstractIterator<List<E>> {
final List<E> list;
final int[] c;
final int[] o;
int j;
PermutationIterator(List<E> list) {
this.list = new ArrayList<E>(list);
int n = list.size();
c = new int[n];
o = new int[n];
Arrays.fill(c, 0);
Arrays.fill(o, 1);
j = Integer.MAX_VALUE;
}
@Override
protected List<E> computeNext() {
if (j <= 0) {
return endOfData();
}
ImmutableList<E> next = ImmutableList.copyOf(list);
calculateNextPermutation();
return next;
}
void calculateNextPermutation() {
j = list.size() - 1;
int s = 0;
// Handle the special case of an empty list. Skip the calculation of the
// next permutation.
if (j == -1) {
return;
}
while (true) {
int q = c[j] + o[j];
if (q < 0) {
switchDirection();
continue;
}
if (q == j + 1) {
if (j == 0) {
break;
}
s++;
switchDirection();
continue;
}
Collections.swap(list, j - c[j] + s, j - q + s);
c[j] = q;
break;
}
}
void switchDirection() {
o[j] = -o[j];
j--;
}
}
/**
* Returns {@code true} if the second list is a permutation of the first.
*/
private static boolean isPermutation(List<?> first, List<?> second) {
if (first.size() != second.size()) {
return false;
}
Multiset<?> firstMultiset = HashMultiset.create(first);
Multiset<?> secondMultiset = HashMultiset.create(second);
return firstMultiset.equals(secondMultiset);
}
private static boolean isPositiveInt(long n) {
return n >= 0 && n <= Integer.MAX_VALUE;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/** An ordering for a pre-existing comparator. */
@GwtCompatible(serializable = true)
final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
final Comparator<T> comparator;
ComparatorOrdering(Comparator<T> comparator) {
this.comparator = checkNotNull(comparator);
}
@Override
public int compare(T a, T b) {
return comparator.compare(a, b);
}
@Override
public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
if (object instanceof ComparatorOrdering) {
ComparatorOrdering<?> that = (ComparatorOrdering<?>) object;
return this.comparator.equals(that.comparator);
}
return false;
}
@Override
public int hashCode() {
return comparator.hashCode();
}
@Override
public String toString() {
return comparator.toString();
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,253 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.primitives.Booleans;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
/**
* A utility for performing a chained comparison statement. For example:
*
* <pre>
* {@code
*
* public int compareTo(Foo that) {
* return ComparisonChain.start()
* .compare(this.aString, that.aString)
* .compare(this.anInt, that.anInt)
* .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
* .result();
* }}
* </pre>
*
* <p>
* The value of this expression will have the same sign as the <i>first
* nonzero</i> comparison result in the chain, or will be zero if every
* comparison result was zero.
*
* <p>
* Performance note: Even though the {@code ComparisonChain} caller always
* invokes its {@code compare} methods unconditionally, the {@code
* ComparisonChain} implementation stops calling its inputs'
* {@link Comparable#compareTo compareTo} and {@link Comparator#compare compare}
* methods as soon as one of them returns a nonzero result. This optimization is
* typically important only in the presence of expensive {@code compareTo} and
* {@code compare} implementations.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo">
* {@code ComparisonChain}</a>.
*
* @author Mark Davis
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public abstract class ComparisonChain {
private ComparisonChain() {
}
/**
* Begins a new chained comparison statement. See example in the class
* documentation.
*/
public static ComparisonChain start() {
return ACTIVE;
}
private static final ComparisonChain ACTIVE = new ComparisonChain() {
@SuppressWarnings("unchecked")
@Override
public ComparisonChain compare(Comparable left, Comparable right) {
return classify(left.compareTo(right));
}
@Override
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator<T> comparator) {
return classify(comparator.compare(left, right));
}
@Override
public ComparisonChain compare(int left, int right) {
return classify(Ints.compare(left, right));
}
@Override
public ComparisonChain compare(long left, long right) {
return classify(Longs.compare(left, right));
}
@Override
public ComparisonChain compare(float left, float right) {
return classify(Float.compare(left, right));
}
@Override
public ComparisonChain compare(double left, double right) {
return classify(Double.compare(left, right));
}
@Override
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return classify(Booleans.compare(right, left)); // reversed
}
@Override
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return classify(Booleans.compare(left, right));
}
ComparisonChain classify(int result) {
return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE;
}
@Override
public int result() {
return 0;
}
};
private static final ComparisonChain LESS = new InactiveComparisonChain(-1);
private static final ComparisonChain GREATER = new InactiveComparisonChain(1);
private static final class InactiveComparisonChain extends ComparisonChain {
final int result;
InactiveComparisonChain(int result) {
this.result = result;
}
@Override
public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) {
return this;
}
@Override
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, @Nullable Comparator<T> comparator) {
return this;
}
@Override
public ComparisonChain compare(int left, int right) {
return this;
}
@Override
public ComparisonChain compare(long left, long right) {
return this;
}
@Override
public ComparisonChain compare(float left, float right) {
return this;
}
@Override
public ComparisonChain compare(double left, double right) {
return this;
}
@Override
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return this;
}
@Override
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return this;
}
@Override
public int result() {
return result;
}
}
/**
* Compares two comparable objects as specified by {@link Comparable#compareTo},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(Comparable<?> left, Comparable<?> right);
/**
* Compares two objects using a comparator, <i>if</i> the result of this
* comparison chain has not already been determined.
*/
public abstract <T> ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator<T> comparator);
/**
* Compares two {@code int} values as specified by {@link Ints#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(int left, int right);
/**
* Compares two {@code long} values as specified by {@link Longs#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(long left, long right);
/**
* Compares two {@code float} values as specified by {@link Float#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(float left, float right);
/**
* Compares two {@code double} values as specified by {@link Double#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(double left, double right);
/**
* Compares two {@code boolean} values, considering {@code true} to be less than
* {@code false}, <i>if</i> the result of this comparison chain has not already
* been determined.
*
* @since 12.0
*/
public abstract ComparisonChain compareTrueFirst(boolean left, boolean right);
/**
* Compares two {@code boolean} values, considering {@code false} to be less
* than {@code true}, <i>if</i> the result of this comparison chain has not
* already been determined.
*
* @since 12.0 (present as {@code compare} since 2.0)
*/
public abstract ComparisonChain compareFalseFirst(boolean left, boolean right);
/**
* Ends this comparison chain and returns its result: a value having the same
* sign as the first nonzero comparison result in the chain, or zero if every
* result was zero.
*/
public abstract int result();
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import java.util.Comparator;
import com.google.common.annotations.GwtCompatible;
/** An ordering that tries several comparators in order. */
@GwtCompatible(serializable = true)
final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableList<Comparator<? super T>> comparators;
CompoundOrdering(Comparator<? super T> primary, Comparator<? super T> secondary) {
this.comparators = ImmutableList.<Comparator<? super T>>of(primary, secondary);
}
CompoundOrdering(Iterable<? extends Comparator<? super T>> comparators) {
this.comparators = ImmutableList.copyOf(comparators);
}
@Override
public int compare(T left, T right) {
// Avoid using the Iterator to avoid generating garbage (issue 979).
int size = comparators.size();
for (int i = 0; i < size; i++) {
int result = comparators.get(i).compare(left, right);
if (result != 0) {
return result;
}
}
return 0;
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof CompoundOrdering) {
CompoundOrdering<?> that = (CompoundOrdering<?>) object;
return this.comparators.equals(that.comparators);
}
return false;
}
@Override
public int hashCode() {
return comparators.hashCode();
}
@Override
public String toString() {
return "Ordering.compound(" + comparators + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Wraps an exception that occurred during a computation.
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public class ComputationException extends RuntimeException {
/**
* Creates a new instance with the given cause.
*/
public ComputationException(@Nullable Throwable cause) {
super(cause);
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* A constraint that an element must satisfy in order to be added to a
* collection. For example, {@link Constraints#notNull()}, which prevents a
* collection from including any null elements, could be implemented like this:
*
* <pre>
* {@code
*
* public Object checkElement(Object element) {
* if (element == null) {
* throw new NullPointerException();
* }
* return element;
* }}
* </pre>
*
* <p>
* In order to be effective, constraints should be deterministic; that is, they
* should not depend on state that can change (such as external state, random
* variables, and time) and should only depend on the value of the passed-in
* element. A non-deterministic constraint cannot reliably enforce that all the
* collection's elements meet the constraint, since the constraint is only
* enforced when elements are added.
*
* @author Mike Bostock
*/
@GwtCompatible
interface Constraint<E> {
/**
* Throws a suitable {@code RuntimeException} if the specified element is
* illegal. Typically this is either a {@link NullPointerException}, an
* {@link IllegalArgumentException}, or a {@link ClassCastException}, though an
* application-specific exception class may be used if appropriate.
*
* @param element the element to check
* @return the provided element
*/
E checkElement(E element);
/**
* Returns a brief human readable description of this constraint, such as "Not
* null" or "Positive number".
*/
@Override
String toString();
}

View File

@ -0,0 +1,340 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.annotations.GwtCompatible;
/**
* Factories and utilities pertaining to the {@link Constraint} interface.
*
* @author Mike Bostock
* @author Jared Levy
*/
@GwtCompatible
final class Constraints {
private Constraints() {
}
/**
* Returns a constrained view of the specified collection, using the specified
* constraint. Any operations that add new elements to the collection will call
* the provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned collection is not serializable.
*
* @param collection the collection to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the collection
*/
public static <E> Collection<E> constrainedCollection(Collection<E> collection, Constraint<? super E> constraint) {
return new ConstrainedCollection<E>(collection, constraint);
}
/** @see Constraints#constrainedCollection */
static class ConstrainedCollection<E> extends ForwardingCollection<E> {
private final Collection<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedCollection(Collection<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected Collection<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified set, using the specified
* constraint. Any operations that add new elements to the set will call the
* provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned set is not serializable.
*
* @param set the set to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the set
*/
public static <E> Set<E> constrainedSet(Set<E> set, Constraint<? super E> constraint) {
return new ConstrainedSet<E>(set, constraint);
}
/** @see Constraints#constrainedSet */
static class ConstrainedSet<E> extends ForwardingSet<E> {
private final Set<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedSet(Set<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected Set<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified sorted set, using the specified
* constraint. Any operations that add new elements to the sorted set will call
* the provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned set is not serializable.
*
* @param sortedSet the sorted set to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the sorted set
*/
public static <E> SortedSet<E> constrainedSortedSet(SortedSet<E> sortedSet, Constraint<? super E> constraint) {
return new ConstrainedSortedSet<E>(sortedSet, constraint);
}
/** @see Constraints#constrainedSortedSet */
private static class ConstrainedSortedSet<E> extends ForwardingSortedSet<E> {
final SortedSet<E> delegate;
final Constraint<? super E> constraint;
ConstrainedSortedSet(SortedSet<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected SortedSet<E> delegate() {
return delegate;
}
@Override
public SortedSet<E> headSet(E toElement) {
return constrainedSortedSet(delegate.headSet(toElement), constraint);
}
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
return constrainedSortedSet(delegate.subSet(fromElement, toElement), constraint);
}
@Override
public SortedSet<E> tailSet(E fromElement) {
return constrainedSortedSet(delegate.tailSet(fromElement), constraint);
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified list, using the specified
* constraint. Any operations that add new elements to the list will call the
* provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* If {@code list} implements {@link RandomAccess}, so will the returned list.
* The returned list is not serializable.
*
* @param list the list to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the list
*/
public static <E> List<E> constrainedList(List<E> list, Constraint<? super E> constraint) {
return (list instanceof RandomAccess) ? new ConstrainedRandomAccessList<E>(list, constraint)
: new ConstrainedList<E>(list, constraint);
}
/** @see Constraints#constrainedList */
@GwtCompatible
private static class ConstrainedList<E> extends ForwardingList<E> {
final List<E> delegate;
final Constraint<? super E> constraint;
ConstrainedList(List<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected List<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public void add(int index, E element) {
constraint.checkElement(element);
delegate.add(index, element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
@Override
public boolean addAll(int index, Collection<? extends E> elements) {
return delegate.addAll(index, checkElements(elements, constraint));
}
@Override
public ListIterator<E> listIterator() {
return constrainedListIterator(delegate.listIterator(), constraint);
}
@Override
public ListIterator<E> listIterator(int index) {
return constrainedListIterator(delegate.listIterator(index), constraint);
}
@Override
public E set(int index, E element) {
constraint.checkElement(element);
return delegate.set(index, element);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return constrainedList(delegate.subList(fromIndex, toIndex), constraint);
}
}
/** @see Constraints#constrainedList */
static class ConstrainedRandomAccessList<E> extends ConstrainedList<E> implements RandomAccess {
ConstrainedRandomAccessList(List<E> delegate, Constraint<? super E> constraint) {
super(delegate, constraint);
}
}
/**
* Returns a constrained view of the specified list iterator, using the
* specified constraint. Any operations that would add new elements to the
* underlying list will be verified by the constraint.
*
* @param listIterator the iterator for which to return a constrained view
* @param constraint the constraint for elements in the list
* @return a constrained view of the specified iterator
*/
private static <E> ListIterator<E> constrainedListIterator(ListIterator<E> listIterator,
Constraint<? super E> constraint) {
return new ConstrainedListIterator<E>(listIterator, constraint);
}
/** @see Constraints#constrainedListIterator */
static class ConstrainedListIterator<E> extends ForwardingListIterator<E> {
private final ListIterator<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedListIterator(ListIterator<E> delegate, Constraint<? super E> constraint) {
this.delegate = delegate;
this.constraint = constraint;
}
@Override
protected ListIterator<E> delegate() {
return delegate;
}
@Override
public void add(E element) {
constraint.checkElement(element);
delegate.add(element);
}
@Override
public void set(E element) {
constraint.checkElement(element);
delegate.set(element);
}
}
static <E> Collection<E> constrainedTypePreservingCollection(Collection<E> collection, Constraint<E> constraint) {
if (collection instanceof SortedSet) {
return constrainedSortedSet((SortedSet<E>) collection, constraint);
} else if (collection instanceof Set) {
return constrainedSet((Set<E>) collection, constraint);
} else if (collection instanceof List) {
return constrainedList((List<E>) collection, constraint);
} else {
return constrainedCollection(collection, constraint);
}
}
/*
* TODO(kevinb): For better performance, avoid making a copy of the elements by
* having addAll() call add() repeatedly instead.
*/
private static <E> Collection<E> checkElements(Collection<E> elements, Constraint<? super E> constraint) {
Collection<E> copy = Lists.newArrayList(elements);
for (E element : copy) {
constraint.checkElement(element);
}
return copy;
}
}

View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A sorted set of contiguous values in a given {@link DiscreteDomain}.
*
* <p>
* <b>Warning:</b> Be extremely careful what you do with conceptually large
* instances (such as
* {@code ContiguousSet.create(Range.greaterThan(0), DiscreteDomain.integers()}).
* Certain operations on such a set can be performed efficiently, but others
* (such as {@link Set#hashCode} or {@link Collections#frequency}) can cause
* major performance problems.
*
* @author Gregory Kick
* @since 10.0
*/
@Beta
@GwtCompatible(emulated = true)
@SuppressWarnings("rawtypes") // allow ungenerified Comparable types
public abstract class ContiguousSet<C extends Comparable> extends ImmutableSortedSet<C> {
/**
* Returns a {@code ContiguousSet} containing the same values in the given
* domain {@linkplain Range#contains contained} by the range.
*
* @throws IllegalArgumentException if neither range nor the domain has a lower
* bound, or if neither has an upper bound
*
* @since 13.0
*/
public static <C extends Comparable> ContiguousSet<C> create(Range<C> range, DiscreteDomain<C> domain) {
checkNotNull(range);
checkNotNull(domain);
Range<C> effectiveRange = range;
try {
if (!range.hasLowerBound()) {
effectiveRange = effectiveRange.intersection(Range.atLeast(domain.minValue()));
}
if (!range.hasUpperBound()) {
effectiveRange = effectiveRange.intersection(Range.atMost(domain.maxValue()));
}
} catch (NoSuchElementException e) {
throw new IllegalArgumentException(e);
}
// Per class spec, we are allowed to throw CCE if necessary
boolean empty = effectiveRange.isEmpty() || Range.compareOrThrow(range.lowerBound.leastValueAbove(domain),
range.upperBound.greatestValueBelow(domain)) > 0;
return empty ? new EmptyContiguousSet<C>(domain) : new RegularContiguousSet<C>(effectiveRange, domain);
}
final DiscreteDomain<C> domain;
ContiguousSet(DiscreteDomain<C> domain) {
super(Ordering.natural());
this.domain = domain;
}
@Override
public ContiguousSet<C> headSet(C toElement) {
return headSetImpl(checkNotNull(toElement), false);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
return headSetImpl(checkNotNull(toElement), inclusive);
}
@Override
public ContiguousSet<C> subSet(C fromElement, C toElement) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, true, toElement, false);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> subSet(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, fromInclusive, toElement, toInclusive);
}
@Override
public ContiguousSet<C> tailSet(C fromElement) {
return tailSetImpl(checkNotNull(fromElement), true);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> tailSet(C fromElement, boolean inclusive) {
return tailSetImpl(checkNotNull(fromElement), inclusive);
}
/*
* These methods perform most headSet, subSet, and tailSet logic, besides
* parameter validation.
*/
/* @Override */ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
/* @Override */ abstract ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
boolean toInclusive);
/* @Override */ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
/**
* Returns the set of values that are contained in both this set and the other.
*
* <p>
* This method should always be used instead of {@link Sets#intersection} for
* {@link ContiguousSet} instances.
*/
public abstract ContiguousSet<C> intersection(ContiguousSet<C> other);
/**
* Returns a range, closed on both ends, whose endpoints are the minimum and
* maximum values contained in this set. This is equivalent to
* {@code range(CLOSED, CLOSED)}.
*
* @throws NoSuchElementException if this set is empty
*/
public abstract Range<C> range();
/**
* Returns the minimal range with the given boundary types for which all values
* in this set are {@linkplain Range#contains(Comparable) contained} within the
* range.
*
* <p>
* Note that this method will return ranges with unbounded endpoints if
* {@link BoundType#OPEN} is requested for a domain minimum or maximum. For
* example, if {@code set} was created from the range
* {@code [1..Integer.MAX_VALUE]} then {@code set.range(CLOSED, OPEN)} must
* return {@code [1..∞)}.
*
* @throws NoSuchElementException if this set is empty
*/
public abstract Range<C> range(BoundType lowerBoundType, BoundType upperBoundType);
/**
* Returns a short-hand representation of the contents such as
* {@code "[1..100]"}.
*/
@Override
public String toString() {
return range().toString();
}
/**
* Not supported. {@code ContiguousSet} instances are constructed with
* {@link #create}. This method exists only to hide {@link ImmutableSet#builder}
* from consumers of {@code
* ContiguousSet}.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #create}.
*/
@Deprecated
public static <E> ImmutableSortedSet.Builder<E> builder() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A mutable value of type {@code int}, for multisets to use in tracking counts
* of values.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class Count implements Serializable {
private int value;
Count(int value) {
this.value = value;
}
public int get() {
return value;
}
public int getAndAdd(int delta) {
int result = value;
value = result + delta;
return result;
}
public int addAndGet(int delta) {
return value += delta;
}
public void set(int newValue) {
value = newValue;
}
public int getAndSet(int newValue) {
int result = value;
value = newValue;
return result;
}
@Override
public int hashCode() {
return value;
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof Count && ((Count) obj).value == value;
}
@Override
public String toString() {
return Integer.toString(value);
}
}

View File

@ -0,0 +1,459 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.primitives.Booleans;
/**
* Implementation detail for the internal structure of {@link Range} instances.
* Represents a unique way of "cutting" a "number line" (actually of instances
* of type {@code C}, not necessarily "numbers") into two sections; this can be
* done below a certain value, above a certain value, below all values or above
* all values. With this object defined in this way, an interval can always be
* represented by a pair of {@code Cut} instances.
*
* @author Kevin Bourrillion
*/
@GwtCompatible
abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializable {
final C endpoint;
Cut(@Nullable C endpoint) {
this.endpoint = endpoint;
}
abstract boolean isLessThan(C value);
abstract BoundType typeAsLowerBound();
abstract BoundType typeAsUpperBound();
abstract Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain);
abstract Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain);
abstract void describeAsLowerBound(StringBuilder sb);
abstract void describeAsUpperBound(StringBuilder sb);
abstract C leastValueAbove(DiscreteDomain<C> domain);
abstract C greatestValueBelow(DiscreteDomain<C> domain);
/*
* The canonical form is a BelowValue cut whenever possible, otherwise
* ABOVE_ALL, or (only in the case of types that are unbounded below) BELOW_ALL.
*/
Cut<C> canonical(DiscreteDomain<C> domain) {
return this;
}
// note: overriden by {BELOW,ABOVE}_ALL
@Override
public int compareTo(Cut<C> that) {
if (that == belowAll()) {
return 1;
}
if (that == aboveAll()) {
return -1;
}
int result = Range.compareOrThrow(endpoint, that.endpoint);
if (result != 0) {
return result;
}
// same value. below comes before above
return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue);
}
C endpoint() {
return endpoint;
}
@SuppressWarnings("unchecked") // catching CCE
@Override
public boolean equals(Object obj) {
if (obj instanceof Cut) {
// It might not really be a Cut<C>, but we'll catch a CCE if it's not
Cut<C> that = (Cut<C>) obj;
try {
int compareResult = compareTo(that);
return compareResult == 0;
} catch (ClassCastException ignored) {
}
}
return false;
}
/*
* The implementation neither produces nor consumes any non-null instance of
* type C, so casting the type parameter is safe.
*/
@SuppressWarnings("unchecked")
static <C extends Comparable> Cut<C> belowAll() {
return (Cut<C>) BelowAll.INSTANCE;
}
private static final long serialVersionUID = 0;
private static final class BelowAll extends Cut<Comparable<?>> {
private static final BelowAll INSTANCE = new BelowAll();
private BelowAll() {
super(null);
}
@Override
Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
@Override
boolean isLessThan(Comparable<?> value) {
return true;
}
@Override
BoundType typeAsLowerBound() {
throw new IllegalStateException();
}
@Override
BoundType typeAsUpperBound() {
throw new AssertionError("this statement should be unreachable");
}
@Override
Cut<Comparable<?>> withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
@Override
Cut<Comparable<?>> withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append("(-\u221e");
}
@Override
void describeAsUpperBound(StringBuilder sb) {
throw new AssertionError();
}
@Override
Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
return domain.minValue();
}
@Override
Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
@Override
Cut<Comparable<?>> canonical(DiscreteDomain<Comparable<?>> domain) {
try {
return Cut.<Comparable<?>>belowValue(domain.minValue());
} catch (NoSuchElementException e) {
return this;
}
}
@Override
public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : -1;
}
@Override
public String toString() {
return "-\u221e";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}
/*
* The implementation neither produces nor consumes any non-null instance of
* type C, so casting the type parameter is safe.
*/
@SuppressWarnings("unchecked")
static <C extends Comparable> Cut<C> aboveAll() {
return (Cut<C>) AboveAll.INSTANCE;
}
private static final class AboveAll extends Cut<Comparable<?>> {
private static final AboveAll INSTANCE = new AboveAll();
private AboveAll() {
super(null);
}
@Override
Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
@Override
boolean isLessThan(Comparable<?> value) {
return false;
}
@Override
BoundType typeAsLowerBound() {
throw new AssertionError("this statement should be unreachable");
}
@Override
BoundType typeAsUpperBound() {
throw new IllegalStateException();
}
@Override
Cut<Comparable<?>> withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
@Override
Cut<Comparable<?>> withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
@Override
void describeAsLowerBound(StringBuilder sb) {
throw new AssertionError();
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append("+\u221e)");
}
@Override
Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
@Override
Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
return domain.maxValue();
}
@Override
public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : 1;
}
@Override
public String toString() {
return "+\u221e";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}
static <C extends Comparable> Cut<C> belowValue(C endpoint) {
return new BelowValue<C>(endpoint);
}
private static final class BelowValue<C extends Comparable> extends Cut<C> {
BelowValue(C endpoint) {
super(checkNotNull(endpoint));
}
@Override
boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) <= 0;
}
@Override
BoundType typeAsLowerBound() {
return BoundType.CLOSED;
}
@Override
BoundType typeAsUpperBound() {
return BoundType.OPEN;
}
@Override
Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
return this;
case OPEN:
@Nullable
C previous = domain.previous(endpoint);
return (previous == null) ? Cut.<C>belowAll() : new AboveValue<C>(previous);
default:
throw new AssertionError();
}
}
@Override
Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
@Nullable
C previous = domain.previous(endpoint);
return (previous == null) ? Cut.<C>aboveAll() : new AboveValue<C>(previous);
case OPEN:
return this;
default:
throw new AssertionError();
}
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append('[').append(endpoint);
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(')');
}
@Override
C leastValueAbove(DiscreteDomain<C> domain) {
return endpoint;
}
@Override
C greatestValueBelow(DiscreteDomain<C> domain) {
return domain.previous(endpoint);
}
@Override
public int hashCode() {
return endpoint.hashCode();
}
@Override
public String toString() {
return "\\" + endpoint + "/";
}
private static final long serialVersionUID = 0;
}
static <C extends Comparable> Cut<C> aboveValue(C endpoint) {
return new AboveValue<C>(endpoint);
}
private static final class AboveValue<C extends Comparable> extends Cut<C> {
AboveValue(C endpoint) {
super(checkNotNull(endpoint));
}
@Override
boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) < 0;
}
@Override
BoundType typeAsLowerBound() {
return BoundType.OPEN;
}
@Override
BoundType typeAsUpperBound() {
return BoundType.CLOSED;
}
@Override
Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
return this;
case CLOSED:
@Nullable
C next = domain.next(endpoint);
return (next == null) ? Cut.<C>belowAll() : belowValue(next);
default:
throw new AssertionError();
}
}
@Override
Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
@Nullable
C next = domain.next(endpoint);
return (next == null) ? Cut.<C>aboveAll() : belowValue(next);
case CLOSED:
return this;
default:
throw new AssertionError();
}
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append('(').append(endpoint);
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(']');
}
@Override
C leastValueAbove(DiscreteDomain<C> domain) {
return domain.next(endpoint);
}
@Override
C greatestValueBelow(DiscreteDomain<C> domain) {
return endpoint;
}
@Override
Cut<C> canonical(DiscreteDomain<C> domain) {
C next = leastValueAbove(domain);
return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
}
@Override
public int hashCode() {
return ~endpoint.hashCode();
}
@Override
public String toString() {
return "/" + endpoint + "\\";
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,278 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.google.common.annotations.GwtCompatible;
/**
* A {@code RegularImmutableTable} optimized for dense data.
*/
@GwtCompatible
@Immutable
final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final ImmutableMap<R, Map<C, V>> rowMap;
private final ImmutableMap<C, Map<R, V>> columnMap;
private final int[] rowCounts;
private final int[] columnCounts;
private final V[][] values;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
private static <E> ImmutableMap<E, Integer> makeIndex(ImmutableSet<E> set) {
ImmutableMap.Builder<E, Integer> indexBuilder = ImmutableMap.builder();
int i = 0;
for (E key : set) {
indexBuilder.put(key, i);
i++;
}
return indexBuilder.build();
}
DenseImmutableTable(ImmutableList<Cell<R, C, V>> cellList, ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
@SuppressWarnings("unchecked")
V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
this.values = array;
this.rowKeyToIndex = makeIndex(rowSpace);
this.columnKeyToIndex = makeIndex(columnSpace);
rowCounts = new int[rowKeyToIndex.size()];
columnCounts = new int[columnKeyToIndex.size()];
int[] iterationOrderRow = new int[cellList.size()];
int[] iterationOrderColumn = new int[cellList.size()];
for (int i = 0; i < cellList.size(); i++) {
Cell<R, C, V> cell = cellList.get(i);
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
int rowIndex = rowKeyToIndex.get(rowKey);
int columnIndex = columnKeyToIndex.get(columnKey);
V existingValue = values[rowIndex][columnIndex];
checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey);
values[rowIndex][columnIndex] = cell.getValue();
rowCounts[rowIndex]++;
columnCounts[columnIndex]++;
iterationOrderRow[i] = rowIndex;
iterationOrderColumn[i] = columnIndex;
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
this.rowMap = new RowMap();
this.columnMap = new ColumnMap();
}
/**
* An immutable map implementation backed by an indexed nullable array.
*/
private abstract static class ImmutableArrayMap<K, V> extends ImmutableMap<K, V> {
private final int size;
ImmutableArrayMap(int size) {
this.size = size;
}
abstract ImmutableMap<K, Integer> keyToIndex();
// True if getValue never returns null.
private boolean isFull() {
return size == keyToIndex().size();
}
K getKey(int index) {
return keyToIndex().keySet().asList().get(index);
}
@Nullable
abstract V getValue(int keyIndex);
@Override
ImmutableSet<K> createKeySet() {
return isFull() ? keyToIndex().keySet() : super.createKeySet();
}
@Override
public int size() {
return size;
}
@Override
public V get(@Nullable Object key) {
Integer keyIndex = keyToIndex().get(key);
return (keyIndex == null) ? null : getValue(keyIndex);
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
return new ImmutableMapEntrySet<K, V>() {
@Override
ImmutableMap<K, V> map() {
return ImmutableArrayMap.this;
}
@Override
public UnmodifiableIterator<Entry<K, V>> iterator() {
return new AbstractIterator<Entry<K, V>>() {
private int index = -1;
private final int maxIndex = keyToIndex().size();
@Override
protected Entry<K, V> computeNext() {
for (index++; index < maxIndex; index++) {
V value = getValue(index);
if (value != null) {
return Maps.immutableEntry(getKey(index), value);
}
}
return endOfData();
}
};
}
};
}
}
private final class Row extends ImmutableArrayMap<C, V> {
private final int rowIndex;
Row(int rowIndex) {
super(rowCounts[rowIndex]);
this.rowIndex = rowIndex;
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[rowIndex][keyIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class Column extends ImmutableArrayMap<R, V> {
private final int columnIndex;
Column(int columnIndex) {
super(columnCounts[columnIndex]);
this.columnIndex = columnIndex;
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[keyIndex][columnIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class RowMap extends ImmutableArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowCounts.length);
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
Map<C, V> getValue(int keyIndex) {
return new Row(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
private final class ColumnMap extends ImmutableArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnCounts.length);
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
Map<R, V> getValue(int keyIndex) {
return new Column(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
@Override
public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
@Override
public ImmutableMap<R, Map<C, V>> rowMap() {
return rowMap;
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return ((rowIndex == null) || (columnIndex == null)) ? null : values[rowIndex][columnIndex];
}
@Override
public int size() {
return iterationOrderRow.length;
}
@Override
Cell<R, C, V> getCell(int index) {
int rowIndex = iterationOrderRow[index];
int columnIndex = iterationOrderColumn[index];
R rowKey = rowKeySet().asList().get(rowIndex);
C columnKey = columnKeySet().asList().get(columnIndex);
V value = values[rowIndex][columnIndex];
return cellOf(rowKey, columnKey, value);
}
@Override
V getValue(int index) {
return values[iterationOrderRow[index]][iterationOrderColumn[index]];
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import javax.annotation.Nullable;
/**
* A descending wrapper around an {@code ImmutableSortedMultiset}
*
* @author Louis Wasserman
*/
@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class DescendingImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
private final transient ImmutableSortedMultiset<E> forward;
DescendingImmutableSortedMultiset(ImmutableSortedMultiset<E> forward) {
this.forward = forward;
}
@Override
public int count(@Nullable Object element) {
return forward.count(element);
}
@Override
public Entry<E> firstEntry() {
return forward.lastEntry();
}
@Override
public Entry<E> lastEntry() {
return forward.firstEntry();
}
@Override
public int size() {
return forward.size();
}
@Override
public ImmutableSortedSet<E> elementSet() {
return forward.elementSet().descendingSet();
}
@Override
Entry<E> getEntry(int index) {
return forward.entrySet().asList().reverse().get(index);
}
@Override
public ImmutableSortedMultiset<E> descendingMultiset() {
return forward;
}
@Override
public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
return forward.tailMultiset(upperBound, boundType).descendingMultiset();
}
@Override
public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
return forward.headMultiset(lowerBound, boundType).descendingMultiset();
}
@Override
boolean isPartialView() {
return forward.isPartialView();
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtIncompatible;
/**
* Skeletal implementation of {@link ImmutableSortedSet#descendingSet()}.
*
* @author Louis Wasserman
*/
class DescendingImmutableSortedSet<E> extends ImmutableSortedSet<E> {
private final ImmutableSortedSet<E> forward;
DescendingImmutableSortedSet(ImmutableSortedSet<E> forward) {
super(Ordering.from(forward.comparator()).reverse());
this.forward = forward;
}
@Override
public int size() {
return forward.size();
}
@Override
public UnmodifiableIterator<E> iterator() {
return forward.descendingIterator();
}
@Override
ImmutableSortedSet<E> headSetImpl(E toElement, boolean inclusive) {
return forward.tailSet(toElement, inclusive).descendingSet();
}
@Override
ImmutableSortedSet<E> subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet();
}
@Override
ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive) {
return forward.headSet(fromElement, inclusive).descendingSet();
}
@Override
@GwtIncompatible("NavigableSet")
public ImmutableSortedSet<E> descendingSet() {
return forward;
}
@Override
@GwtIncompatible("NavigableSet")
public UnmodifiableIterator<E> descendingIterator() {
return forward.iterator();
}
@Override
@GwtIncompatible("NavigableSet")
ImmutableSortedSet<E> createDescendingSet() {
throw new AssertionError("should never be called");
}
@Override
public E lower(E element) {
return forward.higher(element);
}
@Override
public E floor(E element) {
return forward.ceiling(element);
}
@Override
public E ceiling(E element) {
return forward.floor(element);
}
@Override
public E higher(E element) {
return forward.lower(element);
}
@Override
int indexOf(@Nullable Object target) {
int index = forward.indexOf(target);
if (index == -1) {
return index;
} else {
return size() - 1 - index;
}
}
@Override
boolean isPartialView() {
return forward.isPartialView();
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import com.google.common.annotations.GwtCompatible;
/**
* A skeleton implementation of a descending multiset. Only needs
* {@code forwardMultiset()} and {@code entryIterator()}.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
abstract class DescendingMultiset<E> extends ForwardingMultiset<E> implements SortedMultiset<E> {
abstract SortedMultiset<E> forwardMultiset();
private transient Comparator<? super E> comparator;
@Override
public Comparator<? super E> comparator() {
Comparator<? super E> result = comparator;
if (result == null) {
return comparator = Ordering.from(forwardMultiset().comparator()).<E>reverse();
}
return result;
}
private transient NavigableSet<E> elementSet;
@Override
public NavigableSet<E> elementSet() {
NavigableSet<E> result = elementSet;
if (result == null) {
return elementSet = new SortedMultisets.NavigableElementSet<E>(this);
}
return result;
}
@Override
public Entry<E> pollFirstEntry() {
return forwardMultiset().pollLastEntry();
}
@Override
public Entry<E> pollLastEntry() {
return forwardMultiset().pollFirstEntry();
}
@Override
public SortedMultiset<E> headMultiset(E toElement, BoundType boundType) {
return forwardMultiset().tailMultiset(toElement, boundType).descendingMultiset();
}
@Override
public SortedMultiset<E> subMultiset(E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) {
return forwardMultiset().subMultiset(toElement, toBoundType, fromElement, fromBoundType).descendingMultiset();
}
@Override
public SortedMultiset<E> tailMultiset(E fromElement, BoundType boundType) {
return forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset();
}
@Override
protected Multiset<E> delegate() {
return forwardMultiset();
}
@Override
public SortedMultiset<E> descendingMultiset() {
return forwardMultiset();
}
@Override
public Entry<E> firstEntry() {
return forwardMultiset().lastEntry();
}
@Override
public Entry<E> lastEntry() {
return forwardMultiset().firstEntry();
}
abstract Iterator<Entry<E>> entryIterator();
private transient Set<Entry<E>> entrySet;
@Override
public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
Set<Entry<E>> createEntrySet() {
return new Multisets.EntrySet<E>() {
@Override
Multiset<E> multiset() {
return DescendingMultiset.this;
}
@Override
public Iterator<Entry<E>> iterator() {
return entryIterator();
}
@Override
public int size() {
return forwardMultiset().entrySet().size();
}
};
}
@Override
public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public String toString() {
return entrySet().toString();
}
}

View File

@ -0,0 +1,275 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.NoSuchElementException;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A descriptor for a <i>discrete</i> {@code Comparable} domain such as all
* {@link Integer} instances. A discrete domain is one that supports the three
* basic operations: {@link #next}, {@link #previous} and {@link #distance},
* according to their specifications. The methods {@link #minValue} and
* {@link #maxValue} should also be overridden for bounded types.
*
* <p>
* A discrete domain always represents the <i>entire</i> set of values of its
* type; it cannot represent partial domains such as "prime integers" or
* "strings of length 5."
*
* <p>
* See the Guava User Guide section on <a href=
* "http://code.google.com/p/guava-libraries/wiki/RangesExplained#Discrete_Domains">
* {@code DiscreteDomain}</a>.
*
* @author Kevin Bourrillion
* @since 10.0
*/
@GwtCompatible
@Beta
public abstract class DiscreteDomain<C extends Comparable> {
/**
* Returns the discrete domain for values of type {@code Integer}.
*
* @since 14.0 (since 10.0 as {@code DiscreteDomains.integers()})
*/
public static DiscreteDomain<Integer> integers() {
return IntegerDomain.INSTANCE;
}
private static final class IntegerDomain extends DiscreteDomain<Integer> implements Serializable {
private static final IntegerDomain INSTANCE = new IntegerDomain();
@Override
public Integer next(Integer value) {
int i = value;
return (i == Integer.MAX_VALUE) ? null : i + 1;
}
@Override
public Integer previous(Integer value) {
int i = value;
return (i == Integer.MIN_VALUE) ? null : i - 1;
}
@Override
public long distance(Integer start, Integer end) {
return (long) end - start;
}
@Override
public Integer minValue() {
return Integer.MIN_VALUE;
}
@Override
public Integer maxValue() {
return Integer.MAX_VALUE;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.integers()";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the discrete domain for values of type {@code Long}.
*
* @since 14.0 (since 10.0 as {@code DiscreteDomains.longs()})
*/
public static DiscreteDomain<Long> longs() {
return LongDomain.INSTANCE;
}
private static final class LongDomain extends DiscreteDomain<Long> implements Serializable {
private static final LongDomain INSTANCE = new LongDomain();
@Override
public Long next(Long value) {
long l = value;
return (l == Long.MAX_VALUE) ? null : l + 1;
}
@Override
public Long previous(Long value) {
long l = value;
return (l == Long.MIN_VALUE) ? null : l - 1;
}
@Override
public long distance(Long start, Long end) {
long result = end - start;
if (end > start && result < 0) { // overflow
return Long.MAX_VALUE;
}
if (end < start && result > 0) { // underflow
return Long.MIN_VALUE;
}
return result;
}
@Override
public Long minValue() {
return Long.MIN_VALUE;
}
@Override
public Long maxValue() {
return Long.MAX_VALUE;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.longs()";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the discrete domain for values of type {@code BigInteger}.
*
* @since 15.0
*/
public static DiscreteDomain<BigInteger> bigIntegers() {
return BigIntegerDomain.INSTANCE;
}
private static final class BigIntegerDomain extends DiscreteDomain<BigInteger> implements Serializable {
private static final BigIntegerDomain INSTANCE = new BigIntegerDomain();
private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
@Override
public BigInteger next(BigInteger value) {
return value.add(BigInteger.ONE);
}
@Override
public BigInteger previous(BigInteger value) {
return value.subtract(BigInteger.ONE);
}
@Override
public long distance(BigInteger start, BigInteger end) {
return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue();
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.bigIntegers()";
}
private static final long serialVersionUID = 0;
}
/** Constructor for use by subclasses. */
protected DiscreteDomain() {
}
/**
* Returns the unique least value of type {@code C} that is greater than
* {@code value}, or {@code null} if none exists. Inverse operation to
* {@link #previous}.
*
* @param value any value of type {@code C}
* @return the least value greater than {@code value}, or {@code null} if
* {@code value} is {@code maxValue()}
*/
public abstract C next(C value);
/**
* Returns the unique greatest value of type {@code C} that is less than
* {@code value}, or {@code null} if none exists. Inverse operation to
* {@link #next}.
*
* @param value any value of type {@code C}
* @return the greatest value less than {@code value}, or {@code null} if
* {@code value} is {@code minValue()}
*/
public abstract C previous(C value);
/**
* Returns a signed value indicating how many nested invocations of
* {@link #next} (if positive) or {@link #previous} (if negative) are needed to
* reach {@code end} starting from {@code start}. For example, if {@code end =
* next(next(next(start)))}, then {@code distance(start, end) == 3} and {@code
* distance(end, start) == -3}. As well, {@code distance(a, a)} is always zero.
*
* <p>
* Note that this function is necessarily well-defined for any discrete type.
*
* @return the distance as described above, or {@link Long#MIN_VALUE} or
* {@link Long#MAX_VALUE} if the distance is too small or too large,
* respectively.
*/
public abstract long distance(C start, C end);
/**
* Returns the minimum value of type {@code C}, if it has one. The minimum value
* is the unique value for which {@link Comparable#compareTo(Object)} never
* returns a positive value for any input of type {@code C}.
*
* <p>
* The default implementation throws {@code NoSuchElementException}.
*
* @return the minimum value of type {@code C}; never null
* @throws NoSuchElementException if the type has no (practical) minimum value;
* for example, {@link java.math.BigInteger}
*/
public C minValue() {
throw new NoSuchElementException();
}
/**
* Returns the maximum value of type {@code C}, if it has one. The maximum value
* is the unique value for which {@link Comparable#compareTo(Object)} never
* returns a negative value for any input of type {@code C}.
*
* <p>
* The default implementation throws {@code NoSuchElementException}.
*
* @return the maximum value of type {@code C}; never null
* @throws NoSuchElementException if the type has no (practical) maximum value;
* for example, {@link java.math.BigInteger}
*/
public C maxValue() {
throw new NoSuchElementException();
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* An empty contiguous set.
*
* @author Gregory Kick
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("unchecked") // allow ungenerified Comparable types
final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
EmptyContiguousSet(DiscreteDomain<C> domain) {
super(domain);
}
@Override
public C first() {
throw new NoSuchElementException();
}
@Override
public C last() {
throw new NoSuchElementException();
}
@Override
public int size() {
return 0;
}
@Override
public ContiguousSet<C> intersection(ContiguousSet<C> other) {
return this;
}
@Override
public Range<C> range() {
throw new NoSuchElementException();
}
@Override
public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
throw new NoSuchElementException();
}
@Override
ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return this;
}
@Override
ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
return this;
}
@Override
ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
return this;
}
@GwtIncompatible("not used by GWT emulation")
@Override
int indexOf(Object target) {
return -1;
}
@Override
public UnmodifiableIterator<C> iterator() {
return Iterators.emptyIterator();
}
@GwtIncompatible("NavigableSet")
@Override
public UnmodifiableIterator<C> descendingIterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ImmutableList<C> asList() {
return ImmutableList.of();
}
@Override
public String toString() {
return "[]";
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public int hashCode() {
return 0;
}
@GwtIncompatible("serialization")
private static final class SerializedForm<C extends Comparable> implements Serializable {
private final DiscreteDomain<C> domain;
private SerializedForm(DiscreteDomain<C> domain) {
this.domain = domain;
}
private Object readResolve() {
return new EmptyContiguousSet<C>(domain);
}
private static final long serialVersionUID = 0;
}
@GwtIncompatible("serialization")
@Override
Object writeReplace() {
return new SerializedForm<C>(domain);
}
@GwtIncompatible("NavigableSet")
ImmutableSortedSet<C> createDescendingSet() {
return new EmptyImmutableSortedSet<C>(Ordering.natural().reverse());
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Bimap with no mappings.
*
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
private EmptyImmutableBiMap() {
}
@Override
public ImmutableBiMap<Object, Object> inverse() {
return this;
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public Object get(@Nullable Object key) {
return null;
}
@Override
public ImmutableSet<Entry<Object, Object>> entrySet() {
return ImmutableSet.of();
}
@Override
ImmutableSet<Entry<Object, Object>> createEntrySet() {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSetMultimap<Object, Object> asMultimap() {
return ImmutableSetMultimap.of();
}
@Override
public ImmutableSet<Object> keySet() {
return ImmutableSet.of();
}
@Override
boolean isPartialView() {
return false;
}
Object readResolve() {
return INSTANCE; // preserve singleton property
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of {@link ImmutableListMultimap} with no entries.
*
* @author Jared Levy
*/
@GwtCompatible(serializable = true)
class EmptyImmutableListMultimap extends ImmutableListMultimap<Object, Object> {
static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap();
private EmptyImmutableListMultimap() {
super(ImmutableMap.<Object, ImmutableList<Object>>of(), 0);
}
private Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An empty immutable set.
*
* @author Kevin Bourrillion
*/
@GwtCompatible(serializable = true, emulated = true)
final class EmptyImmutableSet extends ImmutableSet<Object> {
static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
private EmptyImmutableSet() {
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean contains(@Nullable Object target) {
return false;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public UnmodifiableIterator<Object> iterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public ImmutableList<Object> asList() {
return ImmutableList.of();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public final int hashCode() {
return 0;
}
@Override
boolean isHashCodeFast() {
return true;
}
@Override
public String toString() {
return "[]";
}
Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of {@link ImmutableListMultimap} with no entries.
*
* @author Mike Ward
*/
@GwtCompatible(serializable = true)
class EmptyImmutableSetMultimap extends ImmutableSetMultimap<Object, Object> {
static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap();
private EmptyImmutableSetMultimap() {
super(ImmutableMap.<Object, ImmutableSet<Object>>of(), 0, null);
}
private Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An empty immutable sorted map.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class EmptyImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
private final transient ImmutableSortedSet<K> keySet;
EmptyImmutableSortedMap(Comparator<? super K> comparator) {
this.keySet = ImmutableSortedSet.emptySet(comparator);
}
EmptyImmutableSortedMap(Comparator<? super K> comparator, ImmutableSortedMap<K, V> descendingMap) {
super(descendingMap);
this.keySet = ImmutableSortedSet.emptySet(comparator);
}
@Override
public V get(@Nullable Object key) {
return null;
}
@Override
public ImmutableSortedSet<K> keySet() {
return keySet;
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ImmutableCollection<V> values() {
return ImmutableList.of();
}
@Override
public String toString() {
return "{}";
}
@Override
boolean isPartialView() {
return false;
}
@Override
public ImmutableSet<Entry<K, V>> entrySet() {
return ImmutableSet.of();
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSetMultimap<K, V> asMultimap() {
return ImmutableSetMultimap.of();
}
@Override
public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
checkNotNull(toKey);
return this;
}
@Override
public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
checkNotNull(fromKey);
return this;
}
@Override
ImmutableSortedMap<K, V> createDescendingMap() {
return new EmptyImmutableSortedMap<K, V>(Ordering.from(comparator()).reverse(), this);
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Comparator;
import javax.annotation.Nullable;
/**
* An empty immutable sorted multiset.
*
* @author Louis Wasserman
*/
@SuppressWarnings("serial") // Uses writeReplace, not default serialization
final class EmptyImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
private final ImmutableSortedSet<E> elementSet;
EmptyImmutableSortedMultiset(Comparator<? super E> comparator) {
this.elementSet = ImmutableSortedSet.emptySet(comparator);
}
@Override
public Entry<E> firstEntry() {
return null;
}
@Override
public Entry<E> lastEntry() {
return null;
}
@Override
public int count(@Nullable Object element) {
return 0;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public int size() {
return 0;
}
@Override
public ImmutableSortedSet<E> elementSet() {
return elementSet;
}
@Override
Entry<E> getEntry(int index) {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
checkNotNull(upperBound);
checkNotNull(boundType);
return this;
}
@Override
public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
checkNotNull(lowerBound);
checkNotNull(boundType);
return this;
}
@Override
public UnmodifiableIterator<E> iterator() {
return Iterators.emptyIterator();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Multiset) {
Multiset<?> other = (Multiset<?>) object;
return other.isEmpty();
}
return false;
}
@Override
boolean isPartialView() {
return false;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public ImmutableList<E> asList() {
return ImmutableList.of();
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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.google.common.collect;
import java.util.Collection;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* An empty immutable sorted set.
*
* @author Jared Levy
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
EmptyImmutableSortedSet(Comparator<? super E> comparator) {
super(comparator);
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean contains(@Nullable Object target) {
return false;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public UnmodifiableIterator<E> iterator() {
return Iterators.emptyIterator();
}
@GwtIncompatible("NavigableSet")
@Override
public UnmodifiableIterator<E> descendingIterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
public ImmutableList<E> asList() {
return ImmutableList.of();
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return "[]";
}
@Override
public E first() {
throw new NoSuchElementException();
}
@Override
public E last() {
throw new NoSuchElementException();
}
@Override
ImmutableSortedSet<E> headSetImpl(E toElement, boolean inclusive) {
return this;
}
@Override
ImmutableSortedSet<E> subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return this;
}
@Override
ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive) {
return this;
}
@Override
int indexOf(@Nullable Object target) {
return -1;
}
@Override
ImmutableSortedSet<E> createDescendingSet() {
return new EmptyImmutableSortedSet<E>(Ordering.from(comparator).reverse());
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A {@code BiMap} backed by two {@code EnumMap} instances. Null keys and values
* are not permitted. An {@code EnumBiMap} and its inverse are both
* serializable.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
private transient Class<V> valueType;
/**
* Returns a new, empty {@code EnumBiMap} using the specified key and value
* types.
*
* @param keyType the key type
* @param valueType the value type
*/
public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Class<K> keyType, Class<V> valueType) {
return new EnumBiMap<K, V>(keyType, valueType);
}
/**
* Returns a new bimap with the same mappings as the specified map. If the
* specified map is an {@code EnumBiMap}, the new bimap has the same types as
* the provided map. Otherwise, the specified map must contain at least one
* mapping, in order to determine the key and value types.
*
* @param map the map whose mappings are to be placed in this map
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} instance
* and contains no mappings
*/
public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Map<K, V> map) {
EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map));
bimap.putAll(map);
return bimap;
}
private EnumBiMap(Class<K> keyType, Class<V> valueType) {
super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)), WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
this.keyType = keyType;
this.valueType = valueType;
}
static <K extends Enum<K>> Class<K> inferKeyType(Map<K, ?> map) {
if (map instanceof EnumBiMap) {
return ((EnumBiMap<K, ?>) map).keyType();
}
if (map instanceof EnumHashBiMap) {
return ((EnumHashBiMap<K, ?>) map).keyType();
}
checkArgument(!map.isEmpty());
return map.keySet().iterator().next().getDeclaringClass();
}
private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
if (map instanceof EnumBiMap) {
return ((EnumBiMap<?, V>) map).valueType;
}
checkArgument(!map.isEmpty());
return map.values().iterator().next().getDeclaringClass();
}
/** Returns the associated key type. */
public Class<K> keyType() {
return keyType;
}
/** Returns the associated value type. */
public Class<V> valueType() {
return valueType;
}
@Override
K checkKey(K key) {
return checkNotNull(key);
}
@Override
V checkValue(V value) {
return checkNotNull(value);
}
/**
* @serialData the key class, value class, number of entries, first key, first
* value, second key, second value, and so on.
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(keyType);
stream.writeObject(valueType);
Serialization.writeMap(this, stream);
}
@SuppressWarnings("unchecked") // reading fields populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
valueType = (Class<V>) stream.readObject();
setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
Serialization.populateMap(this, stream);
}
@GwtIncompatible("not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A {@code BiMap} backed by an {@code EnumMap} instance for keys-to-values, and
* a {@code HashMap} instance for values-to-keys. Null keys are not permitted,
* but null values are. An {@code EnumHashBiMap} and its inverse are both
* serializable.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
/**
* Returns a new, empty {@code EnumHashBiMap} using the specified key type.
*
* @param keyType the key type
*/
public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
return new EnumHashBiMap<K, V>(keyType);
}
/**
* Constructs a new bimap with the same mappings as the specified map. If the
* specified map is an {@code EnumHashBiMap} or an {@link EnumBiMap}, the new
* bimap has the same key type as the input bimap. Otherwise, the specified map
* must contain at least one mapping, in order to determine the key type.
*
* @param map the map whose mappings are to be placed in this map
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an
* {@code EnumHashBiMap} instance and contains
* no mappings
*/
public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Map<K, ? extends V> map) {
EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
bimap.putAll(map);
return bimap;
}
private EnumHashBiMap(Class<K> keyType) {
super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
this.keyType = keyType;
}
// Overriding these 3 methods to show that values may be null (but not keys)
@Override
K checkKey(K key) {
return checkNotNull(key);
}
@Override
public V put(K key, @Nullable V value) {
return super.put(key, value);
}
@Override
public V forcePut(K key, @Nullable V value) {
return super.forcePut(key, value);
}
/** Returns the associated key type. */
public Class<K> keyType() {
return keyType;
}
/**
* @serialData the key class, number of entries, first key, first value, second
* key, second value, and so on.
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(keyType);
Serialization.writeMap(this, stream);
}
@SuppressWarnings("unchecked") // reading field populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
Serialization.populateMap(this, stream);
}
@GwtIncompatible("only needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.Iterator;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Multiset implementation backed by an {@link EnumMap}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
* {@code Multiset}</a>.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
/** Creates an empty {@code EnumMultiset}. */
public static <E extends Enum<E>> EnumMultiset<E> create(Class<E> type) {
return new EnumMultiset<E>(type);
}
/**
* Creates a new {@code EnumMultiset} containing the specified elements.
*
* <p>
* This implementation is highly efficient when {@code elements} is itself a
* {@link Multiset}.
*
* @param elements the elements that the multiset should contain
* @throws IllegalArgumentException if {@code elements} is empty
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements) {
Iterator<E> iterator = elements.iterator();
checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable");
EnumMultiset<E> multiset = new EnumMultiset<E>(iterator.next().getDeclaringClass());
Iterables.addAll(multiset, elements);
return multiset;
}
/**
* Returns a new {@code EnumMultiset} instance containing the given elements.
* Unlike {@link EnumMultiset#create(Iterable)}, this method does not produce an
* exception on an empty iterable.
*
* @since 14.0
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements, Class<E> type) {
EnumMultiset<E> result = create(type);
Iterables.addAll(result, elements);
return result;
}
private transient Class<E> type;
/** Creates an empty {@code EnumMultiset}. */
private EnumMultiset(Class<E> type) {
super(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
this.type = type;
}
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(type);
Serialization.writeMultiset(this, stream);
}
/**
* @serialData the {@code Class<E>} for the enum type, the number of distinct
* elements, the first element, its count, the second element, its
* count, and so on
*/
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
@SuppressWarnings("unchecked") // reading data stored by writeObject
Class<E> localType = (Class<E>) stream.readObject();
type = localType;
setBackingMap(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
Serialization.populateMultiset(this, stream);
}
@GwtIncompatible("Not needed in emulated source")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Queue;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* A non-blocking queue which automatically evicts elements from the head of the
* queue when attempting to add new elements onto the queue and it is full.
*
* <p>
* An evicting queue must be configured with a maximum size. Each time an
* element is added to a full queue, the queue automatically removes its head
* element. This is different from conventional bounded queues, which either
* block or reject new elements when full.
*
* <p>
* This class is not thread-safe, and does not accept null elements.
*
* @author Kurt Alfred Kluever
* @since 15.0
*/
@Beta
@GwtIncompatible("java.util.ArrayDeque")
public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serializable {
private final Queue<E> delegate;
@VisibleForTesting
final int maxSize;
private EvictingQueue(int maxSize) {
checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", maxSize);
this.delegate = new ArrayDeque<E>(maxSize);
this.maxSize = maxSize;
}
/**
* Creates and returns a new evicting queue that will hold up to {@code maxSize}
* elements.
*
* <p>
* When {@code maxSize} is zero, elements will be evicted immediately after
* being added to the queue.
*/
public static <E> EvictingQueue<E> create(int maxSize) {
return new EvictingQueue<E>(maxSize);
}
/**
* Returns the number of additional elements that this queue can accept without
* evicting; zero if the queue is currently full.
*
* @since 16.0
*/
public int remainingCapacity() {
return maxSize - size();
}
@Override
protected Queue<E> delegate() {
return delegate;
}
/**
* Adds the given element to this queue. If the queue is currently full, the
* element at the head of the queue is evicted to make room.
*
* @return {@code true} always
*/
@Override
public boolean offer(E e) {
return add(e);
}
/**
* Adds the given element to this queue. If the queue is currently full, the
* element at the head of the queue is evicted to make room.
*
* @return {@code true} always
*/
@Override
public boolean add(E e) {
checkNotNull(e); // check before removing
if (maxSize == 0) {
return true;
}
if (size() == maxSize) {
delegate.remove();
}
delegate.add(e);
return true;
}
@Override
public boolean addAll(Collection<? extends E> collection) {
return standardAddAll(collection);
}
@Override
public boolean contains(Object object) {
return delegate().contains(checkNotNull(object));
}
@Override
public boolean remove(Object object) {
return delegate().remove(checkNotNull(object));
}
// TODO(user): Do we want to checkNotNull each element in containsAll,
// removeAll, and retainAll?
private static final long serialVersionUID = 0L;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.google.common.collect;
import java.io.Serializable;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/** An ordering that compares objects according to a given order. */
@GwtCompatible(serializable = true)
final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableMap<T, Integer> rankMap;
ExplicitOrdering(List<T> valuesInOrder) {
this(buildRankMap(valuesInOrder));
}
ExplicitOrdering(ImmutableMap<T, Integer> rankMap) {
this.rankMap = rankMap;
}
@Override
public int compare(T left, T right) {
return rank(left) - rank(right); // safe because both are nonnegative
}
private int rank(T value) {
Integer rank = rankMap.get(value);
if (rank == null) {
throw new IncomparableValueException(value);
}
return rank;
}
private static <T> ImmutableMap<T, Integer> buildRankMap(List<T> valuesInOrder) {
ImmutableMap.Builder<T, Integer> builder = ImmutableMap.builder();
int rank = 0;
for (T value : valuesInOrder) {
builder.put(value, rank++);
}
return builder.build();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ExplicitOrdering) {
ExplicitOrdering<?> that = (ExplicitOrdering<?>) object;
return this.rankMap.equals(that.rankMap);
}
return false;
}
@Override
public int hashCode() {
return rankMap.hashCode();
}
@Override
public String toString() {
return "Ordering.explicit(" + rankMap.keySet() + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,393 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps.ImprovedAbstractMap;
/**
* Implementation of {@link Multimaps#filterEntries(Multimap, Predicate)}.
*
* @author Jared Levy
* @author Louis Wasserman
*/
@GwtCompatible
class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements FilteredMultimap<K, V> {
final Multimap<K, V> unfiltered;
final Predicate<? super Entry<K, V>> predicate;
FilteredEntryMultimap(Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
this.unfiltered = checkNotNull(unfiltered);
this.predicate = checkNotNull(predicate);
}
@Override
public Multimap<K, V> unfiltered() {
return unfiltered;
}
@Override
public Predicate<? super Entry<K, V>> entryPredicate() {
return predicate;
}
@Override
public int size() {
return entries().size();
}
private boolean satisfies(K key, V value) {
return predicate.apply(Maps.immutableEntry(key, value));
}
final class ValuePredicate implements Predicate<V> {
private final K key;
ValuePredicate(K key) {
this.key = key;
}
@Override
public boolean apply(@Nullable V value) {
return satisfies(key, value);
}
}
static <E> Collection<E> filterCollection(Collection<E> collection, Predicate<? super E> predicate) {
if (collection instanceof Set) {
return Sets.filter((Set<E>) collection, predicate);
} else {
return Collections2.filter(collection, predicate);
}
}
@Override
public boolean containsKey(@Nullable Object key) {
return asMap().get(key) != null;
}
@Override
public Collection<V> removeAll(@Nullable Object key) {
return Objects.firstNonNull(asMap().remove(key), unmodifiableEmptyCollection());
}
Collection<V> unmodifiableEmptyCollection() {
// These return false, rather than throwing a UOE, on remove calls.
return (unfiltered instanceof SetMultimap) ? Collections.<V>emptySet() : Collections.<V>emptyList();
}
@Override
public void clear() {
entries().clear();
}
@Override
public Collection<V> get(final K key) {
return filterCollection(unfiltered.get(key), new ValuePredicate(key));
}
@Override
Collection<Entry<K, V>> createEntries() {
return filterCollection(unfiltered.entries(), predicate);
}
@Override
Collection<V> createValues() {
return new FilteredMultimapValues<K, V>(this);
}
@Override
Iterator<Entry<K, V>> entryIterator() {
throw new AssertionError("should never be called");
}
@Override
Map<K, Collection<V>> createAsMap() {
return new AsMap();
}
@Override
public Set<K> keySet() {
return asMap().keySet();
}
boolean removeEntriesIf(Predicate<? super Entry<K, Collection<V>>> predicate) {
Iterator<Entry<K, Collection<V>>> entryIterator = unfiltered.asMap().entrySet().iterator();
boolean changed = false;
while (entryIterator.hasNext()) {
Entry<K, Collection<V>> entry = entryIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty() && predicate.apply(Maps.immutableEntry(key, collection))) {
if (collection.size() == entry.getValue().size()) {
entryIterator.remove();
} else {
collection.clear();
}
changed = true;
}
}
return changed;
}
class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
@Override
public boolean containsKey(@Nullable Object key) {
return get(key) != null;
}
@Override
public void clear() {
FilteredEntryMultimap.this.clear();
}
@Override
public Collection<V> get(@Nullable Object key) {
Collection<V> result = unfiltered.asMap().get(key);
if (result == null) {
return null;
}
@SuppressWarnings("unchecked") // key is equal to a K, if not a K itself
K k = (K) key;
result = filterCollection(result, new ValuePredicate(k));
return result.isEmpty() ? null : result;
}
@Override
public Collection<V> remove(@Nullable Object key) {
Collection<V> collection = unfiltered.asMap().get(key);
if (collection == null) {
return null;
}
@SuppressWarnings("unchecked") // it's definitely equal to a K
K k = (K) key;
List<V> result = Lists.newArrayList();
Iterator<V> itr = collection.iterator();
while (itr.hasNext()) {
V v = itr.next();
if (satisfies(k, v)) {
itr.remove();
result.add(v);
}
}
if (result.isEmpty()) {
return null;
} else if (unfiltered instanceof SetMultimap) {
return Collections.unmodifiableSet(Sets.newLinkedHashSet(result));
} else {
return Collections.unmodifiableList(result);
}
}
@Override
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(this) {
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(Maps.<K>keyPredicateOnEntries(in(c)));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(Maps.<K>keyPredicateOnEntries(not(in(c))));
}
@Override
public boolean remove(@Nullable Object o) {
return AsMap.this.remove(o) != null;
}
};
}
@Override
Set<Entry<K, Collection<V>>> createEntrySet() {
return new Maps.EntrySet<K, Collection<V>>() {
@Override
Map<K, Collection<V>> map() {
return AsMap.this;
}
@Override
public Iterator<Entry<K, Collection<V>>> iterator() {
return new AbstractIterator<Entry<K, Collection<V>>>() {
final Iterator<Entry<K, Collection<V>>> backingIterator = unfiltered.asMap().entrySet()
.iterator();
@Override
protected Entry<K, Collection<V>> computeNext() {
while (backingIterator.hasNext()) {
Entry<K, Collection<V>> entry = backingIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty()) {
return Maps.immutableEntry(key, collection);
}
}
return endOfData();
}
};
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(in(c));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
}
@Override
public int size() {
return Iterators.size(iterator());
}
};
}
@Override
Collection<Collection<V>> createValues() {
return new Maps.Values<K, Collection<V>>(AsMap.this) {
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof Collection) {
Collection<?> c = (Collection<?>) o;
Iterator<Entry<K, Collection<V>>> entryIterator = unfiltered.asMap().entrySet().iterator();
while (entryIterator.hasNext()) {
Entry<K, Collection<V>> entry = entryIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty() && c.equals(collection)) {
if (collection.size() == entry.getValue().size()) {
entryIterator.remove();
} else {
collection.clear();
}
return true;
}
}
}
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(in(c)));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(not(in(c))));
}
};
}
}
@Override
Multiset<K> createKeys() {
return new Keys();
}
class Keys extends Multimaps.Keys<K, V> {
Keys() {
super(FilteredEntryMultimap.this);
}
@Override
public int remove(@Nullable Object key, int occurrences) {
checkNonnegative(occurrences, "occurrences");
if (occurrences == 0) {
return count(key);
}
Collection<V> collection = unfiltered.asMap().get(key);
if (collection == null) {
return 0;
}
@SuppressWarnings("unchecked") // key is equal to a K, if not a K itself
K k = (K) key;
int oldCount = 0;
Iterator<V> itr = collection.iterator();
while (itr.hasNext()) {
V v = itr.next();
if (satisfies(k, v)) {
oldCount++;
if (oldCount <= occurrences) {
itr.remove();
}
}
}
return oldCount;
}
@Override
public Set<Multiset.Entry<K>> entrySet() {
return new Multisets.EntrySet<K>() {
@Override
Multiset<K> multiset() {
return Keys.this;
}
@Override
public Iterator<Multiset.Entry<K>> iterator() {
return Keys.this.entryIterator();
}
@Override
public int size() {
return FilteredEntryMultimap.this.keySet().size();
}
private boolean removeEntriesIf(final Predicate<? super Multiset.Entry<K>> predicate) {
return FilteredEntryMultimap.this.removeEntriesIf(new Predicate<Map.Entry<K, Collection<V>>>() {
@Override
public boolean apply(Map.Entry<K, Collection<V>> entry) {
return predicate.apply(Multisets.immutableEntry(entry.getKey(), entry.getValue().size()));
}
});
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(in(c));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
}
};
}
}
}

Some files were not shown because too many files have changed in this diff Show More