[guava-libraries] 01/07: Imported Upstream version 19.0

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Fri Dec 18 00:32:46 UTC 2015


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch master
in repository guava-libraries.

commit 9b06b6f0efee371e43279f679557148446dc77f4
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Fri Dec 18 00:05:28 2015 +0100

    Imported Upstream version 19.0
---
 .gitattributes                                     |   14 +
 .gitignore                                         |    2 +-
 .travis.yml                                        |   30 +
 AUTHORS                                            |    7 -
 CONTRIBUTING.md                                    |   86 +
 README                                             |   46 -
 README.md                                          |   96 +
 guava-gwt/pom.xml                                  |   61 +-
 .../super/com/google/common/base/CharMatcher.java  | 1573 ++++++++-----
 .../super/com/google/common/base/Charsets.java     |    2 +-
 .../base/super/com/google/common/base/Enums.java   |    9 +-
 .../super/com/google/common/base/Predicates.java   |  142 +-
 .../super/com/google/common/base/Splitter.java     |  141 +-
 .../super/com/google/common/base/Stopwatch.java    |   27 +-
 .../com/google/common/cache/CacheBuilder.java      |   16 +-
 .../super/com/google/common/cache/CacheLoader.java |   15 +-
 .../super/com/google/common/cache/LocalCache.java  |   34 +-
 .../com/google/common/collect/AbstractBiMap.java   |  123 +-
 .../common/collect/AbstractMapBasedMultimap.java   |  179 +-
 .../common/collect/AbstractMapBasedMultiset.java   |   34 +-
 .../google/common/collect/ArrayListMultimap.java   |   24 +-
 .../com/google/common/collect/ArrayTable.java      |  102 +-
 .../google/common/collect/BinaryTreeTraverser.java |    8 +-
 .../com/google/common/collect/ContiguousSet.java   |   37 +-
 .../google/common/collect/EmptyContiguousSet.java  |   55 +-
 .../common/collect/EmptyImmutableSortedMap.java    |   42 -
 .../super/com/google/common/collect/EnumBiMap.java |   31 +-
 .../com/google/common/collect/EnumHashBiMap.java   |   28 +-
 .../com/google/common/collect/EnumMultiset.java    |   10 +-
 .../com/google/common/collect/FluentIterable.java  |  258 ++-
 .../com/google/common/collect/GenericMapMaker.java |    2 +-
 .../com/google/common/collect/HashMultimap.java    |   17 +-
 .../com/google/common/collect/HashMultiset.java    |    9 +-
 .../com/google/common/collect/ImmutableAsList.java |    3 +-
 .../com/google/common/collect/ImmutableBiMap.java  |   29 +-
 .../common/collect/ImmutableListMultimap.java      |  118 +-
 .../com/google/common/collect/ImmutableMap.java    |  221 +-
 .../common/collect/ImmutableMapEntrySet.java       |   31 +
 .../google/common/collect/ImmutableMapKeySet.java  |   26 +-
 .../google/common/collect/ImmutableMapValues.java  |   19 +-
 .../google/common/collect/ImmutableMultimap.java   |  209 +-
 .../google/common/collect/ImmutableMultiset.java   |  189 +-
 .../com/google/common/collect/ImmutableSet.java    |   36 +-
 .../common/collect/ImmutableSetMultimap.java       |  179 +-
 .../common/collect/ImmutableSortedAsList.java      |    6 +-
 .../google/common/collect/ImmutableSortedMap.java  |   58 +-
 .../google/common/collect/ImmutableSortedSet.java  |   14 +-
 .../super/com/google/common/collect/Iterables.java |  139 +-
 .../super/com/google/common/collect/Iterators.java |  196 +-
 .../google/common/collect/LinkedHashMultimap.java  |   56 +-
 .../google/common/collect/LinkedHashMultiset.java  |   15 +-
 .../google/common/collect/LinkedListMultimap.java  |   81 +-
 .../super/com/google/common/collect/Lists.java     |  347 ++-
 .../super/com/google/common/collect/MapMaker.java  |    2 +-
 .../super/com/google/common/collect/Maps.java      |  711 +++---
 .../super/com/google/common/collect/Multimaps.java |  515 +++--
 .../com/google/common/collect/ObjectArrays.java    |    9 +-
 .../super/com/google/common/collect/Platform.java  |    6 +
 .../common/collect/RegularContiguousSet.java       |   63 +-
 .../common/collect/RegularImmutableAsList.java     |    5 +-
 .../common/collect/RegularImmutableBiMap.java      |    9 +
 .../google/common/collect/RegularImmutableSet.java |   10 +-
 .../super/com/google/common/collect/Sets.java      |  369 +--
 .../com/google/common/collect/SortedMultisets.java |   30 +-
 .../com/google/common/collect/Synchronized.java    |  346 +--
 .../com/google/common/collect/TreeMultimap.java    |   31 +-
 .../com/google/common/collect/TreeMultiset.java    |   46 +-
 .../super/com/google/common/io/BaseEncoding.java   |  356 +--
 .../super/com/google/common/io/GwtWorkarounds.java |  118 -
 .../super/com/google/common/math/DoubleMath.java   |   46 +
 .../super/com/google/common/math/LongMath.java     |  195 +-
 .../super/com/google/common/primitives/Chars.java  |   51 +-
 .../com/google/common/primitives/Doubles.java      |   53 +-
 .../super/com/google/common/primitives/Floats.java |   58 +-
 .../super/com/google/common/primitives/Ints.java   |  119 +-
 .../super/com/google/common/primitives/Shorts.java |   55 +-
 .../google/common/primitives/UnsignedInteger.java  |   49 +-
 .../common/util/concurrent/AbstractFuture.java     |  326 +++
 .../util/concurrent/AggregateFutureState.java      |   49 +
 .../google/common/util/concurrent/Callables.java   |   28 +-
 .../com/google/common/util/concurrent/Futures.java | 1267 +++++++++++
 .../GwtFuturesCatchingSpecialization.java          |   73 +
 .../common/util/concurrent/InterruptibleTask.java} |   22 +-
 .../common/util/concurrent/MoreExecutors.java      |   85 +
 .../google/common/util/concurrent/Platform.java}   |   22 +-
 .../common/util/concurrent/Uninterruptibles.java}  |   28 +-
 guava-gwt/src-super/java/lang/Lang.gwt.xml         |    1 +
 .../super/java/lang/InterruptedException.java}     |   19 +-
 .../reflect/UndeclaredThrowableException.java}     |   26 +-
 .../util/concurrent/CancellationException.java}    |   21 +-
 .../super/java/util/concurrent/CountDownLatch.java |   55 +
 .../util/super/java/util/concurrent/Delayed.java   |   18 +
 .../util/super/java/util/concurrent/Executor.java} |   18 +-
 .../util/super/java/util/concurrent/Executors.java |   50 +
 .../util/super/java/util/concurrent/Future.java    |   36 +
 .../concurrent/RejectedExecutionException.java     |   30 +-
 .../java/util/concurrent/RunnableFuture.java}      |   15 +-
 .../java/util/concurrent/ScheduledFuture.java      |   19 +
 .../util/super/java/util/concurrent/TimeUnit.java  |  138 +-
 .../java/util/concurrent/TimeoutException.java}    |   18 +-
 .../java/util/concurrent/atomic/AtomicBoolean.java |   77 +
 .../google/common/annotations/Annotations.gwt.xml  |    2 +-
 guava-gwt/src/com/google/common/base/Base.gwt.xml  |    2 +-
 .../common/base/GwtSerializationDependencies.java  |   34 +-
 .../PairwiseEquivalence_CustomFieldSerializer.java |    4 +-
 .../AllEqualOrdering_CustomFieldSerializer.java    |    6 +-
 .../ArrayListMultimap_CustomFieldSerializer.java   |   17 +-
 .../ByFunctionOrdering_CustomFieldSerializer.java  |   18 +-
 .../src/com/google/common/collect/Collect.gwt.xml  |    6 +-
 .../ComparatorOrdering_CustomFieldSerializer.java  |   18 +-
 .../CompoundOrdering_CustomFieldSerializer.java    |   17 +-
 .../DenseImmutableTable_CustomFieldSerializer.java |    3 +-
 .../EmptyImmutableBiMap_CustomFieldSerializer.java |   38 -
 ...mmutableListMultimap_CustomFieldSerializer.java |   15 +-
 ...ImmutableSetMultimap_CustomFieldSerializer.java |   15 +-
 .../EmptyImmutableSet_CustomFieldSerializer.java   |   41 -
 ...tyImmutableSortedMap_CustomFieldSerializer.java |   44 -
 ...tyImmutableSortedSet_CustomFieldSerializer.java |   59 -
 .../ExplicitOrdering_CustomFieldSerializer.java    |   17 +-
 .../collect/GwtSerializationDependencies.java      |   22 +-
 .../HashBasedTable_CustomFieldSerializer.java      |    3 +-
 .../HashMultimap_CustomFieldSerializer.java        |   16 +-
 .../HashMultiset_CustomFieldSerializer.java        |   16 +-
 .../ImmutableEntry_CustomFieldSerializer.java      |   12 +-
 .../ImmutableEnumMap_CustomFieldSerializer.java    |   10 +-
 .../ImmutableEnumSet_CustomFieldSerializer.java    |    9 +-
 ...mmutableListMultimap_CustomFieldSerializer.java |   17 +-
 ...ImmutableSetMultimap_CustomFieldSerializer.java |   14 +-
 .../ImmutableSortedMap_CustomFieldSerializer.java  |   19 +-
 ...icographicalOrdering_CustomFieldSerializer.java |   19 +-
 .../LinkedHashMultimap_CustomFieldSerializer.java  |   17 +-
 .../LinkedHashMultiset_CustomFieldSerializer.java  |   16 +-
 .../LinkedListMultimap_CustomFieldSerializer.java  |   14 +-
 .../Multimap_CustomFieldSerializerBase.java        |    9 +-
 .../Multiset_CustomFieldSerializerBase.java        |    7 +-
 .../NaturalOrdering_CustomFieldSerializer.java     |   13 +-
 .../NullsFirstOrdering_CustomFieldSerializer.java  |   18 +-
 .../NullsLastOrdering_CustomFieldSerializer.java   |   17 +-
 ...gularImmutableAsList_CustomFieldSerializer.java |   13 +-
 ...egularImmutableBiMap_CustomFieldSerializer.java |   19 +-
 ...RegularImmutableList_CustomFieldSerializer.java |   13 +-
 .../RegularImmutableMap_CustomFieldSerializer.java |   13 +-
 ...larImmutableMultiset_CustomFieldSerializer.java |   19 +-
 .../RegularImmutableSet_CustomFieldSerializer.java |   13 +-
 ...arImmutableSortedMap_CustomFieldSerializer.java |   44 -
 ...arImmutableSortedSet_CustomFieldSerializer.java |   19 +-
 ...verseNaturalOrdering_CustomFieldSerializer.java |   14 +-
 .../ReverseOrdering_CustomFieldSerializer.java     |   17 +-
 ...gletonImmutableBiMap_CustomFieldSerializer.java |   12 +-
 ...ngletonImmutableList_CustomFieldSerializer.java |   15 +-
 ...ingletonImmutableSet_CustomFieldSerializer.java |   15 +-
 ...gletonImmutableTable_CustomFieldSerializer.java |    3 +-
 ...SparseImmutableTable_CustomFieldSerializer.java |    3 +-
 .../TreeBasedTable_CustomFieldSerializer.java      |    9 +-
 .../TreeMultimap_CustomFieldSerializer.java        |   12 +-
 ...singToStringOrdering_CustomFieldSerializer.java |   14 +-
 guava-gwt/src/com/google/common/net/Net.gwt.xml    |    2 +-
 .../UnsignedLong_CustomFieldSerializer.java        |   10 +-
 .../common/util/concurrent/Concurrent.gwt.xml      |    4 +-
 .../com/google/common/base/CharMatcherTest.java    |   72 +-
 .../super/com/google/common/base/EnumsTest.java    |   28 +-
 .../super/com/google/common/base/JoinerTest.java   |    3 +
 .../super/com/google/common/base/ObjectsTest.java  |    1 +
 .../super/com/google/common/base/OptionalTest.java |   16 +-
 .../com/google/common/base/PreconditionsTest.java  |   39 +-
 .../super/com/google/common/base/SplitterTest.java |  147 +-
 .../com/google/common/base/StopwatchTest.java      |   43 -
 .../super/com/google/common/base/StringsTest.java  |    4 +
 .../super/com/google/common/base/Utf8Test.java     |   93 +-
 .../com/google/common/cache/CacheBuilderTest.java  |    8 +
 .../common/collect/AbstractImmutableSetTest.java   |   12 +-
 .../collect/AbstractSequentialIteratorTest.java    |   10 +-
 .../common/collect/AbstractTableReadTest.java      |    2 +-
 .../common/collect/ArrayListMultimapTest.java      |    8 +-
 .../com/google/common/collect/ArrayTableTest.java  |   12 +-
 .../google/common/collect/Collections2Test.java    |    2 +-
 .../google/common/collect/ContiguousSetTest.java   |   58 +-
 .../com/google/common/collect/EnumBiMapTest.java   |   24 +-
 .../google/common/collect/EvictingQueueTest.java   |   14 +-
 .../com/google/common/collect/HashBiMapTest.java   |    8 +
 .../google/common/collect/ImmutableBiMapTest.java  |   52 +-
 .../common/collect/ImmutableEnumMapTest.java       |    2 +-
 .../common/collect/ImmutableListMultimapTest.java  |   39 +-
 .../google/common/collect/ImmutableMapTest.java    |   43 +-
 .../common/collect/ImmutableMultimapTest.java      |   10 +-
 .../common/collect/ImmutableMultisetTest.java      |    2 +-
 .../common/collect/ImmutableSetMultimapTest.java   |   64 +-
 .../google/common/collect/ImmutableSetTest.java    |    2 +-
 .../common/collect/ImmutableSortedMapTest.java     |   24 +-
 .../common/collect/ImmutableSortedSetTest.java     |  104 +-
 .../google/common/collect/ImmutableTableTest.java  |   48 +-
 .../com/google/common/collect/IterablesTest.java   |   28 +-
 .../com/google/common/collect/IteratorsTest.java   |  106 +-
 .../common/collect/LinkedHashMultimapTest.java     |   30 +-
 .../common/collect/LinkedHashMultisetTest.java     |    8 +-
 .../common/collect/LinkedListMultimapTest.java     |   14 +-
 .../super/com/google/common/collect/ListsTest.java |   22 +-
 .../google/common/collect/MapConstraintsTest.java  |   28 +-
 .../super/com/google/common/collect/MapsTest.java  |   53 +-
 .../com/google/common/collect/MultimapsTest.java   |   40 +-
 .../com/google/common/collect/MultisetsTest.java   |   36 +-
 .../google/common/collect/ObjectArraysTest.java    |   18 +-
 .../com/google/common/collect/OrderingTest.java    |   34 +-
 .../super/com/google/common/collect/SetsTest.java  |   33 +-
 .../collect/SingletonImmutableTableTest.java       |    2 +-
 .../google/common/collect/TreeBasedTableTest.java  |    8 +-
 .../common/collect/TreeMultimapExplicitTest.java   |   26 +-
 .../common/collect/TreeMultimapNaturalTest.java    |   18 +-
 .../google/common/collect/TreeMultisetTest.java    |   44 +-
 .../google/AbstractMultisetSetCountTester.java     |   42 +-
 .../testing/google/MultisetCountTester.java        |    6 +-
 .../testing/google/MultisetIteratorTester.java     |   27 +-
 .../testing/google/MultisetRemoveTester.java       |   54 +-
 .../google/common/collect/testing/GwtPlatform.java |    5 +-
 .../com/google/common/collect/testing/Helpers.java |   96 +
 .../testing/testers/CollectionAddAllTester.java    |   16 +-
 .../testing/testers/CollectionAddTester.java       |   12 +-
 .../testing/testers/CollectionToArrayTester.java   |    8 +-
 .../testing/testers/ListAddAtIndexTester.java      |   32 +-
 .../collect/testing/testers/ListAddTester.java     |    6 +-
 .../testing/testers/ListListIteratorTester.java    |    2 +-
 .../collect/testing/testers/ListSetTester.java     |   12 +-
 .../collect/testing/testers/ListSubListTester.java |   26 +-
 .../collect/testing/testers/MapCreationTester.java |    2 +-
 .../collect/testing/testers/MapPutAllTester.java   |   18 +-
 .../collect/testing/testers/MapPutTester.java      |   30 +-
 .../collect/testing/testers/SetAddTester.java      |    2 +-
 .../com/google/common/io/BaseEncodingTest.java     |  107 +-
 .../google/common/net/InternetDomainNameTest.java  |    2 +-
 .../super/com/google/common/net/MediaTypeTest.java |    9 +-
 .../com/google/common/primitives/BooleansTest.java |    2 +
 .../com/google/common/primitives/BytesTest.java    |    2 +
 .../com/google/common/primitives/CharsTest.java    |    5 +
 .../com/google/common/primitives/DoublesTest.java  |    7 +-
 .../com/google/common/primitives/FloatsTest.java   |    7 +-
 .../com/google/common/primitives/IntsTest.java     |   54 +
 .../com/google/common/primitives/LongsTest.java    |   53 +
 .../com/google/common/primitives/ShortsTest.java   |    6 +
 .../google/common/primitives/SignedBytesTest.java  |    3 +
 .../google/common/primitives/UnsignedIntsTest.java |   28 +-
 .../google/common/primitives/UnsignedLongTest.java |    2 +-
 .../common/primitives/UnsignedLongsTest.java       |   12 +-
 .../common/util/concurrent/CallablesTest.java      |   30 +-
 .../common/util/concurrent/FutureCallbackTest.java |   44 +-
 .../google/common/util/concurrent/FuturesTest.java | 1518 +++++++++++++
 .../common/util/concurrent/TestPlatform.java       |   61 +
 .../TrustedListenableFutureTaskTest.java           |   79 +
 .../com/google/common/base/StopwatchTest_gwt.java  |   20 -
 .../test/com/google/common/base/Utf8Test_gwt.java  |    5 +
 .../test/com/google/common/base/testModule.gwt.xml |    2 +-
 .../google/common/cache/CacheBuilderTest_gwt.java  |    5 +
 .../common/collect/ComparisonChainTest_gwt.java    |    5 +
 .../common/collect/EvictingQueueTest_gwt.java      |   65 +
 .../google/common/collect/HashBiMapTest_gwt.java   |    5 +
 .../common/collect/ImmutableBiMapTest_gwt.java     |   20 +
 .../common/collect/ImmutableMapTest_gwt.java       |   15 +
 .../common/collect/ImmutableSortedMapTest_gwt.java |    5 +
 .../google/common/collect/IteratorsTest_gwt.java   |    5 +
 .../google/common/collect/OrderingTest_gwt.java    |    5 +
 .../common/collect/testing/HelpersTest_gwt.java    |   30 +
 .../google/common/collect/testing/Testing.gwt.xml  |    4 +-
 .../common/collect/testing/google/Google.gwt.xml   |    1 -
 .../com/google/common/io/BaseEncodingTest_gwt.java |   20 +
 .../test/com/google/common/io/testModule.gwt.xml   |    1 +
 .../test/com/google/common/math/testModule.gwt.xml |    2 +-
 .../test/com/google/common/net/testModule.gwt.xml  |    2 +-
 .../com/google/common/primitives/IntsTest_gwt.java |   15 +
 .../google/common/primitives/LongsTest_gwt.java    |   20 +
 .../common/primitives/UnsignedIntsTest_gwt.java    |   10 +
 .../common/primitives/UnsignedLongsTest_gwt.java   |   10 +
 .../concurrent/CallablesTest_gwt.java}             |   12 +-
 .../util/concurrent/FutureCallbackTest_gwt.java    |   55 +
 .../common/util/concurrent/FuturesTest_gwt.java    | 2153 ++++++++++++++++++
 .../concurrent/TrustedInputFutureTest_gwt.java     |  218 ++
 .../TrustedListenableFutureTaskTest_gwt.java       |   35 +
 .../concurrent/UntrustedInputFutureTest_gwt.java   |  218 ++
 .../common/util/concurrent/testModule.gwt.xml      |    4 +-
 guava-testlib/pom.xml                              |   24 +-
 .../collect/testing/AbstractContainerTester.java   |   22 +-
 .../common/collect/testing/AbstractMapTester.java  |   42 +-
 .../testing/CollectionTestSuiteBuilder.java        |   10 +-
 .../testing/ConcurrentMapTestSuiteBuilder.java     |   52 +
 .../ConcurrentNavigableMapTestSuiteBuilder.java    |   49 +
 .../testing/DerivedCollectionGenerators.java       |   24 +-
 .../com/google/common/collect/testing/Helpers.java |   96 +
 .../collect/testing/ListTestSuiteBuilder.java      |   12 +-
 .../collect/testing/MapTestSuiteBuilder.java       |    2 +-
 .../testing/NavigableMapTestSuiteBuilder.java      |   69 +-
 .../testing/NavigableSetTestSuiteBuilder.java      |   10 +-
 .../common/collect/testing/OneSizeGenerator.java   |    2 +-
 .../google/common/collect/testing/Platform.java    |    4 +-
 .../common/collect/testing/SampleElements.java     |   42 +-
 .../collect/testing/SetTestSuiteBuilder.java       |   10 +-
 .../collect/testing/SortedMapTestSuiteBuilder.java |    7 +-
 .../collect/testing/TestsForMapsInJavaUtil.java    |    9 +-
 .../collect/testing/features/FeatureUtil.java      |   13 +-
 .../testing/google/AbstractListMultimapTester.java |    9 +-
 .../testing/google/AbstractMultimapTester.java     |   52 +-
 .../google/AbstractMultisetSetCountTester.java     |   42 +-
 .../testing/google/AbstractMultisetTester.java     |    2 +-
 .../collect/testing/google/BiMapGenerators.java    |    7 +
 .../collect/testing/google/BiMapPutTester.java     |   43 +-
 .../collect/testing/google/BiMapRemoveTester.java  |   24 +-
 .../testing/google/BiMapTestSuiteBuilder.java      |    2 +-
 .../google/DerivedGoogleCollectionGenerators.java  |   14 +-
 ...etMultimapGetTester.java => GoogleHelpers.java} |   24 +-
 .../testing/google/ListMultimapAsMapTester.java    |   34 +-
 .../testing/google/ListMultimapEqualsTester.java   |   12 +-
 .../testing/google/ListMultimapPutAllTester.java   |    6 +-
 .../testing/google/ListMultimapRemoveTester.java   |   46 +-
 .../google/ListMultimapReplaceValuesTester.java    |    6 +-
 .../collect/testing/google/MapGenerators.java      |    8 +
 .../testing/google/MultimapAsMapGetTester.java     |   92 +-
 .../testing/google/MultimapAsMapTester.java        |   57 +-
 .../testing/google/MultimapClearTester.java        |   37 +-
 .../google/MultimapContainsEntryTester.java        |    8 +-
 .../testing/google/MultimapContainsKeyTester.java  |    4 +-
 .../google/MultimapContainsValueTester.java        |    4 +-
 .../testing/google/MultimapEntriesTester.java      |   54 +-
 .../testing/google/MultimapEqualsTester.java       |    2 +-
 .../collect/testing/google/MultimapGetTester.java  |  106 +-
 .../testing/google/MultimapKeySetTester.java       |   12 +-
 .../collect/testing/google/MultimapKeysTester.java |   60 +-
 .../google/MultimapPutAllMultimapTester.java       |   46 +-
 .../testing/google/MultimapPutIterableTester.java  |   82 +-
 .../collect/testing/google/MultimapPutTester.java  |   91 +-
 .../testing/google/MultimapRemoveAllTester.java    |   34 +-
 .../testing/google/MultimapRemoveEntryTester.java  |   26 +-
 .../google/MultimapReplaceValuesTester.java        |   77 +-
 .../collect/testing/google/MultimapSizeTester.java |    9 +-
 .../testing/google/MultimapTestSuiteBuilder.java   |   24 +-
 .../testing/google/MultimapToStringTester.java     |    3 +-
 .../testing/google/MultimapValuesTester.java       |   12 +-
 .../collect/testing/google/MultisetAddTester.java  |   46 +-
 .../testing/google/MultisetContainsTester.java     |    4 +-
 .../testing/google/MultisetCountTester.java        |    6 +-
 .../testing/google/MultisetElementSetTester.java   |   32 +-
 .../testing/google/MultisetEntrySetTester.java     |   52 +-
 .../testing/google/MultisetIteratorTester.java     |   27 +-
 .../testing/google/MultisetNavigationTester.java   |   12 +-
 .../testing/google/MultisetReadsTester.java        |   18 +-
 .../testing/google/MultisetRemoveTester.java       |   56 +-
 .../MultisetSetCountConditionallyTester.java       |   10 +-
 .../testing/google/MultisetTestSuiteBuilder.java   |   10 +-
 .../testing/google/SetMultimapAsMapTester.java     |   34 +-
 .../testing/google/SetMultimapEqualsTester.java    |   12 +-
 .../testing/google/SetMultimapPutAllTester.java    |    4 +-
 .../testing/google/SetMultimapPutTester.java       |    2 +-
 .../google/SetMultimapReplaceValuesTester.java     |    6 +-
 .../testing/google/SortedMapGenerators.java        |    7 +
 .../google/SortedMultisetTestSuiteBuilder.java     |   30 +-
 .../testing/google/SortedSetMultimapGetTester.java |    2 +-
 .../google/UnmodifiableCollectionTests.java        |    7 +-
 .../testing/testers/AbstractListIndexOfTester.java |    4 +-
 .../testing/testers/CollectionAddAllTester.java    |   16 +-
 .../testing/testers/CollectionAddTester.java       |   12 +-
 .../testing/testers/CollectionClearTester.java     |    2 +
 .../testers/CollectionContainsAllTester.java       |    6 +-
 .../testing/testers/CollectionContainsTester.java  |    6 +-
 .../testing/testers/CollectionRemoveAllTester.java |   24 +-
 .../testing/testers/CollectionRemoveTester.java    |   18 +-
 .../testing/testers/CollectionRetainAllTester.java |   20 +-
 .../testing/testers/CollectionToArrayTester.java   |    8 +-
 .../testing/testers/CollectionToStringTester.java  |    2 +-
 .../testers/ConcurrentMapPutIfAbsentTester.java    |  131 ++
 .../testing/testers/ConcurrentMapRemoveTester.java |  108 +
 .../testers/ConcurrentMapReplaceEntryTester.java   |  149 ++
 .../testers/ConcurrentMapReplaceTester.java        |  105 +
 .../testing/testers/ListAddAllAtIndexTester.java   |   26 +-
 .../collect/testing/testers/ListAddAllTester.java  |   10 +-
 .../testing/testers/ListAddAtIndexTester.java      |   32 +-
 .../collect/testing/testers/ListAddTester.java     |    6 +-
 .../testing/testers/ListCreationTester.java        |    2 +-
 .../collect/testing/testers/ListEqualsTester.java  |    2 +-
 .../collect/testing/testers/ListIndexOfTester.java |    4 +-
 .../testing/testers/ListLastIndexOfTester.java     |    4 +-
 .../testing/testers/ListListIteratorTester.java    |    2 +-
 .../testing/testers/ListRetainAllTester.java       |   19 +-
 .../collect/testing/testers/ListSetTester.java     |   12 +-
 .../collect/testing/testers/ListSubListTester.java |   26 +-
 .../collect/testing/testers/MapClearTester.java    |    2 +
 .../testing/testers/MapContainsKeyTester.java      |    6 +-
 .../testing/testers/MapContainsValueTester.java    |    9 +-
 .../collect/testing/testers/MapCreationTester.java |    2 +-
 .../collect/testing/testers/MapEntrySetTester.java |   24 +-
 .../collect/testing/testers/MapEqualsTester.java   |   12 +-
 .../collect/testing/testers/MapGetTester.java      |    6 +-
 .../collect/testing/testers/MapHashCodeTester.java |    4 +-
 .../collect/testing/testers/MapPutAllTester.java   |   18 +-
 .../collect/testing/testers/MapPutTester.java      |   30 +-
 .../collect/testing/testers/MapRemoveTester.java   |   20 +-
 .../collect/testing/testers/MapToStringTester.java |    2 +-
 .../testers/NavigableMapNavigationTester.java      |   32 +-
 .../testers/NavigableSetNavigationTester.java      |   18 +-
 .../common/collect/testing/testers/Platform.java   |    4 +-
 .../testing/testers/QueueElementTester.java        |    4 +-
 .../collect/testing/testers/QueueOfferTester.java  |    4 +-
 .../collect/testing/testers/QueuePeekTester.java   |    4 +-
 .../collect/testing/testers/QueuePollTester.java   |    8 +-
 .../collect/testing/testers/QueueRemoveTester.java |    8 +-
 .../collect/testing/testers/SetAddAllTester.java   |   10 +-
 .../collect/testing/testers/SetAddTester.java      |    2 +-
 .../collect/testing/testers/SetCreationTester.java |    4 +-
 .../collect/testing/testers/SetEqualsTester.java   |    2 +-
 .../collect/testing/testers/SetRemoveTester.java   |    4 +-
 .../testing/testers/SortedMapNavigationTester.java |   30 +-
 .../common/testing/AbstractPackageSanityTests.java |   24 +-
 .../google/common/testing/ArbitraryInstances.java  |    7 +-
 .../google/common/testing/ClassSanityTester.java   |   24 +-
 .../common/testing/ForwardingWrapperTester.java    |   10 +-
 .../google/common/testing/FreshValueGenerator.java |  510 +++--
 .../com/google/common/testing/GcFinalization.java  |   18 +-
 .../google/common/testing/NullPointerTester.java   |    1 -
 .../com/google/common/testing/TestLogHandler.java  |   21 +-
 .../google/common/collect/testing/HelpersTest.java |  129 ++
 .../collect/testing/features/FeatureEnumTest.java  |   29 +-
 .../collect/testing/features/FeatureUtilTest.java  |   25 +-
 .../testing/AbstractPackageSanityTestsTest.java    |   25 +-
 .../common/testing/ArbitraryInstancesTest.java     |   30 +-
 .../common/testing/ClassSanityTesterTest.java      |   39 +-
 .../google/common/testing/EqualsTesterTest.java    |    5 +-
 .../common/testing/FreshValueGeneratorTest.java    |  343 +--
 .../google/common/testing/GcFinalizationTest.java  |    6 +-
 .../common/testing/NullPointerTesterTest.java      |   29 +-
 .../google/common/testing/TearDownStackTest.java   |    4 +-
 .../com/google/common/base/EnumsBenchmark.java     |    6 +-
 .../common/base/LazyStackTraceBenchmark.java       |   93 +
 .../com/google/common/base/Utf8Benchmark.java      |  172 --
 .../common/base/WhitespaceMatcherBenchmark.java    |    3 +-
 .../common/cache/MapMakerComparisonBenchmark.java  |   29 -
 .../collect/MultipleSetContainsBenchmark.java      |   83 +
 .../com/google/common/hash/ChecksumBenchmark.java  |    4 +-
 .../com/google/common/hash/HashCodeBenchmark.java  |  142 ++
 .../google/common/hash/HashFunctionBenchmark.java  |   10 +-
 .../hash/MessageDigestAlgorithmBenchmark.java      |    1 +
 .../hash/MessageDigestCreationBenchmark.java       |    2 +-
 .../google/common/io/BaseEncodingBenchmark.java    |  108 +
 .../AbstractFutureFootprintBenchmark.java          |   95 +
 .../util/concurrent/ExecutionListBenchmark.java    |  116 +-
 .../util/concurrent/FuturesCombineBenchmark.java   |  147 --
 .../concurrent/FuturesGetCheckedBenchmark.java     |  188 ++
 .../SingleThreadAbstractFutureBenchmark.java       |  127 ++
 guava-tests/pom.xml                                |   16 +-
 .../com/google/common/base/CharMatcherTest.java    |   96 +-
 .../test/com/google/common/base/EnumsTest.java     |   32 +-
 .../common/base/FinalizableReferenceQueueTest.java |    2 +
 .../test/com/google/common/base/FunctionsTest.java |    2 +
 .../test/com/google/common/base/JoinerTest.java    |    3 +
 .../test/com/google/common/base/ObjectsTest.java   |    1 +
 .../test/com/google/common/base/OptionalTest.java  |   16 +-
 .../com/google/common/base/PreconditionsTest.java  |   39 +-
 .../com/google/common/base/PredicatesTest.java     |    1 +
 .../test/com/google/common/base/SplitterTest.java  |  189 +-
 .../test/com/google/common/base/StopwatchTest.java |   43 -
 .../test/com/google/common/base/StringsTest.java   |    4 +
 .../test/com/google/common/base/SuppliersTest.java |    1 +
 .../google/common/base/SuppressUnderAndroid.java   |   72 +
 .../com/google/common/base/ThrowablesTest.java     |   80 +-
 .../test/com/google/common/base/Utf8Test.java      |   65 +-
 .../test/com/google/common/base/VerifyTest.java    |    5 +-
 .../com/google/common/cache/CacheBuilderTest.java  |   22 +-
 .../com/google/common/cache/CacheEvictionTest.java |  145 +-
 .../google/common/cache/CacheExpirationTest.java   |   44 +-
 .../com/google/common/cache/CacheLoadingTest.java  |   20 +-
 .../google/common/cache/CacheReferencesTest.java   |    4 +-
 .../test/com/google/common/cache/CacheTesting.java |    9 +-
 .../com/google/common/cache/LocalCacheTest.java    |  113 +-
 .../google/common/cache/LocalLoadingCacheTest.java |   12 +-
 .../google/common/cache/PopulatedCachesTest.java   |   23 +-
 .../common/cache/RemovalNotificationTest.java      |    8 +-
 .../common/collect/AbstractImmutableSetTest.java   |   12 +-
 .../common/collect/AbstractRangeSetTest.java       |    6 +
 .../collect/AbstractSequentialIteratorTest.java    |   10 +-
 .../common/collect/AbstractTableReadTest.java      |    2 +-
 .../common/collect/ArrayListMultimapTest.java      |    8 +-
 .../com/google/common/collect/ArrayTableTest.java  |   20 +-
 .../google/common/collect/Collections2Test.java    |    2 +-
 .../google/common/collect/ComparisonChainTest.java |    9 +
 .../com/google/common/collect/ConstraintsTest.java |   51 +-
 .../google/common/collect/ContiguousSetTest.java   |   58 +-
 .../com/google/common/collect/EnumBiMapTest.java   |   24 +-
 .../google/common/collect/EvictingQueueTest.java   |    4 +
 .../com/google/common/collect/FauxveridesTest.java |   19 +-
 .../common/collect/FilteredCollectionsTest.java    |   10 +-
 .../google/common/collect/FluentIterableTest.java  |   66 +-
 .../google/common/collect/ForwardingListTest.java  |    4 +-
 .../common/collect/ForwardingMultisetTest.java     |    1 +
 .../common/collect/ForwardingNavigableMapTest.java |    2 +-
 .../com/google/common/collect/HashBiMapTest.java   |  101 +
 .../google/common/collect/ImmutableBiMapTest.java  |   64 +-
 .../collect/ImmutableClassToInstanceMapTest.java   |   18 +-
 .../common/collect/ImmutableEnumMapTest.java       |    9 +-
 .../common/collect/ImmutableListMultimapTest.java  |   59 +-
 .../google/common/collect/ImmutableListTest.java   |   33 +-
 .../google/common/collect/ImmutableMapTest.java    |   62 +-
 .../common/collect/ImmutableMultimapTest.java      |   10 +-
 .../common/collect/ImmutableMultisetTest.java      |    6 +-
 .../common/collect/ImmutableRangeMapTest.java      |   30 +
 .../common/collect/ImmutableRangeSetTest.java      |   17 +-
 .../common/collect/ImmutableSetMultimapTest.java   |  107 +-
 .../google/common/collect/ImmutableSetTest.java    |    2 +-
 .../common/collect/ImmutableSortedMapTest.java     |   36 +-
 .../collect/ImmutableSortedMultisetTest.java       |    6 +-
 .../common/collect/ImmutableSortedSetTest.java     |  104 +-
 .../google/common/collect/ImmutableTableTest.java  |   49 +-
 .../com/google/common/collect/IterablesTest.java   |   30 +-
 .../com/google/common/collect/IteratorsTest.java   |  105 +-
 .../common/collect/LinkedHashMultimapTest.java     |   34 +-
 .../common/collect/LinkedHashMultisetTest.java     |    8 +-
 .../common/collect/LinkedListMultimapTest.java     |   14 +-
 .../test/com/google/common/collect/ListsTest.java  |   24 +-
 .../google/common/collect/MapConstraintsTest.java  |   28 +-
 .../common/collect/MapMakerInternalMapTest.java    |    5 +-
 .../test/com/google/common/collect/MapsTest.java   |  141 +-
 .../common/collect/MinMaxPriorityQueueTest.java    |   14 +-
 .../com/google/common/collect/MultimapsTest.java   |   47 +-
 .../com/google/common/collect/MultisetsTest.java   |   36 +-
 .../google/common/collect/NewCustomTableTest.java  |    4 +-
 .../google/common/collect/ObjectArraysTest.java    |   32 +-
 .../com/google/common/collect/OrderingTest.java    |   34 +-
 .../common/collect/RegularImmutableTableTest.java  |    2 +-
 .../test/com/google/common/collect/SetsTest.java   |   45 +-
 .../collect/SingletonImmutableTableTest.java       |    2 +-
 .../common/collect/SuppressUnderAndroid.java       |   42 +
 .../common/collect/SynchronizedMultimapTest.java   |   19 +-
 .../google/common/collect/TreeBasedTableTest.java  |    8 +-
 .../common/collect/TreeMultimapExplicitTest.java   |   30 +-
 .../common/collect/TreeMultimapNaturalTest.java    |   32 +-
 .../google/common/collect/TreeMultisetTest.java    |   45 +-
 .../google/common/collect/TreeRangeMapTest.java    |  112 +
 .../google/common/collect/TreeRangeSetTest.java    |  108 +-
 .../com/google/common/escape/EscapersTest.java     |    4 +-
 .../com/google/common/eventbus/DispatcherTest.java |  177 ++
 .../com/google/common/eventbus/EventBusTest.java   |   51 +-
 .../common/eventbus/EventSubscriberTest.java       |  195 --
 .../google/common/eventbus/PackageSanityTests.java |   28 +-
 .../common/eventbus/SubscriberRegistryTest.java    |  203 ++
 .../com/google/common/eventbus/SubscriberTest.java |  153 ++
 .../outside/AnnotatedSubscriberFinderTests.java    |   59 +-
 .../com/google/common/hash/BloomFilterTest.java    |   17 +-
 .../test/com/google/common/hash/HashCodeTest.java  |    5 +
 .../com/google/common/hash/HashFunctionEnum.java   |    1 +
 .../test/com/google/common/hash/HashingTest.java   |  123 +-
 .../common/hash/MessageDigestHashFunctionTest.java |    2 +
 .../google/common/hash/SuppressUnderAndroid.java   |   42 +
 .../com/google/common/io/BaseEncodingTest.java     |  124 +-
 .../test/com/google/common/io/ByteSinkTester.java  |    1 +
 .../test/com/google/common/io/ByteSourceTest.java  |   79 +-
 .../com/google/common/io/ByteSourceTester.java     |   36 +-
 .../test/com/google/common/io/ByteStreamsTest.java |   68 +-
 .../test/com/google/common/io/CharSinkTester.java  |    1 +
 .../test/com/google/common/io/CharSourceTest.java  |    5 +-
 .../com/google/common/io/CharSourceTester.java     |   13 +
 .../test/com/google/common/io/CharStreamsTest.java |   17 -
 .../test/com/google/common/io/CloserTest.java      |   11 +-
 .../google/common/io/CountingInputStreamTest.java  |    6 +-
 .../test/com/google/common/io/FilesTest.java       |    9 +-
 .../common/io/LittleEndianDataInputStreamTest.java |    4 +-
 .../test/com/google/common/io/ResourcesTest.java   |   10 +-
 .../com/google/common/io/SourceSinkFactories.java  |    6 +-
 .../com/google/common/io/SourceSinkTester.java     |    1 +
 .../com/google/common/io/SuppressUnderAndroid.java |   42 +
 .../com/google/common/math/BigIntegerMathTest.java |   12 +-
 .../com/google/common/math/DoubleUtilsTest.java    |   14 +-
 .../test/com/google/common/math/LongMathTest.java  |   74 +-
 .../google/common/math/SuppressUnderAndroid.java   |   42 +
 .../com/google/common/net/HostSpecifierTest.java   |    4 +-
 .../com/google/common/net/InetAddressesTest.java   |   10 +-
 .../google/common/net/InternetDomainNameTest.java  |    2 +-
 .../test/com/google/common/net/MediaTypeTest.java  |   18 +-
 .../com/google/common/net/PercentEscaperTest.java  |    5 +-
 .../com/google/common/primitives/BooleansTest.java |    2 +
 .../com/google/common/primitives/BytesTest.java    |    2 +
 .../com/google/common/primitives/CharsTest.java    |   17 +-
 .../com/google/common/primitives/DoublesTest.java  |   25 +-
 .../com/google/common/primitives/FloatsTest.java   |    7 +-
 .../com/google/common/primitives/IntsTest.java     |   57 +
 .../com/google/common/primitives/LongsTest.java    |   53 +
 .../com/google/common/primitives/ShortsTest.java   |   10 +
 .../google/common/primitives/SignedBytesTest.java  |    3 +
 .../common/primitives/UnsignedBytesTest.java       |    6 +
 .../google/common/primitives/UnsignedIntsTest.java |   28 +-
 .../google/common/primitives/UnsignedLongTest.java |    2 +-
 .../common/primitives/UnsignedLongsTest.java       |   12 +-
 .../com/google/common/reflect/ClassPathTest.java   |  268 +--
 .../reflect/ImmutableTypeToInstanceMapTest.java    |    3 +-
 .../com/google/common/reflect/InvokableTest.java   |   20 +-
 .../reflect/MutableTypeToInstanceMapTest.java      |    3 +-
 .../common/reflect/SuppressUnderAndroid.java       |   42 +
 .../google/common/reflect/TypeResolverTest.java    |   54 +-
 .../common/reflect/TypeTokenResolutionTest.java    |    4 +-
 .../com/google/common/reflect/TypeTokenTest.java   |  529 +++--
 .../test/com/google/common/reflect/TypesTest.java  |   38 +-
 .../concurrent/AbstractAbstractFutureTest.java     |  490 ++++
 .../AbstractExecutionThreadServiceTest.java        |   46 +-
 .../util/concurrent/AbstractFutureBenchmarks.java  |  423 ++++
 .../AbstractFutureCancellationCauseTest.java       |   91 +
 .../AbstractFutureFallbackAtomicHelperTest.java    |  145 ++
 .../common/util/concurrent/AbstractFutureTest.java |  526 ++++-
 .../util/concurrent/AbstractIdleServiceTest.java   |   14 +-
 .../AbstractListeningExecutorServiceTest.java      |   14 +-
 .../concurrent/AbstractScheduledServiceTest.java   |  143 +-
 .../util/concurrent/AbstractServiceTest.java       |    7 +-
 .../util/concurrent/AsyncSettableFutureTest.java   |  193 --
 .../common/util/concurrent/CallablesTest.java      |    7 +
 .../util/concurrent/ForwardingObjectTester.java    |   15 +-
 .../concurrent/ForwardingObjectTesterTest.java     |    3 +
 .../common/util/concurrent/FutureCallbackTest.java |   10 +-
 .../util/concurrent/FuturesGetCheckedInputs.java   |  142 ++
 .../util/concurrent/FuturesGetCheckedTest.java     |  367 +++
 .../util/concurrent/FuturesGetUncheckedTest.java   |  107 +
 .../google/common/util/concurrent/FuturesTest.java | 2401 ++++++++++++--------
 .../util/concurrent/FuturesTransformAsyncTest.java |  187 ++
 .../util/concurrent/GeneratedMonitorTest.java      |  787 +++++++
 .../util/concurrent/ListenableFutureTester.java    |    3 +-
 .../common/util/concurrent/MoreExecutorsTest.java  |   59 +-
 .../common/util/concurrent/PackageSanityTests.java |    3 +
 .../common/util/concurrent/RateLimiterTest.java    |  143 +-
 .../util/concurrent/SerializingExecutorTest.java   |  112 +-
 .../common/util/concurrent/ServiceManagerTest.java |   24 +-
 .../google/common/util/concurrent/ServiceTest.java |    4 +-
 .../common/util/concurrent/SettableFutureTest.java |  151 ++
 .../util/concurrent/SupplementalMonitorTest.java   |  145 ++
 .../util/concurrent/SuppressUnderAndroid.java      |   42 +
 .../common/util/concurrent/TestPlatform.java       |   69 +
 .../util/concurrent/ThreadFactoryBuilderTest.java  |   11 +-
 .../util/concurrent/TrustedInputFutureTest.java    |   18 +-
 .../TrustedListenableFutureTaskTest.java           |  172 ++
 .../util/concurrent/UntrustedInputFutureTest.java  |   18 +-
 .../concurrent/WrappingExecutorServiceTest.java    |    9 +-
 .../WrappingScheduledExecutorServiceTest.java      |   23 +-
 .../com/google/common/xml/XmlEscapersTest.java     |    2 +-
 guava/pom.xml                                      |   71 +-
 guava/src/com/google/common/base/Absent.java       |   40 +-
 .../com/google/common/base/AbstractIterator.java   |   12 +-
 guava/src/com/google/common/base/Ascii.java        |    8 +-
 guava/src/com/google/common/base/CaseFormat.java   |   61 +-
 guava/src/com/google/common/base/CharMatcher.java  | 1783 +++++++++------
 guava/src/com/google/common/base/Charsets.java     |    2 +-
 guava/src/com/google/common/base/Converter.java    |   45 +-
 guava/src/com/google/common/base/Defaults.java     |    4 +-
 guava/src/com/google/common/base/Enums.java        |   21 +-
 guava/src/com/google/common/base/Equivalence.java  |   80 +-
 .../common/base/FinalizablePhantomReference.java   |    2 +-
 .../google/common/base/FinalizableReference.java   |    2 +-
 .../common/base/FinalizableReferenceQueue.java     |   31 +-
 .../common/base/FinalizableSoftReference.java      |    2 +-
 .../common/base/FinalizableWeakReference.java      |    2 +-
 guava/src/com/google/common/base/Function.java     |    7 +-
 .../google/common/base/FunctionalEquivalence.java  |   24 +-
 guava/src/com/google/common/base/Functions.java    |  101 +-
 guava/src/com/google/common/base/Joiner.java       |   46 +-
 guava/src/com/google/common/base/MoreObjects.java  |   97 +-
 guava/src/com/google/common/base/Objects.java      |   22 +-
 guava/src/com/google/common/base/Optional.java     |  102 +-
 .../google/common/base/PairwiseEquivalence.java    |    3 +-
 .../src/com/google/common/base/Preconditions.java  |   20 +-
 guava/src/com/google/common/base/Predicate.java    |    4 +-
 guava/src/com/google/common/base/Predicates.java   |  194 +-
 guava/src/com/google/common/base/Present.java      |   41 +-
 .../com/google/common/base/SmallCharMatcher.java   |   24 +-
 guava/src/com/google/common/base/Splitter.java     |  180 +-
 .../google/common/base/StandardSystemProperty.java |    5 +-
 guava/src/com/google/common/base/Stopwatch.java    |   32 +-
 guava/src/com/google/common/base/Strings.java      |   17 +-
 guava/src/com/google/common/base/Supplier.java     |    2 +-
 guava/src/com/google/common/base/Suppliers.java    |   83 +-
 guava/src/com/google/common/base/Throwables.java   |  252 +-
 guava/src/com/google/common/base/Ticker.java       |   18 +-
 guava/src/com/google/common/base/Utf8.java         |   24 +-
 guava/src/com/google/common/base/Verify.java       |    6 +-
 .../com/google/common/base/VerifyException.java    |   22 +-
 .../com/google/common/base/internal/Finalizer.java |   43 +-
 .../src/com/google/common/cache/AbstractCache.java |    4 -
 .../google/common/cache/AbstractLoadingCache.java  |    2 -
 guava/src/com/google/common/cache/Cache.java       |    7 -
 .../src/com/google/common/cache/CacheBuilder.java  |   19 +-
 .../com/google/common/cache/CacheBuilderSpec.java  |   15 +-
 guava/src/com/google/common/cache/CacheLoader.java |   16 +-
 guava/src/com/google/common/cache/CacheStats.java  |    3 -
 .../com/google/common/cache/ForwardingCache.java   |    5 +-
 .../common/cache/ForwardingLoadingCache.java       |    5 +-
 .../src/com/google/common/cache/LoadingCache.java  |   11 +-
 guava/src/com/google/common/cache/LocalCache.java  |   95 +-
 .../src/com/google/common/cache/LongAddables.java  |    2 +-
 .../src/com/google/common/cache/RemovalCause.java  |    2 -
 .../com/google/common/cache/RemovalListener.java   |    5 +-
 .../com/google/common/cache/RemovalListeners.java  |    3 -
 .../google/common/cache/RemovalNotification.java   |   16 +-
 guava/src/com/google/common/cache/Weigher.java     |    2 -
 .../src/com/google/common/cache/package-info.java  |    2 +-
 .../com/google/common/collect/AbstractBiMap.java   |  126 +-
 .../collect/AbstractIndexedListIterator.java       |    3 +-
 .../google/common/collect/AbstractIterator.java    |    2 +-
 .../common/collect/AbstractListMultimap.java       |   28 +-
 .../common/collect/AbstractMapBasedMultimap.java   |  183 +-
 .../common/collect/AbstractMapBasedMultiset.java   |   35 +-
 .../google/common/collect/AbstractMapEntry.java    |    9 +-
 .../google/common/collect/AbstractMultimap.java    |   58 +-
 .../google/common/collect/AbstractMultiset.java    |   57 +-
 .../common/collect/AbstractNavigableMap.java       |   34 +-
 .../google/common/collect/AbstractRangeSet.java    |    2 +-
 .../common/collect/AbstractSequentialIterator.java |    5 +-
 .../google/common/collect/AbstractSetMultimap.java |   32 +-
 .../AbstractSortedKeySortedSetMultimap.java        |    7 +-
 .../common/collect/AbstractSortedMultiset.java     |   14 +-
 .../common/collect/AbstractSortedSetMultimap.java  |   20 +-
 .../com/google/common/collect/AbstractTable.java   |   28 +-
 .../google/common/collect/ArrayListMultimap.java   |   32 +-
 .../src/com/google/common/collect/ArrayTable.java  |  105 +-
 guava/src/com/google/common/collect/BiMap.java     |    8 +-
 .../google/common/collect/BinaryTreeTraverser.java |    4 +-
 .../google/common/collect/ByFunctionOrdering.java  |   21 +-
 .../com/google/common/collect/CartesianList.java   |   10 +-
 .../google/common/collect/ClassToInstanceMap.java  |    6 +-
 .../common/collect/CollectPreconditions.java       |    6 +
 .../com/google/common/collect/Collections2.java    |  135 +-
 .../google/common/collect/ComparatorOrdering.java  |   12 +-
 .../com/google/common/collect/ComparisonChain.java |  150 +-
 .../google/common/collect/CompoundOrdering.java    |   18 +-
 .../common/collect/ComputationException.java       |    3 +-
 .../common/collect/ComputingConcurrentHashMap.java |   64 +-
 .../common/collect/ConcurrentHashMultiset.java     |   92 +-
 .../src/com/google/common/collect/Constraints.java |  122 +-
 .../common/collect/ConsumingQueueIterator.java     |   46 +
 .../com/google/common/collect/ContiguousSet.java   |   48 +-
 guava/src/com/google/common/collect/Cut.java       |  219 +-
 .../google/common/collect/DenseImmutableTable.java |   92 +-
 .../collect/DescendingImmutableSortedMultiset.java |    6 +-
 .../collect/DescendingImmutableSortedSet.java      |    5 +
 .../google/common/collect/DescendingMultiset.java  |   89 +-
 .../com/google/common/collect/DiscreteDomain.java  |   68 +-
 .../google/common/collect/EmptyContiguousSet.java  |   69 +-
 .../google/common/collect/EmptyImmutableBiMap.java |   82 -
 .../common/collect/EmptyImmutableListMultimap.java |    3 +-
 .../google/common/collect/EmptyImmutableSet.java   |   97 -
 .../common/collect/EmptyImmutableSetMultimap.java  |    3 +-
 .../common/collect/EmptyImmutableSortedMap.java    |  112 -
 .../collect/EmptyImmutableSortedMultiset.java      |  114 -
 .../common/collect/EmptyImmutableSortedSet.java    |  130 --
 guava/src/com/google/common/collect/EnumBiMap.java |   34 +-
 .../com/google/common/collect/EnumHashBiMap.java   |   34 +-
 .../com/google/common/collect/EnumMultiset.java    |   10 +-
 .../com/google/common/collect/EvictingQueue.java   |   29 +-
 .../google/common/collect/ExplicitOrdering.java    |   24 +-
 .../common/collect/FilteredEntryMultimap.java      |  101 +-
 .../common/collect/FilteredEntrySetMultimap.java   |    6 +-
 .../common/collect/FilteredKeyListMultimap.java    |    4 +-
 .../google/common/collect/FilteredKeyMultimap.java |    4 +-
 .../common/collect/FilteredKeySetMultimap.java     |    6 +-
 .../google/common/collect/FilteredMultimap.java    |    4 +-
 .../common/collect/FilteredMultimapValues.java     |   18 +-
 .../google/common/collect/FilteredSetMultimap.java |    2 +-
 .../com/google/common/collect/FluentIterable.java  |  274 ++-
 .../common/collect/ForwardingBlockingDeque.java    |    7 +-
 .../common/collect/ForwardingCollection.java       |   10 +-
 .../common/collect/ForwardingConcurrentMap.java    |    6 +-
 .../com/google/common/collect/ForwardingDeque.java |    6 +-
 .../google/common/collect/ForwardingIterator.java  |    8 +-
 .../com/google/common/collect/ForwardingList.java  |   31 +-
 .../common/collect/ForwardingListIterator.java     |    5 +-
 .../common/collect/ForwardingListMultimap.java     |   16 +-
 .../com/google/common/collect/ForwardingMap.java   |   22 +-
 .../google/common/collect/ForwardingMapEntry.java  |   19 +-
 .../google/common/collect/ForwardingMultimap.java  |   14 +-
 .../google/common/collect/ForwardingMultiset.java  |   60 +-
 .../common/collect/ForwardingNavigableMap.java     |    4 +-
 .../common/collect/ForwardingNavigableSet.java     |   14 +-
 .../google/common/collect/ForwardingObject.java    |    5 +-
 .../com/google/common/collect/ForwardingQueue.java |   14 +-
 .../com/google/common/collect/ForwardingSet.java   |   16 +-
 .../common/collect/ForwardingSetMultimap.java      |   19 +-
 .../google/common/collect/ForwardingSortedMap.java |   14 +-
 .../common/collect/ForwardingSortedMultiset.java   |   12 +-
 .../google/common/collect/ForwardingSortedSet.java |   19 +-
 .../collect/ForwardingSortedSetMultimap.java       |   20 +-
 .../com/google/common/collect/ForwardingTable.java |   12 +-
 .../com/google/common/collect/GeneralRange.java    |   80 +-
 .../com/google/common/collect/GenericMapMaker.java |    7 +-
 .../com/google/common/collect/GwtTransient.java    |    3 +-
 .../com/google/common/collect/HashBasedTable.java  |   42 +-
 guava/src/com/google/common/collect/HashBiMap.java |  279 ++-
 .../com/google/common/collect/HashMultimap.java    |   25 +-
 .../com/google/common/collect/HashMultiset.java    |   15 +-
 guava/src/com/google/common/collect/Hashing.java   |    8 +-
 .../com/google/common/collect/ImmutableAsList.java |   12 +-
 .../com/google/common/collect/ImmutableBiMap.java  |  167 +-
 .../collect/ImmutableClassToInstanceMap.java       |   62 +-
 .../google/common/collect/ImmutableCollection.java |  154 +-
 .../com/google/common/collect/ImmutableEntry.java  |   14 +-
 .../google/common/collect/ImmutableEnumMap.java    |   82 +-
 .../google/common/collect/ImmutableEnumSet.java    |   54 +-
 .../com/google/common/collect/ImmutableList.java   |  132 +-
 .../common/collect/ImmutableListMultimap.java      |  133 +-
 .../com/google/common/collect/ImmutableMap.java    |  328 ++-
 .../google/common/collect/ImmutableMapEntry.java   |   65 +-
 .../common/collect/ImmutableMapEntrySet.java       |   40 +
 .../google/common/collect/ImmutableMapKeySet.java  |   31 +-
 .../google/common/collect/ImmutableMapValues.java  |   25 +-
 .../google/common/collect/ImmutableMultimap.java   |  228 +-
 .../google/common/collect/ImmutableMultiset.java   |  188 +-
 .../google/common/collect/ImmutableRangeMap.java   |  159 +-
 .../google/common/collect/ImmutableRangeSet.java   |   77 +-
 .../com/google/common/collect/ImmutableSet.java    |  296 ++-
 .../common/collect/ImmutableSetMultimap.java       |  205 +-
 .../common/collect/ImmutableSortedAsList.java      |   17 +-
 .../google/common/collect/ImmutableSortedMap.java  |  444 ++--
 .../collect/ImmutableSortedMapFauxverideShim.java  |   24 +-
 .../common/collect/ImmutableSortedMultiset.java    |   92 +-
 .../ImmutableSortedMultisetFauxverideShim.java     |   10 +-
 .../google/common/collect/ImmutableSortedSet.java  |  133 +-
 .../collect/ImmutableSortedSetFauxverideShim.java  |   31 +-
 .../com/google/common/collect/ImmutableTable.java  |  106 +-
 guava/src/com/google/common/collect/Interners.java |   30 +-
 guava/src/com/google/common/collect/Iterables.java |  143 +-
 guava/src/com/google/common/collect/Iterators.java |  203 +-
 .../common/collect/LexicographicalOrdering.java    |   21 +-
 .../google/common/collect/LinkedHashMultimap.java  |   65 +-
 .../google/common/collect/LinkedHashMultiset.java  |   21 +-
 .../google/common/collect/LinkedListMultimap.java  |   84 +-
 .../com/google/common/collect/ListMultimap.java    |    6 +-
 guava/src/com/google/common/collect/Lists.java     |  354 ++-
 .../com/google/common/collect/MapConstraint.java   |    6 +
 .../com/google/common/collect/MapConstraints.java  |  418 ++--
 .../com/google/common/collect/MapDifference.java   |   11 +-
 guava/src/com/google/common/collect/MapMaker.java  |   48 +-
 .../google/common/collect/MapMakerInternalMap.java |  468 ++--
 guava/src/com/google/common/collect/Maps.java      |  871 ++++---
 .../google/common/collect/MinMaxPriorityQueue.java |  139 +-
 guava/src/com/google/common/collect/Multimap.java  |   32 +-
 .../com/google/common/collect/MultimapBuilder.java |   22 +-
 guava/src/com/google/common/collect/Multimaps.java |  527 +++--
 guava/src/com/google/common/collect/Multiset.java  |   22 +-
 guava/src/com/google/common/collect/Multisets.java |  279 ++-
 .../common/collect/MutableClassToInstanceMap.java  |   29 +-
 .../com/google/common/collect/NaturalOrdering.java |   12 +-
 .../google/common/collect/NullsFirstOrdering.java  |   21 +-
 .../google/common/collect/NullsLastOrdering.java   |   21 +-
 .../com/google/common/collect/ObjectArrays.java    |    9 +-
 guava/src/com/google/common/collect/Ordering.java  |  124 +-
 .../com/google/common/collect/PeekingIterator.java |    6 +-
 guava/src/com/google/common/collect/Platform.java  |   24 +-
 guava/src/com/google/common/collect/Queues.java    |   31 +-
 guava/src/com/google/common/collect/Range.java     |  103 +-
 guava/src/com/google/common/collect/RangeMap.java  |   30 +-
 guava/src/com/google/common/collect/RangeSet.java  |   28 +-
 .../common/collect/RegularContiguousSet.java       |   72 +-
 .../common/collect/RegularImmutableAsList.java     |    5 +-
 .../common/collect/RegularImmutableBiMap.java      |  248 +-
 .../common/collect/RegularImmutableList.java       |   44 +-
 .../google/common/collect/RegularImmutableMap.java |  160 +-
 .../common/collect/RegularImmutableMultiset.java   |  150 +-
 .../google/common/collect/RegularImmutableSet.java |   32 +-
 .../common/collect/RegularImmutableSortedMap.java  |  130 --
 .../collect/RegularImmutableSortedMultiset.java    |   41 +-
 .../common/collect/RegularImmutableSortedSet.java  |   74 +-
 .../common/collect/RegularImmutableTable.java      |  109 +-
 .../common/collect/ReverseNaturalOrdering.java     |   36 +-
 .../com/google/common/collect/ReverseOrdering.java |   39 +-
 .../com/google/common/collect/RowSortedTable.java  |    6 +-
 .../com/google/common/collect/Serialization.java   |   27 +-
 .../src/com/google/common/collect/SetMultimap.java |   12 +-
 guava/src/com/google/common/collect/Sets.java      |  425 ++--
 .../common/collect/SingletonImmutableBiMap.java    |   22 +-
 .../common/collect/SingletonImmutableList.java     |   59 +-
 .../common/collect/SingletonImmutableSet.java      |   37 +-
 .../common/collect/SingletonImmutableTable.java    |   24 +-
 .../src/com/google/common/collect/SortedLists.java |   34 +-
 .../com/google/common/collect/SortedMultiset.java  |   39 +-
 .../common/collect/SortedMultisetBridge.java       |    2 +-
 .../com/google/common/collect/SortedMultisets.java |   37 +-
 .../google/common/collect/SortedSetMultimap.java   |    9 +-
 .../common/collect/SparseImmutableTable.java       |   35 +-
 .../common/collect/StandardRowSortedTable.java     |   24 +-
 .../com/google/common/collect/StandardTable.java   |  417 ++--
 .../com/google/common/collect/Synchronized.java    |  535 +++--
 guava/src/com/google/common/collect/Table.java     |    9 +-
 guava/src/com/google/common/collect/Tables.java    |  113 +-
 .../com/google/common/collect/TreeBasedTable.java  |  101 +-
 .../com/google/common/collect/TreeMultimap.java    |   46 +-
 .../com/google/common/collect/TreeMultiset.java    |   59 +-
 .../com/google/common/collect/TreeRangeMap.java    |  206 +-
 .../com/google/common/collect/TreeRangeSet.java    |  182 +-
 .../com/google/common/collect/TreeTraverser.java   |    2 +-
 .../common/collect/UnmodifiableIterator.java       |    6 +-
 .../common/collect/UnmodifiableListIterator.java   |   12 +-
 .../common/collect/UnmodifiableSortedMultiset.java |   24 +-
 .../common/collect/UsingToStringOrdering.java      |    9 +-
 .../com/google/common/collect/WellBehavedMap.java  |    8 +-
 .../src/com/google/common/escape/CharEscaper.java  |    6 +-
 guava/src/com/google/common/escape/Escaper.java    |    8 +-
 .../com/google/common/escape/UnicodeEscaper.java   |    7 +-
 .../common/eventbus/AnnotatedSubscriberFinder.java |  169 --
 .../com/google/common/eventbus/AsyncEventBus.java  |   55 +-
 .../src/com/google/common/eventbus/DeadEvent.java  |    8 +
 .../src/com/google/common/eventbus/Dispatcher.java |  207 ++
 guava/src/com/google/common/eventbus/EventBus.java |  318 +--
 .../google/common/eventbus/EventSubscriber.java    |  115 -
 .../src/com/google/common/eventbus/Subscriber.java |  158 ++
 .../common/eventbus/SubscriberFindingStrategy.java |   42 -
 .../google/common/eventbus/SubscriberRegistry.java |  259 +++
 .../eventbus/SynchronizedEventSubscriber.java      |   50 -
 .../com/google/common/eventbus/package-info.java   |    2 +-
 .../com/google/common/hash/AbstractByteHasher.java |    1 -
 .../common/hash/AbstractCompositeHashFunction.java |   42 +-
 .../src/com/google/common/hash/AbstractHasher.java |   15 +-
 .../hash/AbstractNonStreamingHashFunction.java     |   22 +-
 .../common/hash/AbstractStreamingHashFunction.java |   39 +-
 guava/src/com/google/common/hash/BloomFilter.java  |  137 +-
 .../google/common/hash/BloomFilterStrategies.java  |   31 +-
 .../google/common/hash/ChecksumHashFunction.java   |    2 -
 .../com/google/common/hash/Crc32cHashFunction.java |    1 -
 guava/src/com/google/common/hash/Funnels.java      |   69 +-
 guava/src/com/google/common/hash/HashCode.java     |   85 +-
 guava/src/com/google/common/hash/Hasher.java       |   55 +-
 guava/src/com/google/common/hash/Hashing.java      |  162 +-
 .../com/google/common/hash/HashingInputStream.java |    4 +
 .../google/common/hash/HashingOutputStream.java    |   12 +-
 .../common/hash/MessageDigestHashFunction.java     |   14 +-
 .../common/hash/Murmur3_128HashFunction.java       |   27 +-
 .../google/common/hash/Murmur3_32HashFunction.java |   26 +-
 .../com/google/common/hash/SipHashFunction.java    |   28 +-
 guava/src/com/google/common/hash/package-info.java |    2 +-
 guava/src/com/google/common/html/HtmlEscapers.java |    3 +
 guava/src/com/google/common/io/BaseEncoding.java   |  336 ++-
 .../com/google/common/io/ByteArrayDataInput.java   |    2 +-
 guava/src/com/google/common/io/ByteSource.java     |  188 +-
 guava/src/com/google/common/io/ByteStreams.java    |  117 +-
 .../com/google/common/io/CharSequenceReader.java   |    2 +-
 guava/src/com/google/common/io/CharSource.java     |  113 +-
 guava/src/com/google/common/io/CharStreams.java    |   11 +-
 .../com/google/common/io/CountingInputStream.java  |    8 +-
 .../com/google/common/io/CountingOutputStream.java |    8 +-
 guava/src/com/google/common/io/Files.java          |   10 +
 guava/src/com/google/common/io/GwtWorkarounds.java |  231 --
 guava/src/com/google/common/io/package-info.java   |    2 +-
 guava/src/com/google/common/math/DoubleMath.java   |  143 +-
 guava/src/com/google/common/math/LongMath.java     |  186 +-
 guava/src/com/google/common/math/package-info.java |    2 +-
 guava/src/com/google/common/net/HttpHeaders.java   |   14 +
 guava/src/com/google/common/net/InetAddresses.java |   17 +-
 guava/src/com/google/common/net/MediaType.java     |   48 +-
 .../src/com/google/common/primitives/Booleans.java |   60 +-
 guava/src/com/google/common/primitives/Bytes.java  |   51 +-
 guava/src/com/google/common/primitives/Chars.java  |   58 +-
 .../src/com/google/common/primitives/Doubles.java  |   59 +-
 guava/src/com/google/common/primitives/Floats.java |   64 +-
 guava/src/com/google/common/primitives/Ints.java   |  130 +-
 guava/src/com/google/common/primitives/Longs.java  |  132 +-
 .../com/google/common/primitives/ParseRequest.java |    3 +
 .../com/google/common/primitives/Primitives.java   |   12 +-
 guava/src/com/google/common/primitives/Shorts.java |   63 +-
 .../com/google/common/primitives/SignedBytes.java  |   11 +-
 .../google/common/primitives/UnsignedBytes.java    |   83 +-
 .../google/common/primitives/UnsignedInteger.java  |   22 +-
 .../com/google/common/primitives/UnsignedInts.java |   22 +-
 .../com/google/common/primitives/UnsignedLong.java |   21 +-
 .../google/common/primitives/UnsignedLongs.java    |   24 +-
 .../com/google/common/primitives/package-info.java |    2 +-
 guava/src/com/google/common/reflect/ClassPath.java |  270 ++-
 guava/src/com/google/common/reflect/Invokable.java |    2 +-
 .../com/google/common/reflect/TypeResolver.java    |    5 +
 guava/src/com/google/common/reflect/TypeToken.java |  411 ++--
 guava/src/com/google/common/reflect/Types.java     |   96 +-
 .../concurrent/AbstractExecutionThreadService.java |   14 +-
 .../common/util/concurrent/AbstractFuture.java     | 1104 +++++++--
 .../util/concurrent/AbstractIdleService.java       |   22 +-
 .../AbstractListeningExecutorService.java          |   17 +-
 .../util/concurrent/AbstractScheduledService.java  |   98 +-
 .../common/util/concurrent/AbstractService.java    |  131 +-
 .../common/util/concurrent/AggregateFuture.java    |  300 +++
 .../util/concurrent/AggregateFutureState.java      |   99 +
 .../common/util/concurrent/AsyncFunction.java      |   10 +-
 .../util/concurrent/AsyncSettableFuture.java       |  100 -
 .../common/util/concurrent/AtomicLongMap.java      |    9 +-
 .../google/common/util/concurrent/Callables.java   |    6 +
 .../common/util/concurrent/CheckedFuture.java      |   16 +-
 .../common/util/concurrent/CollectionFuture.java   |   90 +
 .../util/concurrent/CycleDetectingLockFactory.java |   15 +-
 .../common/util/concurrent/ExecutionList.java      |  101 +-
 .../common/util/concurrent/FutureCallback.java     |    3 +
 .../common/util/concurrent/FutureFallback.java     |   26 +-
 .../com/google/common/util/concurrent/Futures.java | 1573 ++++++++-----
 .../common/util/concurrent/FuturesGetChecked.java  |  309 +++
 .../GwtFuturesCatchingSpecialization.java          |   33 +
 .../common/util/concurrent/InterruptibleTask.java  |   71 +
 .../common/util/concurrent/JdkFutureAdapters.java  |    7 +-
 .../common/util/concurrent/ListenableFuture.java   |   49 +-
 .../com/google/common/util/concurrent/Monitor.java |  191 +-
 .../common/util/concurrent/MoreExecutors.java      |  142 +-
 .../concurrent/Platform.java}                      |   22 +-
 .../google/common/util/concurrent/RateLimiter.java |   15 +-
 .../util/concurrent/SerializingExecutor.java       |  208 +-
 .../common/util/concurrent/ServiceManager.java     |   51 +-
 .../common/util/concurrent/SettableFuture.java     |   41 +-
 .../common/util/concurrent/SmoothRateLimiter.java  |  161 +-
 .../com/google/common/util/concurrent/Striped.java |   10 +-
 .../util/concurrent/ThreadFactoryBuilder.java      |   10 +-
 .../concurrent/TrustedListenableFutureTask.java    |  119 +
 .../util/concurrent/UncaughtExceptionHandlers.java |    4 +-
 .../common/util/concurrent/Uninterruptibles.java   |   23 +-
 .../util/concurrent/WrappingExecutorService.java   |    2 +-
 .../publicsuffix/PublicSuffixPatterns.java         |    6 +-
 mvn-deploy.sh                                      |   40 -
 pom.xml                                            |   99 +-
 util/deploy_snapshot.sh                            |   16 +
 util/settings.xml                                  |   11 +
 util/update_snapshot_docs.sh                       |   25 +
 1008 files changed, 45114 insertions(+), 21927 deletions(-)

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1e3b765
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Known text files
+*.java text
+*.xml text
+*.yml text
+*.md text
+*.sh text
+*.css text
+*.txt text
+
+# Known binary files
+*.jar binary
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 4265c9b..ea9f52f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,4 @@ out/
 .classpath
 .project
 .settings/
-.metadata/
+.metadata/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..43de008
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,30 @@
+sudo: false
+
+language: java
+
+jdk:
+  - oraclejdk8
+  - oraclejdk7
+  - openjdk7
+
+install: mvn install -U -DskipTests=true
+
+script: mvn verify -U -Dmaven.javadoc.skip=true
+
+after_success:
+  - util/deploy_snapshot.sh
+  - util/update_snapshot_docs.sh
+
+cache:
+  directories:
+  - $HOME/.m2
+
+env:
+  global:
+    - secure: "IPvqFwnLx/GXyImJuwM2MIvzDlBLqEXaQXFGJgAP1nbuenaLAloOOlqQ+iy2FDLBD/j+zjSbR3WWF9DIT4YxAS03Z6iMwxh7GCfk+tyhVtLQnwt7w1rquyhbrrGFsY5U0hr5q80Ww6J+zfp2yZ8aP9FHSy5ahNjqys4FtubOWLk="
+    - secure: "G77Wt2h2fceQ867i1uwOjUygrNeBpLRS8sxgfUZsO66dvlrx1wYFpZLLRIiPcy01peUTE2SvXIXLHKe9v3AlMonPibsQtvvfQSVfx+jgKwLZx9cuf/M5VQlD3etRUh4K/rBezlxWRroeeKcM2DQqiEVLsTDSyNZV9kVAjwfLTvM="
+    - secure: "wieIClPLTXS3QjDzqyp0TqIrVP/Q6iWNPOtcUQYfdDZJGwufE61laTFtzVKXZRb7uJ4GXDObcVU3AcpAwkTX/5sEksBxgv3TZ5Qi0mVx2GRmbE06ULLxi7sPnTCZ/VFtselDWcWArWGAcdCjW9gcCrgj5K/+sYpVKz9a8V+SDM4="
+
+branches:
+  except:
+    - gh-pages
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 324fd82..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,7 +0,0 @@
-Google Inc.
-Colin Decker
-Emily Soldal
-Louis Wasserman
-Maginatics
-Roman Leventov
-David E. Wheeler
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f1d6529
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,86 @@
+How to contribute
+=================
+
+Thank you so much for wanting to contribute to Guava! Here are a few important
+things you should know about contributing:
+
+  1. API changes require discussion, use cases, etc. Code comes later.
+  2. Pull requests are great for small fixes for bugs, documentation, etc.
+  3. Pull requests are not merged directly into the master branch.
+  3. Code contributions require signing a Google CLA.
+
+API changes
+-----------
+
+We make changes to Guava's public [APIs][], including adding new APIs, very
+carefully. Because of this, if you're interested in seeing a new feature in
+Guava, the best approach is to create an [issue][] (or comment on an existing
+issue if there is one) requesting the feature and describing specific use cases
+for it.
+
+If the feature has merit, it will go through a thorough process of API design
+and review. Any code should come after this.
+
+[APIs]: http://en.wikipedia.org/wiki/Application_programming_interface
+[issue]: https://github.com/google/guava/issues
+
+Pull requests
+-------------
+
+Unless the change is a trivial fix such as for a typo, it's generally best to
+start by opening a new issue describing the bug or feature you're intending to
+fix. Even if you think it's relatively minor, it's helpful to know what people
+are working on. And as mentioned above, API changes should be discussed
+thoroughly before moving to code.
+
+Some examples of types of pull requests that are immediately helpful:
+
+  - Fixing a bug without changing a public API.
+  - Fixing or improving documentation.
+  - Improvements to Maven configuration.
+
+Guidelines for any code contributions:
+
+  1. Any significant changes should be accompanied by tests. The project already
+     has good test coverage, so look at some of the existing tests if you're
+     unsure how to go about it.
+  2. All contributions must be licensed Apache 2.0 and all files must have a
+     copy of the boilerplate licence comment (can be copied from an existing
+     file).
+  3. Files should be formatted according to Google's [Java style guide][].
+  4. Please squash all commits for a change into a single commit (this can be
+     done using `git rebase -i`). Do your best to have a
+     [well-formed commit message][] for the change.
+
+[Java style guide]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html
+[well-formed commit message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+
+#### Merging pull requests ####
+
+Due to Guava's nature as a subset of Google's internal codebase which is
+automatically synced to the public GitHub repository, we are unable to merge
+pull requests directly into the master branch. Instead, once a pull request is
+ready for merging, we'll make the appropriate changes in the internal codebase
+and, when the change is synced out, give the pull request author credit for the
+commit.
+
+Contributor License Agreement
+-----------------------------
+
+Contributions to any Google project must be accompanied by a Contributor
+License Agreement. This is not a copyright _assignment_; it simply gives
+Google permission to use and redistribute your contributions as part of the
+project.
+
+  - If you are an individual writing original source code and you're sure you
+    own the intellectual property, then you'll need to sign an [individual
+    CLA][]. Please include your GitHub username.
+  - If you work for a company that wants to allow you to contribute your work,
+    then you'll need to sign a [corporate CLA][].
+
+You generally only need to submit a CLA once, so if you've already submitted
+one (even if it was for a different project), you probably don't need to do it
+again.
+
+[individual CLA]: https://cla.developers.google.com/about/google-individual
+[corporate CLA]: https://developers.google.com/open-source/cla/corporate
diff --git a/README b/README
deleted file mode 100644
index f6b5992..0000000
--- a/README
+++ /dev/null
@@ -1,46 +0,0 @@
-Guava: Google Core Libraries for Java
-=====================================
-
-Requires JDK 1.6 or higher (as of 12.0).
-
-Project page:
-  http://guava-libraries.googlecode.com
-
-Report a defect or feature request here:
-  http://code.google.com/p/guava-libraries/issues/entry
-
-Ask "how-to" and "why-didn't-it-work" questions at:
-  http://www.stackoverflow.com/questions/ask (use the "guava" tag)
-
-For open-ended questions and discussion:
-  http://groups.google.com/group/guava-discuss
-
-Subscribe to project updates in your feed reader:
-  http://code.google.com/feeds/p/guava-libraries/updates/basic
-
-IMPORTANT WARNINGS
-------------------
-
-1. APIs marked with the @Beta annotation at the class or method level
-are subject to change. They can be modified in any way, or even
-removed, at any time. If your code is a library itself (i.e. it is
-used on the CLASSPATH of users outside your own control), you should
-not use beta APIs, unless you repackage them (e.g. using ProGuard).
-
-2. Deprecated non-beta APIs will be removed two years after the
-release in which they are first deprecated. You must fix your
-references before this time. If you don't, any manner of breakage
-could result (you are not guaranteed a compilation error).
-
-3. Serialized forms of ALL objects are subject to change unless noted
-otherwise. Do not persist these and assume they can be read by a
-future version of the library.
-
-4. Our classes are not designed to protect against a malicious caller.
-You should not use them for communication between trusted and
-untrusted code.
-
-5. We unit-test and benchmark the libraries using only OpenJDK 1.7 on
-Linux. Some features, especially in com.google.common.io, may not work
-correctly in other environments.
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fb57053
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+Guava: Google Core Libraries for Java
+=====================================
+
+[![Build Status](https://travis-ci.org/google/guava.svg?branch=master)](https://travis-ci.org/google/guava)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.google.guava/guava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.google.guava/guava)
+
+The Guava project contains several of Google's core libraries that we rely on
+in our Java-based projects: collections, caching, primitives support,
+concurrency libraries, common annotations, string processing, I/O, and so forth.
+
+Requires JDK 1.6 or higher (as of 12.0).
+
+Latest release
+--------------
+
+The most recent release is [Guava 18.0][], released August 25, 2014.
+
+- [18.0 API Docs][Release API Docs]
+- [18.0 API Diffs from 17.0][Release API Diffs]
+
+To add a dependency on Guava using Maven, use the following:
+
+```xml
+<dependency>
+  <groupId>com.google.guava</groupId>
+  <artifactId>guava</artifactId>
+  <version>18.0</version>
+</dependency>
+```
+
+Upcoming release
+----------------
+
+[Guava 19.0][] is the next release. A release candidate is currently available
+on Maven Central as version `19.0-rc1`, release July 23, 2015.
+
+Snapshots
+---------
+
+Snapshots of Guava built from the `master` branch are available through Maven
+using version `19.0-SNAPSHOT`. API documentation and diffs from version 18.0
+are available here:
+
+- [Snapshot API Docs][]
+- [Snapshot API Diffs from 18.0][Snapshot API Diffs]
+
+Learn about Guava
+------------------
+
+- Our users' guide, [Guava Explained][]
+- [Presentation slides focusing on base, primitives, and io](http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf)
+- [Presentation slides focusing on cache]( http://guava-libraries.googlecode.com/files/JavaCachingwithGuava.pdf)
+- [Presentation slides focusing on util.concurrent](http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf)
+- [A nice collection](http://www.tfnico.com/presentations/google-guava) of other helpful links
+
+Links
+-----
+
+- [GitHub project](https://github.com/google/guava)
+- [Issue tracker: report a defect or feature request](https://github.com/google/guava/issues/new)
+- [StackOverflow: Ask "how-to" and "why-didn't-it-work" questions](https://stackoverflow.com/questions/ask?tags=guava+java)
+- [guava-discuss: For open-ended questions and discussion](http://groups.google.com/group/guava-discuss)
+
+IMPORTANT WARNINGS
+------------------
+
+1. APIs marked with the `@Beta` annotation at the class or method level
+are subject to change. They can be modified in any way, or even
+removed, at any time. If your code is a library itself (i.e. it is
+used on the CLASSPATH of users outside your own control), you should
+not use beta APIs, unless you repackage them (e.g. using ProGuard).
+
+2. Deprecated non-beta APIs will be removed two years after the
+release in which they are first deprecated. You must fix your
+references before this time. If you don't, any manner of breakage
+could result (you are not guaranteed a compilation error).
+
+3. Serialized forms of ALL objects are subject to change unless noted
+otherwise. Do not persist these and assume they can be read by a
+future version of the library.
+
+4. Our classes are not designed to protect against a malicious caller.
+You should not use them for communication between trusted and
+untrusted code.
+
+5. We unit-test and benchmark the libraries using only OpenJDK 1.7 on
+Linux. Some features, especially in `com.google.common.io`, may not work
+correctly in other environments.
+
+[Guava 18.0]: https://github.com/google/guava/wiki/Release18
+[Guava 19.0]: https://github.com/google/guava/wiki/Release19
+[Release API Docs]: http://google.github.io/guava/releases/18.0/api/docs/
+[Release API Diffs]: http://google.github.io/guava/releases/18.0/api/diffs/
+[Snapshot API Docs]: http://google.github.io/guava/releases/snapshot/api/docs/
+[Snapshot API Diffs]: http://google.github.io/guava/releases/snapshot/api/diffs/
+[Guava Explained]: https://github.com/google/guava/wiki/Home
diff --git a/guava-gwt/pom.xml b/guava-gwt/pom.xml
index f98a731..34c3013 100644
--- a/guava-gwt/pom.xml
+++ b/guava-gwt/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>com.google.guava</groupId>
     <artifactId>guava-parent</artifactId>
-    <version>18.0</version>
+    <version>19.0</version>
   </parent>
   <artifactId>guava-gwt</artifactId>
   <name>Guava GWT compatible libs</name>
@@ -19,6 +19,7 @@
   <properties>
     <gwt.test.include>**/GwtTestSuite.java</gwt.test.include>
     <gwt.version>2.6.1</gwt.version>
+    <gwt.logLevel>WARN</gwt.logLevel>
   </properties>
   <dependencies>
     <!-- GWT requires a library's transitive dependencies to be present when
@@ -30,6 +31,17 @@
       <optional>false</optional>
     </dependency>
     <dependency>
+      <groupId>com.google.errorprone</groupId>
+      <artifactId>error_prone_annotations</artifactId>
+      <optional>false</optional>
+    </dependency>
+    <dependency>
+      <groupId>com.google.j2objc</groupId>
+      <artifactId>j2objc-annotations</artifactId>
+      <optional>false</optional>
+    </dependency>
+
+    <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <version>${project.version}</version>
@@ -51,7 +63,7 @@
       <groupId>com.google.guava</groupId>
       <artifactId>guava-tests</artifactId>
       <version>${project.version}</version>
-      <classifier>tests</classifier> 
+      <classifier>tests</classifier>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -105,7 +117,6 @@
             <configuration>
               <includeArtifactIds>guava</includeArtifactIds>
               <classifier>sources</classifier>
-              <overWrite>true</overWrite>
               <excludeTransitive>true</excludeTransitive>
               <excludes>META-INF/MANIFEST.MF</excludes>
               <outputDirectory>${project.build.directory}/guava-sources</outputDirectory>
@@ -120,7 +131,6 @@
             <configuration>
               <includeArtifactIds>guava-testlib</includeArtifactIds>
               <classifier>sources</classifier>
-              <overWrite>true</overWrite>
               <excludeTransitive>true</excludeTransitive>
               <excludes>META-INF/MANIFEST.MF</excludes>
               <outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -135,7 +145,6 @@
             <configuration>
               <includeArtifactIds>guava-testlib</includeArtifactIds>
               <classifier>test-sources</classifier>
-              <overWrite>true</overWrite>
               <excludeTransitive>true</excludeTransitive>
               <excludes>META-INF/MANIFEST.MF</excludes>
               <outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -150,7 +159,6 @@
             <configuration>
               <includeArtifactIds>guava-tests</includeArtifactIds>
               <classifier>test-sources</classifier>
-              <overWrite>true</overWrite>
               <excludeTransitive>true</excludeTransitive>
               <excludes>META-INF/MANIFEST.MF</excludes>
               <outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -190,6 +198,7 @@
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
           <execution>
+            <id>copy-gwt-files</id>
             <phase>generate-resources</phase>
             <goals><goal>run</goal></goals>
             <configuration>
@@ -229,10 +238,45 @@
             </goals>
             <configuration>
               <module>com.google.common.ForceGuavaCompilation</module>
-              <strict>true</strict>
+              <failOnError>true</failOnError>
+              <logLevel>${gwt.logLevel}</logLevel>
               <validateOnly>true</validateOnly>
+              <sourceLevel>1.6</sourceLevel>
             </configuration>
           </execution>
+          <!--
+            GWT issues some scary warnings while running tests, but I believe they are harmless.
+            Let's take the warnings for one module, c.g.c.base.testModule, as an example:
+
+              [INFO] Validating units:
+              [INFO]    Ignored 53 units with compilation errors in first pass.
+              [INFO] Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
+
+            Turning up the log level, we see that GWT is trying to compile classes from other
+            packages, like RangeTest. The reason for this is that GWT doesn't distinguish between
+            .java files in c.g.c.collect.Collect, a module that the c.g.c.base test module inherits,
+            and .java files in c.g.c.collect.testModule, one that it doesn't[*]. Consequently,
+            c.g.c.base.testModule transitively pulls in .java files from both modules while reading
+            the module description of only the prod module. And the prod module doesn't inherit all
+            the modules that the test module classes use, so we get errors.
+
+            The good news is that, despite ignoring errors here, GWT does fail if any errors affect
+            classes that are actually used in the module under test.
+
+            One way to eliminate the warnings is to make base.testModule include the not really
+            necessary <inherits> lines for c.g.c.collect.testModule, etc. However, adding <inherits>
+            lines could make c.g.c.base.testModule transitively inherit from extra modules. If some
+            of those modules are ones that it uses but forgets to list in its own <inherits>, we'd
+            like to get an error. Currently we do, but if we add the extra <inherits> lines, we
+            won't.
+
+            I have one idea for a better approach, but it's painful, and I haven't tested it: We
+            could postprocess Collect.gwt.xml to add <skip> lines for all the files that should be
+            covered by testModule.gwt.xml. Maybe I'll try it someday.
+
+            [*] https://code.google.com/p/google-web-toolkit/wiki/ResourceOracle#When_multiple_PathPrefix_es_have_the_same_path
+                https://code.google.com/p/google-web-toolkit/issues/detail?id=7581
+            -->
           <execution>
             <id>gwt-test</id>
             <goals>
@@ -240,11 +284,12 @@
             </goals>
             <configuration>
               <module>com.google.common.GuavaTests</module>
-              <strict>true</strict>
               <includes>${gwt.test.include}</includes>
+              <logLevel>${gwt.logLevel}</logLevel>
               <mode>htmlunit</mode>
               <testTimeOut>600</testTimeOut>
               <extraJvmArgs>-Xms3500m -Xmx3500m -Xss1024k</extraJvmArgs>
+              <sourceLevel>1.6</sourceLevel>
             </configuration>
           </execution>
         </executions>
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
index e3c0b04..7ebbef5 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
@@ -18,9 +18,11 @@ package com.google.common.base;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndex;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.VisibleForTesting;
 
 import java.util.Arrays;
 
@@ -40,11 +42,11 @@ import javax.annotation.CheckReturnValue;
  * treats these just as two separate characters.
  *
  * <p>Example usages: <pre>
- *   String trimmed = {@link #WHITESPACE WHITESPACE}.{@link #trimFrom trimFrom}(userInput);
- *   if ({@link #ASCII ASCII}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
+ *   String trimmed = {@link #whitespace() whitespace()}.{@link #trimFrom trimFrom}(userInput);
+ *   if ({@link #ascii() ascii()}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher">
+ * "https://github.com/google/guava/wiki/StringsExplained#charmatcher">
  * {@code CharMatcher}</a>.
  *
  * @author Kevin Bourrillion
@@ -54,184 +56,144 @@ import javax.annotation.CheckReturnValue;
 @GwtCompatible(emulated = true)
 public abstract class CharMatcher implements Predicate<Character> {
 
-  // Constants
+  // Constant matcher factory methods
+
   /**
-   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
-   * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
-   * discussion of that term.
+   * Matches any character.
    *
-   * @since 2.0
+   * @since 19.0 (since 1.0 as constant {@code ANY})
    */
-  public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() {
-    @Override
-    public boolean matches(char c) {
-      switch (c) {
-        case '\t':
-        case '\n':
-        case '\013':
-        case '\f':
-        case '\r':
-        case ' ':
-        case '\u0085':
-        case '\u1680':
-        case '\u2028':
-        case '\u2029':
-        case '\u205f':
-        case '\u3000':
-          return true;
-        case '\u2007':
-          return false;
-        default:
-          return c >= '\u2000' && c <= '\u200a';
-      }
-    }
-
-    @Override
-    public String toString() {
-      return "CharMatcher.BREAKING_WHITESPACE";
-    }
-  };
+  public static CharMatcher any() {
+    return Any.INSTANCE;
+  }
 
   /**
-   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   * Matches no characters.
+   *
+   * @since 19.0 (since 1.0 as constant {@code NONE})
    */
-  public static final CharMatcher ASCII = inRange('\0', '\u007f', "CharMatcher.ASCII");
-
-  private static class RangesMatcher extends CharMatcher {
-    private final char[] rangeStarts;
-    private final char[] rangeEnds;
-
-    RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
-      super(description);
-      this.rangeStarts = rangeStarts;
-      this.rangeEnds = rangeEnds;
-      checkArgument(rangeStarts.length == rangeEnds.length);
-      for (int i = 0; i < rangeStarts.length; i++) {
-        checkArgument(rangeStarts[i] <= rangeEnds[i]);
-        if (i + 1 < rangeStarts.length) {
-          checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
-        }
-      }
-    }
+  public static CharMatcher none() {
+    return None.INSTANCE;
+  }
 
-    @Override
-    public boolean matches(char c) {
-      int index = Arrays.binarySearch(rangeStarts, c);
-      if (index >= 0) {
-        return true;
-      } else {
-        index = ~index - 1;
-        return index >= 0 && c <= rangeEnds[index];
-      }
-    }
+  /**
+   * Determines whether a character is whitespace according to the latest Unicode standard, as
+   * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+   * This is not the same definition used by other Java APIs. (See a <a
+   * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+   * definitions of "whitespace"</a>.)
+   *
+   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this matcher to keep it up
+   * to date.
+   *
+   * @since 19.0 (since 1.0 as constant {@code WHITESPACE})
+   */
+  public static CharMatcher whitespace() {
+    return Whitespace.INSTANCE;
   }
 
-  // Must be in ascending order.
-  private static final String ZEROES = "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6"
-      + "\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1b50\u1bb0"
-      + "\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+  /**
+   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+   * interpreted as a break between words for formatting purposes). See {@link #whitespace()} for a
+   * discussion of that term.
+   *
+   * @since 19.0 (since 2.0 as constant {@code BREAKING_WHITESPACE})
+   */
+  public static CharMatcher breakingWhitespace() {
+    return BreakingWhitespace.INSTANCE;
+  }
 
-  private static final String NINES;
-  static {
-    StringBuilder builder = new StringBuilder(ZEROES.length());
-    for (int i = 0; i < ZEROES.length(); i++) {
-      builder.append((char) (ZEROES.charAt(i) + 9));
-    }
-    NINES = builder.toString();
+  /**
+   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   *
+   * @since 19.0 (since 1.0 as constant {@code ASCII})
+   */
+  public static CharMatcher ascii() {
+    return Ascii.INSTANCE;
   }
 
   /**
    * Determines whether a character is a digit according to
    * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
    * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code DIGIT})
    */
-  public static final CharMatcher DIGIT = new RangesMatcher(
-      "CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray());
+  public static CharMatcher digit() {
+    return Digit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
-   * Java's definition}. If you only care to match ASCII digits, you can use {@code
-   * inRange('0', '9')}.
+   * Java's definition}. If you only care to match ASCII digits, you can use {@code inRange('0',
+   * '9')}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_DIGIT})
    */
-  public static final CharMatcher JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") {
-    @Override public boolean matches(char c) {
-      return Character.isDigit(c);
-    }
-  };
+  public static CharMatcher javaDigit() {
+    return JavaDigit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
    * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
    * inRange('a', 'z').or(inRange('A', 'Z'))}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER})
    */
-  public static final CharMatcher JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") {
-    @Override public boolean matches(char c) {
-      return Character.isLetter(c);
-    }
-  };
+  public static CharMatcher javaLetter() {
+    return JavaLetter.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a letter or digit according to {@linkplain
    * Character#isLetterOrDigit(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER_OR_DIGIT}).
    */
-  public static final CharMatcher JAVA_LETTER_OR_DIGIT =
-      new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") {
-    @Override public boolean matches(char c) {
-      return Character.isLetterOrDigit(c);
-    }
-  };
+  public static CharMatcher javaLetterOrDigit() {
+    return JavaLetterOrDigit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is upper case according to {@linkplain
    * Character#isUpperCase(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_UPPER_CASE})
    */
-  public static final CharMatcher JAVA_UPPER_CASE =
-      new CharMatcher("CharMatcher.JAVA_UPPER_CASE") {
-    @Override public boolean matches(char c) {
-      return Character.isUpperCase(c);
-    }
-  };
+  public static CharMatcher javaUpperCase() {
+    return JavaUpperCase.INSTANCE;
+  }
 
   /**
    * Determines whether a character is lower case according to {@linkplain
    * Character#isLowerCase(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LOWER_CASE})
    */
-  public static final CharMatcher JAVA_LOWER_CASE =
-      new CharMatcher("CharMatcher.JAVA_LOWER_CASE") {
-    @Override public boolean matches(char c) {
-      return Character.isLowerCase(c);
-    }
-  };
+  public static CharMatcher javaLowerCase() {
+    return JavaLowerCase.INSTANCE;
+  }
 
   /**
    * Determines whether a character is an ISO control character as specified by {@link
    * Character#isISOControl(char)}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_ISO_CONTROL})
    */
-  public static final CharMatcher JAVA_ISO_CONTROL =
-      inRange('\u0000', '\u001f')
-      .or(inRange('\u007f', '\u009f'))
-      .withToString("CharMatcher.JAVA_ISO_CONTROL");
+  public static CharMatcher javaIsoControl() {
+    return JavaIsoControl.INSTANCE;
+  }
 
   /**
    * Determines whether a character is invisible; that is, if its Unicode category is any of
    * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
    * PRIVATE_USE according to ICU4J.
+   *
+   * @since 19.0 (since 1.0 as constant {@code INVISIBLE})
    */
-  public static final CharMatcher INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", (
-      "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067\u2068"
-      + "\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa").toCharArray(), (
-      "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067\u2068"
-      + "\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb").toCharArray());
-
-  private static String showCharacter(char c) {
-    String hex = "0123456789ABCDEF";
-    char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
-    for (int i = 0; i < 4; i++) {
-      tmp[5 - i] = hex.charAt(c & 0xF);
-      c >>= 4;
-    }
-    return String.copyValueOf(tmp);
-
+  public static CharMatcher invisible() {
+    return Invisible.INSTANCE;
   }
 
   /**
@@ -239,170 +201,111 @@ public abstract class CharMatcher implements Predicate<Character> {
    * errs on the side of returning {@code false} (that is, it tends to assume a character is
    * double-width).
    *
-   * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+   * <p><b>Note:</b> as the reference file evolves, we will modify this matcher to keep it up to
    * date.
+   *
+   * @since 19.0 (since 1.0 as constant {@code SINGLE_WIDTH})
    */
-  public static final CharMatcher SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH",
-      "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
-      "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
-
-  /** Matches any character. */
-  public static final CharMatcher ANY =
-      new FastMatcher("CharMatcher.ANY") {
-        @Override public boolean matches(char c) {
-          return true;
-        }
+  public static CharMatcher singleWidth() {
+    return SingleWidth.INSTANCE;
+  }
 
-        @Override public int indexIn(CharSequence sequence) {
-          return (sequence.length() == 0) ? -1 : 0;
-        }
+  // Legacy constants
+  // TODO(cgdecker): Deprecate these so they can be removed eventually
 
-        @Override public int indexIn(CharSequence sequence, int start) {
-          int length = sequence.length();
-          Preconditions.checkPositionIndex(start, length);
-          return (start == length) ? -1 : start;
-        }
+  /**
+   * Determines whether a character is whitespace according to the latest Unicode standard, as
+   * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+   * This is not the same definition used by other Java APIs. (See a <a
+   * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+   * definitions of "whitespace"</a>.)
+   *
+   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
+   * to date.
+   */
+  public static final CharMatcher WHITESPACE = whitespace();
 
-        @Override public int lastIndexIn(CharSequence sequence) {
-          return sequence.length() - 1;
-        }
+  /**
+   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+   * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
+   * discussion of that term.
+   *
+   * @since 2.0
+   */
+  public static final CharMatcher BREAKING_WHITESPACE = breakingWhitespace();
 
-        @Override public boolean matchesAllOf(CharSequence sequence) {
-          checkNotNull(sequence);
-          return true;
-        }
+  /**
+   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   */
+  public static final CharMatcher ASCII = ascii();
 
-        @Override public boolean matchesNoneOf(CharSequence sequence) {
-          return sequence.length() == 0;
-        }
+  /**
+   * Determines whether a character is a digit according to
+   * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
+   * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+   */
+  public static final CharMatcher DIGIT = digit();
 
-        @Override public String removeFrom(CharSequence sequence) {
-          checkNotNull(sequence);
-          return "";
-        }
+  /**
+   * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
+   * Java's definition}. If you only care to match ASCII digits, you can use {@code
+   * inRange('0', '9')}.
+   */
+  public static final CharMatcher JAVA_DIGIT = javaDigit();
 
-        @Override public String replaceFrom(CharSequence sequence, char replacement) {
-          char[] array = new char[sequence.length()];
-          Arrays.fill(array, replacement);
-          return new String(array);
-        }
+  /**
+   * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
+   * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
+   * inRange('a', 'z').or(inRange('A', 'Z'))}.
+   */
+  public static final CharMatcher JAVA_LETTER = javaLetter();
 
-        @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
-          StringBuilder retval = new StringBuilder(sequence.length() * replacement.length());
-          for (int i = 0; i < sequence.length(); i++) {
-            retval.append(replacement);
-          }
-          return retval.toString();
-        }
+  /**
+   * Determines whether a character is a letter or digit according to {@linkplain
+   * Character#isLetterOrDigit(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_LETTER_OR_DIGIT = javaLetterOrDigit();
 
-        @Override public String collapseFrom(CharSequence sequence, char replacement) {
-          return (sequence.length() == 0) ? "" : String.valueOf(replacement);
-        }
+  /**
+   * Determines whether a character is upper case according to {@linkplain
+   * Character#isUpperCase(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_UPPER_CASE = javaUpperCase();
 
-        @Override public String trimFrom(CharSequence sequence) {
-          checkNotNull(sequence);
-          return "";
-        }
+  /**
+   * Determines whether a character is lower case according to {@linkplain
+   * Character#isLowerCase(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_LOWER_CASE = javaLowerCase();
 
-        @Override public int countIn(CharSequence sequence) {
-          return sequence.length();
-        }
+  /**
+   * Determines whether a character is an ISO control character as specified by {@link
+   * Character#isISOControl(char)}.
+   */
+  public static final CharMatcher JAVA_ISO_CONTROL = javaIsoControl();
 
-        @Override public CharMatcher and(CharMatcher other) {
-          return checkNotNull(other);
-        }
+  /**
+   * Determines whether a character is invisible; that is, if its Unicode category is any of
+   * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
+   * PRIVATE_USE according to ICU4J.
+   */
+  public static final CharMatcher INVISIBLE = invisible();
 
-        @Override public CharMatcher or(CharMatcher other) {
-          checkNotNull(other);
-          return this;
-        }
+  /**
+   * Determines whether a character is single-width (not double-width). When in doubt, this matcher
+   * errs on the side of returning {@code false} (that is, it tends to assume a character is
+   * double-width).
+   *
+   * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+   * date.
+   */
+  public static final CharMatcher SINGLE_WIDTH = singleWidth();
 
-        @Override public CharMatcher negate() {
-          return NONE;
-        }
-      };
+  /** Matches any character. */
+  public static final CharMatcher ANY = any();
 
   /** Matches no characters. */
-  public static final CharMatcher NONE =
-      new FastMatcher("CharMatcher.NONE") {
-        @Override public boolean matches(char c) {
-          return false;
-        }
-
-        @Override public int indexIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return -1;
-        }
-
-        @Override public int indexIn(CharSequence sequence, int start) {
-          int length = sequence.length();
-          Preconditions.checkPositionIndex(start, length);
-          return -1;
-        }
-
-        @Override public int lastIndexIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return -1;
-        }
-
-        @Override public boolean matchesAllOf(CharSequence sequence) {
-          return sequence.length() == 0;
-        }
-
-        @Override public boolean matchesNoneOf(CharSequence sequence) {
-          checkNotNull(sequence);
-          return true;
-        }
-
-        @Override public String removeFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override public String replaceFrom(CharSequence sequence, char replacement) {
-          return sequence.toString();
-        }
-
-        @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
-          checkNotNull(replacement);
-          return sequence.toString();
-        }
-
-        @Override public String collapseFrom(CharSequence sequence, char replacement) {
-          return sequence.toString();
-        }
-
-        @Override public String trimFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override
-        public String trimLeadingFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override
-        public String trimTrailingFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override public int countIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return 0;
-        }
-
-        @Override public CharMatcher and(CharMatcher other) {
-          checkNotNull(other);
-          return this;
-        }
-
-        @Override public CharMatcher or(CharMatcher other) {
-          return checkNotNull(other);
-        }
-
-        @Override public CharMatcher negate() {
-          return ANY;
-        }
-      };
+  public static final CharMatcher NONE = none();
 
   // Static factories
 
@@ -410,28 +313,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * Returns a {@code char} matcher that matches only one specified character.
    */
   public static CharMatcher is(final char match) {
-    String description = "CharMatcher.is('" + showCharacter(match) + "')";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c == match;
-      }
-
-      @Override public String replaceFrom(CharSequence sequence, char replacement) {
-        return sequence.toString().replace(match, replacement);
-      }
-
-      @Override public CharMatcher and(CharMatcher other) {
-        return other.matches(match) ? this : NONE;
-      }
-
-      @Override public CharMatcher or(CharMatcher other) {
-        return other.matches(match) ? other : super.or(other);
-      }
-
-      @Override public CharMatcher negate() {
-        return isNot(match);
-      }
-    };
+    return new Is(match);
   }
 
   /**
@@ -440,24 +322,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * <p>To negate another {@code CharMatcher}, use {@link #negate()}.
    */
   public static CharMatcher isNot(final char match) {
-    String description = "CharMatcher.isNot('" + showCharacter(match) + "')";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c != match;
-      }
-
-      @Override public CharMatcher and(CharMatcher other) {
-        return other.matches(match) ? super.and(other) : other;
-      }
-
-      @Override public CharMatcher or(CharMatcher other) {
-        return other.matches(match) ? ANY : this;
-      }
-
-      @Override public CharMatcher negate() {
-        return is(match);
-      }
-    };
+    return new IsNot(match);
   }
 
   /**
@@ -467,39 +332,16 @@ public abstract class CharMatcher implements Predicate<Character> {
   public static CharMatcher anyOf(final CharSequence sequence) {
     switch (sequence.length()) {
       case 0:
-        return NONE;
+        return none();
       case 1:
         return is(sequence.charAt(0));
       case 2:
         return isEither(sequence.charAt(0), sequence.charAt(1));
       default:
-        // continue below to handle the general case
-    }
-    // TODO(user): is it potentially worth just going ahead and building a precomputed matcher?
-    final char[] chars = sequence.toString().toCharArray();
-    Arrays.sort(chars);
-    StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
-    for (char c : chars) {
-      description.append(showCharacter(c));
-    }
-    description.append("\")");
-    return new CharMatcher(description.toString()) {
-      @Override public boolean matches(char c) {
-        return Arrays.binarySearch(chars, c) >= 0;
-      }
-    };
-  }
-
-  private static CharMatcher isEither(
-      final char match1,
-      final char match2) {
-    String description = "CharMatcher.anyOf(\"" +
-        showCharacter(match1) + showCharacter(match2) + "\")";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c == match1 || c == match2;
-      }
-    };
+        // TODO(lowasser): is it potentially worth just going ahead and building a precomputed
+        // matcher?
+        return new AnyOf(sequence);
+    }
   }
 
   /**
@@ -518,20 +360,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * @throws IllegalArgumentException if {@code endInclusive < startInclusive}
    */
   public static CharMatcher inRange(final char startInclusive, final char endInclusive) {
-    checkArgument(endInclusive >= startInclusive);
-    String description = "CharMatcher.inRange('" +
-        showCharacter(startInclusive) + "', '" +
-        showCharacter(endInclusive) + "')";
-    return inRange(startInclusive, endInclusive, description);
-  }
-
-  static CharMatcher inRange(final char startInclusive, final char endInclusive,
-      String description) {
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return startInclusive <= c && c <= endInclusive;
-      }
-    };
+    return new InRange(startInclusive, endInclusive);
   }
 
   /**
@@ -539,41 +368,16 @@ public abstract class CharMatcher implements Predicate<Character> {
    * which operates on primitive {@code char} instances instead.
    */
   public static CharMatcher forPredicate(final Predicate<? super Character> predicate) {
-    checkNotNull(predicate);
-    if (predicate instanceof CharMatcher) {
-      return (CharMatcher) predicate;
-    }
-    String description = "CharMatcher.forPredicate(" + predicate + ")";
-    return new CharMatcher(description) {
-      @Override public boolean matches(char c) {
-        return predicate.apply(c);
-      }
-
-      @Override public boolean apply(Character character) {
-        return predicate.apply(checkNotNull(character));
-      }
-    };
+    return predicate instanceof CharMatcher ? (CharMatcher) predicate : new ForPredicate(predicate);
   }
 
-  // State
-  final String description;
-
   // Constructors
 
   /**
-   * Sets the {@code toString()} from the given description.
-   */
-  CharMatcher(String description) {
-    this.description = description;
-  }
-
-  /**
    * Constructor for use by subclasses. When subclassing, you may want to override
    * {@code toString()} to provide a useful description.
    */
-  protected CharMatcher() {
-    description = super.toString();
-  }
+  protected CharMatcher() {}
 
   // Abstract methods
 
@@ -586,109 +390,21 @@ public abstract class CharMatcher implements Predicate<Character> {
    * Returns a matcher that matches any character not matched by this matcher.
    */
   public CharMatcher negate() {
-    return new NegatedMatcher(this);
-  }
-
-  private static class NegatedMatcher extends CharMatcher {
-    final CharMatcher original;
-
-    NegatedMatcher(String toString, CharMatcher original) {
-      super(toString);
-      this.original = original;
-    }
-
-    NegatedMatcher(CharMatcher original) {
-      this(original + ".negate()", original);
-    }
-
-    @Override public boolean matches(char c) {
-      return !original.matches(c);
-    }
-
-    @Override public boolean matchesAllOf(CharSequence sequence) {
-      return original.matchesNoneOf(sequence);
-    }
-
-    @Override public boolean matchesNoneOf(CharSequence sequence) {
-      return original.matchesAllOf(sequence);
-    }
-
-    @Override public int countIn(CharSequence sequence) {
-      return sequence.length() - original.countIn(sequence);
-    }
-
-    @Override public CharMatcher negate() {
-      return original;
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new NegatedMatcher(description, original);
-    }
+    return new Negated(this);
   }
 
   /**
    * Returns a matcher that matches any character matched by both this matcher and {@code other}.
    */
   public CharMatcher and(CharMatcher other) {
-    return new And(this, checkNotNull(other));
-  }
-
-  private static class And extends CharMatcher {
-    final CharMatcher first;
-    final CharMatcher second;
-
-    And(CharMatcher a, CharMatcher b) {
-      this(a, b, "CharMatcher.and(" + a + ", " + b + ")");
-    }
-
-    And(CharMatcher a, CharMatcher b, String description) {
-      super(description);
-      first = checkNotNull(a);
-      second = checkNotNull(b);
-    }
-
-    @Override
-    public boolean matches(char c) {
-      return first.matches(c) && second.matches(c);
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new And(first, second, description);
-    }
+    return new And(this, other);
   }
 
   /**
    * Returns a matcher that matches any character matched by either this matcher or {@code other}.
    */
   public CharMatcher or(CharMatcher other) {
-    return new Or(this, checkNotNull(other));
-  }
-
-  private static class Or extends CharMatcher {
-    final CharMatcher first;
-    final CharMatcher second;
-
-    Or(CharMatcher a, CharMatcher b, String description) {
-      super(description);
-      first = checkNotNull(a);
-      second = checkNotNull(b);
-    }
-
-    Or(CharMatcher a, CharMatcher b) {
-      this(a, b, "CharMatcher.or(" + a + ", " + b + ")");
-    }
-
-    @Override
-    public boolean matches(char c) {
-      return first.matches(c) || second.matches(c);
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new Or(first, second, description);
-    }
+    return new Or(this, other);
   }
 
   /**
@@ -704,61 +420,8 @@ public abstract class CharMatcher implements Predicate<Character> {
     return Platform.precomputeCharMatcher(this);
   }
 
-  /**
-   * Subclasses should provide a new CharMatcher with the same characteristics as {@code this},
-   * but with their {@code toString} method overridden with the new description.
-   *
-   * <p>This is unsupported by default.
-   */
-  CharMatcher withToString(String description) {
-    throw new UnsupportedOperationException();
-  }
-
   private static final int DISTINCT_CHARS = Character.MAX_VALUE - Character.MIN_VALUE + 1;
 
-  /**
-   * A matcher for which precomputation will not yield any significant benefit.
-   */
-  abstract static class FastMatcher extends CharMatcher {
-    FastMatcher() {
-      super();
-    }
-
-    FastMatcher(String description) {
-      super(description);
-    }
-
-    @Override
-    public final CharMatcher precomputed() {
-      return this;
-    }
-
-    @Override
-    public CharMatcher negate() {
-      return new NegatedFastMatcher(this);
-    }
-  }
-
-  static final class NegatedFastMatcher extends NegatedMatcher {
-    NegatedFastMatcher(CharMatcher original) {
-      super(original);
-    }
-
-    NegatedFastMatcher(String toString, CharMatcher original) {
-      super(toString, original);
-    }
-
-    @Override
-    public final CharMatcher precomputed() {
-      return this;
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new NegatedFastMatcher(description, original);
-    }
-  }
-
   // Text processing routines
 
   /**
@@ -821,13 +484,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * @return an index, or {@code -1} if no character matches
    */
   public int indexIn(CharSequence sequence) {
-    int length = sequence.length();
-    for (int i = 0; i < length; i++) {
-      if (matches(sequence.charAt(i))) {
-        return i;
-      }
-    }
-    return -1;
+    return indexIn(sequence, 0);
   }
 
   /**
@@ -847,7 +504,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    */
   public int indexIn(CharSequence sequence, int start) {
     int length = sequence.length();
-    Preconditions.checkPositionIndex(start, length);
+    checkPositionIndex(start, length);
     for (int i = start; i < length; i++) {
       if (matches(sequence.charAt(i))) {
         return i;
@@ -908,7 +565,8 @@ public abstract class CharMatcher implements Predicate<Character> {
     int spread = 1;
 
     // This unusual loop comes from extensive benchmarking
-    OUT: while (true) {
+    OUT:
+    while (true) {
       pos++;
       while (true) {
         if (pos == chars.length) {
@@ -1116,14 +774,12 @@ public abstract class CharMatcher implements Predicate<Character> {
     for (int i = 0; i < len; i++) {
       char c = sequence.charAt(i);
       if (matches(c)) {
-        if (c == replacement
-            && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
+        if (c == replacement && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
           // a no-op replacement
           i++;
         } else {
-          StringBuilder builder = new StringBuilder(len)
-              .append(sequence.subSequence(0, i))
-              .append(replacement);
+          StringBuilder builder =
+              new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement);
           return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
         }
       }
@@ -1141,23 +797,30 @@ public abstract class CharMatcher implements Predicate<Character> {
   public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
     // This implementation avoids unnecessary allocation.
     int len = sequence.length();
-    int first;
-    int last;
+    int first = 0;
+    int last = len - 1;
+
+    while (first < len && matches(sequence.charAt(first))) {
+      first++;
+    }
 
-    for (first = 0; first < len && matches(sequence.charAt(first)); first++) {}
-    for (last = len - 1; last > first && matches(sequence.charAt(last)); last--) {}
+    while (last > first && matches(sequence.charAt(last))) {
+      last--;
+    }
 
     return (first == 0 && last == len - 1)
         ? collapseFrom(sequence, replacement)
         : finishCollapseFrom(
-              sequence, first, last + 1, replacement,
-              new StringBuilder(last + 1 - first),
-              false);
+            sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
   }
 
   private String finishCollapseFrom(
-      CharSequence sequence, int start, int end, char replacement,
-      StringBuilder builder, boolean inMatchingGroup) {
+      CharSequence sequence,
+      int start,
+      int end,
+      char replacement,
+      StringBuilder builder,
+      boolean inMatchingGroup) {
     for (int i = start; i < end; i++) {
       char c = sequence.charAt(i);
       if (matches(c)) {
@@ -1189,32 +852,800 @@ public abstract class CharMatcher implements Predicate<Character> {
    */
   @Override
   public String toString() {
-    return description;
+    return super.toString();
   }
 
-  static final String WHITESPACE_TABLE = ""
-      + "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
-      + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
-      + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
-      + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
-  static final int WHITESPACE_MULTIPLIER = 1682554634;
-  static final int WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(WHITESPACE_TABLE.length() - 1);
-
   /**
-   * Determines whether a character is whitespace according to the latest Unicode standard, as
-   * illustrated
-   * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
-   * This is not the same definition used by other Java APIs. (See a
-   * <a href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
-   * definitions of "whitespace"</a>.)
-   *
-   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
-   * to date.
+   * Returns the Java Unicode escape sequence for the given character, in the form "\u12AB" where
+   * "12AB" is the four hexadecimal digits representing the 16 bits of the UTF-16 character.
    */
-  public static final CharMatcher WHITESPACE = new FastMatcher("WHITESPACE") {
+  private static String showCharacter(char c) {
+    String hex = "0123456789ABCDEF";
+    char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
+    for (int i = 0; i < 4; i++) {
+      tmp[5 - i] = hex.charAt(c & 0xF);
+      c = (char) (c >> 4);
+    }
+    return String.copyValueOf(tmp);
+  }
+
+  // Fast matchers
+
+  /** A matcher for which precomputation will not yield any significant benefit. */
+  abstract static class FastMatcher extends CharMatcher {
+
+    @Override
+    public final CharMatcher precomputed() {
+      return this;
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return new NegatedFastMatcher(this);
+    }
+  }
+
+  /** {@link FastMatcher} which overrides {@code toString()} with a custom name. */
+  abstract static class NamedFastMatcher extends FastMatcher {
+
+    private final String description;
+
+    NamedFastMatcher(String description) {
+      this.description = checkNotNull(description);
+    }
+
+    @Override
+    public final String toString() {
+      return description;
+    }
+  }
+
+  /** Negation of a {@link FastMatcher}. */
+  static class NegatedFastMatcher extends Negated {
+
+    NegatedFastMatcher(CharMatcher original) {
+      super(original);
+    }
+
+    @Override
+    public final CharMatcher precomputed() {
+      return this;
+    }
+  }
+
+  // Static constant implementation classes
+
+  /** Implementation of {@link #any()}. */
+  private static final class Any extends NamedFastMatcher {
+
+    static final Any INSTANCE = new Any();
+
+    private Any() {
+      super("CharMatcher.any()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return true;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence) {
+      return (sequence.length() == 0) ? -1 : 0;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence, int start) {
+      int length = sequence.length();
+      checkPositionIndex(start, length);
+      return (start == length) ? -1 : start;
+    }
+
+    @Override
+    public int lastIndexIn(CharSequence sequence) {
+      return sequence.length() - 1;
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      checkNotNull(sequence);
+      return true;
+    }
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      return sequence.length() == 0;
+    }
+
+    @Override
+    public String removeFrom(CharSequence sequence) {
+      checkNotNull(sequence);
+      return "";
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      char[] array = new char[sequence.length()];
+      Arrays.fill(array, replacement);
+      return new String(array);
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+      StringBuilder result = new StringBuilder(sequence.length() * replacement.length());
+      for (int i = 0; i < sequence.length(); i++) {
+        result.append(replacement);
+      }
+      return result.toString();
+    }
+
+    @Override
+    public String collapseFrom(CharSequence sequence, char replacement) {
+      return (sequence.length() == 0) ? "" : String.valueOf(replacement);
+    }
+
+    @Override
+    public String trimFrom(CharSequence sequence) {
+      checkNotNull(sequence);
+      return "";
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      return sequence.length();
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return checkNotNull(other);
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      checkNotNull(other);
+      return this;
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return none();
+    }
+  }
+
+  /** Implementation of {@link #none()}. */
+  private static final class None extends NamedFastMatcher {
+
+    static final None INSTANCE = new None();
+
+    private None() {
+      super("CharMatcher.none()");
+    }
+
     @Override
     public boolean matches(char c) {
-      return WHITESPACE_TABLE.charAt((WHITESPACE_MULTIPLIER * c) >>> WHITESPACE_SHIFT) == c;
+      return false;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return -1;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence, int start) {
+      int length = sequence.length();
+      checkPositionIndex(start, length);
+      return -1;
+    }
+
+    @Override
+    public int lastIndexIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return -1;
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      return sequence.length() == 0;
     }
-  };
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      checkNotNull(sequence);
+      return true;
+    }
+
+    @Override
+    public String removeFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+      checkNotNull(replacement);
+      return sequence.toString();
+    }
+
+    @Override
+    public String collapseFrom(CharSequence sequence, char replacement) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimLeadingFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimTrailingFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return 0;
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      checkNotNull(other);
+      return this;
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return checkNotNull(other);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return any();
+    }
+  }
+
+  /** Implementation of {@link #whitespace()}. */
+  @VisibleForTesting
+  static final class Whitespace extends NamedFastMatcher {
+
+    static final String TABLE =
+        "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
+            + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
+            + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
+            + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
+    static final int MULTIPLIER = 1682554634;
+    static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1);
+
+    static final Whitespace INSTANCE = new Whitespace();
+
+    Whitespace() {
+      super("CharMatcher.whitespace()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return TABLE.charAt((MULTIPLIER * c) >>> SHIFT) == c;
+    }
+  }
+
+  /** Implementation of {@link #breakingWhitespace()}. */
+  private static final class BreakingWhitespace extends CharMatcher {
+
+    static final CharMatcher INSTANCE = new BreakingWhitespace();
+
+    @Override
+    public boolean matches(char c) {
+      switch (c) {
+        case '\t':
+        case '\n':
+        case '\013':
+        case '\f':
+        case '\r':
+        case ' ':
+        case '\u0085':
+        case '\u1680':
+        case '\u2028':
+        case '\u2029':
+        case '\u205f':
+        case '\u3000':
+          return true;
+        case '\u2007':
+          return false;
+        default:
+          return c >= '\u2000' && c <= '\u200a';
+      }
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.breakingWhitespace()";
+    }
+  }
+
+  /** Implementation of {@link #ascii()}. */
+  private static final class Ascii extends NamedFastMatcher {
+
+    static final Ascii INSTANCE = new Ascii();
+
+    Ascii() {
+      super("CharMatcher.ascii()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c <= '\u007f';
+    }
+  }
+
+  /** Implementation that matches characters that fall within multiple ranges. */
+  private static class RangesMatcher extends CharMatcher {
+
+    private final String description;
+    private final char[] rangeStarts;
+    private final char[] rangeEnds;
+
+    RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
+      this.description = description;
+      this.rangeStarts = rangeStarts;
+      this.rangeEnds = rangeEnds;
+      checkArgument(rangeStarts.length == rangeEnds.length);
+      for (int i = 0; i < rangeStarts.length; i++) {
+        checkArgument(rangeStarts[i] <= rangeEnds[i]);
+        if (i + 1 < rangeStarts.length) {
+          checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
+        }
+      }
+    }
+
+    @Override
+    public boolean matches(char c) {
+      int index = Arrays.binarySearch(rangeStarts, c);
+      if (index >= 0) {
+        return true;
+      } else {
+        index = ~index - 1;
+        return index >= 0 && c <= rangeEnds[index];
+      }
+    }
+
+    @Override
+    public String toString() {
+      return description;
+    }
+  }
+
+  /** Implementation of {@link #digit()}. */
+  private static final class Digit extends RangesMatcher {
+
+    // Must be in ascending order.
+    private static final String ZEROES =
+        "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66"
+            + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810"
+            + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+
+    private static char[] zeroes() {
+      return ZEROES.toCharArray();
+    }
+
+    private static char[] nines() {
+      char[] nines = new char[ZEROES.length()];
+      for (int i = 0; i < ZEROES.length(); i++) {
+        nines[i] = (char) (ZEROES.charAt(i) + 9);
+      }
+      return nines;
+    }
+
+    static final Digit INSTANCE = new Digit();
+
+    private Digit() {
+      super("CharMatcher.digit()", zeroes(), nines());
+    }
+  }
+
+  /** Implementation of {@link #javaDigit()}. */
+  private static final class JavaDigit extends CharMatcher {
+
+    static final JavaDigit INSTANCE = new JavaDigit();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isDigit(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaDigit()";
+    }
+  }
+
+  /** Implementation of {@link #javaLetter()}. */
+  private static final class JavaLetter extends CharMatcher {
+
+    static final JavaLetter INSTANCE = new JavaLetter();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLetter(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLetter()";
+    }
+  }
+
+  /** Implementation of {@link #javaLetterOrDigit()}. */
+  private static final class JavaLetterOrDigit extends CharMatcher {
+
+    static final JavaLetterOrDigit INSTANCE = new JavaLetterOrDigit();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLetterOrDigit(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLetterOrDigit()";
+    }
+  }
+
+  /** Implementation of {@link #javaUpperCase()}. */
+  private static final class JavaUpperCase extends CharMatcher {
+
+    static final JavaUpperCase INSTANCE = new JavaUpperCase();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isUpperCase(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaUpperCase()";
+    }
+  }
+
+  /** Implementation of {@link #javaLowerCase()}. */
+  private static final class JavaLowerCase extends CharMatcher {
+
+    static final JavaLowerCase INSTANCE = new JavaLowerCase();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLowerCase(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLowerCase()";
+    }
+  }
+
+  /** Implementation of {@link #javaIsoControl()}. */
+  private static final class JavaIsoControl extends NamedFastMatcher {
+
+    static final JavaIsoControl INSTANCE = new JavaIsoControl();
+
+    private JavaIsoControl() {
+      super("CharMatcher.javaIsoControl()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c <= '\u001f' || (c >= '\u007f' && c <= '\u009f');
+    }
+  }
+
+  /** Implementation of {@link #invisible()}. */
+  private static final class Invisible extends RangesMatcher {
+
+    private static final String RANGE_STARTS =
+      "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067"
+          + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa";
+    private static final String RANGE_ENDS =
+      "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067"
+          + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb";
+
+    static final Invisible INSTANCE = new Invisible();
+
+    private Invisible() {
+      super(
+          "CharMatcher.invisible()",
+          RANGE_STARTS.toCharArray(),
+          RANGE_ENDS.toCharArray());
+    }
+  }
+
+  /** Implementation of {@link #singleWidth()}. */
+  private static final class SingleWidth extends RangesMatcher {
+
+    static final SingleWidth INSTANCE = new SingleWidth();
+
+    private SingleWidth() {
+      super(
+          "CharMatcher.singleWidth()",
+          "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
+          "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
+    }
+  }
+
+  // Non-static factory implementation classes
+
+  /** Implementation of {@link #negate()}. */
+  private static class Negated extends CharMatcher {
+
+    final CharMatcher original;
+
+    Negated(CharMatcher original) {
+      this.original = checkNotNull(original);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return !original.matches(c);
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      return original.matchesNoneOf(sequence);
+    }
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      return original.matchesAllOf(sequence);
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      return sequence.length() - original.countIn(sequence);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return original;
+    }
+
+    @Override
+    public String toString() {
+      return original + ".negate()";
+    }
+  }
+
+  /** Implementation of {@link #and(CharMatcher)}. */
+  private static final class And extends CharMatcher {
+
+    final CharMatcher first;
+    final CharMatcher second;
+
+    And(CharMatcher a, CharMatcher b) {
+      first = checkNotNull(a);
+      second = checkNotNull(b);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return first.matches(c) && second.matches(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.and(" + first + ", " + second + ")";
+    }
+  }
+
+  /** Implementation of {@link #or(CharMatcher)}. */
+  private static final class Or extends CharMatcher {
+
+    final CharMatcher first;
+    final CharMatcher second;
+
+    Or(CharMatcher a, CharMatcher b) {
+      first = checkNotNull(a);
+      second = checkNotNull(b);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return first.matches(c) || second.matches(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.or(" + first + ", " + second + ")";
+    }
+  }
+
+  // Static factory implementations
+
+  /** Implementation of {@link #is(char)}. */
+  private static final class Is extends FastMatcher {
+
+    private final char match;
+
+    Is(char match) {
+      this.match = match;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c == match;
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      return sequence.toString().replace(match, replacement);
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return other.matches(match) ? this : none();
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return other.matches(match) ? other : super.or(other);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return isNot(match);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.is('" + showCharacter(match) + "')";
+    }
+  }
+
+  /** Implementation of {@link #isNot(char)}. */
+  private static final class IsNot extends FastMatcher {
+
+    private final char match;
+
+    IsNot(char match) {
+      this.match = match;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c != match;
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return other.matches(match) ? super.and(other) : other;
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return other.matches(match) ? any() : this;
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return is(match);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.isNot('" + showCharacter(match) + "')";
+    }
+  }
+
+  private static CharMatcher.IsEither isEither(char c1, char c2) {
+    return new CharMatcher.IsEither(c1, c2);
+  }
+
+  /** Implementation of {@link #anyOf(CharSequence)} for exactly two characters. */
+  private static final class IsEither extends FastMatcher {
+
+    private final char match1;
+    private final char match2;
+
+    IsEither(char match1, char match2) {
+      this.match1 = match1;
+      this.match2 = match2;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c == match1 || c == match2;
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")";
+    }
+  }
+
+  /** Implementation of {@link #anyOf(CharSequence)} for three or more characters. */
+  private static final class AnyOf extends CharMatcher {
+
+    private final char[] chars;
+
+    public AnyOf(CharSequence chars) {
+      this.chars = chars.toString().toCharArray();
+      Arrays.sort(this.chars);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return Arrays.binarySearch(chars, c) >= 0;
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
+      for (char c : chars) {
+        description.append(showCharacter(c));
+      }
+      description.append("\")");
+      return description.toString();
+    }
+  }
+
+  /** Implementation of {@link #inRange(char, char)}. */
+  private static final class InRange extends FastMatcher {
+
+    private final char startInclusive;
+    private final char endInclusive;
+
+    InRange(char startInclusive, char endInclusive) {
+      checkArgument(endInclusive >= startInclusive);
+      this.startInclusive = startInclusive;
+      this.endInclusive = endInclusive;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return startInclusive <= c && c <= endInclusive;
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.inRange('"
+          + showCharacter(startInclusive)
+          + "', '"
+          + showCharacter(endInclusive)
+          + "')";
+    }
+  }
+
+  /** Implementation of {@link #forPredicate(Predicate)}. */
+  private static final class ForPredicate extends CharMatcher {
+
+    private final Predicate<? super Character> predicate;
+
+    ForPredicate(Predicate<? super Character> predicate) {
+      this.predicate = checkNotNull(predicate);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return predicate.apply(c);
+    }
+
+    @SuppressWarnings("deprecation") // intentional; deprecation is for callers primarily
+    @Override
+    public boolean apply(Character character) {
+      return predicate.apply(checkNotNull(character));
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.forPredicate(" + predicate + ")";
+    }
+  }
 }
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
index 10d83ce..8866e9a 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
@@ -27,7 +27,7 @@ import java.nio.charset.Charset;
  * <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">
+ * href="https://github.com/google/guava/wiki/StringsExplained#charsets">
  * {@code Charsets}</a>.
  *
  * @author Mike Bostock
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
index f4aa4a8..f0f0f5e 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
 
 import java.io.Serializable;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -32,6 +33,7 @@ import javax.annotation.Nullable;
  *
  * @since 9.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 @Beta
 public final class Enums {
@@ -46,8 +48,7 @@ public final class Enums {
    *
    * @since 12.0
    */
-  public static <T extends Enum<T>> Optional<T> getIfPresent(
-      Class<T> enumClass, String value) {
+  public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
     checkNotNull(enumClass);
     checkNotNull(value);
     return Platform.getEnumIfPresent(enumClass, value);
@@ -65,8 +66,8 @@ public final class Enums {
     return new StringConverter<T>(enumClass);
   }
 
-  private static final class StringConverter<T extends Enum<T>>
-      extends Converter<String, T> implements Serializable {
+  private static final class StringConverter<T extends Enum<T>> extends Converter<String, T>
+      implements Serializable {
 
     private final Class<T> enumClass;
 
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
index e9a4b17..aae8245 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -35,12 +36,13 @@ import javax.annotation.Nullable;
  * serializable parameters.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the
  * use of {@code Predicate}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Predicates {
   private Predicates() {}
@@ -99,8 +101,7 @@ public final class Predicates {
    * components} is empty, the returned predicate will always evaluate to {@code
    * true}.
    */
-  public static <T> Predicate<T> and(
-      Iterable<? extends Predicate<? super T>> components) {
+  public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
     return new AndPredicate<T>(defensiveCopy(components));
   }
 
@@ -123,10 +124,8 @@ public final class Predicates {
    * 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)));
+  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)));
   }
 
   /**
@@ -138,8 +137,7 @@ public final class Predicates {
    * components} is empty, the returned predicate will always evaluate to {@code
    * false}.
    */
-  public static <T> Predicate<T> or(
-      Iterable<? extends Predicate<? super T>> components) {
+  public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
     return new OrPredicate<T>(defensiveCopy(components));
   }
 
@@ -162,10 +160,8 @@ public final class Predicates {
    * 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)));
+  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)));
   }
 
   /**
@@ -173,9 +169,7 @@ public final class Predicates {
    * 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);
+    return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
   }
 
   /**
@@ -212,37 +206,49 @@ public final class Predicates {
   enum ObjectPredicate implements Predicate<Object> {
     /** @see Predicates#alwaysTrue() */
     ALWAYS_TRUE {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return true;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.alwaysTrue()";
       }
     },
     /** @see Predicates#alwaysFalse() */
     ALWAYS_FALSE {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return false;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.alwaysFalse()";
       }
     },
     /** @see Predicates#isNull() */
     IS_NULL {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return o == null;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.isNull()";
       }
     },
     /** @see Predicates#notNull() */
     NOT_NULL {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return o != null;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.notNull()";
       }
     };
@@ -260,23 +266,31 @@ public final class Predicates {
     NotPredicate(Predicate<T> predicate) {
       this.predicate = checkNotNull(predicate);
     }
+
     @Override
     public boolean apply(@Nullable T t) {
       return !predicate.apply(t);
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       return ~predicate.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() + ")";
+
+    @Override
+    public String toString() {
+      return "Predicates.not(" + predicate + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -289,6 +303,7 @@ public final class Predicates {
     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).
@@ -299,20 +314,27 @@ public final class Predicates {
       }
       return true;
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       // add a random number to avoid collisions with OrPredicate
       return components.hashCode() + 0x12472c2c;
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @Override
+    public String toString() {
       return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -323,6 +345,7 @@ public final class Predicates {
     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).
@@ -333,48 +356,62 @@ public final class Predicates {
       }
       return false;
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       // add a random number to avoid collisions with AndPredicate
       return components.hashCode() + 0x053c91cf;
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @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 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() {
+
+    @Override
+    public int hashCode() {
       return target.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @Override
+    public String toString() {
       return "Predicates.equalTo(" + target + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -397,7 +434,8 @@ public final class Predicates {
       }
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof InPredicate) {
         InPredicate<?> that = (InPredicate<?>) obj;
         return target.equals(that.target);
@@ -405,19 +443,21 @@ public final class Predicates {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return target.hashCode();
     }
 
-    @Override public String toString() {
+    @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 {
+  private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
     final Predicate<B> p;
     final Function<A, ? extends B> f;
 
@@ -431,7 +471,8 @@ public final class Predicates {
       return p.apply(f.apply(a));
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof CompositionPredicate) {
         CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
         return f.equals(that.f) && p.equals(that.p);
@@ -439,12 +480,15 @@ public final class Predicates {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return f.hashCode() ^ p.hashCode();
     }
 
-    @Override public String toString() {
-      return p.toString() + "(" + f.toString() + ")";
+    @Override
+    public String toString() {
+      // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
+      return p + "(" + f + ")";
     }
 
     private static final long serialVersionUID = 0;
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
index 56e2902..6e30284 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
@@ -87,7 +87,7 @@ import javax.annotation.CheckReturnValue;
  * 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">
+ * "https://github.com/google/guava/wiki/StringsExplained#splitter">
  * {@code Splitter}</a>.
  *
  * @author Julien Silland
@@ -107,8 +107,7 @@ public final class Splitter {
     this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
   }
 
-  private Splitter(Strategy strategy, boolean omitEmptyStrings,
-      CharMatcher trimmer, int limit) {
+  private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
     this.strategy = strategy;
     this.omitEmptyStrings = omitEmptyStrings;
     this.trimmer = trimmer;
@@ -123,6 +122,7 @@ public final class Splitter {
    * @param separator the character to recognize as a separator
    * @return a splitter, with default settings, that recognizes that separator
    */
+  @CheckReturnValue
   public static Splitter on(char separator) {
     return on(CharMatcher.is(separator));
   }
@@ -137,23 +137,27 @@ public final class Splitter {
    *     character is a separator
    * @return a splitter, with default settings, that uses this matcher
    */
+  @CheckReturnValue
   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);
-          }
+    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;
+              @Override
+              int separatorEnd(int separatorPosition) {
+                return separatorPosition + 1;
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -164,36 +168,40 @@ public final class Splitter {
    * @param separator the literal, nonempty string to recognize as a separator
    * @return a splitter, with default settings, that recognizes that separator
    */
+  @CheckReturnValue
   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;
+    checkArgument(separator.length() != 0, "The separator may not be the empty string.");
+    if (separator.length() == 1) {
+      return Splitter.on(separator.charAt(0));
+    }
+    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;
               }
-              return p;
-            }
-            return -1;
-          }
 
-          @Override public int separatorEnd(int separatorPosition) {
-            return separatorPosition + separator.length();
+              @Override
+              public int separatorEnd(int separatorPosition) {
+                return separatorPosition + separator.length();
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -215,24 +223,28 @@ public final class Splitter {
    *     pieces
    * @throws IllegalArgumentException if {@code length} is zero or negative
    */
+  @CheckReturnValue
   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);
-          }
+    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;
+              @Override
+              public int separatorEnd(int separatorPosition) {
+                return separatorPosition;
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -261,7 +273,8 @@ public final class Splitter {
   /**
    * 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.
+   * The limit defines the maximum number of items returned by the iterator, or
+   * the maximum size of the list returned by {@link #splitToList}.
    *
    * <p>For example,
    * {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
@@ -271,9 +284,9 @@ public final class Splitter {
    * 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"]}.
+   * results in {@code ["a", "b", "c , d"]}.
    *
-   * @param limit the maximum number of items returns
+   * @param limit the maximum number of items returned
    * @return a splitter with the desired configuration
    * @since 9.0
    */
@@ -324,14 +337,18 @@ public final class Splitter {
    * @param sequence the sequence of characters to split
    * @return an iteration over the segments split from the parameter.
    */
+  @CheckReturnValue
   public Iterable<String> split(final CharSequence sequence) {
     checkNotNull(sequence);
 
     return new Iterable<String>() {
-      @Override public Iterator<String> iterator() {
+      @Override
+      public Iterator<String> iterator() {
         return splittingIterator(sequence);
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return Joiner.on(", ")
             .appendTo(new StringBuilder().append('['), this)
             .append(']')
@@ -353,6 +370,7 @@ public final class Splitter {
    * @return an immutable list of the segments split from the parameter
    * @since 15.0
    */
+  @CheckReturnValue
   @Beta
   public List<String> splitToList(CharSequence sequence) {
     checkNotNull(sequence);
@@ -413,8 +431,7 @@ public final class Splitter {
    */
   @Beta
   public static final class MapSplitter {
-    private static final String INVALID_ENTRY_MESSAGE =
-        "Chunk [%s] is not a valid entry";
+    private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
     private final Splitter outerSplitter;
     private final Splitter entrySplitter;
 
@@ -438,6 +455,7 @@ public final class Splitter {
      * @throws IllegalArgumentException if the specified sequence does not split
      *         into valid map entries, or if there are duplicate keys
      */
+    @CheckReturnValue
     public Map<String, String> split(CharSequence sequence) {
       Map<String, String> map = new LinkedHashMap<String, String>();
       for (String entry : outerSplitter.split(sequence)) {
@@ -489,7 +507,8 @@ public final class Splitter {
       this.toSplit = toSplit;
     }
 
-    @Override protected String computeNext() {
+    @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
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
index 07f674e..fec69ff 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
@@ -26,11 +26,12 @@ import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * An object that measures elapsed time in nanoseconds. It is useful to measure
  * elapsed time using this class instead of direct calls to {@link
@@ -70,7 +71,6 @@ import java.util.concurrent.TimeUnit;
  * @author Kevin Bourrillion
  * @since 10.0
  */
- at Beta
 @GwtCompatible(emulated = true)
 public final class Stopwatch {
   private final Ticker ticker;
@@ -84,6 +84,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createUnstarted() {
     return new Stopwatch();
   }
@@ -94,6 +95,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createUnstarted(Ticker ticker) {
     return new Stopwatch(ticker);
   }
@@ -104,6 +106,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createStarted() {
     return new Stopwatch().start();
   }
@@ -114,28 +117,15 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createStarted(Ticker ticker) {
     return new Stopwatch(ticker).start();
   }
 
-  /**
-   * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
-   * as its time source.
-   *
-   * @deprecated Use {@link Stopwatch#createUnstarted()} instead.
-   */
-  @Deprecated
   Stopwatch() {
-    this(Ticker.systemTicker());
+    this.ticker = Ticker.systemTicker();
   }
 
-  /**
-   * Creates (but does not start) a new stopwatch, using the specified time
-   * source.
-   *
-   * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead.
-   */
-  @Deprecated
   Stopwatch(Ticker ticker) {
     this.ticker = checkNotNull(ticker, "ticker");
   }
@@ -145,6 +135,7 @@ public final class Stopwatch {
    * and {@link #stop()} has not been called since the last call to {@code
    * start()}.
    */
+  @CheckReturnValue
   public boolean isRunning() {
     return isRunning;
   }
@@ -203,6 +194,7 @@ public final class Stopwatch {
    *
    * @since 14.0 (since 10.0 as {@code elapsedTime()})
    */
+  @CheckReturnValue
   public long elapsed(TimeUnit desiredUnit) {
     return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
   }
@@ -250,3 +242,4 @@ public final class Stopwatch {
     }
   }
 }
+
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
index 8e50152..cf84576 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
@@ -52,6 +52,7 @@ import javax.annotation.CheckReturnValue;
  * <li>accumulation of cache access statistics
  * </ul>
  *
+ *
  * <p>These features are all optional; caches can be created using all or none of them. By default
  * cache instances created by {@code CacheBuilder} will not perform any type of eviction.
  *
@@ -133,7 +134,7 @@ import javax.annotation.CheckReturnValue;
  * <i>not</i> include cache contents, but only configuration.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
+ * "https://github.com/google/guava/wiki/CachesExplained">caching</a> for a higher-level
  * explanation.
  *
  * @param <K> the base key type for all caches created by this builder
@@ -444,11 +445,11 @@ public final class CacheBuilder<K, V> {
   }
 
   /**
-   * Specifies a nanosecond-precision time source for use in determining when entries should be
-   * expired. By default, {@link System#nanoTime} is used.
+   * Specifies a nanosecond-precision time source for this cache. By default,
+   * {@link System#nanoTime} is used.
    *
-   * <p>The primary intent of this method is to facilitate testing of caches which have been
-   * configured with {@link #expireAfterWrite} or {@link #expireAfterAccess}.
+   * <p>The primary intent of this method is to facilitate testing of caches with a fake or mock
+   * time source.
    *
    * @throws IllegalStateException if a ticker was already set
    */
@@ -517,7 +518,7 @@ public final class CacheBuilder<K, V> {
     statsCounterSupplier = CACHE_STATS_COUNTER;
     return this;
   }
-  
+
   boolean isRecordingStats() {
     return statsCounterSupplier == CACHE_STATS_COUNTER;
   }
@@ -539,7 +540,7 @@ public final class CacheBuilder<K, V> {
    * @return a cache having the requested features
    */
   public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
-      CacheLoader<? super K1, V1> loader) {
+          CacheLoader<? super K1, V1> loader) {
     checkWeightWithWeigher();
     return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
   }
@@ -623,4 +624,3 @@ public final class CacheBuilder<K, V> {
     return s.toString();
   }
 }
-
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
index c345553..44a73da 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
@@ -99,7 +98,6 @@ public abstract class CacheLoader<K, V> {
    * @param function the function to be used for loading values; must never return {@code null}
    * @return a cache loader that loads values by passing each key to {@code function}
    */
-  @Beta
   public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
     return new FunctionToCacheLoader<K, V>(function);
   }
@@ -129,7 +127,6 @@ public abstract class CacheLoader<K, V> {
    * @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
    *     key
    */
-  @Beta
   public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
     return new SupplierToCacheLoader<V>(supplier);
   }
@@ -151,7 +148,17 @@ public abstract class CacheLoader<K, V> {
     private static final long serialVersionUID = 0;
   }
 
-  static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {}
+  /**
+   * Exception thrown by {@code loadAll()} to indicate that it is not supported.
+   *
+   * @since 19.0
+   */
+  public static final class UnsupportedLoadingOperationException
+      extends UnsupportedOperationException {
+    // Package-private because this should only be thrown by loadAll() when it is not overridden.
+    // Cache implementors may want to catch it but should not need to be able to throw it.
+    UnsupportedLoadingOperationException() {}
+  }
 
   /**
    * Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
index 16aba06..c8dec84 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
@@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ExecutionError;
 import com.google.common.util.concurrent.UncheckedExecutionException;
 
+import java.util.AbstractCollection;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.HashMap;
@@ -237,7 +238,7 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
   
   private void alertListenerIfPresent(Object key, Object value, RemovalCause cause) {
     if (removalListener != null) {
-      removalListener.onRemoval(new RemovalNotification(key, value, cause));
+      removalListener.onRemoval(RemovalNotification.create(key, value, cause));
     }
   }
 
@@ -487,7 +488,7 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
     protected boolean removeEldestEntry(Map.Entry<K, Timestamped<V>> ignored) {
       boolean removal = (maximumSize == UNSET_INT) ? false : (size() > maximumSize);
       if ((removalListener != null) && removal) {
-        removalListener.onRemoval(new RemovalNotification(
+        removalListener.onRemoval(RemovalNotification.create(
             ignored.getKey(), 
             ignored.getValue().getValue(),
             RemovalCause.SIZE));
@@ -742,9 +743,6 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
     }
   }
 
-  /**
-   * Abstraction layer for the KeySet, which redirects to cache methods.
-   */
   private final class KeySet extends AbstractCacheSet<K> {
 
     KeySet(ConcurrentMap<?, ?> map) {
@@ -767,13 +765,11 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
     }
   }
   
-  /**
-   * Abstraction layer for the Values set, which redirects to cache methods.
-   */
-  private final class Values extends AbstractCacheSet<V> {
+  private final class Values extends AbstractCollection<V> {
+    final ConcurrentMap<?, ?> map;
 
     Values(ConcurrentMap<?, ?> map) {
-      super(map);
+      this.map = map;
     }
 
     @Override
@@ -785,11 +781,23 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
     public boolean contains(Object o) {
       return map.containsValue(o);
     }
+
+    @Override
+    public int size() {
+      return map.size();
+    }
+    
+    @Override
+    public boolean isEmpty() {
+      return map.isEmpty();
+    }
+    
+    @Override
+    public void clear() {
+      map.clear();
+    }
   }
 
-  /**
-   * Abstraction layer for the EntrySet, which redirects to cache methods.
-   */
   private final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
 
     EntrySet(ConcurrentMap<?, ?> map) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
index 6f40246..36eefec 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Collection;
@@ -59,7 +60,8 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     inverse = forward;
   }
 
-  @Override protected Map<K, V> delegate() {
+  @Override
+  protected Map<K, V> delegate() {
     return delegate;
   }
 
@@ -97,13 +99,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   // Query Operations (optimizations)
 
-  @Override public boolean containsValue(@Nullable Object value) {
+  @Override
+  public boolean containsValue(@Nullable Object value) {
     return inverse.containsKey(value);
   }
 
   // Modification Operations
 
-  @Override public V put(@Nullable K key, @Nullable V value) {
+  @Override
+  public V put(@Nullable K key, @Nullable V value) {
     return putInBothMaps(key, value, false);
   }
 
@@ -129,15 +133,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     return oldValue;
   }
 
-  private void updateInverseMap(
-      K key, boolean containedKey, V oldValue, V newValue) {
+  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) {
+  @Override
+  public V remove(@Nullable Object key) {
     return containsKey(key) ? removeFromBothMaps(key) : null;
   }
 
@@ -153,13 +157,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   // Bulk Operations
 
-  @Override public void putAll(Map<? extends K, ? extends V> map) {
+  @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() {
+  @Override
+  public void clear() {
     delegate.clear();
     inverse.delegate.clear();
   }
@@ -173,21 +179,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   private transient Set<K> keySet;
 
-  @Override public Set<K> keySet() {
+  @Override
+  public Set<K> keySet() {
     Set<K> result = keySet;
     return (result == null) ? keySet = new KeySet() : result;
   }
 
+  @WeakOuter
   private class KeySet extends ForwardingSet<K> {
-    @Override protected Set<K> delegate() {
+    @Override
+    protected Set<K> delegate() {
       return delegate.keySet();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       AbstractBiMap.this.clear();
     }
 
-    @Override public boolean remove(Object key) {
+    @Override
+    public boolean remove(Object key) {
       if (!contains(key)) {
         return false;
       }
@@ -195,22 +206,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
       return true;
     }
 
-    @Override public boolean removeAll(Collection<?> keysToRemove) {
+    @Override
+    public boolean removeAll(Collection<?> keysToRemove) {
       return standardRemoveAll(keysToRemove);
     }
 
-    @Override public boolean retainAll(Collection<?> keysToRetain) {
+    @Override
+    public boolean retainAll(Collection<?> keysToRetain) {
       return standardRetainAll(keysToRetain);
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return Maps.keyIterator(entrySet().iterator());
     }
   }
 
   private transient Set<V> valueSet;
 
-  @Override public Set<V> values() {
+  @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.
@@ -219,49 +234,60 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     return (result == null) ? valueSet = new ValueSet() : result;
   }
 
+  @WeakOuter
   private class ValueSet extends ForwardingSet<V> {
     final Set<V> valuesDelegate = inverse.keySet();
 
-    @Override protected Set<V> delegate() {
+    @Override
+    protected Set<V> delegate() {
       return valuesDelegate;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       return Maps.valueIterator(entrySet().iterator());
     }
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return standardToString();
     }
   }
 
   private transient Set<Entry<K, V>> entrySet;
 
-  @Override public 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;
   }
 
+  @WeakOuter
   private class EntrySet extends ForwardingSet<Entry<K, V>> {
     final Set<Entry<K, V>> esDelegate = delegate.entrySet();
 
-    @Override protected Set<Entry<K, V>> delegate() {
+    @Override
+    protected Set<Entry<K, V>> delegate() {
       return esDelegate;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       AbstractBiMap.this.clear();
     }
 
-    @Override public boolean remove(Object object) {
+    @Override
+    public boolean remove(Object object) {
       if (!esDelegate.contains(object)) {
         return false;
       }
@@ -278,43 +304,47 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
       return true;
     }
 
-    @Override public Iterator<Entry<K, V>> iterator() {
+    @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() {
+        @Override
+        public boolean hasNext() {
           return iterator.hasNext();
         }
 
-        @Override public Entry<K, V> next() {
+        @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() {
+            @Override
+            protected Entry<K, V> delegate() {
               return finalEntry;
             }
 
-            @Override public V setValue(V value) {
+            @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);
+              checkArgument(!containsValue(value), "value already present: %s", value);
               V oldValue = finalEntry.setValue(value);
-              checkState(Objects.equal(value, get(getKey())),
-                  "entry no longer in map");
+              checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
               updateInverseMap(getKey(), true, oldValue, value);
               return oldValue;
             }
           };
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(entry != null);
           V value = entry.getValue();
           iterator.remove();
@@ -325,22 +355,33 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
     // See java.util.Collections.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       return Maps.containsEntryImpl(delegate(), o);
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       return standardRemoveAll(c);
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       return standardRetainAll(c);
     }
   }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
index 652b095..af19393 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
@@ -21,7 +21,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.CollectPreconditions.checkRemove;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
@@ -227,7 +228,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return removeAll(key);
     }
 
-    // TODO(user): investigate atomic failure?
+    // TODO(lowasser): investigate atomic failure?
     Collection<V> collection = getOrCreateCollection(key);
     Collection<V> oldValues = createCollection();
     oldValues.addAll(collection);
@@ -324,8 +325,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     }
   }
 
-  private List<V> wrapList(
-      @Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
+  private List<V> wrapList(@Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
     return (list instanceof RandomAccess)
         ? new RandomAccessWrappedList(key, list, ancestor)
         : new WrappedList(key, list, ancestor);
@@ -348,19 +348,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * removeIfEmpty}, and {@code addToMap} methods call the corresponding methods
    * of the full wrapped collection.
    */
+  @WeakOuter
   private class WrappedCollection extends AbstractCollection<V> {
     final K key;
     Collection<V> delegate;
     final WrappedCollection ancestor;
     final Collection<V> ancestorDelegate;
 
-    WrappedCollection(@Nullable K key, Collection<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+    WrappedCollection(
+        @Nullable K key, Collection<V> delegate, @Nullable WrappedCollection ancestor) {
       this.key = key;
       this.delegate = delegate;
       this.ancestor = ancestor;
-      this.ancestorDelegate
-          = (ancestor == null) ? null : ancestor.getDelegate();
+      this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate();
     }
 
     /**
@@ -415,12 +415,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       }
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       refreshIfEmpty();
       return delegate.size();
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -428,12 +430,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return delegate.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       refreshIfEmpty();
       return delegate.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       refreshIfEmpty();
       return delegate.toString();
     }
@@ -442,7 +446,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return delegate;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       refreshIfEmpty();
       return new WrappedIterator();
     }
@@ -496,7 +501,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       }
     }
 
-    @Override public boolean add(V value) {
+    @Override
+    public boolean add(V value) {
       refreshIfEmpty();
       boolean wasEmpty = delegate.isEmpty();
       boolean changed = delegate.add(value);
@@ -515,11 +521,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are provided for better performance.
 
-    @Override public boolean addAll(Collection<? extends V> collection) {
+    @Override
+    public boolean addAll(Collection<? extends V> collection) {
       if (collection.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.addAll(collection);
       if (changed) {
         int newSize = delegate.size();
@@ -531,27 +538,31 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       refreshIfEmpty();
       return delegate.contains(o);
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       refreshIfEmpty();
       return delegate.containsAll(c);
     }
 
-    @Override public void clear() {
-      int oldSize = size();  // calls refreshIfEmpty
+    @Override
+    public void clear() {
+      int oldSize = size(); // calls refreshIfEmpty
       if (oldSize == 0) {
         return;
       }
       delegate.clear();
       totalSize -= oldSize;
-      removeIfEmpty();       // maybe shouldn't be removed if this is a sublist
+      removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       refreshIfEmpty();
       boolean changed = delegate.remove(o);
       if (changed) {
@@ -561,11 +572,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.removeAll(c);
       if (changed) {
         int newSize = delegate.size();
@@ -575,9 +587,10 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       checkNotNull(c);
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.retainAll(c);
       if (changed) {
         int newSize = delegate.size();
@@ -595,6 +608,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /** Set decorator that stays in sync with the multimap values for a key. */
+  @WeakOuter
   private class WrappedSet extends WrappedCollection implements Set<V> {
     WrappedSet(@Nullable K key, Set<V> delegate) {
       super(key, delegate, null);
@@ -605,7 +619,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
 
       // Guava issue 1013: AbstractSet and most JDK set implementations are
       // susceptible to quadratic removeAll performance on lists;
@@ -623,10 +637,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   /**
    * SortedSet decorator that stays in sync with the multimap values for a key.
    */
-  private class WrappedSortedSet extends WrappedCollection
-      implements SortedSet<V> {
-    WrappedSortedSet(@Nullable K key, SortedSet<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+  @WeakOuter
+  private class WrappedSortedSet extends WrappedCollection implements SortedSet<V> {
+    WrappedSortedSet(@Nullable K key, SortedSet<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
 
@@ -655,7 +668,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> headSet(V toElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().headSet(toElement),
+          getKey(),
+          getSortedSetDelegate().headSet(toElement),
           (getAncestor() == null) ? this : getAncestor());
     }
 
@@ -663,7 +677,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> subSet(V fromElement, V toElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().subSet(fromElement, toElement),
+          getKey(),
+          getSortedSetDelegate().subSet(fromElement, toElement),
           (getAncestor() == null) ? this : getAncestor());
     }
 
@@ -671,15 +686,16 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> tailSet(V fromElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().tailSet(fromElement),
+          getKey(),
+          getSortedSetDelegate().tailSet(fromElement),
           (getAncestor() == null) ? this : getAncestor());
     }
   }
 
   /** List decorator that stays in sync with the multimap values for a key. */
+  @WeakOuter
   private class WrappedList extends WrappedCollection implements List<V> {
-    WrappedList(@Nullable K key, List<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+    WrappedList(@Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
 
@@ -692,7 +708,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = getListDelegate().addAll(index, c);
       if (changed) {
         int newSize = getDelegate().size();
@@ -763,14 +779,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     @Override
     public List<V> subList(int fromIndex, int toIndex) {
       refreshIfEmpty();
-      return wrapList(getKey(),
+      return wrapList(
+          getKey(),
           getListDelegate().subList(fromIndex, toIndex),
           (getAncestor() == null) ? this : getAncestor());
     }
 
     /** ListIterator decorator. */
-    private class WrappedListIterator extends WrappedIterator
-        implements ListIterator<V> {
+    private class WrappedListIterator extends WrappedIterator implements ListIterator<V> {
       WrappedListIterator() {}
 
       public WrappedListIterator(int index) {
@@ -822,10 +838,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * List decorator that stays in sync with the multimap values for a key and
    * supports rapid random access.
    */
-  private class RandomAccessWrappedList extends WrappedList
-      implements RandomAccess {
-    RandomAccessWrappedList(@Nullable K key, List<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+  private class RandomAccessWrappedList extends WrappedList implements RandomAccess {
+    RandomAccessWrappedList(
+        @Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
   }
@@ -835,17 +850,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     // TreeMultimap uses NavigableKeySet explicitly, but we don't handle that here for GWT
     // compatibility reasons
     return (map instanceof SortedMap)
-        ? new SortedKeySet((SortedMap<K, Collection<V>>) map) : new KeySet(map);
+        ? new SortedKeySet((SortedMap<K, Collection<V>>) map)
+        : new KeySet(map);
   }
 
+  @WeakOuter
   private class KeySet extends Maps.KeySet<K, Collection<V>> {
     KeySet(final Map<K, Collection<V>> subMap) {
       super(subMap);
     }
 
-    @Override public Iterator<K> iterator() {
-      final Iterator<Map.Entry<K, Collection<V>>> entryIterator
-          = map().entrySet().iterator();
+    @Override
+    public Iterator<K> iterator() {
+      final Iterator<Map.Entry<K, Collection<V>>> entryIterator = map().entrySet().iterator();
       return new Iterator<K>() {
         Map.Entry<K, Collection<V>> entry;
 
@@ -853,11 +870,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
         public boolean hasNext() {
           return entryIterator.hasNext();
         }
+
         @Override
         public K next() {
           entry = entryIterator.next();
           return entry.getKey();
         }
+
         @Override
         public void remove() {
           checkRemove(entry != null);
@@ -871,7 +890,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are included for better performance.
 
-    @Override public boolean remove(Object key) {
+    @Override
+    public boolean remove(Object key) {
       int count = 0;
       Collection<V> collection = map().remove(key);
       if (collection != null) {
@@ -887,19 +907,23 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       Iterators.clear(iterator());
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return map().keySet().containsAll(c);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return this == object || this.map().keySet().equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return map().keySet().hashCode();
     }
   }
 
+  @WeakOuter
   private class SortedKeySet extends KeySet implements SortedSet<K> {
 
     SortedKeySet(SortedMap<K, Collection<V>> subMap) {
@@ -1004,7 +1028,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * <p>The iterator generated by the returned collection traverses the values
    * for one key, followed by the values of a second key, and so on.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
@@ -1062,10 +1087,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     // TreeMultimap uses NavigableAsMap explicitly, but we don't handle that here for GWT
     // compatibility reasons
     return (map instanceof SortedMap)
-        ? new SortedAsMap((SortedMap<K, Collection<V>>) map) : new AsMap(map);
+        ? new SortedAsMap((SortedMap<K, Collection<V>>) map)
+        : new AsMap(map);
   }
 
-  private class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+  @WeakOuter
+  private class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
     /**
      * Usually the same as map, but smaller for the headMap(), tailMap(), or
      * subMap() of a SortedAsMap.
@@ -1083,11 +1110,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are included for performance.
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return Maps.safeContainsKey(submap, key);
     }
 
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       Collection<V> collection = Maps.safeGet(submap, key);
       if (collection == null) {
         return null;
@@ -1097,7 +1126,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return wrapCollection(k, collection);
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return AbstractMapBasedMultimap.this.keySet();
     }
 
@@ -1106,7 +1136,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return submap.size();
     }
 
-    @Override public Collection<V> remove(Object key) {
+    @Override
+    public Collection<V> remove(Object key) {
       Collection<V> collection = submap.remove(key);
       if (collection == null) {
         return null;
@@ -1119,15 +1150,18 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return output;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return this == object || submap.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return submap.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return submap.toString();
     }
 
@@ -1145,23 +1179,27 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return Maps.immutableEntry(key, wrapCollection(key, entry.getValue()));
     }
 
+    @WeakOuter
     class AsMapEntries extends Maps.EntrySet<K, Collection<V>> {
       @Override
       Map<K, Collection<V>> map() {
         return AsMap.this;
       }
 
-      @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+      @Override
+      public Iterator<Map.Entry<K, Collection<V>>> iterator() {
         return new AsMapIterator();
       }
 
       // The following methods are included for performance.
 
-      @Override public boolean contains(Object o) {
+      @Override
+      public boolean contains(Object o) {
         return Collections2.safeContains(submap.entrySet(), o);
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (!contains(o)) {
           return false;
         }
@@ -1173,8 +1211,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     /** Iterator across all keys and value collections. */
     class AsMapIterator implements Iterator<Map.Entry<K, Collection<V>>> {
-      final Iterator<Map.Entry<K, Collection<V>>> delegateIterator
-          = submap.entrySet().iterator();
+      final Iterator<Map.Entry<K, Collection<V>>> delegateIterator = submap.entrySet().iterator();
       Collection<V> collection;
 
       @Override
@@ -1198,8 +1235,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     }
   }
 
-  private class SortedAsMap extends AsMap
-      implements SortedMap<K, Collection<V>> {
+  @WeakOuter
+  private class SortedAsMap extends AsMap implements SortedMap<K, Collection<V>> {
     SortedAsMap(SortedMap<K, Collection<V>> submap) {
       super(submap);
     }
@@ -1242,7 +1279,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // returns a SortedSet, even though returning a Set would be sufficient to
     // satisfy the SortedMap.keySet() interface
-    @Override public SortedSet<K> keySet() {
+    @Override
+    public SortedSet<K> keySet() {
       SortedSet<K> result = sortedKeySet;
       return (result == null) ? sortedKeySet = createKeySet() : result;
     }
@@ -1255,3 +1293,4 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
   private static final long serialVersionUID = 2447537837011683357L;
 }
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
index e2b9cae..60ec200 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
@@ -42,8 +42,7 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  */
 @GwtCompatible(emulated = true)
-abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
-    implements Serializable {
+abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
 
   private transient Map<E, Count> backingMap;
 
@@ -81,8 +80,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
 
   @Override
   Iterator<Entry<E>> entryIterator() {
-    final Iterator<Map.Entry<E, Count>> backingEntries =
-        backingMap.entrySet().iterator();
+    final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
     return new Iterator<Multiset.Entry<E>>() {
       Map.Entry<E, Count> toRemove;
 
@@ -100,6 +98,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
           public E getElement() {
             return mapEntry.getKey();
           }
+
           @Override
           public int getCount() {
             Count count = mapEntry.getValue();
@@ -140,11 +139,13 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
 
   // Optimizations - Query Operations
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return Ints.saturatedCast(size);
   }
 
-  @Override public Iterator<E> iterator() {
+  @Override
+  public Iterator<E> iterator() {
     return new MapBasedMultisetIterator();
   }
 
@@ -194,7 +195,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
     }
   }
 
-  @Override public int count(@Nullable Object element) {
+  @Override
+  public int count(@Nullable Object element) {
     Count frequency = Maps.safeGet(backingMap, element);
     return (frequency == null) ? 0 : frequency.get();
   }
@@ -208,12 +210,12 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
    *     {@link Integer#MAX_VALUE} occurrences of {@code element} in this
    *     multiset.
    */
-  @Override public int add(@Nullable E element, int occurrences) {
+  @Override
+  public int add(@Nullable E element, int occurrences) {
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(
-        occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+    checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
     Count frequency = backingMap.get(element);
     int oldCount;
     if (frequency == null) {
@@ -222,20 +224,19 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
     } else {
       oldCount = frequency.get();
       long newCount = (long) oldCount + (long) occurrences;
-      checkArgument(newCount <= Integer.MAX_VALUE,
-          "too many occurrences: %s", newCount);
+      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) {
+  @Override
+  public int remove(@Nullable Object element, int occurrences) {
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(
-        occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+    checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
     Count frequency = backingMap.get(element);
     if (frequency == null) {
       return 0;
@@ -257,7 +258,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
   }
 
   // Roughly a 33% performance improvement over AbstractMultiset.setCount().
-  @Override public int setCount(@Nullable E element, int count) {
+  @Override
+  public int setCount(@Nullable E element, int count) {
     checkNonnegative(count, "count");
 
     Count existingCounter;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
index 5c12596..3f3f93d 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
@@ -50,13 +50,13 @@ import java.util.List;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
@@ -82,8 +82,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> ArrayListMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
   }
 
@@ -93,8 +92,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    *
    * @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) {
+  public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
     return new ArrayListMultimap<K, V>(multimap);
   }
 
@@ -110,10 +108,11 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
   }
 
   private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
-    this(multimap.keySet().size(),
-        (multimap instanceof ArrayListMultimap) ?
-            ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey :
-            DEFAULT_VALUES_PER_KEY);
+    this(
+        multimap.keySet().size(),
+        (multimap instanceof ArrayListMultimap)
+            ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
+            : DEFAULT_VALUES_PER_KEY);
     putAll(multimap);
   }
 
@@ -121,7 +120,8 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    * Creates a new, empty {@code ArrayList} to hold the collection of values for
    * an arbitrary key.
    */
-  @Override List<V> createCollection() {
+  @Override
+  List<V> createCollection() {
     return new ArrayList<V>(expectedValuesPerKey);
   }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
index 9ac68a1..b798a3e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
@@ -23,13 +23,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collection;
 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;
@@ -73,7 +75,7 @@ import javax.annotation.Nullable;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
  * {@code Table}</a>.
  *
  * @author Jared Levy
@@ -127,8 +129,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    */
   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);
+        ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
+        : new ArrayTable<R, C, V>(table);
   }
 
   private final ImmutableList<R> rowList;
@@ -139,8 +141,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   private final ImmutableMap<C, Integer> columnKeyToIndex;
   private final V[][] array;
 
-  private ArrayTable(Iterable<? extends R> rowKeys,
-      Iterable<? extends C> columnKeys) {
+  private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
     this.rowList = ImmutableList.copyOf(rowKeys);
     this.columnList = ImmutableList.copyOf(columnKeys);
     checkArgument(!rowList.isEmpty());
@@ -151,25 +152,16 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
      * 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);
+    rowKeyToIndex = Maps.indexMap(rowList);
+    columnKeyToIndex = Maps.indexMap(columnList);
 
     @SuppressWarnings("unchecked")
-    V[][] tmpArray
-        = (V[][]) new Object[rowList.size()][columnList.size()];
+    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);
@@ -190,7 +182,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     }
   }
 
-  private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
+  private abstract static class ArrayMap<K, V> extends IteratorBasedAbstractMap<K, V> {
     private final ImmutableMap<K, Integer> keyIndex;
 
     private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
@@ -208,9 +200,11 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
 
     abstract String getKeyRole();
 
-    @Nullable abstract V getValue(int index);
+    @Nullable
+    abstract V getValue(int index);
 
-    @Nullable abstract V setValue(int index, V newValue);
+    @Nullable
+    abstract V setValue(int index, V newValue);
 
     @Override
     public int size() {
@@ -223,41 +217,31 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     }
 
     @Override
-    protected Set<Entry<K, V>> createEntrySet() {
-      return new Maps.EntrySet<K, V>() {
+    Iterator<Entry<K, V>> entryIterator() {
+      return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
         @Override
-        Map<K, V> map() {
-          return ArrayMap.this;
-        }
+        protected Entry<K, V> get(final int index) {
+          return new AbstractMapEntry<K, V>() {
+            @Override
+            public K getKey() {
+              return ArrayMap.this.getKey(index);
+            }
 
-        @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);
-                }
-              };
+            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
+    // TODO(lowasser): consider an optimized values() implementation
 
     @Override
     public boolean containsKey(@Nullable Object key) {
@@ -363,7 +347,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    * @deprecated Use {@link #eraseAll}
    */
   @Override
-  @Deprecated public void clear() {
+  @Deprecated
+  public void clear() {
     throw new UnsupportedOperationException();
   }
 
@@ -420,8 +405,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   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);
+    return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
   }
 
   /**
@@ -445,8 +429,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     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);
+    checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
     return set(rowIndex, columnIndex, value);
   }
 
@@ -478,7 +461,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    * @deprecated Use {@link #erase}
    */
   @Override
-  @Deprecated public V remove(Object rowKey, Object columnKey) {
+  @Deprecated
+  public V remove(Object rowKey, Object columnKey) {
     throw new UnsupportedOperationException();
   }
 
@@ -532,18 +516,22 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   @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) {
+      @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);
@@ -569,8 +557,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   public Map<R, V> column(C columnKey) {
     checkNotNull(columnKey);
     Integer columnIndex = columnKeyToIndex.get(columnKey);
-    return (columnIndex == null)
-        ? ImmutableMap.<R, V>of() : new Column(columnIndex);
+    return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
   }
 
   private class Column extends ArrayMap<R, V> {
@@ -616,6 +603,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     return (map == null) ? columnMap = new ColumnMap() : map;
   }
 
+  @WeakOuter
   private class ColumnMap extends ArrayMap<C, Map<R, V>> {
     private ColumnMap() {
       super(columnKeyToIndex);
@@ -705,6 +693,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     return (map == null) ? rowMap = new RowMap() : map;
   }
 
+  @WeakOuter
   private class RowMap extends ArrayMap<R, Map<C, V>> {
     private RowMap() {
       super(rowKeyToIndex);
@@ -747,3 +736,4 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
 
   private static final long serialVersionUID = 0;
 }
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
index 6c87148..ae40605 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
@@ -30,7 +30,7 @@ import java.util.Iterator;
  * @author Louis Wasserman
  */
 public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
-  // TODO(user): make this GWT-compatible when we've checked in ArrayDeque and BitSet emulation
+  // TODO(lowasser): 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
@@ -80,7 +80,7 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
     };
   }
 
-  // TODO(user): see if any significant optimizations are possible for breadthFirstIterator
+  // TODO(lowasser): see if any significant optimizations are possible for breadthFirstIterator
 
   public final FluentIterable<T> inOrderTraversal(final T root) {
     checkNotNull(root);
@@ -91,11 +91,11 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
       }
     };
   }
-
+  
   private static final class InOrderNode<T> {
     final T node;
     boolean hasExpandedLeft;
-
+    
     InOrderNode(T node) {
       this.node = checkNotNull(node);
       this.hasExpandedLeft = false;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
index 0c8393a..015a81e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
@@ -63,10 +63,12 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
     }
 
     // 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;
+    boolean empty =
+        effectiveRange.isEmpty()
+            || Range.compareOrThrow(
+                    range.lowerBound.leastValueAbove(domain),
+                    range.upperBound.greatestValueBelow(domain))
+                > 0;
 
     return empty
         ? new EmptyContiguousSet<C>(domain)
@@ -80,30 +82,37 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
     this.domain = domain;
   }
 
-  @Override public ContiguousSet<C> headSet(C toElement) {
+  @Override
+  public ContiguousSet<C> headSet(C toElement) {
     return headSetImpl(checkNotNull(toElement), false);
   }
 
-  @Override public ContiguousSet<C> subSet(C fromElement, C toElement) {
+  @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);
   }
 
-  @Override public ContiguousSet<C> tailSet(C fromElement) {
+  @Override
+  public ContiguousSet<C> tailSet(C fromElement) {
     return tailSetImpl(checkNotNull(fromElement), true);
   }
 
   /*
    * These methods perform most headSet, subSet, and tailSet logic, besides parameter validation.
    */
-  /*@Override*/ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
+  // TODO(kevinb): we can probably make these real @Overrides now
+  /*@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> subSetImpl(
+      C fromElement, boolean fromInclusive, C toElement, boolean toInclusive);
 
-  /*@Override*/ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
+  /*@Override*/
+  abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
 
   /**
    * Returns the set of values that are contained in both this set and the other.
@@ -135,7 +144,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
   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() {
+  @Override
+  public String toString() {
     return range().toString();
   }
 
@@ -147,7 +157,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
    * @throws UnsupportedOperationException always
    * @deprecated Use {@link #create}.
    */
-  @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+  @Deprecated
+  public static <E> ImmutableSortedSet.Builder<E> builder() {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
index 368e856..927e889 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
@@ -10,7 +10,7 @@
  * 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;
@@ -32,64 +32,84 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
     super(domain);
   }
 
-  @Override public C first() {
+  @Override
+  public C first() {
     throw new NoSuchElementException();
   }
 
-  @Override public C last() {
+  @Override
+  public C last() {
     throw new NoSuchElementException();
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return 0;
   }
 
-  @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+  @Override
+  public ContiguousSet<C> intersection(ContiguousSet<C> other) {
     return this;
   }
 
-  @Override public Range<C> range() {
+  @Override
+  public Range<C> range() {
     throw new NoSuchElementException();
   }
 
-  @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+  @Override
+  public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
     throw new NoSuchElementException();
   }
 
-  @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
     return this;
   }
 
-  @Override ContiguousSet<C> subSetImpl(
+  @Override
+  ContiguousSet<C> subSetImpl(
       C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
     return this;
   }
 
-  @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
+  @Override
+  ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
     return this;
   }
 
-  @Override public UnmodifiableIterator<C> iterator() {
+  @Override
+  public boolean contains(Object object) {
+    return false;
+  }
+
+  @Override
+  public UnmodifiableIterator<C> iterator() {
     return Iterators.emptyIterator();
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return true;
   }
 
-  @Override public ImmutableList<C> asList() {
+  @Override
+  public ImmutableList<C> asList() {
     return ImmutableList.of();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "[]";
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof Set) {
       Set<?> that = (Set<?>) object;
       return that.isEmpty();
@@ -97,7 +117,8 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return 0;
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java
deleted file mode 100644
index 4159cd4..0000000
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.TreeMap;
-
-/**
- * GWT emulated version of {@link EmptyImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-final class EmptyImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
-  private EmptyImmutableSortedMap(Comparator<? super K> comparator) {
-    super(new TreeMap<K, V>(comparator), comparator);
-  }
-
-  @SuppressWarnings("unchecked")
-  private static final ImmutableSortedMap<Object, Object> NATURAL_EMPTY_MAP =
-      new EmptyImmutableSortedMap<Object, Object>(NATURAL_ORDER);
-
-  static <K, V> ImmutableSortedMap<K, V> forComparator(Comparator<? super K> comparator) {
-    if (comparator == NATURAL_ORDER) {
-      return (ImmutableSortedMap) NATURAL_EMPTY_MAP;
-    }
-    return new EmptyImmutableSortedMap<K, V>(comparator);
-  }
-}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
index 46fa641..a3f4757 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
@@ -28,17 +28,16 @@ import java.util.Map;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
  * {@code BiMap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
-public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
-    extends AbstractBiMap<K, V> {
+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;
 
@@ -49,8 +48,8 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
    * @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) {
+  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);
   }
 
@@ -64,15 +63,15 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
    * @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) {
+  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)),
+    super(
+        WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
         WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
     this.keyType = keyType;
     this.valueType = valueType;
@@ -86,7 +85,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
       return ((EnumHashBiMap<K, ?>) map).keyType();
     }
     checkArgument(!map.isEmpty());
-    return map.keySet().iterator().next().getDeclaringClass();
+    return map
+        .keySet()
+        .iterator()
+        .next()
+        .getDeclaringClass();
   }
 
   private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
@@ -94,7 +97,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
       return ((EnumBiMap<?, V>) map).valueType;
     }
     checkArgument(!map.isEmpty());
-    return map.values().iterator().next().getDeclaringClass();
+    return map
+        .values()
+        .iterator()
+        .next()
+        .getDeclaringClass();
   }
 
   /** Returns the associated key type. */
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
index 3d9503f..3ff3ce5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
@@ -30,17 +30,16 @@ import javax.annotation.Nullable;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
  * {@code BiMap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
-public final class EnumHashBiMap<K extends Enum<K>, V>
-    extends AbstractBiMap<K, V> {
+public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
   private transient Class<K> keyType;
 
   /**
@@ -48,8 +47,7 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
    *
    * @param keyType the key type
    */
-  public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
-      create(Class<K> keyType) {
+  public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
     return new EnumHashBiMap<K, V>(keyType);
   }
 
@@ -63,18 +61,16 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
    * @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) {
+  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));
+    super(
+        WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+        Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
     this.keyType = keyType;
   }
 
@@ -85,11 +81,13 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
     return checkNotNull(key);
   }
 
-  @Override public V put(K key, @Nullable V value) {
+  @Override
+  public V put(K key, @Nullable V value) {
     return super.put(key, value);
   }
 
-  @Override public V forcePut(K key, @Nullable V value) {
+  @Override
+  public V forcePut(K key, @Nullable V value) {
     return super.forcePut(key, value);
   }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
index 4e769fb..e463409 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
@@ -23,13 +23,13 @@ import java.util.Iterator;
 
 /**
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
@@ -54,12 +54,12 @@ public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMulti
     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) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
index 641b052..c98fc2f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
@@ -36,34 +36,72 @@ import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
- * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
- * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
- * of elements. The following types of methods are provided on {@code FluentIterable}:
+ * An expanded {@code Iterable} API, providing functionality similar to Java 8's powerful <a href=
+ * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description"
+ * >streams library</a> in a slightly different way.
+ *
+ * <p>The following types of methods are provided:
+ *
  * <ul>
- * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
- * of the current one (for example {@link #transform})
- * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
- * array (for example {@link #toList})
+ * <li>chaining methods which return a new {@code FluentIterable} based in some way on the contents
+ *     of the current one (for example {@link #transform})
  * <li>element extraction methods which facilitate the retrieval of certain elements (for example
- * {@link #last})
+ *     {@link #last})
  * <li>query methods which answer questions about the {@code FluentIterable}'s contents (for example
- * {@link #anyMatch})
+ *     {@link #anyMatch})
+ * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
+ *     array (for example {@link #toList})
+ * </ul>
+ *
+ * <p>Several lesser-used features are currently available only as static methods on the {@link
+ * Iterables} class.
+ *
+ * <a name="streams"></a>
+ * <h3>Comparison to streams</h3>
+ *
+ * <p>Starting with Java 8, the core Java class libraries provide a new "Streams" library (in {@code
+ * java.util.stream}), which is similar to {@code FluentIterable} but generally more powerful. Key
+ * differences include:</b>
+ *
+ * <ul>
+ * <li>A stream is <i>single-use</i>; it becomes invalid as soon as any "terminal operation" such as
+ *     {@code findFirst()} or {@code iterator()} is invoked. (Even though {@code Stream} contains
+ *     all the right method <i>signatures</i> to implement {@link Iterable}, it does not actually
+ *     do so, to avoid implying repeat-iterability.) {@code FluentIterable}, on the other hand, is
+ *     multiple-use, and does implement {@link Iterable}.
+ * <li>Streams offer many features not found here, including {@code min/max}, {@code
+ *     distinct}, {@code reduce}, {@code sorted}, the very powerful {@code collect}, and built-in
+ *     support for parallelizing stream operations.
+ * <li>{@code FluentIterable} contains several features not available on {@code Stream}, which are
+ *     noted in the method descriptions below.
+ * <li>Streams include primitive-specialized variants such as {@code IntStream}, the use of which is
+ *     strongly recommended.
+ * <li>Streams are standard Java, not requiring a third-party dependency (but do render your code
+ *     incompatible with Java 7 and earlier).
  * </ul>
  *
- * <p>Here is an example that merges the lists returned by two separate database calls, transforms
- * it by invoking {@code toString()} on each element, and returns the first 10 elements as an
- * {@code ImmutableList}: <pre>   {@code
+ * <h3>Example</h3>
  *
- *   FluentIterable
- *       .from(database.getClientList())
- *       .filter(activeInLastMonth())
- *       .transform(Functions.toStringFunction())
- *       .limit(10)
- *       .toList();}</pre>
+ * <p>Here is an example that accepts a list from a database call, filters it based on a predicate,
+ * transforms it by invoking {@code toString()} on each element, and returns the first 10 elements
+ * as a {@code List}: <pre>   {@code
  *
- * <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
- * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
- * operations significantly more concise.
+ *   List<String> results =
+ *       FluentIterable.from(database.getClientList())
+ *           .filter(activeInLastMonthPredicate)
+ *           .transform(Functions.toStringFunction())
+ *           .limit(10)
+ *           .toList();}</pre>
+ *
+ * The approximate stream equivalent is: <pre>   {@code
+ *
+ *   List<String> results =
+ *       database.getClientList()
+ *           .stream()
+ *           .filter(activeInLastMonthPredicate)
+ *           .map(Functions.toStringFunction())
+ *           .limit(10)
+ *           .collect(Collectors.toList());}</pre>
  *
  * @author Marcin Mikosik
  * @since 12.0
@@ -86,9 +124,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
    * is already a {@code FluentIterable}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code iterable.stream()} if {@code iterable} is a
+   * {@link Collection}; {@code StreamSupport.stream(iterable.spliterator(), false)} otherwise.
    */
+  @CheckReturnValue
   public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
-    return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
+    return (iterable instanceof FluentIterable)
+        ? (FluentIterable<E>) iterable
         : new FluentIterable<E>(iterable) {
           @Override
           public Iterator<E> iterator() {
@@ -106,6 +149,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *     {@code FluentIterable}
    */
   @Deprecated
+  @CheckReturnValue
   public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
     return checkNotNull(iterable);
   }
@@ -113,9 +157,13 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a fluent iterable containing {@code elements} in the specified order.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.of(elements)} or {@code
+   * Arrays.stream(elements)}.
+   *
    * @since 18.0
    */
   @Beta
+  @CheckReturnValue
   public static <E> FluentIterable<E> of(E[] elements) {
     return from(Lists.newArrayList(elements));
   }
@@ -123,25 +171,35 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a string representation of this fluent iterable, with the format
    * {@code [e1, e2, ..., en]}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.joining(", ", "[", "]"))}
+   * or (less efficiently) {@code collect(Collectors.toList()).toString()}.
    */
   @Override
+  @CheckReturnValue
   public String toString() {
     return Iterables.toString(iterable);
   }
 
   /**
    * Returns the number of elements in this fluent iterable.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.count()}.
    */
+  @CheckReturnValue
   public final int size() {
     return Iterables.size(iterable);
   }
 
   /**
    * Returns {@code true} if this fluent iterable contains any object for which
-   * {@code equals(element)} is true.
+   * {@code equals(target)} is true.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(Predicate.isEqual(target))}.
    */
-  public final boolean contains(@Nullable Object element) {
-    return Iterables.contains(iterable, element);
+  @CheckReturnValue
+  public final boolean contains(@Nullable Object target) {
+    return Iterables.contains(iterable, target);
   }
 
   /**
@@ -156,6 +214,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p><b>Warning:</b> Typical uses of the resulting iterator may produce an infinite loop. You
    * should use an explicit {@code break} or be certain that you will eventually remove all the
    * elements.
+   *
+   * <p><b>{@code Stream} equivalent:</b> if the source iterable has only a single element {@code
+   * element}, use {@code Stream.generate(() -> element)}. Otherwise, if the source iterable has
+   * a {@code stream} method (for example, if it is a {@link Collection}), use
+   * {@code Stream.generate(iterable::stream).flatMap(s -> s)}.
    */
   @CheckReturnValue
   public final FluentIterable<E> cycle() {
@@ -169,6 +232,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
    * {@code Iterator} supports it.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, otherStream)}.
+   *
    * @since 18.0
    */
   @Beta
@@ -181,6 +246,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
    * followed by {@code elements}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, Stream.of(elements))}.
+   *
    * @since 18.0
    */
   @Beta
@@ -192,6 +259,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns the elements from this fluent iterable that satisfy a predicate. The
    * resulting fluent iterable's iterator does not support {@code remove()}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate)} (same).
    */
   @CheckReturnValue
   public final FluentIterable<E> filter(Predicate<? super E> predicate) {
@@ -200,7 +269,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
 
   /**
    * Returns {@code true} if any element in this fluent iterable satisfies the predicate.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(predicate)} (same).
    */
+  @CheckReturnValue
   public final boolean anyMatch(Predicate<? super E> predicate) {
     return Iterables.any(iterable, predicate);
   }
@@ -208,7 +280,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns {@code true} if every element in this fluent iterable satisfies the predicate.
    * If this fluent iterable is empty, {@code true} is returned.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.allMatch(predicate)} (same).
    */
+  @CheckReturnValue
   public final boolean allMatch(Predicate<? super E> predicate) {
     return Iterables.all(iterable, predicate);
   }
@@ -219,7 +294,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *
    * <p><b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If {@code null}
    * is matched in this fluent iterable, a {@link NullPointerException} will be thrown.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate).findFirst()}.
    */
+  @CheckReturnValue
   public final Optional<E> firstMatch(Predicate<? super E> predicate) {
     return Iterables.tryFind(iterable, predicate);
   }
@@ -231,7 +309,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
    * iterator does. After a successful {@code remove()} call, this fluent iterable no longer
    * contains the corresponding element.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.map(function)}.
    */
+  @CheckReturnValue
   public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
     return from(Iterables.transform(iterable, function));
   }
@@ -245,8 +326,12 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * function-returned iterables' iterator does. After a successful {@code remove()} call,
    * the returned fluent iterable no longer contains the corresponding element.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.flatMap(function)} (using a function that
+   * produces streams, not iterables).
+   *
    * @since 13.0 (required {@code Function<E, Iterable<T>>} until 14.0)
    */
+  @CheckReturnValue
   public <T> FluentIterable<T> transformAndConcat(
       Function<? super E, ? extends Iterable<? extends T>> function) {
     return from(Iterables.concat(transform(function)));
@@ -256,23 +341,29 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@link Optional} containing the first element in this fluent iterable.
    * If the iterable is empty, {@code Optional.absent()} is returned.
    *
+   * <p><b>{@code Stream} equivalent:</b> if the goal is to obtain any element, {@code
+   * stream.findAny()}; if it must specifically be the <i>first</i> element, {@code
+   * stream.findFirst()}.
+   *
    * @throws NullPointerException if the first element is null; if this is a possibility, use
    *     {@code iterator().next()} or {@link Iterables#getFirst} instead.
    */
+  @CheckReturnValue
   public final Optional<E> first() {
     Iterator<E> iterator = iterable.iterator();
-    return iterator.hasNext()
-        ? Optional.of(iterator.next())
-        : Optional.<E>absent();
+    return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.<E>absent();
   }
 
   /**
    * Returns an {@link Optional} containing the last element in this fluent iterable.
    * If the iterable is empty, {@code Optional.absent()} is returned.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.reduce((a, b) -> b)}.
+   *
    * @throws NullPointerException if the last element is null; if this is a possibility, use
    *     {@link Iterables#getLast} instead.
    */
+  @CheckReturnValue
   public final Optional<E> last() {
     // Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
 
@@ -323,6 +414,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * returned fluent iterable's iterator, as the {@code Iterator} contract states that a call
    * to {@code * remove()} before a call to {@code next()} will throw an
    * {@link IllegalStateException}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(numberToSkip)} (same).
    */
   @CheckReturnValue
   public final FluentIterable<E> skip(int numberToSkip) {
@@ -336,17 +429,22 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * The returned fluent iterable's iterator supports {@code remove()} if this
    * fluent iterable's iterator does.
    *
-   * @param size the maximum number of elements in the returned fluent iterable
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.limit(maxSize)} (same).
+   *
+   * @param maxSize the maximum number of elements in the returned fluent iterable
    * @throws IllegalArgumentException if {@code size} is negative
    */
   @CheckReturnValue
-  public final FluentIterable<E> limit(int size) {
-    return from(Iterables.limit(iterable, size));
+  public final FluentIterable<E> limit(int maxSize) {
+    return from(Iterables.limit(iterable, maxSize));
   }
 
   /**
    * Determines whether this fluent iterable is empty.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code !stream.findAny().isPresent()}.
    */
+  @CheckReturnValue
   public final boolean isEmpty() {
     return !iterable.iterator().hasNext();
   }
@@ -355,8 +453,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@code ImmutableList} containing all of the elements from this fluent iterable in
    * proper sequence.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableList.copyOf(stream.iterator())}.
+   *
    * @since 14.0 (since 12.0 as {@code toImmutableList()}).
    */
+  @CheckReturnValue
   public final ImmutableList<E> toList() {
     return ImmutableList.copyOf(iterable);
   }
@@ -366,10 +467,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * FluentIterable} in the order specified by {@code comparator}.  To produce an {@code
    * ImmutableList} sorted by its natural ordering, use {@code toSortedList(Ordering.natural())}.
    *
+   * <p><b>{@code Stream} equivalent:</b>
+   * {@code ImmutableList.copyOf(stream.sorted(comparator).iterator())}.
+   *
    * @param comparator the function by which to sort list elements
    * @throws NullPointerException if any element is null
    * @since 14.0 (since 13.0 as {@code toSortedImmutableList()}).
    */
+  @CheckReturnValue
   public final ImmutableList<E> toSortedList(Comparator<? super E> comparator) {
     return Ordering.from(comparator).immutableSortedCopy(iterable);
   }
@@ -378,8 +483,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@code ImmutableSet} containing all of the elements from this fluent iterable with
    * duplicates removed.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableSet.copyOf(stream.iterator())}.
+   *
    * @since 14.0 (since 12.0 as {@code toImmutableSet()}).
    */
+  @CheckReturnValue
   public final ImmutableSet<E> toSet() {
     return ImmutableSet.copyOf(iterable);
   }
@@ -390,24 +498,48 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * {@code comparator.compare(x, y) == 0}) removed. To produce an {@code ImmutableSortedSet} sorted
    * by its natural ordering, use {@code toSortedSet(Ordering.natural())}.
    *
+   * <p><b>{@code Stream} equivalent:</b>
+   * {@code ImmutableSortedSet.copyOf(comparator, stream.iterator())}.
+   *
    * @param comparator the function by which to sort set elements
    * @throws NullPointerException if any element is null
    * @since 14.0 (since 12.0 as {@code toImmutableSortedSet()}).
    */
+  @CheckReturnValue
   public final ImmutableSortedSet<E> toSortedSet(Comparator<? super E> comparator) {
     return ImmutableSortedSet.copyOf(comparator, iterable);
   }
 
   /**
-   * Returns an immutable map for which the elements of this {@code FluentIterable} are the keys in
-   * the same order, mapped to values by the given function. If this iterable contains duplicate
-   * elements, the returned map will contain each distinct element once in the order it first
-   * appears.
+   * Returns an {@code ImmutableMultiset} containing all of the elements from this fluent iterable.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableMultiset.copyOf(stream.iterator())}.
+   *
+   * @since 19.0
+   */
+  @CheckReturnValue
+  public final ImmutableMultiset<E> toMultiset() {
+    return ImmutableMultiset.copyOf(iterable);
+  }
+
+  /**
+   * Returns an immutable map whose keys are the distinct elements of this {@code FluentIterable}
+   * and whose value for each key was computed by {@code valueFunction}. The map's iteration order
+   * is the order of the first appearance of each key in this iterable.
+   *
+   * <p>When there are multiple instances of a key in this iterable, it is unspecified whether
+   * {@code valueFunction} will be applied to more than one instance of that key and, if it is,
+   * which result will be mapped to that key in the returned map.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code
+   * ImmutableMap.copyOf(stream.collect(Collectors.toMap(k -> k, valueFunction)))} (but note that
+   * this may not preserve the order of entries).
    *
    * @throws NullPointerException if any element of this iterable is {@code null}, or if {@code
    *     valueFunction} produces {@code null} for any key
    * @since 14.0
    */
+  @CheckReturnValue
   public final <V> ImmutableMap<E, V> toMap(Function<? super E, V> valueFunction) {
     return Maps.toMap(iterable, valueFunction);
   }
@@ -428,24 +560,49 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *       <li>An element in this fluent iterable is null
    *       <li>{@code keyFunction} returns {@code null} for any element of this iterable
    *     </ul>
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.groupingBy(keyFunction))}
+   * behaves similarly, but returns a mutable {@code Map<K, List<E>>} instead, and may not preserve
+   * the order of entries).
+   *
    * @since 14.0
    */
+  @CheckReturnValue
   public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
     return Multimaps.index(iterable, keyFunction);
   }
 
   /**
-   * Returns an immutable map for which the {@link java.util.Map#values} are the elements of this
-   * {@code FluentIterable} in the given order, and each key is the product of invoking a supplied
-   * function on its corresponding value.
+   * Returns a map with the contents of this {@code FluentIterable} as its {@code values}, indexed
+   * by keys derived from those values. In other words, each input value produces an entry in the
+   * map whose key is the result of applying {@code keyFunction} to that value. These entries appear
+   * in the same order as they appeared in this fluent iterable. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   FluentIterable<Color> allColors = FluentIterable.from(ImmutableSet.of(red, green, blue));
+   *
+   *   Map<String, Color> colorForName = allColors.uniqueIndex(toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link #index(Function)
+   * index}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code
+   * ImmutableMap.copyOf(stream.collect(Collectors.toMap(keyFunction, v -> v)))} (but note that this
+   * may not preserve the order of entries).
    *
    * @param keyFunction the function used to produce the key for each value
-   * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one
-   *     value in this fluent iterable
-   * @throws NullPointerException if any element of this fluent iterable is null, or if
-   *     {@code keyFunction} produces {@code null} for any value
+   * @return a map mapping the result of evaluating the function {@code
+   *     keyFunction} on each value in this fluent iterable to that value
+   * @throws IllegalArgumentException if {@code keyFunction} produces the same
+   *     key for more than one value in this fluent iterable
+   * @throws NullPointerException if any elements of this fluent iterable is null, or
+   *     if {@code keyFunction} produces {@code null} for any value
    * @since 14.0
    */
+  @CheckReturnValue
   public final <K> ImmutableMap<K, E> uniqueIndex(Function<? super E, K> keyFunction) {
     return Maps.uniqueIndex(iterable, keyFunction);
   }
@@ -454,6 +611,9 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to
    * calling {@code Iterables.addAll(collection, this)}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.forEachOrdered(collection::add)} or
+   * {@code stream.forEach(collection::add)}.
+   *
    * @param collection the collection to copy elements to
    * @return {@code collection}, for convenience
    * @since 14.0
@@ -474,9 +634,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns a {@link String} containing all of the elements of this fluent iterable joined with
    * {@code joiner}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code joiner.join(stream.iterator())}, or, if you are not
+   * using any optional {@code Joiner} features,
+   * {@code stream.collect(Collectors.joining(delimiter)}.
+   *
    * @since 18.0
    */
   @Beta
+  @CheckReturnValue
   public final String join(Joiner joiner) {
     return joiner.join(this);
   }
@@ -484,11 +649,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns the element at the specified position in this fluent iterable.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(position).findFirst().get()} (but note
+   * that this throws different exception types, and throws an exception if {@code null} would be
+   * returned).
+   *
    * @param position position of the element to return
    * @return the element at the specified position in this fluent iterable
    * @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
    *     the size of this fluent iterable
    */
+  // TODO(kevinb): add @Nullable?
+  @CheckReturnValue
   public final E get(int position) {
     return Iterables.get(iterable, position);
   }
@@ -496,8 +667,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Function that transforms {@code Iterable<E>} into a fluent iterable.
    */
-  private static class FromIterableFunction<E>
-      implements Function<Iterable<E>, FluentIterable<E>> {
+  private static class FromIterableFunction<E> implements Function<Iterable<E>, FluentIterable<E>> {
     @Override
     public FluentIterable<E> apply(Iterable<E> fromObject) {
       return FluentIterable.from(fromObject);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
index 6240625..164b90c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
@@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit;
  *     com.google.common.cache.CacheBuilder}, which is a properly generified class and thus needs no
  *     "Generic" equivalent; simple use {@code CacheBuilder} naturally. For general migration
  *     instructions, see the <a
- *     href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker Migration
+ *     href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker Migration
  *     Guide</a>.
  */
 @Beta
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
index 582c2f7..196661f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
@@ -39,14 +39,13 @@ import java.util.Set;
  * Multimaps#synchronizedSetMultimap}.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   private static final int DEFAULT_VALUES_PER_KEY = 2;
 
-  @VisibleForTesting
-  transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
+  @VisibleForTesting transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
 
   /**
    * Creates a new, empty {@code HashMultimap} with the default initial
@@ -65,8 +64,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> HashMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new HashMultimap<K, V>(expectedKeys, expectedValuesPerKey);
   }
 
@@ -77,8 +75,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    *
    * @param multimap the multimap whose contents are copied to this multimap
    */
-  public static <K, V> HashMultimap<K, V> create(
-      Multimap<? extends K, ? extends V> multimap) {
+  public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
     return new HashMultimap<K, V>(multimap);
   }
 
@@ -93,8 +90,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   }
 
   private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
-    super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(
-        multimap.keySet().size()));
+    super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(multimap.keySet().size()));
     putAll(multimap);
   }
 
@@ -105,7 +101,8 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    *
    * @return a new {@code HashSet} containing a collection of values for one key
    */
-  @Override Set<V> createCollection() {
+  @Override
+  Set<V> createCollection() {
     return Sets.<V>newHashSetWithExpectedSize(expectedValuesPerKey);
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
index 1ee2d8d..02fb070 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
@@ -25,7 +25,7 @@ import java.util.HashMap;
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
@@ -51,15 +51,14 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
 
   /**
    * Creates a new {@code HashMultiset} 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
    */
   public static <E> HashMultiset<E> create(Iterable<? extends E> elements) {
-    HashMultiset<E> multiset =
-        create(Multisets.inferDistinctElements(elements));
+    HashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
     Iterables.addAll(multiset, elements);
     return multiset;
   }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
index 1279bee..8569c3e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
@@ -30,7 +30,8 @@ import com.google.common.annotations.GwtCompatible;
 abstract class ImmutableAsList<E> extends ImmutableList<E> {
   abstract ImmutableCollection<E> delegateCollection();
 
-  @Override public boolean contains(Object target) {
+  @Override
+  public boolean contains(Object target) {
     // The collection's contains() is at least as fast as ImmutableList's
     // and is often faster.
     return delegateCollection().contains(target);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
index 9ddef1c..518f166 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
@@ -18,7 +18,9 @@ package com.google.common.collect;
 
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 
+import java.util.Comparator;
 import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * GWT emulation of {@link ImmutableBiMap}.
@@ -31,7 +33,7 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
   // Casting to any type is safe because the set will never hold any elements.
   @SuppressWarnings("unchecked")
   public static <K, V> ImmutableBiMap<K, V> of() {
-    return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
+    return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
   }
 
   public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
@@ -69,15 +71,35 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
 
     public Builder() {}
 
+    Builder(int initCapacity) {
+      super(initCapacity);
+    }
+
     @Override public Builder<K, V> put(K key, V value) {
       super.put(key, value);
       return this;
     }
 
+    @Override public Builder<K, V> put(Map.Entry<? extends K, ? extends V> entry) {
+      super.put(entry);
+      return this;
+    }
+
     @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
       super.putAll(map);
       return this;
     }
+    
+    @Override public Builder<K, V> putAll(
+        Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
+      return this;
+    }
+    
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      super.orderEntriesByValue(valueComparator);
+      return this;
+    }
 
     @Override public ImmutableBiMap<K, V> build() {
       ImmutableMap<K, V> map = super.build();
@@ -103,6 +125,11 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
     ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map);
     return new RegularImmutableBiMap<K, V>(immutableMap);
   }
+  
+  public static <K, V> ImmutableBiMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>().putAll(entries).build();
+  }
 
   ImmutableBiMap(Map<K, V> delegate) {
     super(delegate);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
index b0cac0c..7f96ca0 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
@@ -16,6 +16,7 @@
 
 package com.google.common.collect;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
 import java.util.Collection;
@@ -25,31 +26,18 @@ import java.util.Map.Entry;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link ListMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableListMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableListMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link ListMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
-public class ImmutableListMultimap<K, V>
-    extends ImmutableMultimap<K, V>
+public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
     implements ListMultimap<K, V> {
 
   /** Returns the empty multimap. */
@@ -63,8 +51,7 @@ public class ImmutableListMultimap<K, V>
    * Returns an immutable multimap containing a single entry.
    */
   public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     return builder.build();
   }
@@ -73,8 +60,7 @@ public class ImmutableListMultimap<K, V>
    * Returns an immutable multimap containing the given entries, in order.
    */
   public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     return builder.build();
@@ -83,10 +69,8 @@ public class ImmutableListMultimap<K, V>
   /**
    * Returns an immutable multimap containing the given entries, in order.
    */
-  public static <K, V> ImmutableListMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+  public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -98,8 +82,7 @@ public class ImmutableListMultimap<K, V>
    */
   public static <K, V> ImmutableListMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -112,8 +95,7 @@ public class ImmutableListMultimap<K, V>
    */
   public static <K, V> ImmutableListMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -148,17 +130,17 @@ public class ImmutableListMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
-  public static final class Builder<K, V>
-      extends ImmutableMultimap.Builder<K, V> {
+  public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
     /**
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableListMultimap#builder}.
      */
     public Builder() {}
 
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       super.put(key, value);
       return this;
     }
@@ -168,24 +150,38 @@ public class ImmutableListMultimap<K, V>
      *
      * @since 11.0
      */
-    @Override public Builder<K, V> put(
-        Entry<? extends K, ? extends V> entry) {
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
       super.put(entry);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+    /**
+     * {@inheritDoc}
+     *
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
+      return this;
+    }
+
+    @Override
+    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       super.putAll(key, values);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, V... values) {
+    @Override
+    public Builder<K, V> putAll(K key, V... values) {
       super.putAll(key, values);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(
-        Multimap<? extends K, ? extends V> multimap) {
+    @Override
+    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
       super.putAll(multimap);
       return this;
     }
@@ -215,7 +211,8 @@ public class ImmutableListMultimap<K, V>
     /**
      * Returns a newly-created immutable list multimap.
      */
-    @Override public ImmutableListMultimap<K, V> build() {
+    @Override
+    public ImmutableListMultimap<K, V> build() {
       return (ImmutableListMultimap<K, V>) super.build();
     }
   }
@@ -238,21 +235,21 @@ public class ImmutableListMultimap<K, V>
       return of();
     }
 
-    // TODO(user): copy ImmutableSetMultimap by using asList() on the sets
+    // TODO(lowasser): copy ImmutableSetMultimap by using asList() on the sets
     if (multimap instanceof ImmutableListMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableListMultimap<K, V> kvMultimap
-          = (ImmutableListMultimap<K, V>) multimap;
+      ImmutableListMultimap<K, V> kvMultimap = (ImmutableListMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
     }
 
-    ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder();
+    ImmutableMap.Builder<K, ImmutableList<V>> builder =
+        new ImmutableMap.Builder<K, ImmutableList<V>>(multimap.asMap().size());
     int size = 0;
 
-    for (Entry<? extends K, ? extends Collection<? extends V>> entry
-        : multimap.asMap().entrySet()) {
+    for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+        multimap.asMap().entrySet()) {
       ImmutableList<V> list = ImmutableList.copyOf(entry.getValue());
       if (!list.isEmpty()) {
         builder.put(entry.getKey(), list);
@@ -263,6 +260,21 @@ public class ImmutableListMultimap<K, V>
     return new ImmutableListMultimap<K, V>(builder.build(), size);
   }
 
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableListMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>().putAll(entries).build();
+  }
+
   ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) {
     super(map, size);
   }
@@ -275,7 +287,8 @@ public class ImmutableListMultimap<K, V>
    * returned. The values are in the same order as the parameters used to build
    * this multimap.
    */
-  @Override public ImmutableList<V> get(@Nullable K key) {
+  @Override
+  public ImmutableList<V> get(@Nullable K key) {
     // This cast is safe as its type is known in constructor.
     ImmutableList<V> list = (ImmutableList<V>) map.get(key);
     return (list == null) ? ImmutableList.<V>of() : list;
@@ -315,7 +328,9 @@ public class ImmutableListMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableList<V> removeAll(Object key) {
+  @Deprecated
+  @Override
+  public ImmutableList<V> removeAll(Object key) {
     throw new UnsupportedOperationException();
   }
 
@@ -325,8 +340,9 @@ public class ImmutableListMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableList<V> replaceValues(
-      K key, Iterable<? extends V> values) {
+  @Deprecated
+  @Override
+  public ImmutableList<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
index 679e22f..c4f7cc3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
@@ -17,15 +17,19 @@
 package com.google.common.collect;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 import static com.google.common.collect.Iterables.getOnlyElement;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.EnumMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 
@@ -41,7 +45,25 @@ import javax.annotation.Nullable;
  * @author Hayward Chan
  */
 public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
+  abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {
+    abstract UnmodifiableIterator<Entry<K, V>> entryIterator();
+
+    @Override
+    ImmutableSet<Entry<K, V>> createEntrySet() {
+      return new ImmutableMapEntrySet<K, V>() {
+        @Override
+        ImmutableMap<K, V> map() {
+          return IteratorBasedImmutableMap.this;
+        }
 
+        @Override
+        public UnmodifiableIterator<Entry<K, V>> iterator() {
+          return entryIterator();
+        }        
+      };
+    }
+  }
+  
   ImmutableMap() {}
 
   public static <K, V> ImmutableMap<K, V> of() {
@@ -86,9 +108,16 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
   }
 
   public static class Builder<K, V> {
-    final List<Entry<K, V>> entries = Lists.newArrayList();
+    final List<Entry<K, V>> entries;
+    Comparator<? super V> valueComparator;
 
-    public Builder() {}
+    public Builder() {
+      this.entries = Lists.newArrayList();
+    }
+
+    Builder(int initCapacity) {
+      this.entries = Lists.newArrayListWithCapacity(initCapacity);
+    }
 
     public Builder<K, V> put(K key, V value) {
       entries.add(entryOf(key, value));
@@ -109,31 +138,46 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
     }
 
     public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
-      for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
-        put(entry.getKey(), entry.getValue());
+      return putAll(map.entrySet());
+    }
+    
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      for (Entry<? extends K, ? extends V> entry : entries) {
+        put(entry);
       }
       return this;
     }
+    
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      checkState(this.valueComparator == null, "valueComparator was already set");
+      this.valueComparator = checkNotNull(valueComparator, "valueComparator");
+      return this;
+    }
 
     public ImmutableMap<K, V> build() {
+      if (valueComparator != null) {
+        Collections.sort(
+            entries, 
+            Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+      }
       return fromEntryList(entries);
     }
+  }
 
-    private static <K, V> ImmutableMap<K, V> fromEntryList(
-        List<Entry<K, V>> entries) {
-      int size = entries.size();
-      switch (size) {
-        case 0:
-          return of();
-        case 1:
-          Entry<K, V> entry = getOnlyElement(entries);
-          return of(entry.getKey(), entry.getValue());
-        default:
-          @SuppressWarnings("unchecked")
-          Entry<K, V>[] entryArray
-              = entries.toArray(new Entry[entries.size()]);
-          return new RegularImmutableMap<K, V>(entryArray);
-      }
+  static <K, V> ImmutableMap<K, V> fromEntryList(
+      Collection<? extends Entry<? extends K, ? extends V>> entries) {
+    int size = entries.size();
+    switch (size) {
+      case 0:
+        return of();
+      case 1:
+        Entry<? extends K, ? extends V> entry = getOnlyElement(entries);
+        return of((K) entry.getKey(), (V) entry.getValue());
+      default:
+        @SuppressWarnings("unchecked")
+        Entry<K, V>[] entryArray
+            = entries.toArray(new Entry[entries.size()]);
+        return new RegularImmutableMap<K, V>(entryArray);
     }
   }
 
@@ -172,6 +216,16 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
         return new RegularImmutableMap<K, V>(orderPreservingCopy);
     }
   }
+  
+  public static <K, V> ImmutableMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    if (entries instanceof Collection) {
+      return fromEntryList(
+          (Collection<? extends Entry<? extends K, ? extends V>>) entries);
+    } else {
+      return fromEntryList(Lists.newArrayList(entries.iterator()));
+    }
+  }
 
   abstract boolean isPartialView();
 
@@ -229,6 +283,19 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
   ImmutableSet<K> createKeySet() {
     return new ImmutableMapKeySet<K, V>(this);
   }
+  
+  UnmodifiableIterator<K> keyIterator() {
+    final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator();
+    return new UnmodifiableIterator<K>() {
+      @Override public boolean hasNext() {
+        return entryIterator.hasNext();
+      }
+
+      @Override public K next() {
+        return entryIterator.next().getKey();
+      }
+    };
+  }
 
   private transient ImmutableCollection<V> cachedValues = null;
 
@@ -239,82 +306,68 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
     return cachedValues = createValues();
   }
 
-  // esnickell is editing here
-
   // cached so that this.multimapView().inverse() only computes inverse once
   private transient ImmutableSetMultimap<K, V> multimapView;
 
   public ImmutableSetMultimap<K, V> asMultimap() {
     ImmutableSetMultimap<K, V> result = multimapView;
-    return (result == null) ? (multimapView = createMultimapView()) : result;
+    return (result == null) 
+        ? (multimapView = new ImmutableSetMultimap<K, V>(
+            new MapViewOfValuesAsSingletonSets(), size(), null))
+        : result;
   }
+  
+  final class MapViewOfValuesAsSingletonSets 
+      extends IteratorBasedImmutableMap<K, ImmutableSet<V>> {
 
-  private ImmutableSetMultimap<K, V> createMultimapView() {
-    ImmutableMap<K, ImmutableSet<V>> map = viewValuesAsImmutableSet();
-    return new ImmutableSetMultimap<K, V>(map, map.size(), null);
-  }
+    @Override public int size() {
+      return ImmutableMap.this.size();
+    }
+ 
+    @Override public ImmutableSet<K> keySet() {
+      return ImmutableMap.this.keySet();
+    }
 
-  private ImmutableMap<K, ImmutableSet<V>> viewValuesAsImmutableSet() {
-    final Map<K, V> outer = this;
-    return new ImmutableMap<K, ImmutableSet<V>>() {
-      @Override
-      public int size() {
-        return outer.size();
-      }
+    @Override public boolean containsKey(@Nullable Object key) {
+      return ImmutableMap.this.containsKey(key);
+    }
 
-      @Override
-      public ImmutableSet<V> get(@Nullable Object key) {
-        V outerValue = outer.get(key);
-        return outerValue == null ? null : ImmutableSet.of(outerValue);
-      }
+    @Override public ImmutableSet<V> get(@Nullable Object key) {
+      V outerValue = ImmutableMap.this.get(key);
+      return (outerValue == null) ? null : ImmutableSet.of(outerValue);
+    }
 
-      @Override
-      ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
-        return new ImmutableSet<Entry<K, ImmutableSet<V>>>() {
-          @Override
-          public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
-            final Iterator<Entry<K,V>> outerEntryIterator = outer.entrySet().iterator();
-            return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
-              @Override
-              public boolean hasNext() {
-                return outerEntryIterator.hasNext();
-              }
-
-              @Override
-              public Entry<K, ImmutableSet<V>> next() {
-                final Entry<K, V> outerEntry = outerEntryIterator.next();
-                return new AbstractMapEntry<K, ImmutableSet<V>>() {
-                  @Override
-                  public K getKey() {
-                    return outerEntry.getKey();
-                  }
-
-                  @Override
-                  public ImmutableSet<V> getValue() {
-                    return ImmutableSet.of(outerEntry.getValue());
-                  }
-                };
-              }
-            };
-          }
-
-          @Override
-          boolean isPartialView() {
-            return false;
-          }
-
-          @Override
-          public int size() {
-            return outer.size();
-          }
-        };
-      }
+    @Override boolean isPartialView() {
+      return ImmutableMap.this.isPartialView();
+    }
 
-      @Override
-      boolean isPartialView() {
-        return false;
-      }
-    };
+    @Override public int hashCode() {
+      // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same
+      return ImmutableMap.this.hashCode();
+    }
+
+    @Override
+    UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() {
+      final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator();
+      return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
+        @Override public boolean hasNext() {
+          return backingIterator.hasNext();
+        }
+
+        @Override public Entry<K, ImmutableSet<V>> next() {
+          final Entry<K, V> backingEntry = backingIterator.next();
+          return new AbstractMapEntry<K, ImmutableSet<V>>() {
+            @Override public K getKey() {
+              return backingEntry.getKey();
+            }
+
+            @Override public ImmutableSet<V> getValue() {
+              return ImmutableSet.of(backingEntry.getValue());
+            }
+          };
+        }
+      };
+    }
   }
 
   ImmutableCollection<V> createValues() {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
index 7a5e580..4fd69b5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
@@ -17,6 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.Map.Entry;
 
@@ -30,6 +31,31 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
+  static final class RegularEntrySet<K, V> extends ImmutableMapEntrySet<K, V> {
+    @Weak private final transient ImmutableMap<K, V> map;
+    private final transient Entry<K, V>[] entries;
+
+    RegularEntrySet(ImmutableMap<K, V> map, Entry<K, V>[] entries) {
+      this.map = map;
+      this.entries = entries;
+    }
+
+    @Override
+    ImmutableMap<K, V> map() {
+      return map;
+    }
+
+    @Override
+    public UnmodifiableIterator<Entry<K, V>> iterator() {
+      return asList().iterator();
+    }
+
+    @Override
+    ImmutableList<Entry<K, V>> createAsList() {
+      return new RegularImmutableAsList<Entry<K, V>>(this, entries);
+    }
+  }
+
   ImmutableMapEntrySet() {}
 
   abstract ImmutableMap<K, V> map();
@@ -53,5 +79,10 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
   boolean isPartialView() {
     return map().isPartialView();
   }
+
+  @Override
+  public int hashCode() {
+    return map().hashCode();
+  }
 }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
index 78508f4..2469a60 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
@@ -17,8 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
-
-import java.util.Map.Entry;
+import com.google.j2objc.annotations.Weak;
 
 import javax.annotation.Nullable;
 
@@ -29,8 +28,8 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  */
 @GwtCompatible(emulated = true)
-final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
-  private final ImmutableMap<K, V> map;
+final class ImmutableMapKeySet<K, V> extends ImmutableSet.Indexed<K> {
+  @Weak private final ImmutableMap<K, V> map;
 
   ImmutableMapKeySet(ImmutableMap<K, V> map) {
     this.map = map;
@@ -43,7 +42,7 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
 
   @Override
   public UnmodifiableIterator<K> iterator() {
-    return asList().iterator();
+    return map.keyIterator();
   }
 
   @Override
@@ -52,21 +51,8 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
   }
 
   @Override
-  ImmutableList<K> createAsList() {
-    final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
-    return new ImmutableAsList<K>() {
-
-      @Override
-      public K get(int index) {
-        return entryList.get(index).getKey();
-      }
-
-      @Override
-      ImmutableCollection<K> delegateCollection() {
-        return ImmutableMapKeySet.this;
-      }
-
-    };
+  K get(int index) {
+    return map.entrySet().asList().get(index).getKey();
   }
 
   @Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
index ec6a40f..4ba2644 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
@@ -17,6 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.Map.Entry;
 
@@ -30,8 +31,8 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
-  private final ImmutableMap<K, V> map;
-  
+  @Weak private final ImmutableMap<K, V> map;
+
   ImmutableMapValues(ImmutableMap<K, V> map) {
     this.map = map;
   }
@@ -43,7 +44,19 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
 
   @Override
   public UnmodifiableIterator<V> iterator() {
-    return Maps.valueIterator(map.entrySet().iterator());
+    return new UnmodifiableIterator<V>() {
+      final UnmodifiableIterator<Entry<K, V>> entryItr = map.entrySet().iterator();
+
+      @Override
+      public boolean hasNext() {
+        return entryItr.hasNext();
+      }
+
+      @Override
+      public V next() {
+        return entryItr.next().getValue();
+      }
+    };
   }
 
   @Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
index 236c75b..985ffe9 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
@@ -19,7 +19,10 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Arrays;
@@ -27,7 +30,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -36,29 +38,30 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link Multimap}. Does not permit null keys or values.
+ * A {@link Multimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Multimaps#unmodifiableMultimap(Multimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
+ * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
+ * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
+ * source of bugs and confusion.
  *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
+ * need for a distinct {@code ImmutableBiMultimap} type.
  *
- * <p>In addition to methods defined by {@link Multimap}, an {@link #inverse}
- * method is also supported.
+ * <a name="iteration"></a>
+ * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
+ * current implementations, the iteration order always keeps multiple entries with the same key
+ * together. Any creation method that would customarily respect insertion order (such as {@link
+ * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
+ * immediately after the last entry having that key.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
@@ -84,23 +87,27 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
-  public static <K, V> ImmutableMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
+  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
     return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
-  public static <K, V> ImmutableMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
     return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
   public static <K, V> ImmutableMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
@@ -118,21 +125,6 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
-   * value orderings, allows duplicate values, and performs better than
-   * {@link LinkedListMultimap}.
-   */
-  private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
-    BuilderMultimap() {
-      super(new LinkedHashMap<K, Collection<V>>());
-    }
-    @Override Collection<V> createCollection() {
-      return Lists.newArrayList();
-    }
-    private static final long serialVersionUID = 0;
-  }
-
-  /**
    * A builder for creating immutable multimap instances, especially
    * {@code public static final} multimaps ("constant multimaps"). Example:
    * <pre>   {@code
@@ -148,10 +140,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<K, V> {
-    Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
+    Multimap<K, V> builderMultimap;
     Comparator<? super K> keyComparator;
     Comparator<? super V> valueComparator;
 
@@ -159,7 +151,13 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableMultimap#builder}.
      */
-    public Builder() {}
+    public Builder() {
+      this(MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build());
+    }
+    
+    Builder(Multimap<K, V> builderMultimap) {
+      this.builderMultimap = builderMultimap;
+    }
 
     /**
      * Adds a key-value mapping to the built multimap.
@@ -180,6 +178,19 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     }
 
     /**
+     * Adds entries to the built multimap.
+     *
+     * @since 19.0
+     */
+    @Beta
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      for (Entry<? extends K, ? extends V> entry : entries) {
+        put(entry);
+      }
+      return this;
+    }
+
+    /**
      * Stores a collection of values with the same key in the built multimap.
      *
      * @throws NullPointerException if {@code key}, {@code values}, or any
@@ -188,8 +199,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      */
     public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       if (key == null) {
-        throw new NullPointerException(
-            "null key in entry: null=" + Iterables.toString(values));
+        throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
       }
       Collection<V> valueList = builderMultimap.get(key);
       for (V value : values) {
@@ -219,8 +229,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      *     null. The builder is left in an invalid state.
      */
     public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
-      for (Entry<? extends K, ? extends Collection<? extends V>> entry
-          : multimap.asMap().entrySet()) {
+      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+          multimap.asMap().entrySet()) {
         putAll(entry.getKey(), entry.getValue());
       }
       return this;
@@ -252,17 +262,17 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public ImmutableMultimap<K, V> build() {
       if (valueComparator != null) {
         for (Collection<V> values : builderMultimap.asMap().values()) {
-          List<V> list = (List <V>) values;
+          List<V> list = (List<V>) values;
           Collections.sort(list, valueComparator);
         }
       }
       if (keyComparator != null) {
-        Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
-        List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
-            builderMultimap.asMap().entrySet());
-        Collections.sort(
-            entries,
-            Ordering.from(keyComparator).<K>onKeys());
+        Multimap<K, V> sortedCopy =
+            MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build();
+        List<Map.Entry<K, Collection<V>>> entries =
+            Ordering.from(keyComparator)
+                .<K>onKeys()
+                .immutableSortedCopy(builderMultimap.asMap().entrySet());
         for (Map.Entry<K, Collection<V>> entry : entries) {
           sortedCopy.putAll(entry.getKey(), entry.getValue());
         }
@@ -274,8 +284,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
   /**
    * Returns an immutable multimap containing the same mappings as {@code
-   * multimap}. The generated multimap's key and value orderings correspond to
-   * the iteration ordering of the {@code multimap.asMap()} view.
+   * multimap}, in the "key-grouped" iteration order described in the class
+   * documentation.
    *
    * <p>Despite the method name, this method attempts to avoid actually copying
    * the data when it is safe to do so. The exact circumstances under which a
@@ -284,12 +294,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    * @throws NullPointerException if any key or value in {@code multimap} is
    *         null
    */
-  public static <K, V> ImmutableMultimap<K, V> copyOf(
-      Multimap<? extends K, ? extends V> multimap) {
+  public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
     if (multimap instanceof ImmutableMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableMultimap<K, V> kvMultimap
-          = (ImmutableMultimap<K, V>) multimap;
+      ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
@@ -297,6 +305,21 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     return ImmutableListMultimap.copyOf(multimap);
   }
 
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return ImmutableListMultimap.copyOf(entries);
+  }
+
   final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
   final transient int size;
 
@@ -304,8 +327,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   // holder class makes sure they are not initialized unless an instance is
   // deserialized.
 
-  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
-      int size) {
+  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
     this.map = map;
     this.size = size;
   }
@@ -332,8 +354,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    */
   @Deprecated
   @Override
-  public ImmutableCollection<V> replaceValues(K key,
-      Iterable<? extends V> values) {
+  public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 
@@ -414,7 +435,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public boolean remove(Object key, Object value) {
     throw new UnsupportedOperationException();
   }
-  
+
   /**
    * Returns {@code true} if this immutable multimap's implementation contains references to
    * user-created objects that aren't accessible via this multimap's methods. This is generally
@@ -436,7 +457,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public boolean containsValue(@Nullable Object value) {
     return value != null && super.containsValue(value);
   }
-  
+
   @Override
   public int size() {
     return size;
@@ -445,9 +466,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   // views
 
   /**
-   * Returns an immutable set of the distinct keys in this multimap. These keys
-   * are ordered according to when they first appeared during the construction
-   * of this multimap.
+   * Returns an immutable set of the distinct keys in this multimap, in the same
+   * order as they appear in this multimap.
    */
   @Override
   public ImmutableSet<K> keySet() {
@@ -456,47 +476,47 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
   /**
    * Returns an immutable map that associates each key with its corresponding
-   * values in the multimap.
+   * values in the multimap. Keys and values appear in the same order as in this
+   * multimap.
    */
   @Override
   @SuppressWarnings("unchecked") // a widening cast
   public ImmutableMap<K, Collection<V>> asMap() {
     return (ImmutableMap) map;
   }
-  
+
   @Override
   Map<K, Collection<V>> createAsMap() {
     throw new AssertionError("should never be called");
   }
 
   /**
-   * Returns an immutable collection of all key-value pairs in the multimap. Its
-   * iterator traverses the values for the first key, the values for the second
-   * key, and so on.
+   * Returns an immutable collection of all key-value pairs in the multimap.
    */
   @Override
   public ImmutableCollection<Entry<K, V>> entries() {
     return (ImmutableCollection<Entry<K, V>>) super.entries();
   }
-  
+
   @Override
   ImmutableCollection<Entry<K, V>> createEntries() {
     return new EntryCollection<K, V>(this);
   }
 
-  private static class EntryCollection<K, V>
-      extends ImmutableCollection<Entry<K, V>> {
-    final ImmutableMultimap<K, V> multimap;
+  private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
+    @Weak final ImmutableMultimap<K, V> multimap;
 
     EntryCollection(ImmutableMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
 
-    @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
+    @Override
+    public UnmodifiableIterator<Entry<K, V>> iterator() {
       return multimap.entryIterator();
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return multimap.isPartialView();
     }
 
@@ -505,7 +525,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return multimap.size();
     }
 
-    @Override public boolean contains(Object object) {
+    @Override
+    public boolean contains(Object object) {
       if (object instanceof Entry) {
         Entry<?, ?> entry = (Entry<?, ?>) object;
         return multimap.containsEntry(entry.getKey(), entry.getValue());
@@ -515,12 +536,12 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
     private static final long serialVersionUID = 0;
   }
-  
+
   private abstract class Itr<T> extends UnmodifiableIterator<T> {
     final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
     K key = null;
     Iterator<V> valueIterator = Iterators.emptyIterator();
-    
+
     abstract T output(K key, V value);
 
     @Override
@@ -538,7 +559,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return output(key, valueIterator.next());
     }
   }
-  
+
   @Override
   UnmodifiableIterator<Entry<K, V>> entryIterator() {
     return new Itr<Entry<K, V>>() {
@@ -550,10 +571,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Returns a collection, which may contain duplicates, of all keys. The number
-   * of times a key appears in the returned multiset equals the number of
-   * mappings the key has in the multimap. Duplicate keys appear consecutively
-   * in the multiset's iteration order.
+   * Returns an immutable multiset containing all the keys in this multimap, in
+   * the same order and with the same frequencies as they appear in this
+   * multimap; to get only a single occurrence of each key, use {@link #keySet}.
    */
   @Override
   public ImmutableMultiset<K> keys() {
@@ -566,6 +586,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   @SuppressWarnings("serial") // Uses writeReplace, not default serialization
+  @WeakOuter
   class Keys extends ImmutableMultiset<K> {
     @Override
     public boolean contains(@Nullable Object object) {
@@ -587,7 +608,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public int size() {
       return ImmutableMultimap.this.size();
     }
-    
+
     @Override
     Multiset.Entry<K> getEntry(int index) {
       Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
@@ -609,7 +630,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public ImmutableCollection<V> values() {
     return (ImmutableCollection<V>) super.values();
   }
-  
+
   @Override
   ImmutableCollection<V> createValues() {
     return new Values<K, V>(this);
@@ -626,8 +647,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   private static final class Values<K, V> extends ImmutableCollection<V> {
-    private transient final ImmutableMultimap<K, V> multimap;
-    
+    @Weak private final transient ImmutableMultimap<K, V> multimap;
+
     Values(ImmutableMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
@@ -636,8 +657,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public boolean contains(@Nullable Object object) {
       return multimap.containsValue(object);
     }
-    
-    @Override public UnmodifiableIterator<V> iterator() {
+
+    @Override
+    public UnmodifiableIterator<V> iterator() {
       return multimap.valueIterator();
     }
 
@@ -646,7 +668,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return multimap.size();
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return true;
     }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
index ead2ba0..b75259b 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
@@ -20,46 +20,41 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multiset.Entry;
-import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 
 import javax.annotation.Nullable;
 
 /**
- * An immutable hash-based multiset. Does not permit null elements.
+ * A {@link Multiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Its iterator orders elements according to the first appearance of the
- * element among the items passed to the factory method or builder. When the
- * multiset contains multiple instances of an element, those instances are
- * consecutive in the iteration order.
+ * <p><b>Grouped iteration.</b> In all current implementations, duplicate elements always appear
+ * consecutively when iterating. Elements iterate in order by the <i>first</i> appearance of
+ * that element when the multiset was created.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
-// TODO(user): write an efficient asList() implementation
-public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
-    implements Multiset<E> {
-
-  private static final ImmutableMultiset<Object> EMPTY =
-      new RegularImmutableMultiset<Object>(ImmutableMap.<Object, Integer>of(), 0);
-
+// TODO(lowasser): write an efficient asList() implementation
+public abstract class ImmutableMultiset<E> extends ImmutableCollection<E> implements Multiset<E> {
   /**
    * Returns the empty immutable multiset.
    */
   @SuppressWarnings("unchecked") // all supported methods are covariant
   public static <E> ImmutableMultiset<E> of() {
-    return (ImmutableMultiset<E>) EMPTY;
+    return (ImmutableMultiset<E>) RegularImmutableMultiset.EMPTY;
   }
 
   /**
@@ -70,7 +65,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    */
   @SuppressWarnings("unchecked") // generic array created but never written
   public static <E> ImmutableMultiset<E> of(E element) {
-    return copyOfInternal(element);
+    return copyFromElements(element);
   }
 
   /**
@@ -81,51 +76,54 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2) {
-    return copyOfInternal(e1, e2);
+    return copyFromElements(e1, e2);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) {
-    return copyOfInternal(e1, e2, e3);
+    return copyFromElements(e1, e2, e3);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) {
-    return copyOfInternal(e1, e2, e3, e4);
+    return copyFromElements(e1, e2, e3, e4);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
-    return copyOfInternal(e1, e2, e3, e4, e5);
+    return copyFromElements(e1, e2, e3, e4, e5);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
-  public static <E> ImmutableMultiset<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
+  public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
     return new Builder<E>()
         .add(e1)
         .add(e2)
@@ -138,38 +136,23 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example, {@code ImmutableMultiset.copyOf([2, 3, 1, 3])} yields a multiset
-   * with elements in the order {@code 2, 3, 3, 1}.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    * @since 6.0
    */
   public static <E> ImmutableMultiset<E> copyOf(E[] elements) {
-    return copyOf(Arrays.asList(elements));
+    return copyFromElements(elements);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example, {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3))} yields
-   * a multiset with elements in the order {@code 2, 3, 3, 1}.
-   *
-   * <p>Despite the method name, this method attempts to avoid actually copying
-   * the data when it is safe to do so. The exact circumstances under which a
-   * copy will or will not be performed are undocumented and subject to change.
-   *
-   * <p><b>Note:</b> Despite what the method name suggests, if {@code elements}
-   * is an {@code ImmutableMultiset}, no copy will actually be performed, and
-   * the given multiset itself will be returned.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableMultiset<E> copyOf(
-      Iterable<? extends E> elements) {
+  public static <E> ImmutableMultiset<E> copyOf(Iterable<? extends E> elements) {
     if (elements instanceof ImmutableMultiset) {
       @SuppressWarnings("unchecked") // all supported methods are covariant
       ImmutableMultiset<E> result = (ImmutableMultiset<E>) elements;
@@ -178,63 +161,45 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
       }
     }
 
-    Multiset<? extends E> multiset = (elements instanceof Multiset)
-        ? Multisets.cast(elements)
-        : LinkedHashMultiset.create(elements);
+    Multiset<? extends E> multiset =
+        (elements instanceof Multiset)
+            ? Multisets.cast(elements)
+            : LinkedHashMultiset.create(elements);
 
-    return copyOfInternal(multiset);
-  }
-
-  private static <E> ImmutableMultiset<E> copyOfInternal(E... elements) {
-    return copyOf(Arrays.asList(elements));
+    return copyFromEntries(multiset.entrySet());
   }
 
-  private static <E> ImmutableMultiset<E> copyOfInternal(
-      Multiset<? extends E> multiset) {
+  private static <E> ImmutableMultiset<E> copyFromElements(E... elements) {
+    Multiset<E> multiset = LinkedHashMultiset.create();
+    Collections.addAll(multiset, elements);
     return copyFromEntries(multiset.entrySet());
   }
 
   static <E> ImmutableMultiset<E> copyFromEntries(
       Collection<? extends Entry<? extends E>> entries) {
-    long size = 0;
-    ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
-    for (Entry<? extends E> entry : entries) {
-      int count = entry.getCount();
-      if (count > 0) {
-        // Since ImmutableMap.Builder throws an NPE if an element is null, no
-        // other null checks are needed.
-        builder.put(entry.getElement(), count);
-        size += count;
-      }
-    }
-
-    if (size == 0) {
+    if (entries.isEmpty()) {
       return of();
+    } else {
+      return new RegularImmutableMultiset<E>(entries);
     }
-    return new RegularImmutableMultiset<E>(
-        builder.build(), Ints.saturatedCast(size));
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example,
-   * {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3).iterator())}
-   * yields a multiset with elements in the order {@code 2, 3, 3, 1}.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableMultiset<E> copyOf(
-      Iterator<? extends E> elements) {
+  public static <E> ImmutableMultiset<E> copyOf(Iterator<? extends E> elements) {
     Multiset<E> multiset = LinkedHashMultiset.create();
     Iterators.addAll(multiset, elements);
-    return copyOfInternal(multiset);
+    return copyFromEntries(multiset.entrySet());
   }
 
   ImmutableMultiset() {}
 
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     final Iterator<Entry<E>> entryIterator = entrySet().iterator();
     return new UnmodifiableIterator<E>() {
       int remaining;
@@ -263,11 +228,6 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     return count(object) > 0;
   }
 
-  @Override
-  public boolean containsAll(Collection<?> targets) {
-    return elementSet().containsAll(targets);
-  }
-
   /**
    * Guaranteed to throw an exception and leave the collection unmodified.
    *
@@ -316,15 +276,18 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     throw new UnsupportedOperationException();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return Multisets.equalsImpl(this, object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Sets.hashCodeImpl(entrySet());
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return entrySet().toString();
   }
 
@@ -342,30 +305,16 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
 
   abstract Entry<E> getEntry(int index);
 
-  private final class EntrySet extends ImmutableSet<Entry<E>> {
+  @WeakOuter
+  private final class EntrySet extends ImmutableSet.Indexed<Entry<E>> {
     @Override
     boolean isPartialView() {
       return ImmutableMultiset.this.isPartialView();
     }
 
     @Override
-    public UnmodifiableIterator<Entry<E>> iterator() {
-      return asList().iterator();
-    }
-
-    @Override
-    ImmutableList<Entry<E>> createAsList() {
-      return new ImmutableAsList<Entry<E>>() {
-        @Override
-        public Entry<E> get(int index) {
-          return getEntry(index);
-        }
-
-        @Override
-        ImmutableCollection<Entry<E>> delegateCollection() {
-          return EntrySet.this;
-        }
-      };
+    Entry<E> get(int index) {
+      return getEntry(index);
     }
 
     @Override
@@ -430,8 +379,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     }
 
     Object readResolve() {
-      LinkedHashMultiset<Object> multiset =
-          LinkedHashMultiset.create(elements.length);
+      LinkedHashMultiset<Object> multiset = LinkedHashMultiset.create(elements.length);
       for (int i = 0; i < elements.length; i++) {
         multiset.add(elements[i], counts[i]);
       }
@@ -471,7 +419,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
    * times to build multiple multisets in series.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<E> extends ImmutableCollection.Builder<E> {
     final Multiset<E> contents;
@@ -495,7 +443,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code element} is null
      */
-    @Override public Builder<E> add(E element) {
+    @Override
+    public Builder<E> add(E element) {
       contents.add(checkNotNull(element));
       return this;
     }
@@ -541,7 +490,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> add(E... elements) {
+    @Override
+    public Builder<E> add(E... elements) {
       super.add(elements);
       return this;
     }
@@ -555,7 +505,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterable<? extends E> elements) {
       if (elements instanceof Multiset) {
         Multiset<? extends E> multiset = Multisets.cast(elements);
         for (Entry<? extends E> entry : multiset.entrySet()) {
@@ -575,7 +526,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterator<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -584,7 +536,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * Returns a newly-created {@code ImmutableMultiset} based on the contents
      * of the {@code Builder}.
      */
-    @Override public ImmutableMultiset<E> build() {
+    @Override
+    public ImmutableMultiset<E> build() {
       return copyOf(contents);
     }
   }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
index 7c0bae7..7918a24 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
@@ -43,7 +43,7 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
   // Casting to any type is safe because the set will never hold any elements.
   @SuppressWarnings({"unchecked"})
   public static <E> ImmutableSet<E> of() {
-    return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE;
+    return (ImmutableSet<E>) RegularImmutableSet.EMPTY;
   }
 
   public static <E> ImmutableSet<E> of(E element) {
@@ -162,6 +162,30 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
   @Override public int hashCode() {
     return Sets.hashCodeImpl(this);
   }
+  
+  abstract static class Indexed<E> extends ImmutableSet<E> {
+    abstract E get(int index);
+
+    @Override
+    public UnmodifiableIterator<E> iterator() {
+      return asList().iterator();
+    }
+
+    @Override
+    ImmutableList<E> createAsList() {
+      return new ImmutableAsList<E>() {
+        @Override
+        public E get(int index) {
+          return Indexed.this.get(index);
+        }
+
+        @Override
+        Indexed<E> delegateCollection() {
+          return Indexed.this;
+        }
+      };
+    }
+  }
 
   public static <E> Builder<E> builder() {
     return new Builder<E>();
@@ -169,9 +193,15 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
 
   public static class Builder<E> extends ImmutableCollection.Builder<E> {
     // accessed directly by ImmutableSortedSet
-    final ArrayList<E> contents = Lists.newArrayList();
+    final ArrayList<E> contents;
 
-    public Builder() {}
+    public Builder() {
+      this.contents = Lists.newArrayList();
+    }
+    
+    Builder(int initialCapacity) {
+      this.contents = Lists.newArrayListWithCapacity(initialCapacity);
+    }
 
     @Override public Builder<E> add(E element) {
       contents.add(checkNotNull(element));
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
index 1a4b392..0815e5d 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
@@ -18,14 +18,14 @@ package com.google.common.collect;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.MoreObjects;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -33,31 +33,18 @@ import java.util.Map.Entry;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link SetMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableSetMultimap(SetMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableSetMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableSetMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link SetMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Mike Ward
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
-public class ImmutableSetMultimap<K, V>
-    extends ImmutableMultimap<K, V>
+public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V>
     implements SetMultimap<K, V> {
 
   /** Returns the empty multimap. */
@@ -93,8 +80,7 @@ public class ImmutableSetMultimap<K, V>
    * Repeated occurrences of an entry (according to {@link Object#equals}) after
    * the first are ignored.
    */
-  public static <K, V> ImmutableSetMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
+  public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
     ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
@@ -143,20 +129,6 @@ public class ImmutableSetMultimap<K, V>
   }
 
   /**
-   * Multimap for {@link ImmutableSetMultimap.Builder} that maintains key
-   * and value orderings and performs better than {@link LinkedHashMultimap}.
-   */
-  private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
-    BuilderMultimap() {
-      super(new LinkedHashMap<K, Collection<V>>());
-    }
-    @Override Collection<V> createCollection() {
-      return Sets.newLinkedHashSet();
-    }
-    private static final long serialVersionUID = 0;
-  }
-
-  /**
    * A builder for creating immutable {@code SetMultimap} instances, especially
    * {@code public static final} multimaps ("constant multimaps"). Example:
    * <pre>   {@code
@@ -172,23 +144,23 @@ public class ImmutableSetMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
-  public static final class Builder<K, V>
-      extends ImmutableMultimap.Builder<K, V> {
+  public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
     /**
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableSetMultimap#builder}.
      */
     public Builder() {
-      builderMultimap = new BuilderMultimap<K, V>();
+      super(MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build());
     }
 
     /**
      * Adds a key-value mapping to the built multimap if it is not already
      * present.
      */
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       builderMultimap.put(checkNotNull(key), checkNotNull(value));
       return this;
     }
@@ -198,13 +170,26 @@ public class ImmutableSetMultimap<K, V>
      *
      * @since 11.0
      */
-    @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
-      builderMultimap.put(
-          checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+      builderMultimap.put(checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+      return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+    @Override
+    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       Collection<V> collection = builderMultimap.get(checkNotNull(key));
       for (V value : values) {
         collection.add(checkNotNull(value));
@@ -212,14 +197,15 @@ public class ImmutableSetMultimap<K, V>
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, V... values) {
+    @Override
+    public Builder<K, V> putAll(K key, V... values) {
       return putAll(key, Arrays.asList(values));
     }
 
-    @Override public Builder<K, V> putAll(
-        Multimap<? extends K, ? extends V> multimap) {
-      for (Entry<? extends K, ? extends Collection<? extends V>> entry
-          : multimap.asMap().entrySet()) {
+    @Override
+    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
+      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+          multimap.asMap().entrySet()) {
         putAll(entry.getKey(), entry.getValue());
       }
       return this;
@@ -257,14 +243,15 @@ public class ImmutableSetMultimap<K, V>
     /**
      * Returns a newly-created immutable set multimap.
      */
-    @Override public ImmutableSetMultimap<K, V> build() {
+    @Override
+    public ImmutableSetMultimap<K, V> build() {
       if (keyComparator != null) {
-        Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
-        List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
-            builderMultimap.asMap().entrySet());
-        Collections.sort(
-            entries,
-            Ordering.from(keyComparator).<K>onKeys());
+        Multimap<K, V> sortedCopy =
+            MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build();
+        List<Map.Entry<K, Collection<V>>> entries =
+            Ordering.from(keyComparator)
+                .<K>onKeys()
+                .immutableSortedCopy(builderMultimap.asMap().entrySet());
         for (Map.Entry<K, Collection<V>> entry : entries) {
           sortedCopy.putAll(entry.getKey(), entry.getValue());
         }
@@ -294,8 +281,7 @@ public class ImmutableSetMultimap<K, V>
   }
 
   private static <K, V> ImmutableSetMultimap<K, V> copyOf(
-      Multimap<? extends K, ? extends V> multimap,
-      Comparator<? super V> valueComparator) {
+      Multimap<? extends K, ? extends V> multimap, Comparator<? super V> valueComparator) {
     checkNotNull(multimap); // eager for GWT
     if (multimap.isEmpty() && valueComparator == null) {
       return of();
@@ -303,18 +289,18 @@ public class ImmutableSetMultimap<K, V>
 
     if (multimap instanceof ImmutableSetMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableSetMultimap<K, V> kvMultimap
-          = (ImmutableSetMultimap<K, V>) multimap;
+      ImmutableSetMultimap<K, V> kvMultimap = (ImmutableSetMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
     }
 
-    ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
+    ImmutableMap.Builder<K, ImmutableSet<V>> builder =
+        new ImmutableMap.Builder<K, ImmutableSet<V>>(multimap.asMap().size());
     int size = 0;
 
-    for (Entry<? extends K, ? extends Collection<? extends V>> entry
-        : multimap.asMap().entrySet()) {
+    for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+        multimap.asMap().entrySet()) {
       K key = entry.getKey();
       Collection<? extends V> values = entry.getValue();
       ImmutableSet<V> set = valueSet(valueComparator, values);
@@ -324,8 +310,23 @@ public class ImmutableSetMultimap<K, V>
       }
     }
 
-    return new ImmutableSetMultimap<K, V>(
-        builder.build(), size, valueComparator);
+    return new ImmutableSetMultimap<K, V>(builder.build(), size, valueComparator);
+  }
+
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.  If two values for the same key are
+   * {@linkplain Object#equals equal}, the first value encountered is used.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableSetMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>().putAll(entries).build();
   }
 
   /**
@@ -334,7 +335,9 @@ public class ImmutableSetMultimap<K, V>
    */
   private final transient ImmutableSet<V> emptySet;
 
-  ImmutableSetMultimap(ImmutableMap<K, ImmutableSet<V>> map, int size,
+  ImmutableSetMultimap(
+      ImmutableMap<K, ImmutableSet<V>> map,
+      int size,
       @Nullable Comparator<? super V> valueComparator) {
     super(map, size);
     this.emptySet = emptySet(valueComparator);
@@ -348,7 +351,8 @@ public class ImmutableSetMultimap<K, V>
    * The values are in the same order as the parameters used to build this
    * multimap.
    */
-  @Override public ImmutableSet<V> get(@Nullable K key) {
+  @Override
+  public ImmutableSet<V> get(@Nullable K key) {
     // This cast is safe as its type is known in constructor.
     ImmutableSet<V> set = (ImmutableSet<V>) map.get(key);
     return MoreObjects.firstNonNull(set, emptySet);
@@ -387,7 +391,9 @@ public class ImmutableSetMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableSet<V> removeAll(Object key) {
+  @Deprecated
+  @Override
+  public ImmutableSet<V> removeAll(Object key) {
     throw new UnsupportedOperationException();
   }
 
@@ -397,8 +403,9 @@ public class ImmutableSetMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableSet<V> replaceValues(
-      K key, Iterable<? extends V> values) {
+  @Deprecated
+  @Override
+  public ImmutableSet<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 
@@ -409,16 +416,17 @@ public class ImmutableSetMultimap<K, V>
    * Its iterator traverses the values for the first key, the values for the
    * second key, and so on.
    */
-  @Override public ImmutableSet<Entry<K, V>> entries() {
+  @Override
+  public ImmutableSet<Entry<K, V>> entries() {
     ImmutableSet<Entry<K, V>> result = entries;
-    return (result == null)
+    return result == null
         ? (entries = new EntrySet<K, V>(this))
         : result;
   }
-  
+
   private static final class EntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
-    private transient final ImmutableSetMultimap<K, V> multimap;
-    
+    @Weak private final transient ImmutableSetMultimap<K, V> multimap;
+
     EntrySet(ImmutableSetMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
@@ -445,28 +453,33 @@ public class ImmutableSetMultimap<K, V>
     @Override
     boolean isPartialView() {
       return false;
-    }    
+    }
   }
 
   private static <V> ImmutableSet<V> valueSet(
-      @Nullable Comparator<? super V> valueComparator,
-      Collection<? extends V> values) {
+      @Nullable Comparator<? super V> valueComparator, Collection<? extends V> values) {
     return (valueComparator == null)
         ? ImmutableSet.copyOf(values)
         : ImmutableSortedSet.copyOf(valueComparator, values);
   }
 
-  private static <V> ImmutableSet<V> emptySet(
-      @Nullable Comparator<? super V> valueComparator) {
+  private static <V> ImmutableSet<V> emptySet(@Nullable Comparator<? super V> valueComparator) {
     return (valueComparator == null)
         ? ImmutableSet.<V>of()
         : ImmutableSortedSet.<V>emptySet(valueComparator);
   }
 
-  @Nullable Comparator<? super V> valueComparator() {
+  private static <V> ImmutableSet.Builder<V> valuesBuilder(
+      @Nullable Comparator<? super V> valueComparator) {
+    return (valueComparator == null)
+        ? new ImmutableSet.Builder<V>()
+        : new ImmutableSortedSet.Builder<V>(valueComparator);
+  }
+
+  @Nullable
+  Comparator<? super V> valueComparator() {
     return emptySet instanceof ImmutableSortedSet
         ? ((ImmutableSortedSet<V>) emptySet).comparator()
         : null;
   }
 }
-
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
index c94e88e..e1a068a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
@@ -28,8 +28,7 @@ import java.util.Comparator;
 @SuppressWarnings("serial")
 final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
     implements SortedIterable<E> {
-  ImmutableSortedAsList(
-      ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
+  ImmutableSortedAsList(ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
     super(backingSet, backingList);
   }
 
@@ -38,7 +37,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
     return (ImmutableSortedSet<E>) super.delegateCollection();
   }
 
-  @Override public Comparator<? super E> comparator() {
+  @Override
+  public Comparator<? super E> comparator() {
     return delegateCollection().comparator();
   }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
index 238ffe9..f8f151f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
@@ -19,9 +19,10 @@ 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.Maps.newTreeMap;
+import static java.util.Collections.singletonMap;
 import static java.util.Collections.unmodifiableSortedMap;
 
-import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableSortedMap.Builder;
 
 import java.util.Comparator;
 import java.util.Iterator;
@@ -34,7 +35,7 @@ import java.util.SortedMap;
  *
  * @author Hayward Chan
  */
-public abstract class ImmutableSortedMap<K, V>
+public final class ImmutableSortedMap<K, V>
     extends ForwardingImmutableMap<K, V> implements SortedMap<K, V> {
 
   @SuppressWarnings("unchecked")
@@ -62,26 +63,15 @@ public abstract class ImmutableSortedMap<K, V>
     this.sortedDelegate = delegate;
   }
 
-  private static <K, V> ImmutableSortedMap<K, V> create(
-      Comparator<? super K> comparator,
-      Entry<? extends K, ? extends V>... entries) {
-    checkNotNull(comparator);
-    SortedMap<K, V> delegate = newModifiableDelegate(comparator);
-    for (Entry<? extends K, ? extends V> entry : entries) {
-      delegate.put(entry.getKey(), entry.getValue());
-    }
-    return newView(unmodifiableSortedMap(delegate), comparator);
-  }
-
   // Casting to any type is safe because the set will never hold any elements.
   @SuppressWarnings("unchecked")
   public static <K, V> ImmutableSortedMap<K, V> of() {
-    return EmptyImmutableSortedMap.forComparator(NATURAL_ORDER);
+    return new Builder<K, V>(NATURAL_ORDER).build();
   }
 
   public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
       of(K k1, V v1) {
-    return create(Ordering.natural(), entryOf(k1, v1));
+    return copyOf(singletonMap(k1, v1));
   }
 
   public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
@@ -118,6 +108,17 @@ public abstract class ImmutableSortedMap<K, V>
     return copyOfInternal(map, checkNotNull(comparator));
   }
 
+  public static <K, V> ImmutableSortedMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>(NATURAL_ORDER).putAll(entries).build();
+  }
+
+  public static <K, V> ImmutableSortedMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries, 
+          Comparator<? super K> comparator) {
+    return new Builder<K, V>(comparator).putAll(entries).build();
+  }
+
   public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
       SortedMap<K, ? extends V> map) {
     // If map has a null comparator, the keys should have a natural ordering,
@@ -162,9 +163,9 @@ public abstract class ImmutableSortedMap<K, V>
       Entry<K, V> previousEntry
           = map.tailMap(key).entrySet().iterator().next();
       throw new IllegalArgumentException(
-          "Duplicate keys in mappings " + previousEntry.getKey() +
-          "=" + previousEntry.getValue() + " and " + key +
-          "=" + value);
+          "Duplicate keys in mappings " + previousEntry.getKey()
+          + "=" + previousEntry.getValue() + " and " + key
+          + "=" + value);
     }
     map.put(key, value);
   }
@@ -199,11 +200,21 @@ public abstract class ImmutableSortedMap<K, V>
     }
 
     @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
-      for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
-        put(entry.getKey(), entry.getValue());
+      return putAll(map.entrySet());
+    }
+    
+    @Override public Builder<K, V> putAll(
+        Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      for (Entry<? extends K, ? extends V> entry : entries) {
+        put(entry);
       }
       return this;
     }
+    
+    @Override
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
+    }
 
     @Override public ImmutableSortedMap<K, V> build() {
       SortedMap<K, V> delegate = newModifiableDelegate(comparator);
@@ -295,7 +306,7 @@ public abstract class ImmutableSortedMap<K, V>
     if (!inclusive) {
       fromKey = higher(fromKey);
       if (fromKey == null) {
-        return EmptyImmutableSortedMap.forComparator(comparator());
+        return new Builder<K, V>(this.comparator).build();
       }
     }
     return tailMap(fromKey);
@@ -307,10 +318,7 @@ public abstract class ImmutableSortedMap<K, V>
 
   private static <K, V> ImmutableSortedMap<K, V> newView(
       SortedMap<K, V> delegate, Comparator<? super K> comparator) {
-    if (delegate.isEmpty()) {
-      return EmptyImmutableSortedMap.forComparator(comparator);
-    }
-    return new RegularImmutableSortedMap<K, V>(delegate, comparator);
+    return new ImmutableSortedMap<K, V>(delegate, comparator);
   }
 
   /*
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
index 1eff230..e24caae 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
@@ -55,25 +55,21 @@ public abstract class ImmutableSortedSet<E>
 
   @SuppressWarnings("unchecked")
   private static final ImmutableSortedSet<Object> NATURAL_EMPTY_SET =
-      new EmptyImmutableSortedSet<Object>(NATURAL_ORDER);
-
-  @SuppressWarnings("unchecked")
-  private static <E> ImmutableSortedSet<E> emptySet() {
-    return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
-  }
+      new RegularImmutableSortedSet<Object>(new TreeSet<Object>(NATURAL_ORDER), false);
 
   static <E> ImmutableSortedSet<E> emptySet(
       Comparator<? super E> comparator) {
     checkNotNull(comparator);
     if (NATURAL_ORDER.equals(comparator)) {
-      return emptySet();
+      return of();
     } else {
-      return new EmptyImmutableSortedSet<E>(comparator);
+      return new RegularImmutableSortedSet<E>(new TreeSet<E>(comparator), false);
     }
   }
 
+  @SuppressWarnings("unchecked")
   public static <E> ImmutableSortedSet<E> of() {
-    return emptySet();
+    return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
   }
 
   public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
index 0ca88c7..6be8885 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
@@ -35,6 +35,7 @@ import java.util.Queue;
 import java.util.RandomAccess;
 import java.util.Set;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -47,23 +48,21 @@ import javax.annotation.Nullable;
  * only advance the backing iteration when absolutely necessary.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
  * {@code Iterables}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Iterables {
   private Iterables() {}
 
   /** Returns an unmodifiable view of {@code iterable}. */
-  public static <T> Iterable<T> unmodifiableIterable(
-      final Iterable<T> iterable) {
+  public static <T> Iterable<T> unmodifiableIterable(final Iterable<T> iterable) {
     checkNotNull(iterable);
-    if (iterable instanceof UnmodifiableIterable ||
-        iterable instanceof ImmutableCollection) {
+    if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) {
       return iterable;
     }
     return new UnmodifiableIterable<T>(iterable);
@@ -75,8 +74,8 @@ public final class Iterables {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <E> Iterable<E> unmodifiableIterable(
-      ImmutableCollection<E> iterable) {
+  @Deprecated
+  public static <E> Iterable<E> unmodifiableIterable(ImmutableCollection<E> iterable) {
     return checkNotNull(iterable);
   }
 
@@ -131,8 +130,7 @@ public final class Iterables {
    * @param elementsToRemove the elements to remove
    * @return {@code true} if any element was removed from {@code iterable}
    */
-  public static boolean removeAll(
-      Iterable<?> removeFrom, Collection<?> elementsToRemove) {
+  public static boolean removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) {
     return (removeFrom instanceof Collection)
         ? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
         : Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
@@ -149,8 +147,7 @@ public final class Iterables {
    * @param elementsToRetain the elements to retain
    * @return {@code true} if any element was removed from {@code iterable}
    */
-  public static boolean retainAll(
-      Iterable<?> removeFrom, Collection<?> elementsToRetain) {
+  public static boolean retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) {
     return (removeFrom instanceof Collection)
         ? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
         : Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
@@ -169,11 +166,9 @@ public final class Iterables {
    *     {@code remove()}.
    * @since 2.0
    */
-  public static <T> boolean removeIf(
-      Iterable<T> removeFrom, Predicate<? super T> predicate) {
+  public static <T> boolean removeIf(Iterable<T> removeFrom, Predicate<? super T> predicate) {
     if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
-      return removeIfFromRandomAccessList(
-          (List<T>) removeFrom, checkNotNull(predicate));
+      return removeIfFromRandomAccessList((List<T>) removeFrom, checkNotNull(predicate));
     }
     return Iterators.removeIf(removeFrom.iterator(), predicate);
   }
@@ -205,8 +200,8 @@ public final class Iterables {
     return from != to;
   }
 
-  private static <T> void slowRemoveIfForRemainingElements(List<T> list,
-      Predicate<? super T> predicate, int to, int from) {
+  private static <T> void slowRemoveIfForRemainingElements(
+      List<T> list, Predicate<? super T> predicate, int to, int from) {
     // Here we know that:
     // * (to < from) and that both are valid indices.
     // * Everything with (index < to) should be kept.
@@ -252,8 +247,8 @@ public final class Iterables {
    * of {@code iterable1} is equal to the corresponding element of
    * {@code iterable2}.
    */
-  public static boolean elementsEqual(
-      Iterable<?> iterable1, Iterable<?> iterable2) {
+  @CheckReturnValue
+  public static boolean elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
     if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
       Collection<?> collection1 = (Collection<?>) iterable1;
       Collection<?> collection2 = (Collection<?>) iterable2;
@@ -295,11 +290,15 @@ public final class Iterables {
    *     elements
    */
   @Nullable
-  public static <T> T getOnlyElement(
-      Iterable<? extends T> iterable, @Nullable T defaultValue) {
+  public static <T> T getOnlyElement(Iterable<? extends T> iterable, @Nullable T defaultValue) {
     return Iterators.getOnlyElement(iterable.iterator(), defaultValue);
   }
 
+  static <T> T[] toArray(Iterable<? extends T> iterable, T[] array) {
+    Collection<? extends T> collection = toCollection(iterable);
+    return collection.toArray(array);
+  }
+
   /**
    * Copies an iterable's elements into an array.
    *
@@ -328,8 +327,7 @@ public final class Iterables {
    * @return {@code true} if {@code collection} was modified as a result of this
    *     operation.
    */
-  public static <T> boolean addAll(
-      Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
+  public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
     if (elementsToAdd instanceof Collection) {
       Collection<? extends T> c = Collections2.cast(elementsToAdd);
       return addTo.addAll(c);
@@ -377,7 +375,9 @@ public final class Iterables {
       public Iterator<T> iterator() {
         return Iterators.cycle(iterable);
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return iterable.toString() + " (cycled)";
       }
     };
@@ -413,8 +413,7 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(
-      Iterable<? extends T> a, Iterable<? extends T> b) {
+  public static <T> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b) {
     return concat(ImmutableList.of(a, b));
   }
 
@@ -427,8 +426,8 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(Iterable<? extends T> a,
-      Iterable<? extends T> b, Iterable<? extends T> c) {
+  public static <T> Iterable<T> concat(
+      Iterable<? extends T> a, Iterable<? extends T> b, Iterable<? extends T> c) {
     return concat(ImmutableList.of(a, b, c));
   }
 
@@ -442,8 +441,10 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(Iterable<? extends T> a,
-      Iterable<? extends T> b, Iterable<? extends T> c,
+  public static <T> Iterable<T> concat(
+      Iterable<? extends T> a,
+      Iterable<? extends T> b,
+      Iterable<? extends T> c,
       Iterable<? extends T> d) {
     return concat(ImmutableList.of(a, b, c, d));
   }
@@ -472,8 +473,7 @@ public final class Iterables {
    * iterable may throw {@code NullPointerException} if any of the input
    * iterators is null.
    */
-  public static <T> Iterable<T> concat(
-      final Iterable<? extends Iterable<? extends T>> inputs) {
+  public static <T> Iterable<T> concat(final Iterable<? extends Iterable<? extends T>> inputs) {
     checkNotNull(inputs);
     return new FluentIterable<T>() {
       @Override
@@ -517,8 +517,7 @@ public final class Iterables {
    *     iterable} divided into partitions
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> Iterable<List<T>> partition(
-      final Iterable<T> iterable, final int size) {
+  public static <T> Iterable<List<T>> partition(final Iterable<T> iterable, final int size) {
     checkNotNull(iterable);
     checkArgument(size > 0);
     return new FluentIterable<List<T>>() {
@@ -546,8 +545,7 @@ public final class Iterables {
    *     trailing null elements)
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> Iterable<List<T>> paddedPartition(
-      final Iterable<T> iterable, final int size) {
+  public static <T> Iterable<List<T>> paddedPartition(final Iterable<T> iterable, final int size) {
     checkNotNull(iterable);
     checkArgument(size > 0);
     return new FluentIterable<List<T>>() {
@@ -562,6 +560,7 @@ public final class Iterables {
    * Returns the elements of {@code unfiltered} that satisfy a predicate. The
    * resulting iterable's iterator does not support {@code remove()}.
    */
+  @CheckReturnValue
   public static <T> Iterable<T> filter(
       final Iterable<T> unfiltered, final Predicate<? super T> predicate) {
     checkNotNull(unfiltered);
@@ -577,8 +576,7 @@ public final class Iterables {
   /**
    * Returns {@code true} if any element in {@code iterable} satisfies the predicate.
    */
-  public static <T> boolean any(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.any(iterable.iterator(), predicate);
   }
 
@@ -586,8 +584,7 @@ public final class Iterables {
    * Returns {@code true} if every element in {@code iterable} satisfies the
    * predicate. If {@code iterable} is empty, {@code true} is returned.
    */
-  public static <T> boolean all(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.all(iterable.iterator(), predicate);
   }
 
@@ -600,8 +597,7 @@ public final class Iterables {
    * @throws NoSuchElementException if no element in {@code iterable} matches
    *     the given predicate
    */
-  public static <T> T find(Iterable<T> iterable,
-      Predicate<? super T> predicate) {
+  public static <T> T find(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.find(iterable.iterator(), predicate);
   }
 
@@ -614,8 +610,8 @@ public final class Iterables {
    * @since 7.0
    */
   @Nullable
-  public static <T> T find(Iterable<? extends T> iterable,
-      Predicate<? super T> predicate, @Nullable T defaultValue) {
+  public static <T> T find(
+      Iterable<? extends T> iterable, Predicate<? super T> predicate, @Nullable T defaultValue) {
     return Iterators.find(iterable.iterator(), predicate, defaultValue);
   }
 
@@ -629,8 +625,7 @@ public final class Iterables {
    *
    * @since 11.0
    */
-  public static <T> Optional<T> tryFind(Iterable<T> iterable,
-      Predicate<? super T> predicate) {
+  public static <T> Optional<T> tryFind(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.tryFind(iterable.iterator(), predicate);
   }
 
@@ -645,8 +640,7 @@ public final class Iterables {
    *
    * @since 2.0
    */
-  public static <T> int indexOf(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.indexOf(iterable.iterator(), predicate);
   }
 
@@ -662,8 +656,9 @@ public final class Iterables {
    * {@code Collection}, consider {@link Lists#transform} and {@link
    * Collections2#transform}.
    */
-  public static <F, T> Iterable<T> transform(final Iterable<F> fromIterable,
-      final Function<? super F, ? extends T> function) {
+  @CheckReturnValue
+  public static <F, T> Iterable<T> transform(
+      final Iterable<F> fromIterable, final Function<? super F, ? extends T> function) {
     checkNotNull(fromIterable);
     checkNotNull(function);
     return new FluentIterable<T>() {
@@ -799,8 +794,7 @@ public final class Iterables {
    *
    * @since 3.0
    */
-  public static <T> Iterable<T> skip(final Iterable<T> iterable,
-      final int numberToSkip) {
+  public static <T> Iterable<T> skip(final Iterable<T> iterable, final int numberToSkip) {
     checkNotNull(iterable);
     checkArgument(numberToSkip >= 0, "number to skip cannot be negative");
 
@@ -865,8 +859,7 @@ public final class Iterables {
    * @throws IllegalArgumentException if {@code limitSize} is negative
    * @since 3.0
    */
-  public static <T> Iterable<T> limit(
-      final Iterable<T> iterable, final int limitSize) {
+  public static <T> Iterable<T> limit(final Iterable<T> iterable, final int limitSize) {
     checkNotNull(iterable);
     checkArgument(limitSize >= 0, "limit is negative");
     return new FluentIterable<T>() {
@@ -926,22 +919,6 @@ public final class Iterables {
     };
   }
 
-  private static class ConsumingQueueIterator<T> extends AbstractIterator<T> {
-    private final Queue<T> queue;
-
-    private ConsumingQueueIterator(Queue<T> queue) {
-      this.queue = queue;
-    }
-
-    @Override public T computeNext() {
-      try {
-        return queue.remove();
-      } catch (NoSuchElementException e) {
-        return endOfData();
-      }
-    }
-  }
-
   // Methods only in Iterables, not in Iterators
 
   /**
@@ -978,21 +955,21 @@ public final class Iterables {
       final Comparator<? super T> comparator) {
     checkNotNull(iterables, "iterables");
     checkNotNull(comparator, "comparator");
-    Iterable<T> iterable = new FluentIterable<T>() {
-      @Override
-      public Iterator<T> iterator() {
-        return Iterators.mergeSorted(
-            Iterables.transform(iterables, Iterables.<T>toIterator()),
-            comparator);
-      }
-    };
+    Iterable<T> iterable =
+        new FluentIterable<T>() {
+          @Override
+          public Iterator<T> iterator() {
+            return Iterators.mergeSorted(
+                Iterables.transform(iterables, Iterables.<T>toIterator()),
+                comparator);
+          }
+        };
     return new UnmodifiableIterable<T>(iterable);
   }
 
   // TODO(user): Is this the best place for this? Move to fluent functions?
   // Useful as a public method?
-  private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
-      toIterator() {
+  private static <T> Function<Iterable<? extends T>, Iterator<? extends T>> toIterator() {
     return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
       @Override
       public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
index e63a460..d1e1fff 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
@@ -44,6 +44,7 @@ import java.util.NoSuchElementException;
 import java.util.PriorityQueue;
 import java.util.Queue;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -56,39 +57,44 @@ import javax.annotation.Nullable;
  * the backing iteration when absolutely necessary.
  *
  * <p>See the Guava User Guide section on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
  * {@code Iterators}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Iterators {
   private Iterators() {}
 
-  static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR
-      = new UnmodifiableListIterator<Object>() {
+  static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
+      new UnmodifiableListIterator<Object>() {
         @Override
         public boolean hasNext() {
           return false;
         }
+
         @Override
         public Object next() {
           throw new NoSuchElementException();
         }
+
         @Override
         public boolean hasPrevious() {
           return false;
         }
+
         @Override
         public Object previous() {
           throw new NoSuchElementException();
         }
+
         @Override
         public int nextIndex() {
           return 0;
         }
+
         @Override
         public int previousIndex() {
           return -1;
@@ -124,15 +130,18 @@ public final class Iterators {
 
   private static final Iterator<Object> EMPTY_MODIFIABLE_ITERATOR =
       new Iterator<Object>() {
-        @Override public boolean hasNext() {
+        @Override
+        public boolean hasNext() {
           return false;
         }
 
-        @Override public Object next() {
+        @Override
+        public Object next() {
           throw new NoSuchElementException();
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(false);
         }
       };
@@ -150,8 +159,7 @@ public final class Iterators {
   }
 
   /** Returns an unmodifiable view of {@code iterator}. */
-  public static <T> UnmodifiableIterator<T> unmodifiableIterator(
-      final Iterator<T> iterator) {
+  public static <T> UnmodifiableIterator<T> unmodifiableIterator(final Iterator<T> iterator) {
     checkNotNull(iterator);
     if (iterator instanceof UnmodifiableIterator) {
       return (UnmodifiableIterator<T>) iterator;
@@ -161,6 +169,7 @@ public final class Iterators {
       public boolean hasNext() {
         return iterator.hasNext();
       }
+
       @Override
       public T next() {
         return iterator.next();
@@ -174,8 +183,8 @@ public final class Iterators {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <T> UnmodifiableIterator<T> unmodifiableIterator(
-      UnmodifiableIterator<T> iterator) {
+  @Deprecated
+  public static <T> UnmodifiableIterator<T> unmodifiableIterator(UnmodifiableIterator<T> iterator) {
     return checkNotNull(iterator);
   }
 
@@ -209,8 +218,7 @@ public final class Iterators {
    * @param elementsToRemove the elements to remove
    * @return {@code true} if any element was removed from {@code iterator}
    */
-  public static boolean removeAll(
-      Iterator<?> removeFrom, Collection<?> elementsToRemove) {
+  public static boolean removeAll(Iterator<?> removeFrom, Collection<?> elementsToRemove) {
     return removeIf(removeFrom, in(elementsToRemove));
   }
 
@@ -225,8 +233,7 @@ public final class Iterators {
    * @return {@code true} if any elements were removed from the iterator
    * @since 2.0
    */
-  public static <T> boolean removeIf(
-      Iterator<T> removeFrom, Predicate<? super T> predicate) {
+  public static <T> boolean removeIf(Iterator<T> removeFrom, Predicate<? super T> predicate) {
     checkNotNull(predicate);
     boolean modified = false;
     while (removeFrom.hasNext()) {
@@ -247,8 +254,7 @@ public final class Iterators {
    * @param elementsToRetain the elements to retain
    * @return {@code true} if any element was removed from {@code iterator}
    */
-  public static boolean retainAll(
-      Iterator<?> removeFrom, Collection<?> elementsToRetain) {
+  public static boolean retainAll(Iterator<?> removeFrom, Collection<?> elementsToRetain) {
     return removeIf(removeFrom, not(in(elementsToRetain)));
   }
 
@@ -262,8 +268,7 @@ public final class Iterators {
    * <p>Note that this will modify the supplied iterators, since they will have
    * been advanced some number of elements forward.
    */
-  public static boolean elementsEqual(
-      Iterator<?> iterator1, Iterator<?> iterator2) {
+  public static boolean elementsEqual(Iterator<?> iterator1, Iterator<?> iterator2) {
     while (iterator1.hasNext()) {
       if (!iterator2.hasNext()) {
         return false;
@@ -335,8 +340,7 @@ public final class Iterators {
    * @return {@code true} if {@code collection} was modified as a result of this
    *         operation
    */
-  public static <T> boolean addAll(
-      Collection<T> addTo, Iterator<? extends T> iterator) {
+  public static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
     checkNotNull(addTo);
     checkNotNull(iterator);
     boolean wasModified = false;
@@ -374,29 +378,36 @@ public final class Iterators {
   public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
     checkNotNull(iterable);
     return new Iterator<T>() {
-      Iterator<T> iterator = emptyIterator();
-      Iterator<T> removeFrom;
+      Iterator<T> iterator = emptyModifiableIterator();
 
       @Override
       public boolean hasNext() {
-        if (!iterator.hasNext()) {
-          iterator = iterable.iterator();
-        }
-        return iterator.hasNext();
+        /*
+         * Don't store a new Iterator until we know the user can't remove() the last returned
+         * element anymore. Otherwise, when we remove from the old iterator, we may be invalidating
+         * the new one. The result is a ConcurrentModificationException or other bad behavior.
+         *
+         * (If we decide that we really, really hate allocating two Iterators per cycle instead of
+         * one, we can optimistically store the new Iterator and then be willing to throw it out if
+         * the user calls remove().)
+         */
+        return iterator.hasNext() || iterable.iterator().hasNext();
       }
+
       @Override
       public T next() {
-        if (!hasNext()) {
-          throw new NoSuchElementException();
+        if (!iterator.hasNext()) {
+          iterator = iterable.iterator();
+          if (!iterator.hasNext()) {
+            throw new NoSuchElementException();
+          }
         }
-        removeFrom = iterator;
         return iterator.next();
       }
+
       @Override
       public void remove() {
-        checkRemove(removeFrom != null);
-        removeFrom.remove();
-        removeFrom = null;
+        iterator.remove();
       }
     };
   }
@@ -431,9 +442,10 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b) {
-    return concat(ImmutableList.of(a, b).iterator());
+  public static <T> Iterator<T> concat(Iterator<? extends T> a, Iterator<? extends T> b) {
+    checkNotNull(a);
+    checkNotNull(b);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b));
   }
 
   /**
@@ -450,9 +462,12 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b, Iterator<? extends T> c) {
-    return concat(ImmutableList.of(a, b, c).iterator());
+  public static <T> Iterator<T> concat(
+      Iterator<? extends T> a, Iterator<? extends T> b, Iterator<? extends T> c) {
+    checkNotNull(a);
+    checkNotNull(b);
+    checkNotNull(c);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c));
   }
 
   /**
@@ -469,10 +484,16 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b, Iterator<? extends T> c,
+  public static <T> Iterator<T> concat(
+      Iterator<? extends T> a,
+      Iterator<? extends T> b,
+      Iterator<? extends T> c,
       Iterator<? extends T> d) {
-    return concat(ImmutableList.of(a, b, c, d).iterator());
+    checkNotNull(a);
+    checkNotNull(b);
+    checkNotNull(c);
+    checkNotNull(d);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c, d));
   }
 
   /**
@@ -491,7 +512,10 @@ public final class Iterators {
    * @throws NullPointerException if any of the provided iterators is null
    */
   public static <T> Iterator<T> concat(Iterator<? extends T>... inputs) {
-    return concat(ImmutableList.copyOf(inputs).iterator());
+    for (Iterator<? extends T> input : checkNotNull(inputs)) {
+      checkNotNull(input);
+    }
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(inputs));
   }
 
   /**
@@ -508,8 +532,7 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(
-      final Iterator<? extends Iterator<? extends T>> inputs) {
+  public static <T> Iterator<T> concat(final Iterator<? extends Iterator<? extends T>> inputs) {
     checkNotNull(inputs);
     return new Iterator<T>() {
       Iterator<? extends T> current = emptyIterator();
@@ -525,12 +548,12 @@ public final class Iterators {
         // because otherwise we'll have called inputs.next() before throwing
         // the first NPE, and the next time around we'll call inputs.next()
         // again, incorrectly moving beyond the error.
-        while (!(currentHasNext = checkNotNull(current).hasNext())
-            && inputs.hasNext()) {
+        while (!(currentHasNext = checkNotNull(current).hasNext()) && inputs.hasNext()) {
           current = inputs.next();
         }
         return currentHasNext;
       }
+
       @Override
       public T next() {
         if (!hasNext()) {
@@ -539,6 +562,7 @@ public final class Iterators {
         removeFrom = current;
         return current.next();
       }
+
       @Override
       public void remove() {
         checkRemove(removeFrom != null);
@@ -563,8 +587,7 @@ public final class Iterators {
    *     iterator} divided into partitions
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> UnmodifiableIterator<List<T>> partition(
-      Iterator<T> iterator, int size) {
+  public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
     return partitionImpl(iterator, size, false);
   }
 
@@ -584,8 +607,7 @@ public final class Iterators {
    *     trailing null elements)
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> UnmodifiableIterator<List<T>> paddedPartition(
-      Iterator<T> iterator, int size) {
+  public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
     return partitionImpl(iterator, size, true);
   }
 
@@ -598,6 +620,7 @@ public final class Iterators {
       public boolean hasNext() {
         return iterator.hasNext();
       }
+
       @Override
       public List<T> next() {
         if (!hasNext()) {
@@ -613,8 +636,7 @@ public final class Iterators {
         }
 
         @SuppressWarnings("unchecked") // we only put Ts in it
-        List<T> list = Collections.unmodifiableList(
-            (List<T>) Arrays.asList(array));
+        List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
         return (pad || count == size) ? list : list.subList(0, count);
       }
     };
@@ -623,12 +645,14 @@ public final class Iterators {
   /**
    * Returns the elements of {@code unfiltered} that satisfy a predicate.
    */
+  @CheckReturnValue
   public static <T> UnmodifiableIterator<T> filter(
       final Iterator<T> unfiltered, final Predicate<? super T> predicate) {
     checkNotNull(unfiltered);
     checkNotNull(predicate);
     return new AbstractIterator<T>() {
-      @Override protected T computeNext() {
+      @Override
+      protected T computeNext() {
         while (unfiltered.hasNext()) {
           T element = unfiltered.next();
           if (predicate.apply(element)) {
@@ -644,8 +668,7 @@ public final class Iterators {
    * Returns {@code true} if one or more elements returned by {@code iterator}
    * satisfy the given predicate.
    */
-  public static <T> boolean any(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> boolean any(Iterator<T> iterator, Predicate<? super T> predicate) {
     return indexOf(iterator, predicate) != -1;
   }
 
@@ -654,8 +677,7 @@ public final class Iterators {
    * satisfies the given predicate. If {@code iterator} is empty, {@code true}
    * is returned.
    */
-  public static <T> boolean all(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> boolean all(Iterator<T> iterator, Predicate<? super T> predicate) {
     checkNotNull(predicate);
     while (iterator.hasNext()) {
       T element = iterator.next();
@@ -677,8 +699,7 @@ public final class Iterators {
    * @throws NoSuchElementException if no element in {@code iterator} matches
    *     the given predicate
    */
-  public static <T> T find(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> T find(Iterator<T> iterator, Predicate<? super T> predicate) {
     return filter(iterator, predicate).next();
   }
 
@@ -693,8 +714,8 @@ public final class Iterators {
    * @since 7.0
    */
   @Nullable
-  public static <T> T find(Iterator<? extends T> iterator, Predicate<? super T> predicate,
-      @Nullable T defaultValue) {
+  public static <T> T find(
+      Iterator<? extends T> iterator, Predicate<? super T> predicate, @Nullable T defaultValue) {
     return getNext(filter(iterator, predicate), defaultValue);
   }
 
@@ -711,8 +732,7 @@ public final class Iterators {
    *
    * @since 11.0
    */
-  public static <T> Optional<T> tryFind(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> Optional<T> tryFind(Iterator<T> iterator, Predicate<? super T> predicate) {
     UnmodifiableIterator<T> filteredIterator = filter(iterator, predicate);
     return filteredIterator.hasNext()
         ? Optional.of(filteredIterator.next())
@@ -735,8 +755,7 @@ public final class Iterators {
    *
    * @since 2.0
    */
-  public static <T> int indexOf(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> int indexOf(Iterator<T> iterator, Predicate<? super T> predicate) {
     checkNotNull(predicate, "predicate");
     for (int i = 0; iterator.hasNext(); i++) {
       T current = iterator.next();
@@ -755,8 +774,8 @@ public final class Iterators {
    * does. After a successful {@code remove()} call, {@code fromIterator} no
    * longer contains the corresponding element.
    */
-  public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator,
-      final Function<? super F, ? extends T> function) {
+  public static <F, T> Iterator<T> transform(
+      final Iterator<F> fromIterator, final Function<? super F, ? extends T> function) {
     checkNotNull(function);
     return new TransformedIterator<F, T>(fromIterator) {
       @Override
@@ -780,17 +799,19 @@ public final class Iterators {
     checkNonnegative(position);
     int skipped = advance(iterator, position);
     if (!iterator.hasNext()) {
-      throw new IndexOutOfBoundsException("position (" + position
-          + ") must be less than the number of elements that remained ("
-          + skipped + ")");
+      throw new IndexOutOfBoundsException(
+          "position ("
+              + position
+              + ") must be less than the number of elements that remained ("
+              + skipped
+              + ")");
     }
     return iterator.next();
   }
 
   static void checkNonnegative(int position) {
     if (position < 0) {
-      throw new IndexOutOfBoundsException("position (" + position
-          + ") must not be negative");
+      throw new IndexOutOfBoundsException("position (" + position + ") must not be negative");
     }
   }
 
@@ -888,8 +909,7 @@ public final class Iterators {
    * @throws IllegalArgumentException if {@code limitSize} is negative
    * @since 3.0
    */
-  public static <T> Iterator<T> limit(
-      final Iterator<T> iterator, final int limitSize) {
+  public static <T> Iterator<T> limit(final Iterator<T> iterator, final int limitSize) {
     checkNotNull(iterator);
     checkArgument(limitSize >= 0, "limit is negative");
     return new Iterator<T>() {
@@ -1021,7 +1041,8 @@ public final class Iterators {
      * past the beginning of the iteration.
      */
     return new AbstractIndexedListIterator<T>(length, index) {
-      @Override protected T get(int index) {
+      @Override
+      protected T get(int index) {
         return array[offset + index];
       }
     };
@@ -1033,14 +1054,15 @@ public final class Iterators {
    * <p>The {@link Iterable} equivalent of this method is {@link
    * Collections#singleton}.
    */
-  public static <T> UnmodifiableIterator<T> singletonIterator(
-      @Nullable final T value) {
+  public static <T> UnmodifiableIterator<T> singletonIterator(@Nullable final T value) {
     return new UnmodifiableIterator<T>() {
       boolean done;
+
       @Override
       public boolean hasNext() {
         return !done;
       }
+
       @Override
       public T next() {
         if (done) {
@@ -1060,14 +1082,14 @@ public final class Iterators {
    * contents can be <i>copied</i> into a collection using {@link
    * Collections#list}.
    */
-  public static <T> UnmodifiableIterator<T> forEnumeration(
-      final Enumeration<T> enumeration) {
+  public static <T> UnmodifiableIterator<T> forEnumeration(final Enumeration<T> enumeration) {
     checkNotNull(enumeration);
     return new UnmodifiableIterator<T>() {
       @Override
       public boolean hasNext() {
         return enumeration.hasMoreElements();
       }
+
       @Override
       public T next() {
         return enumeration.nextElement();
@@ -1089,6 +1111,7 @@ public final class Iterators {
       public boolean hasMoreElements() {
         return iterator.hasNext();
       }
+
       @Override
       public T nextElement() {
         return iterator.next();
@@ -1179,8 +1202,7 @@ public final class Iterators {
    *     additional {@link PeekingIterator#peek()} method, this iterator behaves
    *     exactly the same as {@code iterator}.
    */
-  public static <T> PeekingIterator<T> peekingIterator(
-      Iterator<? extends T> iterator) {
+  public static <T> PeekingIterator<T> peekingIterator(Iterator<? extends T> iterator) {
     if (iterator instanceof PeekingImpl) {
       // Safe to cast <? extends T> to <T> because PeekingImpl only uses T
       // covariantly (and cannot be subclassed to add non-covariant uses).
@@ -1197,8 +1219,8 @@ public final class Iterators {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <T> PeekingIterator<T> peekingIterator(
-      PeekingIterator<T> iterator) {
+  @Deprecated
+  public static <T> PeekingIterator<T> peekingIterator(PeekingIterator<T> iterator) {
     return checkNotNull(iterator);
   }
 
@@ -1217,8 +1239,7 @@ public final class Iterators {
    */
   @Beta
   public static <T> UnmodifiableIterator<T> mergeSorted(
-      Iterable<? extends Iterator<? extends T>> iterators,
-      Comparator<? super T> comparator) {
+      Iterable<? extends Iterator<? extends T>> iterators, Comparator<? super T> comparator) {
     checkNotNull(iterators, "iterators");
     checkNotNull(comparator, "comparator");
 
@@ -1237,7 +1258,8 @@ public final class Iterators {
   private static class MergingIterator<T> extends UnmodifiableIterator<T> {
     final Queue<PeekingIterator<T>> queue;
 
-    public MergingIterator(Iterable<? extends Iterator<? extends T>> iterators,
+    public MergingIterator(
+        Iterable<? extends Iterator<? extends T>> iterators,
         final Comparator<? super T> itemComparator) {
       // A comparator that's used by the heap, allowing the heap
       // to be sorted based on the top of each iterator.
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
index 1223678..5c9961c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -67,12 +68,12 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedSetMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@@ -94,11 +95,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> LinkedHashMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> LinkedHashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new LinkedHashMultimap<K, V>(
-        Maps.capacity(expectedKeys),
-        Maps.capacity(expectedValuesPerKey));
+        Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey));
   }
 
   /**
@@ -119,9 +118,11 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
 
   private interface ValueSetLink<K, V> {
     ValueSetLink<K, V> getPredecessorInValueSet();
+
     ValueSetLink<K, V> getSuccessorInValueSet();
 
     void setPredecessorInValueSet(ValueSetLink<K, V> entry);
+
     void setSuccessorInValueSet(ValueSetLink<K, V> entry);
   }
 
@@ -130,8 +131,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     succ.setPredecessorInValueSet(pred);
   }
 
-  private static <K, V> void succeedsInMultimap(
-      ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
+  private static <K, V> void succeedsInMultimap(ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
     pred.setSuccessorInMultimap(succ);
     succ.setPredecessorInMultimap(pred);
   }
@@ -151,8 +151,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * in the LinkedHashMultimap as a whole.
    */
   @VisibleForTesting
-  static final class ValueEntry<K, V> extends ImmutableEntry<K, V>
-      implements ValueSetLink<K, V> {
+  static final class ValueEntry<K, V> extends ImmutableEntry<K, V> implements ValueSetLink<K, V> {
     final int smearedValueHash;
 
     @Nullable ValueEntry<K, V> nextInValueBucket;
@@ -163,13 +162,16 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     ValueEntry<K, V> predecessorInMultimap;
     ValueEntry<K, V> successorInMultimap;
 
-    ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash,
+    ValueEntry(
+        @Nullable K key,
+        @Nullable V value,
+        int smearedValueHash,
         @Nullable ValueEntry<K, V> nextInValueBucket) {
       super(key, value);
       this.smearedValueHash = smearedValueHash;
       this.nextInValueBucket = nextInValueBucket;
     }
-    
+
     boolean matchesValue(@Nullable Object v, int smearedVHash) {
       return smearedValueHash == smearedVHash && Objects.equal(getValue(), v);
     }
@@ -280,7 +282,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * multimap, taken at the time the entry is returned by a method call to the
    * collection or its iterator.
    */
-  @Override public Set<Map.Entry<K, V>> entries() {
+  @Override
+  public Set<Map.Entry<K, V>> entries() {
     return super.entries();
   }
 
@@ -291,11 +294,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * <p>The iterator generated by the returned collection traverses the values
    * in the order they were added to the multimap.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
   @VisibleForTesting
+  @WeakOuter
   final class ValueSet extends Sets.ImprovedAbstractSet<V> implements ValueSetLink<K, V> {
     /*
      * We currently use a fixed load factor of 1.0, a bit higher than normal to reduce memory
@@ -318,12 +323,12 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       this.lastEntry = this;
       // Round expected values up to a power of 2 to get the table size.
       int tableSize = Hashing.closedTableSize(expectedValues, VALUE_SET_LOAD_FACTOR);
-      
+
       @SuppressWarnings("unchecked")
       ValueEntry<K, V>[] hashTable = new ValueEntry[tableSize];
       this.hashTable = hashTable;
     }
-    
+
     private int mask() {
       return hashTable.length - 1;
     }
@@ -398,7 +403,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     @Override
     public boolean contains(@Nullable Object o) {
       int smearedHash = Hashing.smearedHash(o);
-      for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()]; entry != null;
+      for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()];
+          entry != null;
           entry = entry.nextInValueBucket) {
         if (entry.matchesValue(o, smearedHash)) {
           return true;
@@ -412,8 +418,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       int smearedHash = Hashing.smearedHash(value);
       int bucket = smearedHash & mask();
       ValueEntry<K, V> rowHead = hashTable[bucket];
-      for (ValueEntry<K, V> entry = rowHead; entry != null;
-          entry = entry.nextInValueBucket) {
+      for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
         if (entry.matchesValue(value, smearedHash)) {
           return false;
         }
@@ -438,7 +443,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
         this.hashTable = hashTable;
         int mask = hashTable.length - 1;
         for (ValueSetLink<K, V> entry = firstEntry;
-            entry != this; entry = entry.getSuccessorInValueSet()) {
+            entry != this;
+            entry = entry.getSuccessorInValueSet()) {
           ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
           int bucket = valueEntry.smearedValueHash & mask;
           valueEntry.nextInValueBucket = hashTable[bucket];
@@ -452,8 +458,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       int smearedHash = Hashing.smearedHash(o);
       int bucket = smearedHash & mask();
       ValueEntry<K, V> prev = null;
-      for (ValueEntry<K, V> entry = hashTable[bucket]; entry != null;
-           prev = entry, entry = entry.nextInValueBucket) {
+      for (ValueEntry<K, V> entry = hashTable[bucket];
+          entry != null;
+          prev = entry, entry = entry.nextInValueBucket) {
         if (entry.matchesValue(o, smearedHash)) {
           if (prev == null) {
             // first entry in the bucket
@@ -476,7 +483,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       Arrays.fill(hashTable, null);
       size = 0;
       for (ValueSetLink<K, V> entry = firstEntry;
-           entry != this; entry = entry.getSuccessorInValueSet()) {
+          entry != this;
+          entry = entry.getSuccessorInValueSet()) {
         ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
         deleteFromMultimap(valueEntry);
       }
@@ -515,7 +523,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       }
     };
   }
-  
+
   @Override
   Iterator<V> valueIterator() {
     return Maps.valueIterator(entryIterator());
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
index da93ead..3259636 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
@@ -27,14 +27,14 @@ import java.util.LinkedHashMap;
  * element, those instances are consecutive in the iteration order. If all
  * occurrences of an element are removed, after which that element is added to
  * the multiset, the element will appear at the end of the iteration.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
@@ -67,10 +67,8 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
    *
    * @param elements the elements that the multiset should contain
    */
-  public static <E> LinkedHashMultiset<E> create(
-      Iterable<? extends E> elements) {
-    LinkedHashMultiset<E> multiset =
-        create(Multisets.inferDistinctElements(elements));
+  public static <E> LinkedHashMultiset<E> create(Iterable<? extends E> elements) {
+    LinkedHashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
     Iterables.addAll(multiset, elements);
     return multiset;
   }
@@ -80,8 +78,7 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
   }
 
   private LinkedHashMultiset(int distinctElements) {
-    // Could use newLinkedHashMapWithExpectedSize() if it existed
-    super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
+    super(Maps.<E, Count>newLinkedHashMapWithExpectedSize(distinctElements));
   }
 }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
index f648b51..3ac726f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 import static java.util.Collections.unmodifiableList;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractSequentialList;
@@ -88,11 +89,11 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedListMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@@ -134,12 +135,12 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       return result;
     }
   }
-  
+
   private static class KeyList<K, V> {
     Node<K, V> head;
     Node<K, V> tail;
     int count;
-    
+
     KeyList(Node<K, V> firstNode) {
       this.head = firstNode;
       this.tail = firstNode;
@@ -153,7 +154,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
   private transient Node<K, V> tail; // the tail for all keys
   private transient Map<K, KeyList<K, V>> keyToKeyList;
   private transient int size;
-  
+
   /*
    * Tracks modifications to keyToKeyList so that addition or removal of keys invalidates
    * preexisting iterators. This does *not* track simple additions and removals of values
@@ -211,8 +212,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
    * nextSibling} is null. Note: if {@code nextSibling} is specified, it MUST be
    * for an node for the same {@code key}!
    */
-  private Node<K, V> addNode(
-      @Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
+  private Node<K, V> addNode(@Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
     Node<K, V> node = new Node<K, V>(key, value);
     if (head == null) { // empty list
       head = tail = node;
@@ -286,7 +286,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       } else {
         node.previousSibling.nextSibling = node.nextSibling;
       }
-      
+
       if (node.nextSibling == null) {
         keyList.tail = node.previousSibling;
       } else {
@@ -333,16 +333,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       }
       current = null;
     }
+
     private void checkForConcurrentModification() {
       if (modCount != expectedModCount) {
         throw new ConcurrentModificationException();
       }
     }
+
     @Override
     public boolean hasNext() {
       checkForConcurrentModification();
       return next != null;
     }
+
     @Override
     public Node<K, V> next() {
       checkForConcurrentModification();
@@ -352,6 +355,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       nextIndex++;
       return current;
     }
+
     @Override
     public void remove() {
       checkForConcurrentModification();
@@ -366,11 +370,13 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       current = null;
       expectedModCount = modCount;
     }
+
     @Override
     public boolean hasPrevious() {
       checkForConcurrentModification();
       return previous != null;
     }
+
     @Override
     public Node<K, V> previous() {
       checkForConcurrentModification();
@@ -380,22 +386,27 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       nextIndex--;
       return current;
     }
+
     @Override
     public int nextIndex() {
       return nextIndex;
     }
+
     @Override
     public int previousIndex() {
       return nextIndex - 1;
     }
+
     @Override
     public void set(Entry<K, V> e) {
       throw new UnsupportedOperationException();
     }
+
     @Override
     public void add(Entry<K, V> e) {
       throw new UnsupportedOperationException();
     }
+
     void setValue(V value) {
       checkState(current != null);
       current.value = value;
@@ -408,17 +419,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
     Node<K, V> next = head;
     Node<K, V> current;
     int expectedModCount = modCount;
-    
+
     private void checkForConcurrentModification() {
       if (modCount != expectedModCount) {
         throw new ConcurrentModificationException();
       }
     }
+
     @Override
     public boolean hasNext() {
       checkForConcurrentModification();
       return next != null;
     }
+
     @Override
     public K next() {
       checkForConcurrentModification();
@@ -430,6 +443,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       } while ((next != null) && !seenKeys.add(next.key));
       return current.key;
     }
+
     @Override
     public void remove() {
       checkForConcurrentModification();
@@ -665,11 +679,14 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
   @Override
   public List<V> get(final @Nullable K key) {
     return new AbstractSequentialList<V>() {
-      @Override public int size() {
+      @Override
+      public int size() {
         KeyList<K, V> keyList = keyToKeyList.get(key);
         return (keyList == null) ? 0 : keyList.count;
       }
-      @Override public ListIterator<V> listIterator(int index) {
+
+      @Override
+      public ListIterator<V> listIterator(int index) {
         return new ValueForKeyIterator(key, index);
       }
     };
@@ -677,21 +694,29 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   Set<K> createKeySet() {
-    return new Sets.ImprovedAbstractSet<K>() {
-      @Override public int size() {
+    @WeakOuter
+    class KeySetImpl extends Sets.ImprovedAbstractSet<K> {
+      @Override
+      public int size() {
         return keyToKeyList.size();
       }
-      @Override public Iterator<K> iterator() {
+
+      @Override
+      public Iterator<K> iterator() {
         return new DistinctKeyIterator();
       }
-      @Override public boolean contains(Object key) { // for performance
+
+      @Override
+      public boolean contains(Object key) { // for performance
         return containsKey(key);
       }
+
       @Override
       public boolean remove(Object o) { // for performance
         return !LinkedListMultimap.this.removeAll(o).isEmpty();
       }
-    };
+    }
+    return new KeySetImpl();
   }
 
   /**
@@ -710,12 +735,15 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   List<V> createValues() {
-    return new AbstractSequentialList<V>() {
-      @Override public int size() {
+    @WeakOuter
+    class ValuesImpl extends AbstractSequentialList<V> {
+      @Override
+      public int size() {
         return size;
       }
 
-      @Override public ListIterator<V> listIterator(int index) {
+      @Override
+      public ListIterator<V> listIterator(int index) {
         final NodeIterator nodeItr = new NodeIterator(index);
         return new TransformedListIterator<Entry<K, V>, V>(nodeItr) {
           @Override
@@ -729,7 +757,8 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
           }
         };
       }
-    };
+    }
+    return new ValuesImpl();
   }
 
   /**
@@ -757,15 +786,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   List<Entry<K, V>> createEntries() {
-    return new AbstractSequentialList<Entry<K, V>>() {
-      @Override public int size() {
+    @WeakOuter
+    class EntriesImpl extends AbstractSequentialList<Entry<K, V>> {
+      @Override
+      public int size() {
         return size;
       }
 
-      @Override public ListIterator<Entry<K, V>> listIterator(int index) {
+      @Override
+      public ListIterator<Entry<K, V>> listIterator(int index) {
         return new NodeIterator(index);
       }
-    };
+    }
+    return new EntriesImpl();
   }
 
   @Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
index 74e9606..ab30fa5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
@@ -48,6 +48,7 @@ import java.util.ListIterator;
 import java.util.NoSuchElementException;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -55,13 +56,13 @@ import javax.annotation.Nullable;
  * class's counterparts {@link Sets}, {@link Maps} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Lists">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#lists">
  * {@code Lists}</a>.
  *
  * @author Kevin Bourrillion
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Lists {
@@ -113,7 +114,8 @@ public final class Lists {
     return list;
   }
 
-  @VisibleForTesting static int computeArrayListCapacity(int arraySize) {
+  @VisibleForTesting
+  static int computeArrayListCapacity(int arraySize) {
     checkNonnegative(arraySize, "arraySize");
 
     // TODO(kevinb): Figure out the right behavior, and document it
@@ -178,8 +180,7 @@ public final class Lists {
    * @throws IllegalArgumentException if {@code initialArraySize} is negative
    */
   @GwtCompatible(serializable = true)
-  public static <E> ArrayList<E> newArrayListWithCapacity(
-      int initialArraySize) {
+  public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
     checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
     return new ArrayList<E>(initialArraySize);
   }
@@ -201,8 +202,7 @@ public final class Lists {
    * @throws IllegalArgumentException if {@code estimatedSize} is negative
    */
   @GwtCompatible(serializable = true)
-  public static <E> ArrayList<E> newArrayListWithExpectedSize(
-      int estimatedSize) {
+  public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
     return new ArrayList<E>(computeArrayListCapacity(estimatedSize));
   }
 
@@ -251,8 +251,7 @@ public final class Lists {
    * advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
    */
   @GwtCompatible(serializable = true)
-  public static <E> LinkedList<E> newLinkedList(
-      Iterable<? extends E> elements) {
+  public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
     LinkedList<E> list = newLinkedList();
     Iterables.addAll(list, elements);
     return list;
@@ -288,14 +287,19 @@ public final class Lists {
       this.first = first;
       this.rest = checkNotNull(rest);
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return rest.length + 1;
     }
-    @Override public E get(int index) {
+
+    @Override
+    public E get(int index) {
       // check explicitly so the IOOBE will have the right message
       checkElementIndex(index, size());
       return (index == 0) ? first : rest[index - 1];
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -316,8 +320,7 @@ public final class Lists {
    * @param rest an array of additional elements, possibly empty
    * @return an unmodifiable list containing the specified elements
    */
-  public static <E> List<E> asList(
-      @Nullable E first, @Nullable E second, E[] rest) {
+  public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
     return new TwoPlusArrayList<E>(first, second, rest);
   }
 
@@ -333,10 +336,14 @@ public final class Lists {
       this.second = second;
       this.rest = checkNotNull(rest);
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return rest.length + 2;
     }
-    @Override public E get(int index) {
+
+    @Override
+    public E get(int index) {
       switch (index) {
         case 0:
           return first;
@@ -348,6 +355,7 @@ public final class Lists {
           return rest[index - 2];
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -406,8 +414,9 @@ public final class Lists {
    *     be greater than {@link Integer#MAX_VALUE}
    * @throws NullPointerException if {@code lists}, any one of the {@code lists},
    *     or any element of a provided list is null
-   */ static <B> List<List<B>>
-      cartesianProduct(List<? extends List<? extends B>> lists) {
+   * @since 19.0
+   */
+  public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
     return CartesianList.create(lists);
   }
 
@@ -466,8 +475,9 @@ public final class Lists {
    *     be greater than {@link Integer#MAX_VALUE}
    * @throws NullPointerException if {@code lists}, any one of the
    *     {@code lists}, or any element of a provided list is null
-   */ static <B> List<List<B>>
-      cartesianProduct(List<? extends B>... lists) {
+   * @since 19.0
+   */
+  public static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
     return cartesianProduct(Arrays.asList(lists));
   }
 
@@ -504,6 +514,7 @@ public final class Lists {
    * then serialize the copy. Other methods similar to this do not implement
    * serialization at all for this reason.
    */
+  @CheckReturnValue
   public static <F, T> List<T> transform(
       List<F> fromList, Function<? super F, ? extends T> function) {
     return (fromList instanceof RandomAccess)
@@ -516,13 +527,12 @@ public final class Lists {
    *
    * @see Lists#transform
    */
-  private static class TransformingSequentialList<F, T>
-      extends AbstractSequentialList<T> implements Serializable {
+  private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
+      implements Serializable {
     final List<F> fromList;
     final Function<? super F, ? extends T> function;
 
-    TransformingSequentialList(
-        List<F> fromList, Function<? super F, ? extends T> function) {
+    TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
       this.fromList = checkNotNull(fromList);
       this.function = checkNotNull(function);
     }
@@ -531,13 +541,18 @@ public final class Lists {
      * each element which can be overkill. That's why we forward this call
      * directly to the backing list.
      */
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromList.clear();
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return fromList.size();
     }
-    @Override public ListIterator<T> listIterator(final int index) {
+
+    @Override
+    public ListIterator<T> listIterator(final int index) {
       return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
         @Override
         T transform(F from) {
@@ -557,26 +572,33 @@ public final class Lists {
    *
    * @see Lists#transform
    */
-  private static class TransformingRandomAccessList<F, T>
-      extends AbstractList<T> implements RandomAccess, Serializable {
+  private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
+      implements RandomAccess, Serializable {
     final List<F> fromList;
     final Function<? super F, ? extends T> function;
 
-    TransformingRandomAccessList(
-        List<F> fromList, Function<? super F, ? extends T> function) {
+    TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
       this.fromList = checkNotNull(fromList);
       this.function = checkNotNull(function);
     }
-    @Override public void clear() {
+
+    @Override
+    public void clear() {
       fromList.clear();
     }
-    @Override public T get(int index) {
+
+    @Override
+    public T get(int index) {
       return function.apply(fromList.get(index));
     }
-    @Override public Iterator<T> iterator() {
+
+    @Override
+    public Iterator<T> iterator() {
       return listIterator();
     }
-    @Override public ListIterator<T> listIterator(int index) {
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
       return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
         @Override
         T transform(F from) {
@@ -584,15 +606,22 @@ public final class Lists {
         }
       };
     }
-    @Override public boolean isEmpty() {
+
+    @Override
+    public boolean isEmpty() {
       return fromList.isEmpty();
     }
-    @Override public T remove(int index) {
+
+    @Override
+    public T remove(int index) {
       return function.apply(fromList.remove(index));
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return fromList.size();
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -631,24 +660,26 @@ public final class Lists {
       this.size = size;
     }
 
-    @Override public List<T> get(int index) {
+    @Override
+    public List<T> get(int index) {
       checkElementIndex(index, size());
       int start = index * size;
       int end = Math.min(start + size, list.size());
       return list.subList(start, end);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return IntMath.divide(list.size(), size, RoundingMode.CEILING);
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return list.isEmpty();
     }
   }
 
-  private static class RandomAccessPartition<T> extends Partition<T>
-      implements RandomAccess {
+  private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
     RandomAccessPartition(List<T> list, int size) {
       super(list, size);
     }
@@ -660,13 +691,13 @@ public final class Lists {
    *
    * @since 7.0
    */
-  @Beta public static ImmutableList<Character> charactersOf(String string) {
+  @Beta
+  public static ImmutableList<Character> charactersOf(String string) {
     return new StringAsImmutableList(checkNotNull(string));
   }
 
   @SuppressWarnings("serial") // serialized using ImmutableList serialization
-  private static final class StringAsImmutableList
-      extends ImmutableList<Character> {
+  private static final class StringAsImmutableList extends ImmutableList<Character> {
 
     private final String string;
 
@@ -674,32 +705,35 @@ public final class Lists {
       this.string = string;
     }
 
-    @Override public int indexOf(@Nullable Object object) {
-      return (object instanceof Character)
-          ? string.indexOf((Character) object) : -1;
+    @Override
+    public int indexOf(@Nullable Object object) {
+      return (object instanceof Character) ? string.indexOf((Character) object) : -1;
     }
 
-    @Override public int lastIndexOf(@Nullable Object object) {
-      return (object instanceof Character)
-          ? string.lastIndexOf((Character) object) : -1;
+    @Override
+    public int lastIndexOf(@Nullable Object object) {
+      return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
     }
 
-    @Override public ImmutableList<Character> subList(
-        int fromIndex, int toIndex) {
+    @Override
+    public ImmutableList<Character> subList(int fromIndex, int toIndex) {
       checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
       return charactersOf(string.substring(fromIndex, toIndex));
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return false;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size()); // for GWT
       return string.charAt(index);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return string.length();
     }
   }
@@ -715,24 +749,26 @@ public final class Lists {
    * @return an {@code List<Character>} view of the character sequence
    * @since 7.0
    */
-  @Beta public static List<Character> charactersOf(CharSequence sequence) {
+  @Beta
+  public static List<Character> charactersOf(CharSequence sequence) {
     return new CharSequenceAsList(checkNotNull(sequence));
   }
 
-  private static final class CharSequenceAsList
-      extends AbstractList<Character> {
+  private static final class CharSequenceAsList extends AbstractList<Character> {
     private final CharSequence sequence;
 
     CharSequenceAsList(CharSequence sequence) {
       this.sequence = sequence;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size()); // for GWT
       return sequence.charAt(index);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return sequence.length();
     }
   }
@@ -749,6 +785,7 @@ public final class Lists {
    *
    * @since 7.0
    */
+  @CheckReturnValue
   public static <T> List<T> reverse(List<T> list) {
     if (list instanceof ImmutableList) {
       return ((ImmutableList<T>) list).reverse();
@@ -784,66 +821,79 @@ public final class Lists {
       return size - index;
     }
 
-    @Override public void add(int index, @Nullable T element) {
+    @Override
+    public void add(int index, @Nullable T element) {
       forwardList.add(reversePosition(index), element);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       forwardList.clear();
     }
 
-    @Override public T remove(int index) {
+    @Override
+    public T remove(int index) {
       return forwardList.remove(reverseIndex(index));
     }
 
-    @Override protected void removeRange(int fromIndex, int toIndex) {
+    @Override
+    protected void removeRange(int fromIndex, int toIndex) {
       subList(fromIndex, toIndex).clear();
     }
 
-    @Override public T set(int index, @Nullable T element) {
+    @Override
+    public T set(int index, @Nullable T element) {
       return forwardList.set(reverseIndex(index), element);
     }
 
-    @Override public T get(int index) {
+    @Override
+    public T get(int index) {
       return forwardList.get(reverseIndex(index));
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return forwardList.size();
     }
 
-    @Override public List<T> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<T> subList(int fromIndex, int toIndex) {
       checkPositionIndexes(fromIndex, toIndex, size());
-      return reverse(forwardList.subList(
-          reversePosition(toIndex), reversePosition(fromIndex)));
+      return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
     }
 
-    @Override public Iterator<T> iterator() {
+    @Override
+    public Iterator<T> iterator() {
       return listIterator();
     }
 
-    @Override public ListIterator<T> listIterator(int index) {
+    @Override
+    public ListIterator<T> listIterator(int index) {
       int start = reversePosition(index);
       final ListIterator<T> forwardIterator = forwardList.listIterator(start);
       return new ListIterator<T>() {
 
         boolean canRemoveOrSet;
 
-        @Override public void add(T e) {
+        @Override
+        public void add(T e) {
           forwardIterator.add(e);
           forwardIterator.previous();
           canRemoveOrSet = false;
         }
 
-        @Override public boolean hasNext() {
+        @Override
+        public boolean hasNext() {
           return forwardIterator.hasPrevious();
         }
 
-        @Override public boolean hasPrevious() {
+        @Override
+        public boolean hasPrevious() {
           return forwardIterator.hasNext();
         }
 
-        @Override public T next() {
+        @Override
+        public T next() {
           if (!hasNext()) {
             throw new NoSuchElementException();
           }
@@ -851,11 +901,13 @@ public final class Lists {
           return forwardIterator.previous();
         }
 
-        @Override public int nextIndex() {
+        @Override
+        public int nextIndex() {
           return reversePosition(forwardIterator.nextIndex());
         }
 
-        @Override public T previous() {
+        @Override
+        public T previous() {
           if (!hasPrevious()) {
             throw new NoSuchElementException();
           }
@@ -863,17 +915,20 @@ public final class Lists {
           return forwardIterator.next();
         }
 
-        @Override public int previousIndex() {
+        @Override
+        public int previousIndex() {
           return nextIndex() - 1;
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(canRemoveOrSet);
           forwardIterator.remove();
           canRemoveOrSet = false;
         }
 
-        @Override public void set(T e) {
+        @Override
+        public void set(T e) {
           checkState(canRemoveOrSet);
           forwardIterator.set(e);
         }
@@ -881,8 +936,7 @@ public final class Lists {
     }
   }
 
-  private static class RandomAccessReverseList<T> extends ReverseList<T>
-      implements RandomAccess {
+  private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
     RandomAccessReverseList(List<T> forwardList) {
       super(forwardList);
     }
@@ -892,7 +946,7 @@ public final class Lists {
    * An implementation of {@link List#hashCode()}.
    */
   static int hashCodeImpl(List<?> list) {
-    // TODO(user): worth optimizing for RandomAccess?
+    // TODO(lowasser): worth optimizing for RandomAccess?
     int hashCode = 1;
     for (Object o : list) {
       hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
@@ -906,25 +960,35 @@ public final class Lists {
   /**
    * An implementation of {@link List#equals(Object)}.
    */
-  static boolean equalsImpl(List<?> list, @Nullable Object object) {
-    if (object == checkNotNull(list)) {
+  static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
+    if (other == checkNotNull(thisList)) {
       return true;
     }
-    if (!(object instanceof List)) {
+    if (!(other instanceof List)) {
       return false;
     }
-
-    List<?> o = (List<?>) object;
-
-    return list.size() == o.size()
-        && Iterators.elementsEqual(list.iterator(), o.iterator());
+    List<?> otherList = (List<?>) other;
+    int size = thisList.size();
+    if (size != otherList.size()) {
+      return false;
+    }
+    if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
+      // avoid allocation and use the faster loop
+      for (int i = 0; i < size; i++) {
+        if (!Objects.equal(thisList.get(i), otherList.get(i))) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
+    }
   }
 
   /**
    * An implementation of {@link List#addAll(int, Collection)}.
    */
-  static <E> boolean addAllImpl(
-      List<E> list, int index, Iterable<? extends E> elements) {
+  static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
     boolean changed = false;
     ListIterator<E> listIterator = list.listIterator(index);
     for (E e : elements) {
@@ -938,10 +1002,32 @@ public final class Lists {
    * An implementation of {@link List#indexOf(Object)}.
    */
   static int indexOfImpl(List<?> list, @Nullable Object element) {
-    ListIterator<?> listIterator = list.listIterator();
-    while (listIterator.hasNext()) {
-      if (Objects.equal(element, listIterator.next())) {
-        return listIterator.previousIndex();
+    if (list instanceof RandomAccess) {
+      return indexOfRandomAccess(list, element);
+    } else {
+      ListIterator<?> listIterator = list.listIterator();
+      while (listIterator.hasNext()) {
+        if (Objects.equal(element, listIterator.next())) {
+          return listIterator.previousIndex();
+        }
+      }
+      return -1;
+    }
+  }
+
+  private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
+    int size = list.size();
+    if (element == null) {
+      for (int i = 0; i < size; i++) {
+        if (list.get(i) == null) {
+          return i;
+        }
+      }
+    } else {
+      for (int i = 0; i < size; i++) {
+        if (element.equals(list.get(i))) {
+          return i;
+        }
       }
     }
     return -1;
@@ -951,10 +1037,31 @@ public final class Lists {
    * An implementation of {@link List#lastIndexOf(Object)}.
    */
   static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
-    ListIterator<?> listIterator = list.listIterator(list.size());
-    while (listIterator.hasPrevious()) {
-      if (Objects.equal(element, listIterator.previous())) {
-        return listIterator.nextIndex();
+    if (list instanceof RandomAccess) {
+      return lastIndexOfRandomAccess(list, element);
+    } else {
+      ListIterator<?> listIterator = list.listIterator(list.size());
+      while (listIterator.hasPrevious()) {
+        if (Objects.equal(element, listIterator.previous())) {
+          return listIterator.nextIndex();
+        }
+      }
+      return -1;
+    }
+  }
+
+  private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
+    if (element == null) {
+      for (int i = list.size() - 1; i >= 0; i--) {
+        if (list.get(i) == null) {
+          return i;
+        }
+      }
+    } else {
+      for (int i = list.size() - 1; i >= 0; i--) {
+        if (element.equals(list.get(i))) {
+          return i;
+        }
       }
     }
     return -1;
@@ -970,12 +1077,12 @@ public final class Lists {
   /**
    * An implementation of {@link List#subList(int, int)}.
    */
-  static <E> List<E> subListImpl(
-      final List<E> list, int fromIndex, int toIndex) {
+  static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
     List<E> wrapper;
     if (list instanceof RandomAccess) {
       wrapper = new RandomAccessListWrapper<E>(list) {
-        @Override public ListIterator<E> listIterator(int index) {
+        @Override
+        public ListIterator<E> listIterator(int index) {
           return backingList.listIterator(index);
         }
 
@@ -983,7 +1090,8 @@ public final class Lists {
       };
     } else {
       wrapper = new AbstractListWrapper<E>(list) {
-        @Override public ListIterator<E> listIterator(int index) {
+        @Override
+        public ListIterator<E> listIterator(int index) {
           return backingList.listIterator(index);
         }
 
@@ -1000,37 +1108,44 @@ public final class Lists {
       this.backingList = checkNotNull(backingList);
     }
 
-    @Override public void add(int index, E element) {
+    @Override
+    public void add(int index, E element) {
       backingList.add(index, element);
     }
 
-    @Override public boolean addAll(int index, Collection<? extends E> c) {
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
       return backingList.addAll(index, c);
     }
 
-    @Override public E get(int index) {
+    @Override
+    public E get(int index) {
       return backingList.get(index);
     }
 
-    @Override public E remove(int index) {
+    @Override
+    public E remove(int index) {
       return backingList.remove(index);
     }
 
-    @Override public E set(int index, E element) {
+    @Override
+    public E set(int index, E element) {
       return backingList.set(index, element);
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return backingList.contains(o);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return backingList.size();
     }
   }
 
-  private static class RandomAccessListWrapper<E>
-      extends AbstractListWrapper<E> implements RandomAccess {
+  private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
+      implements RandomAccess {
     RandomAccessListWrapper(List<E> backingList) {
       super(backingList);
     }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
index ac4c06a..69abc79 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
@@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit;
  */
 public final class MapMaker extends GenericMapMaker<Object, Object> {
 
-  // TODO(fry,user): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
+  // TODO(fry,kak): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
   // this implementation (based on a LHM) does. This will all be replaced soon anyways, so leaving
   // it as is for now.
   private static class ExpiringComputingMap<K, V> extends LinkedHashMap<K, V>
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
index f5d84ae..e9e046a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
@@ -36,6 +36,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.MapDifference.ValueDifference;
 import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
@@ -56,6 +58,7 @@ import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -64,14 +67,14 @@ import javax.annotation.Nullable;
  * {@link Lists}, {@link Sets} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Maps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#maps">
  * {@code Maps}</a>.
  *
  * @author Kevin Bourrillion
  * @author Mike Bostock
  * @author Isaac Shum
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Maps {
@@ -112,21 +115,6 @@ public final class Maps {
     return Iterators.transform(entryIterator, Maps.<V>valueFunction());
   }
 
-  static <K, V> UnmodifiableIterator<V> valueIterator(
-      final UnmodifiableIterator<Entry<K, V>> entryIterator) {
-    return new UnmodifiableIterator<V>() {
-      @Override
-      public boolean hasNext() {
-        return entryIterator.hasNext();
-      }
-
-      @Override
-      public V next() {
-        return entryIterator.next().getValue();
-      }
-    };
-  }
-
   /**
    * Returns an immutable map instance containing the given entries.
    * Internally, the returned map will be backed by an {@link EnumMap}.
@@ -176,17 +164,16 @@ public final class Maps {
    * Creates a {@code HashMap} instance, with a high enough "initial capacity"
    * that it <i>should</i> hold {@code expectedSize} elements without growth.
    * This behavior cannot be broadly guaranteed, but it is observed to be true
-   * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
+   * for OpenJDK 1.7. It also can't be guaranteed that the method isn't
    * inadvertently <i>oversizing</i> the returned map.
    *
-   * @param expectedSize the number of elements you expect to add to the
+   * @param expectedSize the number of entries you expect to add to the
    *        returned map
    * @return a new, empty {@code HashMap} with enough capacity to hold {@code
-   *         expectedSize} elements without resizing
+   *         expectedSize} entries without resizing
    * @throws IllegalArgumentException if {@code expectedSize} is negative
    */
-  public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(
-      int expectedSize) {
+  public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
     return new HashMap<K, V>(capacity(expectedSize));
   }
 
@@ -201,7 +188,10 @@ public final class Maps {
       return expectedSize + 1;
     }
     if (expectedSize < Ints.MAX_POWER_OF_TWO) {
-      return expectedSize + expectedSize / 3;
+      // This is the calculation used in JDK8 to resize when a putAll
+      // happens; it seems to be the most conservative calculation we
+      // can make.  0.75 is the default load factor.
+      return (int) ((float) expectedSize / 0.75F + 1.0F);
     }
     return Integer.MAX_VALUE; // any large value
   }
@@ -220,8 +210,7 @@ public final class Maps {
    * @return a new {@code HashMap} initialized with the mappings from {@code
    *         map}
    */
-  public static <K, V> HashMap<K, V> newHashMap(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map) {
     return new HashMap<K, V>(map);
   }
 
@@ -239,6 +228,24 @@ public final class Maps {
   }
 
   /**
+   * Creates a {@code LinkedHashMap} instance, with a high enough
+   * "initial capacity" that it <i>should</i> hold {@code expectedSize}
+   * elements without growth. This behavior cannot be broadly guaranteed, but
+   * it is observed to be true for OpenJDK 1.7. It also can't be guaranteed
+   * that the method isn't inadvertently <i>oversizing</i> the returned map.
+   *
+   * @param expectedSize the number of entries you expect to add to the
+   *        returned map
+   * @return a new, empty {@code LinkedHashMap} with enough capacity to hold
+   *         {@code expectedSize} entries without resizing
+   * @throws IllegalArgumentException if {@code expectedSize} is negative
+   * @since 19.0
+   */
+  public static <K, V> LinkedHashMap<K, V> newLinkedHashMapWithExpectedSize(int expectedSize) {
+    return new LinkedHashMap<K, V>(capacity(expectedSize));
+  }
+
+  /**
    * Creates a <i>mutable</i>, insertion-ordered {@code LinkedHashMap} instance
    * with the same mappings as the specified map.
    *
@@ -249,8 +256,7 @@ public final class Maps {
    * @return a new, {@code LinkedHashMap} initialized with the mappings from
    *         {@code map}
    */
-  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map) {
     return new LinkedHashMap<K, V>(map);
   }
 
@@ -312,8 +318,7 @@ public final class Maps {
    * @param comparator the comparator to sort the keys with
    * @return a new, empty {@code TreeMap}
    */
-  public static <C, K extends C, V> TreeMap<K, V> newTreeMap(
-      @Nullable Comparator<C> comparator) {
+  public static <C, K extends C, V> TreeMap<K, V> newTreeMap(@Nullable Comparator<C> comparator) {
     // Ideally, the extra type parameter "C" shouldn't be necessary. It is a
     // work-around of a compiler type inference quirk that prevents the
     // following code from being compiled:
@@ -341,8 +346,7 @@ public final class Maps {
    * @throws IllegalArgumentException if {@code m} is not an {@code EnumMap}
    *         instance and contains no mappings
    */
-  public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(
-      Map<K, ? extends V> map) {
+  public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Map<K, ? extends V> map) {
     return new EnumMap<K, V>(map);
   }
 
@@ -403,22 +407,26 @@ public final class Maps {
    */
   @Beta
   public static <K, V> MapDifference<K, V> difference(
-      Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+      Map<? extends K, ? extends V> left,
+      Map<? extends K, ? extends V> right,
       Equivalence<? super V> valueEquivalence) {
     Preconditions.checkNotNull(valueEquivalence);
 
-    Map<K, V> onlyOnLeft = newHashMap();
-    Map<K, V> onlyOnRight = new HashMap<K, V>(right); // will whittle it down
-    Map<K, V> onBoth = newHashMap();
-    Map<K, MapDifference.ValueDifference<V>> differences = newHashMap();
+    Map<K, V> onlyOnLeft = newLinkedHashMap();
+    Map<K, V> onlyOnRight = new LinkedHashMap<K, V>(right); // will whittle it down
+    Map<K, V> onBoth = newLinkedHashMap();
+    Map<K, MapDifference.ValueDifference<V>> differences = newLinkedHashMap();
     doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences);
     return new MapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
   }
 
   private static <K, V> void doDifference(
-      Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+      Map<? extends K, ? extends V> left,
+      Map<? extends K, ? extends V> right,
       Equivalence<? super V> valueEquivalence,
-      Map<K, V> onlyOnLeft, Map<K, V> onlyOnRight, Map<K, V> onBoth,
+      Map<K, V> onlyOnLeft,
+      Map<K, V> onlyOnRight,
+      Map<K, V> onBoth,
       Map<K, MapDifference.ValueDifference<V>> differences) {
     for (Entry<? extends K, ? extends V> entry : left.entrySet()) {
       K leftKey = entry.getKey();
@@ -428,8 +436,7 @@ public final class Maps {
         if (valueEquivalence.equivalent(leftValue, rightValue)) {
           onBoth.put(leftKey, leftValue);
         } else {
-          differences.put(
-              leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
+          differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
         }
       } else {
         onlyOnLeft.put(leftKey, leftValue);
@@ -451,8 +458,10 @@ public final class Maps {
     final Map<K, V> onBoth;
     final Map<K, ValueDifference<V>> differences;
 
-    MapDifferenceImpl(Map<K, V> onlyOnLeft,
-        Map<K, V> onlyOnRight, Map<K, V> onBoth,
+    MapDifferenceImpl(
+        Map<K, V> onlyOnLeft,
+        Map<K, V> onlyOnRight,
+        Map<K, V> onBoth,
         Map<K, ValueDifference<V>> differences) {
       this.onlyOnLeft = unmodifiableMap(onlyOnLeft);
       this.onlyOnRight = unmodifiableMap(onlyOnRight);
@@ -485,7 +494,8 @@ public final class Maps {
       return differences;
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(Object object) {
       if (object == this) {
         return true;
       }
@@ -499,12 +509,14 @@ public final class Maps {
       return false;
     }
 
-    @Override public int hashCode() {
-      return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(),
-          entriesInCommon(), entriesDiffering());
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(
+          entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering());
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       if (areEqual()) {
         return "equal";
       }
@@ -523,8 +535,7 @@ public final class Maps {
     }
   }
 
-  static class ValueDifferenceImpl<V>
-      implements MapDifference.ValueDifference<V> {
+  static class ValueDifferenceImpl<V> implements MapDifference.ValueDifference<V> {
     private final V left;
     private final V right;
 
@@ -547,21 +558,23 @@ public final class Maps {
       return right;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object instanceof MapDifference.ValueDifference) {
-        MapDifference.ValueDifference<?> that =
-            (MapDifference.ValueDifference<?>) object;
+        MapDifference.ValueDifference<?> that = (MapDifference.ValueDifference<?>) object;
         return Objects.equal(this.left, that.leftValue())
             && Objects.equal(this.right, that.rightValue());
       }
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(left, right);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "(" + left + ", " + right + ")";
     }
   }
@@ -594,33 +607,38 @@ public final class Maps {
     SortedMap<K, V> onlyOnRight = Maps.newTreeMap(comparator);
     onlyOnRight.putAll(right); // will whittle it down
     SortedMap<K, V> onBoth = Maps.newTreeMap(comparator);
-    SortedMap<K, MapDifference.ValueDifference<V>> differences =
-        Maps.newTreeMap(comparator);
+    SortedMap<K, MapDifference.ValueDifference<V>> differences = Maps.newTreeMap(comparator);
     doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
     return new SortedMapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
   }
 
   static class SortedMapDifferenceImpl<K, V> extends MapDifferenceImpl<K, V>
       implements SortedMapDifference<K, V> {
-    SortedMapDifferenceImpl(SortedMap<K, V> onlyOnLeft,
-        SortedMap<K, V> onlyOnRight, SortedMap<K, V> onBoth,
+    SortedMapDifferenceImpl(
+        SortedMap<K, V> onlyOnLeft,
+        SortedMap<K, V> onlyOnRight,
+        SortedMap<K, V> onBoth,
         SortedMap<K, ValueDifference<V>> differences) {
       super(onlyOnLeft, onlyOnRight, onBoth, differences);
     }
 
-    @Override public SortedMap<K, ValueDifference<V>> entriesDiffering() {
+    @Override
+    public SortedMap<K, ValueDifference<V>> entriesDiffering() {
       return (SortedMap<K, ValueDifference<V>>) super.entriesDiffering();
     }
 
-    @Override public SortedMap<K, V> entriesInCommon() {
+    @Override
+    public SortedMap<K, V> entriesInCommon() {
       return (SortedMap<K, V>) super.entriesInCommon();
     }
 
-    @Override public SortedMap<K, V> entriesOnlyOnLeft() {
+    @Override
+    public SortedMap<K, V> entriesOnlyOnLeft() {
       return (SortedMap<K, V>) super.entriesOnlyOnLeft();
     }
 
-    @Override public SortedMap<K, V> entriesOnlyOnRight() {
+    @Override
+    public SortedMap<K, V> entriesOnlyOnRight() {
       return (SortedMap<K, V>) super.entriesOnlyOnRight();
     }
   }
@@ -631,8 +649,7 @@ public final class Maps {
    * purpose of this method is to contain the ugly type-casting in one place.
    */
   @SuppressWarnings("unchecked")
-  static <E> Comparator<? super E> orNaturalOrder(
-      @Nullable Comparator<? super E> comparator) {
+  static <E> Comparator<? super E> orNaturalOrder(@Nullable Comparator<? super E> comparator) {
     if (comparator != null) { // can't use ? : because of javac bug 5080917
       return comparator;
     }
@@ -666,9 +683,7 @@ public final class Maps {
    *
    * @since 14.0
    */
-  @Beta
-  public static <K, V> Map<K, V> asMap(
-      Set<K> set, Function<? super K, V> function) {
+  public static <K, V> Map<K, V> asMap(Set<K> set, Function<? super K, V> function) {
     if (set instanceof SortedSet) {
       return asMap((SortedSet<K>) set, function);
     } else {
@@ -702,18 +717,16 @@ public final class Maps {
    *
    * @since 14.0
    */
-  @Beta
-  public static <K, V> SortedMap<K, V> asMap(
-      SortedSet<K> set, Function<? super K, V> function) {
+  public static <K, V> SortedMap<K, V> asMap(SortedSet<K> set, Function<? super K, V> function) {
     return Platform.mapsAsMapSortedSet(set, function);
   }
 
-  static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(SortedSet<K> set,
-      Function<? super K, V> function) {
+  static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(
+      SortedSet<K> set, Function<? super K, V> function) {
     return new SortedAsMapView<K, V>(set, function);
   }
 
-  private static class AsMapView<K, V> extends ImprovedAbstractMap<K, V> {
+  private static class AsMapView<K, V> extends ViewCachingAbstractMap<K, V> {
 
     private final Set<K> set;
     final Function<? super K, V> function;
@@ -776,7 +789,8 @@ public final class Maps {
 
     @Override
     protected Set<Entry<K, V>> createEntrySet() {
-      return new EntrySet<K, V>() {
+      @WeakOuter
+      class EntrySetImpl extends EntrySet<K, V> {
         @Override
         Map<K, V> map() {
           return AsMapView.this;
@@ -786,13 +800,14 @@ public final class Maps {
         public Iterator<Entry<K, V>> iterator() {
           return asMapEntryIterator(backingSet(), function);
         }
-      };
+      }
+      return new EntrySetImpl();
     }
   }
 
   static <K, V> Iterator<Entry<K, V>> asMapEntryIterator(
       Set<K> set, final Function<? super K, V> function) {
-    return new TransformedIterator<K, Entry<K,V>>(set.iterator()) {
+    return new TransformedIterator<K, Entry<K, V>>(set.iterator()) {
       @Override
       Entry<K, V> transform(final K key) {
         return immutableEntry(key, function.apply(key));
@@ -800,8 +815,7 @@ public final class Maps {
     };
   }
 
-  private static class SortedAsMapView<K, V> extends AsMapView<K, V>
-      implements SortedMap<K, V> {
+  private static class SortedAsMapView<K, V> extends AsMapView<K, V> implements SortedMap<K, V> {
 
     SortedAsMapView(SortedSet<K> set, Function<? super K, V> function) {
       super(set, function);
@@ -907,6 +921,11 @@ public final class Maps {
    * The map's iteration order is the order of the first appearance of each key
    * in {@code keys}.
    *
+   * <p>When there are multiple instances of a key in {@code keys}, it is
+   * unspecified whether {@code valueFunction} will be applied to more than one
+   * instance of that key and, if it is, which result will be mapped to that
+   * key in the returned map.
+   *
    * <p>If {@code keys} is a {@link Set}, a live view can be obtained instead of
    * a copy using {@link Maps#asMap(Set, Function)}.
    *
@@ -915,9 +934,8 @@ public final class Maps {
    *     for any key
    * @since 14.0
    */
-  @Beta
-  public static <K, V> ImmutableMap<K, V> toMap(Iterable<K> keys,
-      Function<? super K, V> valueFunction) {
+  public static <K, V> ImmutableMap<K, V> toMap(
+      Iterable<K> keys, Function<? super K, V> valueFunction) {
     return toMap(keys.iterator(), valueFunction);
   }
 
@@ -927,14 +945,18 @@ public final class Maps {
    * The map's iteration order is the order of the first appearance of each key
    * in {@code keys}.
    *
+   * <p>When there are multiple instances of a key in {@code keys}, it is
+   * unspecified whether {@code valueFunction} will be applied to more than one
+   * instance of that key and, if it is, which result will be mapped to that
+   * key in the returned map.
+   *
    * @throws NullPointerException if any element of {@code keys} is
    *     {@code null}, or if {@code valueFunction} produces {@code null}
    *     for any key
    * @since 14.0
    */
-  @Beta
-  public static <K, V> ImmutableMap<K, V> toMap(Iterator<K> keys,
-      Function<? super K, V> valueFunction) {
+  public static <K, V> ImmutableMap<K, V> toMap(
+      Iterator<K> keys, Function<? super K, V> valueFunction) {
     checkNotNull(valueFunction);
     // Using LHM instead of a builder so as not to fail on duplicate keys
     Map<K, V> builder = newLinkedHashMap();
@@ -946,9 +968,22 @@ public final class Maps {
   }
 
   /**
-   * Returns an immutable map for which the {@link Map#values} are the given
-   * elements in the given order, and each key is the product of invoking a
-   * supplied function on its corresponding value.
+   * Returns a map with the given {@code values}, indexed by keys derived from
+   * those values. In other words, each input value produces an entry in the map
+   * whose key is the result of applying {@code keyFunction} to that value.
+   * These entries appear in the same order as the input values. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   ImmutableSet<Color> allColors = ImmutableSet.of(red, green, blue);
+   *
+   *   Map<String, Color> colorForName =
+   *       uniqueIndex(allColors, toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link
+   * Multimaps#index(Iterable, Function) Multimaps.index}.
    *
    * @param values the values to use when constructing the {@code Map}
    * @param keyFunction the function used to produce the key for each value
@@ -961,13 +996,27 @@ public final class Maps {
    */
   public static <K, V> ImmutableMap<K, V> uniqueIndex(
       Iterable<V> values, Function<? super V, K> keyFunction) {
+    // TODO(lowasser): consider presizing the builder if values is a Collection
     return uniqueIndex(values.iterator(), keyFunction);
   }
 
   /**
-   * Returns an immutable map for which the {@link Map#values} are the given
-   * elements in the given order, and each key is the product of invoking a
-   * supplied function on its corresponding value.
+   * Returns a map with the given {@code values}, indexed by keys derived from
+   * those values. In other words, each input value produces an entry in the map
+   * whose key is the result of applying {@code keyFunction} to that value.
+   * These entries appear in the same order as the input values. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   Iterator<Color> allColors = ImmutableSet.of(red, green, blue).iterator();
+   *
+   *   Map<String, Color> colorForName =
+   *       uniqueIndex(allColors, toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link
+   * Multimaps#index(Iterator, Function) Multimaps.index}.
    *
    * @param values the values to use when constructing the {@code Map}
    * @param keyFunction the function used to produce the key for each value
@@ -987,7 +1036,13 @@ public final class Maps {
       V value = values.next();
       builder.put(keyFunction.apply(value), value);
     }
-    return builder.build();
+    try {
+      return builder.build();
+    } catch (IllegalArgumentException duplicateKeys) {
+      throw new IllegalArgumentException(
+          duplicateKeys.getMessage()
+              + ". To index multiple values under a key, use Multimaps.index.");
+    }
   }
 
   /**
@@ -1000,8 +1055,7 @@ public final class Maps {
    * @param value the value to be associated with the returned entry
    */
   @GwtCompatible(serializable = true)
-  public static <K, V> Entry<K, V> immutableEntry(
-      @Nullable K key, @Nullable V value) {
+  public static <K, V> Entry<K, V> immutableEntry(@Nullable K key, @Nullable V value) {
     return new ImmutableEntry<K, V>(key, value);
   }
 
@@ -1013,10 +1067,8 @@ public final class Maps {
    * @param entrySet the entries for which to return an unmodifiable view
    * @return an unmodifiable view of the entries
    */
-  static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(
-      Set<Entry<K, V>> entrySet) {
-    return new UnmodifiableEntrySet<K, V>(
-        Collections.unmodifiableSet(entrySet));
+  static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(Set<Entry<K, V>> entrySet) {
+    return new UnmodifiableEntrySet<K, V>(Collections.unmodifiableSet(entrySet));
   }
 
   /**
@@ -1031,68 +1083,80 @@ public final class Maps {
   static <K, V> Entry<K, V> unmodifiableEntry(final Entry<? extends K, ? extends V> entry) {
     checkNotNull(entry);
     return new AbstractMapEntry<K, V>() {
-      @Override public K getKey() {
+      @Override
+      public K getKey() {
         return entry.getKey();
       }
 
-      @Override public V getValue() {
+      @Override
+      public V getValue() {
         return entry.getValue();
       }
     };
   }
 
+  static <K, V> UnmodifiableIterator<Entry<K, V>> unmodifiableEntryIterator(
+      final Iterator<Entry<K, V>> entryIterator) {
+    return new UnmodifiableIterator<Entry<K, V>>() {
+      @Override
+      public boolean hasNext() {
+        return entryIterator.hasNext();
+      }
+
+      @Override
+      public Entry<K, V> next() {
+        return unmodifiableEntry(entryIterator.next());
+      }
+    };
+  }
+
   /** @see Multimaps#unmodifiableEntries */
-  static class UnmodifiableEntries<K, V>
-      extends ForwardingCollection<Entry<K, V>> {
+  static class UnmodifiableEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
     private final Collection<Entry<K, V>> entries;
 
     UnmodifiableEntries(Collection<Entry<K, V>> entries) {
       this.entries = entries;
     }
 
-    @Override protected Collection<Entry<K, V>> delegate() {
+    @Override
+    protected Collection<Entry<K, V>> delegate() {
       return entries;
     }
 
-    @Override public Iterator<Entry<K, V>> iterator() {
-      final Iterator<Entry<K, V>> delegate = super.iterator();
-      return new UnmodifiableIterator<Entry<K, V>>() {
-        @Override
-        public boolean hasNext() {
-          return delegate.hasNext();
-        }
-
-        @Override public Entry<K, V> next() {
-          return unmodifiableEntry(delegate.next());
-        }
-      };
+    @Override
+    public Iterator<Entry<K, V>> iterator() {
+      return unmodifiableEntryIterator(entries.iterator());
     }
 
     // See java.util.Collections.UnmodifiableEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
   }
 
   /** @see Maps#unmodifiableEntrySet(Set) */
-  static class UnmodifiableEntrySet<K, V>
-      extends UnmodifiableEntries<K, V> implements Set<Entry<K, V>> {
+  static class UnmodifiableEntrySet<K, V> extends UnmodifiableEntries<K, V>
+      implements Set<Entry<K, V>> {
     UnmodifiableEntrySet(Set<Entry<K, V>> entries) {
       super(entries);
     }
 
     // See java.util.Collections.UnmodifiableEntrySet for details on attacks.
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return Sets.equalsImpl(this, object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Sets.hashCodeImpl(this);
     }
   }
@@ -1204,27 +1268,26 @@ public final class Maps {
    * @param bimap the bimap for which an unmodifiable view is to be returned
    * @return an unmodifiable view of the specified bimap
    */
-  public static <K, V> BiMap<K, V> unmodifiableBiMap(
-      BiMap<? extends K, ? extends V> bimap) {
+  public static <K, V> BiMap<K, V> unmodifiableBiMap(BiMap<? extends K, ? extends V> bimap) {
     return new UnmodifiableBiMap<K, V>(bimap, null);
   }
 
   /** @see Maps#unmodifiableBiMap(BiMap) */
-  private static class UnmodifiableBiMap<K, V>
-      extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
+  private static class UnmodifiableBiMap<K, V> extends ForwardingMap<K, V>
+      implements BiMap<K, V>, Serializable {
     final Map<K, V> unmodifiableMap;
     final BiMap<? extends K, ? extends V> delegate;
     BiMap<V, K> inverse;
     transient Set<V> values;
 
-    UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate,
-        @Nullable BiMap<V, K> inverse) {
+    UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @Nullable BiMap<V, K> inverse) {
       unmodifiableMap = Collections.unmodifiableMap(delegate);
       this.delegate = delegate;
       this.inverse = inverse;
     }
 
-    @Override protected Map<K, V> delegate() {
+    @Override
+    protected Map<K, V> delegate() {
       return unmodifiableMap;
     }
 
@@ -1241,7 +1304,8 @@ public final class Maps {
           : result;
     }
 
-    @Override public Set<V> values() {
+    @Override
+    public Set<V> values() {
       Set<V> result = values;
       return (result == null)
           ? values = Collections.unmodifiableSet(delegate.values())
@@ -1388,8 +1452,7 @@ public final class Maps {
    * @since 7.0
    */
   public static <K, V1, V2> Map<K, V2> transformEntries(
-      Map<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     if (fromMap instanceof SortedMap) {
       return transformEntries((SortedMap<K, V1>) fromMap, transformer);
     }
@@ -1449,14 +1512,12 @@ public final class Maps {
    * @since 11.0
    */
   public static <K, V1, V2> SortedMap<K, V2> transformEntries(
-      SortedMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return Platform.mapsTransformEntriesSortedMap(fromMap, transformer);
   }
 
   static <K, V1, V2> SortedMap<K, V2> transformEntriesIgnoreNavigable(
-      SortedMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesSortedMap<K, V1, V2>(fromMap, transformer);
   }
 
@@ -1494,8 +1555,8 @@ public final class Maps {
   /**
    * Views a function as an entry transformer that ignores the entry key.
    */
-  static <K, V1, V2> EntryTransformer<K, V1, V2>
-      asEntryTransformer(final Function<? super V1, V2> function) {
+  static <K, V1, V2> EntryTransformer<K, V1, V2> asEntryTransformer(
+      final Function<? super V1, V2> function) {
     checkNotNull(function);
     return new EntryTransformer<K, V1, V2>() {
       @Override
@@ -1564,29 +1625,30 @@ public final class Maps {
     };
   }
 
-  static class TransformedEntriesMap<K, V1, V2>
-      extends ImprovedAbstractMap<K, V2> {
+  static class TransformedEntriesMap<K, V1, V2> extends IteratorBasedAbstractMap<K, V2> {
     final Map<K, V1> fromMap;
     final EntryTransformer<? super K, ? super V1, V2> transformer;
 
     TransformedEntriesMap(
-        Map<K, V1> fromMap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+        Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       this.fromMap = checkNotNull(fromMap);
       this.transformer = checkNotNull(transformer);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromMap.size();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return fromMap.containsKey(key);
     }
 
     // safe as long as the user followed the <b>Warning</b> in the javadoc
     @SuppressWarnings("unchecked")
-    @Override public V2 get(Object key) {
+    @Override
+    public V2 get(Object key) {
       V1 value = fromMap.get(key);
       return (value != null || fromMap.containsKey(key))
           ? transformer.transformEntry((K) key, value)
@@ -1595,69 +1657,74 @@ public final class Maps {
 
     // safe as long as the user followed the <b>Warning</b> in the javadoc
     @SuppressWarnings("unchecked")
-    @Override public V2 remove(Object key) {
+    @Override
+    public V2 remove(Object key) {
       return fromMap.containsKey(key)
           ? transformer.transformEntry((K) key, fromMap.remove(key))
           : null;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromMap.clear();
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return fromMap.keySet();
     }
 
     @Override
-    protected Set<Entry<K, V2>> createEntrySet() {
-      return new EntrySet<K, V2>() {
-        @Override Map<K, V2> map() {
-          return TransformedEntriesMap.this;
-        }
+    Iterator<Entry<K, V2>> entryIterator() {
+      return Iterators.transform(
+          fromMap.entrySet().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+    }
 
-        @Override public Iterator<Entry<K, V2>> iterator() {
-          return Iterators.transform(fromMap.entrySet().iterator(),
-              Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
-        }
-      };
+    @Override
+    public Collection<V2> values() {
+      return new Values<K, V2>(this);
     }
   }
 
-  static class TransformedEntriesSortedMap<K, V1, V2>
-      extends TransformedEntriesMap<K, V1, V2> implements SortedMap<K, V2> {
+  static class TransformedEntriesSortedMap<K, V1, V2> extends TransformedEntriesMap<K, V1, V2>
+      implements SortedMap<K, V2> {
 
     protected SortedMap<K, V1> fromMap() {
       return (SortedMap<K, V1>) fromMap;
     }
 
-    TransformedEntriesSortedMap(SortedMap<K, V1> fromMap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+    TransformedEntriesSortedMap(
+        SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       super(fromMap, transformer);
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       return fromMap().comparator();
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       return fromMap().firstKey();
     }
 
-    @Override public SortedMap<K, V2> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V2> headMap(K toKey) {
       return transformEntries(fromMap().headMap(toKey), transformer);
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       return fromMap().lastKey();
     }
 
-    @Override public SortedMap<K, V2> subMap(K fromKey, K toKey) {
-      return transformEntries(
-          fromMap().subMap(fromKey, toKey), transformer);
+    @Override
+    public SortedMap<K, V2> subMap(K fromKey, K toKey) {
+      return transformEntries(fromMap().subMap(fromKey, toKey), transformer);
     }
 
-    @Override public SortedMap<K, V2> tailMap(K fromKey) {
+    @Override
+    public SortedMap<K, V2> tailMap(K fromKey) {
       return transformEntries(fromMap().tailMap(fromKey), transformer);
     }
   }
@@ -1698,6 +1765,7 @@ public final class Maps {
    * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
    * inconsistent with equals.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterKeys(
       Map<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -1709,8 +1777,7 @@ public final class Maps {
     Predicate<Entry<K, ?>> entryPredicate = keyPredicateOnEntries(keyPredicate);
     return (unfiltered instanceof AbstractFilteredMap)
         ? filterFiltered((AbstractFilteredMap<K, V>) unfiltered, entryPredicate)
-        : new FilteredKeyMap<K, V>(
-            checkNotNull(unfiltered), keyPredicate, entryPredicate);
+        : new FilteredKeyMap<K, V>(checkNotNull(unfiltered), keyPredicate, entryPredicate);
   }
 
   /**
@@ -1743,9 +1810,10 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterKeys(
       SortedMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
-    // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+    // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
     // performance.
     return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
   }
@@ -1775,6 +1843,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterKeys(
       BiMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     checkNotNull(keyPredicate);
@@ -1810,6 +1879,7 @@ public final class Maps {
    * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
    * inconsistent with equals.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterValues(
       Map<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -1851,6 +1921,7 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterValues(
       SortedMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1884,6 +1955,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterValues(
       BiMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1918,6 +1990,7 @@ public final class Maps {
    * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
    * equals</i>, as documented at {@link Predicate#apply}.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterEntries(
       Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -1962,15 +2035,14 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterEntries(
-      SortedMap<K, V> unfiltered,
-      Predicate<? super Entry<K, V>> entryPredicate) {
+      SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     return Platform.mapsFilterSortedMap(unfiltered, entryPredicate);
   }
 
   static <K, V> SortedMap<K, V> filterSortedIgnoreNavigable(
-      SortedMap<K, V> unfiltered,
-      Predicate<? super Entry<K, V>> entryPredicate) {
+      SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
     return (unfiltered instanceof FilteredEntrySortedMap)
         ? filterFiltered((FilteredEntrySortedMap<K, V>) unfiltered, entryPredicate)
@@ -2004,6 +2076,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterEntries(
       BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(unfiltered);
@@ -2017,19 +2090,17 @@ public final class Maps {
    * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
    * filtering a filtered map.
    */
-  private static <K, V> Map<K, V> filterFiltered(AbstractFilteredMap<K, V> map,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    return new FilteredEntryMap<K, V>(map.unfiltered,
-        Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
+  private static <K, V> Map<K, V> filterFiltered(
+      AbstractFilteredMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+    return new FilteredEntryMap<K, V>(
+        map.unfiltered, Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
   }
 
-  private abstract static class AbstractFilteredMap<K, V>
-      extends ImprovedAbstractMap<K, V> {
+  private abstract static class AbstractFilteredMap<K, V> extends ViewCachingAbstractMap<K, V> {
     final Map<K, V> unfiltered;
     final Predicate<? super Entry<K, V>> predicate;
 
-    AbstractFilteredMap(
-        Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
+    AbstractFilteredMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
       this.unfiltered = unfiltered;
       this.predicate = predicate;
     }
@@ -2042,32 +2113,38 @@ public final class Maps {
       return predicate.apply(Maps.immutableEntry(k, value));
     }
 
-    @Override public V put(K key, V value) {
+    @Override
+    public V put(K key, V value) {
       checkArgument(apply(key, value));
       return unfiltered.put(key, value);
     }
 
-    @Override public void putAll(Map<? extends K, ? extends V> map) {
+    @Override
+    public void putAll(Map<? extends K, ? extends V> map) {
       for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
         checkArgument(apply(entry.getKey(), entry.getValue()));
       }
       unfiltered.putAll(map);
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return unfiltered.containsKey(key) && apply(key, unfiltered.get(key));
     }
 
-    @Override public V get(Object key) {
+    @Override
+    public V get(Object key) {
       V value = unfiltered.get(key);
       return ((value != null) && apply(key, value)) ? value : null;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return entrySet().isEmpty();
     }
 
-    @Override public V remove(Object key) {
+    @Override
+    public V remove(Object key) {
       return containsKey(key) ? unfiltered.remove(key) : null;
     }
 
@@ -2081,38 +2158,45 @@ public final class Maps {
     Map<K, V> unfiltered;
     Predicate<? super Entry<K, V>> predicate;
 
-    FilteredMapValues(Map<K, V> filteredMap, Map<K, V> unfiltered,
-        Predicate<? super Entry<K, V>> predicate) {
+    FilteredMapValues(
+        Map<K, V> filteredMap, Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
       super(filteredMap);
       this.unfiltered = unfiltered;
       this.predicate = predicate;
     }
 
-    @Override public boolean remove(Object o) {
-      return Iterables.removeFirstMatching(unfiltered.entrySet(),
-          Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
+    @Override
+    public boolean remove(Object o) {
+      return Iterables.removeFirstMatching(
+              unfiltered.entrySet(),
+              Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
           != null;
     }
 
     private boolean removeIf(Predicate<? super V> valuePredicate) {
-      return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
-          predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
+      return Iterables.removeIf(
+          unfiltered.entrySet(),
+          Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
     }
 
-    @Override public boolean removeAll(Collection<?> collection) {
+    @Override
+    public boolean removeAll(Collection<?> collection) {
       return removeIf(in(collection));
     }
 
-    @Override public boolean retainAll(Collection<?> collection) {
+    @Override
+    public boolean retainAll(Collection<?> collection) {
       return removeIf(not(in(collection)));
     }
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       // creating an ArrayList so filtering happens once
       return Lists.newArrayList(iterator()).toArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return Lists.newArrayList(iterator()).toArray(array);
     }
   }
@@ -2120,7 +2204,9 @@ public final class Maps {
   private static class FilteredKeyMap<K, V> extends AbstractFilteredMap<K, V> {
     Predicate<? super K> keyPredicate;
 
-    FilteredKeyMap(Map<K, V> unfiltered, Predicate<? super K> keyPredicate,
+    FilteredKeyMap(
+        Map<K, V> unfiltered,
+        Predicate<? super K> keyPredicate,
         Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
       this.keyPredicate = keyPredicate;
@@ -2152,8 +2238,7 @@ public final class Maps {
      */
     final Set<Entry<K, V>> filteredEntrySet;
 
-    FilteredEntryMap(
-        Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
+    FilteredEntryMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
       filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate);
     }
@@ -2163,12 +2248,15 @@ public final class Maps {
       return new EntrySet();
     }
 
+    @WeakOuter
     private class EntrySet extends ForwardingSet<Entry<K, V>> {
-      @Override protected Set<Entry<K, V>> delegate() {
+      @Override
+      protected Set<Entry<K, V>> delegate() {
         return filteredEntrySet;
       }
 
-      @Override public Iterator<Entry<K, V>> iterator() {
+      @Override
+      public Iterator<Entry<K, V>> iterator() {
         return new TransformedIterator<Entry<K, V>, Entry<K, V>>(filteredEntrySet.iterator()) {
           @Override
           Entry<K, V> transform(final Entry<K, V> entry) {
@@ -2194,12 +2282,14 @@ public final class Maps {
       return new KeySet();
     }
 
+    @WeakOuter
     class KeySet extends Maps.KeySet<K, V> {
       KeySet() {
         super(FilteredEntryMap.this);
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (containsKey(o)) {
           unfiltered.remove(o);
           return true;
@@ -2208,8 +2298,9 @@ public final class Maps {
       }
 
       private boolean removeIf(Predicate<? super K> keyPredicate) {
-        return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
-            predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
+        return Iterables.removeIf(
+            unfiltered.entrySet(),
+            Predicates.<Entry<K, V>>and(predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
       }
 
       @Override
@@ -2222,12 +2313,14 @@ public final class Maps {
         return removeIf(not(in(c)));
       }
 
-      @Override public Object[] toArray() {
+      @Override
+      public Object[] toArray() {
         // creating an ArrayList so filtering happens once
         return Lists.newArrayList(iterator()).toArray();
       }
 
-      @Override public <T> T[] toArray(T[] array) {
+      @Override
+      public <T> T[] toArray(T[] array) {
         return Lists.newArrayList(iterator()).toArray(array);
       }
     }
@@ -2238,18 +2331,16 @@ public final class Maps {
    * filtering a filtered sorted map.
    */
   private static <K, V> SortedMap<K, V> filterFiltered(
-      FilteredEntrySortedMap<K, V> map,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(map.predicate, entryPredicate);
+      FilteredEntrySortedMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(map.predicate, entryPredicate);
     return new FilteredEntrySortedMap<K, V>(map.sortedMap(), predicate);
   }
 
-  private static class FilteredEntrySortedMap<K, V>
-      extends FilteredEntryMap<K, V> implements SortedMap<K, V> {
+  private static class FilteredEntrySortedMap<K, V> extends FilteredEntryMap<K, V>
+      implements SortedMap<K, V> {
 
-    FilteredEntrySortedMap(SortedMap<K, V> unfiltered,
-        Predicate<? super Entry<K, V>> entryPredicate) {
+    FilteredEntrySortedMap(
+        SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
     }
 
@@ -2257,7 +2348,8 @@ public final class Maps {
       return (SortedMap<K, V>) unfiltered;
     }
 
-    @Override public SortedSet<K> keySet() {
+    @Override
+    public SortedSet<K> keySet() {
       return (SortedSet<K>) super.keySet();
     }
 
@@ -2266,6 +2358,7 @@ public final class Maps {
       return new SortedKeySet();
     }
 
+    @WeakOuter
     class SortedKeySet extends KeySet implements SortedSet<K> {
       @Override
       public Comparator<? super K> comparator() {
@@ -2298,16 +2391,19 @@ public final class Maps {
       }
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       return sortedMap().comparator();
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       // correctly throws NoSuchElementException when filtered map is empty.
       return keySet().iterator().next();
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       SortedMap<K, V> headMap = sortedMap();
       while (true) {
         // correctly throws NoSuchElementException when filtered map is empty.
@@ -2319,18 +2415,19 @@ public final class Maps {
       }
     }
 
-    @Override public SortedMap<K, V> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V> headMap(K toKey) {
       return new FilteredEntrySortedMap<K, V>(sortedMap().headMap(toKey), predicate);
     }
 
-    @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
-      return new FilteredEntrySortedMap<K, V>(
-          sortedMap().subMap(fromKey, toKey), predicate);
+    @Override
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
+      return new FilteredEntrySortedMap<K, V>(sortedMap().subMap(fromKey, toKey), predicate);
     }
 
-    @Override public SortedMap<K, V> tailMap(K fromKey) {
-      return new FilteredEntrySortedMap<K, V>(
-          sortedMap().tailMap(fromKey), predicate);
+    @Override
+    public SortedMap<K, V> tailMap(K fromKey) {
+      return new FilteredEntrySortedMap<K, V>(sortedMap().tailMap(fromKey), predicate);
     }
   }
 
@@ -2353,22 +2450,19 @@ public final class Maps {
       return new Predicate<Entry<V, K>>() {
         @Override
         public boolean apply(Entry<V, K> input) {
-          return forwardPredicate.apply(
-              Maps.immutableEntry(input.getValue(), input.getKey()));
+          return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey()));
         }
       };
     }
 
-    FilteredEntryBiMap(BiMap<K, V> delegate,
-        Predicate<? super Entry<K, V>> predicate) {
+    FilteredEntryBiMap(BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate) {
       super(delegate, predicate);
-      this.inverse = new FilteredEntryBiMap<V, K>(
-          delegate.inverse(), inversePredicate(predicate), this);
+      this.inverse =
+          new FilteredEntryBiMap<V, K>(delegate.inverse(), inversePredicate(predicate), this);
     }
 
     private FilteredEntryBiMap(
-        BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate,
-        BiMap<V, K> inverse) {
+        BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate, BiMap<V, K> inverse) {
       super(delegate, predicate);
       this.inverse = inverse;
     }
@@ -2394,19 +2488,17 @@ public final class Maps {
     }
   }
 
-  @Nullable private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
+  @Nullable
+  private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
     return (entry == null) ? null : Maps.unmodifiableEntry(entry);
   }
 
   /**
-   * {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code
-   * entrySet().isEmpty()} instead of {@code size() == 0} to speed up
-   * implementations where {@code size()} is O(n), and it delegates the {@code
-   * isEmpty()} methods of its key set and value collection to this
-   * implementation.
+   * {@code AbstractMap} extension that makes it easy to cache customized keySet, values,
+   * and entrySet views.
    */
   @GwtCompatible
-  abstract static class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
+  abstract static class ViewCachingAbstractMap<K, V> extends AbstractMap<K, V> {
     /**
      * Creates the entry set to be returned by {@link #entrySet()}. This method
      * is invoked at most once on a given map, at the time when {@code entrySet}
@@ -2416,14 +2508,16 @@ public final class Maps {
 
     private transient Set<Entry<K, V>> entrySet;
 
-    @Override public Set<Entry<K, V>> entrySet() {
+    @Override
+    public Set<Entry<K, V>> entrySet() {
       Set<Entry<K, V>> result = entrySet;
       return (result == null) ? entrySet = createEntrySet() : result;
     }
 
     private transient Set<K> keySet;
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       Set<K> result = keySet;
       return (result == null) ? keySet = createKeySet() : result;
     }
@@ -2434,7 +2528,8 @@ public final class Maps {
 
     private transient Collection<V> values;
 
-    @Override public Collection<V> values() {
+    @Override
+    public Collection<V> values() {
       Collection<V> result = values;
       return (result == null) ? values = createValues() : result;
     }
@@ -2444,6 +2539,33 @@ public final class Maps {
     }
   }
 
+  abstract static class IteratorBasedAbstractMap<K, V> extends AbstractMap<K, V> {
+    @Override
+    public abstract int size();
+
+    abstract Iterator<Entry<K, V>> entryIterator();
+
+    @Override
+    public Set<Entry<K, V>> entrySet() {
+      return new EntrySet<K, V>() {
+        @Override
+        Map<K, V> map() {
+          return IteratorBasedAbstractMap.this;
+        }
+
+        @Override
+        public Iterator<Entry<K, V>> iterator() {
+          return entryIterator();
+        }
+      };
+    }
+
+    @Override
+    public void clear() {
+      Iterators.clear(entryIterator());
+    }
+  }
+
   /**
    * Delegates to {@link Map#get}. Returns {@code null} on {@code
    * ClassCastException} and {@code NullPointerException}.
@@ -2556,15 +2678,13 @@ public final class Maps {
     return false;
   }
 
-  static final MapJoiner STANDARD_JOINER =
-      Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
+  static final MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
 
   /**
    * An implementation of {@link Map#toString}.
    */
   static String toStringImpl(Map<?, ?> map) {
-    StringBuilder sb
-        = Collections2.newStringBuilderForCollection(map.size()).append('{');
+    StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{');
     STANDARD_JOINER.appendTo(sb, map);
     return sb.append('}').toString();
   }
@@ -2572,15 +2692,14 @@ public final class Maps {
   /**
    * An implementation of {@link Map#putAll}.
    */
-  static <K, V> void putAllImpl(
-      Map<K, V> self, Map<? extends K, ? extends V> map) {
+  static <K, V> void putAllImpl(Map<K, V> self, Map<? extends K, ? extends V> map) {
     for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
       self.put(entry.getKey(), entry.getValue());
     }
   }
 
   static class KeySet<K, V> extends Sets.ImprovedAbstractSet<K> {
-    final Map<K, V> map;
+    @Weak final Map<K, V> map;
 
     KeySet(Map<K, V> map) {
       this.map = checkNotNull(map);
@@ -2590,23 +2709,28 @@ public final class Maps {
       return map;
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return keyIterator(map().entrySet().iterator());
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return map().containsKey(o);
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       if (contains(o)) {
         map().remove(o);
         return true;
@@ -2614,7 +2738,8 @@ public final class Maps {
       return false;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
   }
@@ -2671,7 +2796,7 @@ public final class Maps {
   }
 
   static class Values<K, V> extends AbstractCollection<V> {
-    final Map<K, V> map;
+    @Weak final Map<K, V> map;
 
     Values(Map<K, V> map) {
       this.map = checkNotNull(map);
@@ -2681,11 +2806,13 @@ public final class Maps {
       return map;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       return valueIterator(map().entrySet().iterator());
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       try {
         return super.remove(o);
       } catch (UnsupportedOperationException e) {
@@ -2699,7 +2826,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       try {
         return super.removeAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -2713,7 +2841,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       try {
         return super.retainAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -2727,51 +2856,58 @@ public final class Maps {
       }
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       return map().containsValue(o);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
   }
 
-  abstract static class EntrySet<K, V>
-      extends Sets.ImprovedAbstractSet<Entry<K, V>> {
+  abstract static class EntrySet<K, V> extends Sets.ImprovedAbstractSet<Entry<K, V>> {
     abstract Map<K, V> map();
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       if (o instanceof Entry) {
         Entry<?, ?> entry = (Entry<?, ?>) o;
         Object key = entry.getKey();
         V value = Maps.safeGet(map(), key);
-        return Objects.equal(value, entry.getValue())
-            && (value != null || map().containsKey(key));
+        return Objects.equal(value, entry.getValue()) && (value != null || map().containsKey(key));
       }
       return false;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       if (contains(o)) {
         Entry<?, ?> entry = (Entry<?, ?>) o;
         return map().keySet().remove(entry.getKey());
@@ -2779,7 +2915,8 @@ public final class Maps {
       return false;
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       try {
         return super.removeAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -2788,7 +2925,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       try {
         return super.retainAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -2804,4 +2942,17 @@ public final class Maps {
       }
     }
   }
+
+  /**
+   * Returns a map from the ith element of list to i.
+   */
+  static <E> ImmutableMap<E, Integer> indexMap(Collection<E> list) {
+    ImmutableMap.Builder<E, Integer> builder = new ImmutableMap.Builder<E, Integer>(list.size());
+    int i = 0;
+    for (E e : list) {
+      builder.put(e, i++);
+    }
+    return builder.build();
+  }
 }
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
index 271e59e..ad5a1c8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
@@ -27,6 +27,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.base.Supplier;
 import com.google.common.collect.Maps.EntryTransformer;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
@@ -42,20 +44,21 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.SortedSet;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
  * Provides static methods acting on or generating a {@code Multimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multimaps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multimaps">
  * {@code Multimaps}</a>.
  *
  * @author Jared Levy
  * @author Robert Konigsberg
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Multimaps {
@@ -104,21 +107,21 @@ public final class Multimaps {
    *     values for a given key
    * @throws IllegalArgumentException if {@code map} is not empty
    */
-  public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
-      final Supplier<? extends Collection<V>> factory) {
+  public static <K, V> Multimap<K, V> newMultimap(
+      Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory) {
     return new CustomMultimap<K, V>(map, factory);
   }
 
   private static class CustomMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
     transient Supplier<? extends Collection<V>> factory;
 
-    CustomMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends Collection<V>> factory) {
+    CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected Collection<V> createCollection() {
+    @Override
+    protected Collection<V> createCollection() {
       return factory.get();
     }
 
@@ -169,17 +172,16 @@ public final class Multimaps {
     return new CustomListMultimap<K, V>(map, factory);
   }
 
-  private static class CustomListMultimap<K, V>
-      extends AbstractListMultimap<K, V> {
+  private static class CustomListMultimap<K, V> extends AbstractListMultimap<K, V> {
     transient Supplier<? extends List<V>> factory;
 
-    CustomListMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends List<V>> factory) {
+    CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected List<V> createCollection() {
+    @Override
+    protected List<V> createCollection() {
       return factory.get();
     }
   }
@@ -226,17 +228,16 @@ public final class Multimaps {
     return new CustomSetMultimap<K, V>(map, factory);
   }
 
-  private static class CustomSetMultimap<K, V>
-      extends AbstractSetMultimap<K, V> {
+  private static class CustomSetMultimap<K, V> extends AbstractSetMultimap<K, V> {
     transient Supplier<? extends Set<V>> factory;
 
-    CustomSetMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends Set<V>> factory) {
+    CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected Set<V> createCollection() {
+    @Override
+    protected Set<V> createCollection() {
       return factory.get();
     }
   }
@@ -278,28 +279,27 @@ public final class Multimaps {
    * @throws IllegalArgumentException if {@code map} is not empty
    */
   public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
-      Map<K, Collection<V>> map,
-      final Supplier<? extends SortedSet<V>> factory) {
+      Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory) {
     return new CustomSortedSetMultimap<K, V>(map, factory);
   }
 
-  private static class CustomSortedSetMultimap<K, V>
-      extends AbstractSortedSetMultimap<K, V> {
+  private static class CustomSortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
     transient Supplier<? extends SortedSet<V>> factory;
     transient Comparator<? super V> valueComparator;
 
-    CustomSortedSetMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends SortedSet<V>> factory) {
+    CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
       valueComparator = factory.get().comparator();
     }
 
-    @Override protected SortedSet<V> createCollection() {
+    @Override
+    protected SortedSet<V> createCollection() {
       return factory.get();
     }
 
-    @Override public Comparator<? super V> valueComparator() {
+    @Override
+    public Comparator<? super V> valueComparator() {
       return valueComparator;
     }
   }
@@ -357,8 +357,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped in a synchronized view
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> Multimap<K, V> synchronizedMultimap(
-      Multimap<K, V> multimap) {
+  public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
     return Synchronized.multimap(multimap, null);
   }
 
@@ -379,10 +378,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> Multimap<K, V> unmodifiableMultimap(
-      Multimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableMultimap ||
-        delegate instanceof ImmutableMultimap) {
+  public static <K, V> Multimap<K, V> unmodifiableMultimap(Multimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) {
       return delegate;
     }
     return new UnmodifiableMultimap<K, V>(delegate);
@@ -394,13 +391,13 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
-      ImmutableMultimap<K, V> delegate) {
+  @Deprecated
+  public static <K, V> Multimap<K, V> unmodifiableMultimap(ImmutableMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
 
-  private static class UnmodifiableMultimap<K, V>
-      extends ForwardingMultimap<K, V> implements Serializable {
+  private static class UnmodifiableMultimap<K, V> extends ForwardingMultimap<K, V>
+      implements Serializable {
     final Multimap<K, V> delegate;
     transient Collection<Entry<K, V>> entries;
     transient Multiset<K> keys;
@@ -412,29 +409,36 @@ public final class Multimaps {
       this.delegate = checkNotNull(delegate);
     }
 
-    @Override protected Multimap<K, V> delegate() {
+    @Override
+    protected Multimap<K, V> delegate() {
       return delegate;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Map<K, Collection<V>> asMap() {
+    @Override
+    public Map<K, Collection<V>> asMap() {
       Map<K, Collection<V>> result = map;
       if (result == null) {
-        result = map = Collections.unmodifiableMap(
-            Maps.transformValues(delegate.asMap(), new Function<Collection<V>, Collection<V>>() {
-              @Override
-              public Collection<V> apply(Collection<V> collection) {
-                return unmodifiableValueCollection(collection);
-              }
-            }));
+        result = map =
+            Collections.unmodifiableMap(
+                Maps.transformValues(
+                    delegate.asMap(),
+                    new Function<Collection<V>, Collection<V>>() {
+                      @Override
+                      public Collection<V> apply(Collection<V> collection) {
+                        return unmodifiableValueCollection(collection);
+                      }
+                    }));
       }
       return result;
     }
 
-    @Override public Collection<Entry<K, V>> entries() {
+    @Override
+    public Collection<Entry<K, V>> entries() {
       Collection<Entry<K, V>> result = entries;
       if (result == null) {
         entries = result = unmodifiableEntries(delegate.entries());
@@ -442,11 +446,13 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public Collection<V> get(K key) {
+    @Override
+    public Collection<V> get(K key) {
       return unmodifiableValueCollection(delegate.get(key));
     }
 
-    @Override public Multiset<K> keys() {
+    @Override
+    public Multiset<K> keys() {
       Multiset<K> result = keys;
       if (result == null) {
         keys = result = Multisets.unmodifiableMultiset(delegate.keys());
@@ -454,7 +460,8 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       Set<K> result = keySet;
       if (result == null) {
         keySet = result = Collections.unmodifiableSet(delegate.keySet());
@@ -462,11 +469,13 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public boolean put(K key, V value) {
+    @Override
+    public boolean put(K key, V value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(K key, Iterable<? extends V> values) {
+    @Override
+    public boolean putAll(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
@@ -475,20 +484,23 @@ public final class Multimaps {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean remove(Object key, Object value) {
+    @Override
+    public boolean remove(Object key, Object value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> removeAll(Object key) {
+    @Override
+    public Collection<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+    @Override
+    public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> values() {
+    @Override
+    public Collection<V> values() {
       Collection<V> result = values;
       if (result == null) {
         values = result = Collections.unmodifiableCollection(delegate.values());
@@ -499,77 +511,104 @@ public final class Multimaps {
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableListMultimap<K, V>
-      extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
+  private static class UnmodifiableListMultimap<K, V> extends UnmodifiableMultimap<K, V>
+      implements ListMultimap<K, V> {
     UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public ListMultimap<K, V> delegate() {
+
+    @Override
+    public ListMultimap<K, V> delegate() {
       return (ListMultimap<K, V>) super.delegate();
     }
-    @Override public List<V> get(K key) {
+
+    @Override
+    public List<V> get(K key) {
       return Collections.unmodifiableList(delegate().get(key));
     }
-    @Override public List<V> removeAll(Object key) {
+
+    @Override
+    public List<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public List<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public List<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableSetMultimap<K, V>
-      extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
+  private static class UnmodifiableSetMultimap<K, V> extends UnmodifiableMultimap<K, V>
+      implements SetMultimap<K, V> {
     UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public SetMultimap<K, V> delegate() {
+
+    @Override
+    public SetMultimap<K, V> delegate() {
       return (SetMultimap<K, V>) super.delegate();
     }
-    @Override public Set<V> get(K key) {
+
+    @Override
+    public Set<V> get(K key) {
       /*
        * Note that this doesn't return a SortedSet when delegate is a
        * SortedSetMultiset, unlike (SortedSet<V>) super.get().
        */
       return Collections.unmodifiableSet(delegate().get(key));
     }
-    @Override public Set<Map.Entry<K, V>> entries() {
+
+    @Override
+    public Set<Map.Entry<K, V>> entries() {
       return Maps.unmodifiableEntrySet(delegate().entries());
     }
-    @Override public Set<V> removeAll(Object key) {
+
+    @Override
+    public Set<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public Set<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableSortedSetMultimap<K, V>
-      extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+  private static class UnmodifiableSortedSetMultimap<K, V> extends UnmodifiableSetMultimap<K, V>
+      implements SortedSetMultimap<K, V> {
     UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public SortedSetMultimap<K, V> delegate() {
+
+    @Override
+    public SortedSetMultimap<K, V> delegate() {
       return (SortedSetMultimap<K, V>) super.delegate();
     }
-    @Override public SortedSet<V> get(K key) {
+
+    @Override
+    public SortedSet<V> get(K key) {
       return Collections.unmodifiableSortedSet(delegate().get(key));
     }
-    @Override public SortedSet<V> removeAll(Object key) {
+
+    @Override
+    public SortedSet<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public SortedSet<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     @Override
     public Comparator<? super V> valueComparator() {
       return delegate().valueComparator();
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -585,8 +624,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
-      SetMultimap<K, V> multimap) {
+  public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(SetMultimap<K, V> multimap) {
     return Synchronized.setMultimap(multimap, null);
   }
 
@@ -608,10 +646,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
-      SetMultimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableSetMultimap ||
-        delegate instanceof ImmutableSetMultimap) {
+  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(SetMultimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) {
       return delegate;
     }
     return new UnmodifiableSetMultimap<K, V>(delegate);
@@ -623,7 +659,8 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
+  @Deprecated
+  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
       ImmutableSetMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
@@ -640,8 +677,8 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> SortedSetMultimap<K, V>
-      synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
+  public static <K, V> SortedSetMultimap<K, V> synchronizedSortedSetMultimap(
+      SortedSetMultimap<K, V> multimap) {
     return Synchronized.sortedSetMultimap(multimap, null);
   }
 
@@ -680,8 +717,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
-      ListMultimap<K, V> multimap) {
+  public static <K, V> ListMultimap<K, V> synchronizedListMultimap(ListMultimap<K, V> multimap) {
     return Synchronized.listMultimap(multimap, null);
   }
 
@@ -703,10 +739,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
-      ListMultimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableListMultimap ||
-        delegate instanceof ImmutableListMultimap) {
+  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(ListMultimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) {
       return delegate;
     }
     return new UnmodifiableListMultimap<K, V>(delegate);
@@ -718,7 +752,8 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
+  @Deprecated
+  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
       ImmutableListMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
@@ -731,8 +766,7 @@ public final class Multimaps {
    * @param collection the collection for which to return an unmodifiable view
    * @return an unmodifiable view of the collection
    */
-  private static <V> Collection<V> unmodifiableValueCollection(
-      Collection<V> collection) {
+  private static <V> Collection<V> unmodifiableValueCollection(Collection<V> collection) {
     if (collection instanceof SortedSet) {
       return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
     } else if (collection instanceof Set) {
@@ -757,8 +791,7 @@ public final class Multimaps {
     if (entries instanceof Set) {
       return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
     }
-    return new Maps.UnmodifiableEntries<K, V>(
-        Collections.unmodifiableCollection(entries));
+    return new Maps.UnmodifiableEntries<K, V>(Collections.unmodifiableCollection(entries));
   }
 
   /**
@@ -797,8 +830,7 @@ public final class Multimaps {
   @Beta
   @SuppressWarnings("unchecked")
   // safe by specification of SortedSetMultimap.asMap()
-  public static <K, V> Map<K, SortedSet<V>> asMap(
-      SortedSetMultimap<K, V> multimap) {
+  public static <K, V> Map<K, SortedSet<V>> asMap(SortedSetMultimap<K, V> multimap) {
     return (Map<K, SortedSet<V>>) (Map<K, ?>) multimap.asMap();
   }
 
@@ -835,8 +867,8 @@ public final class Multimaps {
   }
 
   /** @see Multimaps#forMap */
-  private static class MapMultimap<K, V>
-      extends AbstractMultimap<K, V> implements SetMultimap<K, V>, Serializable {
+  private static class MapMultimap<K, V> extends AbstractMultimap<K, V>
+      implements SetMultimap<K, V>, Serializable {
     final Map<K, V> map;
 
     MapMultimap(Map<K, V> map) {
@@ -866,7 +898,8 @@ public final class Multimaps {
     @Override
     public Set<V> get(final K key) {
       return new Sets.ImprovedAbstractSet<V>() {
-        @Override public Iterator<V> iterator() {
+        @Override
+        public Iterator<V> iterator() {
           return new Iterator<V>() {
             int i;
 
@@ -893,7 +926,8 @@ public final class Multimaps {
           };
         }
 
-        @Override public int size() {
+        @Override
+        public int size() {
           return map.containsKey(key) ? 1 : 0;
         }
       };
@@ -953,7 +987,7 @@ public final class Multimaps {
     public Set<Entry<K, V>> entries() {
       return map.entrySet();
     }
-    
+
     @Override
     Iterator<Entry<K, V>> entryIterator() {
       return map.entrySet().iterator();
@@ -964,10 +998,11 @@ public final class Multimaps {
       return new AsMap<K, V>(this);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return map.hashCode();
     }
-    
+
     private static final long serialVersionUID = 7845222491160860175L;
   }
 
@@ -1078,25 +1113,23 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> Multimap<K, V2> transformEntries(
-      Multimap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      Multimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
   }
 
-  private static class TransformedEntriesMultimap<K, V1, V2>
-      extends AbstractMultimap<K, V2> {
+  private static class TransformedEntriesMultimap<K, V1, V2> extends AbstractMultimap<K, V2> {
     final Multimap<K, V1> fromMultimap;
     final EntryTransformer<? super K, ? super V1, V2> transformer;
 
-    TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
+    TransformedEntriesMultimap(
+        Multimap<K, V1> fromMultimap,
         final EntryTransformer<? super K, ? super V1, V2> transformer) {
       this.fromMultimap = checkNotNull(fromMultimap);
       this.transformer = checkNotNull(transformer);
     }
 
     Collection<V2> transform(K key, Collection<V1> values) {
-      Function<? super V1, V2> function = 
-          Maps.asValueToValueFunction(transformer, key);
+      Function<? super V1, V2> function = Maps.asValueToValueFunction(transformer, key);
       if (values instanceof List) {
         return Lists.transform((List<V1>) values, function);
       } else {
@@ -1106,77 +1139,89 @@ public final class Multimaps {
 
     @Override
     Map<K, Collection<V2>> createAsMap() {
-      return Maps.transformEntries(fromMultimap.asMap(),
+      return Maps.transformEntries(
+          fromMultimap.asMap(),
           new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
-        @Override public Collection<V2> transformEntry(
-            K key, Collection<V1> value) {
-          return transform(key, value);
-        }
-      });
+            @Override
+            public Collection<V2> transformEntry(K key, Collection<V1> value) {
+              return transform(key, value);
+            }
+          });
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromMultimap.clear();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return fromMultimap.containsKey(key);
     }
 
     @Override
     Iterator<Entry<K, V2>> entryIterator() {
-      return Iterators.transform(fromMultimap.entries().iterator(), 
-          Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+      return Iterators.transform(
+          fromMultimap.entries().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
     }
 
-    @Override public Collection<V2> get(final K key) {
+    @Override
+    public Collection<V2> get(final K key) {
       return transform(key, fromMultimap.get(key));
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return fromMultimap.isEmpty();
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return fromMultimap.keySet();
     }
 
-    @Override public Multiset<K> keys() {
+    @Override
+    public Multiset<K> keys() {
       return fromMultimap.keys();
     }
 
-    @Override public boolean put(K key, V2 value) {
+    @Override
+    public boolean put(K key, V2 value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(K key, Iterable<? extends V2> values) {
+    @Override
+    public boolean putAll(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(
-        Multimap<? extends K, ? extends V2> multimap) {
+    @Override
+    public boolean putAll(Multimap<? extends K, ? extends V2> multimap) {
       throw new UnsupportedOperationException();
     }
 
     @SuppressWarnings("unchecked")
-    @Override public boolean remove(Object key, Object value) {
+    @Override
+    public boolean remove(Object key, Object value) {
       return get((K) key).remove(value);
     }
 
     @SuppressWarnings("unchecked")
-    @Override public Collection<V2> removeAll(Object key) {
+    @Override
+    public Collection<V2> removeAll(Object key) {
       return transform((K) key, fromMultimap.removeAll(key));
     }
 
-    @Override public Collection<V2> replaceValues(
-        K key, Iterable<? extends V2> values) {
+    @Override
+    public Collection<V2> replaceValues(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromMultimap.size();
     }
-    
+
     @Override
     Collection<V2> createValues() {
       return Collections2.transform(
@@ -1226,8 +1271,7 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> ListMultimap<K, V2> transformValues(
-      ListMultimap<K, V1> fromMultimap,
-      final Function<? super V1, V2> function) {
+      ListMultimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
     checkNotNull(function);
     EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function);
     return transformEntries(fromMultimap, transformer);
@@ -1286,35 +1330,36 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
-      ListMultimap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      ListMultimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
   }
 
   private static final class TransformedEntriesListMultimap<K, V1, V2>
-      extends TransformedEntriesMultimap<K, V1, V2>
-      implements ListMultimap<K, V2> {
+      extends TransformedEntriesMultimap<K, V1, V2> implements ListMultimap<K, V2> {
 
-    TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+    TransformedEntriesListMultimap(
+        ListMultimap<K, V1> fromMultimap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       super(fromMultimap, transformer);
     }
 
-    @Override List<V2> transform(K key, Collection<V1> values) {
+    @Override
+    List<V2> transform(K key, Collection<V1> values) {
       return Lists.transform((List<V1>) values, Maps.asValueToValueFunction(transformer, key));
     }
 
-    @Override public List<V2> get(K key) {
+    @Override
+    public List<V2> get(K key) {
       return transform(key, fromMultimap.get(key));
     }
 
     @SuppressWarnings("unchecked")
-    @Override public List<V2> removeAll(Object key) {
+    @Override
+    public List<V2> removeAll(Object key) {
       return transform((K) key, fromMultimap.removeAll(key));
     }
 
-    @Override public List<V2> replaceValues(
-        K key, Iterable<? extends V2> values) {
+    @Override
+    public List<V2> replaceValues(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
   }
@@ -1412,8 +1457,7 @@ public final class Multimaps {
   public static <K, V> ImmutableListMultimap<K, V> index(
       Iterator<V> values, Function<? super V, K> keyFunction) {
     checkNotNull(keyFunction);
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     while (values.hasNext()) {
       V value = values.next();
       checkNotNull(value, values);
@@ -1423,18 +1467,18 @@ public final class Multimaps {
   }
 
   static class Keys<K, V> extends AbstractMultiset<K> {
-    final Multimap<K, V> multimap;
-    
+    @Weak final Multimap<K, V> multimap;
+
     Keys(Multimap<K, V> multimap) {
       this.multimap = multimap;
     }
 
-    @Override Iterator<Multiset.Entry<K>> entryIterator() {
+    @Override
+    Iterator<Multiset.Entry<K>> entryIterator() {
       return new TransformedIterator<Map.Entry<K, Collection<V>>, Multiset.Entry<K>>(
           multimap.asMap().entrySet().iterator()) {
         @Override
-        Multiset.Entry<K> transform(
-            final Map.Entry<K, Collection<V>> backingEntry) {
+        Multiset.Entry<K> transform(final Map.Entry<K, Collection<V>> backingEntry) {
           return new Multisets.AbstractEntry<K>() {
             @Override
             public K getElement() {
@@ -1450,32 +1494,40 @@ public final class Multimaps {
       };
     }
 
-    @Override int distinctElements() {
+    @Override
+    int distinctElements() {
       return multimap.asMap().size();
     }
 
-    @Override Set<Multiset.Entry<K>> createEntrySet() {
+    @Override
+    Set<Multiset.Entry<K>> createEntrySet() {
       return new KeysEntrySet();
     }
 
+    @WeakOuter
     class KeysEntrySet extends Multisets.EntrySet<K> {
-      @Override Multiset<K> multiset() {
+      @Override
+      Multiset<K> multiset() {
         return Keys.this;
       }
 
-      @Override public Iterator<Multiset.Entry<K>> iterator() {
+      @Override
+      public Iterator<Multiset.Entry<K>> iterator() {
         return entryIterator();
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         return distinctElements();
       }
 
-      @Override public boolean isEmpty() {
+      @Override
+      public boolean isEmpty() {
         return multimap.isEmpty();
       }
 
-      @Override public boolean contains(@Nullable Object o) {
+      @Override
+      public boolean contains(@Nullable Object o) {
         if (o instanceof Multiset.Entry) {
           Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
           Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1484,7 +1536,8 @@ public final class Multimaps {
         return false;
       }
 
-      @Override public boolean remove(@Nullable Object o) {
+      @Override
+      public boolean remove(@Nullable Object o) {
         if (o instanceof Multiset.Entry) {
           Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
           Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1497,20 +1550,24 @@ public final class Multimaps {
       }
     }
 
-    @Override public boolean contains(@Nullable Object element) {
+    @Override
+    public boolean contains(@Nullable Object element) {
       return multimap.containsKey(element);
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return Maps.keyIterator(multimap.entries().iterator());
     }
 
-    @Override public int count(@Nullable Object element) {
+    @Override
+    public int count(@Nullable Object element) {
       Collection<V> values = Maps.safeGet(multimap.asMap(), element);
       return (values == null) ? 0 : values.size();
     }
 
-    @Override public int remove(@Nullable Object element, int occurrences) {
+    @Override
+    public int remove(@Nullable Object element, int occurrences) {
       checkNonnegative(occurrences, "occurrences");
       if (occurrences == 0) {
         return count(element);
@@ -1535,11 +1592,13 @@ public final class Multimaps {
       return oldCount;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap.clear();
     }
 
-    @Override public Set<K> elementSet() {
+    @Override
+    public Set<K> elementSet() {
       return multimap.keySet();
     }
   }
@@ -1547,15 +1606,16 @@ public final class Multimaps {
   /**
    * A skeleton implementation of {@link Multimap#entries()}.
    */
-  abstract static class Entries<K, V> extends
-      AbstractCollection<Map.Entry<K, V>> {
+  abstract static class Entries<K, V> extends AbstractCollection<Map.Entry<K, V>> {
     abstract Multimap<K, V> multimap();
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return multimap().size();
     }
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       if (o instanceof Map.Entry) {
         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
         return multimap().containsEntry(entry.getKey(), entry.getValue());
@@ -1563,7 +1623,8 @@ public final class Multimaps {
       return false;
     }
 
-    @Override public boolean remove(@Nullable Object o) {
+    @Override
+    public boolean remove(@Nullable Object o) {
       if (o instanceof Map.Entry) {
         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
         return multimap().remove(entry.getKey(), entry.getValue());
@@ -1571,7 +1632,8 @@ public final class Multimaps {
       return false;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap().clear();
     }
   }
@@ -1579,19 +1641,20 @@ public final class Multimaps {
   /**
    * A skeleton implementation of {@link Multimap#asMap()}.
    */
-  static final class AsMap<K, V> extends
-      Maps.ImprovedAbstractMap<K, Collection<V>> {
-    private final Multimap<K, V> multimap;
-    
+  static final class AsMap<K, V> extends Maps.ViewCachingAbstractMap<K, Collection<V>> {
+    @Weak private final Multimap<K, V> multimap;
+
     AsMap(Multimap<K, V> multimap) {
       this.multimap = checkNotNull(multimap);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return multimap.keySet().size();
     }
 
-    @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
+    @Override
+    protected Set<Entry<K, Collection<V>>> createEntrySet() {
       return new EntrySet();
     }
 
@@ -1599,21 +1662,27 @@ public final class Multimaps {
       multimap.keySet().remove(key);
     }
 
+    @WeakOuter
     class EntrySet extends Maps.EntrySet<K, Collection<V>> {
-      @Override Map<K, Collection<V>> map() {
+      @Override
+      Map<K, Collection<V>> map() {
         return AsMap.this;
       }
 
-      @Override public Iterator<Entry<K, Collection<V>>> iterator() {
-        return Maps.asMapEntryIterator(multimap.keySet(), new Function<K, Collection<V>>() {
-          @Override
-          public Collection<V> apply(K key) {
-            return multimap.get(key);
-          }
-        });
+      @Override
+      public Iterator<Entry<K, Collection<V>>> iterator() {
+        return Maps.asMapEntryIterator(
+            multimap.keySet(),
+            new Function<K, Collection<V>>() {
+              @Override
+              public Collection<V> apply(K key) {
+                return multimap.get(key);
+              }
+            });
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (!contains(o)) {
           return false;
         }
@@ -1624,27 +1693,33 @@ public final class Multimaps {
     }
 
     @SuppressWarnings("unchecked")
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       return containsKey(key) ? multimap.get((K) key) : null;
     }
 
-    @Override public Collection<V> remove(Object key) {
+    @Override
+    public Collection<V> remove(Object key) {
       return containsKey(key) ? multimap.removeAll(key) : null;
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return multimap.keySet();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return multimap.isEmpty();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return multimap.containsKey(key);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap.clear();
     }
   }
@@ -1679,6 +1754,7 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterKeys(
       Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof SetMultimap) {
@@ -1687,8 +1763,8 @@ public final class Multimaps {
       return filterKeys((ListMultimap<K, V>) unfiltered, keyPredicate);
     } else if (unfiltered instanceof FilteredKeyMultimap) {
       FilteredKeyMultimap<K, V> prev = (FilteredKeyMultimap<K, V>) unfiltered;
-      return new FilteredKeyMultimap<K, V>(prev.unfiltered,
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeyMultimap<K, V>(
+          prev.unfiltered, Predicates.and(prev.keyPredicate, keyPredicate));
     } else if (unfiltered instanceof FilteredMultimap) {
       FilteredMultimap<K, V> prev = (FilteredMultimap<K, V>) unfiltered;
       return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1696,7 +1772,7 @@ public final class Multimaps {
       return new FilteredKeyMultimap<K, V>(unfiltered, keyPredicate);
     }
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose keys
    * satisfy a predicate. The returned multimap is a live view of
@@ -1727,12 +1803,13 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterKeys(
       SetMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof FilteredKeySetMultimap) {
       FilteredKeySetMultimap<K, V> prev = (FilteredKeySetMultimap<K, V>) unfiltered;
-      return new FilteredKeySetMultimap<K, V>(prev.unfiltered(),
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeySetMultimap<K, V>(
+          prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
     } else if (unfiltered instanceof FilteredSetMultimap) {
       FilteredSetMultimap<K, V> prev = (FilteredSetMultimap<K, V>) unfiltered;
       return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1740,7 +1817,7 @@ public final class Multimaps {
       return new FilteredKeySetMultimap<K, V>(unfiltered, keyPredicate);
     }
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose keys
    * satisfy a predicate. The returned multimap is a live view of
@@ -1771,12 +1848,13 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> ListMultimap<K, V> filterKeys(
       ListMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof FilteredKeyListMultimap) {
       FilteredKeyListMultimap<K, V> prev = (FilteredKeyListMultimap<K, V>) unfiltered;
-      return new FilteredKeyListMultimap<K, V>(prev.unfiltered(),
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeyListMultimap<K, V>(
+          prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
     } else {
       return new FilteredKeyListMultimap<K, V>(unfiltered, keyPredicate);
     }
@@ -1812,11 +1890,12 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterValues(
       Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose values
    * satisfy a predicate. The returned multimap is a live view of
@@ -1847,6 +1926,7 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterValues(
       SetMultimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1880,6 +1960,7 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterEntries(
       Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
@@ -1890,7 +1971,7 @@ public final class Multimaps {
         ? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate)
         : new FilteredEntryMultimap<K, V>(checkNotNull(unfiltered), entryPredicate);
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} that
    * satisfy a predicate. The returned multimap is a live view of
@@ -1919,6 +2000,7 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterEntries(
       SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
@@ -1934,10 +2016,9 @@ public final class Multimaps {
    * operations would fail. This method combines the predicates to avoid that
    * problem.
    */
-  private static <K, V> Multimap<K, V> filterFiltered(FilteredMultimap<K, V> multimap,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(multimap.entryPredicate(), entryPredicate);
+  private static <K, V> Multimap<K, V> filterFiltered(
+      FilteredMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
     return new FilteredEntryMultimap<K, V>(multimap.unfiltered(), predicate);
   }
 
@@ -1948,13 +2029,11 @@ public final class Multimaps {
    * avoid that problem.
    */
   private static <K, V> SetMultimap<K, V> filterFiltered(
-      FilteredSetMultimap<K, V> multimap,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(multimap.entryPredicate(), entryPredicate);
+      FilteredSetMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
     return new FilteredEntrySetMultimap<K, V>(multimap.unfiltered(), predicate);
   }
-  
+
   static boolean equalsImpl(Multimap<?, ?> multimap, @Nullable Object object) {
     if (object == multimap) {
       return true;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
index 340985c..73d7573 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
@@ -28,7 +28,7 @@ import javax.annotation.Nullable;
  * Static utility methods pertaining to object arrays.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class ObjectArrays {
@@ -81,8 +81,7 @@ public final class ObjectArrays {
   /** GWT safe version of Arrays.copyOf. */
   static <T> T[] arraysCopyOf(T[] original, int newLength) {
     T[] copy = newArray(original, newLength);
-    System.arraycopy(
-        original, 0, copy, 0, Math.min(original.length, newLength));
+    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
     return copy;
   }
 
@@ -121,7 +120,7 @@ public final class ObjectArrays {
     }
     return array;
   }
-  
+
   /**
    * Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
    * array. the runtime type of the returned array is that of the specified array. If the collection
@@ -196,7 +195,7 @@ public final class ObjectArrays {
   static Object[] checkElementsNotNull(Object... array) {
     return checkElementsNotNull(array, array.length);
   }
-  
+
   static Object[] checkElementsNotNull(Object[] array, int length) {
     for (int i = 0; i < length; i++) {
       checkElementNotNull(array[i], i);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
index 3af12bd..be5b600 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
@@ -26,7 +26,9 @@ import java.io.Serializable;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
@@ -141,5 +143,9 @@ final class Platform {
     return Maps.filterSortedIgnoreNavigable(unfiltered, predicate);
   }
 
+  static <E> Queue<E> newFastestQueue(int ignored) {
+    return new LinkedList<E>();
+  }
+
   private Platform() {}
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
index 0a30c0a..e57973a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
@@ -45,26 +45,31 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
         : new EmptyContiguousSet<C>(domain);
   }
 
-  @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
     return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
   }
 
-  @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
-      boolean toInclusive) {
+  @Override
+  ContiguousSet<C> subSetImpl(
+      C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
     if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
       // Range would reject our attempt to create (x, x).
       return new EmptyContiguousSet<C>(domain);
     }
-    return intersectionInCurrentDomain(Range.range(
-        fromElement, BoundType.forBoolean(fromInclusive),
-        toElement, BoundType.forBoolean(toInclusive)));
+    return intersectionInCurrentDomain(
+        Range.range(
+            fromElement, BoundType.forBoolean(fromInclusive),
+            toElement, BoundType.forBoolean(toInclusive)));
   }
 
-  @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
     return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
   }
 
-  @Override public UnmodifiableIterator<C> iterator() {
+  @Override
+  public UnmodifiableIterator<C> iterator() {
     return new AbstractSequentialIterator<C>(first()) {
       final C last = last();
 
@@ -79,24 +84,29 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     return right != null && Range.compareOrThrow(left, right) == 0;
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
-  @Override public C first() {
+  @Override
+  public C first() {
     return range.lowerBound.leastValueAbove(domain);
   }
 
-  @Override public C last() {
+  @Override
+  public C last() {
     return range.upperBound.greatestValueBelow(domain);
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     long distance = domain.distance(first(), last());
     return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
   }
 
-  @Override public boolean contains(@Nullable Object object) {
+  @Override
+  public boolean contains(@Nullable Object object) {
     if (object == null) {
       return false;
     }
@@ -107,15 +117,18 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     }
   }
 
-  @Override public boolean containsAll(Collection<?> targets) {
+  @Override
+  public boolean containsAll(Collection<?> targets) {
     return Collections2.containsAllImpl(this, targets);
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return false;
   }
 
-  @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+  @Override
+  public ContiguousSet<C> intersection(ContiguousSet<C> other) {
     checkNotNull(other);
     checkArgument(this.domain.equals(other.domain));
     if (other.isEmpty()) {
@@ -129,30 +142,34 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     }
   }
 
-  @Override public Range<C> range() {
+  @Override
+  public Range<C> range() {
     return range(CLOSED, CLOSED);
   }
 
-  @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
-    return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
+  @Override
+  public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+    return Range.create(
+        range.lowerBound.withLowerBoundType(lowerBoundType, domain),
         range.upperBound.withUpperBoundType(upperBoundType, domain));
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     } else if (object instanceof RegularContiguousSet) {
       RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
       if (this.domain.equals(that.domain)) {
-        return this.first().equals(that.first())
-            && this.last().equals(that.last());
+        return this.first().equals(that.first()) && this.last().equals(that.last());
       }
     }
     return super.equals(object);
   }
 
   // copied to make sure not to use the GWT-emulated version
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Sets.hashCodeImpl(this);
   }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
index bd6e43d..c774525 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
@@ -17,6 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
 
 /**
  * An {@link ImmutableAsList} implementation specialized for when the delegate collection is
@@ -27,7 +28,7 @@ import com.google.common.annotations.GwtCompatible;
 @GwtCompatible(emulated = true)
 @SuppressWarnings("serial") // uses writeReplace, not default serialization
 class RegularImmutableAsList<E> extends ImmutableAsList<E> {
-  private final ImmutableCollection<E> delegate;
+  @Weak private final ImmutableCollection<E> delegate;
   private final ImmutableList<? extends E> delegateList;
 
   RegularImmutableAsList(ImmutableCollection<E> delegate, ImmutableList<? extends E> delegateList) {
@@ -48,7 +49,7 @@ class RegularImmutableAsList<E> extends ImmutableAsList<E> {
     return delegateList;
   }
 
-  @SuppressWarnings("unchecked")  // safe covariant cast!
+  @SuppressWarnings("unchecked") // safe covariant cast!
   @Override
   public UnmodifiableListIterator<E> listIterator(int index) {
     return (UnmodifiableListIterator<E>) delegateList.listIterator(index);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
index 5b4e851..cc3b1a7 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
@@ -16,6 +16,8 @@
 
 package com.google.common.collect;
 
+import java.util.HashMap;
+
 /**
  * GWT emulation of {@link RegularImmutableBiMap}.
  *
@@ -24,10 +26,17 @@ package com.google.common.collect;
  */
 @SuppressWarnings("serial")
 class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
+  static final RegularImmutableBiMap<Object, Object> EMPTY =
+      new RegularImmutableBiMap<Object, Object>();
 
   // This reference is used both by the GWT compiler to infer the elements
   // of the lists that needs to be serialized.
   private ImmutableBiMap<V, K> inverse;
+  
+  RegularImmutableBiMap() {
+    super(new RegularImmutableMap<K, V>(new HashMap<K, V>()));
+    this.inverse = (ImmutableBiMap<V, K>) this;
+  }
 
   RegularImmutableBiMap(ImmutableMap<K, V> delegate) {
     super(delegate);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
index 72da3e4..7245096 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
@@ -16,8 +16,7 @@
 
 package com.google.common.collect;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
+import java.util.Collections;
 import java.util.Set;
 
 /**
@@ -26,11 +25,10 @@ import java.util.Set;
  * @author Hayward Chan
  */
 final class RegularImmutableSet<E> extends ForwardingImmutableSet<E> {
+  static final RegularImmutableSet<Object> EMPTY = new RegularImmutableSet<Object>(
+      Collections.emptySet());
+
   RegularImmutableSet(Set<E> delegate) {
     super(delegate);
-
-    // Required for GWT deserialization because the server-side implementation
-    // requires this.
-    checkArgument(delegate.size() >= 2);
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
index 2a0c594..eb2634c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
@@ -41,6 +41,7 @@ import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -48,13 +49,13 @@ import javax.annotation.Nullable;
  * class's counterparts {@link Lists}, {@link Maps} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Sets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#sets">
  * {@code Sets}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
  * @author Chris Povirk
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Sets {
@@ -107,8 +108,7 @@ public final class Sets {
    */
   // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
   @GwtCompatible(serializable = true)
-  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(
-      Iterable<E> elements) {
+  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(Iterable<E> elements) {
     if (elements instanceof ImmutableEnumSet) {
       return (ImmutableEnumSet<E>) elements;
     } else if (elements instanceof Collection) {
@@ -131,13 +131,12 @@ public final class Sets {
   }
 
   /**
-   * Returns a new {@code EnumSet} instance containing the given elements.
-   * Unlike {@link EnumSet#copyOf(Collection)}, this method does not produce an
-   * exception on an empty collection, and it may be called on any iterable, not
-   * just a {@code Collection}.
+   * Returns a new, <i>mutable</i> {@code EnumSet} instance containing the given elements in their
+   * natural order. This method behaves identically to {@link EnumSet#copyOf(Collection)}, but also
+   * accepts non-{@code Collection} iterables and empty iterables.
    */
-  public static <E extends Enum<E>> EnumSet<E> newEnumSet(Iterable<E> iterable,
-      Class<E> elementType) {
+  public static <E extends Enum<E>> EnumSet<E> newEnumSet(
+      Iterable<E> iterable, Class<E> elementType) {
     EnumSet<E> set = EnumSet.noneOf(elementType);
     Iterables.addAll(set, iterable);
     return set;
@@ -146,33 +145,33 @@ public final class Sets {
   // HashSet
 
   /**
-   * Creates a <i>mutable</i>, empty {@code HashSet} instance.
+   * Creates a <i>mutable</i>, initially empty {@code HashSet} instance.
    *
-   * <p><b>Note:</b> if mutability is not required, use {@link
-   * ImmutableSet#of()} instead.
+   * <p><b>Note:</b> if mutability is not required, use {@link ImmutableSet#of()} instead. If
+   * {@code E} is an {@link Enum} type, use {@link EnumSet#noneOf} instead. Otherwise, strongly
+   * consider using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to
+   * get deterministic iteration behavior.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
-   * EnumSet#noneOf} instead.
-   *
-   * @return a new, empty {@code HashSet}
+   * <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
+   * deprecated. Instead, use the {@code HashSet} constructor directly, taking advantage of the new
+   * <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
    */
   public static <E> HashSet<E> newHashSet() {
     return new HashSet<E>();
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
+   * Creates a <i>mutable</i> {@code HashSet} instance initially containing the given elements.
    *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use an overload of {@link ImmutableSet#of()} (for varargs) or
-   * {@link ImmutableSet#copyOf(Object[])} (for an array) instead.
+   * <p><b>Note:</b> if elements are non-null and won't be added or removed after this point, use
+   * {@link ImmutableSet#of()} or {@link ImmutableSet#copyOf(Object[])} instead. If {@code E} is an
+   * {@link Enum} type, use {@link EnumSet#of(Enum, Enum[])} instead. Otherwise, strongly consider
+   * using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to get
+   * deterministic iteration behavior.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
-   * EnumSet#of(Enum, Enum[])} instead.
-   *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p>This method is just a small convenience, either for {@code newHashSet(}{@link Arrays#asList
+   * asList}{@code (...))}, or for creating an empty set then calling {@link Collections#addAll}.
+   * This method is not actually very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(E... elements) {
     HashSet<E> set = newHashSetWithExpectedSize(elements.length);
@@ -181,11 +180,10 @@ public final class Sets {
   }
 
   /**
-   * Creates a {@code HashSet} instance, with a high enough "initial capacity"
-   * that it <i>should</i> hold {@code expectedSize} elements without growth.
-   * This behavior cannot be broadly guaranteed, but it is observed to be true
-   * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
-   * inadvertently <i>oversizing</i> the returned set.
+   * Creates a {@code HashSet} instance, with a high enough initial table size that it <i>should</i>
+   * hold {@code expectedSize} elements without resizing. This behavior cannot be broadly
+   * guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the
+   * method isn't inadvertently <i>oversizing</i> the returned set.
    *
    * @param expectedSize the number of elements you expect to add to the
    *        returned set
@@ -198,17 +196,22 @@ public final class Sets {
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
+   * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+   * convenience for creating an empty set then calling {@link Collection#addAll} or {@link
+   * Iterables#addAll}.
    *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+   * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+   * ImmutableSet#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
+   * FluentIterable} and call {@code elements.toSet()}.)
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use
-   * {@link #newEnumSet(Iterable, Class)} instead.
+   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link #newEnumSet(Iterable, Class)}
+   * instead.
    *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
+   * need this method. Instead, use the {@code HashSet} constructor directly, taking advantage of
+   * the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
+   *
+   * <p>Overall, this method is not very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
     return (elements instanceof Collection)
@@ -217,17 +220,16 @@ public final class Sets {
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
+   * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+   * convenience for creating an empty set and then calling {@link Iterators#addAll}.
    *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+   * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+   * ImmutableSet#copyOf(Iterator)} instead.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an
-   * {@link EnumSet} instead.
+   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an {@link EnumSet}
+   * instead.
    *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p>Overall, this method is not very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
     HashSet<E> set = newHashSet();
@@ -264,8 +266,7 @@ public final class Sets {
    *      null
    * @since 15.0
    */
-  public static <E> Set<E> newConcurrentHashSet(
-      Iterable<? extends E> elements) {
+  public static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) {
     Set<E> set = newConcurrentHashSet();
     Iterables.addAll(set, elements);
     return set;
@@ -299,8 +300,7 @@ public final class Sets {
    * @throws IllegalArgumentException if {@code expectedSize} is negative
    * @since 11.0
    */
-  public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(
-      int expectedSize) {
+  public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(int expectedSize) {
     return new LinkedHashSet<E>(Maps.capacity(expectedSize));
   }
 
@@ -315,8 +315,7 @@ public final class Sets {
    * @return a new {@code LinkedHashSet} containing those elements (minus
    *     duplicates)
    */
-  public static <E> LinkedHashSet<E> newLinkedHashSet(
-      Iterable<? extends E> elements) {
+  public static <E> LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements) {
     if (elements instanceof Collection) {
       return new LinkedHashSet<E>(Collections2.cast(elements));
     }
@@ -355,8 +354,7 @@ public final class Sets {
    * @param elements the elements that the set should contain
    * @return a new {@code TreeSet} containing those elements (minus duplicates)
    */
-  public static <E extends Comparable> TreeSet<E> newTreeSet(
-      Iterable<? extends E> elements) {
+  public static <E extends Comparable> TreeSet<E> newTreeSet(Iterable<? extends E> elements) {
     TreeSet<E> set = newTreeSet();
     Iterables.addAll(set, elements);
     return set;
@@ -406,13 +404,12 @@ public final class Sets {
    * @throws IllegalArgumentException if {@code collection} is not an
    *     {@code EnumSet} instance and contains no elements
    */
-  public static <E extends Enum<E>> EnumSet<E> complementOf(
-      Collection<E> collection) {
+  public static <E extends Enum<E>> EnumSet<E> complementOf(Collection<E> collection) {
     if (collection instanceof EnumSet) {
       return EnumSet.complementOf((EnumSet<E>) collection);
     }
-    checkArgument(!collection.isEmpty(),
-        "collection is empty; use the other version of this method");
+    checkArgument(
+        !collection.isEmpty(), "collection is empty; use the other version of this method");
     Class<E> type = collection.iterator().next().getDeclaringClass();
     return makeComplementByHand(collection, type);
   }
@@ -467,14 +464,15 @@ public final class Sets {
    *   Set<Object> identityHashSet = Sets.newSetFromMap(
    *       new IdentityHashMap<Object, Boolean>());}</pre>
    *
-   * <p>This method has the same behavior as the JDK 6 method
-   * {@code Collections.newSetFromMap()}. The returned set is serializable if
-   * the backing map is.
+   * <p>The returned set is serializable if the backing map is.
    *
    * @param map the backing map
    * @return the set backed by the map
    * @throws IllegalArgumentException if {@code map} is not empty
+   * @deprecated Use {@link Collections#newSetFromMap} instead. This method
+   *     will be removed in August 2017.
    */
+  @Deprecated
   public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
     return Platform.newSetFromMap(map);
   }
@@ -487,7 +485,7 @@ public final class Sets {
    * as a plain {@link Set}, or immediately invoke {@link #immutableCopy} or
    * {@link #copyInto} and forget the {@code SetView} itself.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public abstract static class SetView<E> extends AbstractSet<E> {
     private SetView() {} // no subclasses but our own
@@ -540,35 +538,44 @@ public final class Sets {
    * {@code union = Sets.union(union, anotherSet);}, since iterating over the resulting
    * set has a cubic complexity to the depth of the nesting.
    */
-  public static <E> SetView<E> union(
-      final Set<? extends E> set1, final Set<? extends E> set2) {
+  public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Set<? extends E> set2minus1 = difference(set2, set1);
 
     return new SetView<E>() {
-      @Override public int size() {
+      @Override
+      public int size() {
         return set1.size() + set2minus1.size();
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return set1.isEmpty() && set2.isEmpty();
       }
-      @Override public Iterator<E> iterator() {
+
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.unmodifiableIterator(
             Iterators.concat(set1.iterator(), set2minus1.iterator()));
       }
-      @Override public boolean contains(Object object) {
+
+      @Override
+      public boolean contains(Object object) {
         return set1.contains(object) || set2.contains(object);
       }
-      @Override public <S extends Set<E>> S copyInto(S set) {
+
+      @Override
+      public <S extends Set<E>> S copyInto(S set) {
         set.addAll(set1);
         set.addAll(set2);
         return set;
       }
-      @Override public ImmutableSet<E> immutableCopy() {
-        return new ImmutableSet.Builder<E>()
-            .addAll(set1).addAll(set2).build();
+
+      @Override
+      public ImmutableSet<E> immutableCopy() {
+        return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
       }
     };
   }
@@ -599,28 +606,35 @@ public final class Sets {
    *
    * <p>This is unfortunate, but should come up only very rarely.
    */
-  public static <E> SetView<E> intersection(
-      final Set<E> set1, final Set<?> set2) {
+  public static <E> SetView<E> intersection(final Set<E> set1, final Set<?> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Predicate<Object> inSet2 = Predicates.in(set2);
     return new SetView<E>() {
-      @Override public Iterator<E> iterator() {
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.filter(set1.iterator(), inSet2);
       }
-      @Override public int size() {
+
+      @Override
+      public int size() {
         return Iterators.size(iterator());
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return !iterator().hasNext();
       }
-      @Override public boolean contains(Object object) {
+
+      @Override
+      public boolean contains(Object object) {
         return set1.contains(object) && set2.contains(object);
       }
-      @Override public boolean containsAll(Collection<?> collection) {
-        return set1.containsAll(collection)
-            && set2.containsAll(collection);
+
+      @Override
+      public boolean containsAll(Collection<?> collection) {
+        return set1.containsAll(collection) && set2.containsAll(collection);
       }
     };
   }
@@ -636,23 +650,29 @@ public final class Sets {
    * on different equivalence relations (as {@code HashSet}, {@code TreeSet},
    * and the keySet of an {@code IdentityHashMap} all are).
    */
-  public static <E> SetView<E> difference(
-      final Set<E> set1, final Set<?> set2) {
+  public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Predicate<Object> notInSet2 = Predicates.not(Predicates.in(set2));
     return new SetView<E>() {
-      @Override public Iterator<E> iterator() {
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.filter(set1.iterator(), notInSet2);
       }
-      @Override public int size() {
+
+      @Override
+      public int size() {
         return Iterators.size(iterator());
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return set2.containsAll(set1);
       }
-      @Override public boolean contains(Object element) {
+
+      @Override
+      public boolean contains(Object element) {
         return set1.contains(element) && !set2.contains(element);
       }
     };
@@ -671,12 +691,50 @@ public final class Sets {
    * @since 3.0
    */
   public static <E> SetView<E> symmetricDifference(
-      Set<? extends E> set1, Set<? extends E> set2) {
+      final Set<? extends E> set1, final Set<? extends E> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
-    // TODO(kevinb): Replace this with a more efficient implementation
-    return difference(union(set1, set2), intersection(set1, set2));
+    return new SetView<E>() {
+      @Override
+      public Iterator<E> iterator() {
+        final Iterator<? extends E> itr1 = set1.iterator();
+        final Iterator<? extends E> itr2 = set2.iterator();
+        return new AbstractIterator<E>() {
+          @Override
+          public E computeNext() {
+            while (itr1.hasNext()) {
+              E elem1 = itr1.next();
+              if (!set2.contains(elem1)) {
+                return elem1;
+              }
+            }
+            while (itr2.hasNext()) {
+              E elem2 = itr2.next();
+              if (!set1.contains(elem2)) {
+                return elem2;
+              }
+            }
+            return endOfData();
+          }
+        };
+      }
+
+      @Override
+      public int size() {
+        return Iterators.size(iterator());
+      }
+
+      @Override
+      public boolean isEmpty() {
+        return set1.equals(set2);
+      }
+
+      @Override
+      public boolean contains(Object element) {
+        return set1.contains(element) ^ set2.contains(element);
+      }
+    };
   }
 
   /**
@@ -706,8 +764,8 @@ public final class Sets {
    * functionality.)
    */
   // TODO(kevinb): how to omit that last sentence when building GWT javadoc?
-  public static <E> Set<E> filter(
-      Set<E> unfiltered, Predicate<? super E> predicate) {
+  @CheckReturnValue
+  public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) {
     if (unfiltered instanceof SortedSet) {
       return filter((SortedSet<E>) unfiltered, predicate);
     }
@@ -715,27 +773,25 @@ public final class Sets {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
-      return new FilteredSet<E>(
-          (Set<E>) filtered.unfiltered, combinedPredicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+      return new FilteredSet<E>((Set<E>) filtered.unfiltered, combinedPredicate);
     }
 
-    return new FilteredSet<E>(
-        checkNotNull(unfiltered), checkNotNull(predicate));
+    return new FilteredSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
-  private static class FilteredSet<E> extends FilteredCollection<E>
-      implements Set<E> {
+  private static class FilteredSet<E> extends FilteredCollection<E> implements Set<E> {
     FilteredSet(Set<E> unfiltered, Predicate<? super E> predicate) {
       super(unfiltered, predicate);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return equalsImpl(this, object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return hashCodeImpl(this);
     }
   }
@@ -769,8 +825,8 @@ public final class Sets {
    *
    * @since 11.0
    */
-  public static <E> SortedSet<E> filter(
-      SortedSet<E> unfiltered, Predicate<? super E> predicate) {
+  @CheckReturnValue
+  public static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
     return Platform.setsFilterSortedSet(unfiltered, predicate);
   }
 
@@ -780,18 +836,14 @@ public final class Sets {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
-      return new FilteredSortedSet<E>(
-          (SortedSet<E>) filtered.unfiltered, combinedPredicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+      return new FilteredSortedSet<E>((SortedSet<E>) filtered.unfiltered, combinedPredicate);
     }
 
-    return new FilteredSortedSet<E>(
-        checkNotNull(unfiltered), checkNotNull(predicate));
+    return new FilteredSortedSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
-  private static class FilteredSortedSet<E> extends FilteredSet<E>
-      implements SortedSet<E> {
+  private static class FilteredSortedSet<E> extends FilteredSet<E> implements SortedSet<E> {
 
     FilteredSortedSet(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
       super(unfiltered, predicate);
@@ -804,8 +856,8 @@ public final class Sets {
 
     @Override
     public SortedSet<E> subSet(E fromElement, E toElement) {
-      return new FilteredSortedSet<E>(((SortedSet<E>) unfiltered).subSet(fromElement, toElement),
-          predicate);
+      return new FilteredSortedSet<E>(
+          ((SortedSet<E>) unfiltered).subSet(fromElement, toElement), predicate);
     }
 
     @Override
@@ -891,8 +943,7 @@ public final class Sets {
    *     or any element of a provided set is null
    * @since 2.0
    */
-  public static <B> Set<List<B>> cartesianProduct(
-      List<? extends Set<? extends B>> sets) {
+  public static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
     return CartesianSet.create(sets);
   }
 
@@ -951,13 +1002,12 @@ public final class Sets {
    *     or any element of a provided set is null
    * @since 2.0
    */
-  public static <B> Set<List<B>> cartesianProduct(
-      Set<? extends B>... sets) {
+  public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) {
     return cartesianProduct(Arrays.asList(sets));
   }
 
-  private static final class CartesianSet<E>
-      extends ForwardingCollection<List<E>> implements Set<List<E>> {
+  private static final class CartesianSet<E> extends ForwardingCollection<List<E>>
+      implements Set<List<E>> {
     private transient final ImmutableList<ImmutableSet<E>> axes;
     private transient final CartesianList<E> delegate;
 
@@ -972,28 +1022,27 @@ public final class Sets {
         axesBuilder.add(copy);
       }
       final ImmutableList<ImmutableSet<E>> axes = axesBuilder.build();
-      ImmutableList<List<E>> listAxes = new ImmutableList<List<E>>() {
-
-        @Override
-        public int size() {
-          return axes.size();
-        }
-
-        @Override
-        public List<E> get(int index) {
-          return axes.get(index).asList();
-        }
-
-        @Override
-        boolean isPartialView() {
-          return true;
-        }
-      };
+      ImmutableList<List<E>> listAxes =
+          new ImmutableList<List<E>>() {
+            @Override
+            public int size() {
+              return axes.size();
+            }
+
+            @Override
+            public List<E> get(int index) {
+              return axes.get(index).asList();
+            }
+
+            @Override
+            boolean isPartialView() {
+              return true;
+            }
+          };
       return new CartesianSet<E>(axes, new CartesianList<E>(listAxes));
     }
 
-    private CartesianSet(
-        ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
+    private CartesianSet(ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
       this.axes = axes;
       this.delegate = delegate;
     }
@@ -1003,7 +1052,8 @@ public final class Sets {
       return delegate;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       // Warning: this is broken if size() == 0, so it is critical that we
       // substitute an empty ImmutableSet to the user in place of this
       if (object instanceof CartesianSet) {
@@ -1118,33 +1168,33 @@ public final class Sets {
     final ImmutableMap<E, Integer> inputSet;
 
     PowerSet(Set<E> input) {
-      ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
-      int i = 0;
-      for (E e : checkNotNull(input)) {
-        builder.put(e, i++);
-      }
-      this.inputSet = builder.build();
-      checkArgument(inputSet.size() <= 30,
-          "Too many elements to create power set: %s > 30", inputSet.size());
+      this.inputSet = Maps.indexMap(input);
+      checkArgument(
+          inputSet.size() <= 30, "Too many elements to create power set: %s > 30", inputSet.size());
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return 1 << inputSet.size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Iterator<Set<E>> iterator() {
+    @Override
+    public Iterator<Set<E>> iterator() {
       return new AbstractIndexedListIterator<Set<E>>(size()) {
-        @Override protected Set<E> get(final int setBits) {
+        @Override
+        protected Set<E> get(final int setBits) {
           return new SubSet<E>(inputSet, setBits);
         }
       };
     }
 
-    @Override public boolean contains(@Nullable Object obj) {
+    @Override
+    public boolean contains(@Nullable Object obj) {
       if (obj instanceof Set) {
         Set<?> set = (Set<?>) obj;
         return inputSet.keySet().containsAll(set);
@@ -1152,7 +1202,8 @@ public final class Sets {
       return false;
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof PowerSet) {
         PowerSet<?> that = (PowerSet<?>) obj;
         return inputSet.equals(that.inputSet);
@@ -1160,7 +1211,8 @@ public final class Sets {
       return super.equals(obj);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       /*
        * The sum of the sums of the hash codes in each subset is just the sum of
        * each input element's hash code times the number of sets that element
@@ -1169,7 +1221,8 @@ public final class Sets {
       return inputSet.keySet().hashCode() << (inputSet.size() - 1);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "powerSet(" + inputSet + ")";
     }
   }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
index e3955b5..edff70c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
@@ -21,6 +21,7 @@ import static com.google.common.collect.BoundType.OPEN;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multiset.Entry;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.Comparator;
 import java.util.NoSuchElementException;
@@ -36,45 +37,50 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 final class SortedMultisets {
-  private SortedMultisets() {
-  }
+  private SortedMultisets() {}
 
   /**
    * A skeleton implementation for {@link SortedMultiset#elementSet}.
    */
-  static class ElementSet<E> extends Multisets.ElementSet<E> implements
-      SortedSet<E> {
-    private final SortedMultiset<E> multiset;
+  static class ElementSet<E> extends Multisets.ElementSet<E> implements SortedSet<E> {
+    @Weak private final SortedMultiset<E> multiset;
 
     ElementSet(SortedMultiset<E> multiset) {
       this.multiset = multiset;
     }
 
-    @Override final SortedMultiset<E> multiset() {
+    @Override
+    final SortedMultiset<E> multiset() {
       return multiset;
     }
 
-    @Override public Comparator<? super E> comparator() {
+    @Override
+    public Comparator<? super E> comparator() {
       return multiset().comparator();
     }
 
-    @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+    @Override
+    public SortedSet<E> subSet(E fromElement, E toElement) {
       return multiset().subMultiset(fromElement, CLOSED, toElement, OPEN).elementSet();
     }
 
-    @Override public SortedSet<E> headSet(E toElement) {
+    @Override
+    public SortedSet<E> headSet(E toElement) {
       return multiset().headMultiset(toElement, OPEN).elementSet();
     }
 
-    @Override public SortedSet<E> tailSet(E fromElement) {
+    @Override
+    public SortedSet<E> tailSet(E fromElement) {
       return multiset().tailMultiset(fromElement, CLOSED).elementSet();
     }
 
-    @Override public E first() {
+    @Override
+    public E first() {
       return getElementOrThrow(multiset().firstEntry());
     }
 
-    @Override public E last() {
+    @Override
+    public E last() {
       return getElementOrThrow(multiset().lastEntry());
     }
   }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
index c809da8..08378c8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
@@ -69,7 +69,8 @@ final class Synchronized {
 
     // No equals and hashCode; see ForwardingObject for details.
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       synchronized (mutex) {
         return delegate.toString();
       }
@@ -81,20 +82,19 @@ final class Synchronized {
     // following writeObject() handles the SynchronizedObject members.
   }
 
-  private static <E> Collection<E> collection(
-      Collection<E> collection, @Nullable Object mutex) {
+  private static <E> Collection<E> collection(Collection<E> collection, @Nullable Object mutex) {
     return new SynchronizedCollection<E>(collection, mutex);
   }
 
-  @VisibleForTesting static class SynchronizedCollection<E>
-      extends SynchronizedObject implements Collection<E> {
-    private SynchronizedCollection(
-        Collection<E> delegate, @Nullable Object mutex) {
+  @VisibleForTesting
+  static class SynchronizedCollection<E> extends SynchronizedObject implements Collection<E> {
+    private SynchronizedCollection(Collection<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
     @SuppressWarnings("unchecked")
-    @Override Collection<E> delegate() {
+    @Override
+    Collection<E> delegate() {
       return (Collection<E>) super.delegate();
     }
 
@@ -190,22 +190,24 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  @VisibleForTesting static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
+  @VisibleForTesting
+  static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
     return new SynchronizedSet<E>(set, mutex);
   }
 
-  static class SynchronizedSet<E>
-      extends SynchronizedCollection<E> implements Set<E> {
+  static class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {
 
     SynchronizedSet(Set<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override Set<E> delegate() {
+    @Override
+    Set<E> delegate() {
       return (Set<E>) super.delegate();
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -214,7 +216,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -223,18 +226,17 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static <E> SortedSet<E> sortedSet(
-      SortedSet<E> set, @Nullable Object mutex) {
+  private static <E> SortedSet<E> sortedSet(SortedSet<E> set, @Nullable Object mutex) {
     return new SynchronizedSortedSet<E>(set, mutex);
   }
 
-  static class SynchronizedSortedSet<E> extends SynchronizedSet<E>
-      implements SortedSet<E> {
+  static class SynchronizedSortedSet<E> extends SynchronizedSet<E> implements SortedSet<E> {
     SynchronizedSortedSet(SortedSet<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override SortedSet<E> delegate() {
+    @Override
+    SortedSet<E> delegate() {
       return (SortedSet<E>) super.delegate();
     }
 
@@ -289,13 +291,13 @@ final class Synchronized {
         : new SynchronizedList<E>(list, mutex);
   }
 
-  private static class SynchronizedList<E> extends SynchronizedCollection<E>
-      implements List<E> {
+  private static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
     SynchronizedList(List<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override List<E> delegate() {
+    @Override
+    List<E> delegate() {
       return (List<E>) super.delegate();
     }
 
@@ -365,7 +367,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -374,7 +377,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -383,18 +387,17 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedRandomAccessList<E>
-      extends SynchronizedList<E> implements RandomAccess {
+  private static class SynchronizedRandomAccessList<E> extends SynchronizedList<E>
+      implements RandomAccess {
     SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) {
       super(list, mutex);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  static <E> Multiset<E> multiset(
-      Multiset<E> multiset, @Nullable Object mutex) {
-    if (multiset instanceof SynchronizedMultiset ||
-        multiset instanceof ImmutableMultiset) {
+  static <E> Multiset<E> multiset(Multiset<E> multiset, @Nullable Object mutex) {
+    if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) {
       return multiset;
     }
     return new SynchronizedMultiset<E>(multiset, mutex);
@@ -409,7 +412,8 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override Multiset<E> delegate() {
+    @Override
+    Multiset<E> delegate() {
       return (Multiset<E>) super.delegate();
     }
 
@@ -468,7 +472,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -477,7 +482,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -486,10 +492,8 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> Multimap<K, V> multimap(
-      Multimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedMultimap ||
-        multimap instanceof ImmutableMultimap) {
+  static <K, V> Multimap<K, V> multimap(Multimap<K, V> multimap, @Nullable Object mutex) {
+    if (multimap instanceof SynchronizedMultimap || multimap instanceof ImmutableMultimap) {
       return multimap;
     }
     return new SynchronizedMultimap<K, V>(multimap, mutex);
@@ -504,7 +508,8 @@ final class Synchronized {
     transient Multiset<K> keys;
 
     @SuppressWarnings("unchecked")
-    @Override Multimap<K, V> delegate() {
+    @Override
+    Multimap<K, V> delegate() {
       return (Multimap<K, V>) super.delegate();
     }
 
@@ -653,7 +658,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -662,7 +668,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -673,78 +680,90 @@ final class Synchronized {
 
   static <K, V> ListMultimap<K, V> listMultimap(
       ListMultimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedListMultimap ||
-        multimap instanceof ImmutableListMultimap) {
+    if (multimap instanceof SynchronizedListMultimap || multimap instanceof ImmutableListMultimap) {
       return multimap;
     }
     return new SynchronizedListMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedListMultimap<K, V>
-      extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> {
-    SynchronizedListMultimap(
-        ListMultimap<K, V> delegate, @Nullable Object mutex) {
+  private static class SynchronizedListMultimap<K, V> extends SynchronizedMultimap<K, V>
+      implements ListMultimap<K, V> {
+    SynchronizedListMultimap(ListMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override ListMultimap<K, V> delegate() {
+
+    @Override
+    ListMultimap<K, V> delegate() {
       return (ListMultimap<K, V>) super.delegate();
     }
-    @Override public List<V> get(K key) {
+
+    @Override
+    public List<V> get(K key) {
       synchronized (mutex) {
         return list(delegate().get(key), mutex);
       }
     }
-    @Override public List<V> removeAll(Object key) {
+
+    @Override
+    public List<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public List<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public List<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> SetMultimap<K, V> setMultimap(
-      SetMultimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedSetMultimap ||
-        multimap instanceof ImmutableSetMultimap) {
+  static <K, V> SetMultimap<K, V> setMultimap(SetMultimap<K, V> multimap, @Nullable Object mutex) {
+    if (multimap instanceof SynchronizedSetMultimap || multimap instanceof ImmutableSetMultimap) {
       return multimap;
     }
     return new SynchronizedSetMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedSetMultimap<K, V>
-      extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> {
+  private static class SynchronizedSetMultimap<K, V> extends SynchronizedMultimap<K, V>
+      implements SetMultimap<K, V> {
     transient Set<Map.Entry<K, V>> entrySet;
 
-    SynchronizedSetMultimap(
-        SetMultimap<K, V> delegate, @Nullable Object mutex) {
+    SynchronizedSetMultimap(SetMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override SetMultimap<K, V> delegate() {
+
+    @Override
+    SetMultimap<K, V> delegate() {
       return (SetMultimap<K, V>) super.delegate();
     }
-    @Override public Set<V> get(K key) {
+
+    @Override
+    public Set<V> get(K key) {
       synchronized (mutex) {
         return set(delegate().get(key), mutex);
       }
     }
-    @Override public Set<V> removeAll(Object key) {
+
+    @Override
+    public Set<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public Set<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
-    @Override public Set<Map.Entry<K, V>> entries() {
+
+    @Override
+    public Set<Map.Entry<K, V>> entries() {
       synchronized (mutex) {
         if (entrySet == null) {
           entrySet = set(delegate().entries(), mutex);
@@ -752,6 +771,7 @@ final class Synchronized {
         return entrySet;
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -763,37 +783,45 @@ final class Synchronized {
     return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedSortedSetMultimap<K, V>
-      extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
-    SynchronizedSortedSetMultimap(
-        SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
+  private static class SynchronizedSortedSetMultimap<K, V> extends SynchronizedSetMultimap<K, V>
+      implements SortedSetMultimap<K, V> {
+    SynchronizedSortedSetMultimap(SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override SortedSetMultimap<K, V> delegate() {
+
+    @Override
+    SortedSetMultimap<K, V> delegate() {
       return (SortedSetMultimap<K, V>) super.delegate();
     }
-    @Override public SortedSet<V> get(K key) {
+
+    @Override
+    public SortedSet<V> get(K key) {
       synchronized (mutex) {
         return sortedSet(delegate().get(key), mutex);
       }
     }
-    @Override public SortedSet<V> removeAll(Object key) {
+
+    @Override
+    public SortedSet<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public SortedSet<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
+
     @Override
     public Comparator<? super V> valueComparator() {
       synchronized (mutex) {
         return delegate().valueComparator();
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -811,8 +839,7 @@ final class Synchronized {
     return collection(collection, mutex);
   }
 
-  private static <E> Set<E> typePreservingSet(
-      Set<E> set, @Nullable Object mutex) {
+  private static <E> Set<E> typePreservingSet(Set<E> set, @Nullable Object mutex) {
     if (set instanceof SortedSet) {
       return sortedSet((SortedSet<E>) set, mutex);
     } else {
@@ -822,26 +849,25 @@ final class Synchronized {
 
   private static class SynchronizedAsMapEntries<K, V>
       extends SynchronizedSet<Map.Entry<K, Collection<V>>> {
-    SynchronizedAsMapEntries(
-        Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
+    SynchronizedAsMapEntries(Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+    @Override
+    public Iterator<Map.Entry<K, Collection<V>>> iterator() {
       // Must be manually synchronized.
-      final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator();
-      return new ForwardingIterator<Map.Entry<K, Collection<V>>>() {
-        @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() {
-          return iterator;
-        }
-
-        @Override public Map.Entry<K, Collection<V>> next() {
-          final Map.Entry<K, Collection<V>> entry = super.next();
+      return new TransformedIterator<Map.Entry<K, Collection<V>>, Map.Entry<K, Collection<V>>>(
+          super.iterator()) {
+        @Override
+        Map.Entry<K, Collection<V>> transform(final Map.Entry<K, Collection<V>> entry) {
           return new ForwardingMapEntry<K, Collection<V>>() {
-            @Override protected Map.Entry<K, Collection<V>> delegate() {
+            @Override
+            protected Map.Entry<K, Collection<V>> delegate() {
               return entry;
             }
-            @Override public Collection<V> getValue() {
+
+            @Override
+            public Collection<V> getValue() {
               return typePreservingCollection(entry.getValue(), mutex);
             }
           };
@@ -851,27 +877,36 @@ final class Synchronized {
 
     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       synchronized (mutex) {
         return ObjectArrays.toArrayImpl(delegate());
       }
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       synchronized (mutex) {
         return ObjectArrays.toArrayImpl(delegate(), array);
       }
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       synchronized (mutex) {
         return Maps.containsEntryImpl(delegate(), o);
       }
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       synchronized (mutex) {
         return Collections2.containsAllImpl(delegate(), c);
       }
     }
-    @Override public boolean equals(Object o) {
+
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -879,17 +914,23 @@ final class Synchronized {
         return Sets.equalsImpl(delegate(), o);
       }
     }
-    @Override public boolean remove(Object o) {
+
+    @Override
+    public boolean remove(Object o) {
       synchronized (mutex) {
         return Maps.removeEntryImpl(delegate(), o);
       }
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       synchronized (mutex) {
         return Iterators.removeAll(delegate().iterator(), c);
       }
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       synchronized (mutex) {
         return Iterators.retainAll(delegate().iterator(), c);
       }
@@ -903,8 +944,7 @@ final class Synchronized {
     return new SynchronizedMap<K, V>(map, mutex);
   }
 
-  private static class SynchronizedMap<K, V> extends SynchronizedObject
-      implements Map<K, V> {
+  private static class SynchronizedMap<K, V> extends SynchronizedObject implements Map<K, V> {
     transient Set<K> keySet;
     transient Collection<V> values;
     transient Set<Map.Entry<K, V>> entrySet;
@@ -914,7 +954,8 @@ final class Synchronized {
     }
 
     @SuppressWarnings("unchecked")
-    @Override Map<K, V> delegate() {
+    @Override
+    Map<K, V> delegate() {
       return (Map<K, V>) super.delegate();
     }
 
@@ -1011,7 +1052,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -1020,7 +1062,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -1029,8 +1072,7 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> SortedMap<K, V> sortedMap(
-      SortedMap<K, V> sortedMap, @Nullable Object mutex) {
+  static <K, V> SortedMap<K, V> sortedMap(SortedMap<K, V> sortedMap, @Nullable Object mutex) {
     return new SynchronizedSortedMap<K, V>(sortedMap, mutex);
   }
 
@@ -1041,41 +1083,48 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override SortedMap<K, V> delegate() {
+    @Override
+    SortedMap<K, V> delegate() {
       return (SortedMap<K, V>) super.delegate();
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       synchronized (mutex) {
         return delegate().comparator();
       }
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       synchronized (mutex) {
         return delegate().firstKey();
       }
     }
 
-    @Override public SortedMap<K, V> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V> headMap(K toKey) {
       synchronized (mutex) {
         return sortedMap(delegate().headMap(toKey), mutex);
       }
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       synchronized (mutex) {
         return delegate().lastKey();
       }
     }
 
-    @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+    @Override
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
       synchronized (mutex) {
         return sortedMap(delegate().subMap(fromKey, toKey), mutex);
       }
     }
 
-    @Override public SortedMap<K, V> tailMap(K fromKey) {
+    @Override
+    public SortedMap<K, V> tailMap(K fromKey) {
       synchronized (mutex) {
         return sortedMap(delegate().tailMap(fromKey), mutex);
       }
@@ -1085,29 +1134,31 @@ final class Synchronized {
   }
 
   static <K, V> BiMap<K, V> biMap(BiMap<K, V> bimap, @Nullable Object mutex) {
-    if (bimap instanceof SynchronizedBiMap ||
-        bimap instanceof ImmutableBiMap) {
+    if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) {
       return bimap;
     }
     return new SynchronizedBiMap<K, V>(bimap, mutex, null);
   }
 
-  @VisibleForTesting static class SynchronizedBiMap<K, V>
-      extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable {
+  @VisibleForTesting
+  static class SynchronizedBiMap<K, V> extends SynchronizedMap<K, V>
+      implements BiMap<K, V>, Serializable {
     private transient Set<V> valueSet;
     private transient BiMap<V, K> inverse;
 
-    private SynchronizedBiMap(BiMap<K, V> delegate, @Nullable Object mutex,
-        @Nullable BiMap<V, K> inverse) {
+    private SynchronizedBiMap(
+        BiMap<K, V> delegate, @Nullable Object mutex, @Nullable BiMap<V, K> inverse) {
       super(delegate, mutex);
       this.inverse = inverse;
     }
 
-    @Override BiMap<K, V> delegate() {
+    @Override
+    BiMap<K, V> delegate() {
       return (BiMap<K, V>) super.delegate();
     }
 
-    @Override public Set<V> values() {
+    @Override
+    public Set<V> values() {
       synchronized (mutex) {
         if (valueSet == null) {
           valueSet = set(delegate().values(), mutex);
@@ -1127,8 +1178,7 @@ final class Synchronized {
     public BiMap<V, K> inverse() {
       synchronized (mutex) {
         if (inverse == null) {
-          inverse
-              = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
+          inverse = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
         }
         return inverse;
       }
@@ -1137,8 +1187,7 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedAsMap<K, V>
-      extends SynchronizedMap<K, Collection<V>> {
+  private static class SynchronizedAsMap<K, V> extends SynchronizedMap<K, Collection<V>> {
     transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet;
     transient Collection<Collection<V>> asMapValues;
 
@@ -1146,35 +1195,36 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       synchronized (mutex) {
         Collection<V> collection = super.get(key);
-        return (collection == null) ? null
-            : typePreservingCollection(collection, mutex);
+        return (collection == null) ? null : typePreservingCollection(collection, mutex);
       }
     }
 
-    @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
+    @Override
+    public Set<Map.Entry<K, Collection<V>>> entrySet() {
       synchronized (mutex) {
         if (asMapEntrySet == null) {
-          asMapEntrySet = new SynchronizedAsMapEntries<K, V>(
-              delegate().entrySet(), mutex);
+          asMapEntrySet = new SynchronizedAsMapEntries<K, V>(delegate().entrySet(), mutex);
         }
         return asMapEntrySet;
       }
     }
 
-    @Override public Collection<Collection<V>> values() {
+    @Override
+    public Collection<Collection<V>> values() {
       synchronized (mutex) {
         if (asMapValues == null) {
-          asMapValues
-              = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
+          asMapValues = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
         }
         return asMapValues;
       }
     }
 
-    @Override public boolean containsValue(Object o) {
+    @Override
+    public boolean containsValue(Object o) {
       // values() and its contains() method are both synchronized.
       return values().contains(o);
     }
@@ -1182,22 +1232,18 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedAsMapValues<V>
-      extends SynchronizedCollection<Collection<V>> {
-    SynchronizedAsMapValues(
-        Collection<Collection<V>> delegate, @Nullable Object mutex) {
+  private static class SynchronizedAsMapValues<V> extends SynchronizedCollection<Collection<V>> {
+    SynchronizedAsMapValues(Collection<Collection<V>> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override public Iterator<Collection<V>> iterator() {
+    @Override
+    public Iterator<Collection<V>> iterator() {
       // Must be manually synchronized.
-      final Iterator<Collection<V>> iterator = super.iterator();
-      return new ForwardingIterator<Collection<V>>() {
-        @Override protected Iterator<Collection<V>> delegate() {
-          return iterator;
-        }
-        @Override public Collection<V> next() {
-          return typePreservingCollection(super.next(), mutex);
+      return new TransformedIterator<Collection<V>, Collection<V>>(super.iterator()) {
+        @Override
+        Collection<V> transform(Collection<V> from) {
+          return typePreservingCollection(from, mutex);
         }
       };
     }
@@ -1206,19 +1252,17 @@ final class Synchronized {
   }
 
   static <E> Queue<E> queue(Queue<E> queue, @Nullable Object mutex) {
-    return (queue instanceof SynchronizedQueue)
-        ? queue
-        : new SynchronizedQueue<E>(queue, mutex);
+    return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex);
   }
 
-  private static class SynchronizedQueue<E> extends SynchronizedCollection<E>
-      implements Queue<E> {
+  private static class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
 
     SynchronizedQueue(Queue<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override Queue<E> delegate() {
+    @Override
+    Queue<E> delegate() {
       return (Queue<E>) super.delegate();
     }
 
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
index 5023a0c..91869f8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
@@ -62,12 +62,12 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedSortedSetMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V> {
@@ -78,8 +78,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * Creates an empty {@code TreeMultimap} ordered by the natural ordering of
    * its keys and values.
    */
-  public static <K extends Comparable, V extends Comparable>
-      TreeMultimap<K, V> create() {
+  public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create() {
     return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural());
   }
 
@@ -92,10 +91,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * @param valueComparator the comparator that determines the value ordering
    */
   public static <K, V> TreeMultimap<K, V> create(
-      Comparator<? super K> keyComparator,
-      Comparator<? super V> valueComparator) {
-    return new TreeMultimap<K, V>(checkNotNull(keyComparator),
-        checkNotNull(valueComparator));
+      Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
+    return new TreeMultimap<K, V>(checkNotNull(keyComparator), checkNotNull(valueComparator));
   }
 
   /**
@@ -104,20 +101,19 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    *
    * @param multimap the multimap whose contents are copied to this multimap
    */
-  public static <K extends Comparable, V extends Comparable>
-      TreeMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
-    return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(),
-        multimap);
+  public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create(
+      Multimap<? extends K, ? extends V> multimap) {
+    return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(), multimap);
   }
 
-  TreeMultimap(Comparator<? super K> keyComparator,
-      Comparator<? super V> valueComparator) {
+  TreeMultimap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
     super(new TreeMap<K, Collection<V>>(keyComparator));
     this.keyComparator = keyComparator;
     this.valueComparator = valueComparator;
   }
 
-  private TreeMultimap(Comparator<? super K> keyComparator,
+  private TreeMultimap(
+      Comparator<? super K> keyComparator,
       Comparator<? super V> valueComparator,
       Multimap<? extends K, ? extends V> multimap) {
     this(keyComparator, valueComparator);
@@ -132,7 +128,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * @return a new {@code TreeSet} containing a collection of values for one
    *     key
    */
-  @Override SortedSet<V> createCollection() {
+  @Override
+  SortedSet<V> createCollection() {
     return new TreeSet<V>(valueComparator);
   }
 
@@ -157,7 +154,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
   }
 
   /*
-   * The following @GwtIncompatible methods override the methods in 
+   * The following @GwtIncompatible methods override the methods in
    * AbstractSortedKeySortedSetMultimap, so GWT will fall back to the ASKSSM implementations,
    * which return SortedSets and SortedMaps.
    */
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
index b9be3d3..b27dbf3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
@@ -44,12 +44,12 @@ import javax.annotation.Nullable;
  * {@link java.util.Collection} contract, which is specified in terms of {@link Object#equals}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Louis Wasserman
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements Serializable {
@@ -149,6 +149,7 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
         return (root == null) ? 0 : root.distinctElements;
       }
     };
+
     abstract int nodeAggregate(AvlNode<?> node);
 
     abstract long treeAggregate(@Nullable AvlNode<?> root);
@@ -183,7 +184,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
           throw new AssertionError();
       }
     } else {
-      return aggr.treeAggregate(node.left) + aggr.nodeAggregate(node)
+      return aggr.treeAggregate(node.left)
+          + aggr.nodeAggregate(node)
           + aggregateBelowRange(aggr, node.right);
     }
   }
@@ -205,7 +207,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
           throw new AssertionError();
       }
     } else {
-      return aggr.treeAggregate(node.right) + aggr.nodeAggregate(node)
+      return aggr.treeAggregate(node.right)
+          + aggr.nodeAggregate(node)
           + aggregateAboveRange(aggr, node.left);
     }
   }
@@ -349,7 +352,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
   /**
    * Returns the first node in the tree that is in range.
    */
-  @Nullable private AvlNode<E> firstNode() {
+  @Nullable
+  private AvlNode<E> firstNode() {
     AvlNode<E> root = rootReference.get();
     if (root == null) {
       return null;
@@ -371,7 +375,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
     return (node == header || !range.contains(node.getElement())) ? null : node;
   }
 
-  @Nullable private AvlNode<E> lastNode() {
+  @Nullable
+  private AvlNode<E> lastNode() {
     AvlNode<E> root = rootReference.get();
     if (root == null) {
       return null;
@@ -479,18 +484,18 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
 
   @Override
   public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) {
-    return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.upTo(
-        comparator(),
-        upperBound,
-        boundType)), header);
+    return new TreeMultiset<E>(
+        rootReference,
+        range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)),
+        header);
   }
 
   @Override
   public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
-    return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.downTo(
-        comparator(),
-        lowerBound,
-        boundType)), header);
+    return new TreeMultiset<E>(
+        rootReference,
+        range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
+        header);
   }
 
   static int distinctElements(@Nullable AvlNode<?> node) {
@@ -500,7 +505,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
   private static final class Reference<T> {
     @Nullable private T value;
 
-    @Nullable public T get() {
+    @Nullable
+    public T get() {
       return value;
     }
 
@@ -824,8 +830,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
     }
 
     private void recomputeMultiset() {
-      this.distinctElements = 1 + TreeMultiset.distinctElements(left)
-          + TreeMultiset.distinctElements(right);
+      this.distinctElements =
+          1 + TreeMultiset.distinctElements(left) + TreeMultiset.distinctElements(right);
       this.totalCount = elemCount + totalCount(left) + totalCount(right);
     }
 
@@ -892,7 +898,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
       return (node == null) ? 0 : node.height;
     }
 
-    @Nullable private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
+    @Nullable
+    private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
       int cmp = comparator.compare(e, elem);
       if (cmp < 0) {
         return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
@@ -903,7 +910,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
       }
     }
 
-    @Nullable private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
+    @Nullable
+    private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
       int cmp = comparator.compare(e, elem);
       if (cmp > 0) {
         return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
diff --git a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
index ea083b6..1bcf0c7 100644
--- a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
+++ b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
@@ -18,8 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkPositionIndexes;
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.io.GwtWorkarounds.asCharInput;
-import static com.google.common.io.GwtWorkarounds.stringBuilderOutput;
 import static com.google.common.math.IntMath.divide;
 import static com.google.common.math.IntMath.log2;
 import static java.math.RoundingMode.CEILING;
@@ -30,10 +28,6 @@ import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Ascii;
 import com.google.common.base.CharMatcher;
-import com.google.common.io.GwtWorkarounds.ByteInput;
-import com.google.common.io.GwtWorkarounds.ByteOutput;
-import com.google.common.io.GwtWorkarounds.CharInput;
-import com.google.common.io.GwtWorkarounds.CharOutput;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -123,7 +117,7 @@ import javax.annotation.Nullable;
 @Beta
 @GwtCompatible(emulated = true)
 public abstract class BaseEncoding {
-  // TODO(user): consider adding encodeTo(Appendable, byte[], [int, int])
+  // TODO(lowasser): consider making encodeTo(Appendable, byte[], int, int) public.
 
   BaseEncoding() {}
 
@@ -147,7 +141,7 @@ public abstract class BaseEncoding {
    * Encodes the specified byte array, and returns the encoded {@code String}.
    */
   public String encode(byte[] bytes) {
-    return encode(checkNotNull(bytes), 0, bytes.length);
+    return encode(bytes, 0, bytes.length);
   }
 
   /**
@@ -155,22 +149,17 @@ public abstract class BaseEncoding {
    * {@code String}.
    */
   public final String encode(byte[] bytes, int off, int len) {
-    checkNotNull(bytes);
     checkPositionIndexes(off, off + len, bytes.length);
-    CharOutput result = stringBuilderOutput(maxEncodedSize(len));
-    ByteOutput byteOutput = encodingStream(result);
+    StringBuilder result = new StringBuilder(maxEncodedSize(len));
     try {
-      for (int i = 0; i < len; i++) {
-        byteOutput.write(bytes[off + i]);
-      }
-      byteOutput.close();
+      encodeTo(result, bytes, off, len);
     } catch (IOException impossible) {
-      throw new AssertionError("impossible");
+      throw new AssertionError(impossible);
     }
     return result.toString();
   }
 
-  // TODO(user): document the extent of leniency, probably after adding ignore(CharMatcher)
+  // TODO(lowasser): document the extent of leniency, probably after adding ignore(CharMatcher)
 
   private static byte[] extract(byte[] result, int length) {
     if (length == result.length) {
@@ -206,30 +195,20 @@ public abstract class BaseEncoding {
    */
   final byte[] decodeChecked(CharSequence chars) throws DecodingException {
     chars = padding().trimTrailingFrom(chars);
-    ByteInput decodedInput = decodingStream(asCharInput(chars));
     byte[] tmp = new byte[maxDecodedSize(chars.length())];
-    int index = 0;
-    try {
-      for (int i = decodedInput.read(); i != -1; i = decodedInput.read()) {
-        tmp[index++] = (byte) i;
-      }
-    } catch (DecodingException badInput) {
-      throw badInput;
-    } catch (IOException impossible) {
-      throw new AssertionError(impossible);
-    }
-    return extract(tmp, index);
+    int len = decodeTo(tmp, chars);
+    return extract(tmp, len);
   }
 
   // Implementations for encoding/decoding
 
   abstract int maxEncodedSize(int bytes);
 
-  abstract ByteOutput encodingStream(CharOutput charOutput);
+  abstract void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException;
 
   abstract int maxDecodedSize(int chars);
 
-  abstract ByteInput decodingStream(CharInput charInput);
+  abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException;
 
   abstract CharMatcher padding();
 
@@ -285,7 +264,7 @@ public abstract class BaseEncoding {
   @CheckReturnValue
   public abstract BaseEncoding lowerCase();
 
-  private static final BaseEncoding BASE64 = new StandardBaseEncoding(
+  private static final BaseEncoding BASE64 = new Base64Encoding(
       "base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", '=');
 
   /**
@@ -305,7 +284,7 @@ public abstract class BaseEncoding {
     return BASE64;
   }
 
-  private static final BaseEncoding BASE64_URL = new StandardBaseEncoding(
+  private static final BaseEncoding BASE64_URL = new Base64Encoding(
       "base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", '=');
 
   /**
@@ -365,8 +344,7 @@ public abstract class BaseEncoding {
     return BASE32_HEX;
   }
 
-  private static final BaseEncoding BASE16 =
-      new StandardBaseEncoding("base16()", "0123456789ABCDEF", null);
+  private static final BaseEncoding BASE16 = new Base16Encoding("base16()", "0123456789ABCDEF");
 
   /**
    * The "base16" encoding specified by <a
@@ -441,9 +419,10 @@ public abstract class BaseEncoding {
       return validPadding[index % charsPerChunk];
     }
 
-    int decode(char ch) throws IOException {
+    int decode(char ch) throws DecodingException {
       if (ch > Ascii.MAX || decodabet[ch] == -1) {
-        throw new DecodingException("Unrecognized character: " + ch);
+        throw new DecodingException("Unrecognized character: "
+            + (CharMatcher.INVISIBLE.matches(ch) ? "0x" + Integer.toHexString(ch) : ch));
       }
       return decodabet[ch];
     }
@@ -503,12 +482,12 @@ public abstract class BaseEncoding {
     }
   }
 
-  static final class StandardBaseEncoding extends BaseEncoding {
-    // TODO(user): provide a useful toString
-    private final Alphabet alphabet;
+  static class StandardBaseEncoding extends BaseEncoding {
+    // TODO(lowasser): provide a useful toString
+    final Alphabet alphabet;
 
     @Nullable
-    private final Character paddingChar;
+    final Character paddingChar;
 
     StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) {
       this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
@@ -532,49 +511,38 @@ public abstract class BaseEncoding {
     }
 
     @Override
-    ByteOutput encodingStream(final CharOutput out) {
-      checkNotNull(out);
-      return new ByteOutput() {
-        int bitBuffer = 0;
-        int bitBufferLength = 0;
-        int writtenChars = 0;
-
-        @Override
-        public void write(byte b) throws IOException {
-          bitBuffer <<= 8;
-          bitBuffer |= b & 0xFF;
-          bitBufferLength += 8;
-          while (bitBufferLength >= alphabet.bitsPerChar) {
-            int charIndex = (bitBuffer >> (bitBufferLength - alphabet.bitsPerChar))
-                & alphabet.mask;
-            out.write(alphabet.encode(charIndex));
-            writtenChars++;
-            bitBufferLength -= alphabet.bitsPerChar;
-          }
-        }
-
-        @Override
-        public void flush() throws IOException {
-          out.flush();
-        }
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      for (int i = 0; i < len; i += alphabet.bytesPerChunk) {
+        encodeChunkTo(target, bytes, off + i, Math.min(alphabet.bytesPerChunk, len - i));
+      }
+    }
 
-        @Override
-        public void close() throws IOException {
-          if (bitBufferLength > 0) {
-            int charIndex = (bitBuffer << (alphabet.bitsPerChar - bitBufferLength))
-                & alphabet.mask;
-            out.write(alphabet.encode(charIndex));
-            writtenChars++;
-            if (paddingChar != null) {
-              while (writtenChars % alphabet.charsPerChunk != 0) {
-                out.write(paddingChar.charValue());
-                writtenChars++;
-              }
-            }
-          }
-          out.close();
+    void encodeChunkTo(Appendable target, byte[] bytes, int off, int len)
+        throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      checkArgument(len <= alphabet.bytesPerChunk);
+      long bitBuffer = 0;
+      for (int i = 0; i < len; ++i) {
+        bitBuffer |= bytes[off + i] & 0xFF;
+        bitBuffer <<= 8; // Add additional zero byte in the end.
+      }
+      // Position of first character is length of bitBuffer minus bitsPerChar.
+      final int bitOffset = (len + 1) * 8 - alphabet.bitsPerChar;
+      int bitsProcessed = 0;
+      while (bitsProcessed < len * 8) {
+        int charIndex = (int) (bitBuffer >>> (bitOffset - bitsProcessed)) & alphabet.mask;
+        target.append(alphabet.encode(charIndex));
+        bitsProcessed += alphabet.bitsPerChar;
+      }
+      if (paddingChar != null) {
+        while (bitsProcessed < alphabet.bytesPerChunk * 8) {
+          target.append(paddingChar.charValue());
+          bitsProcessed += alphabet.bitsPerChar;
         }
-      };
+      }
     }
 
     @Override
@@ -583,59 +551,33 @@ public abstract class BaseEncoding {
     }
 
     @Override
-    ByteInput decodingStream(final CharInput reader) {
-      checkNotNull(reader);
-      return new ByteInput() {
-        int bitBuffer = 0;
-        int bitBufferLength = 0;
-        int readChars = 0;
-        boolean hitPadding = false;
-        final CharMatcher paddingMatcher = padding();
-
-        @Override
-        public int read() throws IOException {
-          while (true) {
-            int readChar = reader.read();
-            if (readChar == -1) {
-              if (!hitPadding && !alphabet.isValidPaddingStartPosition(readChars)) {
-                throw new DecodingException("Invalid input length " + readChars);
-              }
-              return -1;
-            }
-            readChars++;
-            char ch = (char) readChar;
-            if (paddingMatcher.matches(ch)) {
-              if (!hitPadding
-                  && (readChars == 1 || !alphabet.isValidPaddingStartPosition(readChars - 1))) {
-                throw new DecodingException("Padding cannot start at index " + readChars);
-              }
-              hitPadding = true;
-            } else if (hitPadding) {
-              throw new DecodingException(
-                  "Expected padding character but found '" + ch + "' at index " + readChars);
-            } else {
-              bitBuffer <<= alphabet.bitsPerChar;
-              bitBuffer |= alphabet.decode(ch);
-              bitBufferLength += alphabet.bitsPerChar;
-
-              if (bitBufferLength >= 8) {
-                bitBufferLength -= 8;
-                return (bitBuffer >> bitBufferLength) & 0xFF;
-              }
-            }
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      chars = padding().trimTrailingFrom(chars);
+      if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int charIdx = 0; charIdx < chars.length(); charIdx += alphabet.charsPerChunk) {
+        long chunk = 0;
+        int charsProcessed = 0;
+        for (int i = 0; i < alphabet.charsPerChunk; i++) {
+          chunk <<= alphabet.bitsPerChar;
+          if (charIdx + i < chars.length()) {
+            chunk |= alphabet.decode(chars.charAt(charIdx + charsProcessed++));
           }
         }
-
-        @Override
-        public void close() throws IOException {
-          reader.close();
+        final int minOffset = alphabet.bytesPerChunk * 8 - charsProcessed * alphabet.bitsPerChar;
+        for (int offset = (alphabet.bytesPerChunk - 1) * 8; offset >= minOffset; offset -= 8) {
+          target[bytesWritten++] = (byte) ((chunk >>> offset) & 0xFF);
         }
-      };
+      }
+      return bytesWritten;
     }
 
     @Override
     public BaseEncoding omitPadding() {
-      return (paddingChar == null) ? this : new StandardBaseEncoding(alphabet, null);
+      return (paddingChar == null) ? this : newInstance(alphabet, null);
     }
 
     @Override
@@ -644,15 +586,14 @@ public abstract class BaseEncoding {
           (paddingChar != null && paddingChar.charValue() == padChar)) {
         return this;
       } else {
-        return new StandardBaseEncoding(alphabet, padChar);
+        return newInstance(alphabet, padChar);
       }
     }
 
     @Override
     public BaseEncoding withSeparator(String separator, int afterEveryChars) {
-      checkNotNull(separator);
       checkArgument(padding().or(alphabet).matchesNoneOf(separator),
-          "Separator cannot contain alphabet or padding characters");
+          "Separator (%s) cannot contain alphabet or padding characters", separator);
       return new SeparatedBaseEncoding(this, separator, afterEveryChars);
     }
 
@@ -665,7 +606,7 @@ public abstract class BaseEncoding {
       if (result == null) {
         Alphabet upper = alphabet.upperCase();
         result = upperCase =
-            (upper == alphabet) ? this : new StandardBaseEncoding(upper, paddingChar);
+            (upper == alphabet) ? this : newInstance(upper, paddingChar);
       }
       return result;
     }
@@ -676,11 +617,15 @@ public abstract class BaseEncoding {
       if (result == null) {
         Alphabet lower = alphabet.lowerCase();
         result = lowerCase =
-            (lower == alphabet) ? this : new StandardBaseEncoding(lower, paddingChar);
+            (lower == alphabet) ? this : newInstance(lower, paddingChar);
       }
       return result;
     }
 
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new StandardBaseEncoding(alphabet, paddingChar);
+    }
+
     @Override
     public String toString() {
       StringBuilder builder = new StringBuilder("BaseEncoding.");
@@ -696,54 +641,137 @@ public abstract class BaseEncoding {
     }
   }
 
-  static CharInput ignoringInput(final CharInput delegate, final CharMatcher toIgnore) {
-    checkNotNull(delegate);
-    checkNotNull(toIgnore);
-    return new CharInput() {
-      @Override
-      public int read() throws IOException {
-        int readChar;
-        do {
-          readChar = delegate.read();
-        } while (readChar != -1 && toIgnore.matches((char) readChar));
-        return readChar;
+  static final class Base16Encoding extends StandardBaseEncoding {
+    final char[] encoding = new char[512];
+
+    Base16Encoding(String name, String alphabetChars) {
+      this(new Alphabet(name, alphabetChars.toCharArray()));
+    }
+
+    private Base16Encoding(Alphabet alphabet) {
+      super(alphabet, null);
+      checkArgument(alphabet.chars.length == 16);
+      for (int i = 0; i < 256; ++i) {
+        encoding[i] = alphabet.encode(i >>> 4);
+        encoding[i | 0x100] = alphabet.encode(i & 0xF);
       }
+    }
 
-      @Override
-      public void close() throws IOException {
-        delegate.close();
+    @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      for (int i = 0; i < len; ++i) {
+        int b = bytes[off + i] & 0xFF;
+        target.append(encoding[b]);
+        target.append(encoding[b | 0x100]);
       }
-    };
+    }
+
+    @Override
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      if (chars.length() % 2 == 1) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int i = 0; i < chars.length(); i += 2) {
+        int decoded = alphabet.decode(chars.charAt(i)) << 4 | alphabet.decode(chars.charAt(i + 1));
+        target[bytesWritten++] = (byte) decoded;
+      }
+      return bytesWritten;
+    }
+
+    @Override
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new Base16Encoding(alphabet);
+    }
+  }
+
+  static final class Base64Encoding extends StandardBaseEncoding {
+    Base64Encoding(String name, String alphabetChars, @Nullable Character paddingChar) {
+      this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
+    }
+
+    private Base64Encoding(Alphabet alphabet, @Nullable Character paddingChar) {
+      super(alphabet, paddingChar);
+      checkArgument(alphabet.chars.length == 64);
+    }
+
+    @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      int i = off;
+      for (int remaining = len; remaining >= 3; remaining -= 3) {
+        int chunk = (bytes[i++] & 0xFF) << 16 | (bytes[i++] & 0xFF) << 8 | bytes[i++] & 0xFF;
+        target.append(alphabet.encode(chunk >>> 18));
+        target.append(alphabet.encode((chunk >>> 12) & 0x3F));
+        target.append(alphabet.encode((chunk >>> 6) & 0x3F));
+        target.append(alphabet.encode(chunk & 0x3F));
+      }
+      if (i < off + len) {
+        encodeChunkTo(target, bytes, i, off + len - i);
+      }
+    }
+
+    @Override
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      chars = padding().trimTrailingFrom(chars);
+      if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int i = 0; i < chars.length();) {
+        int chunk = alphabet.decode(chars.charAt(i++)) << 18;
+        chunk |= alphabet.decode(chars.charAt(i++)) << 12;
+        target[bytesWritten++] = (byte) (chunk >>> 16);
+        if (i < chars.length()) {
+          chunk |= alphabet.decode(chars.charAt(i++)) << 6;
+          target[bytesWritten++] = (byte) ((chunk >>> 8) & 0xFF);
+          if (i < chars.length()) {
+            chunk |= alphabet.decode(chars.charAt(i++));
+            target[bytesWritten++] = (byte) (chunk & 0xFF);
+          }
+        }
+      }
+      return bytesWritten;
+    }
+
+    @Override
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new Base64Encoding(alphabet, paddingChar);
+    }
   }
 
-  static CharOutput separatingOutput(
-      final CharOutput delegate, final String separator, final int afterEveryChars) {
+  static Appendable separatingAppendable(
+      final Appendable delegate, final String separator, final int afterEveryChars) {
     checkNotNull(delegate);
     checkNotNull(separator);
     checkArgument(afterEveryChars > 0);
-    return new CharOutput() {
+    return new Appendable() {
       int charsUntilSeparator = afterEveryChars;
 
       @Override
-      public void write(char c) throws IOException {
+      public Appendable append(char c) throws IOException {
         if (charsUntilSeparator == 0) {
-          for (int i = 0; i < separator.length(); i++) {
-            delegate.write(separator.charAt(i));
-          }
+          delegate.append(separator);
           charsUntilSeparator = afterEveryChars;
         }
-        delegate.write(c);
+        delegate.append(c);
         charsUntilSeparator--;
+        return this;
       }
 
       @Override
-      public void flush() throws IOException {
-        delegate.flush();
+      public Appendable append(CharSequence chars, int off, int len) throws IOException {
+        throw new UnsupportedOperationException();
       }
 
       @Override
-      public void close() throws IOException {
-        delegate.close();
+      public Appendable append(CharSequence chars) throws IOException {
+        throw new UnsupportedOperationException();
       }
     };
   }
@@ -776,8 +804,8 @@ public abstract class BaseEncoding {
     }
 
     @Override
-    ByteOutput encodingStream(final CharOutput output) {
-      return delegate.encodingStream(separatingOutput(output, separator, afterEveryChars));
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      delegate.encodeTo(separatingAppendable(target, separator, afterEveryChars), bytes, off, len);
     }
 
     @Override
@@ -786,8 +814,8 @@ public abstract class BaseEncoding {
     }
 
     @Override
-    ByteInput decodingStream(final CharInput input) {
-      return delegate.decodingStream(ignoringInput(input, separatorChars));
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      return delegate.decodeTo(target, separatorChars.removeFrom(chars));
     }
 
     @Override
diff --git a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java
deleted file mode 100644
index f3f955e..0000000
--- a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.io;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.GwtCompatible;
-
-import java.io.IOException;
-
-/**
- * Provides simple GWT-compatible substitutes for {@code InputStream}, {@code OutputStream},
- * {@code Reader}, and {@code Writer} so that {@code BaseEncoding} can use streaming implementations
- * while remaining GWT-compatible.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
-final class GwtWorkarounds {
-  private GwtWorkarounds() {}
-
-  /**
-   * A GWT-compatible substitute for a {@code Reader}.
-   */
-  interface CharInput {
-    int read() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Views a {@code CharSequence} as a {@code CharInput}.
-   */
-  static CharInput asCharInput(final CharSequence chars) {
-    checkNotNull(chars);
-    return new CharInput() {
-      int index = 0;
-
-      @Override
-      public int read() {
-        if (index < chars.length()) {
-          return chars.charAt(index++);
-        } else {
-          return -1;
-        }
-      }
-
-      @Override
-      public void close() {
-        index = chars.length();
-      }
-    };
-  }
-
-  /**
-   * A GWT-compatible substitute for an {@code InputStream}.
-   */
-  interface ByteInput {
-    int read() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * A GWT-compatible substitute for an {@code OutputStream}.
-   */
-  interface ByteOutput {
-    void write(byte b) throws IOException;
-    void flush() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * A GWT-compatible substitute for a {@code Writer}.
-   */
-  interface CharOutput {
-    void write(char c) throws IOException;
-    void flush() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Returns a {@code CharOutput} whose {@code toString()} method can be used
-   * to get the combined output.
-   */
-  static CharOutput stringBuilderOutput(int initialSize) {
-    final StringBuilder builder = new StringBuilder(initialSize);
-    return new CharOutput() {
-
-      @Override
-      public void write(char c) {
-        builder.append(c);
-      }
-
-      @Override
-      public void flush() {}
-
-      @Override
-      public void close() {}
-
-      @Override
-      public String toString() {
-        return builder.toString();
-      }
-    };
-  }
-}
-
diff --git a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
index 2574322..2d18344 100644
--- a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
+++ b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
@@ -16,6 +16,7 @@
 
 package com.google.common.math;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.math.MathPreconditions.checkNonNegative;
 import static java.lang.Math.log;
 
@@ -168,6 +169,51 @@ public final class DoubleMath {
     }
   }
 
+  /**
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values
+   * @throws IllegalArgumentException if {@code values} is empty
+   */
+  public static double mean(int... values) {
+    checkArgument(values.length > 0, "Cannot take mean of 0 values");
+    // The upper bound on the the length of an array and the bounds on the int values mean that, in
+    // this case only, we can compute the sum as a long without risking overflow or loss of
+    // precision. So we do that, as it's slightly quicker than the Knuth algorithm.
+    long sum = 0;
+    for (int index = 0; index < values.length; ++index) {
+      sum += values[index];
+    }
+    return (double) sum / values.length;
+  }
+
+  /**
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values, which will be converted to {@code double} values
+   *     (this may cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
+   * @throws IllegalArgumentException if {@code values} is empty
+   */
+  public static double mean(long... values) {
+    checkArgument(values.length > 0, "Cannot take mean of 0 values");
+    long count = 1;
+    double mean = values[0];
+    for (int index = 1; index < values.length; ++index) {
+      count++;
+      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+      mean += (values[index] - mean) / count;
+    }
+    return mean;
+  }
+
   private DoubleMath() {}
 }
 
diff --git a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
index a210627..5a617da 100644
--- a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
+++ b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
@@ -26,6 +26,7 @@ import static java.math.RoundingMode.HALF_UP;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLongs;
 
 import java.math.RoundingMode;
 
@@ -56,7 +57,7 @@ public final class LongMath {
   public static boolean isPowerOfTwo(long x) {
     return x > 0 & (x & (x - 1)) == 0;
   }
-
+  
   /**
    * Returns 1 if {@code x < y} as unsigned longs, and 0 otherwise.  Assumes that x - y fits into a
    * signed long.  The implementation is branch-free, and benchmarks suggest it is measurably
@@ -227,14 +228,14 @@ public final class LongMath {
           return result;
         } else {
           int nBits = LongMath.log2(n, RoundingMode.CEILING);
-
+          
           long result = 1;
           long numerator = n--;
           long denominator = 1;
-
+          
           int numeratorBits = nBits;
           // This is an upper bound on log2(numerator, ceiling).
-
+          
           /*
            * We want to do this in long math for speed, but want to avoid overflow. We adapt the
            * technique previously used by BigIntegerMath: maintain separate numerator and
@@ -259,7 +260,7 @@ public final class LongMath {
         }
     }
   }
-
+  
   /**
    * Returns (x * numerator / denominator), which is assumed to come out to an integral value.
    */
@@ -311,6 +312,190 @@ public final class LongMath {
     // The alternative (x + y) >>> 1 fails for negative values.
     return (x & y) + ((x ^ y) >> 1);
   }
+  
+  /*
+   * If n <= millerRabinBases[i][0], then testing n against bases millerRabinBases[i][1..]
+   * suffices to prove its primality.  Values from miller-rabin.appspot.com.
+   * 
+   * NOTE: We could get slightly better bases that would be treated as unsigned, but benchmarks
+   * showed negligible performance improvements.
+   */
+  private static final long[][] millerRabinBaseSets = {
+    {291830, 126401071349994536L},
+    {885594168, 725270293939359937L, 3569819667048198375L},
+    {273919523040L, 15, 7363882082L, 992620450144556L},
+    {47636622961200L, 2, 2570940, 211991001, 3749873356L},
+    {7999252175582850L,
+      2, 4130806001517L, 149795463772692060L, 186635894390467037L, 3967304179347715805L},
+    {585226005592931976L,
+      2, 123635709730000L, 9233062284813009L, 43835965440333360L, 761179012939631437L,
+      1263739024124850375L},
+    {Long.MAX_VALUE,
+        2, 325, 9375, 28178, 450775, 9780504, 1795265022}
+  };
+  
+  private enum MillerRabinTester {
+    /**
+     * Works for inputs <= FLOOR_SQRT_MAX_LONG.
+     */
+    SMALL {
+      @Override
+      long mulMod(long a, long b, long m) {
+        /* 
+         * NOTE(lowasser, 2015-Feb-12): Benchmarks suggest that changing this to 
+         * UnsignedLongs.remainder and increasing the threshold to 2^32 doesn't pay for itself,
+         * and adding another enum constant hurts performance further -- I suspect because
+         * bimorphic implementation is a sweet spot for the JVM.
+         */ 
+        return (a * b) % m;
+      }
+      
+      @Override
+      long squareMod(long a, long m) {
+        return (a * a) % m;
+      }
+    },
+    /**
+     * Works for all nonnegative signed longs.
+     */
+    LARGE {
+      /**
+       * Returns (a + b) mod m.  Precondition: 0 <= a, b < m < 2^63.
+       */
+      private long plusMod(long a, long b, long m) {
+        return (a >= m - b) ? (a + b - m) : (a + b);
+      }
+
+      /**
+       * Returns (a * 2^32) mod m.  a may be any unsigned long.
+       */
+      private long times2ToThe32Mod(long a, long m) {
+        int remainingPowersOf2 = 32;
+        do {
+          int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a));
+          // shift is either the number of powers of 2 left to multiply a by, or the biggest shift
+          // possible while keeping a in an unsigned long.
+          a = UnsignedLongs.remainder(a << shift, m);
+          remainingPowersOf2 -= shift;
+        } while (remainingPowersOf2 > 0);
+        return a;
+      }
+
+      @Override
+      long mulMod(long a, long b, long m) {
+        long aHi = a >>> 32; // < 2^31
+        long bHi = b >>> 32; // < 2^31
+        long aLo = a & 0xFFFFFFFFL; // < 2^32
+        long bLo = b & 0xFFFFFFFFL; // < 2^32
+        
+        /*
+         * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^63 + aLo * bLo.
+         *       == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo
+         * 
+         * We carry out this computation in modular arithmetic.  Since times2ToThe32Mod accepts
+         * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+         * results can exceed 2^63.
+         */
+        long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63
+        result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64
+        if (result < 0) {
+          result = UnsignedLongs.remainder(result, m);
+        }
+        // result < 2^63 again
+        result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64
+        result = times2ToThe32Mod(result, m); // result < m < 2^63
+        return plusMod(
+            result,
+            UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m),
+            m);
+      }
+
+      @Override
+      long squareMod(long a, long m) {
+        long aHi = a >>> 32; // < 2^31
+        long aLo = a & 0xFFFFFFFFL; // < 2^32
+        
+        /*
+         * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2
+         *     == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2
+         * We carry out this computation in modular arithmetic.  Since times2ToThe32Mod accepts
+         * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+         * results can exceed 2^63.  
+         */
+        long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63
+        long hiLo = aHi * aLo * 2;
+        if (hiLo < 0) {
+          hiLo = UnsignedLongs.remainder(hiLo, m);
+        }
+        // hiLo < 2^63
+        result += hiLo; // result < 2^64
+        result = times2ToThe32Mod(result, m); // result < m < 2^63
+        return plusMod(
+            result,
+            UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m),
+            m);
+      }
+    };
+    
+    static boolean test(long base, long n) {
+      // Since base will be considered % n, it's okay if base > FLOOR_SQRT_MAX_LONG,
+      // so long as n <= FLOOR_SQRT_MAX_LONG.
+      return ((n <= FLOOR_SQRT_MAX_LONG) ? SMALL : LARGE).testWitness(base, n);
+    }
+    
+    /**
+     * Returns a * b mod m.
+     */
+    abstract long mulMod(long a, long b, long m);
+    
+    /**
+     * Returns a^2 mod m.
+     */
+    abstract long squareMod(long a, long m);
+    
+    /**
+     * Returns a^p mod m.
+     */
+    private long powMod(long a, long p, long m) {
+      long res = 1;
+      for (; p != 0; p >>= 1) {
+        if ((p & 1) != 0) {
+          res = mulMod(res, a, m);
+        }
+        a = squareMod(a, m);
+      }
+      return res;
+    }
+    
+    /**
+     * Returns true if n is a strong probable prime relative to the specified base.
+     */
+    private boolean testWitness(long base, long n) {
+      int r = Long.numberOfTrailingZeros(n - 1);
+      long d = (n - 1) >> r;
+      base %= n;
+      if (base == 0) {
+        return true;
+      }
+      // Calculate a := base^d mod n.
+      long a = powMod(base, d, n);
+      // n passes this test if
+      //    base^d = 1 (mod n)
+      // or base^(2^j * d) = -1 (mod n) for some 0 <= j < r.
+      if (a == 1) {
+        return true;
+      }
+      int j = 0;
+      while (a != n - 1) {
+        if (++j == r) {
+          return false;
+        }
+        a = squareMod(a, n);
+      }
+      return true;
+    }
+  }
 
   private LongMath() {}
 }
+
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
index c167373..df84c50 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
@@ -31,6 +31,9 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code char} primitives, that are not
  * already found in either {@link Character} or {@link Arrays}.
@@ -39,12 +42,13 @@ import java.util.RandomAccess;
  * numerically; they are neither Unicode-aware nor locale-dependent.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Chars {
   private Chars() {}
@@ -149,8 +153,7 @@ public final class Chars {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      char[] array, char target, int start, int end) {
+  private static int indexOf(char[] array, char target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -203,8 +206,7 @@ public final class Chars {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      char[] array, char target, int start, int end) {
+  private static int lastIndexOf(char[] array, char target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -290,8 +292,7 @@ public final class Chars {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static char[] ensureCapacity(
-      char[] array, int minLength, int padding) {
+  public static char[] ensureCapacity(char[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -322,8 +323,7 @@ public final class Chars {
       return "";
     }
 
-    StringBuilder builder
-        = new StringBuilder(len + separator.length() * (len - 1));
+    StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
     builder.append(array[0]);
     for (int i = 1; i < len; i++) {
       builder.append(separator).append(array[i]);
@@ -434,26 +434,31 @@ public final class Chars {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
       return (target instanceof Character)
           && Chars.indexOf(array, (Character) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Character) {
         int i = Chars.indexOf(array, (Character) target, start, end);
@@ -464,7 +469,8 @@ public final class Chars {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Character) {
         int i = Chars.lastIndexOf(array, (Character) target, start, end);
@@ -475,7 +481,8 @@ public final class Chars {
       return -1;
     }
 
-    @Override public Character set(int index, Character element) {
+    @Override
+    public Character set(int index, Character element) {
       checkElementIndex(index, size());
       char oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -483,7 +490,8 @@ public final class Chars {
       return oldValue;
     }
 
-    @Override public List<Character> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Character> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -492,7 +500,8 @@ public final class Chars {
       return new CharArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -512,7 +521,8 @@ public final class Chars {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Chars.hashCode(array[i]);
@@ -520,7 +530,8 @@ public final class Chars {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 3);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
index 0b7bb63..6117678 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
@@ -35,17 +35,21 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code double} primitives, that are not
  * already found in either {@link Double} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Doubles {
   private Doubles() {}
@@ -136,8 +140,7 @@ public final class Doubles {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      double[] array, double target, int start, int end) {
+  private static int indexOf(double[] array, double target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -194,8 +197,7 @@ public final class Doubles {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      double[] array, double target, int start, int end) {
+  private static int lastIndexOf(double[] array, double target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -263,8 +265,8 @@ public final class Doubles {
     return result;
   }
 
-  private static final class DoubleConverter
-      extends Converter<String, Double> implements Serializable {
+  private static final class DoubleConverter extends Converter<String, Double>
+      implements Serializable {
     static final DoubleConverter INSTANCE = new DoubleConverter();
 
     @Override
@@ -285,6 +287,7 @@ public final class Doubles {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -315,8 +318,7 @@ public final class Doubles {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static double[] ensureCapacity(
-      double[] array, int minLength, int padding) {
+  public static double[] ensureCapacity(double[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -467,26 +469,31 @@ public final class Doubles {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Double get(int index) {
+    @Override
+    public Double get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
       return (target instanceof Double)
           && Doubles.indexOf(array, (Double) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Double) {
         int i = Doubles.indexOf(array, (Double) target, start, end);
@@ -497,7 +504,8 @@ public final class Doubles {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Double) {
         int i = Doubles.lastIndexOf(array, (Double) target, start, end);
@@ -508,7 +516,8 @@ public final class Doubles {
       return -1;
     }
 
-    @Override public Double set(int index, Double element) {
+    @Override
+    public Double set(int index, Double element) {
       checkElementIndex(index, size());
       double oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -516,7 +525,8 @@ public final class Doubles {
       return oldValue;
     }
 
-    @Override public List<Double> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Double> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -525,7 +535,8 @@ public final class Doubles {
       return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -545,7 +556,8 @@ public final class Doubles {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Doubles.hashCode(array[i]);
@@ -553,7 +565,8 @@ public final class Doubles {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 12);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
index d669e50..4234d38 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
@@ -35,17 +35,21 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code float} primitives, that are not
  * already found in either {@link Float} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Floats {
   private Floats() {}
@@ -133,8 +137,7 @@ public final class Floats {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      float[] array, float target, int start, int end) {
+  private static int indexOf(float[] array, float target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -191,8 +194,7 @@ public final class Floats {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      float[] array, float target, int start, int end) {
+  private static int lastIndexOf(float[] array, float target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -221,7 +223,7 @@ public final class Floats {
 
   /**
    * Returns the greatest value present in {@code array}, using the same rules
-   * of comparison as {@link Math#min(float, float)}.
+   * of comparison as {@link Math#max(float, float)}.
    *
    * @param array a <i>nonempty</i> array of {@code float} values
    * @return the value present in {@code array} that is greater than or equal to
@@ -260,8 +262,8 @@ public final class Floats {
     return result;
   }
 
-  private static final class FloatConverter
-      extends Converter<String, Float> implements Serializable {
+  private static final class FloatConverter extends Converter<String, Float>
+      implements Serializable {
     static final FloatConverter INSTANCE = new FloatConverter();
 
     @Override
@@ -282,6 +284,7 @@ public final class Floats {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -312,8 +315,7 @@ public final class Floats {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static float[] ensureCapacity(
-      float[] array, int minLength, int padding) {
+  public static float[] ensureCapacity(float[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -464,26 +466,30 @@ public final class Floats {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Float get(int index) {
+    @Override
+    public Float get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Float)
-          && Floats.indexOf(array, (Float) target, start, end) != -1;
+      return (target instanceof Float) && Floats.indexOf(array, (Float) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Float) {
         int i = Floats.indexOf(array, (Float) target, start, end);
@@ -494,7 +500,8 @@ public final class Floats {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Float) {
         int i = Floats.lastIndexOf(array, (Float) target, start, end);
@@ -505,7 +512,8 @@ public final class Floats {
       return -1;
     }
 
-    @Override public Float set(int index, Float element) {
+    @Override
+    public Float set(int index, Float element) {
       checkElementIndex(index, size());
       float oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -513,7 +521,8 @@ public final class Floats {
       return oldValue;
     }
 
-    @Override public List<Float> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Float> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -522,7 +531,8 @@ public final class Floats {
       return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -542,7 +552,8 @@ public final class Floats {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Floats.hashCode(array[i]);
@@ -550,7 +561,8 @@ public final class Floats {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 12);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
index eb14ea5..6938ae9 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
@@ -27,7 +27,6 @@ import com.google.common.base.Converter;
 
 import java.io.Serializable;
 import java.util.AbstractList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -35,18 +34,21 @@ import java.util.List;
 import java.util.RandomAccess;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
 
 /**
  * Static utility methods pertaining to {@code int} primitives, that are not
  * already found in either {@link Integer} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Ints {
   private Ints() {}
@@ -158,8 +160,7 @@ public final class Ints {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      int[] array, int target, int start, int end) {
+  private static int indexOf(int[] array, int target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -212,8 +213,7 @@ public final class Ints {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      int[] array, int target, int start, int end) {
+  private static int lastIndexOf(int[] array, int target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -283,8 +283,8 @@ public final class Ints {
     return result;
   }
 
-  private static final class IntConverter
-      extends Converter<String, Integer> implements Serializable {
+  private static final class IntConverter extends Converter<String, Integer>
+      implements Serializable {
     static final IntConverter INSTANCE = new IntConverter();
 
     @Override
@@ -305,6 +305,7 @@ public final class Ints {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -335,8 +336,7 @@ public final class Ints {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static int[] ensureCapacity(
-      int[] array, int minLength, int padding) {
+  public static int[] ensureCapacity(int[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -478,26 +478,30 @@ public final class Ints {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Integer get(int index) {
+    @Override
+    public Integer get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Integer)
-          && Ints.indexOf(array, (Integer) target, start, end) != -1;
+      return (target instanceof Integer) && Ints.indexOf(array, (Integer) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Integer) {
         int i = Ints.indexOf(array, (Integer) target, start, end);
@@ -508,7 +512,8 @@ public final class Ints {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Integer) {
         int i = Ints.lastIndexOf(array, (Integer) target, start, end);
@@ -519,7 +524,8 @@ public final class Ints {
       return -1;
     }
 
-    @Override public Integer set(int index, Integer element) {
+    @Override
+    public Integer set(int index, Integer element) {
       checkElementIndex(index, size());
       int oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -527,7 +533,8 @@ public final class Ints {
       return oldValue;
     }
 
-    @Override public List<Integer> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Integer> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -536,7 +543,8 @@ public final class Ints {
       return new IntArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -556,7 +564,8 @@ public final class Ints {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Ints.hashCode(array[i]);
@@ -564,7 +573,8 @@ public final class Ints {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 5);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
@@ -584,23 +594,6 @@ public final class Ints {
     private static final long serialVersionUID = 0;
   }
 
-  private static final byte[] asciiDigits = new byte[128];
-
-  static {
-    Arrays.fill(asciiDigits, (byte) -1);
-    for (int i = 0; i <= 9; i++) {
-      asciiDigits['0' + i] = (byte) i;
-    }
-    for (int i = 0; i <= 26; i++) {
-      asciiDigits['A' + i] = (byte) (10 + i);
-      asciiDigits['a' + i] = (byte) (10 + i);
-    }
-  }
-
-  private static int digit(char c) {
-    return (c < 128) ? asciiDigits[c] : -1;
-  }
-
   /**
    * Parses the specified string as a signed decimal integer value. The ASCII
    * character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -622,6 +615,7 @@ public final class Ints {
    * @since 11.0
    */
   @Beta
+  @Nullable
   @CheckForNull
   public static Integer tryParse(String string) {
     return tryParse(string, 10);
@@ -648,47 +642,18 @@ public final class Ints {
    *     or cannot be parsed as an integer value
    * @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
    *     {@code radix > Character.MAX_RADIX}
+   * @since 19.0
    */
-  @CheckForNull static Integer tryParse(
+  @Beta
+  @Nullable
+  @CheckForNull
+  public static Integer tryParse(
       String string, int radix) {
-    if (checkNotNull(string).isEmpty()) {
-      return null;
-    }
-    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
-      throw new IllegalArgumentException(
-          "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
-    }
-    boolean negative = string.charAt(0) == '-';
-    int index = negative ? 1 : 0;
-    if (index == string.length()) {
-      return null;
-    }
-    int digit = digit(string.charAt(index++));
-    if (digit < 0 || digit >= radix) {
-      return null;
-    }
-    int accum = -digit;
-
-    int cap = Integer.MIN_VALUE / radix;
-
-    while (index < string.length()) {
-      digit = digit(string.charAt(index++));
-      if (digit < 0 || digit >= radix || accum < cap) {
-        return null;
-      }
-      accum *= radix;
-      if (accum < Integer.MIN_VALUE + digit) {
-        return null;
-      }
-      accum -= digit;
-    }
-
-    if (negative) {
-      return accum;
-    } else if (accum == Integer.MIN_VALUE) {
+    Long result = Longs.tryParse(string, radix);
+    if (result == null || result.longValue() != result.intValue()) {
       return null;
     } else {
-      return -accum;
+      return result.intValue();
     }
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
index 221255b..d776550 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
@@ -33,17 +33,20 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code short} primitives, that are not
  * already found in either {@link Short} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Shorts {
   private Shorts() {}
@@ -156,8 +159,7 @@ public final class Shorts {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      short[] array, short target, int start, int end) {
+  private static int indexOf(short[] array, short target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -210,8 +212,7 @@ public final class Shorts {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      short[] array, short target, int start, int end) {
+  private static int lastIndexOf(short[] array, short target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -281,8 +282,8 @@ public final class Shorts {
     return result;
   }
 
-  private static final class ShortConverter
-      extends Converter<String, Short> implements Serializable {
+  private static final class ShortConverter extends Converter<String, Short>
+      implements Serializable {
     static final ShortConverter INSTANCE = new ShortConverter();
 
     @Override
@@ -303,6 +304,7 @@ public final class Shorts {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -333,8 +335,7 @@ public final class Shorts {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static short[] ensureCapacity(
-      short[] array, int minLength, int padding) {
+  public static short[] ensureCapacity(short[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -477,26 +478,30 @@ public final class Shorts {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Short get(int index) {
+    @Override
+    public Short get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Short)
-          && Shorts.indexOf(array, (Short) target, start, end) != -1;
+      return (target instanceof Short) && Shorts.indexOf(array, (Short) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Short) {
         int i = Shorts.indexOf(array, (Short) target, start, end);
@@ -507,7 +512,8 @@ public final class Shorts {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Short) {
         int i = Shorts.lastIndexOf(array, (Short) target, start, end);
@@ -518,7 +524,8 @@ public final class Shorts {
       return -1;
     }
 
-    @Override public Short set(int index, Short element) {
+    @Override
+    public Short set(int index, Short element) {
       checkElementIndex(index, size());
       short oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -526,7 +533,8 @@ public final class Shorts {
       return oldValue;
     }
 
-    @Override public List<Short> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Short> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -535,7 +543,8 @@ public final class Shorts {
       return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(Object object) {
       if (object == this) {
         return true;
       }
@@ -555,7 +564,8 @@ public final class Shorts {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Shorts.hashCode(array[i]);
@@ -563,7 +573,8 @@ public final class Shorts {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 6);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
index 8ddc57d..54f4c15 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
@@ -1,11 +1,11 @@
 /*
  * 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
@@ -29,17 +29,18 @@ import javax.annotation.Nullable;
 
 /**
  * A wrapper class for unsigned {@code int} values, supporting arithmetic operations.
- * 
+ *
  * <p>In some cases, when speed is more important than code readability, it may be faster simply to
  * treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
  * unsigned primitive utilities</a>.
- * 
+ *
  * @author Louis Wasserman
  * @since 11.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
   public static final UnsignedInteger ZERO = fromIntBits(0);
@@ -62,7 +63,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    * otherwise, the result will be equal to {@code 2^32 + bits}.
    *
    * <p>To represent unsigned decimal constants, consider {@link #valueOf(long)} instead.
-   * 
+   *
    * @since 14.0
    */
   public static UnsignedInteger fromIntBits(int bits) {
@@ -74,28 +75,32 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    * if possible.  The inverse operation of {@link #longValue()}.
    */
   public static UnsignedInteger valueOf(long value) {
-    checkArgument((value & INT_MASK) == value,
-        "value (%s) is outside the range for an unsigned integer value", value);
+    checkArgument(
+        (value & INT_MASK) == value,
+        "value (%s) is outside the range for an unsigned integer value",
+        value);
     return fromIntBits((int) value);
   }
 
   /**
    * Returns a {@code UnsignedInteger} representing the same value as the specified
    * {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
-   * 
+   *
    * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
    */
   public static UnsignedInteger valueOf(BigInteger value) {
     checkNotNull(value);
-    checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
-        "value (%s) is outside the range for an unsigned integer value", value);
+    checkArgument(
+        value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
+        "value (%s) is outside the range for an unsigned integer value",
+        value);
     return fromIntBits(value.intValue());
   }
 
   /**
    * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
    * as an unsigned {@code int} value.
-   * 
+   *
    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
    *         value
    */
@@ -106,7 +111,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
   /**
    * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
    * as an unsigned {@code int} value in the specified radix.
-   * 
+   *
    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
    *         value
    */
@@ -117,10 +122,9 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
   /**
    * Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
    * returns the low 32 bits of the result.
-   * 
+   *
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger plus(UnsignedInteger val) {
     return fromIntBits(this.value + checkNotNull(val).value);
   }
@@ -128,32 +132,29 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
   /**
    * Returns the result of subtracting this and {@code val}. If the result would be negative,
    * returns the low 32 bits of the result.
-   * 
+   *
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger minus(UnsignedInteger val) {
     return fromIntBits(value - checkNotNull(val).value);
   }
 
   /**
    * Returns the result of dividing this by {@code val}.
-   * 
+   *
    * @throws ArithmeticException if {@code val} is zero
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger dividedBy(UnsignedInteger val) {
     return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
   }
 
   /**
    * Returns this mod {@code val}.
-   * 
+   *
    * @throws ArithmeticException if {@code val} is zero
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger mod(UnsignedInteger val) {
     return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
   }
@@ -161,7 +162,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
   /**
    * Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
    * operation to {@link #fromIntBits}.
-   * 
+   *
    * <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
    * will be equal to {@code this - 2^32}.
    */
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
new file mode 100644
index 0000000..931e3fe
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+/**
+ * Emulation for AbstractFuture in GWT.
+ */
+public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+
+  abstract static class TrustedFuture<V> extends AbstractFuture<V> {
+    @Override public final V get() throws InterruptedException, ExecutionException {
+      return super.get();
+    }
+
+    @Override public final V get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException {
+      return super.get(timeout, unit);
+    }
+
+    @Override public final boolean isDone() {
+      return super.isDone();
+    }
+
+    @Override public final boolean isCancelled() {
+      return super.isCancelled();
+    }
+
+    @Override public final void addListener(Runnable listener, Executor executor) {
+      super.addListener(listener, executor);
+    }
+  }
+
+  private static final Logger log = Logger.getLogger(AbstractFuture.class.getName());
+
+  private State state;
+  private V value;
+  private Future<? extends V> delegate;
+  private Throwable throwable;
+  private boolean mayInterruptIfRunning;
+  private List<Listener> listeners;
+
+  protected AbstractFuture() {
+    state = State.PENDING;
+    listeners = new ArrayList<Listener>();
+  }
+  
+  @Override
+  public boolean cancel(boolean mayInterruptIfRunning) {
+    if (!state.permitsPublicUserToTransitionTo(State.CANCELLED)) {
+      return false;
+    }
+    
+    this.mayInterruptIfRunning = mayInterruptIfRunning;
+    state = State.CANCELLED;
+    notifyAndClearListeners();
+
+    if (delegate != null) {
+      delegate.cancel(mayInterruptIfRunning);
+    }
+
+    return true;
+  }
+
+  @Override
+  public boolean isCancelled() {
+    return state.isCancelled();
+  }
+
+  @Override
+  public boolean isDone() {
+    return state.isDone();
+  }
+
+  @Override
+  public V get() throws InterruptedException, ExecutionException {
+    state.maybeThrowOnGet(throwable);
+    return value;
+  }
+
+  @Override
+  public V get(long timeout, TimeUnit unit)
+      throws InterruptedException, ExecutionException, TimeoutException {
+    checkNotNull(unit);
+    return get();
+  }
+
+  @Override
+  public void addListener(Runnable runnable, Executor executor) {
+    Listener listener = new Listener(runnable, executor);
+    if (isDone()) {
+      listener.execute();
+    } else {
+      listeners.add(listener);
+    }
+  }
+
+  protected boolean setException(Throwable throwable) {
+    checkNotNull(throwable);
+    if (!state.permitsPublicUserToTransitionTo(State.FAILURE)) {
+      return false;
+    }
+    
+    forceSetException(throwable);
+    return true;
+  }
+
+  private void forceSetException(Throwable throwable) {
+    this.throwable = throwable;
+    this.state = State.FAILURE;
+    notifyAndClearListeners();
+  }
+
+  protected boolean set(V value) {
+    if (!state.permitsPublicUserToTransitionTo(State.VALUE)) {
+      return false;
+    }
+
+    forceSet(value);
+    return true;
+  }
+
+  private void forceSet(V value) {
+    this.value = value;
+    this.state = State.VALUE;
+    notifyAndClearListeners();
+  }
+
+  protected boolean setFuture(ListenableFuture<? extends V> future) {
+    checkNotNull(future);
+
+    // If this future is already cancelled, cancel the delegate.
+    if (isCancelled()) {
+      future.cancel(mayInterruptIfRunning);
+    }
+
+    if (!state.permitsPublicUserToTransitionTo(State.DELEGATED)) {
+      return false;
+    }
+
+    state = State.DELEGATED;
+    this.delegate = future;
+
+    future.addListener(new SetFuture(future), directExecutor());
+    return true;
+  }
+
+  protected final boolean wasInterrupted() {
+    return mayInterruptIfRunning;
+  }
+
+  private void notifyAndClearListeners() {
+    // TODO(cpovirk): consider clearing this.delegate
+    for (Listener listener : listeners) {
+      listener.execute();
+    }
+    listeners = null;
+    done();
+  }
+
+  void done() {}
+
+  final Throwable trustedGetException() {
+    checkState(state == State.FAILURE);
+    return throwable;
+  }
+
+  final void maybePropagateCancellation(@Nullable Future<?> related) {
+    if (related != null & isCancelled()) {
+      related.cancel(wasInterrupted());
+    }
+  }
+
+  private enum State {
+    PENDING {
+      @Override
+      boolean isDone() {
+        return false;
+      }
+      
+      @Override
+      void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+        throw new IllegalStateException("Cannot get() on a pending future.");
+      }
+      
+      @Override
+      boolean permitsPublicUserToTransitionTo(State state) {
+        return !state.equals(PENDING);
+      }
+    },
+    DELEGATED {
+      @Override
+      boolean isDone() {
+        return false;
+      }
+
+      @Override
+      void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+        throw new IllegalStateException("Cannot get() on a pending future.");
+      }
+
+      boolean permitsPublicUserToTransitionTo(State state) {
+        return state.equals(CANCELLED);
+      }
+    },
+    VALUE,
+    FAILURE {
+      @Override
+      void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+        throw new ExecutionException(cause);
+      }
+    },
+    CANCELLED {
+      @Override
+      boolean isCancelled() {
+        return true;
+      }
+
+      @Override
+      void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+        // TODO(cpovirk): chain in a CancellationException created at the cancel() call?
+        throw new CancellationException();
+      }
+    };
+    
+    boolean isDone() {
+      return true;
+    }
+    
+    boolean isCancelled() {
+      return false;
+    }
+
+    void maybeThrowOnGet(Throwable cause) throws ExecutionException {}
+    
+    boolean permitsPublicUserToTransitionTo(State state) {
+      return false;
+    }
+  }
+
+  private static final class Listener {
+    final Runnable command;
+    final Executor executor;
+    
+    Listener(Runnable command, Executor executor) {
+      this.command = checkNotNull(command);
+      this.executor = checkNotNull(executor);
+    }
+    
+    void execute() {
+      try {
+        executor.execute(command);
+      } catch (RuntimeException e) {
+        log.log(Level.SEVERE, "RuntimeException while executing runnable "
+            + command + " with executor " + executor, e);
+      }
+    }
+  }
+
+  private final class SetFuture implements Runnable {
+    final ListenableFuture<? extends V> delegate;
+
+    SetFuture(ListenableFuture<? extends V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public void run() {
+      if (isCancelled()) {
+        return;
+      }
+
+      if (delegate instanceof TrustedFuture) {
+        AbstractFuture<? extends V> other = (AbstractFuture<? extends V>) delegate;
+        value = other.value;
+        throwable = other.throwable;
+        mayInterruptIfRunning = other.mayInterruptIfRunning;
+        state = other.state;
+
+        notifyAndClearListeners();
+        return;
+      }
+
+      try {
+        forceSet(getUninterruptibly(delegate));
+      } catch (ExecutionException exception) {
+        forceSetException(exception.getCause());
+      } catch (CancellationException cancellation) {
+        cancel(false);
+      } catch (Throwable t) {
+        forceSetException(t);
+      }
+    }
+  }
+}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java
new file mode 100644
index 0000000..780adc8
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java
@@ -0,0 +1,49 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+import java.util.Set;
+
+/**
+ * Emulation of AggregateFutureState.
+ */
+abstract class AggregateFutureState {
+  // Lazily initialized the first time we see an exception; not released until all the input futures
+  // & this future completes. Released when the future releases the reference to the running state
+  private Set<Throwable> seenExceptions = null;
+  private int remaining;
+
+  AggregateFutureState(int remainingFutures) {
+    this.remaining = remainingFutures;
+  }
+
+  final Set<Throwable> getOrInitSeenExceptions() {
+    if (seenExceptions == null) {
+      seenExceptions = newHashSet();
+      addInitialException(seenExceptions);
+    }
+    return seenExceptions;
+  }
+
+  abstract void addInitialException(Set<Throwable> seen);
+
+  final int decrementRemainingAndGet() {
+    return --remaining;
+  }
+}
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
similarity index 56%
copy from guava/src/com/google/common/collect/ComputationException.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
index ac80d6a..0da6387 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
@@ -14,25 +14,33 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
 import com.google.common.annotations.GwtCompatible;
 
+import java.util.concurrent.Callable;
+
 import javax.annotation.Nullable;
 
 /**
- * Wraps an exception that occurred during a computation.
+ * Static utility methods pertaining to the {@link Callable} interface.
  *
- * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @author Isaac Shum
+ * @since 1.0
  */
- at GwtCompatible
-public class ComputationException extends RuntimeException {
+ at GwtCompatible(emulated = true)
+public final class Callables {
+  private Callables() {}
+
   /**
-   * Creates a new instance with the given cause.
+   * Creates a {@code Callable} which immediately returns a preset value each
+   * time it is called.
    */
-  public ComputationException(@Nullable Throwable cause) {
-    super(cause);
+  public static <T> Callable<T> returning(final @Nullable T value) {
+    return new Callable<T>() {
+      @Override public T call() {
+        return value;
+      }
+    };
   }
-  private static final long serialVersionUID = 0;
 }
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java
new file mode 100644
index 0000000..4b60f95
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java
@@ -0,0 +1,1267 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Platform.isInstanceOfThrowableClass;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
+/**
+ * Static utility methods pertaining to the {@link Future} interface.
+ *
+ * <p>Many of these methods use the {@link ListenableFuture} API; consult the
+ * Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
+ * {@code ListenableFuture}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @author Nishant Thakkar
+ * @author Sven Mawson
+ * @since 1.0
+ */
+ at Beta
+ at GwtCompatible(emulated = true)
+public final class Futures extends GwtFuturesCatchingSpecialization {
+
+  // A note on memory visibility.
+  // Many of the utilities in this class (transform, withFallback, withTimeout, asList, combine)
+  // have two requirements that significantly complicate their design.
+  // 1. Cancellation should propagate from the returned future to the input future(s).
+  // 2. The returned futures shouldn't unnecessarily 'pin' their inputs after completion.
+  //
+  // A consequence of these requirements is that the delegate futures cannot be stored in
+  // final fields.
+  //
+  // For simplicity the rest of this description will discuss Futures.catching since it is the
+  // simplest instance, though very similar descriptions apply to many other classes in this file.
+  //
+  // In the constructor of AbstractCatchingFuture, the delegate future is assigned to a field
+  // 'inputFuture'. That field is non-final and non-volatile.  There are 2 places where the
+  // 'inputFuture' field is read and where we will have to consider visibility of the write
+  // operation in the constructor.
+  //
+  // 1. In the listener that performs the callback.  In this case it is fine since inputFuture is
+  //    assigned prior to calling addListener, and addListener happens-before any invocation of the
+  //    listener. Notably, this means that 'volatile' is unnecessary to make 'inputFuture' visible
+  //    to the listener.
+  //
+  // 2. In done() where we may propagate cancellation to the input.  In this case it is _not_ fine.
+  //    There is currently nothing that enforces that the write to inputFuture in the constructor is
+  //    visible to done().  This is because there is no happens before edge between the write and a
+  //    (hypothetical) unsafe read by our caller. Note: adding 'volatile' does not fix this issue,
+  //    it would just add an edge such that if done() observed non-null, then it would also
+  //    definitely observe all earlier writes, but we still have no guarantee that done() would see
+  //    the inital write (just stronger guarantees if it does).
+  //
+  // See: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013800.html
+  // For a (long) discussion about this specific issue and the general futility of life.
+  //
+  // For the time being we are OK with the problem discussed above since it requires a caller to
+  // introduce a very specific kind of data-race.  And given the other operations performed by these
+  // methods that involve volatile read/write operations, in practice there is no issue.  Also, the
+  // way in such a visibility issue would surface is most likely as a failure of cancel() to
+  // propagate to the input.  Cancellation propagation is fundamentally racy so this is fine.
+  //
+  // Future versions of the JMM may revise safe construction semantics in such a way that we can
+  // safely publish these objects and we won't need this whole discussion.
+  // TODO(user,lukes): consider adding volatile to all these fields since in current known JVMs
+  // that should resolve the issue.  This comes at the cost of adding more write barriers to the
+  // implementations.
+
+  private Futures() {}
+
+  private abstract static class ImmediateFuture<V>
+      implements ListenableFuture<V> {
+
+    private static final Logger log =
+        Logger.getLogger(ImmediateFuture.class.getName());
+
+    @Override
+    public void addListener(Runnable listener, Executor executor) {
+      checkNotNull(listener, "Runnable was null.");
+      checkNotNull(executor, "Executor was null.");
+      try {
+        executor.execute(listener);
+      } catch (RuntimeException e) {
+        // ListenableFuture's contract is that it will not throw unchecked
+        // exceptions, so log the bad runnable and/or executor and swallow it.
+        log.log(Level.SEVERE, "RuntimeException while executing runnable "
+            + listener + " with executor " + executor, e);
+      }
+    }
+
+    @Override
+    public boolean cancel(boolean mayInterruptIfRunning) {
+      return false;
+    }
+
+    @Override
+    public abstract V get() throws ExecutionException;
+
+    @Override
+    public V get(long timeout, TimeUnit unit) throws ExecutionException {
+      checkNotNull(unit);
+      return get();
+    }
+
+    @Override
+    public boolean isCancelled() {
+      return false;
+    }
+
+    @Override
+    public boolean isDone() {
+      return true;
+    }
+  }
+
+  private static class ImmediateSuccessfulFuture<V> extends ImmediateFuture<V> {
+    static final ImmediateSuccessfulFuture<Object> NULL =
+        new ImmediateSuccessfulFuture<Object>(null);
+
+    @Nullable private final V value;
+
+    ImmediateSuccessfulFuture(@Nullable V value) {
+      this.value = value;
+    }
+
+    @Override
+    public V get() {
+      return value;
+    }
+  }
+
+  private static class ImmediateFailedFuture<V> extends ImmediateFuture<V> {
+
+    private final Throwable thrown;
+
+    ImmediateFailedFuture(Throwable thrown) {
+      this.thrown = thrown;
+    }
+
+    @Override
+    public V get() throws ExecutionException {
+      throw new ExecutionException(thrown);
+    }
+  }
+
+  /**
+   * Creates a {@code ListenableFuture} which has its value set immediately upon
+   * construction. The getters just return the value. This {@code Future} can't
+   * be canceled or timed out and its {@code isDone()} method always returns
+   * {@code true}.
+   */
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
+    if (value == null) {
+      // This cast is safe because null is assignable to V for all V (i.e. it is covariant)
+      @SuppressWarnings({"unchecked", "rawtypes"})
+      ListenableFuture<V> typedNull = (ListenableFuture) ImmediateSuccessfulFuture.NULL;
+      return typedNull;
+    }
+    return new ImmediateSuccessfulFuture<V>(value);
+  }
+
+  /**
+   * Returns a {@code ListenableFuture} which has an exception set immediately
+   * upon construction.
+   *
+   * <p>The returned {@code Future} can't be cancelled, and its {@code isDone()}
+   * method always returns {@code true}. Calling {@code get()} will immediately
+   * throw the provided {@code Throwable} wrapped in an {@code
+   * ExecutionException}.
+   */
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> immediateFailedFuture(
+      Throwable throwable) {
+    checkNotNull(throwable);
+    return new ImmediateFailedFuture<V>(throwable);
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary
+   * {@code input} or, if the primary input fails, from the {@code Future}
+   * provided by the {@code fallback}. {@link FutureFallback#create} is not
+   * invoked until the primary input has failed, so if the primary input
+   * succeeds, it is never invoked. If, during the invocation of {@code
+   * fallback}, an exception is thrown, this exception is used as the result of
+   * the output {@code Future}.
+   *
+   * <p>Below is an example of a fallback that returns a default value if an
+   * exception occurs:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+   *       fetchCounterFuture, new FutureFallback<Integer>() {
+   *         public ListenableFuture<Integer> create(Throwable t) {
+   *           // Returning "0" as the default for the counter when the
+   *           // exception happens.
+   *           return immediateFuture(0);
+   *         }
+   *       });}</pre>
+   *
+   * <p>The fallback can also choose to propagate the original exception when
+   * desired:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter only in case the exception was a
+   *   // TimeoutException.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+   *       fetchCounterFuture, new FutureFallback<Integer>() {
+   *         public ListenableFuture<Integer> create(Throwable t) {
+   *           if (t instanceof TimeoutException) {
+   *             return immediateFuture(0);
+   *           }
+   *           return immediateFailedFuture(t);
+   *         }
+   *       });}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code FutureFallback.create}, not to
+   * any work done to complete the returned {@code Future}.
+   *
+   * @param input the primary input {@code Future}
+   * @param fallback the {@link FutureFallback} implementation to be called if
+   *     {@code input} fails
+   * @since 14.0
+   * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+   *     AsyncFunction) catchingAsync(input, Throwable.class,
+   *     fallbackImplementedAsAnAsyncFunction)}, usually replacing {@code
+   *     Throwable.class} with the specific type you want to handle. This method
+   *     will be removed in Guava release 20.0.
+   */
+  @Deprecated
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> withFallback(
+      ListenableFuture<? extends V> input,
+      FutureFallback<? extends V> fallback) {
+    return withFallback(input, fallback, directExecutor());
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary
+   * {@code input} or, if the primary input fails, from the {@code Future}
+   * provided by the {@code fallback}. {@link FutureFallback#create} is not
+   * invoked until the primary input has failed, so if the primary input
+   * succeeds, it is never invoked. If, during the invocation of {@code
+   * fallback}, an exception is thrown, this exception is used as the result of
+   * the output {@code Future}.
+   *
+   * <p>Below is an example of a fallback that returns a default value if an
+   * exception occurs:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+   *       fetchCounterFuture, new FutureFallback<Integer>() {
+   *         public ListenableFuture<Integer> create(Throwable t) {
+   *           // Returning "0" as the default for the counter when the
+   *           // exception happens.
+   *           return immediateFuture(0);
+   *         }
+   *       }, directExecutor());}</pre>
+   *
+   * <p>The fallback can also choose to propagate the original exception when
+   * desired:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter only in case the exception was a
+   *   // TimeoutException.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+   *       fetchCounterFuture, new FutureFallback<Integer>() {
+   *         public ListenableFuture<Integer> create(Throwable t) {
+   *           if (t instanceof TimeoutException) {
+   *             return immediateFuture(0);
+   *           }
+   *           return immediateFailedFuture(t);
+   *         }
+   *       }, directExecutor());}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code FutureFallback.create}, not to any work done to
+   * complete the returned {@code Future}.
+   *
+   * @param input the primary input {@code Future}
+   * @param fallback the {@link FutureFallback} implementation to be called if
+   *     {@code input} fails
+   * @param executor the executor that runs {@code fallback} if {@code input}
+   *     fails
+   * @since 14.0
+   * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+   *     AsyncFunction, Executor) catchingAsync(input, Throwable.class,
+   *     fallbackImplementedAsAnAsyncFunction, executor)}, usually replacing
+   *     {@code Throwable.class} with the specific type you want to handle. This method
+   *     will be removed in Guava release 20.0.
+   */
+  @Deprecated
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> withFallback(
+      ListenableFuture<? extends V> input,
+      FutureFallback<? extends V> fallback, Executor executor) {
+    return catchingAsync(
+        input, Throwable.class, asAsyncFunction(fallback), executor);
+  }
+
+  @Deprecated
+  static <V> AsyncFunction<Throwable, V> asAsyncFunction(final FutureFallback<V> fallback) {
+    checkNotNull(fallback);
+    return new AsyncFunction<Throwable, V>() {
+      @Override
+      public ListenableFuture<V> apply(Throwable t) throws Exception {
+        return checkNotNull(fallback.create(t), "FutureFallback.create returned null instead of a "
+            + "Future. Did you mean to return immediateFuture(null)?");
+      }
+    };
+  }
+
+  private abstract static class AbstractCatchingFuture<V, X extends Throwable, F>
+      extends AbstractFuture.TrustedFuture<V> implements Runnable {
+    @Nullable ListenableFuture<? extends V> inputFuture;
+    @Nullable Class<X> exceptionType;
+    @Nullable F fallback;
+
+    AbstractCatchingFuture(
+        ListenableFuture<? extends V> inputFuture, Class<X> exceptionType, F fallback) {
+      this.inputFuture = checkNotNull(inputFuture);
+      this.exceptionType = checkNotNull(exceptionType);
+      this.fallback = checkNotNull(fallback);
+    }
+
+    @Override public final void run() {
+      ListenableFuture<? extends V> localInputFuture = inputFuture;
+      Class<X> localExceptionType = exceptionType;
+      F localFallback = fallback;
+      if (localInputFuture == null | localExceptionType == null | localFallback == null
+          | isCancelled()) {
+        return;
+      }
+      inputFuture = null;
+      exceptionType = null;
+      fallback = null;
+
+      Throwable throwable;
+      try {
+        set(getUninterruptibly(localInputFuture));
+        return;
+      } catch (ExecutionException e) {
+        throwable = e.getCause();
+      } catch (Throwable e) {  // this includes cancellation exception
+        throwable = e;
+      }
+      try {
+        if (isInstanceOfThrowableClass(throwable, localExceptionType)) {
+          @SuppressWarnings("unchecked") // verified safe by isInstance
+          X castThrowable = (X) throwable;
+          doFallback(localFallback, castThrowable);
+        } else {
+          setException(throwable);
+        }
+      } catch (Throwable e) {
+        setException(e);
+      }
+    }
+
+    /** Template method for subtypes to actually run the fallback. */
+    abstract void doFallback(F fallback, X throwable) throws Exception;
+
+    @Override final void done() {
+      maybePropagateCancellation(inputFuture);
+      this.inputFuture = null;
+      this.exceptionType = null;
+      this.fallback = null;
+    }
+  }
+
+  /**
+   * A {@link AbstractCatchingFuture} that delegates to an {@link AsyncFunction}
+   * and {@link #setFuture(ListenableFuture)} to implement {@link #doFallback}
+   */
+  static final class AsyncCatchingFuture<V, X extends Throwable>
+      extends AbstractCatchingFuture<V, X, AsyncFunction<? super X, ? extends V>> {
+
+    AsyncCatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+        AsyncFunction<? super X, ? extends V> fallback) {
+      super(input, exceptionType, fallback);
+    }
+
+    @Override void doFallback(
+        AsyncFunction<? super X, ? extends V> fallback, X cause) throws Exception {
+      ListenableFuture<? extends V> replacement = fallback.apply(cause);
+      checkNotNull(replacement, "AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+      setFuture(replacement);
+    }
+  }
+
+  /**
+   * A {@link AbstractCatchingFuture} that delegates to a {@link Function}
+   * and {@link #set(Object)} to implement {@link #doFallback}
+   */
+  static final class CatchingFuture<V, X extends Throwable>
+      extends AbstractCatchingFuture<V, X, Function<? super X, ? extends V>> {
+    CatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+        Function<? super X, ? extends V> fallback) {
+      super(input, exceptionType, fallback);
+    }
+
+    @Override void doFallback(Function<? super X, ? extends V> fallback, X cause) throws Exception {
+      V replacement = fallback.apply(cause);
+      set(replacement);
+    }
+  }
+
+  /**
+   * Future that delegates to another but will finish early (via a {@link
+   * TimeoutException} wrapped in an {@link ExecutionException}) if the
+   * specified duration expires.
+   * The delegate future is interrupted and cancelled if it times out.
+   */
+  private static final class TimeoutFuture<V> extends AbstractFuture.TrustedFuture<V> {
+    // Memory visibility of these fields.
+    // There are two cases to consider.
+    // 1. visibility of the writes to these fields to Fire.run
+    //    The initial write to delegateRef is made definitely visible via the semantics of
+    //    addListener/SES.schedule.  The later racy write in cancel() is not guaranteed to be
+    //    observed, however that is fine since the correctness is based on the atomic state in
+    //    our base class.
+    //    The initial write to timer is never definitely visible to Fire.run since it is assigned
+    //    after SES.schedule is called. Therefore Fire.run has to check for null.  However, it
+    //    should be visible if Fire.run is called by delegate.addListener since addListener is
+    //    called after the assignment to timer, and importantly this is the main situation in which
+    //    we need to be able to see the write.
+    // 2. visibility of the writes to cancel
+    //    Since these fields are non-final that means that TimeoutFuture is not being 'safely
+    //    published', thus a motivated caller may be able to expose the reference to another thread
+    //    that would then call cancel() and be unable to cancel the delegate.
+    //    There are a number of ways to solve this, none of which are very pretty, and it is
+    //    currently believed to be a purely theoretical problem (since the other actions should
+    //    supply sufficient write-barriers).
+
+    @Nullable ListenableFuture<V> delegateRef;
+    @Nullable Future<?> timer;
+
+    TimeoutFuture(ListenableFuture<V> delegate) {
+      this.delegateRef = Preconditions.checkNotNull(delegate);
+    }
+
+    /** A runnable that is called when the delegate or the timer completes. */
+    private static final class Fire<V> implements Runnable {
+      @Nullable TimeoutFuture<V> timeoutFutureRef;
+
+      Fire(TimeoutFuture<V> timeoutFuture) {
+        this.timeoutFutureRef = timeoutFuture;
+      }
+
+      @Override public void run() {
+        // If either of these reads return null then we must be after a successful cancel
+        // or another call to this method.
+        TimeoutFuture<V> timeoutFuture = timeoutFutureRef;
+        if (timeoutFuture == null) {
+          return;
+        }
+        ListenableFuture<V> delegate = timeoutFuture.delegateRef;
+        if (delegate == null) {
+          return;
+        }
+
+        /*
+         * If we're about to complete the TimeoutFuture, we want to release our reference to it.
+         * Otherwise, we'll pin it (and its result) in memory until the timeout task is GCed. (The
+         * need to clear our reference to the TimeoutFuture is the reason we use a *static* nested
+         * class with a manual reference back to the "containing" class.)
+         *
+         * This has the nice-ish side effect of limiting reentrancy: run() calls
+         * timeoutFuture.setException() calls run(). That reentrancy would already be harmless,
+         * since timeoutFuture can be set (and delegate cancelled) only once. (And "set only once"
+         * is important for other reasons: run() can still be invoked concurrently in different
+         * threads, even with the above null checks.)
+         */
+        timeoutFutureRef = null;
+        if (delegate.isDone()) {
+          timeoutFuture.setFuture(delegate);
+        } else {
+          try {
+            // TODO(lukes): this stack trace is particularly useless (all it does is point at the
+            // scheduledexecutorservice thread), consider eliminating it altogether?
+            timeoutFuture.setException(new TimeoutException("Future timed out: " + delegate));
+          } finally {
+            delegate.cancel(true);
+          }
+        }
+      }
+    }
+
+    @Override void done() {
+      maybePropagateCancellation(delegateRef);
+
+      Future<?> localTimer = timer;
+      // Try to cancel the timer as an optimization
+      // timer may be null if this call to run was by the timer task since there is no
+      // happens-before edge between the assignment to timer and an execution of the timer task.
+      if (localTimer != null) {
+        localTimer.cancel(false);
+      }
+
+      delegateRef = null;
+      timer = null;
+    }
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously
+   * derived from the result of the given {@code Future}. More precisely, the
+   * returned {@code Future} takes its result from a {@code Future} produced by
+   * applying the given {@code AsyncFunction} to the result of the original
+   * {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transform(rowKeyFuture, queryFunction);}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code AsyncFunction.apply}, not to any
+   * work done to complete the returned {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in
+   * sync with that of the input future and that of the future returned by the
+   * function. That is, if the returned {@code Future} is cancelled, it will
+   * attempt to cancel the other two, and if either of the other two is
+   * cancelled, the returned {@code Future} will receive a callback in which it
+   * will attempt to cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future
+   *     to the result of the output future
+   * @return A future that holds result of the function (if the input succeeded)
+   *     or the original input's failure (if not)
+   * @since 11.0
+   * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+   *     being renamed to {@code transformAsync}. (The {@code Function}
+   *     overloads are keeping the "transform" name.) This method will be removed in Guava release
+   *     20.0.
+   */
+  @Deprecated
+  public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+      AsyncFunction<? super I, ? extends O> function) {
+    return transformAsync(input, function);
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously
+   * derived from the result of the given {@code Future}. More precisely, the
+   * returned {@code Future} takes its result from a {@code Future} produced by
+   * applying the given {@code AsyncFunction} to the result of the original
+   * {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transform(rowKeyFuture, queryFunction, executor);}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code AsyncFunction.apply}, not to any work done to
+   * complete the returned {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in
+   * sync with that of the input future and that of the future returned by the
+   * chain function. That is, if the returned {@code Future} is cancelled, it
+   * will attempt to cancel the other two, and if either of the other two is
+   * cancelled, the returned {@code Future} will receive a callback in which it
+   * will attempt to cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future
+   *     to the result of the output future
+   * @param executor Executor to run the function in.
+   * @return A future that holds result of the function (if the input succeeded)
+   *     or the original input's failure (if not)
+   * @since 11.0
+   * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+   *     being renamed to {@code transformAsync}. (The {@code Function}
+   *     overloads are keeping the "transform" name.) This method will be removed in Guava release
+   *     20.0.
+   */
+  @Deprecated
+  public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+      AsyncFunction<? super I, ? extends O> function,
+      Executor executor) {
+    return transformAsync(input, function, executor);
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+   * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+   * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+   * original {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transformAsync(rowKeyFuture, queryFunction);}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+   * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+   * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+   * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+   * to complete the returned {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+   * input future and that of the future returned by the function. That is, if the returned {@code
+   * Future} is cancelled, it will attempt to cancel the other two, and if either of the other two
+   * is cancelled, the returned {@code Future} will receive a callback in which it will attempt to
+   * cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future to the result of the
+   *     output future
+   * @return A future that holds result of the function (if the input succeeded) or the original
+   *     input's failure (if not)
+   * @since 19.0 (in 11.0 as {@code transform})
+   */
+  public static <I, O> ListenableFuture<O> transformAsync(
+      ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function) {
+    AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+    input.addListener(output, directExecutor());
+    return output;
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+   * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+   * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+   * original {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transformAsync(rowKeyFuture, queryFunction, executor);}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+   * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+   * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+   * {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+   * input future and that of the future returned by the chain function. That is, if the returned
+   * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
+   * other two is cancelled, the returned {@code Future} will receive a callback in which it will
+   * attempt to cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future to the result of the
+   *     output future
+   * @param executor Executor to run the function in.
+   * @return A future that holds result of the function (if the input succeeded) or the original
+   *     input's failure (if not)
+   * @since 19.0 (in 11.0 as {@code transform})
+   */
+  public static <I, O> ListenableFuture<O> transformAsync(ListenableFuture<I> input,
+      AsyncFunction<? super I, ? extends O> function, Executor executor) {
+    checkNotNull(executor);
+    AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+    input.addListener(output, rejectionPropagatingExecutor(executor, output));
+    return output;
+  }
+
+  /**
+   * Returns an Executor that will propagate {@link RejectedExecutionException} from the delegate
+   * executor to the given {@code future}.
+   *
+   * <p>Note, the returned executor can only be used once.
+   */
+  private static Executor rejectionPropagatingExecutor(
+      final Executor delegate, final AbstractFuture<?> future) {
+    checkNotNull(delegate);
+    if (delegate == directExecutor()) {
+      // directExecutor() cannot throw RejectedExecutionException
+      return delegate;
+    }
+    return new Executor() {
+      volatile boolean thrownFromDelegate = true;
+      @Override public void execute(final Runnable command) {
+        try {
+          delegate.execute(new Runnable() {
+            @Override public void run() {
+              thrownFromDelegate = false;
+              command.run();
+            }
+          });
+        } catch (RejectedExecutionException e) {
+          if (thrownFromDelegate) {
+            // wrap exception?
+            future.setException(e);
+          }
+          // otherwise it must have been thrown from a transitive call and the delegate runnable
+          // should have handled it.
+        }
+      }
+    };
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is the product of
+   * applying the given {@code Function} to the result of the given {@code
+   * Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<QueryResult> queryFuture = ...;
+   *   Function<QueryResult, List<Row>> rowsFunction =
+   *       new Function<QueryResult, List<Row>>() {
+   *         public List<Row> apply(QueryResult queryResult) {
+   *           return queryResult.getRows();
+   *         }
+   *       };
+   *   ListenableFuture<List<Row>> rowsFuture =
+   *       transform(queryFuture, rowsFunction);}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code Function.apply}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in
+   * sync with that of the input future. That is, if the returned {@code Future}
+   * is cancelled, it will attempt to cancel the input, and if the input is
+   * cancelled, the returned {@code Future} will receive a callback in which it
+   * will attempt to cancel itself.
+   *
+   * <p>An example use of this method is to convert a serializable object
+   * returned from an RPC into a POJO.
+   *
+   * @param input The future to transform
+   * @param function A Function to transform the results of the provided future
+   *     to the results of the returned future.  This will be run in the thread
+   *     that notifies input it is complete.
+   * @return A future that holds result of the transformation.
+   * @since 9.0 (in 1.0 as {@code compose})
+   */
+  public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+      final Function<? super I, ? extends O> function) {
+    checkNotNull(function);
+    ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+    input.addListener(output, directExecutor());
+    return output;
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is the product of
+   * applying the given {@code Function} to the result of the given {@code
+   * Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<QueryResult> queryFuture = ...;
+   *   Function<QueryResult, List<Row>> rowsFunction =
+   *       new Function<QueryResult, List<Row>>() {
+   *         public List<Row> apply(QueryResult queryResult) {
+   *           return queryResult.getRows();
+   *         }
+   *       };
+   *   ListenableFuture<List<Row>> rowsFuture =
+   *       transform(queryFuture, rowsFunction, executor);}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code Function.apply}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in
+   * sync with that of the input future. That is, if the returned {@code Future}
+   * is cancelled, it will attempt to cancel the input, and if the input is
+   * cancelled, the returned {@code Future} will receive a callback in which it
+   * will attempt to cancel itself.
+   *
+   * <p>An example use of this method is to convert a serializable object
+   * returned from an RPC into a POJO.
+   *
+   * @param input The future to transform
+   * @param function A Function to transform the results of the provided future
+   *     to the results of the returned future.
+   * @param executor Executor to run the function in.
+   * @return A future that holds result of the transformation.
+   * @since 9.0 (in 2.0 as {@code compose})
+   */
+  public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+      final Function<? super I, ? extends O> function, Executor executor) {
+    checkNotNull(function);
+    ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+    input.addListener(output, rejectionPropagatingExecutor(executor, output));
+    return output;
+  }
+
+  /**
+   * An implementation of {@code ListenableFuture} that also implements
+   * {@code Runnable} so that it can be used to nest ListenableFutures.
+   * Once the passed-in {@code ListenableFuture} is complete, it calls the
+   * passed-in {@code Function} to generate the result.
+   *
+   * <p>For historical reasons, this class has a special case in its exception
+   * handling: If the given {@code AsyncFunction} throws an {@code
+   * UndeclaredThrowableException}, {@code ChainingListenableFuture} unwraps it
+   * and uses its <i>cause</i> as the output future's exception, rather than
+   * using the {@code UndeclaredThrowableException} itself as it would for other
+   * exception types. The reason for this is that {@code Futures.transform} used
+   * to require a {@code Function}, whose {@code apply} method is not allowed to
+   * throw checked exceptions. Nowadays, {@code Futures.transform} has an
+   * overload that accepts an {@code AsyncFunction}, whose {@code apply} method
+   * <i>is</i> allowed to throw checked exception. Users who wish to throw
+   * checked exceptions should use that overload instead, and <a
+   * href="http://code.google.com/p/guava-libraries/issues/detail?id=1548">we
+   * should remove the {@code UndeclaredThrowableException} special case</a>.
+   */
+  private abstract static class AbstractChainingFuture<I, O, F>
+      extends AbstractFuture.TrustedFuture<O> implements Runnable {
+    // In theory, this field might not be visible to a cancel() call in certain circumstances. For
+    // details, see the comments on the fields of TimeoutFuture.
+    @Nullable ListenableFuture<? extends I> inputFuture;
+    @Nullable F function;
+
+    AbstractChainingFuture(ListenableFuture<? extends I> inputFuture, F function) {
+      this.inputFuture = checkNotNull(inputFuture);
+      this.function = checkNotNull(function);
+    }
+
+    @Override
+    public final void run() {
+      try {
+        ListenableFuture<? extends I> localInputFuture = inputFuture;
+        F localFunction = function;
+        if (isCancelled() | localInputFuture == null | localFunction == null) {
+          return;
+        }
+        inputFuture = null;
+        function = null;
+
+        I sourceResult;
+        try {
+          sourceResult = getUninterruptibly(localInputFuture);
+        } catch (CancellationException e) {
+          // Cancel this future and return.
+          // At this point, inputFuture is cancelled and outputFuture doesn't
+          // exist, so the value of mayInterruptIfRunning is irrelevant.
+          cancel(false);
+          return;
+        } catch (ExecutionException e) {
+          // Set the cause of the exception as this future's exception
+          setException(e.getCause());
+          return;
+        }
+        doTransform(localFunction, sourceResult);
+      } catch (UndeclaredThrowableException e) {
+        // Set the cause of the exception as this future's exception
+        setException(e.getCause());
+      } catch (Throwable t) {
+        // This exception is irrelevant in this thread, but useful for the
+        // client
+        setException(t);
+      }
+    }
+
+    /** Template method for subtypes to actually run the transform. */
+    abstract void doTransform(F function, I result) throws Exception;
+
+    @Override final void done() {
+      maybePropagateCancellation(inputFuture);
+      this.inputFuture = null;
+      this.function = null;
+    }
+  }
+
+  /**
+   * A {@link AbstractChainingFuture} that delegates to an {@link AsyncFunction} and
+   * {@link #setFuture(ListenableFuture)} to implement {@link #doTransform}.
+   */
+  private static final class AsyncChainingFuture<I, O>
+      extends AbstractChainingFuture<I, O, AsyncFunction<? super I, ? extends O>> {
+    AsyncChainingFuture(ListenableFuture<? extends I> inputFuture,
+        AsyncFunction<? super I, ? extends O> function) {
+      super(inputFuture, function);
+    }
+
+    @Override
+    void doTransform(AsyncFunction<? super I, ? extends O> function, I input) throws Exception {
+      ListenableFuture<? extends O> outputFuture = function.apply(input);
+      checkNotNull(outputFuture, "AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+      setFuture(outputFuture);
+    }
+  }
+
+  /**
+   * A {@link AbstractChainingFuture} that delegates to a {@link Function} and
+   * {@link #set(Object)} to implement {@link #doTransform}.
+   */
+  private static final class ChainingFuture<I, O>
+      extends AbstractChainingFuture<I, O, Function<? super I, ? extends O>> {
+
+    ChainingFuture(ListenableFuture<? extends I> inputFuture,
+        Function<? super I, ? extends O> function) {
+      super(inputFuture, function);
+    }
+
+    @Override
+    void doTransform(Function<? super I, ? extends O> function, I input) {
+      // TODO(lukes): move the UndeclaredThrowable catch block here?
+      set(function.apply(input));
+    }
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is the product of
+   * calling {@code get()} on the {@code Future} nested within the given {@code
+   * Future}, effectively chaining the futures one after the other.  Example:
+   *
+   * <pre>   {@code
+   *   SettableFuture<ListenableFuture<String>> nested = SettableFuture.create();
+   *   ListenableFuture<String> dereferenced = dereference(nested);}</pre>
+   *
+   * <p>This call has the same cancellation and execution semantics as {@link
+   * #transform(ListenableFuture, AsyncFunction)}, in that the returned {@code
+   * Future} attempts to keep its cancellation state in sync with both the
+   * input {@code Future} and the nested {@code Future}.  The transformation
+   * is very lightweight and therefore takes place in the same thread (either
+   * the thread that called {@code dereference}, or the thread in which the
+   * dereferenced future completes).
+   *
+   * @param nested The nested future to transform.
+   * @return A future that holds result of the inner future.
+   * @since 13.0
+   */
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> dereference(
+      ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
+    return transformAsync((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
+  }
+
+  /**
+   * Helper {@code Function} for {@link #dereference}.
+   */
+  private static final AsyncFunction<ListenableFuture<Object>, Object> DEREFERENCER =
+      new AsyncFunction<ListenableFuture<Object>, Object>() {
+        @Override public ListenableFuture<Object> apply(ListenableFuture<Object> input) {
+          return input;
+        }
+      };
+
+  /**
+   * Creates a new {@code ListenableFuture} whose value is a list containing the
+   * values of all its input futures, if all succeed. If any input fails, the
+   * returned future fails immediately.
+   *
+   * <p>The list of results is in the same order as the input list.
+   *
+   * <p>Canceling this future will attempt to cancel all the component futures,
+   * and if any of the provided futures fails or is canceled, this one is,
+   * too.
+   *
+   * @param futures futures to combine
+   * @return a future that provides a list of the results of the component
+   *         futures
+   * @since 10.0
+   */
+  @Beta
+  @SafeVarargs
+  @CheckReturnValue
+  public static <V> ListenableFuture<List<V>> allAsList(
+      ListenableFuture<? extends V>... futures) {
+    return new ListFuture<V>(ImmutableList.copyOf(futures), true);
+  }
+
+  /**
+   * Creates a new {@code ListenableFuture} whose value is a list containing the
+   * values of all its input futures, if all succeed. If any input fails, the
+   * returned future fails immediately.
+   *
+   * <p>The list of results is in the same order as the input list.
+   *
+   * <p>Canceling this future will attempt to cancel all the component futures,
+   * and if any of the provided futures fails or is canceled, this one is,
+   * too.
+   *
+   * @param futures futures to combine
+   * @return a future that provides a list of the results of the component
+   *         futures
+   * @since 10.0
+   */
+  @Beta
+  @CheckReturnValue
+  public static <V> ListenableFuture<List<V>> allAsList(
+      Iterable<? extends ListenableFuture<? extends V>> futures) {
+    return new ListFuture<V>(ImmutableList.copyOf(futures), true);
+  }
+
+  /**
+   * Creates a new {@code ListenableFuture} whose value is a list containing the
+   * values of all its successful input futures. The list of results is in the
+   * same order as the input list, and if any of the provided futures fails or
+   * is canceled, its corresponding position will contain {@code null} (which is
+   * indistinguishable from the future having a successful value of
+   * {@code null}).
+   *
+   * <p>Canceling this future will attempt to cancel all the component futures.
+   *
+   * @param futures futures to combine
+   * @return a future that provides a list of the results of the component
+   *         futures
+   * @since 10.0
+   */
+  @Beta
+  @SafeVarargs
+  @CheckReturnValue
+  public static <V> ListenableFuture<List<V>> successfulAsList(
+      ListenableFuture<? extends V>... futures) {
+    return new ListFuture<V>(ImmutableList.copyOf(futures), false);
+  }
+
+  /**
+   * Creates a new {@code ListenableFuture} whose value is a list containing the
+   * values of all its successful input futures. The list of results is in the
+   * same order as the input list, and if any of the provided futures fails or
+   * is canceled, its corresponding position will contain {@code null} (which is
+   * indistinguishable from the future having a successful value of
+   * {@code null}).
+   *
+   * <p>Canceling this future will attempt to cancel all the component futures.
+   *
+   * @param futures futures to combine
+   * @return a future that provides a list of the results of the component
+   *         futures
+   * @since 10.0
+   */
+  @Beta
+  @CheckReturnValue
+  public static <V> ListenableFuture<List<V>> successfulAsList(
+      Iterable<? extends ListenableFuture<? extends V>> futures) {
+    return new ListFuture<V>(ImmutableList.copyOf(futures), false);
+  }
+
+  /**
+   * Registers separate success and failure callbacks to be run when the {@code
+   * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+   * complete} or, if the computation is already complete, immediately.
+   *
+   * <p>There is no guaranteed ordering of execution of callbacks, but any
+   * callback added through this method is guaranteed to be called once the
+   * computation is complete.
+   *
+   * Example: <pre> {@code
+   * ListenableFuture<QueryResult> future = ...;
+   * addCallback(future,
+   *     new FutureCallback<QueryResult> {
+   *       public void onSuccess(QueryResult result) {
+   *         storeInCache(result);
+   *       }
+   *       public void onFailure(Throwable t) {
+   *         reportError(t);
+   *       }
+   *     });}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation.
+   *
+   * <p>For a more general interface to attach a completion listener to a
+   * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+   *
+   * @param future The future attach the callback to.
+   * @param callback The callback to invoke when {@code future} is completed.
+   * @since 10.0
+   */
+  public static <V> void addCallback(ListenableFuture<V> future,
+      FutureCallback<? super V> callback) {
+    addCallback(future, callback, directExecutor());
+  }
+
+  /**
+   * Registers separate success and failure callbacks to be run when the {@code
+   * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+   * complete} or, if the computation is already complete, immediately.
+   *
+   * <p>The callback is run in {@code executor}.
+   * There is no guaranteed ordering of execution of callbacks, but any
+   * callback added through this method is guaranteed to be called once the
+   * computation is complete.
+   *
+   * Example: <pre> {@code
+   * ListenableFuture<QueryResult> future = ...;
+   * Executor e = ...
+   * addCallback(future,
+   *     new FutureCallback<QueryResult> {
+   *       public void onSuccess(QueryResult result) {
+   *         storeInCache(result);
+   *       }
+   *       public void onFailure(Throwable t) {
+   *         reportError(t);
+   *       }
+   *     }, e);}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   *
+   * <p>For a more general interface to attach a completion listener to a
+   * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+   *
+   * @param future The future attach the callback to.
+   * @param callback The callback to invoke when {@code future} is completed.
+   * @param executor The executor to run {@code callback} when the future
+   *    completes.
+   * @since 10.0
+   */
+  public static <V> void addCallback(final ListenableFuture<V> future,
+      final FutureCallback<? super V> callback, Executor executor) {
+    Preconditions.checkNotNull(callback);
+    Runnable callbackListener = new Runnable() {
+      @Override
+      public void run() {
+        final V value;
+        try {
+          // TODO(user): (Before Guava release), validate that this
+          // is the thing for IE.
+          value = getUninterruptibly(future);
+        } catch (ExecutionException e) {
+          callback.onFailure(e.getCause());
+          return;
+        } catch (RuntimeException e) {
+          callback.onFailure(e);
+          return;
+        } catch (Error e) {
+          callback.onFailure(e);
+          return;
+        }
+        callback.onSuccess(value);
+      }
+    };
+    future.addListener(callbackListener, executor);
+  }
+
+  /*
+   * Arguably we don't need a timed getUnchecked because any operation slow
+   * enough to require a timeout is heavyweight enough to throw a checked
+   * exception and therefore be inappropriate to use with getUnchecked. Further,
+   * it's not clear that converting the checked TimeoutException to a
+   * RuntimeException -- especially to an UncheckedExecutionException, since it
+   * wasn't thrown by the computation -- makes sense, and if we don't convert
+   * it, the user still has to write a try-catch block.
+   *
+   * If you think you would use this method, let us know. You might also also
+   * look into the Fork-Join framework:
+   * http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
+   */
+
+  /** Used for {@link #allAsList} and {@link #successfulAsList}. */
+  private static final class ListFuture<V> extends CollectionFuture<V, List<V>> {
+    ListFuture(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+        boolean allMustSucceed) {
+      init(new ListFutureRunningState(futures, allMustSucceed));
+    }
+
+    private final class ListFutureRunningState extends CollectionFutureRunningState {
+      ListFutureRunningState(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+        boolean allMustSucceed) {
+        super(futures, allMustSucceed);
+      }
+
+      @Override
+      public List<V> combine(List<Optional<V>> values) {
+        List<V> result = Lists.newArrayList();
+        for (Optional<V> element : values) {
+          result.add(element != null ? element.orNull() : null);
+        }
+        return Collections.unmodifiableList(result);
+      }
+    }
+  }
+}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
new file mode 100644
index 0000000..e156427
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
@@ -0,0 +1,73 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures.AsyncCatchingFuture;
+import com.google.common.util.concurrent.Futures.CatchingFuture;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Hidden superclass of {@link Futures} that provides us a place to declare special GWT versions of
+ * the {@link Futures#catching(ListenableFuture, Class, com.google.common.base.Function)
+ * Futures.catching} family of methods. Those versions have slightly different signatures.
+ */
+abstract class GwtFuturesCatchingSpecialization {
+  /*
+   * In the GWT versions of the methods (below), every exceptionType parameter is required to be
+   * Class<Throwable>. To handle only certain kinds of exceptions under GWT, you'll need to write
+   * your own instanceof tests.
+   */
+
+  public static <V> ListenableFuture<V> catching(
+      ListenableFuture<? extends V> input,
+      Class<Throwable> exceptionType,
+      Function<? super Throwable, ? extends V> fallback) {
+    return catching(input, exceptionType, fallback, directExecutor());
+  }
+
+  public static <V> ListenableFuture<V> catching(
+      ListenableFuture<? extends V> input,
+      Class<Throwable> exceptionType,
+      Function<? super Throwable, ? extends V> fallback,
+      Executor executor) {
+    CatchingFuture future = new CatchingFuture<V, Throwable>(input, exceptionType, fallback);
+    input.addListener(future, executor);
+    return future;
+  }
+
+  public static <V> ListenableFuture<V> catchingAsync(
+      ListenableFuture<? extends V> input,
+      Class<Throwable> exceptionType,
+      AsyncFunction<? super Throwable, ? extends V> fallback) {
+    return catchingAsync(input, exceptionType, fallback, directExecutor());
+  }
+
+  public static <V> ListenableFuture<V> catchingAsync(
+      ListenableFuture<? extends V> input,
+      Class<Throwable> exceptionType,
+      AsyncFunction<? super Throwable, ? extends V> fallback,
+      Executor executor) {
+    AsyncCatchingFuture<V, Throwable> future =
+        new AsyncCatchingFuture<V, Throwable>(input, exceptionType, fallback);
+    input.addListener(future, executor);
+    return future;
+  }
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
similarity index 62%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
index ff45a39..d5b4209 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
+package com.google.common.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation for InterruptibleTask in GWT.
  */
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
-  EmptyImmutableSortedSet(Comparator<? super E> comparator) {
-    super(Sets.newTreeSet(comparator));
+abstract class InterruptibleTask implements Runnable {
+  @Override public void run() {
+    runInterruptibly();
   }
+
+  abstract void runInterruptibly();
+
+  abstract boolean wasInterrupted();
+
+  final void interruptTask() {}
 }
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java
new file mode 100644
index 0000000..3042fff
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.concurrent;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
+ * ExecutorService}, and {@link ThreadFactory}.
+ *
+ * @author Eric Fellheimer
+ * @author Kyle Littlefield
+ * @author Justin Mahoney
+ * @since 3.0
+ */
+ at GwtCompatible(emulated = true)
+public final class MoreExecutors {
+  private MoreExecutors() {}
+
+  // See sameThreadExecutor javadoc for behavioral notes.
+
+  /**
+   * Returns an {@link Executor} that runs each task in the thread that invokes
+   * {@link Executor#execute execute}, as in {@link CallerRunsPolicy}.
+   *
+   * <p>This instance is equivalent to: <pre>   {@code
+   *   final class DirectExecutor implements Executor {
+   *     public void execute(Runnable r) {
+   *       r.run();
+   *     }
+   *   }}</pre>
+   *
+   * <p>This should be preferred to {@link #newDirectExecutorService()} because the implementing the
+   * {@link ExecutorService} subinterface necessitates significant performance overhead.
+   *
+   * @since 18.0
+   */
+  public static Executor directExecutor() {
+    return DirectExecutor.INSTANCE;
+  }
+
+  /** See {@link #directExecutor} for behavioral notes. */
+  private enum DirectExecutor implements Executor {
+    INSTANCE;
+    @Override public void execute(Runnable command) {
+      command.run();
+    }
+
+    @Override public String toString() {
+      return "MoreExecutors.directExecutor()";
+    }
+  }
+
+  /*
+   * This following method is a modified version of one found in
+   * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck/AbstractExecutorServiceTest.java?revision=1.30
+   * which contained the following notice:
+   *
+   * Written by Doug Lea with assistance from members of JCP JSR-166
+   * Expert Group and released to the public domain, as explained at
+   * http://creativecommons.org/publicdomain/zero/1.0/
+   * Other contributors include Andrew Wright, Jeffrey Hayes,
+   * Pat Fisher, Mike Judd.
+   */
+
+  // TODO(lukes): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
+  // TODO(lukes): provide overloads that take constant strings? Function<Runnable, String>s to
+  // calculate names?
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
similarity index 56%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
index ff45a39..fc75d67 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
+package com.google.common.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Methods factored out so that they can be emulated differently in GWT.
  */
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
-  EmptyImmutableSortedSet(Comparator<? super E> comparator) {
-    super(Sets.newTreeSet(comparator));
+final class Platform {
+  static boolean isInstanceOfThrowableClass(Throwable t, Class<? extends Throwable> expectedClass) {
+    /*
+     * This method is used only by CatchingFuture, and CatchingFuture accepts only Throwable.class
+     * under GWT.
+     */
+    return true;
   }
+
+  private Platform() {}
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
similarity index 51%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
index 1520d58..86eacb0 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,23 +14,25 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
-import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 /**
- * GWT emulation of {@link EmptyImmutableBiMap}.
- *
- * @author Hayward Chan
+ * Emulation of Uninterruptibles in GWT.
  */
- at SuppressWarnings("serial")
-final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
-  static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
+public final class Uninterruptibles {
 
-  private EmptyImmutableBiMap() {
-    super(Collections.emptyMap());
+  private Uninterruptibles() {
   }
-  @Override public ImmutableBiMap<Object, Object> inverse() {
-    return this;
+
+  public static <V> V getUninterruptibly(Future<V> future) throws ExecutionException {
+    try {
+      return future.get();
+    } catch (InterruptedException e) {
+      // Should never be thrown in GWT but play it safe
+      throw new IllegalStateException(e);
+    }
   }
 }
diff --git a/guava-gwt/src-super/java/lang/Lang.gwt.xml b/guava-gwt/src-super/java/lang/Lang.gwt.xml
new file mode 100644
index 0000000..bd7134f
--- /dev/null
+++ b/guava-gwt/src-super/java/lang/Lang.gwt.xml
@@ -0,0 +1 @@
+<module><super-source path="super"/></module>
\ No newline at end of file
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java b/guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
similarity index 59%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java
rename to guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
index 2e36f39..3592c60 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java
+++ b/guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
-import java.util.SortedMap;
+package java.lang;
 
 /**
- * GWT emulated version of {@link RegularImmutableSortedMap}.
+ * Minimal emulation of {@link java.lang.InterruptedException}, that should
+ * only be used in method signatures.  New GWT code should not reference this
+ * class at all.  It is here only to ease the GWTification of common code.
  *
- * @author Chris Povirk
+ * @author Tom O'Neill
  */
-final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
-  RegularImmutableSortedMap(SortedMap<K, V> delegate, Comparator<? super K> comparator) {
-    super(delegate, comparator);
+public class InterruptedException extends Exception {
+  public InterruptedException() {}
+
+  public InterruptedException(String message) {
+    super(message);
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java b/guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
similarity index 53%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
rename to guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
index 1520d58..a7daad8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
+++ b/guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,23 +14,21 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Collections;
+package java.lang.reflect;
 
 /**
- * GWT emulation of {@link EmptyImmutableBiMap}.
- *
- * @author Hayward Chan
+ * GWT emulation of UndeclaredThrowableException.
  */
- at SuppressWarnings("serial")
-final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
-  static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
+public class UndeclaredThrowableException extends RuntimeException {
+  public UndeclaredThrowableException(Throwable undeclaredThrowable) {
+    super(undeclaredThrowable);
+  }
 
-  private EmptyImmutableBiMap() {
-    super(Collections.emptyMap());
+  public UndeclaredThrowableException(Throwable undeclaredThrowable, String message) {
+    super(message, undeclaredThrowable);
   }
-  @Override public ImmutableBiMap<Object, Object> inverse() {
-    return this;
+
+  public Throwable getUndeclaredThrowable() {
+    return getCause();
   }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
similarity index 59%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java
rename to guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
index ae3b3f3..24636e3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Collections;
+package java.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSet}.
- *
- * @author Hayward Chan
+ * Emulation of CancellationException.
  */
-final class EmptyImmutableSet extends ForwardingImmutableSet<Object> {
-  private EmptyImmutableSet() {
-    super(Collections.emptySet());
-  }
+public class CancellationException extends IllegalStateException {
 
-  static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
+  public CancellationException() {}
+  
+  public CancellationException(String message) {
+    super(message);
+  }
 }
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java
new file mode 100644
index 0000000..b353296
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java
@@ -0,0 +1,55 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of CountDownLatch in GWT. Since GWT environment is single threaded, attempting to block
+ * on the latch by calling {@link #await()} or {@link #await(long, TimeUnit)} when it is not ready
+ * is considered illegal because it would lead to a deadlock. Both methods will throw {@link
+ * IllegalStateException} to avoid the deadlock.
+ */
+public class CountDownLatch {
+
+  private int count;
+
+  public CountDownLatch(int count) {
+    if (count < 0) {
+      throw new IllegalArgumentException("count < 0");
+    }
+    this.count = count;
+  }
+
+  public void await() throws InterruptedException {
+    if (count > 0) {
+      throw new IllegalStateException("May not block. Count is " + count);
+    }
+  }
+
+  public boolean await(long timeout, TimeUnit unit)
+      throws InterruptedException {
+    await();
+    return true;
+  }
+
+  public void countDown() {
+    if (count > 0) {
+      count--;
+    }
+  }
+
+  public long getCount() {
+    return count;
+  }
+
+  public String toString() {
+    return super.toString() + "[Count = " + count + "]";
+  }
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java
new file mode 100644
index 0000000..4bfca00
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java
@@ -0,0 +1,18 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of Delayed.
+ */
+public interface Delayed extends Comparable<Delayed> {
+ long getDelay(TimeUnit unit);
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
similarity index 61%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
index ff45a39..35fc246 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,11 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of Executor.
  */
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
-  EmptyImmutableSortedSet(Comparator<? super E> comparator) {
-    super(Sets.newTreeSet(comparator));
-  }
-}
+public interface Executor {
+  void execute(Runnable command);
+}
\ No newline at end of file
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java
new file mode 100644
index 0000000..09a3e8d
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java
@@ -0,0 +1,50 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/Executors.java?revision=1.90
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of executors.
+ */
+public class Executors {
+
+  public static <T> Callable<T> callable(Runnable task, T result) {
+    if (task == null) {
+      throw new NullPointerException();
+    }
+    return new RunnableAdapter<T>(task, result);
+  }
+
+  public static Callable<Object> callable(Runnable task) {
+    if (task == null) {
+      throw new NullPointerException();
+    }
+    return new RunnableAdapter<Object>(task, null);
+  }
+
+  static final class RunnableAdapter<T> implements Callable<T> {
+
+    final Runnable task;
+    final T result;
+
+    RunnableAdapter(Runnable task, T result) {
+      this.task = task;
+      this.result = result;
+    }
+
+    public T call() {
+      task.run();
+      return result;
+    }
+  }
+
+  private Executors() {
+  }
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java
new file mode 100644
index 0000000..db07080
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 java.util.concurrent;
+
+/**
+ * Emulation of Future. Since GWT environment is single threaded, attempting to block on the future
+ * by calling {@link #get()} or {@link #get(long, TimeUnit)} when the it is not yet done is
+ * considered illegal because it would lead to a deadlock. Future implementations must throw
+ * {@link IllegalStateException} to avoid a deadlock.
+ */
+public interface Future<V> {
+   boolean cancel(boolean mayInterruptIfRunning);
+
+   boolean isCancelled();
+
+   boolean isDone();
+    
+   V get() throws InterruptedException, ExecutionException;
+
+   V get(long timeout, TimeUnit unit)
+       throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/guava/src/com/google/common/collect/SortedMultisetBridge.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
similarity index 55%
copy from guava/src/com/google/common/collect/SortedMultisetBridge.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
index 669b54d..ec7c2da 100644
--- a/guava/src/com/google/common/collect/SortedMultisetBridge.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,18 +14,24 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.SortedSet;
+package java.util.concurrent;
 
 /**
- * Superinterface of {@link SortedMultiset} to introduce a bridge method for
- * {@code elementSet()}, to ensure binary compatibility with older Guava versions
- * that specified {@code elementSet()} to return {@code SortedSet}.
- * 
- * @author Louis Wasserman
+ * GWT emulation of RejectedExecutionException.
  */
-interface SortedMultisetBridge<E> extends Multiset<E> {
-  @Override
-  SortedSet<E> elementSet();
+public class RejectedExecutionException extends RuntimeException {
+  public RejectedExecutionException() {
+  }
+
+  public RejectedExecutionException(String message) {
+    super(message);
+  }
+
+  public RejectedExecutionException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public RejectedExecutionException(Throwable cause) {
+    super(cause);
+  }
 }
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
similarity index 61%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
index ff45a39..08e2660 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,10 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of RunnableFuture.
  */
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
-  EmptyImmutableSortedSet(Comparator<? super E> comparator) {
-    super(Sets.newTreeSet(comparator));
-  }
+public interface RunnableFuture<V> extends Runnable, Future<V> {
 }
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java
new file mode 100644
index 0000000..616acab
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java
@@ -0,0 +1,19 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of ScheduleFuture.
+ *
+ * @param <V> value type returned by the future.
+ */
+public interface ScheduledFuture<V> extends Delayed, Future<V> {
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
index 52f3fb4..ba891b3 100644
--- a/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
@@ -17,77 +17,77 @@ package java.util.concurrent;
 public enum TimeUnit {
   NANOSECONDS {
     public long toNanos(long d)   { return d; }
-    public long toMicros(long d)  { return d/(C1/C0); }
-    public long toMillis(long d)  { return d/(C2/C0); }
-    public long toSeconds(long d) { return d/(C3/C0); }
-    public long toMinutes(long d) { return d/(C4/C0); }
-    public long toHours(long d)   { return d/(C5/C0); }
-    public long toDays(long d)    { return d/(C6/C0); }
+    public long toMicros(long d)  { return d / C1_C0; }
+    public long toMillis(long d)  { return d / C2_C0; }
+    public long toSeconds(long d) { return d / C3_C0; }
+    public long toMinutes(long d) { return d / C4_C0; }
+    public long toHours(long d)   { return d / C5_C0; }
+    public long toDays(long d)    { return d / C6_C0; }
     public long convert(long d, TimeUnit u) { return u.toNanos(d); }
     int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
   },
   MICROSECONDS {
-    public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
+    public long toNanos(long d)   { return x(d, C1_C0, MAX_C1_C0); }
     public long toMicros(long d)  { return d; }
-    public long toMillis(long d)  { return d/(C2/C1); }
-    public long toSeconds(long d) { return d/(C3/C1); }
-    public long toMinutes(long d) { return d/(C4/C1); }
-    public long toHours(long d)   { return d/(C5/C1); }
-    public long toDays(long d)    { return d/(C6/C1); }
+    public long toMillis(long d)  { return d / C2_C1; }
+    public long toSeconds(long d) { return d / C3_C1; }
+    public long toMinutes(long d) { return d / C4_C1; }
+    public long toHours(long d)   { return d / C5_C1; }
+    public long toDays(long d)    { return d / C6_C1; }
     public long convert(long d, TimeUnit u) { return u.toMicros(d); }
     int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
   },
   MILLISECONDS {
-    public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
-    public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
+    public long toNanos(long d)   { return x(d, C2_C0, MAX_C2_C0); }
+    public long toMicros(long d)  { return x(d, C2_C1, MAX_C2_C1); }
     public long toMillis(long d)  { return d; }
-    public long toSeconds(long d) { return d/(C3/C2); }
-    public long toMinutes(long d) { return d/(C4/C2); }
-    public long toHours(long d)   { return d/(C5/C2); }
-    public long toDays(long d)    { return d/(C6/C2); }
+    public long toSeconds(long d) { return d / C3_C2; }
+    public long toMinutes(long d) { return d / C4_C2; }
+    public long toHours(long d)   { return d / C5_C2; }
+    public long toDays(long d)    { return d / C6_C2; }
     public long convert(long d, TimeUnit u) { return u.toMillis(d); }
     int excessNanos(long d, long m) { return 0; }
   },
   SECONDS {
-    public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
-    public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
-    public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
+    public long toNanos(long d)   { return x(d, C3_C0, MAX_C3_C0); }
+    public long toMicros(long d)  { return x(d, C3_C1, MAX_C3_C1); }
+    public long toMillis(long d)  { return x(d, C3_C2, MAX_C3_C2); }
     public long toSeconds(long d) { return d; }
-    public long toMinutes(long d) { return d/(C4/C3); }
-    public long toHours(long d)   { return d/(C5/C3); }
-    public long toDays(long d)    { return d/(C6/C3); }
+    public long toMinutes(long d) { return d / C4_C3; }
+    public long toHours(long d)   { return d / C5_C3; }
+    public long toDays(long d)    { return d / C6_C3; }
     public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
     int excessNanos(long d, long m) { return 0; }
   },
   MINUTES {
-    public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
-    public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
-    public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
-    public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
+    public long toNanos(long d)   { return x(d, C4_C0, MAX_C4_C0); }
+    public long toMicros(long d)  { return x(d, C4_C1, MAX_C4_C1); }
+    public long toMillis(long d)  { return x(d, C4_C2, MAX_C4_C2); }
+    public long toSeconds(long d) { return x(d, C4_C3, MAX_C4_C3); }
     public long toMinutes(long d) { return d; }
-    public long toHours(long d)   { return d/(C5/C4); }
-    public long toDays(long d)    { return d/(C6/C4); }
+    public long toHours(long d)   { return d / C5_C4; }
+    public long toDays(long d)    { return d / C6_C4; }
     public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
     int excessNanos(long d, long m) { return 0; }
   },
   HOURS {
-    public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
-    public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
-    public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
-    public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
-    public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
+    public long toNanos(long d)   { return x(d, C5_C0, MAX_C5_C0); }
+    public long toMicros(long d)  { return x(d, C5_C1, MAX_C5_C1); }
+    public long toMillis(long d)  { return x(d, C5_C2, MAX_C5_C2); }
+    public long toSeconds(long d) { return x(d, C5_C3, MAX_C5_C3); }
+    public long toMinutes(long d) { return x(d, C5_C4, MAX_C5_C4); }
     public long toHours(long d)   { return d; }
-    public long toDays(long d)    { return d/(C6/C5); }
+    public long toDays(long d)    { return d / C6_C5; }
     public long convert(long d, TimeUnit u) { return u.toHours(d); }
     int excessNanos(long d, long m) { return 0; }
   },
   DAYS {
-    public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
-    public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
-    public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
-    public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
-    public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
-    public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
+    public long toNanos(long d)   { return x(d, C6_C0, MAX_C6_C0); }
+    public long toMicros(long d)  { return x(d, C6_C1, MAX_C6_C1); }
+    public long toMillis(long d)  { return x(d, C6_C2, MAX_C6_C2); }
+    public long toSeconds(long d) { return x(d, C6_C3, MAX_C6_C3); }
+    public long toMinutes(long d) { return x(d, C6_C4, MAX_C6_C4); }
+    public long toHours(long d)   { return x(d, C6_C5, MAX_C6_C5); }
     public long toDays(long d)    { return d; }
     public long convert(long d, TimeUnit u) { return u.toDays(d); }
     int excessNanos(long d, long m) { return 0; }
@@ -103,7 +103,61 @@ public enum TimeUnit {
   static final long C6 = C5 * 24L;
 
   static final long MAX = Long.MAX_VALUE;
+  
+  static final long C6_C0 = C6 / C0;
+  static final long C6_C1 = C6 / C1;
+  static final long C6_C2 = C6 / C2;
+  static final long C6_C3 = C6 / C3;
+  static final long C6_C4 = C6 / C4;
+  static final long C6_C5 = C6 / C5;
 
+  static final long C5_C0 = C5 / C0;
+  static final long C5_C1 = C5 / C1;
+  static final long C5_C2 = C5 / C2;
+  static final long C5_C3 = C5 / C3;
+  static final long C5_C4 = C5 / C4;
+
+  static final long C4_C0 = C4 / C0;
+  static final long C4_C1 = C4 / C1;
+  static final long C4_C2 = C4 / C2;
+  static final long C4_C3 = C4 / C3;
+  
+  static final long C3_C0 = C3 / C0;
+  static final long C3_C1 = C3 / C1;
+  static final long C3_C2 = C3 / C2;
+  
+  static final long C2_C0 = C2 / C0;
+  static final long C2_C1 = C2 / C1;
+  
+  static final long C1_C0 = C1 / C0;
+
+  static final long MAX_C6_C0 = MAX / C6_C0;
+  static final long MAX_C6_C1 = MAX / C6_C1;
+  static final long MAX_C6_C2 = MAX / C6_C2;
+  static final long MAX_C6_C3 = MAX / C6_C3;
+  static final long MAX_C6_C4 = MAX / C6_C4;
+  static final long MAX_C6_C5 = MAX / C6_C5;
+
+  static final long MAX_C5_C0 = MAX / C5_C0;
+  static final long MAX_C5_C1 = MAX / C5_C1;
+  static final long MAX_C5_C2 = MAX / C5_C2;
+  static final long MAX_C5_C3 = MAX / C5_C3;
+  static final long MAX_C5_C4 = MAX / C5_C4;
+
+  static final long MAX_C4_C0 = MAX / C4_C0;
+  static final long MAX_C4_C1 = MAX / C4_C1;
+  static final long MAX_C4_C2 = MAX / C4_C2;
+  static final long MAX_C4_C3 = MAX / C4_C3;
+
+  static final long MAX_C3_C0 = MAX / C3_C0;
+  static final long MAX_C3_C1 = MAX / C3_C1;
+  static final long MAX_C3_C2 = MAX / C3_C2;
+
+  static final long MAX_C2_C0 = MAX / C2_C0;
+  static final long MAX_C2_C1 = MAX / C2_C1;
+
+  static final long MAX_C1_C0 = MAX / C1_C0;
+  
   static long x(long d, long m, long over) {
     if (d >  over) return Long.MAX_VALUE;
     if (d < -over) return Long.MIN_VALUE;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
similarity index 62%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
rename to guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
index ff45a39..63723f6 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,15 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
 
 /**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of TimeoutException.
  */
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
-  EmptyImmutableSortedSet(Comparator<? super E> comparator) {
-    super(Sets.newTreeSet(comparator));
+public class TimeoutException extends Exception {
+  public TimeoutException() {}
+
+  public TimeoutException(String message) {
+    super(message);
   }
 }
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java
new file mode 100644
index 0000000..a871204
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 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.
+ */  /**
+ * Atomically sets the value to the given updated value
+ * if the current value {@code ==} the expected value.
+ *
+ * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+ * and does not provide ordering guarantees, so is only rarely an
+ * appropriate alternative to {@code compareAndSet}.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+
+package java.util.concurrent.atomic;
+
+/**
+ * GWT emulation of AtomicBoolean.
+ */
+public class AtomicBoolean implements java.io.Serializable {
+  private boolean value;
+
+  public AtomicBoolean(boolean initialValue) {
+    value = initialValue;
+  }
+
+  public AtomicBoolean() {
+  }
+
+  public final boolean get() {
+    return value;
+  }
+
+  public final boolean compareAndSet(boolean expect, boolean update) {
+    if (get() == expect) {
+      set(update);
+      return true;
+    }
+
+    return false;
+  }
+
+  public boolean weakCompareAndSet(boolean expect, boolean update) {
+    return compareAndSet(expect, update);
+  }
+
+  public final void set(boolean newValue) {
+    value = newValue;
+  }
+
+  public final void lazySet(boolean newValue) {
+    set(newValue);
+  }
+
+  public final boolean getAndSet(boolean newValue) {
+    boolean current = get();
+    set(newValue);
+    return current;
+  }
+
+  public String toString() {
+    return Boolean.toString(get());
+  }
+}
diff --git a/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml b/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
index 7338d55..dde2a98 100644
--- a/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
+++ b/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
@@ -13,7 +13,7 @@
   <!-- We used to set this only for packages that had manual supersource. That worked everywhere that I know of except for one place: when running the GWT util.concurrent tests under Guava. The problem is that GWT responds poorly to two .gwt.xml files in the same Java package: http://goo.gl/CO7dLB The summary is that it ignores one file in favor of the other. util.concurrent, like nearly all our packages, has two .gwt.xml files: one for prod and one for tests. util.concurrent, unlike our [...]
    
   <super-source path="super"/>
-    
+     
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/src/com/google/common/base/Base.gwt.xml b/guava-gwt/src/com/google/common/base/Base.gwt.xml
index 6041565..955a3c1 100644
--- a/guava-gwt/src/com/google/common/base/Base.gwt.xml
+++ b/guava-gwt/src/com/google/common/base/Base.gwt.xml
@@ -21,7 +21,7 @@
   <inherits name="java.nio.charset.Charset"/>
    
   <inherits name="java.util.Util"/>
-    
+     
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java b/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
index 0ddac1f..9b93ee9 100644
--- a/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
+++ b/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
@@ -42,48 +42,58 @@ final class GwtSerializationDependencies {
       super();
     }
 
-    @Override public boolean isPresent() {
+    @Override
+    public boolean isPresent() {
       throw new AssertionError();
     }
 
-    @Override public T get() {
+    @Override
+    public T get() {
       throw new AssertionError();
     }
 
-    @Override public T or(T defaultValue) {
+    @Override
+    public T or(T defaultValue) {
       throw new AssertionError();
     }
 
-    @Override public Optional<T> or(Optional<? extends T> secondChoice) {
+    @Override
+    public Optional<T> or(Optional<? extends T> secondChoice) {
       throw new AssertionError();
     }
 
-    @Override public T or(Supplier<? extends T> supplier) {
+    @Override
+    public T or(Supplier<? extends T> supplier) {
       throw new AssertionError();
     }
 
-    @Override public T orNull() {
+    @Override
+    public T orNull() {
       throw new AssertionError();
     }
 
-    @Override public Set<T> asSet() {
+    @Override
+    public Set<T> asSet() {
       throw new AssertionError();
     }
 
-    @Override public <V> Optional<V> transform(
-        Function<? super T, V> function) {
+    @Override
+    public <V> Optional<V> transform(Function<? super T, V> function) {
       throw new AssertionError();
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       throw new AssertionError();
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       throw new AssertionError();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       throw new AssertionError();
     }
   }
diff --git a/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
index 531550c..0a34f93 100644
--- a/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
@@ -29,8 +29,8 @@ public class PairwiseEquivalence_CustomFieldSerializer {
 
   private PairwiseEquivalence_CustomFieldSerializer() {}
 
-  public static void deserialize(SerializationStreamReader reader,
-      PairwiseEquivalence<?> instance) {}
+  public static void deserialize(
+      SerializationStreamReader reader, PairwiseEquivalence<?> instance) {}
 
   public static PairwiseEquivalence<?> instantiate(SerializationStreamReader reader)
       throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
index 4b9d370..ab46c9e 100644
--- a/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
@@ -25,13 +25,11 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  * @author Chris Povirk
  */
 public class AllEqualOrdering_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader, AllEqualOrdering instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, AllEqualOrdering instance) {}
 
   public static AllEqualOrdering instantiate(SerializationStreamReader reader) {
     return AllEqualOrdering.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer, AllEqualOrdering instance) {
-  }
+  public static void serialize(SerializationStreamWriter writer, AllEqualOrdering instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
index 129562d..a58ca25 100644
--- a/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link ArrayListMultimap}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ArrayListMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader in,
-      ArrayListMultimap<?, ?> out) {
-  }
+  public static void deserialize(SerializationStreamReader in, ArrayListMultimap<?, ?> out) {}
 
-  public static ArrayListMultimap<Object, Object> instantiate(
-      SerializationStreamReader in) throws SerializationException {
+  public static ArrayListMultimap<Object, Object> instantiate(SerializationStreamReader in)
+      throws SerializationException {
     return (ArrayListMultimap<Object, Object>)
-        Multimap_CustomFieldSerializerBase.populate(
-            in, ArrayListMultimap.create());
+        Multimap_CustomFieldSerializerBase.populate(in, ArrayListMultimap.create());
   }
 
-  public static void serialize(SerializationStreamWriter out,
-      ArrayListMultimap<?, ?> multimap) throws SerializationException {
+  public static void serialize(SerializationStreamWriter out, ArrayListMultimap<?, ?> multimap)
+      throws SerializationException {
     Multimap_CustomFieldSerializerBase.serialize(out, multimap);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
index d42648c..c79b569 100644
--- a/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
@@ -23,25 +23,23 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link ByFunctionOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ByFunctionOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ByFunctionOrdering<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ByFunctionOrdering<?, ?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static ByFunctionOrdering<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static ByFunctionOrdering<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     return new ByFunctionOrdering<Object, Object>(
-        (Function<Object, Object>) reader.readObject(),
-        (Ordering<Object>) reader.readObject());
+        (Function<Object, Object>) reader.readObject(), (Ordering<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ByFunctionOrdering<?, ?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ByFunctionOrdering<?, ?> instance)
+      throws SerializationException {
     writer.writeObject(instance.function);
     writer.writeObject(instance.ordering);
   }
diff --git a/guava-gwt/src/com/google/common/collect/Collect.gwt.xml b/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
index 8b98acd..38316f9 100644
--- a/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
+++ b/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
@@ -23,9 +23,11 @@
   <inherits name="com.google.common.math.Math"/>
    
   <inherits name="com.google.common.primitives.Primitives"/>
-    
+   
+  <inherits name="java.lang.Lang"/>
+   
   <inherits name="java.util.Util"/>
-     
+      
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
index 4b0cc11..7d2e313 100644
--- a/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
@@ -24,24 +24,22 @@ import java.util.Comparator;
 
 /**
  * This class implements the GWT serialization of {@link ComparatorOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ComparatorOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ComparatorOrdering<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ComparatorOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static ComparatorOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new ComparatorOrdering<Object>(
-        (Comparator<Object>) reader.readObject());
+  public static ComparatorOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new ComparatorOrdering<Object>((Comparator<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ComparatorOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ComparatorOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.comparator);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
index 2cfd6dc..23cef62 100644
--- a/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
@@ -24,24 +24,21 @@ import java.util.Comparator;
 
 /**
  * This class implements the GWT serialization of {@link CompoundOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class CompoundOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      CompoundOrdering<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, CompoundOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static CompoundOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new CompoundOrdering<Object>(
-        (ImmutableList<Comparator<Object>>) reader.readObject());
+  public static CompoundOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new CompoundOrdering<Object>((ImmutableList<Comparator<Object>>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      CompoundOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, CompoundOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.comparators);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
index 2bc219b..c02db5b 100644
--- a/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class DenseImmutableTable_CustomFieldSerializer {
   public static void deserialize(
-      SerializationStreamReader reader, DenseImmutableTable<?, ?, ?> instance) {
-  }
+      SerializationStreamReader reader, DenseImmutableTable<?, ?, ?> instance) {}
 
   public static DenseImmutableTable<Object, Object, Object> instantiate(
       SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java
deleted file mode 100644
index c2d7a05..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of
- * {@link EmptyImmutableBiMap}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableBiMap_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader, EmptyImmutableBiMap instance) {
-  }
-
-  public static EmptyImmutableBiMap instantiate(SerializationStreamReader reader) {
-    return EmptyImmutableBiMap.INSTANCE;
-  }
-
-  public static void serialize(SerializationStreamWriter writer, EmptyImmutableBiMap instance) {
-  }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
index 8b1173e..23d706f 100644
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
@@ -22,21 +22,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 /**
  * This class implements the GWT serialization of
  * {@link EmptyImmutableListMultimap}.
- * 
+ *
  * @author Chris Povirk
  */
 public class EmptyImmutableListMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      EmptyImmutableListMultimap instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, EmptyImmutableListMultimap instance) {}
 
-  public static EmptyImmutableListMultimap instantiate(
-      SerializationStreamReader reader) {
+  public static EmptyImmutableListMultimap instantiate(SerializationStreamReader reader) {
     return EmptyImmutableListMultimap.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      EmptyImmutableListMultimap instance) {
-  }
+  public static void serialize(
+      SerializationStreamWriter writer, EmptyImmutableListMultimap instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
index 905abfb..f08d80c 100644
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
@@ -22,21 +22,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 /**
  * This class implements the GWT serialization of
  * {@link EmptyImmutableSetMultimap}.
- * 
+ *
  * @author Chris Povirk
  */
 public class EmptyImmutableSetMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      EmptyImmutableSetMultimap instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, EmptyImmutableSetMultimap instance) {}
 
-  public static EmptyImmutableSetMultimap instantiate(
-      SerializationStreamReader reader) {
+  public static EmptyImmutableSetMultimap instantiate(SerializationStreamReader reader) {
     return EmptyImmutableSetMultimap.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      EmptyImmutableSetMultimap instance) {
-  }
+  public static void serialize(
+      SerializationStreamWriter writer, EmptyImmutableSetMultimap instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java
deleted file mode 100644
index b52dac9..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link EmptyImmutableSet}.
- * 
- * @author Chris Povirk
- */
-public class EmptyImmutableSet_CustomFieldSerializer {
-
-  public static void deserialize(SerializationStreamReader reader,
-      EmptyImmutableSet instance) {
-  }
-
-  public static EmptyImmutableSet instantiate(
-      SerializationStreamReader reader) {
-    return EmptyImmutableSet.INSTANCE;
-  }
-
-  public static void serialize(SerializationStreamWriter writer,
-      EmptyImmutableSet instance) {
-  }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java
deleted file mode 100644
index a47f6a0..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link EmptyImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableSortedMap_CustomFieldSerializer {
-  public static void deserialize(
-      SerializationStreamReader reader, EmptyImmutableSortedMap<?, ?> instance) {
-  }
-
-  public static EmptyImmutableSortedMap<?, ?> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return (EmptyImmutableSortedMap<?, ?>)
-        ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
-  }
-
-  public static void serialize(
-      SerializationStreamWriter writer, EmptyImmutableSortedMap<?, ?> instance)
-      throws SerializationException {
-    ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
-  }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java
deleted file mode 100644
index 3857616..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-import java.util.Comparator;
-
-/**
- * This class implements the GWT serialization of
- * {@link EmptyImmutableSortedSet}.
- * 
- * @author Chris Povirk
- */
-public class EmptyImmutableSortedSet_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader,
-      EmptyImmutableSortedSet<?> instance) {
-  }
-
-  public static EmptyImmutableSortedSet<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    /*
-     * Nothing we can do, but we're already assuming the serialized form is
-     * correctly typed, anyway.
-     */
-    @SuppressWarnings("unchecked")
-    Comparator<Object> comparator = (Comparator<Object>) reader.readObject();
-
-    /*
-     * For this custom field serializer to be invoked, the set must have been
-     * EmptyImmutableSortedSet before it's serialized. Since
-     * EmptyImmutableSortedSet always has no elements, ImmutableSortedSet.copyOf
-     * always return an EmptyImmutableSortedSet back.
-     */
-    return (EmptyImmutableSortedSet<Object>)
-        ImmutableSortedSet.orderedBy(comparator).build();
-  }
-
-  public static void serialize(SerializationStreamWriter writer,
-      EmptyImmutableSortedSet<?> instance) throws SerializationException {
-    writer.writeObject(instance.comparator());
-  }
-}
diff --git a/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
index 89ebdf2..ffbbe49 100644
--- a/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link ExplicitOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ExplicitOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ExplicitOrdering<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, ExplicitOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static ExplicitOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new ExplicitOrdering<Object>(
-        (ImmutableMap<Object, Integer>) reader.readObject());
+  public static ExplicitOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new ExplicitOrdering<Object>((ImmutableMap<Object, Integer>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ExplicitOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ExplicitOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.rankMap);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java b/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
index 92a59fb..baaf753 100644
--- a/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
+++ b/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
@@ -60,8 +60,7 @@ import java.util.TreeMap;
 final class GwtSerializationDependencies {
   private GwtSerializationDependencies() {}
 
-  static final class ImmutableListMultimapDependencies<K, V>
-      extends ImmutableListMultimap<K, V> {
+  static final class ImmutableListMultimapDependencies<K, V> extends ImmutableListMultimap<K, V> {
     K key;
     V value;
 
@@ -74,8 +73,7 @@ final class GwtSerializationDependencies {
 
   // ImmutableMultimap is covered by ImmutableSetMultimap/ImmutableListMultimap.
 
-  static final class ImmutableSetMultimapDependencies<K, V>
-      extends ImmutableSetMultimap<K, V> {
+  static final class ImmutableSetMultimapDependencies<K, V> extends ImmutableSetMultimap<K, V> {
     K key;
     V value;
 
@@ -88,16 +86,14 @@ final class GwtSerializationDependencies {
    * We support an interface declared in terms of LinkedListMultimap because it
    * supports entry ordering not supported by other implementations.
    */
-  static final class LinkedListMultimapDependencies<K, V>
-      extends LinkedListMultimap<K, V> {
+  static final class LinkedListMultimapDependencies<K, V> extends LinkedListMultimap<K, V> {
     K key;
     V value;
 
     LinkedListMultimapDependencies() {}
   }
 
-  static final class HashBasedTableDependencies<R, C, V>
-      extends HashBasedTable<R, C, V> {
+  static final class HashBasedTableDependencies<R, C, V> extends HashBasedTable<R, C, V> {
     HashMap<R, HashMap<C, V>> data;
 
     HashBasedTableDependencies() {
@@ -105,8 +101,7 @@ final class GwtSerializationDependencies {
     }
   }
 
-  static final class TreeBasedTableDependencies<R, C, V>
-      extends TreeBasedTable<R, C, V> {
+  static final class TreeBasedTableDependencies<R, C, V> extends TreeBasedTable<R, C, V> {
     TreeMap<R, TreeMap<C, V>> data;
 
     TreeBasedTableDependencies() {
@@ -120,8 +115,8 @@ final class GwtSerializationDependencies {
    * need for GWT to believe that this dummy class is serializable, or else it
    * won't generate serialization code for R, C, and V.
    */
-  static final class ImmutableTableDependencies<R, C, V>
-      extends SingletonImmutableTable<R, C, V> implements Serializable {
+  static final class ImmutableTableDependencies<R, C, V> extends SingletonImmutableTable<R, C, V>
+      implements Serializable {
     R rowKey;
     C columnKey;
     V value;
@@ -131,8 +126,7 @@ final class GwtSerializationDependencies {
     }
   }
 
-  static final class TreeMultimapDependencies<K, V>
-      extends TreeMultimap<K, V> {
+  static final class TreeMultimapDependencies<K, V> extends TreeMultimap<K, V> {
     Comparator<? super K> keyComparator;
     Comparator<? super V> valueComparator;
     K key;
diff --git a/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
index 26f3e13..4ce2b43 100644
--- a/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
@@ -24,8 +24,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  * @author Hayward Chan
  */
 public class HashBasedTable_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader, HashBasedTable<?, ?, ?> table) {
-  }
+  public static void deserialize(SerializationStreamReader reader, HashBasedTable<?, ?, ?> table) {}
 
   public static HashBasedTable<Object, Object, Object> instantiate(SerializationStreamReader reader)
       throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
index 85611b1..d3ee4ee 100644
--- a/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
@@ -22,24 +22,22 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link HashMultimap}.
- * 
+ *
  * @author Jord Sonneveld
- * 
+ *
  */
 public class HashMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader in,
-      HashMultimap<?, ?> out) {
-  }
+  public static void deserialize(SerializationStreamReader in, HashMultimap<?, ?> out) {}
 
-  public static HashMultimap<Object, Object> instantiate(
-      SerializationStreamReader in) throws SerializationException {
+  public static HashMultimap<Object, Object> instantiate(SerializationStreamReader in)
+      throws SerializationException {
     return (HashMultimap<Object, Object>)
         Multimap_CustomFieldSerializerBase.populate(in, HashMultimap.create());
   }
 
-  public static void serialize(SerializationStreamWriter out,
-      HashMultimap<?, ?> multimap) throws SerializationException {
+  public static void serialize(SerializationStreamWriter out, HashMultimap<?, ?> multimap)
+      throws SerializationException {
     Multimap_CustomFieldSerializerBase.serialize(out, multimap);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
index ff18183..1244e1e 100644
--- a/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
@@ -27,18 +27,16 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class HashMultiset_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      HashMultiset<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, HashMultiset<?> instance) {}
 
-  public static HashMultiset<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return (HashMultiset<Object>) Multiset_CustomFieldSerializerBase.populate(
-        reader, HashMultiset.create());
+  public static HashMultiset<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return (HashMultiset<Object>)
+        Multiset_CustomFieldSerializerBase.populate(reader, HashMultiset.create());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      HashMultiset<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, HashMultiset<?> instance)
+      throws SerializationException {
     Multiset_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
index 821c33a..927a120 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
@@ -28,19 +28,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class ImmutableEntry_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ImmutableEntry<?, ?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, ImmutableEntry<?, ?> instance) {}
 
-  public static ImmutableEntry<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static ImmutableEntry<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Object key = reader.readObject();
     Object value = reader.readObject();
     return new ImmutableEntry<Object, Object>(key, value);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ImmutableEntry<?, ?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ImmutableEntry<?, ?> instance)
+      throws SerializationException {
     writer.writeObject(instance.getKey());
     writer.writeObject(instance.getValue());
   }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
index 868cb74..636364a 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
@@ -30,9 +30,8 @@ import java.util.Map;
  */
 public class ImmutableEnumMap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ImmutableEnumMap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ImmutableEnumMap<?, ?> instance) {}
 
   public static <K extends Enum<K>, V> ImmutableEnumMap<?, ?> instantiate(
       SerializationStreamReader reader) throws SerializationException {
@@ -46,9 +45,8 @@ public class ImmutableEnumMap_CustomFieldSerializer {
     return (ImmutableEnumMap<?, ?>) Maps.immutableEnumMap(deserialized);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ImmutableEnumMap<?, ?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ImmutableEnumMap<?, ?> instance)
+      throws SerializationException {
     Map_CustomFieldSerializerBase.serialize(writer, instance);
   }
-
 }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
index 8b5a66d..e494a8f 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
@@ -30,9 +30,7 @@ import java.util.List;
  */
 public class ImmutableEnumSet_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ImmutableEnumSet<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, ImmutableEnumSet<?> instance) {}
 
   public static <E extends Enum<E>> ImmutableEnumSet<?> instantiate(
       SerializationStreamReader reader) throws SerializationException {
@@ -46,9 +44,8 @@ public class ImmutableEnumSet_CustomFieldSerializer {
     return (ImmutableEnumSet<?>) Sets.immutableEnumSet(deserialized);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ImmutableEnumSet<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ImmutableEnumSet<?> instance)
+      throws SerializationException {
     Collection_CustomFieldSerializerBase.serialize(writer, instance);
   }
-
 }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
index 528ca3d..68a6176 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
@@ -27,19 +27,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class ImmutableListMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ImmutableListMultimap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ImmutableListMultimap<?, ?> instance) {}
 
-  public static ImmutableListMultimap<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static ImmutableListMultimap<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     return (ImmutableListMultimap<Object, Object>)
-        Multimap_CustomFieldSerializerBase.instantiate(
-            reader, ImmutableListMultimap.builder());
+        Multimap_CustomFieldSerializerBase.instantiate(reader, ImmutableListMultimap.builder());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ImmutableListMultimap<?, ?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, ImmutableListMultimap<?, ?> instance)
+      throws SerializationException {
     Multimap_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
index 4799c72..980c11b 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
@@ -29,14 +29,13 @@ import java.util.Comparator;
  */
 public class ImmutableSetMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ImmutableSetMultimap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ImmutableSetMultimap<?, ?> instance) {}
 
   // Serialization type safety is at the caller's mercy.
   @SuppressWarnings("unchecked")
-  public static ImmutableSetMultimap<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static ImmutableSetMultimap<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Comparator<Object> valueComparator = (Comparator<Object>) reader.readObject();
     ImmutableSetMultimap.Builder<Object, Object> builder = ImmutableSetMultimap.builder();
     if (valueComparator != null) {
@@ -46,8 +45,9 @@ public class ImmutableSetMultimap_CustomFieldSerializer {
         Multimap_CustomFieldSerializerBase.instantiate(reader, builder);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ImmutableSetMultimap<?, ?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, ImmutableSetMultimap<?, ?> instance)
+      throws SerializationException {
     writer.writeObject(instance.valueComparator());
     Multimap_CustomFieldSerializerBase.serialize(writer, instance);
   }
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
index 70cf908..215ffa6 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
@@ -16,6 +16,10 @@
 
 package com.google.common.collect;
 
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
 /**
  * Even though {@link ImmutableSortedMap} cannot be instantiated, we still need a custom field
  * serializer. TODO(cpovirk): why? Does it help if ensure that the GWT and non-GWT classes have the
@@ -23,4 +27,17 @@ package com.google.common.collect;
  *
  * @author Chris Povirk
  */
-public final class ImmutableSortedMap_CustomFieldSerializer {}
+public final class ImmutableSortedMap_CustomFieldSerializer {
+  public static void deserialize(
+      SerializationStreamReader reader, ImmutableSortedMap<?, ?> instance) {}
+
+  public static ImmutableSortedMap<?, ?> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
+  }
+
+  public static void serialize(SerializationStreamWriter writer, ImmutableSortedMap<?, ?> instance)
+      throws SerializationException {
+    ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
+  }
+}
diff --git a/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
index 597207d..94d490b 100644
--- a/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
@@ -23,24 +23,23 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 /**
  * This class implements the GWT serialization of {@link
  * LexicographicalOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class LexicographicalOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      LexicographicalOrdering<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, LexicographicalOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static LexicographicalOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new LexicographicalOrdering<Object>(
-        (Ordering<Object>) reader.readObject());
+  public static LexicographicalOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new LexicographicalOrdering<Object>((Ordering<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      LexicographicalOrdering<?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, LexicographicalOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.elementOrder);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
index a0a9163..6aa24e9 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
@@ -31,18 +31,14 @@ import java.util.Map;
  */
 public class LinkedHashMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader in,
-      LinkedHashMultimap<?, ?> out) {
-  }
+  public static void deserialize(SerializationStreamReader in, LinkedHashMultimap<?, ?> out) {}
 
-  public static LinkedHashMultimap<Object, Object> instantiate(
-      SerializationStreamReader stream) throws SerializationException {
+  public static LinkedHashMultimap<Object, Object> instantiate(SerializationStreamReader stream)
+      throws SerializationException {
     LinkedHashMultimap<Object, Object> multimap = LinkedHashMultimap.create();
 
-    multimap.valueSetCapacity = stream.readInt();
     int distinctKeys = stream.readInt();
-    Map<Object, Collection<Object>> map =
-        new LinkedHashMap<Object, Collection<Object>>(Maps.capacity(distinctKeys));
+    Map<Object, Collection<Object>> map = new LinkedHashMap<Object, Collection<Object>>();
     for (int i = 0; i < distinctKeys; i++) {
       Object key = stream.readObject();
       map.put(key, multimap.createCollection(key));
@@ -58,9 +54,8 @@ public class LinkedHashMultimap_CustomFieldSerializer {
     return multimap;
   }
 
-  public static void serialize(SerializationStreamWriter stream,
-      LinkedHashMultimap<?, ?> multimap) throws SerializationException {
-    stream.writeInt(multimap.valueSetCapacity);
+  public static void serialize(SerializationStreamWriter stream, LinkedHashMultimap<?, ?> multimap)
+      throws SerializationException {
     stream.writeInt(multimap.keySet().size());
     for (Object key : multimap.keySet()) {
       stream.writeObject(key);
diff --git a/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
index 77cc126..934bc69 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
@@ -27,19 +27,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class LinkedHashMultiset_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      LinkedHashMultiset<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, LinkedHashMultiset<?> instance) {}
 
-  public static LinkedHashMultiset<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static LinkedHashMultiset<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     return (LinkedHashMultiset<Object>)
-        Multiset_CustomFieldSerializerBase.populate(
-            reader, LinkedHashMultiset.create());
+        Multiset_CustomFieldSerializerBase.populate(reader, LinkedHashMultiset.create());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      LinkedHashMultiset<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, LinkedHashMultiset<?> instance)
+      throws SerializationException {
     Multiset_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
index 28d3327..736076c 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
@@ -24,17 +24,15 @@ import java.util.Map;
 
 /**
  * This class implements the GWT serialization of {@link LinkedListMultimap}.
- * 
+ *
  * @author Chris Povirk
  */
 public class LinkedListMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader in,
-      LinkedListMultimap<?, ?> out) {
-  }
+  public static void deserialize(SerializationStreamReader in, LinkedListMultimap<?, ?> out) {}
 
-  public static LinkedListMultimap<Object, Object> instantiate(
-      SerializationStreamReader in) throws SerializationException {
+  public static LinkedListMultimap<Object, Object> instantiate(SerializationStreamReader in)
+      throws SerializationException {
     LinkedListMultimap<Object, Object> multimap = LinkedListMultimap.create();
     int size = in.readInt();
     for (int i = 0; i < size; i++) {
@@ -45,8 +43,8 @@ public class LinkedListMultimap_CustomFieldSerializer {
     return multimap;
   }
 
-  public static void serialize(SerializationStreamWriter out,
-      LinkedListMultimap<?, ?> multimap) throws SerializationException {
+  public static void serialize(SerializationStreamWriter out, LinkedListMultimap<?, ?> multimap)
+      throws SerializationException {
     out.writeInt(multimap.size());
     for (Map.Entry<?, ?> entry : multimap.entries()) {
       out.writeObject(entry.getKey());
diff --git a/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java b/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
index 5e60a45..4992830 100644
--- a/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
+++ b/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
@@ -35,8 +35,7 @@ import java.util.Map;
 public final class Multimap_CustomFieldSerializerBase {
 
   static ImmutableMultimap<Object, Object> instantiate(
-      SerializationStreamReader reader,
-      ImmutableMultimap.Builder<Object, Object> builder)
+      SerializationStreamReader reader, ImmutableMultimap.Builder<Object, Object> builder)
       throws SerializationException {
     int keyCount = reader.readInt();
     for (int i = 0; i < keyCount; ++i) {
@@ -65,12 +64,10 @@ public final class Multimap_CustomFieldSerializerBase {
     return multimap;
   }
 
-  public static void serialize(
-      SerializationStreamWriter writer, Multimap<?, ?> instance)
+  public static void serialize(SerializationStreamWriter writer, Multimap<?, ?> instance)
       throws SerializationException {
     writer.writeInt(instance.asMap().size());
-    for (Map.Entry<?, ? extends Collection<?>> entry
-        : instance.asMap().entrySet()) {
+    for (Map.Entry<?, ? extends Collection<?>> entry : instance.asMap().entrySet()) {
       writer.writeObject(entry.getKey());
       writer.writeInt(entry.getValue().size());
       for (Object value : entry.getValue()) {
diff --git a/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java b/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
index 7c44bba..f740a60 100644
--- a/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
+++ b/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
@@ -25,13 +25,12 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  * field serializers. Serializers should delegate to
  * {@link #serialize(SerializationStreamWriter, Multiset)} and
  * {@link #populate(SerializationStreamReader, Multiset)}.
- * 
+ *
  * @author Chris Povirk
  */
 final class Multiset_CustomFieldSerializerBase {
 
-  static Multiset<Object> populate(
-      SerializationStreamReader reader, Multiset<Object> multiset)
+  static Multiset<Object> populate(SerializationStreamReader reader, Multiset<Object> multiset)
       throws SerializationException {
     int distinctElements = reader.readInt();
     for (int i = 0; i < distinctElements; i++) {
@@ -50,7 +49,7 @@ final class Multiset_CustomFieldSerializerBase {
       writer.writeObject(entry.getElement());
       writer.writeInt(entry.getCount());
     }
-  } 
+  }
 
   private Multiset_CustomFieldSerializerBase() {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
index 9e57fff..e75655c 100644
--- a/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
@@ -21,21 +21,16 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link NaturalOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class NaturalOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      NaturalOrdering instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, NaturalOrdering instance) {}
 
-  public static NaturalOrdering instantiate(
-      SerializationStreamReader reader) {
+  public static NaturalOrdering instantiate(SerializationStreamReader reader) {
     return NaturalOrdering.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      NaturalOrdering instance) {
-  }
+  public static void serialize(SerializationStreamWriter writer, NaturalOrdering instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
index d1a0a71..9b27b57 100644
--- a/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
@@ -22,24 +22,22 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link NullsFirstOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class NullsFirstOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      NullsFirstOrdering<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, NullsFirstOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static NullsFirstOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new NullsFirstOrdering<Object>(
-        (Ordering<Object>) reader.readObject());
+  public static NullsFirstOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new NullsFirstOrdering<Object>((Ordering<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      NullsFirstOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, NullsFirstOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.ordering);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
index 0c306e0..965d75f 100644
--- a/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link NullsLastOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class NullsLastOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      NullsLastOrdering<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, NullsLastOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static NullsLastOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new NullsLastOrdering<Object>(
-        (Ordering<Object>) reader.readObject());
+  public static NullsLastOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new NullsLastOrdering<Object>((Ordering<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      NullsLastOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, NullsLastOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.ordering);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
index f41b8cf..7d2d555 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
@@ -30,20 +30,19 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 @GwtCompatible(emulated = true)
 public class RegularImmutableAsList_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableAsList<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableAsList<?> instance) {}
 
-  public static RegularImmutableAsList<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableAsList<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     @SuppressWarnings("unchecked") // serialization is necessarily type unsafe
     ImmutableCollection<Object> delegateCollection = (ImmutableCollection) reader.readObject();
     ImmutableList<?> delegateList = (ImmutableList<?>) reader.readObject();
     return new RegularImmutableAsList<Object>(delegateCollection, delegateList);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableAsList<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, RegularImmutableAsList<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.delegateCollection());
     writer.writeObject(instance.delegateList());
   }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
index 4d68331..af0d437 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
@@ -27,16 +27,15 @@ import java.util.Map;
 /**
  * This class implements the GWT serialization of
  * {@link RegularImmutableBiMap}.
- * 
+ *
  * @author Chris Povirk
  */
 public class RegularImmutableBiMap_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableBiMap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableBiMap<?, ?> instance) {}
 
-  public static RegularImmutableBiMap<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableBiMap<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Map<Object, Object> entries = new LinkedHashMap<Object, Object>();
     Map_CustomFieldSerializerBase.deserialize(reader, entries);
     /*
@@ -45,12 +44,12 @@ public class RegularImmutableBiMap_CustomFieldSerializer {
      * always have one or more elements, ImmutableBiMap.copyOf always return a
      * RegularImmutableBiMap back.
      */
-    return 
-        (RegularImmutableBiMap<Object, Object>) ImmutableBiMap.copyOf(entries);
+    return (RegularImmutableBiMap<Object, Object>) ImmutableBiMap.copyOf(entries);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableBiMap<?, ?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, RegularImmutableBiMap<?, ?> instance)
+      throws SerializationException {
     Map_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
index 9dd652c..4f70472 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
@@ -32,12 +32,11 @@ import java.util.List;
  */
 public class RegularImmutableList_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableList<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableList<?> instance) {}
 
-  public static RegularImmutableList<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableList<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     List<Object> elements = new ArrayList<Object>();
     Collection_CustomFieldSerializerBase.deserialize(reader, elements);
     /*
@@ -49,8 +48,8 @@ public class RegularImmutableList_CustomFieldSerializer {
     return (RegularImmutableList<Object>) ImmutableList.copyOf(elements);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableList<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, RegularImmutableList<?> instance)
+      throws SerializationException {
     Collection_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
index d9e1748..8b466a7 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
@@ -31,12 +31,11 @@ import java.util.Map;
  */
 public class RegularImmutableMap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableMap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableMap<?, ?> instance) {}
 
-  public static RegularImmutableMap<Object, Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableMap<Object, Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Map<Object, Object> entries = new LinkedHashMap<Object, Object>();
     Map_CustomFieldSerializerBase.deserialize(reader, entries);
     /*
@@ -48,8 +47,8 @@ public class RegularImmutableMap_CustomFieldSerializer {
     return (RegularImmutableMap<Object, Object>) ImmutableMap.copyOf(entries);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableMap<?, ?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, RegularImmutableMap<?, ?> instance)
+      throws SerializationException {
     Map_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
index 3c04929..eec62c4 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
@@ -25,16 +25,15 @@ import java.util.List;
 
 /**
  * This class implements the GWT serialization of {@link RegularImmutableMultiset}.
- * 
+ *
  * @author Louis Wasserman
  */
 public class RegularImmutableMultiset_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableMultiset<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableMultiset<?> instance) {}
 
-  public static RegularImmutableMultiset<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableMultiset<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     List<Object> elements = Lists.newArrayList();
     Collection_CustomFieldSerializerBase.deserialize(reader, elements);
     /*
@@ -43,12 +42,12 @@ public class RegularImmutableMultiset_CustomFieldSerializer {
      * RegularImmutableMultiset always have one or more elements,
      * ImmutableMultiset.copyOf always return a RegularImmutableMultiset back.
      */
-    return (RegularImmutableMultiset<Object>) ImmutableMultiset
-        .copyOf(elements);
+    return (RegularImmutableMultiset<Object>) ImmutableMultiset.copyOf(elements);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableMultiset<?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, RegularImmutableMultiset<?> instance)
+      throws SerializationException {
     Collection_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
index 5908935..dc8f88b 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
@@ -30,12 +30,11 @@ import java.util.List;
  */
 public class RegularImmutableSet_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableSet<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableSet<?> instance) {}
 
-  public static RegularImmutableSet<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableSet<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     List<Object> elements = Lists.newArrayList();
     Collection_CustomFieldSerializerBase.deserialize(reader, elements);
     /*
@@ -47,8 +46,8 @@ public class RegularImmutableSet_CustomFieldSerializer {
     return (RegularImmutableSet<Object>) ImmutableSet.copyOf(elements);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableSet<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, RegularImmutableSet<?> instance)
+      throws SerializationException {
     Collection_CustomFieldSerializerBase.serialize(writer, instance);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java
deleted file mode 100644
index 9f64e37..0000000
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link RegularImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-public class RegularImmutableSortedMap_CustomFieldSerializer {
-  public static void deserialize(
-      SerializationStreamReader reader, RegularImmutableSortedMap<?, ?> instance) {
-  }
-
-  public static RegularImmutableSortedMap<?, ?> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return (RegularImmutableSortedMap<?, ?>)
-        ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
-  }
-
-  public static void serialize(
-      SerializationStreamWriter writer, RegularImmutableSortedMap<?, ?> instance)
-      throws SerializationException {
-    ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
-  }
-}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
index d3018c3..b489737 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
@@ -28,16 +28,15 @@ import java.util.List;
 /**
  * This class implements the GWT serialization of
  * {@link RegularImmutableSortedSet}.
- * 
+ *
  * @author Chris Povirk
  */
 public class RegularImmutableSortedSet_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader,
-      RegularImmutableSortedSet<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, RegularImmutableSortedSet<?> instance) {}
 
-  public static RegularImmutableSortedSet<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static RegularImmutableSortedSet<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     /*
      * Nothing we can do, but we're already assuming the serialized form is
      * correctly typed, anyway.
@@ -53,12 +52,12 @@ public class RegularImmutableSortedSet_CustomFieldSerializer {
      * RegularImmutableSortedSet always have one or more elements,
      * ImmutableSortedSet.copyOf always return a RegularImmutableSortedSet back.
      */
-    return (RegularImmutableSortedSet<Object>)
-        ImmutableSortedSet.copyOf(comparator, elements);
+    return (RegularImmutableSortedSet<Object>) ImmutableSortedSet.copyOf(comparator, elements);
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      RegularImmutableSortedSet<?> instance) throws SerializationException {
+  public static void serialize(
+      SerializationStreamWriter writer, RegularImmutableSortedSet<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.comparator());
 
     Collection_CustomFieldSerializerBase.serialize(writer, instance);
diff --git a/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
index b3744f5..fab8648 100644
--- a/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
@@ -22,21 +22,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 /**
  * This class implements the GWT serialization of
  * {@link ReverseNaturalOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ReverseNaturalOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ReverseNaturalOrdering instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, ReverseNaturalOrdering instance) {}
 
-  public static ReverseNaturalOrdering instantiate(
-      SerializationStreamReader reader) {
+  public static ReverseNaturalOrdering instantiate(SerializationStreamReader reader) {
     return ReverseNaturalOrdering.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ReverseNaturalOrdering instance) {
-  }
+  public static void serialize(SerializationStreamWriter writer, ReverseNaturalOrdering instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
index 67711bd..9cf4a6e 100644
--- a/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link ReverseOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class ReverseOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      ReverseOrdering<?> instance) {
-  }
+  public static void deserialize(SerializationStreamReader reader, ReverseOrdering<?> instance) {}
 
   @SuppressWarnings("unchecked") // deserialization is unsafe
-  public static ReverseOrdering<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
-    return new ReverseOrdering<Object>(
-        (Ordering<Object>) reader.readObject());
+  public static ReverseOrdering<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
+    return new ReverseOrdering<Object>((Ordering<Object>) reader.readObject());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      ReverseOrdering<?> instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, ReverseOrdering<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.forwardOrder);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
index 7b87633..c5a8c7c 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
@@ -29,9 +29,8 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class SingletonImmutableBiMap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      SingletonImmutableBiMap<?, ?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, SingletonImmutableBiMap<?, ?> instance) {}
 
   public static SingletonImmutableBiMap<Object, Object> instantiate(
       SerializationStreamReader reader) throws SerializationException {
@@ -39,9 +38,10 @@ public class SingletonImmutableBiMap_CustomFieldSerializer {
     Object value = checkNotNull(reader.readObject());
     return new SingletonImmutableBiMap<Object, Object>(key, value);
   }
-  
-  public static void serialize(SerializationStreamWriter writer,
-      SingletonImmutableBiMap<?, ?> instance) throws SerializationException {
+
+  public static void serialize(
+      SerializationStreamWriter writer, SingletonImmutableBiMap<?, ?> instance)
+      throws SerializationException {
     writer.writeObject(instance.singleKey);
     writer.writeObject(instance.singleValue);
   }
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
index 712e275..ef1a2cf 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
@@ -28,18 +28,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class SingletonImmutableList_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      SingletonImmutableList<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, SingletonImmutableList<?> instance) {}
 
-  public static SingletonImmutableList<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static SingletonImmutableList<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Object element = reader.readObject();
     return new SingletonImmutableList<Object>(element);
   }
-  
-  public static void serialize(SerializationStreamWriter writer,
-      SingletonImmutableList<?> instance) throws SerializationException {
+
+  public static void serialize(SerializationStreamWriter writer, SingletonImmutableList<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.element);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
index bfa9d42..b389fdd 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
@@ -27,18 +27,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class SingletonImmutableSet_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      SingletonImmutableSet<?> instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, SingletonImmutableSet<?> instance) {}
 
-  public static SingletonImmutableSet<Object> instantiate(
-      SerializationStreamReader reader) throws SerializationException {
+  public static SingletonImmutableSet<Object> instantiate(SerializationStreamReader reader)
+      throws SerializationException {
     Object element = reader.readObject();
     return new SingletonImmutableSet<Object>(element);
   }
-  
-  public static void serialize(SerializationStreamWriter writer,
-      SingletonImmutableSet<?> instance) throws SerializationException {
+
+  public static void serialize(SerializationStreamWriter writer, SingletonImmutableSet<?> instance)
+      throws SerializationException {
     writer.writeObject(instance.element);
   }
 }
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
index a156247..9bc44ac 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class SingletonImmutableTable_CustomFieldSerializer {
   public static void deserialize(
-      SerializationStreamReader reader, SingletonImmutableTable<?, ?, ?> instance) {
-  }
+      SerializationStreamReader reader, SingletonImmutableTable<?, ?, ?> instance) {}
 
   public static SingletonImmutableTable<Object, Object, Object> instantiate(
       SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
index 94f6a13..571ddd1 100644
--- a/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
  */
 public class SparseImmutableTable_CustomFieldSerializer {
   public static void deserialize(
-      SerializationStreamReader reader, SparseImmutableTable<?, ?, ?> instance) {
-  }
+      SerializationStreamReader reader, SparseImmutableTable<?, ?, ?> instance) {}
 
   public static SparseImmutableTable<Object, Object, Object> instantiate(
       SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
index 332b453..5a211ea 100644
--- a/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
@@ -26,17 +26,14 @@ import java.util.Comparator;
  * @author Hayward Chan
  */
 public class TreeBasedTable_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader, TreeBasedTable<?, ?, ?> table) {
-  }
+  public static void deserialize(SerializationStreamReader reader, TreeBasedTable<?, ?, ?> table) {}
 
   public static TreeBasedTable<Object, Object, Object> instantiate(SerializationStreamReader reader)
       throws SerializationException {
     @SuppressWarnings("unchecked") // The comparator isn't used statically.
-    Comparator<Object> rowComparator
-        = (Comparator<Object>) reader.readObject();
+    Comparator<Object> rowComparator = (Comparator<Object>) reader.readObject();
     @SuppressWarnings("unchecked") // The comparator isn't used statically.
-    Comparator<Object> columnComparator
-        = (Comparator<Object>) reader.readObject();
+    Comparator<Object> columnComparator = (Comparator<Object>) reader.readObject();
 
     TreeBasedTable<Object, Object, Object> table =
         TreeBasedTable.create(rowComparator, columnComparator);
diff --git a/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
index 22db170..a9b0be4 100644
--- a/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
@@ -29,13 +29,11 @@ import java.util.Comparator;
  */
 public class TreeMultimap_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader in,
-      TreeMultimap<?, ?> out) {
-  }
+  public static void deserialize(SerializationStreamReader in, TreeMultimap<?, ?> out) {}
 
   @SuppressWarnings("unchecked")
-  public static TreeMultimap<Object, Object> instantiate(
-      SerializationStreamReader in) throws SerializationException {
+  public static TreeMultimap<Object, Object> instantiate(SerializationStreamReader in)
+      throws SerializationException {
     Comparator<Object> keyComparator = (Comparator<Object>) in.readObject();
     Comparator<Object> valueComparator = (Comparator<Object>) in.readObject();
 
@@ -44,8 +42,8 @@ public class TreeMultimap_CustomFieldSerializer {
             in, TreeMultimap.create(keyComparator, valueComparator));
   }
 
-  public static void serialize(SerializationStreamWriter out,
-      TreeMultimap<?, ?> multimap) throws SerializationException {
+  public static void serialize(SerializationStreamWriter out, TreeMultimap<?, ?> multimap)
+      throws SerializationException {
     out.writeObject(multimap.keyComparator());
     out.writeObject(multimap.valueComparator());
     Multimap_CustomFieldSerializerBase.serialize(out, multimap);
diff --git a/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
index dacf0c2..54a9e15 100644
--- a/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
@@ -21,21 +21,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
 /**
  * This class implements the GWT serialization of {@link UsingToStringOrdering}.
- * 
+ *
  * @author Chris Povirk
  */
 public class UsingToStringOrdering_CustomFieldSerializer {
 
-  public static void deserialize(SerializationStreamReader reader,
-      UsingToStringOrdering instance) {
-  }
+  public static void deserialize(
+      SerializationStreamReader reader, UsingToStringOrdering instance) {}
 
-  public static UsingToStringOrdering instantiate(
-      SerializationStreamReader reader) {
+  public static UsingToStringOrdering instantiate(SerializationStreamReader reader) {
     return UsingToStringOrdering.INSTANCE;
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      UsingToStringOrdering instance) {
-  }
+  public static void serialize(SerializationStreamWriter writer, UsingToStringOrdering instance) {}
 }
diff --git a/guava-gwt/src/com/google/common/net/Net.gwt.xml b/guava-gwt/src/com/google/common/net/Net.gwt.xml
index 12a73fe..4d0a3c4 100644
--- a/guava-gwt/src/com/google/common/net/Net.gwt.xml
+++ b/guava-gwt/src/com/google/common/net/Net.gwt.xml
@@ -27,7 +27,7 @@
   <inherits name="java.nio.charset.Charset"/>
     
   <inherits name="com.google.thirdparty.publicsuffix.PublicSuffixPatterns"/>
-    
+     
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
index 732730e..7908c64 100644
--- a/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
@@ -18,22 +18,24 @@ import com.google.gwt.user.client.rpc.SerializationException;
 import com.google.gwt.user.client.rpc.SerializationStreamReader;
 import com.google.gwt.user.client.rpc.SerializationStreamWriter;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * This class implements the GWT serialization of {@code UnsignedLong}.
  *
  * @author Louis Wasserman
  */
+ at CheckReturnValue
 public class UnsignedLong_CustomFieldSerializer {
-  public static void deserialize(SerializationStreamReader reader,
-      UnsignedLong instance) {}
+  public static void deserialize(SerializationStreamReader reader, UnsignedLong instance) {}
 
   public static UnsignedLong instantiate(SerializationStreamReader reader)
       throws SerializationException {
     return UnsignedLong.fromLongBits(reader.readLong());
   }
 
-  public static void serialize(SerializationStreamWriter writer,
-      UnsignedLong instance) throws SerializationException {
+  public static void serialize(SerializationStreamWriter writer, UnsignedLong instance)
+      throws SerializationException {
     writer.writeLong(instance.longValue());
   }
 }
diff --git a/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml b/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
index e3ce2b7..7c2932c 100644
--- a/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
+++ b/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
@@ -19,7 +19,9 @@
   <inherits name="com.google.common.base.Base"/>
    
   <inherits name="com.google.common.collect.Collect"/>
-    
+   
+  <inherits name="java.util.Util"/>
+     
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
index 55b659f..2099a1d 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
@@ -16,14 +16,14 @@
 
 package com.google.common.base;
 
-import static com.google.common.base.CharMatcher.BREAKING_WHITESPACE;
-import static com.google.common.base.CharMatcher.WHITESPACE;
 import static com.google.common.base.CharMatcher.anyOf;
+import static com.google.common.base.CharMatcher.breakingWhitespace;
 import static com.google.common.base.CharMatcher.forPredicate;
 import static com.google.common.base.CharMatcher.inRange;
 import static com.google.common.base.CharMatcher.is;
 import static com.google.common.base.CharMatcher.isNot;
 import static com.google.common.base.CharMatcher.noneOf;
+import static com.google.common.base.CharMatcher.whitespace;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Sets;
@@ -56,14 +56,14 @@ public class CharMatcherTest extends TestCase {
     // we're lucky enough that these do pass, it saves us from having to write
     // more excruciating tests! Hooray!
 
-    assertSame(CharMatcher.ANY, CharMatcher.NONE.negate());
-    assertSame(CharMatcher.NONE, CharMatcher.ANY.negate());
+    assertSame(CharMatcher.any(), CharMatcher.none().negate());
+    assertSame(CharMatcher.none(), CharMatcher.any().negate());
 
-    assertSame(WHATEVER, CharMatcher.ANY.and(WHATEVER));
-    assertSame(CharMatcher.ANY, CharMatcher.ANY.or(WHATEVER));
+    assertSame(WHATEVER, CharMatcher.any().and(WHATEVER));
+    assertSame(CharMatcher.any(), CharMatcher.any().or(WHATEVER));
 
-    assertSame(CharMatcher.NONE, CharMatcher.NONE.and(WHATEVER));
-    assertSame(WHATEVER, CharMatcher.NONE.or(WHATEVER));
+    assertSame(CharMatcher.none(), CharMatcher.none().and(WHATEVER));
+    assertSame(WHATEVER, CharMatcher.none().or(WHATEVER));
   }
 
   // The rest of the behavior of ANY and DEFAULT will be covered in the tests for
@@ -71,8 +71,8 @@ public class CharMatcherTest extends TestCase {
 
   public void testWhitespaceBreakingWhitespaceSubset() throws Exception {
     for (int c = 0; c <= Character.MAX_VALUE; c++) {
-      if (BREAKING_WHITESPACE.apply((char) c)) {
-        assertTrue(Integer.toHexString(c), WHITESPACE.apply((char) c));
+      if (breakingWhitespace().matches((char) c)) {
+        assertTrue(Integer.toHexString(c), whitespace().matches((char) c));
       }
     }
   }
@@ -91,8 +91,8 @@ public class CharMatcherTest extends TestCase {
   // do borders on absurd overkill. Better safe than sorry, though?
 
   public void testEmpty() throws Exception {
-    doTestEmpty(CharMatcher.ANY);
-    doTestEmpty(CharMatcher.NONE);
+    doTestEmpty(CharMatcher.any());
+    doTestEmpty(CharMatcher.none());
     doTestEmpty(is('a'));
     doTestEmpty(isNot('a'));
     doTestEmpty(anyOf(""));
@@ -135,7 +135,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testNoMatches() {
-    doTestNoMatches(CharMatcher.NONE, "blah");
+    doTestNoMatches(CharMatcher.none(), "blah");
     doTestNoMatches(is('a'), "bcde");
     doTestNoMatches(isNot('a'), "aaaa");
     doTestNoMatches(anyOf(""), "abcd");
@@ -146,10 +146,10 @@ public class CharMatcherTest extends TestCase {
     doTestNoMatches(inRange('p', 'x'), "mom");
     doTestNoMatches(forPredicate(Predicates.equalTo('c')), "abe");
     doTestNoMatches(inRange('A', 'Z').and(inRange('F', 'K').negate()), "F1a");
-    doTestNoMatches(CharMatcher.DIGIT, "\tAz()");
-    doTestNoMatches(CharMatcher.JAVA_DIGIT, "\tAz()");
-    doTestNoMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "\tAz()");
-    doTestNoMatches(CharMatcher.SINGLE_WIDTH, "\u05bf\u3000");
+    doTestNoMatches(CharMatcher.digit(), "\tAz()");
+    doTestNoMatches(CharMatcher.javaDigit(), "\tAz()");
+    doTestNoMatches(CharMatcher.digit().and(CharMatcher.ascii()), "\tAz()");
+    doTestNoMatches(CharMatcher.singleWidth(), "\u05bf\u3000");
   }
 
   private void doTestNoMatches(CharMatcher matcher, String s) {
@@ -164,7 +164,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testAllMatches() {
-    doTestAllMatches(CharMatcher.ANY, "blah");
+    doTestAllMatches(CharMatcher.any(), "blah");
     doTestAllMatches(isNot('a'), "bcde");
     doTestAllMatches(is('a'), "aaaa");
     doTestAllMatches(noneOf("CharMatcher"), "zxqy");
@@ -173,10 +173,10 @@ public class CharMatcherTest extends TestCase {
     doTestAllMatches(anyOf("CharMatcher"), "ChMa");
     doTestAllMatches(inRange('m', 'p'), "mom");
     doTestAllMatches(forPredicate(Predicates.equalTo('c')), "ccc");
-    doTestAllMatches(CharMatcher.DIGIT, "0123456789\u0ED0\u1B59");
-    doTestAllMatches(CharMatcher.JAVA_DIGIT, "0123456789");
-    doTestAllMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "0123456789");
-    doTestAllMatches(CharMatcher.SINGLE_WIDTH, "\t0123ABCdef~\u00A0\u2111");
+    doTestAllMatches(CharMatcher.digit(), "0123456789\u0ED0\u1B59");
+    doTestAllMatches(CharMatcher.javaDigit(), "0123456789");
+    doTestAllMatches(CharMatcher.digit().and(CharMatcher.ascii()), "0123456789");
+    doTestAllMatches(CharMatcher.singleWidth(), "\t0123ABCdef~\u00A0\u2111");
   }
 
   private void doTestAllMatches(CharMatcher matcher, String s) {
@@ -286,6 +286,7 @@ public class CharMatcherTest extends TestCase {
     reallyTestMatchThenNoMatch(matcher.precomputed().negate(), s);
   }
 
+  @SuppressWarnings("deprecation") // intentionally testing apply() method
   private void reallyTestOneCharMatch(CharMatcher matcher, String s) {
     assertTrue(matcher.matches(s.charAt(0)));
     assertTrue(matcher.apply(s.charAt(0)));
@@ -303,6 +304,7 @@ public class CharMatcherTest extends TestCase {
     assertEquals(1, matcher.countIn(s));
   }
 
+  @SuppressWarnings("deprecation") // intentionally testing apply() method
   private void reallyTestOneCharNoMatch(CharMatcher matcher, String s) {
     assertFalse(matcher.matches(s.charAt(0)));
     assertFalse(matcher.apply(s.charAt(0)));
@@ -418,14 +420,14 @@ public class CharMatcherTest extends TestCase {
     assertSame(inout, anyOf("-").collapseFrom(inout, '_'));
     assertSame(inout, anyOf("-#").collapseFrom(inout, '_'));
     assertSame(inout, anyOf("-#123").collapseFrom(inout, '_'));
-    assertSame(inout, CharMatcher.NONE.collapseFrom(inout, '_'));
+    assertSame(inout, CharMatcher.none().collapseFrom(inout, '_'));
   }
 
   public void testCollapse_any() {
-    assertEquals("", CharMatcher.ANY.collapseFrom("", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("a", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("ab", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("abcd", '_'));
+    assertEquals("", CharMatcher.any().collapseFrom("", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("a", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("ab", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("abcd", '_'));
   }
 
   public void testTrimFrom() {
@@ -583,24 +585,24 @@ public class CharMatcherTest extends TestCase {
     // build a precomputed version.
     CharMatcher m1 = is('x');
     assertSame(m1, m1.precomputed());
-    assertSame(m1.toString(), m1.precomputed().toString());
+    assertEquals(m1.toString(), m1.precomputed().toString());
 
     CharMatcher m2 = anyOf("Az");
     assertSame(m2, m2.precomputed());
-    assertSame(m2.toString(), m2.precomputed().toString());
+    assertEquals(m2.toString(), m2.precomputed().toString());
 
     CharMatcher m3 = inRange('A', 'Z');
     assertSame(m3, m3.precomputed());
-    assertSame(m3.toString(), m3.precomputed().toString());
+    assertEquals(m3.toString(), m3.precomputed().toString());
 
-    assertSame(CharMatcher.NONE, CharMatcher.NONE.precomputed());
-    assertSame(CharMatcher.ANY, CharMatcher.ANY.precomputed());
+    assertSame(CharMatcher.none(), CharMatcher.none().precomputed());
+    assertSame(CharMatcher.any(), CharMatcher.any().precomputed());
   }
 
   static void checkExactMatches(CharMatcher m, char[] chars) {
     Set<Character> positive = Sets.newHashSetWithExpectedSize(chars.length);
-    for (int i = 0; i < chars.length; i++) {
-      positive.add(chars[i]);
+    for (char c : chars) {
+      positive.add(c);
     }
     for (int c = 0; c <= Character.MAX_VALUE; c++) {
       assertFalse(positive.contains(new Character((char) c)) ^ m.matches((char) c));
@@ -629,7 +631,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testToString() {
-    assertToStringWorks("CharMatcher.NONE", CharMatcher.anyOf(""));
+    assertToStringWorks("CharMatcher.none()", CharMatcher.anyOf(""));
     assertToStringWorks("CharMatcher.is('\\u0031')", CharMatcher.anyOf("1"));
     assertToStringWorks("CharMatcher.isNot('\\u0031')", CharMatcher.isNot('1'));
     assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\")", CharMatcher.anyOf("12"));
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
index c61855a..963fe73 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.testing.SerializableTester;
 
@@ -41,27 +43,27 @@ public class EnumsTest extends TestCase {
   private enum OtherEnum {}
 
   public void testGetIfPresent() {
-    assertEquals(Optional.of(TestEnum.CHEETO), Enums.getIfPresent(TestEnum.class, "CHEETO"));
-    assertEquals(Optional.of(TestEnum.HONDA), Enums.getIfPresent(TestEnum.class, "HONDA"));
-    assertEquals(Optional.of(TestEnum.POODLE), Enums.getIfPresent(TestEnum.class, "POODLE"));
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
 
-    assertTrue(Enums.getIfPresent(TestEnum.class, "CHEETO").isPresent());
-    assertTrue(Enums.getIfPresent(TestEnum.class, "HONDA").isPresent());
-    assertTrue(Enums.getIfPresent(TestEnum.class, "POODLE").isPresent());
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).isPresent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).isPresent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).isPresent();
 
-    assertEquals(TestEnum.CHEETO, Enums.getIfPresent(TestEnum.class, "CHEETO").get());
-    assertEquals(TestEnum.HONDA, Enums.getIfPresent(TestEnum.class, "HONDA").get());
-    assertEquals(TestEnum.POODLE, Enums.getIfPresent(TestEnum.class, "POODLE").get());
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
   }
 
   public void testGetIfPresent_caseSensitive() {
-    assertFalse(Enums.getIfPresent(TestEnum.class, "cHEETO").isPresent());
-    assertFalse(Enums.getIfPresent(TestEnum.class, "Honda").isPresent());
-    assertFalse(Enums.getIfPresent(TestEnum.class, "poodlE").isPresent());
+    assertThat(Enums.getIfPresent(TestEnum.class, "cHEETO")).isAbsent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "Honda")).isAbsent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "poodlE")).isAbsent();
   }
 
   public void testGetIfPresent_whenNoMatchingConstant() {
-    assertEquals(Optional.absent(), Enums.getIfPresent(TestEnum.class, "WOMBAT"));
+    assertThat(Enums.getIfPresent(TestEnum.class, "WOMBAT")).isAbsent();
   }
 
   // Create a second ClassLoader and use it to get a second version of the TestEnum class.
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
index 15ba5c8..d6cc3a8 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
@@ -56,6 +56,7 @@ public class JoinerTest extends TestCase {
   private static final Iterable<Integer> ITERABLE_FOUR_NULLS
       = Arrays.asList((Integer) null, null, null, null);
 
+  @SuppressWarnings("CheckReturnValue")
   public void testNoSpecialNullBehavior() {
     checkNoOutput(J, ITERABLE_);
     checkResult(J, ITERABLE_1, "1");
@@ -235,6 +236,7 @@ public class JoinerTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMap() {
     MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
     assertEquals("", j.join(ImmutableMap.of()));
@@ -257,6 +259,7 @@ public class JoinerTest extends TestCase {
     assertEquals("1:2;3:4;5:6", sb.toString());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEntries() {
     MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
     assertEquals("", j.join(ImmutableMultimap.of().entries()));
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
index 8030f14..a205378 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
@@ -68,6 +68,7 @@ public class ObjectsTest extends TestCase {
     assertSame(n1, n2);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFirstNonNull_throwsNullPointerException() throws Exception {
     try {
       Objects.firstNonNull(null, null);
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
index 6d78535..5c6947b 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
@@ -44,6 +44,7 @@ public final class OptionalTest extends TestCase {
     assertEquals("training", Optional.of("training").get());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testOf_null() {
     try {
       Optional.of(null);
@@ -70,6 +71,7 @@ public final class OptionalTest extends TestCase {
     assertTrue(Optional.of("training").isPresent());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testGet_absent() {
     Optional<String> optional = Optional.absent();
     try {
@@ -99,6 +101,7 @@ public final class OptionalTest extends TestCase {
     assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testOr_nullSupplier_absent() {
     Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
     Optional<Object> absentOptional = Optional.absent();
@@ -170,6 +173,7 @@ public final class OptionalTest extends TestCase {
     assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testTransform_present_functionReturnsNull() {
     try {
       Optional.of("a").transform(
@@ -198,6 +202,8 @@ public final class OptionalTest extends TestCase {
   public void testEqualsAndHashCode_absent() {
     assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
     assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
+    assertThat(Optional.absent().hashCode())
+        .isNotEqualTo(Optional.of(0).hashCode());
   }
 
   public void testEqualsAndHashCode_present() {
@@ -218,7 +224,7 @@ public final class OptionalTest extends TestCase {
   public void testPresentInstances_allPresent() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
-    assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
+    assertThat(Optional.presentInstances(optionals)).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testPresentInstances_allAbsent() {
@@ -230,22 +236,22 @@ public final class OptionalTest extends TestCase {
   public void testPresentInstances_somePresent() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
-    assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
+    assertThat(Optional.presentInstances(optionals)).containsExactly("a", "c").inOrder();
   }
 
   public void testPresentInstances_callingIteratorTwice() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
     Iterable<String> onlyPresent = Optional.presentInstances(optionals);
-    assertThat(onlyPresent).iteratesAs("a", "c");
-    assertThat(onlyPresent).iteratesAs("a", "c");
+    assertThat(onlyPresent).containsExactly("a", "c").inOrder();
+    assertThat(onlyPresent).containsExactly("a", "c").inOrder();
   }
 
   public void testPresentInstances_wildcards() {
     List<Optional<? extends Number>> optionals =
         ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
     Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
-    assertThat(onlyPresent).iteratesAs(2);
+    assertThat(onlyPresent).containsExactly(2).inOrder();
   }
 
   private static Optional<Integer> getSomeOptionalInt() {
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
index e35864a..bb4bc09 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 
 import junit.framework.AssertionFailedError;
@@ -59,7 +61,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkArgument(false, null);
       fail("no exception thrown");
     } catch (IllegalArgumentException expected) {
-      assertEquals("null", expected.getMessage());
+      assertThat(expected).hasMessage("null");
     }
   }
 
@@ -106,7 +108,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkState(false, null);
       fail("no exception thrown");
     } catch (IllegalStateException expected) {
-      assertEquals("null", expected.getMessage());
+      assertThat(expected).hasMessage("null");
     }
   }
 
@@ -188,7 +190,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(-1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("index (-1) must not be negative");
     }
   }
 
@@ -197,8 +199,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (1) must be less than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("index (1) must be less than size (1)");
     }
   }
 
@@ -207,7 +208,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(-1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("foo (-1) must not be negative");
     }
   }
 
@@ -216,8 +217,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (1) must be less than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("foo (1) must be less than size (1)");
     }
   }
 
@@ -242,7 +242,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(-1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("index (-1) must not be negative");
     }
   }
 
@@ -251,8 +251,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(2, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("index (2) must not be greater than size (1)");
     }
   }
 
@@ -261,7 +260,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(-1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("foo (-1) must not be negative");
     }
   }
 
@@ -270,8 +269,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(2, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("foo (2) must not be greater than size (1)");
     }
   }
 
@@ -295,8 +293,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(-1, 1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("start index (-1) must not be negative",
-          expected.getMessage());
+      assertThat(expected).hasMessage("start index (-1) must not be negative");
     }
   }
 
@@ -305,8 +302,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(0, 2, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("end index (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("end index (2) must not be greater than size (1)");
     }
   }
 
@@ -315,8 +311,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(1, 0, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("end index (0) must not be less than start index (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("end index (0) must not be less than start index (1)");
     }
   }
 
@@ -356,10 +351,10 @@ public class PreconditionsTest extends TestCase {
   private static final String FORMAT = "I ate %s pies.";
 
   private static void verifySimpleMessage(Exception e) {
-    assertEquals("A message", e.getMessage());
+    assertThat(e).hasMessage("A message");
   }
 
   private static void verifyComplexMessage(Exception e) {
-    assertEquals("I ate 5 pies.", e.getMessage());
+    assertThat(e).hasMessage("I ate 5 pies.");
   }
 }
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
index aabd88d..b2891a5 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
@@ -19,12 +19,10 @@ package com.google.common.base;
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
 import junit.framework.TestCase;
 
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -37,6 +35,7 @@ public class SplitterTest extends TestCase {
 
   private static final Splitter COMMA_SPLITTER = Splitter.on(',');
 
+  @SuppressWarnings("CheckReturnValue")
   public void testSplitNullString() {
     try {
       COMMA_SPLITTER.split(null);
@@ -48,7 +47,7 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplit() {
     String simple = "a,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   /**
@@ -62,7 +61,7 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplitToList() {
     String simple = "a,b,c";
     List<String> letters = COMMA_SPLITTER.splitToList(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testToString() {
@@ -74,72 +73,74 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplitWithNoDelimiter() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on('.').split(simple);
-    assertThat(letters).iteratesAs("a,b,c");
+    assertThat(letters).containsExactly("a,b,c").inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiter() {
     String doubled = "a,,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(doubled);
-    assertThat(letters).iteratesAs("a", "", "b", "c");
+    assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiterAndSpace() {
     String doubled = "a,, b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(doubled);
-    assertThat(letters).iteratesAs("a", "", " b", "c");
+    assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
   }
 
   public void testCharacterSplitWithTrailingDelimiter() {
     String trailing = "a,b,c,";
     Iterable<String> letters = COMMA_SPLITTER.split(trailing);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testCharacterSplitWithLeadingDelimiter() {
     String leading = ",a,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(leading);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testCharacterSplitWithMulitpleLetters() {
     Iterable<String> testCharacteringMotto = Splitter.on('-').split(
         "Testing-rocks-Debugging-sucks");
-    assertThat(testCharacteringMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testCharacteringMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testCharacterSplitWithMatcherDelimiter() {
     Iterable<String> testCharacteringMotto = Splitter
         .on(CharMatcher.WHITESPACE)
         .split("Testing\nrocks\tDebugging sucks");
-    assertThat(testCharacteringMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testCharacteringMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
     String doubled = "a..b.c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().split(doubled);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testCharacterSplitEmptyToken() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.').trimResults()
         .split(emptyToken);
-    assertThat(letters).iteratesAs("a", "", "c");
+    assertThat(letters).containsExactly("a", "", "c").inOrder();
   }
 
   public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "c");
+    assertThat(letters).containsExactly("a", "c").inOrder();
   }
 
   public void testCharacterSplitOnEmptyString() {
     Iterable<String> nothing = Splitter.on('.').split("");
-    assertThat(nothing).iteratesAs("");
+    assertThat(nothing).containsExactly("").inOrder();
   }
 
   public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
@@ -148,7 +149,7 @@ public class SplitterTest extends TestCase {
 
   public void testCharacterSplitOnOnlyDelimiter() {
     Iterable<String> blankblank = Splitter.on('.').split(".");
-    assertThat(blankblank).iteratesAs("", "");
+    assertThat(blankblank).containsExactly("", "").inOrder();
   }
 
   public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -162,99 +163,102 @@ public class SplitterTest extends TestCase {
     Iterable<String> family = COMMA_SPLITTER
         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
         .split(jacksons);
-    assertThat(family).iteratesAs(
-        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+    assertThat(family)
+        .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+        .inOrder();
   }
 
   public void testStringSimpleSplit() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on(',').split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSimpleSplitWithNoDelimiter() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on('.').split(simple);
-    assertThat(letters).iteratesAs("a,b,c");
+    assertThat(letters).containsExactly("a,b,c").inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiter() {
     String doubled = "a,,b,c";
     Iterable<String> letters = Splitter.on(',').split(doubled);
-    assertThat(letters).iteratesAs("a", "", "b", "c");
+    assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiterAndSpace() {
     String doubled = "a,, b,c";
     Iterable<String> letters = Splitter.on(',').split(doubled);
-    assertThat(letters).iteratesAs("a", "", " b", "c");
+    assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
   }
 
   public void testStringSplitWithTrailingDelimiter() {
     String trailing = "a,b,c,";
     Iterable<String> letters = Splitter.on(',').split(trailing);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testStringSplitWithLeadingDelimiter() {
     String leading = ",a,b,c";
     Iterable<String> letters = Splitter.on(',').split(leading);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithMultipleLetters() {
     Iterable<String> testStringingMotto = Splitter.on('-').split(
         "Testing-rocks-Debugging-sucks");
-    assertThat(testStringingMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testStringingMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
     String doubled = "a..b.c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().split(doubled);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSplitEmptyToken() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.').trimResults()
         .split(emptyToken);
-    assertThat(letters).iteratesAs("a", "", "c");
+    assertThat(letters).containsExactly("a", "", "c").inOrder();
   }
 
   public void testStringSplitEmptyTokenOmitEmptyStrings() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "c");
+    assertThat(letters).containsExactly("a", "c").inOrder();
   }
 
   public void testStringSplitWithLongDelimiter() {
     String longDelimiter = "a, b, c";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithLongLeadingDelimiter() {
     String longDelimiter = ", a, b, c";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithLongTrailingDelimiter() {
     String longDelimiter = "a, b, c, ";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testStringSplitWithDelimiterSubstringInValue() {
     String fourCommasAndFourSpaces = ",,,,    ";
     Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
         fourCommasAndFourSpaces);
-    assertThat(threeCommasThenThreeSpaces).iteratesAs(",,,", "   ");
+    assertThat(threeCommasThenThreeSpaces).containsExactly(",,,", "   ").inOrder();
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringSplitWithEmptyString() {
     try {
       Splitter.on("");
@@ -265,7 +269,7 @@ public class SplitterTest extends TestCase {
 
   public void testStringSplitOnEmptyString() {
     Iterable<String> notMuch = Splitter.on('.').split("");
-    assertThat(notMuch).iteratesAs("");
+    assertThat(notMuch).containsExactly("").inOrder();
   }
 
   public void testStringSplitOnEmptyStringOmitEmptyString() {
@@ -274,7 +278,7 @@ public class SplitterTest extends TestCase {
 
   public void testStringSplitOnOnlyDelimiter() {
     Iterable<String> blankblank = Splitter.on('.').split(".");
-    assertThat(blankblank).iteratesAs("", "");
+    assertThat(blankblank).containsExactly("", "").inOrder();
   }
 
   public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -288,8 +292,9 @@ public class SplitterTest extends TestCase {
     Iterable<String> family = Splitter.on(',')
         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
         .split(jacksons);
-    assertThat(family).iteratesAs(
-        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+    assertThat(family)
+        .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+        .inOrder();
   }
 
   // TODO(kevinb): the name of this method suggests it might not actually be testing what it
@@ -341,31 +346,31 @@ public class SplitterTest extends TestCase {
   public void testFixedLengthSimpleSplit() {
     String simple = "abcde";
     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
-    assertThat(letters).iteratesAs("ab", "cd", "e");
+    assertThat(letters).containsExactly("ab", "cd", "e").inOrder();
   }
 
   public void testFixedLengthSplitEqualChunkLength() {
     String simple = "abcdef";
     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
-    assertThat(letters).iteratesAs("ab", "cd", "ef");
+    assertThat(letters).containsExactly("ab", "cd", "ef").inOrder();
   }
 
   public void testFixedLengthSplitOnlyOneChunk() {
     String simple = "abc";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("abc");
+    assertThat(letters).containsExactly("abc").inOrder();
   }
 
   public void testFixedLengthSplitSmallerString() {
     String simple = "ab";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("ab");
+    assertThat(letters).containsExactly("ab").inOrder();
   }
 
   public void testFixedLengthSplitEmptyString() {
     String simple = "";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("");
+    assertThat(letters).containsExactly("").inOrder();
   }
 
   public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
@@ -375,9 +380,10 @@ public class SplitterTest extends TestCase {
   public void testFixedLengthSplitIntoChars() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c", "d");
+    assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFixedLengthSplitZeroChunkLen() {
     try {
       Splitter.fixedLength(0);
@@ -386,6 +392,7 @@ public class SplitterTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFixedLengthSplitNegativeChunkLen() {
     try {
       Splitter.fixedLength(-1);
@@ -397,73 +404,73 @@ public class SplitterTest extends TestCase {
   public void testLimitLarge() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c", "d");
+    assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
   }
 
   public void testLimitOne() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
-    assertThat(letters).iteratesAs("abcd");
+    assertThat(letters).containsExactly("abcd").inOrder();
   }
 
   public void testLimitFixedLength() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
-    assertThat(letters).iteratesAs("a", "bcd");
+    assertThat(letters).containsExactly("a", "bcd").inOrder();
   }
 
   public void testLimitSeparator() {
     String simple = "a,b,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
-    assertThat(items).iteratesAs("a", "b,c,d");
+    assertThat(items).containsExactly("a", "b,c,d").inOrder();
   }
 
   public void testLimitExtraSeparators() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
-    assertThat(items).iteratesAs("a", ",,b,,c,d");
+    assertThat(items).containsExactly("a", ",,b,,c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsOmitEmpty() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
-    assertThat(items).iteratesAs("a", "b,,c,d");
+    assertThat(items).containsExactly("a", "b,,c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsOmitEmpty3() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
-    assertThat(items).iteratesAs("a", "b", "c,d");
+    assertThat(items).containsExactly("a", "b", "c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a", "b ,, c,d");
+    assertThat(items).containsExactly("a", "b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim3() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a", "b", "c,d");
+    assertThat(items).containsExactly("a", "b", "c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a,,  , b ,, c,d");
+    assertThat(items).containsExactly("a,,  , b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1NoOmit() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
-    assertThat(items).iteratesAs(",,a,,  , b ,, c,d");
+    assertThat(items).containsExactly(",,a,,  , b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1Empty() {
     String text = "";
     Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
-    assertThat(items).iteratesAs("");
+    assertThat(items).containsExactly("").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1EmptyOmit() {
@@ -481,19 +488,15 @@ public class SplitterTest extends TestCase {
     }
   }
 
-  private static <E> List<E> asList(Collection<E> collection) {
-    return ImmutableList.copyOf(collection);
-  }
-
   public void testMapSplitter_trimmedBoth() {
     Map<String, String> m = COMMA_SPLITTER
         .trimResults()
         .withKeyValueSeparator(Splitter.on(':').trimResults())
         .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
     ImmutableMap<String, String> expected =
-          ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
+        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_trimmedEntries() {
@@ -505,7 +508,7 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy  ", " tom", "girl", " tina", "cat  ", " kitty", "dog", " tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_trimmedKeyValue() {
@@ -515,7 +518,7 @@ public class SplitterTest extends TestCase {
     ImmutableMap<String, String> expected =
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_notTrimmed() {
@@ -524,7 +527,7 @@ public class SplitterTest extends TestCase {
     ImmutableMap<String, String> expected =
         ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", "  tommy ");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_CharacterSeparator() {
@@ -537,7 +540,7 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_multiCharacterSeparator() {
@@ -550,10 +553,10 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
-  @SuppressWarnings("ReturnValueIgnored") // testing for exception
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_emptySeparator() {
     try {
       COMMA_SPLITTER.withKeyValueSeparator("");
@@ -562,6 +565,7 @@ public class SplitterTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_malformedEntry() {
     try {
       COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
@@ -575,7 +579,7 @@ public class SplitterTest extends TestCase {
         .withKeyValueSeparator(":")
         .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
 
-    assertThat(m.keySet()).iteratesAs("boy", "girl", "cat", "dog");
+    assertThat(m.keySet()).containsExactly("boy", "girl", "cat", "dog").inOrder();
     assertThat(m).isEqualTo(
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
 
@@ -584,11 +588,12 @@ public class SplitterTest extends TestCase {
         .withKeyValueSeparator(":")
         .split("girl:tina,boy:tom,dog:tommy,cat:kitty");
 
-    assertThat(m.keySet()).iteratesAs("girl", "boy", "dog", "cat");
+    assertThat(m.keySet()).containsExactly("girl", "boy", "dog", "cat").inOrder();
     assertThat(m).isEqualTo(
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_duplicateKeys() {
     try {
       Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
index b8da84d..55a1593 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
@@ -167,48 +167,5 @@ public class StopwatchTest extends TestCase {
     assertEquals(1, stopwatch.elapsed(MILLISECONDS));
   }
 
-  public void testElapsedMillis() {
-    stopwatch.start();
-    ticker.advance(999999);
-    assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-    ticker.advance(1);
-    assertEquals(1, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_whileRunning() {
-    ticker.advance(78000000);
-    stopwatch.start();
-    assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-
-    ticker.advance(345000000);
-    assertEquals(345, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_notRunning() {
-    ticker.advance(1000000);
-    stopwatch.start();
-    ticker.advance(4000000);
-    stopwatch.stop();
-    ticker.advance(9000000);
-    assertEquals(4, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_multipleSegments() {
-    stopwatch.start();
-    ticker.advance(9000000);
-    stopwatch.stop();
-
-    ticker.advance(16000000);
-
-    stopwatch.start();
-    assertEquals(9, stopwatch.elapsed(MILLISECONDS));
-    ticker.advance(25000000);
-    assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-
-    stopwatch.stop();
-    ticker.advance(36000000);
-    assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-  }
-
 }
 
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
index 96395d8..4a0eddf 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
@@ -66,6 +66,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testPadStart_null() {
     try {
       Strings.padStart(null, 5, '0');
@@ -95,6 +96,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testPadEnd_null() {
     try {
       Strings.padEnd(null, 5, '0');
@@ -103,6 +105,7 @@ public class StringsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testRepeat() {
     String input = "20";
     assertEquals("", Strings.repeat(input, 0));
@@ -130,6 +133,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testRepeat_null() {
     try {
       Strings.repeat(null, 5);
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
index 10545bc..95b5c62 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
@@ -16,10 +16,22 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+import static java.lang.Character.MAX_CODE_POINT;
+import static java.lang.Character.MAX_HIGH_SURROGATE;
+import static java.lang.Character.MAX_LOW_SURROGATE;
+import static java.lang.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableList;
 
 import junit.framework.TestCase;
 
+import java.util.HashMap;
+import java.util.Random;
+
 /**
  * Unit tests for {@link Utf8}.
  *
@@ -29,6 +41,26 @@ import junit.framework.TestCase;
  */
 @GwtCompatible(emulated = true)
 public class Utf8Test extends TestCase {
+
+  private static final ImmutableList<String> ILL_FORMED_STRINGS;
+  static {
+    ImmutableList.Builder<String> builder = ImmutableList.builder();
+    char[] surrogates = {
+      MAX_LOW_SURROGATE,
+      MAX_HIGH_SURROGATE,
+      MIN_LOW_SURROGATE,
+      MIN_HIGH_SURROGATE,
+    };
+    for (char surrogate : surrogates) {
+      builder.add(newString(surrogate));
+      builder.add(newString(surrogate, 'n'));
+      builder.add(newString('n', surrogate));
+      builder.add(newString(surrogate, surrogate));
+    }
+    builder.add(newString(MIN_LOW_SURROGATE, MAX_HIGH_SURROGATE));
+    ILL_FORMED_STRINGS = builder.build();
+  }
+
   public void testEncodedLength_validStrings() {
     assertEquals(0, Utf8.encodedLength(""));
     assertEquals(11, Utf8.encodedLength("Hello world"));
@@ -40,29 +72,57 @@ public class Utf8Test extends TestCase {
         + "狹斯丕爾。[2]莎士比亞編寫過好多作品,佢嗰劇作響西洋文學好有影響,"
         + "哈都拕人翻譯做好多話。"));
     // A surrogate pair
-    assertEquals(4, Utf8.encodedLength(
-        newString(Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE)));
+    assertEquals(4, Utf8.encodedLength(newString(MIN_HIGH_SURROGATE, MIN_LOW_SURROGATE)));
+  }
+
+  public void testEncodedLength_validStrings2() {
+    HashMap<Integer, Integer> utf8Lengths = new HashMap<Integer, Integer>();
+    utf8Lengths.put(0x00, 1);
+    utf8Lengths.put(0x7f, 1);
+    utf8Lengths.put(0x80, 2);
+    utf8Lengths.put(0x7ff, 2);
+    utf8Lengths.put(0x800, 3);
+    utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
+    utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT, 4);
+    utf8Lengths.put(MAX_CODE_POINT, 4);
+
+    Integer[] codePoints = utf8Lengths.keySet().toArray(new Integer[]{});
+    StringBuilder sb = new StringBuilder();
+    Random rnd = new Random();
+    for (int trial = 0; trial < 100; trial++) {
+      sb.setLength(0);
+      int utf8Length = 0;
+      for (int i = 0; i < 6; i++) {
+        Integer randomCodePoint = codePoints[rnd.nextInt(codePoints.length)];
+        sb.appendCodePoint(randomCodePoint);
+        utf8Length += utf8Lengths.get(randomCodePoint);
+        if (utf8Length != Utf8.encodedLength(sb)) {
+          StringBuilder repro = new StringBuilder();
+          for (int j = 0; j < sb.length(); j++) {
+            repro.append(" " + (int) sb.charAt(j));  // GWT compatible
+          }
+          assertEquals(repro.toString(), utf8Length, Utf8.encodedLength(sb));
+        }
+      }
+    }
   }
 
   public void testEncodedLength_invalidStrings() {
-    testEncodedLengthFails(newString(Character.MIN_HIGH_SURROGATE), 0);
-    testEncodedLengthFails("foobar" + newString(Character.MIN_HIGH_SURROGATE), 6);
-    testEncodedLengthFails(newString(Character.MIN_LOW_SURROGATE), 0);
-    testEncodedLengthFails("foobar" + newString(Character.MIN_LOW_SURROGATE), 6);
-    testEncodedLengthFails(
-        newString(
-            Character.MIN_HIGH_SURROGATE,
-            Character.MIN_HIGH_SURROGATE), 0);
+    testEncodedLengthFails(newString(MIN_HIGH_SURROGATE), 0);
+    testEncodedLengthFails("foobar" + newString(MIN_HIGH_SURROGATE), 6);
+    testEncodedLengthFails(newString(MIN_LOW_SURROGATE), 0);
+    testEncodedLengthFails("foobar" + newString(MIN_LOW_SURROGATE), 6);
+    testEncodedLengthFails(newString(MIN_HIGH_SURROGATE, MIN_HIGH_SURROGATE), 0);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void testEncodedLengthFails(String invalidString,
       int invalidCodePointIndex) {
     try {
       Utf8.encodedLength(invalidString);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Unpaired surrogate at index " + invalidCodePointIndex,
-          expected.getMessage());
+      assertThat(expected).hasMessage("Unpaired surrogate at index " + invalidCodePointIndex);
     }
   }
 
@@ -169,11 +229,11 @@ public class Utf8Test extends TestCase {
     assertEquals(EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
   }
 
-  private String newString(char... chars) {
+  private static String newString(char... chars) {
     return new String(chars);
   }
 
-  private byte[] toByteArray(int... bytes) {
+  private static byte[] toByteArray(int... bytes) {
     byte[] realBytes = new byte[bytes.length];
     for (int i = 0; i < bytes.length; i++) {
       realBytes[i] = (byte) bytes[i];
@@ -181,11 +241,11 @@ public class Utf8Test extends TestCase {
     return realBytes;
   }
 
-  private void assertWellFormed(int... bytes) {
+  private static void assertWellFormed(int... bytes) {
     assertTrue(Utf8.isWellFormed(toByteArray(bytes)));
   }
 
-  private void assertNotWellFormed(int... bytes) {
+  private static void assertNotWellFormed(int... bytes) {
     assertFalse(Utf8.isWellFormed(toByteArray(bytes)));
   }
 
@@ -214,4 +274,3 @@ public class Utf8Test extends TestCase {
     return expected;
   }
 }
-
diff --git a/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java b/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
index 668a066..dfb0a18 100644
--- a/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
+++ b/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
@@ -20,6 +20,7 @@ import static com.google.common.cache.TestingCacheLoaders.constantLoader;
 import static com.google.common.cache.TestingCacheLoaders.identityLoader;
 import static com.google.common.cache.TestingRemovalListeners.countingRemovalListener;
 import static com.google.common.cache.TestingRemovalListeners.nullRemovalListener;
+import static com.google.common.truth.Truth.assertThat;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
@@ -28,6 +29,8 @@ import com.google.common.base.Ticker;
 
 import junit.framework.TestCase;
 
+import java.util.Set;
+
 /**
  * Unit tests for CacheBuilder.
  */
@@ -187,6 +190,11 @@ public class CacheBuilderTest extends TestCase {
     } catch (IllegalStateException expected) {}
   }
 
+  public void testValuesIsNotASet() {
+    assertThat(new CacheBuilder<Object, Object>().build().asMap().values())
+        .isNotInstanceOf(Set.class);
+  }
+
   // "Basher tests", where we throw a bunch of stuff at a LoadingCache and check basic invariants.
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
index b16137a..58db77a 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
@@ -271,7 +271,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .add("d", "e", "f")
         .add("g", "h", "i", "j")
         .build();
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j").inOrder();
   }
 
@@ -279,9 +279,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
     ImmutableSet.Builder<String> builder = this.<String>builder()
         .add("a")
         .add("b");
-    assertThat(builder.build()).has().exactly("a", "b").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b").inOrder();
     builder.add("c", "d");
-    assertThat(builder.build()).has().exactly("a", "b", "c", "d").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b", "c", "d").inOrder();
   }
 
   public void testBuilderWithDuplicateElements() {
@@ -301,9 +301,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .add("a")
         .add("a", "a")
         .add("b");
-    assertThat(builder.build()).has().exactly("a", "b").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b").inOrder();
     builder.add("a", "b", "c", "c");
-    assertThat(builder.build()).has().exactly("a", "b", "c").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testBuilderAddAll() {
@@ -313,7 +313,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .addAll(a)
         .addAll(b)
         .build();
-    assertThat(set).has().exactly("a", "b", "c", "d", "e").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e").inOrder();
   }
 
   static final int LAST_COLOR_ADDED = 0x00BFFF;
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
index 81b9b85..689e6b9 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
@@ -37,7 +37,7 @@ public class AbstractSequentialIteratorTest extends TestCase {
         return newDoubler(2, 32);
       }
     };
-    assertThat(doubled).iteratesAs(2, 4, 8, 16, 32);
+    assertThat(doubled).containsExactly(2, 4, 8, 16, 32).inOrder();
   }
 
   public void testSampleCode() {
@@ -52,9 +52,11 @@ public class AbstractSequentialIteratorTest extends TestCase {
         return powersOfTwo;
       }
     };
-    assertThat(actual).iteratesAs(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
-        4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
-        8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824);
+    assertThat(actual)
+        .containsExactly(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
+            32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216,
+            33554432, 67108864, 134217728, 268435456, 536870912, 1073741824)
+        .inOrder();
   }
 
   public void testEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
index 342b112..fdf96e4 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
@@ -181,7 +181,7 @@ public abstract class AbstractTableReadTest extends TestCase {
   public void testColumnSetPartialOverlap() {
     table = create(
         "foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd');
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3);
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3);
   }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
index 18339cc..191847f 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
@@ -82,9 +82,9 @@ public class ArrayListMultimapTest extends TestCase {
     ListMultimap<String, Integer> multimap = create();
     multimap.putAll("foo", asList(1, 2, 3, 4, 5));
     List<Integer> list = multimap.get("foo");
-    assertThat(multimap.get("foo")).has().exactly(1, 2, 3, 4, 5).inOrder();
+    assertThat(multimap.get("foo")).containsExactly(1, 2, 3, 4, 5).inOrder();
     List<Integer> sublist = list.subList(0, 5);
-    assertThat(sublist).has().exactly(1, 2, 3, 4, 5).inOrder();
+    assertThat(sublist).containsExactly(1, 2, 3, 4, 5).inOrder();
 
     sublist.clear();
     assertTrue(sublist.isEmpty());
@@ -153,8 +153,8 @@ public class ArrayListMultimapTest extends TestCase {
     multimap.put("bar", 3);
     multimap.trimToSize();
     assertEquals(3, multimap.size());
-    assertThat(multimap.get("foo")).has().exactly(1, 2).inOrder();
-    assertThat(multimap.get("bar")).has().item(3);
+    assertThat(multimap.get("foo")).containsExactly(1, 2).inOrder();
+    assertThat(multimap.get("bar")).contains(3);
   }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
index 76cc870..817ce68 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
@@ -279,13 +279,13 @@ public class ArrayTableTest extends AbstractTableTest {
   public void testRowKeyList() {
     ArrayTable<String, Integer, Character> table
         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
-    assertThat(table.rowKeyList()).has().exactly("foo", "bar", "cat").inOrder();
+    assertThat(table.rowKeyList()).containsExactly("foo", "bar", "cat").inOrder();
   }
 
   public void testColumnKeyList() {
     ArrayTable<String, Integer, Character> table
         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
-    assertThat(table.columnKeyList()).has().exactly(1, 2, 3).inOrder();
+    assertThat(table.columnKeyList()).containsExactly(1, 2, 3).inOrder();
   }
 
   public void testGetMissingKeys() {
@@ -362,13 +362,13 @@ public class ArrayTableTest extends AbstractTableTest {
       table.put("dog", 1, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+      assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
     }
     try {
       table.put("foo", 4, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+      assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
     }
     assertFalse(table.containsValue('d'));
   }
@@ -422,7 +422,7 @@ public class ArrayTableTest extends AbstractTableTest {
       map.put(4, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+      assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
     }
   }
 
@@ -433,7 +433,7 @@ public class ArrayTableTest extends AbstractTableTest {
       map.put("dog", 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+      assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
     }
   }
 }
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
index 31e19a4..b788479 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
@@ -79,7 +79,7 @@ public class Collections2Test extends TestCase {
         Collections2.orderedPermutations(list);
 
     assertEquals(1, permutationSet.size());
-    assertThat(permutationSet).has().item(list);
+    assertThat(permutationSet).contains(list);
 
     Iterator<List<Integer>> permutations = permutationSet.iterator();
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
index ea7efe1..f2ef4ca 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
@@ -67,6 +67,10 @@ public class ContiguousSetTest extends TestCase {
             ContiguousSet.create(Range.openClosed(0, 3), NOT_EQUAL_TO_INTEGERS),
             ContiguousSet.create(Range.open(0, 4), NOT_EQUAL_TO_INTEGERS),
             ImmutableSortedSet.of(1, 2, 3))
+        .addEqualityGroup(
+            ContiguousSet.create(Range.closedOpen(1, 1), integers()),
+            ImmutableSortedSet.of(),
+            ImmutableSet.of())
         .testEquals();
     // not testing hashCode for these because it takes forever to compute
     assertEquals(
@@ -108,15 +112,15 @@ public class ContiguousSetTest extends TestCase {
   public void testHeadSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
     assertThat(set.headSet(1)).isEmpty();
-    assertThat(set.headSet(2)).has().item(1);
-    assertThat(set.headSet(3)).has().exactly(1, 2).inOrder();
-    assertThat(set.headSet(4)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(1, true)).has().item(1);
-    assertThat(set.headSet(2, true)).has().exactly(1, 2).inOrder();
-    assertThat(set.headSet(3, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(4, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(Integer.MAX_VALUE, true)).has().exactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(2)).contains(1);
+    assertThat(set.headSet(3)).containsExactly(1, 2).inOrder();
+    assertThat(set.headSet(4)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(1, true)).contains(1);
+    assertThat(set.headSet(2, true)).containsExactly(1, 2).inOrder();
+    assertThat(set.headSet(3, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(4, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(Integer.MAX_VALUE, true)).containsExactly(1, 2, 3).inOrder();
   }
 
   public void testHeadSet_tooSmall() {
@@ -125,13 +129,13 @@ public class ContiguousSetTest extends TestCase {
 
   public void testTailSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
-    assertThat(set.tailSet(Integer.MIN_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(1)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(2)).has().exactly(2, 3).inOrder();
-    assertThat(set.tailSet(3)).has().item(3);
-    assertThat(set.tailSet(Integer.MIN_VALUE, false)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(1, false)).has().exactly(2, 3).inOrder();
-    assertThat(set.tailSet(2, false)).has().item(3);
+    assertThat(set.tailSet(Integer.MIN_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(1)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(2)).containsExactly(2, 3).inOrder();
+    assertThat(set.tailSet(3)).contains(3);
+    assertThat(set.tailSet(Integer.MIN_VALUE, false)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(1, false)).containsExactly(2, 3).inOrder();
+    assertThat(set.tailSet(2, false)).contains(3);
     assertThat(set.tailSet(3, false)).isEmpty();
   }
 
@@ -141,19 +145,19 @@ public class ContiguousSetTest extends TestCase {
 
   public void testSubSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
-    assertThat(set.subSet(1, 4)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(2, 4)).has().exactly(2, 3).inOrder();
-    assertThat(set.subSet(3, 4)).has().item(3);
+    assertThat(set.subSet(1, 4)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(2, 4)).containsExactly(2, 3).inOrder();
+    assertThat(set.subSet(3, 4)).contains(3);
     assertThat(set.subSet(3, 3)).isEmpty();
-    assertThat(set.subSet(2, 3)).has().item(2);
-    assertThat(set.subSet(1, 3)).has().exactly(1, 2).inOrder();
-    assertThat(set.subSet(1, 2)).has().item(1);
+    assertThat(set.subSet(2, 3)).contains(2);
+    assertThat(set.subSet(1, 3)).containsExactly(1, 2).inOrder();
+    assertThat(set.subSet(1, 2)).contains(1);
     assertThat(set.subSet(2, 2)).isEmpty();
-    assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(1, true, 3, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(1, false, 3, true)).has().exactly(2, 3).inOrder();
-    assertThat(set.subSet(1, true, 3, false)).has().exactly(1, 2).inOrder();
-    assertThat(set.subSet(1, false, 3, false)).has().item(2);
+    assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(1, true, 3, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(1, false, 3, true)).containsExactly(2, 3).inOrder();
+    assertThat(set.subSet(1, true, 3, false)).containsExactly(1, 2).inOrder();
+    assertThat(set.subSet(1, false, 3, false)).contains(2);
   }
 
   public void testSubSet_outOfOrder() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
index bed6626..89bd9a7 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
@@ -173,16 +173,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
   }
 
   public void testKeySetIteratorRemove() {
@@ -200,16 +200,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.FRANC, Currency.PESO).inOrder();
+        .containsExactly(Currency.FRANC, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.SWITZERLAND, Country.CHILE).inOrder();
+        .containsExactly(Country.SWITZERLAND, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CHILE, Country.SWITZERLAND).inOrder();
+        .containsExactly(Country.CHILE, Country.SWITZERLAND).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.PESO, Currency.FRANC).inOrder();
+        .containsExactly(Currency.PESO, Currency.FRANC).inOrder();
   }
 
   public void testValuesIteratorRemove() {
@@ -228,16 +228,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
   }
 
   public void testEntrySet() {
diff --git a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
similarity index 91%
copy from guava-tests/test/com/google/common/collect/EvictingQueueTest.java
copy to guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
index 9567dee..598622e 100644
--- a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
@@ -18,7 +18,7 @@ package com.google.common.collect;
 
 import static java.util.Arrays.asList;
 
-import com.google.common.testing.NullPointerTester;
+import com.google.common.annotations.GwtCompatible;
 import com.google.common.testing.SerializableTester;
 
 import junit.framework.TestCase;
@@ -30,6 +30,7 @@ import java.util.NoSuchElementException;
  *
  * @author Kurt Alfred Kluever
  */
+ at GwtCompatible(emulated = true)
 public class EvictingQueueTest extends TestCase {
 
   public void testCreateWithNegativeSize() throws Exception {
@@ -157,16 +158,6 @@ public class EvictingQueueTest extends TestCase {
     assertEquals(1, queue.remainingCapacity());
   }
 
-  public void testNullPointerExceptions() {
-    NullPointerTester tester = new NullPointerTester();
-    tester.testAllPublicStaticMethods(EvictingQueue.class);
-    tester.testAllPublicConstructors(EvictingQueue.class);
-    EvictingQueue<String> queue = EvictingQueue.create(5);
-    // The queue must be non-empty so it throws a NPE correctly
-    queue.add("one");
-    tester.testAllPublicInstanceMethods(queue);
-  }
-
   public void testSerialization() {
     EvictingQueue<String> original = EvictingQueue.create(5);
     original.add("one");
@@ -181,3 +172,4 @@ public class EvictingQueueTest extends TestCase {
     assertTrue(copy.isEmpty());
   }
 }
+
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
index 428805d..672013d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
@@ -102,5 +102,13 @@ public class HashBiMapTest extends TestCase {
     iterator.remove(); // removes the updated entry
     assertTrue(map.isEmpty());
   }
+  
+  public void testInverseEntrySetValue() {
+    BiMap<Integer, String> map = HashBiMap.create();
+    map.put(1, "one");
+    Entry<String, Integer> inverseEntry = Iterables.getOnlyElement(map.inverse().entrySet());
+    inverseEntry.setValue(2);
+    assertEquals(Integer.valueOf(2), inverseEntry.getValue());
+  }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
index 514effe..f8817cb 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
@@ -131,6 +131,13 @@ public class ImmutableBiMapTest extends TestCase {
       assertMapEquals(map.inverse(), 1, "one");
     }
 
+    public void testBuilder_withImmutableEntry() {
+      ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
+          .put(Maps.immutableEntry("one", 1))
+          .build();
+      assertMapEquals(map, "one", 1);
+    }
+
     public void testBuilder() {
       ImmutableBiMap<String, Integer> map
           = ImmutableBiMap.<String, Integer>builder()
@@ -145,6 +152,41 @@ public class ImmutableBiMapTest extends TestCase {
       assertMapEquals(map.inverse(),
           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
     }
+    
+    public void testBuilder_orderEntriesByValue() {
+      ImmutableBiMap<String, Integer> map =
+          ImmutableBiMap.<String, Integer>builder()
+              .orderEntriesByValue(Ordering.natural())
+              .put("three", 3)
+              .put("one", 1)
+              .put("five", 5)
+              .put("four", 4)
+              .put("two", 2)
+              .build();
+      assertMapEquals(map,
+          "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+      assertMapEquals(map.inverse(),
+          1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
+    }
+    
+    public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+      ImmutableBiMap.Builder<String, Integer> builder =
+          new ImmutableBiMap.Builder<String, Integer>(2).put("four", 4).put("one", 1);
+      ImmutableMap<String, Integer> keyOrdered = builder.build();
+      ImmutableMap<String, Integer> valueOrdered =
+          builder.orderEntriesByValue(Ordering.natural()).build();
+      assertMapEquals(keyOrdered, "four", 4, "one", 1);
+      assertMapEquals(valueOrdered, "one", 1, "four", 4);
+    }
+    
+    public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+      ImmutableBiMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural());
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {}
+    }
 
     public void testBuilderPutAllWithEmptyMap() {
       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
@@ -235,7 +277,7 @@ public class ImmutableBiMapTest extends TestCase {
         builder.build();
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("one"));
+        assertThat(expected.getMessage()).contains("one");
       }
     }
 
@@ -308,7 +350,7 @@ public class ImmutableBiMapTest extends TestCase {
         ImmutableBiMap.of("one", 1, "one", 1);
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("one"));
+        assertThat(expected.getMessage()).contains("one");
       }
     }
 
@@ -382,7 +424,7 @@ public class ImmutableBiMapTest extends TestCase {
         ImmutableBiMap.copyOf(map);
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("1"));
+        assertThat(expected.getMessage()).contains("1");
       }
     }
   }
@@ -404,7 +446,7 @@ public class ImmutableBiMapTest extends TestCase {
           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
       Set<String> keys = bimap.keySet();
       assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
-      assertThat(keys).has().exactly("one", "two", "three", "four").inOrder();
+      assertThat(keys).containsExactly("one", "two", "three", "four").inOrder();
     }
 
     public void testValues() {
@@ -412,7 +454,7 @@ public class ImmutableBiMapTest extends TestCase {
           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
       Set<Integer> values = bimap.values();
       assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
-      assertThat(values).has().exactly(1, 2, 3, 4).inOrder();
+      assertThat(values).containsExactly(1, 2, 3, 4).inOrder();
     }
 
     public void testDoubleInverse() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
index 1233a93..9a4d548 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
@@ -55,7 +55,7 @@ public class ImmutableEnumMapTest extends TestCase {
     ImmutableMap<AnEnum, String> map = Maps.immutableEnumMap(
         ImmutableMap.of(AnEnum.C, "c", AnEnum.A, "a", AnEnum.E, "e"));
 
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Helpers.mapEntry(AnEnum.A, "a"),
         Helpers.mapEntry(AnEnum.C, "c"),
         Helpers.mapEntry(AnEnum.E, "e")).inOrder();
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
index b71caa8..0a66661 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
@@ -47,6 +47,13 @@ public class ImmutableListMultimapTest extends TestCase {
       return builder.build();
     }
   }
+  public static class ImmutableListMultimapCopyOfEntriesGenerator 
+      extends TestStringListMultimapGenerator {
+    @Override
+    protected ListMultimap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableListMultimap.copyOf(Arrays.asList(entries));
+    }
+  }
 
   public void testBuilder_withImmutableEntry() {
     ImmutableListMultimap<String, Integer> multimap = new Builder<String, Integer>()
@@ -239,10 +246,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
   }
 
   public void testBuilderOrderKeysByDuplicates() {
@@ -261,10 +268,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("bb", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
   }
 
   public void testBuilderOrderValuesBy() {
@@ -278,10 +285,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
-    assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+    assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
   }
 
   public void testBuilderOrderKeysAndValuesBy() {
@@ -296,10 +303,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
   }
 
   public void testCopyOf() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
index 5acce3a..14ce007 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
@@ -119,14 +119,14 @@ public class ImmutableMapTest extends TestCase {
     @Override protected Map<Object, Integer> makePopulatedMap() {
       Colliders colliders = new Colliders();
       return ImmutableMap.of(
-          colliders.e0, 0,
-          colliders.e1, 1,
-          colliders.e2, 2,
-          colliders.e3, 3);
+          colliders.e0(), 0,
+          colliders.e1(), 1,
+          colliders.e2(), 2,
+          colliders.e3(), 3);
     }
 
     @Override protected Object getKeyNotInPopulatedMap() {
-      return new Colliders().e4;
+      return new Colliders().e4();
     }
 
     @Override protected Integer getValueNotInPopulatedMap() {
@@ -159,6 +159,39 @@ public class ImmutableMapTest extends TestCase {
       assertMapEquals(map,
           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
     }
+    
+    public void testBuilder_orderEntriesByValue() {
+      ImmutableMap<String, Integer> map = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural())
+          .put("three", 3)
+          .put("one", 1)
+          .put("five", 5)
+          .put("four", 4)
+          .put("two", 2)
+          .build();
+      assertMapEquals(map,
+          "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+    }
+    
+    public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+      Builder<String, Integer> builder = new Builder<String, Integer>(2)
+          .put("four", 4)
+          .put("one", 1);
+      ImmutableMap<String, Integer> keyOrdered = builder.build();
+      ImmutableMap<String, Integer> valueOrdered =
+          builder.orderEntriesByValue(Ordering.natural()).build();
+      assertMapEquals(keyOrdered, "four", 4, "one", 1);
+      assertMapEquals(valueOrdered, "one", 1, "four", 4);
+    }
+    
+    public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+      ImmutableMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural());
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {}
+    }
 
     public void testBuilder_withImmutableEntry() {
       ImmutableMap<String, Integer> map = new Builder<String, Integer>()
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
index 06b7294..14f0252 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
@@ -101,18 +101,18 @@ public class ImmutableMultimapTest extends TestCase {
   public void testUnhashableSingletonValue() {
     SampleElements<UnhashableObject> unhashables = new Unhashables();
     Multimap<Integer, UnhashableObject> multimap = ImmutableMultimap.of(
-        0, unhashables.e0);
+        0, unhashables.e0());
     assertEquals(1, multimap.get(0).size());
-    assertTrue(multimap.get(0).contains(unhashables.e0));
+    assertTrue(multimap.get(0).contains(unhashables.e0()));
   }
 
   public void testUnhashableMixedValues() {
     SampleElements<UnhashableObject> unhashables = new Unhashables();
     Multimap<Integer, Object> multimap = ImmutableMultimap.<Integer, Object>of(
-        0, unhashables.e0, 2, "hey you", 0, unhashables.e1);
+        0, unhashables.e0(), 2, "hey you", 0, unhashables.e1());
     assertEquals(2, multimap.get(0).size());
-    assertTrue(multimap.get(0).contains(unhashables.e0));
-    assertTrue(multimap.get(0).contains(unhashables.e1));
+    assertTrue(multimap.get(0).contains(unhashables.e0()));
+    assertTrue(multimap.get(0).contains(unhashables.e1()));
     assertTrue(multimap.get(2).contains("hey you"));
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
index 5396ef2..ab42678 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
@@ -354,7 +354,7 @@ public class ImmutableMultisetTest extends TestCase {
 
   public void testIterationOrder() {
     Collection<String> c = ImmutableMultiset.of("a", "b", "a");
-    assertThat(c).has().exactly("a", "a", "b").inOrder();
+    assertThat(c).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testMultisetWrites() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
index 1b1b586..6365e35 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ImmutableSetMultimap.Builder;
+import com.google.common.collect.testing.google.TestStringSetMultimapGenerator;
 import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
 import com.google.common.testing.EqualsTester;
 
@@ -36,6 +37,25 @@ import java.util.Map.Entry;
  */
 @GwtCompatible(emulated = true)
 public class ImmutableSetMultimapTest extends TestCase {
+  private static final class ImmutableSetMultimapGenerator extends
+      TestStringSetMultimapGenerator {
+    @Override
+    protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+      ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
+      for (Entry<String, String> entry : entries) {
+        builder.put(entry.getKey(), entry.getValue());
+      }
+      return builder.build();
+    }
+  }
+  
+  private static final class ImmutableSetMultimapCopyOfEntriesGenerator extends
+      TestStringSetMultimapGenerator {
+    @Override
+    protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableSetMultimap.copyOf(Arrays.asList(entries));
+    }
+  }
 
   public void testBuilder_withImmutableEntry() {
     ImmutableSetMultimap<String, Integer> multimap = new Builder<String, Integer>()
@@ -216,13 +236,13 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
-    assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
-    assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
-    assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
+    assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
   }
 
   public void testBuilderOrderKeysByDuplicates() {
@@ -241,13 +261,13 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("bb", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
-    assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
-    assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
-    assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+    assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
+    assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
   }
 
   public void testBuilderOrderValuesBy() {
@@ -261,10 +281,10 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
-    assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+    assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
     assertEquals(Collections.reverseOrder(),
         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -288,10 +308,10 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
     assertEquals(Collections.reverseOrder(),
         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
index 15cf351..d2fa8aa 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
@@ -103,7 +103,7 @@ public class ImmutableSetTest extends AbstractImmutableSetTest {
     // now we'll get the varargs overload
     ImmutableSet<String> set = ImmutableSet.of(
         "a", "b", "c", "c", "c", "c", "b", "b", "a", "a", "c", "c", "c", "a");
-    assertThat(set).has().exactly("a", "b", "c").inOrder();
+    assertThat(set).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testCreation_arrayOfArray() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
index 1b76d45..603f6ac 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
@@ -212,6 +212,14 @@ public class ImmutableSortedMapTest extends TestCase {
       assertMapEquals(map,
           "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
     }
+    
+    public void testBuilder_orderEntriesByValueFails() {
+      ImmutableSortedMap.Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {}
+    }
 
     public void testBuilder_withImmutableEntry() {
       ImmutableSortedMap<String, Integer> map =
@@ -611,7 +619,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testHeadMapInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3)).inOrder();
   }
@@ -620,14 +628,14 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testHeadMapExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testTailMapInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
         Maps.immutableEntry("two", 2)).inOrder();
   }
 
@@ -635,21 +643,21 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testTailMapExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("two", 2));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testSubMapExclusiveExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testSubMapInclusiveExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3)).inOrder();
   }
 
@@ -657,7 +665,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testSubMapExclusiveInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
         Maps.immutableEntry("two", 2)).inOrder();
   }
 
@@ -665,7 +673,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testSubMapInclusiveInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
index 89d5448..a07df11 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
@@ -145,7 +145,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSingle_headSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.headSet("g") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("g")).has().item("e");
+    assertThat(set.headSet("g")).contains("e");
     assertSame(of(), set.headSet("c"));
     assertSame(of(), set.headSet("e"));
   }
@@ -153,16 +153,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSingle_tailSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.tailSet("c") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("c")).has().item("e");
-    assertThat(set.tailSet("e")).has().item("e");
+    assertThat(set.tailSet("c")).contains("e");
+    assertThat(set.tailSet("e")).contains("e");
     assertSame(of(), set.tailSet("g"));
   }
 
   public void testSingle_subSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.subSet("c", "g") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("c", "g")).has().item("e");
-    assertThat(set.subSet("e", "g")).has().item("e");
+    assertThat(set.subSet("c", "g")).contains("e");
+    assertThat(set.subSet("e", "g")).contains("e");
     assertSame(of(), set.subSet("f", "g"));
     assertSame(of(), set.subSet("c", "e"));
     assertSame(of(), set.subSet("c", "d"));
@@ -180,7 +180,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testOf_ordering() {
     SortedSet<String> set = of("e", "a", "f", "b", "d", "c");
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   /*
@@ -229,7 +229,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testOf_ordering_dupes() {
     SortedSet<String> set = of("e", "a", "e", "f", "b", "b", "d", "a", "c");
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testOf_comparator() {
@@ -240,8 +240,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testOf_headSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.headSet("e") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("e")).has().exactly("b", "c", "d").inOrder();
-    assertThat(set.headSet("g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.headSet("e")).containsExactly("b", "c", "d").inOrder();
+    assertThat(set.headSet("g")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.headSet("a"));
     assertSame(of(), set.headSet("b"));
   }
@@ -249,16 +249,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testOf_tailSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.tailSet("e") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("e")).has().exactly("e", "f").inOrder();
-    assertThat(set.tailSet("a")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.tailSet("e")).containsExactly("e", "f").inOrder();
+    assertThat(set.tailSet("a")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.tailSet("g"));
   }
 
   public void testOf_subSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.subSet("c", "e") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("c", "e")).has().exactly("c", "d").inOrder();
-    assertThat(set.subSet("a", "g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.subSet("c", "e")).containsExactly("c", "d").inOrder();
+    assertThat(set.subSet("a", "g")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.subSet("a", "b"));
     assertSame(of(), set.subSet("g", "h"));
     assertSame(of(), set.subSet("c", "c"));
@@ -284,14 +284,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testExplicit_ordering() {
     SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
         "in", "the", "quick", "jumped", "over", "a").build();
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testExplicit_ordering_dupes() {
     SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
         "in", "the", "quick", "brown", "fox", "jumped",
         "over", "a", "lazy", "dog").build();
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testExplicit_contains() {
@@ -321,9 +321,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.headSet("a") instanceof ImmutableSortedSet);
     assertTrue(set.headSet("fish") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("fish")).has().exactly("a", "in", "the").inOrder();
-    assertThat(set.headSet("california")).has()
-        .exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set.headSet("fish")).containsExactly("a", "in", "the").inOrder();
+    assertThat(set.headSet("california"))
+        .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.headSet("a").isEmpty());
     assertTrue(set.headSet("").isEmpty());
   }
@@ -333,9 +333,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.tailSet("california") instanceof ImmutableSortedSet);
     assertTrue(set.tailSet("fish") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("fish")).has().exactly("over", "quick", "jumped").inOrder();
+    assertThat(set.tailSet("fish")).containsExactly("over", "quick", "jumped").inOrder();
     assertThat(
-        set.tailSet("a")).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+        set.tailSet("a")).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.tailSet("california").isEmpty());
   }
 
@@ -344,9 +344,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.subSet("the", "quick") instanceof ImmutableSortedSet);
     assertTrue(set.subSet("", "b") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("the", "quick")).has().exactly("the", "over").inOrder();
+    assertThat(set.subSet("the", "quick")).containsExactly("the", "over").inOrder();
     assertThat(set.subSet("a", "california"))
-        .has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+        .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.subSet("", "b").isEmpty());
     assertTrue(set.subSet("vermont", "california").isEmpty());
     assertTrue(set.subSet("aaa", "zzz").isEmpty());
@@ -372,13 +372,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testCopyOf_ordering() {
     SortedSet<String> set =
         copyOf(asList("e", "a", "f", "b", "d", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_ordering_dupes() {
     SortedSet<String> set =
         copyOf(asList("e", "a", "e", "f", "b", "b", "d", "a", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_subSet() {
@@ -409,13 +409,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testCopyOf_iterator_ordering() {
     SortedSet<String> set = copyOf(asIterator("e", "a", "f", "b", "d", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_iterator_ordering_dupes() {
     SortedSet<String> set =
         copyOf(asIterator("e", "a", "e", "f", "b", "b", "d", "a", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_iterator_comparator() {
@@ -426,7 +426,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testCopyOf_sortedSet_ordering() {
     SortedSet<String> set =
         copyOf(Sets.newTreeSet(asList("e", "a", "f", "b", "d", "c")));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_sortedSet_comparator() {
@@ -438,7 +438,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> set =
         ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
             "in", "the", "quick", "jumped", "over", "a"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_ordering_dupes() {
@@ -446,7 +446,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
             "in", "the", "quick", "brown", "fox", "jumped", "over", "a",
             "lazy", "dog"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_comparator() {
@@ -460,7 +460,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> set =
         ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
             "in", "the", "quick", "jumped", "over", "a"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_iterator_ordering_dupes() {
@@ -468,7 +468,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
             "in", "the", "quick", "brown", "fox", "jumped", "over", "a",
             "lazy", "dog"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_iterator_comparator() {
@@ -482,14 +482,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
     Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
     SortedSet<String> set = copyOf(input);
-    assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+    assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
   }
 
   public void testCopyOfSorted_natural_ordering() {
     SortedSet<String> input = Sets.newTreeSet(
         asList("in", "the", "quick", "jumped", "over", "a"));
     SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
-    assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+    assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
   }
 
   public void testCopyOfSorted_natural_comparator() {
@@ -503,7 +503,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
     Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
     SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertSame(STRING_LENGTH, set.comparator());
   }
 
@@ -591,7 +591,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testReverseOrder() {
     SortedSet<String> set = ImmutableSortedSet.<String>reverseOrder()
         .add("a", "b", "c").build();
-    assertThat(set).has().exactly("c", "b", "a").inOrder();
+    assertThat(set).containsExactly("c", "b", "a").inOrder();
     assertEquals(Ordering.natural().reverse(), set.comparator());
   }
 
@@ -606,13 +606,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSupertypeComparator() {
     SortedSet<Integer> set = new ImmutableSortedSet.Builder<Integer>(TO_STRING)
         .add(3, 12, 101, 44).build();
-    assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+    assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
   }
 
   public void testSupertypeComparatorSubtypeElements() {
     SortedSet<Number> set = new ImmutableSortedSet.Builder<Number>(TO_STRING)
         .add(3, 12, 101, 44).build();
-    assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+    assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
   }
 
   @Override <E extends Comparable<E>> ImmutableSortedSet.Builder<E> builder() {
@@ -735,7 +735,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
       assertThat(set.headSet(strings[i], true))
-          .has().exactlyAs(sortedNumberNames(0, i + 1)).inOrder();
+          .containsExactlyElementsIn(sortedNumberNames(0, i + 1))
+          .inOrder();
     }
   }
 
@@ -744,8 +745,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.headSet(strings[i], false)).has().exactlyAs(
-          sortedNumberNames(0, i)).inOrder();
+      assertThat(set.headSet(strings[i], false))
+          .containsExactlyElementsIn(sortedNumberNames(0, i))
+          .inOrder();
     }
   }
 
@@ -754,8 +756,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.tailSet(strings[i], true)).has().exactlyAs(
-          sortedNumberNames(i, strings.length)).inOrder();
+      assertThat(set.tailSet(strings[i], true))
+          .containsExactlyElementsIn(sortedNumberNames(i, strings.length))
+          .inOrder();
     }
   }
 
@@ -764,8 +767,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.tailSet(strings[i], false)).has().exactlyAs(
-          sortedNumberNames(i + 1, strings.length)).inOrder();
+      assertThat(set.tailSet(strings[i], false))
+          .containsExactlyElementsIn(sortedNumberNames(i + 1, strings.length))
+          .inOrder();
     }
   }
 
@@ -776,7 +780,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], false, strings[j], false))
-            .has().exactlyAs(sortedNumberNames(Math.min(i + 1, j), j)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(Math.min(i + 1, j), j))
+            .inOrder();
       }
     }
   }
@@ -788,7 +793,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], true, strings[j], false))
-            .has().exactlyAs(sortedNumberNames(i, j)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i, j))
+            .inOrder();
       }
     }
   }
@@ -800,7 +806,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], false, strings[j], true))
-            .has().exactlyAs(sortedNumberNames(i + 1, j + 1)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i + 1, j + 1))
+            .inOrder();
       }
     }
   }
@@ -812,7 +819,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], true, strings[j], true))
-            .has().exactlyAs(sortedNumberNames(i, j + 1)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i, j + 1))
+            .inOrder();
       }
     }
   }
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
index c602d65..685cbf5 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
@@ -184,9 +184,9 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     validateTableCopies(table);
     // Even though rowKeySet, columnKeySet, and cellSet have the same
     // iteration ordering, row has an inconsistent ordering.
-    assertThat(table.row('b').keySet()).has().exactly(1, 2).inOrder();
+    assertThat(table.row('b').keySet()).containsExactly(1, 2).inOrder();
     assertThat(ImmutableTable.copyOf(table).row('b').keySet())
-        .has().exactly(2, 1).inOrder();
+        .containsExactly(2, 1).inOrder();
   }
 
   public void testCopyOfSparse() {
@@ -227,10 +227,10 @@ public class ImmutableTableTest extends AbstractTableReadTest {
         = builder.orderRowsBy(Ordering.natural())
             .orderColumnsBy(Ordering.natural())
             .putAll(table).build();
-    assertThat(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
-    assertThat(copy.columnKeySet()).has().exactly(1, 2).inOrder();
-    assertThat(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
-    assertThat(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
+    assertThat(copy.rowKeySet()).containsExactly('a', 'b').inOrder();
+    assertThat(copy.columnKeySet()).containsExactly(1, 2).inOrder();
+    assertThat(copy.values()).containsExactly("baz", "bar", "foo").inOrder();
+    assertThat(copy.row('b').keySet()).containsExactly(1, 2).inOrder();
   }
 
   public void testBuilder_orderRowsAndColumnsBy_sparse() {
@@ -248,12 +248,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
-    assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
-    assertThat(table.values()).has().exactly("cat", "axe", "baz", "tub",
+    assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+    assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+    assertThat(table.values()).containsExactly("cat", "axe", "baz", "tub",
         "dog", "bar", "foo", "foo", "bar").inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
-    assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
+    assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
   }
 
   public void testBuilder_orderRowsAndColumnsBy_dense() {
@@ -270,12 +270,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.values()).has().exactly("baz", "bar", "foo", "dog",
+    assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.values()).containsExactly("baz", "bar", "foo", "dog",
         "cat", "baz", "bar", "foo").inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
   }
 
   public void testBuilder_orderRowsBy_sparse() {
@@ -292,8 +292,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
-    assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+    assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+    assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
   }
 
   public void testBuilder_orderRowsBy_dense() {
@@ -309,8 +309,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
-    assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+    assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+    assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
   }
 
   public void testBuilder_orderColumnsBy_sparse() {
@@ -327,8 +327,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
+    assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
   }
 
   public void testBuilder_orderColumnsBy_dense() {
@@ -344,8 +344,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
   }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
index 5d0b304..68101ec 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
@@ -26,7 +26,6 @@ import static java.util.Collections.emptyList;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.testing.IteratorTester;
@@ -234,14 +233,10 @@ public class IterablesTest extends TestCase {
 
   public void testTryFind() {
     Iterable<String> list = newArrayList("cool", "pants");
-    assertEquals(Optional.of("cool"),
-        Iterables.tryFind(list, Predicates.equalTo("cool")));
-    assertEquals(Optional.of("pants"),
-        Iterables.tryFind(list, Predicates.equalTo("pants")));
-    assertEquals(Optional.of("cool"),
-        Iterables.tryFind(list, Predicates.alwaysTrue()));
-    assertEquals(Optional.absent(),
-        Iterables.tryFind(list, Predicates.alwaysFalse()));
+    assertThat(Iterables.tryFind(list, Predicates.equalTo("cool"))).hasValue("cool");
+    assertThat(Iterables.tryFind(list, Predicates.equalTo("pants"))).hasValue("pants");
+    assertThat(Iterables.tryFind(list, Predicates.alwaysTrue())).hasValue("cool");
+    assertThat(Iterables.tryFind(list, Predicates.alwaysFalse())).isAbsent();
     assertCanIterateAgain(list);
   }
 
@@ -374,8 +369,7 @@ public class IterablesTest extends TestCase {
     int n = 4;
     Iterable<Integer> repeated
         = Iterables.concat(Collections.nCopies(n, iterable));
-    assertThat(repeated).iteratesAs(
-        1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3);
+    assertThat(repeated).containsExactly(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3).inOrder();
   }
 
   public void testPartition_badSize() {
@@ -451,7 +445,7 @@ public class IterablesTest extends TestCase {
     List<String> freshlyAdded = newArrayList("freshly", "added");
 
     boolean changed = Iterables.addAll(alreadyThere, freshlyAdded);
-    assertThat(alreadyThere).has().exactly(
+    assertThat(alreadyThere).containsExactly(
         "already", "there", "freshly", "added").inOrder();
     assertTrue(changed);
   }
@@ -603,7 +597,7 @@ public class IterablesTest extends TestCase {
     Iterable<String> tail = skip(set, 1);
     set.remove("b");
     set.addAll(newArrayList("A", "B", "C"));
-    assertThat(tail).iteratesAs("c", "A", "B", "C");
+    assertThat(tail).containsExactly("c", "A", "B", "C").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -611,7 +605,7 @@ public class IterablesTest extends TestCase {
     Iterable<String> tail = skip(list, 1);
     list.subList(1, 3).clear();
     list.addAll(0, newArrayList("A", "B", "C"));
-    assertThat(tail).iteratesAs("B", "C", "a");
+    assertThat(tail).containsExactly("B", "C", "a").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -1042,12 +1036,12 @@ public class IterablesTest extends TestCase {
     assertEquals("Iterables.consumingIterable(...)", consumingIterable.toString());
     Iterator<String> consumingIterator = consumingIterable.iterator();
 
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
 
     assertTrue(consumingIterator.hasNext());
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
     assertEquals("a", consumingIterator.next());
-    assertThat(list).has().item("b");
+    assertThat(list).contains("b");
 
     assertTrue(consumingIterator.hasNext());
     assertEquals("b", consumingIterator.next());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
index 38bb635..a1fd86b 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
@@ -16,6 +16,7 @@
 
 package com.google.common.collect;
 
+import static com.google.common.collect.CollectPreconditions.checkRemove;
 import static com.google.common.collect.Iterators.advance;
 import static com.google.common.collect.Iterators.get;
 import static com.google.common.collect.Iterators.getLast;
@@ -31,7 +32,9 @@ import com.google.common.base.Predicates;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.ConcurrentModificationException;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
@@ -169,8 +172,7 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: <one, two>",
-                   expected.getMessage());
+      assertThat(expected).hasMessage("expected one element but was: <one, two>");
     }
   }
 
@@ -181,9 +183,8 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: "
-                   + "<one, two, three, four, five>",
-                   expected.getMessage());
+      assertThat(expected)
+          .hasMessage("expected one element but was: " + "<one, two, three, four, five>");
     }
   }
 
@@ -194,9 +195,8 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: "
-                   + "<one, two, three, four, five, ...>",
-                   expected.getMessage());
+      assertThat(expected)
+          .hasMessage("expected one element but was: " + "<one, two, three, four, five, ...>");
     }
   }
 
@@ -221,8 +221,7 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator, "x");
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: <foo, bar>",
-                   expected.getMessage());
+      assertThat(expected).hasMessage("expected one element but was: <foo, bar>");
     }
   }
 
@@ -365,22 +364,19 @@ public class IteratorsTest extends TestCase {
   public void testTryFind_firstElement() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("cool",
-        Iterators.tryFind(iterator, Predicates.equalTo("cool")).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.equalTo("cool"))).hasValue("cool");
   }
 
   public void testTryFind_lastElement() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("pants",
-        Iterators.tryFind(iterator, Predicates.equalTo("pants")).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.equalTo("pants"))).hasValue("pants");
   }
 
   public void testTryFind_alwaysTrue() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("cool",
-        Iterators.tryFind(iterator, Predicates.alwaysTrue()).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.alwaysTrue())).hasValue("cool");
   }
 
   public void testTryFind_alwaysFalse_orDefault() {
@@ -394,8 +390,7 @@ public class IteratorsTest extends TestCase {
   public void testTryFind_alwaysFalse_isPresent() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertFalse(
-        Iterators.tryFind(iterator, Predicates.alwaysFalse()).isPresent());
+    assertThat(Iterators.tryFind(iterator, Predicates.alwaysFalse())).isAbsent();
     assertFalse(iterator.hasNext());
   }
 
@@ -562,6 +557,69 @@ public class IteratorsTest extends TestCase {
     assertFalse(cycle.hasNext());
   }
 
+  /** An Iterable whose Iterator is rigorous in checking for concurrent modification. */
+  private static final class PickyIterable<E> implements Iterable<E> {
+    final List<E> elements;
+    int modCount = 0;
+
+    PickyIterable(E... elements) {
+      this.elements = new ArrayList<E>(asList(elements));
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return new PickyIterator();
+    }
+
+    final class PickyIterator implements Iterator<E> {
+      int expectedModCount = modCount;
+      int index = 0;
+      boolean canRemove;
+
+      @Override
+      public boolean hasNext() {
+        checkConcurrentModification();
+        return index < elements.size();
+      }
+
+      @Override
+      public E next() {
+        checkConcurrentModification();
+        if (!hasNext()) {
+          throw new NoSuchElementException();
+        }
+        canRemove = true;
+        return elements.get(index++);
+      }
+
+      @Override
+      public void remove() {
+        checkConcurrentModification();
+        checkRemove(canRemove);
+        elements.remove(--index);
+        expectedModCount = ++modCount;
+        canRemove = false;
+      }
+
+      void checkConcurrentModification() {
+        if (expectedModCount != modCount) {
+          throw new ConcurrentModificationException();
+        }
+      }
+    }
+  }
+
+  public void testCycleRemoveAfterHasNextExtraPicky() {
+    PickyIterable<String> iterable = new PickyIterable("a");
+    Iterator<String> cycle = Iterators.cycle(iterable);
+    assertTrue(cycle.hasNext());
+    assertEquals("a", cycle.next());
+    assertTrue(cycle.hasNext());
+    cycle.remove();
+    assertTrue(iterable.elements.isEmpty());
+    assertFalse(cycle.hasNext());
+  }
+
   public void testCycleNoSuchElementException() {
     Iterable<String> iterable = Lists.newArrayList("a");
     Iterator<String> cycle = Iterators.cycle(iterable);
@@ -613,7 +671,7 @@ public class IteratorsTest extends TestCase {
 
     boolean changed = Iterators.addAll(alreadyThere,
                                        Iterators.<String>emptyIterator());
-    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+    assertThat(alreadyThere).containsExactly("already", "there").inOrder();
     assertFalse(changed);
   }
 
@@ -623,7 +681,7 @@ public class IteratorsTest extends TestCase {
 
     boolean changed = Iterators.addAll(alreadyThere, freshlyAdded.iterator());
 
-    assertThat(alreadyThere).has().exactly("already", "there", "freshly", "added");
+    assertThat(alreadyThere).containsExactly("already", "there", "freshly", "added");
     assertTrue(changed);
   }
 
@@ -633,7 +691,7 @@ public class IteratorsTest extends TestCase {
     List<String> oneMore = Lists.newArrayList("there");
 
     boolean changed = Iterators.addAll(alreadyThere, oneMore.iterator());
-    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+    assertThat(alreadyThere).containsExactly("already", "there").inOrder();
     assertFalse(changed);
   }
 
@@ -1229,12 +1287,12 @@ public class IteratorsTest extends TestCase {
 
     assertEquals("Iterators.consumingIterator(...)", consumingIterator.toString());
 
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
 
     assertTrue(consumingIterator.hasNext());
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
     assertEquals("a", consumingIterator.next());
-    assertThat(list).has().item("b");
+    assertThat(list).contains("b");
 
     assertTrue(consumingIterator.hasNext());
     assertEquals("b", consumingIterator.next());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
index 05d6650..ac4803d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
@@ -88,12 +88,12 @@ public class LinkedHashMultimapTest extends TestCase {
   }
 
   private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
-    assertThat(multimap.get("foo")).has().exactly(5, 3).inOrder();
-    assertThat(multimap.get("bar")).has().exactly(4, 1).inOrder();
-    assertThat(multimap.get("cow")).has().item(2);
+    assertThat(multimap.get("foo")).containsExactly(5, 3).inOrder();
+    assertThat(multimap.get("bar")).containsExactly(4, 1).inOrder();
+    assertThat(multimap.get("cow")).contains(2);
 
-    assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
-    assertThat(multimap.values()).has().exactly(5, 4, 3, 2, 1).inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+    assertThat(multimap.values()).containsExactly(5, 4, 3, 2, 1).inOrder();
 
     Iterator<Map.Entry<String, Integer>> entryIterator =
         multimap.entries().iterator();
@@ -107,28 +107,28 @@ public class LinkedHashMultimapTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = collectionIterator.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(5, 3).inOrder();
+    assertThat(entry.getValue()).containsExactly(5, 3).inOrder();
     entry = collectionIterator.next();
     assertEquals("bar", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(4, 1).inOrder();
+    assertThat(entry.getValue()).containsExactly(4, 1).inOrder();
     entry = collectionIterator.next();
     assertEquals("cow", entry.getKey());
-    assertThat(entry.getValue()).has().item(2);
+    assertThat(entry.getValue()).contains(2);
   }
 
   public void testOrderingUpdates() {
     Multimap<String, Integer> multimap = initializeMultimap5();
 
-    assertThat(multimap.replaceValues("foo", asList(6, 7))).has().exactly(5, 3).inOrder();
-    assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
-    assertThat(multimap.removeAll("foo")).has().exactly(6, 7).inOrder();
-    assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+    assertThat(multimap.replaceValues("foo", asList(6, 7))).containsExactly(5, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+    assertThat(multimap.removeAll("foo")).containsExactly(6, 7).inOrder();
+    assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
     assertTrue(multimap.remove("bar", 4));
-    assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+    assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
     assertTrue(multimap.remove("bar", 1));
-    assertThat(multimap.keySet()).has().item("cow");
+    assertThat(multimap.keySet()).contains("cow");
     multimap.put("bar", 9);
-    assertThat(multimap.keySet()).has().exactly("cow", "bar").inOrder();
+    assertThat(multimap.keySet()).containsExactly("cow", "bar").inOrder();
   }
 
   public void testToStringNullExact() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
index bfab499..a08ffbd 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
@@ -97,14 +97,14 @@ public class LinkedHashMultisetTest extends TestCase {
     ms.add("a");
     ms.add("b", 2);
     ms.add("c");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.remove("b");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.add("b");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.remove("b", 2);
     ms.add("b");
-    assertThat(ms.elementSet()).has().exactly("a", "c", "b").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "c", "b").inOrder();
   }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
index 469b1b6..ea7d041 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
@@ -51,8 +51,8 @@ public class LinkedListMultimapTest extends TestCase {
     Multimap<String, Integer> multimap = create();
     multimap.put("foo", 1);
     multimap.put("foo", 3);
-    assertFalse(multimap.get("foo") instanceof RandomAccess);
-    assertFalse(multimap.get("bar") instanceof RandomAccess);
+    assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+    assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
   }
 
   /**
@@ -89,7 +89,7 @@ public class LinkedListMultimapTest extends TestCase {
     LinkedListMultimap<String, Integer> copy =
         LinkedListMultimap.create(multimap);
     assertEquals(multimap, copy);
-    assertThat(copy.entries()).has().exactlyAs(multimap.entries()).inOrder();
+    assertThat(copy.entries()).containsExactlyElementsIn(multimap.entries()).inOrder();
   }
 
   public void testCreateFromSize() {
@@ -183,7 +183,7 @@ public class LinkedListMultimapTest extends TestCase {
     List<Integer> foos = map.get("foo");
     Collection<Integer> values = map.values();
     assertEquals(asList(1, 2), foos);
-    assertThat(values).has().exactly(1, 2, 3).inOrder();
+    assertThat(values).containsExactly(1, 2, 3).inOrder();
     map.clear();
     assertEquals(Collections.emptyList(), foos);
     assertThat(values).isEmpty();
@@ -210,7 +210,7 @@ public class LinkedListMultimapTest extends TestCase {
     map.put("bar", 4);
     assertEquals("[bar=1, foo=2, bar=3, bar=4]",
         map.entries().toString());
-    assertThat(map.keys()).has().exactly("bar", "foo", "bar", "bar").inOrder();
+    assertThat(map.keys()).containsExactly("bar", "foo", "bar", "bar").inOrder();
     map.keys().remove("bar"); // bar is no longer the first key!
     assertEquals("{foo=[2], bar=[3, 4]}", map.toString());
   }
@@ -256,7 +256,7 @@ public class LinkedListMultimapTest extends TestCase {
         = map.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = entries.next();
     assertEquals("bar", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(1, 3).inOrder();
+    assertThat(entry.getValue()).containsExactly(1, 3).inOrder();
     try {
       entry.setValue(Arrays.<Integer>asList());
       fail("UnsupportedOperationException expected");
@@ -264,7 +264,7 @@ public class LinkedListMultimapTest extends TestCase {
     entries.remove(); // clear
     entry = entries.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().item(2);
+    assertThat(entry.getValue()).contains(2);
     assertFalse(entries.hasNext());
     assertEquals("{foo=[2]}", map.toString());
   }
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
index dcd52d5..d142a37 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
@@ -214,7 +214,7 @@ public class ListsTest extends TestCase {
   }
 
   private void checkFooBarBazList(List<String> list) {
-    assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
     assertEquals(3, list.size());
     assertIndexIsOutOfBounds(list, -1);
     assertEquals("foo", list.get(0));
@@ -225,7 +225,7 @@ public class ListsTest extends TestCase {
 
   public void testAsList1Small() {
     List<String> list = Lists.asList("foo", new String[0]);
-    assertThat(list).has().item("foo");
+    assertThat(list).contains("foo");
     assertEquals(1, list.size());
     assertIndexIsOutOfBounds(list, -1);
     assertEquals("foo", list.get(0));
@@ -308,24 +308,24 @@ public class ListsTest extends TestCase {
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x1() {
-    assertThat(Lists.cartesianProduct(list(1), list(2))).has().item(list(1, 2));
+    assertThat(Lists.cartesianProduct(list(1), list(2))).contains(list(1, 2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x2() {
     assertThat(Lists.cartesianProduct(list(1), list(2, 3)))
-        .has().exactly(list(1, 2), list(1, 3)).inOrder();
+        .containsExactly(list(1, 2), list(1, 3)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary2x2() {
     assertThat(Lists.cartesianProduct(list(1, 2), list(3, 4)))
-        .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+        .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_2x2x2() {
-    assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).has().exactly(
+    assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).containsExactly(
         list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
         list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
   }
@@ -351,7 +351,7 @@ public class ListsTest extends TestCase {
     List<Object> exp4 = list((Object) 2, "4");
 
     assertThat(Lists.<Object>cartesianProduct(x, y))
-        .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+        .containsExactly(exp1, exp2, exp3, exp4).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
@@ -442,7 +442,7 @@ public class ListsTest extends TestCase {
 
   public void testTransformSequential() {
     List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
-    assertFalse(list instanceof RandomAccess);
+    assertThat(list).isNotInstanceOf(RandomAccess.class);
   }
 
   public void testTransformListIteratorRandomAccess() {
@@ -598,9 +598,9 @@ public class ListsTest extends TestCase {
   public void testPartitionRandomAccessFalse() {
     List<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
     List<List<Integer>> partitions = Lists.partition(source, 2);
-    assertFalse(partitions instanceof RandomAccess);
-    assertFalse(partitions.get(0) instanceof RandomAccess);
-    assertFalse(partitions.get(1) instanceof RandomAccess);
+    assertThat(partitions).isNotInstanceOf(RandomAccess.class);
+    assertThat(partitions.get(0)).isNotInstanceOf(RandomAccess.class);
+    assertThat(partitions.get(1)).isNotInstanceOf(RandomAccess.class);
   }
 
   // TODO: use the ListTestSuiteBuilder
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
index 928f809..05263d3 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
@@ -110,10 +110,10 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(map.keySet(), constrained.keySet());
     assertEquals(HashMultiset.create(map.values()),
         HashMultiset.create(constrained.values()));
-    assertFalse(map.values() instanceof Serializable);
+    assertThat(map.values()).isNotInstanceOf(Serializable.class);
     assertEquals(map.toString(), constrained.toString());
     assertEquals(map.hashCode(), constrained.hashCode());
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -161,7 +161,7 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(map.values(), constrained.values());
     assertEquals(map.toString(), constrained.toString());
     assertEquals(map.hashCode(), constrained.hashCode());
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -230,7 +230,7 @@ public class MapConstraintsTest extends TestCase {
     assertTrue(constrained.equals(multimap));
     assertThat(ImmutableList.copyOf(multimap.entries())).isEqualTo(
         ImmutableList.copyOf(constrained.entries()));
-    assertThat(constrained.asMap().get("foo")).has().item(1);
+    assertThat(constrained.asMap().get("foo")).contains(1);
     assertNull(constrained.asMap().get("missing"));
     assertEquals(multimap.asMap(), constrained.asMap());
     assertEquals(multimap.values(), constrained.values());
@@ -238,7 +238,7 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(multimap.keySet(), constrained.keySet());
     assertEquals(multimap.toString(), constrained.toString());
     assertEquals(multimap.hashCode(), constrained.hashCode());
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -251,9 +251,8 @@ public class MapConstraintsTest extends TestCase {
         Maps.immutableEntry("bop", 9),
         Maps.immutableEntry("dig", 10),
         Maps.immutableEntry("dag", 11)).inOrder();
-    assertFalse(constrained.asMap().values() instanceof Serializable);
-    Iterator<Collection<Integer>> iterator =
-        constrained.asMap().values().iterator();
+    assertThat(constrained.asMap().values()).isNotInstanceOf(Serializable.class);
+    Iterator<Collection<Integer>> iterator = constrained.asMap().values().iterator();
     iterator.next();
     iterator.next().add(12);
     assertTrue(multimap.containsEntry("foo", 12));
@@ -538,7 +537,18 @@ public class MapConstraintsTest extends TestCase {
     Collection<Map.Entry<String, Integer>> entries = constrained.entries();
     assertFalse(entries.remove(nefariousEntry));
     assertFalse(multimap.containsValue(TEST_VALUE));
-    assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+    /*
+     * Either the Multimap should reject the nefarious internalEntry.setValue() call that
+     * queryEntry.equals() makes, or it should arrange for internalEntry.equals(queryEntry) to be
+     * used instead of the reverse so that queryEntry.equals(internalEntry) is never invoked.
+     *
+     * Probably the other tests should be similarly tolerant of either outcome. But for now, this is
+     * the only one failing in any of our environments.
+     */
+    try {
+      assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+    } catch (TestValueException tolerated) {
+    }
     assertFalse(multimap.containsValue(TEST_VALUE));
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
index f2b3538..fc8b911 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
@@ -94,7 +94,7 @@ public class MapsTest extends TestCase {
     try {
       Maps.capacity(-1);
       fail("Negative expected size must result in IllegalArgumentException");
-    } catch (IllegalArgumentException ex) {
+    } catch (IllegalArgumentException expected) {
     }
   }
 
@@ -183,9 +183,9 @@ public class MapsTest extends TestCase {
     assertEquals(Collections.emptyMap(), map);
     map.put(new Derived("foo"), 1);
     map.put(new Derived("bar"), 2);
-    assertThat(map.keySet()).has().exactly(
+    assertThat(map.keySet()).containsExactly(
         new Derived("bar"), new Derived("foo")).inOrder();
-    assertThat(map.values()).has().exactly(2, 1).inOrder();
+    assertThat(map.values()).containsExactly(2, 1).inOrder();
     assertNull(map.comparator());
   }
 
@@ -194,9 +194,9 @@ public class MapsTest extends TestCase {
     assertEquals(Collections.emptyMap(), map);
     map.put(new LegacyComparable("foo"), 1);
     map.put(new LegacyComparable("bar"), 2);
-    assertThat(map.keySet()).has().exactly(
+    assertThat(map.keySet()).containsExactly(
         new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
-    assertThat(map.values()).has().exactly(2, 1).inOrder();
+    assertThat(map.values()).containsExactly(2, 1).inOrder();
     assertNull(map.comparator());
   }
 
@@ -460,13 +460,13 @@ public class MapsTest extends TestCase {
     SortedMapDifference<Integer, String> diff1 =
         Maps.difference(left, right);
     assertFalse(diff1.areEqual());
-    assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
         Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
-    assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
-    assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
         Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
         Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
     assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
@@ -475,11 +475,11 @@ public class MapsTest extends TestCase {
     SortedMapDifference<Integer, String> diff2 =
         Maps.difference(right, left);
     assertFalse(diff2.areEqual());
-    assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item(
+    assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly(
+    assertThat(diff2.entriesOnlyOnRight().entrySet()).containsExactly(
         Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
     assertEquals(ImmutableMap.of(
             3, ValueDifferenceImpl.create("f", "c"),
@@ -499,13 +499,13 @@ public class MapsTest extends TestCase {
         Maps.difference(left, right);
     left.put(6, "z");
     assertFalse(diff1.areEqual());
-    assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
         Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
-    assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
-    assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
         Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
         Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
     try {
@@ -562,7 +562,7 @@ public class MapsTest extends TestCase {
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(5), map.get("three"));
     assertNull(map.get("five"));
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -585,7 +585,7 @@ public class MapsTest extends TestCase {
     Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(3), map.remove("two"));
-    assertThat(strings).has().exactly("one", "three").inOrder();
+    assertThat(strings).containsExactly("one", "three").inOrder();
   }
 
   public void testAsMapEmpty() {
@@ -618,14 +618,14 @@ public class MapsTest extends TestCase {
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(5), map.get("three"));
     assertNull(map.get("five"));
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.tailMap("onea").entrySet()).has().exactly(
+    assertThat(map.tailMap("onea").entrySet()).containsExactly(
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+    assertThat(map.subMap("one", "two").entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5)).inOrder();
   }
@@ -651,7 +651,7 @@ public class MapsTest extends TestCase {
     assertEquals(
         ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
         headMap);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("five", 4),
         mapEntry("four", 4),
         mapEntry("three", 5),
@@ -664,7 +664,7 @@ public class MapsTest extends TestCase {
     SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(3), map.remove("two"));
-    assertThat(strings).has().exactly("one", "three").inOrder();
+    assertThat(strings).containsExactly("one", "three").inOrder();
   }
 
   public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
@@ -704,7 +704,7 @@ public class MapsTest extends TestCase {
     Iterable<String> strings = ImmutableList.of("one", "two", "three");
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -714,7 +714,7 @@ public class MapsTest extends TestCase {
     Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -724,7 +724,7 @@ public class MapsTest extends TestCase {
     Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -787,6 +787,7 @@ public class MapsTest extends TestCase {
       Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
       fail();
     } catch (IllegalArgumentException expected) {
+      assertThat(expected.getMessage()).contains("Multimaps.index");
     }
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
index 43b9831..81fe775 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
@@ -28,7 +28,6 @@ import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Predicates;
 import com.google.common.base.Supplier;
-import com.google.common.collect.Maps.EntryTransformer;
 import com.google.common.collect.testing.IteratorTester;
 import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
 
@@ -66,14 +65,6 @@ public class MultimapsTest extends TestCase {
   private static final Comparator<Integer> INT_COMPARATOR =
       Ordering.<Integer>natural().reverse().nullsFirst();
 
-  private static final EntryTransformer<Object, Object, Object> ALWAYS_NULL =
-      new EntryTransformer<Object, Object, Object>() {
-        @Override
-        public Object transformEntry(Object k, Object v1) {
-          return null;
-        }
-      };
-
   @SuppressWarnings("deprecation")
   public void testUnmodifiableListMultimapShortCircuit() {
     ListMultimap<String, Integer> mod = ArrayListMultimap.create();
@@ -125,10 +116,9 @@ public class MultimapsTest extends TestCase {
     ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
     delegate.put("foo", 1);
     delegate.put("foo", 3);
-    ListMultimap<String, Integer> multimap
-        = Multimaps.unmodifiableListMultimap(delegate);
-    assertFalse(multimap.get("foo") instanceof RandomAccess);
-    assertFalse(multimap.get("bar") instanceof RandomAccess);
+    ListMultimap<String, Integer> multimap = Multimaps.unmodifiableListMultimap(delegate);
+    assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+    assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
   }
 
   public void testUnmodifiableMultimapIsView() {
@@ -205,10 +195,10 @@ public class MultimapsTest extends TestCase {
     assertEquals(multimap.hashCode(), unmodifiable.hashCode());
     assertEquals(multimap, unmodifiable);
 
-    assertThat(unmodifiable.asMap().get("bar")).has().exactly(5, -1);
+    assertThat(unmodifiable.asMap().get("bar")).containsExactly(5, -1);
     assertNull(unmodifiable.asMap().get("missing"));
 
-    assertFalse(unmodifiable.entries() instanceof Serializable);
+    assertThat(unmodifiable.entries()).isNotInstanceOf(Serializable.class);
   }
 
   /**
@@ -362,13 +352,11 @@ public class MultimapsTest extends TestCase {
     assertFalse(map.containsKey("bar"));
     assertEquals(map.keySet(), multimapView.keySet());
     assertEquals(map.keySet(), multimapView.keys().elementSet());
-    assertThat(multimapView.keys()).has().item("foo");
-    assertThat(multimapView.values()).has().item(1);
-    assertThat(multimapView.entries()).has().item(
-        Maps.immutableEntry("foo", 1));
-    assertThat(multimapView.asMap().entrySet()).has().item(
-        Maps.immutableEntry(
-            "foo", (Collection<Integer>) Collections.singleton(1)));
+    assertThat(multimapView.keys()).contains("foo");
+    assertThat(multimapView.values()).contains(1);
+    assertThat(multimapView.entries()).contains(Maps.immutableEntry("foo", 1));
+    assertThat(multimapView.asMap().entrySet())
+        .contains(Maps.immutableEntry("foo", (Collection<Integer>) Collections.singleton(1)));
     multimapView.clear();
     assertFalse(multimapView.containsKey("foo"));
     assertFalse(map.containsKey("foo"));
@@ -514,7 +502,7 @@ public class MultimapsTest extends TestCase {
     } catch (IllegalArgumentException expected) {
       // expected
     }
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry(Color.RED, 1),
         Maps.immutableEntry(Color.BLUE, 2));
   }
@@ -539,8 +527,8 @@ public class MultimapsTest extends TestCase {
     Collection<Integer> collection = multimap.get(Color.BLUE);
     assertEquals(collection, collection);
 
-    assertFalse(multimap.keySet() instanceof SortedSet);
-    assertFalse(multimap.asMap() instanceof SortedMap);
+    assertThat(multimap.keySet()).isNotInstanceOf(SortedSet.class);
+    assertThat(multimap.asMap()).isNotInstanceOf(SortedMap.class);
   }
 
   private static class ListSupplier extends
@@ -562,7 +550,7 @@ public class MultimapsTest extends TestCase {
     multimap.putAll(Color.RED, asList(2, 7, 1, 8));
     assertEquals(2, factory.count);
     assertEquals("{BLUE=[3, 1, 4, 1], RED=[2, 7, 1, 8]}", multimap.toString());
-    assertFalse(multimap.get(Color.BLUE) instanceof RandomAccess);
+    assertThat(multimap.get(Color.BLUE)).isNotInstanceOf(RandomAccess.class);
 
     assertTrue(multimap.keySet() instanceof SortedSet);
     assertTrue(multimap.asMap() instanceof SortedMap);
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
index 5394626..6f879f0 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
@@ -44,7 +44,7 @@ public class MultisetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new DerivedComparable("foo"), 2);
     set.add(new DerivedComparable("bar"), 3);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
         new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
   }
@@ -54,7 +54,7 @@ public class MultisetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new LegacyComparable("foo"), 2);
     set.add(new LegacyComparable("bar"), 3);
-    assertThat(set).has().exactly(new LegacyComparable("bar"),
+    assertThat(set).containsExactly(new LegacyComparable("bar"),
         new LegacyComparable("bar"), new LegacyComparable("bar"),
         new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
   }
@@ -64,7 +64,7 @@ public class MultisetsTest extends TestCase {
         = TreeMultiset.create(Collections.reverseOrder());
     multiset.add("bar", 3);
     multiset.add("foo", 2);
-    assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
+    assertThat(multiset).containsExactly("foo", "foo", "bar", "bar", "bar").inOrder();
   }
 
   public void testRetainOccurrencesEmpty() {
@@ -86,7 +86,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> multiset = HashMultiset.create();
     Multiset<String> toRemove =
         HashMultiset.create(Arrays.asList("a", "b", "a"));
-    assertFalse(Multisets.retainOccurrences(multiset, toRemove));
+    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
     assertTrue(multiset.isEmpty());
   }
 
@@ -94,7 +94,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(
         Arrays.asList("a", "b", "b", "c"));
-    assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+    assertThat(Multisets.union(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
   }
 
   public void testUnionEqualMultisets() {
@@ -130,38 +130,38 @@ public class MultisetsTest extends TestCase {
   public void testSum() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
   }
 
   public void testSumEmptyNonempty() {
     Multiset<String> ms1 = HashMultiset.create();
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
   }
 
   public void testSumNonemptyEmpty() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create();
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
   }
 
   public void testDifferenceWithNoRemovedElements() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
-    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
+    assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "b");
   }
 
   public void testDifferenceWithRemovedElement() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
-    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
+    assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "a");
   }
 
   public void testDifferenceWithMoreElementsInSecondMultiset() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
     Multiset<String> diff = Multisets.difference(ms1, ms2);
-    assertThat(diff).has().item("a");
+    assertThat(diff).contains("a");
     assertEquals(0, diff.count("b"));
     assertEquals(1, diff.count("a"));
     assertFalse(diff.contains("b"));
@@ -211,7 +211,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> toRetain =
         HashMultiset.create(Arrays.asList("a", "b", "b"));
     assertTrue(Multisets.retainOccurrences(multiset, toRetain));
-    assertThat(multiset).has().exactly("a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "b").inOrder();
   }
 
   public void testRemoveEmptyOccurrencesMultiset() {
@@ -219,7 +219,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> toRemove = HashMultiset.create();
     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testRemoveOccurrencesMultiset() {
@@ -228,7 +228,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> toRemove =
         HashMultiset.create(Arrays.asList("a", "b", "b"));
     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "c").inOrder();
+    assertThat(multiset).containsExactly("a", "c").inOrder();
   }
 
   public void testRemoveEmptyOccurrencesIterable() {
@@ -236,7 +236,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a"));
     Iterable<String> toRemove = ImmutableList.of();
     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testRemoveOccurrencesMultisetIterable() {
@@ -244,7 +244,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
     List<String> toRemove = Arrays.asList("a", "b", "b");
     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "c").inOrder();
+    assertThat(multiset).containsExactly("a", "c").inOrder();
   }
 
   @SuppressWarnings("deprecation")
@@ -264,11 +264,11 @@ public class MultisetsTest extends TestCase {
     ImmutableMultiset<String> sortedMultiset =
         Multisets.copyHighestCountFirst(multiset);
 
-    assertThat(sortedMultiset.entrySet()).has().exactly(
+    assertThat(sortedMultiset.entrySet()).containsExactly(
         Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
         Multisets.immutableEntry("b", 1)).inOrder();
 
-    assertThat(sortedMultiset).has().exactly(
+    assertThat(sortedMultiset).containsExactly(
         "a",
         "a",
         "a",
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
index b9342da..e6ff97e 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
@@ -36,20 +36,20 @@ public class ObjectArraysTest extends TestCase {
   public void testNewArray_fromArray_Empty() {
     String[] in = new String[0];
     String[] empty = ObjectArrays.newArray(in, 0);
-    assertEquals(0, empty.length);
+    assertThat(empty).isEmpty();
   }
 
   public void testNewArray_fromArray_Nonempty() {
     String[] array = ObjectArrays.newArray(new String[0], 2);
     assertEquals(String[].class, array.getClass());
-    assertEquals(2, array.length);
+    assertThat(array).hasLength(2);
     assertNull(array[0]);
   }
 
   public void testNewArray_fromArray_OfArray() {
     String[][] array = ObjectArrays.newArray(new String[0][0], 1);
     assertEquals(String[][].class, array.getClass());
-    assertEquals(1, array.length);
+    assertThat(array).hasLength(1);
     assertNull(array[0]);
   }
 
@@ -99,32 +99,32 @@ public class ObjectArraysTest extends TestCase {
 
   public void testPrependZeroElements() {
     String[] result = ObjectArrays.concat("foo", new String[] {});
-    assertThat(result).asList().has().item("foo");
+    assertThat(result).asList().contains("foo");
   }
 
   public void testPrependOneElement() {
     String[] result = ObjectArrays.concat("foo", new String[] { "bar" });
-    assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar").inOrder();
   }
 
   public void testPrependTwoElements() {
     String[] result = ObjectArrays.concat("foo", new String[] { "bar", "baz" });
-    assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
   }
 
   public void testAppendZeroElements() {
     String[] result = ObjectArrays.concat(new String[] {}, "foo");
-    assertThat(result).asList().has().item("foo");
+    assertThat(result).asList().contains("foo");
   }
 
   public void testAppendOneElement() {
     String[] result = ObjectArrays.concat(new String[] { "foo" }, "bar");
-    assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar").inOrder();
   }
 
   public void testAppendTwoElements() {
     String[] result = ObjectArrays.concat(new String[] { "foo", "bar" }, "baz");
-    assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
   }
 
   public void testEmptyArrayToEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
index 579842c..17b607d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
@@ -70,6 +70,38 @@ public class OrderingTest extends TestCase {
     assertEquals(strings, comparator.immutableSortedCopy(strings));
   }
 
+  // From https://github.com/google/guava/issues/1342
+  public void testComplicatedOrderingExample() {
+    Integer nullInt = (Integer) null;
+    Ordering<Iterable<Integer>> example =
+        Ordering.<Integer>natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
+    List<Integer> list1 = Lists.newArrayList();
+    List<Integer> list2 = Lists.newArrayList(1);
+    List<Integer> list3 = Lists.newArrayList(1, 1);
+    List<Integer> list4 = Lists.newArrayList(1, 2);
+    List<Integer> list5 = Lists.newArrayList(1, null, 2);
+    List<Integer> list6 = Lists.newArrayList(2);
+    List<Integer> list7 = Lists.newArrayList(nullInt);
+    List<Integer> list8 = Lists.newArrayList(nullInt, nullInt);
+    List<List<Integer>> list =
+        Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);
+    List<List<Integer>> sorted = example.sortedCopy(list);
+
+    // [[null, null], [null], [1, null, 2], [1, 1], [1, 2], [1], [2], [], null]
+    assertThat(sorted)
+        .containsExactly(
+            Lists.newArrayList(nullInt, nullInt),
+            Lists.newArrayList(nullInt),
+            Lists.newArrayList(1, null, 2),
+            Lists.newArrayList(1, 1),
+            Lists.newArrayList(1, 2),
+            Lists.newArrayList(1),
+            Lists.newArrayList(2),
+            Lists.newArrayList(),
+            null)
+        .inOrder();
+  }
+
   public void testNatural() {
     Ordering<Integer> comparator = Ordering.natural();
     Helpers.testComparator(comparator,
@@ -155,7 +187,7 @@ public class OrderingTest extends TestCase {
         = Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
     List<Integer> list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
     Collections.sort(list, c);
-    assertThat(list).has().exactly(8, 6, 7, 5, 3, 0, 9).inOrder();
+    assertThat(list).containsExactly(8, 6, 7, 5, 3, 0, 9).inOrder();
     reserializeAndAssert(c);
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
index 6242ee2..66ab974 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
@@ -91,7 +91,7 @@ public class SetsTest extends TestCase {
   public void testImmutableEnumSet() {
     Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
 
-    assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+    assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
     try {
       units.remove(SomeEnum.B);
       fail("ImmutableEnumSet should throw an exception on remove()");
@@ -109,11 +109,10 @@ public class SetsTest extends TestCase {
 
     ImmutableSet<SomeEnum> one
         = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.B));
-    assertThat(one).has().item(SomeEnum.B);
+    assertThat(one).contains(SomeEnum.B);
 
-    ImmutableSet<SomeEnum> two
-        = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
-    assertThat(two).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+    ImmutableSet<SomeEnum> two = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
+    assertThat(two).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
   }
 
   private static byte[] prepended(byte b, byte[] array) {
@@ -230,7 +229,7 @@ public class SetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new Derived("foo"));
     set.add(new Derived("bar"));
-    assertThat(set).has().exactly(new Derived("bar"), new Derived("foo")).inOrder();
+    assertThat(set).containsExactly(new Derived("bar"), new Derived("foo")).inOrder();
   }
 
   public void testNewTreeSetEmptyNonGeneric() {
@@ -238,8 +237,8 @@ public class SetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new LegacyComparable("foo"));
     set.add(new LegacyComparable("bar"));
-    assertThat(set).has()
-        .exactly(new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
+    assertThat(set).containsExactly(
+        new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
   }
 
   public void testNewTreeSetFromCollection() {
@@ -256,7 +255,7 @@ public class SetsTest extends TestCase {
     Iterable<Derived> iterable =
         Arrays.asList(new Derived("foo"), new Derived("bar"));
     TreeSet<Derived> set = Sets.newTreeSet(iterable);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new Derived("bar"), new Derived("foo")).inOrder();
   }
 
@@ -264,7 +263,7 @@ public class SetsTest extends TestCase {
     Iterable<LegacyComparable> iterable =
         Arrays.asList(new LegacyComparable("foo"), new LegacyComparable("bar"));
     TreeSet<LegacyComparable> set = Sets.newTreeSet(iterable);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
   }
 
@@ -357,7 +356,7 @@ public class SetsTest extends TestCase {
    */
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_zeroary() {
-    assertThat(Sets.cartesianProduct()).has().exactly(list());
+    assertThat(Sets.cartesianProduct()).containsExactly(list());
   }
 
   /**
@@ -366,7 +365,7 @@ public class SetsTest extends TestCase {
    */
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_unary() {
-    assertThat(Sets.cartesianProduct(set(1, 2))).has().exactly(list(1), list(2));
+    assertThat(Sets.cartesianProduct(set(1, 2))).containsExactly(list(1), list(2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
@@ -395,24 +394,24 @@ public class SetsTest extends TestCase {
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x1() {
-    assertThat(Sets.cartesianProduct(set(1), set(2))).has().item(list(1, 2));
+    assertThat(Sets.cartesianProduct(set(1), set(2))).contains(list(1, 2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x2() {
     assertThat(Sets.cartesianProduct(set(1), set(2, 3)))
-        .has().exactly(list(1, 2), list(1, 3)).inOrder();
+        .containsExactly(list(1, 2), list(1, 3)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary2x2() {
     assertThat(Sets.cartesianProduct(set(1, 2), set(3, 4)))
-        .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+        .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_2x2x2() {
-    assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).has().exactly(
+    assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).containsExactly(
         list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
         list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
   }
@@ -438,7 +437,7 @@ public class SetsTest extends TestCase {
     List<Object> exp4 = list((Object) 2, "4");
 
     assertThat(Sets.<Object>cartesianProduct(x, y))
-        .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+        .containsExactly(exp1, exp2, exp3, exp4).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
index c21fdc0..d7f04ec 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
@@ -117,7 +117,7 @@ public class SingletonImmutableTableTest extends AbstractImmutableTableTest {
   }
 
   public void testValues() {
-    assertThat(testTable.values()).has().item("blah");
+    assertThat(testTable.values()).contains("blah");
   }
 
   @Override Iterable<ImmutableTable<Character, Integer, String>> getTestInstances() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
index 7977f8d..fe71a6d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
@@ -117,8 +117,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
     table.put("foo", 12, 'b');
     table.put("bar", 5, 'c');
     table.put("cat", 8, 'd');
-    assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
-    assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+    assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+    assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
   }
 
   public void testCreateCopy() {
@@ -129,8 +129,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
     original.put("bar", 5, 'c');
     original.put("cat", 8, 'd');
     table = TreeBasedTable.create(original);
-    assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
-    assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+    assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+    assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
     assertEquals(original, table);
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
index e0b1ec4..f392586 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
@@ -97,13 +97,13 @@ public class TreeMultimapExplicitTest extends TestCase {
     tree.put("google", 6);
     tree.put("tree", 0);
     tree.put("tree", 3);
-    assertThat(tree.keySet()).has().exactly("tree", "google").inOrder();
-    assertThat(tree.get("google")).has().exactly(6, 2).inOrder();
+    assertThat(tree.keySet()).containsExactly("tree", "google").inOrder();
+    assertThat(tree.get("google")).containsExactly(6, 2).inOrder();
 
     TreeMultimap<String, Integer> copy = TreeMultimap.create(tree);
     assertEquals(tree, copy);
-    assertThat(copy.keySet()).has().exactly("google", "tree").inOrder();
-    assertThat(copy.get("google")).has().exactly(2, 6).inOrder();
+    assertThat(copy.keySet()).containsExactly("google", "tree").inOrder();
+    assertThat(copy.get("google")).containsExactly(2, 6).inOrder();
     assertEquals(Ordering.natural(), copy.keyComparator());
     assertEquals(Ordering.natural(), copy.valueComparator());
     assertEquals(Ordering.natural(), copy.get("google").comparator());
@@ -128,14 +128,14 @@ public class TreeMultimapExplicitTest extends TestCase {
 
   public void testOrderedGet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.get(null)).has().exactly(7, 3, 1).inOrder();
-    assertThat(multimap.get("google")).has().exactly(6, 2).inOrder();
-    assertThat(multimap.get("tree")).has().exactly(null, 0).inOrder();
+    assertThat(multimap.get(null)).containsExactly(7, 3, 1).inOrder();
+    assertThat(multimap.get("google")).containsExactly(6, 2).inOrder();
+    assertThat(multimap.get("tree")).containsExactly(null, 0).inOrder();
   }
 
   public void testOrderedKeySet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.keySet()).has().exactly(null, "tree", "google").inOrder();
+    assertThat(multimap.keySet()).containsExactly(null, "tree", "google").inOrder();
   }
 
   public void testOrderedAsMapEntries() {
@@ -144,18 +144,18 @@ public class TreeMultimapExplicitTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = iterator.next();
     assertEquals(null, entry.getKey());
-    assertThat(entry.getValue()).has().exactly(7, 3, 1);
+    assertThat(entry.getValue()).containsExactly(7, 3, 1);
     entry = iterator.next();
     assertEquals("tree", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(null, 0);
+    assertThat(entry.getValue()).containsExactly(null, 0);
     entry = iterator.next();
     assertEquals("google", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(6, 2);
+    assertThat(entry.getValue()).containsExactly(6, 2);
   }
 
   public void testOrderedEntries() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry((String) null, 7),
         Maps.immutableEntry((String) null, 3),
         Maps.immutableEntry((String) null, 1),
@@ -167,7 +167,7 @@ public class TreeMultimapExplicitTest extends TestCase {
 
   public void testOrderedValues() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
+    assertThat(multimap.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
   }
 
   public void testComparator() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
index 3882958..3f093dc 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
@@ -68,14 +68,14 @@ public class TreeMultimapNaturalTest extends TestCase {
 
   public void testOrderedGet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.get("foo")).has().exactly(1, 3, 7).inOrder();
-    assertThat(multimap.get("google")).has().exactly(2, 6).inOrder();
-    assertThat(multimap.get("tree")).has().exactly(0, 4).inOrder();
+    assertThat(multimap.get("foo")).containsExactly(1, 3, 7).inOrder();
+    assertThat(multimap.get("google")).containsExactly(2, 6).inOrder();
+    assertThat(multimap.get("tree")).containsExactly(0, 4).inOrder();
   }
 
   public void testOrderedKeySet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.keySet()).has().exactly("foo", "google", "tree").inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "google", "tree").inOrder();
   }
 
   public void testOrderedAsMapEntries() {
@@ -84,18 +84,18 @@ public class TreeMultimapNaturalTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = iterator.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(1, 3, 7);
+    assertThat(entry.getValue()).containsExactly(1, 3, 7);
     entry = iterator.next();
     assertEquals("google", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(2, 6);
+    assertThat(entry.getValue()).containsExactly(2, 6);
     entry = iterator.next();
     assertEquals("tree", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(0, 4);
+    assertThat(entry.getValue()).containsExactly(0, 4);
   }
 
   public void testOrderedEntries() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("foo", 3),
         Maps.immutableEntry("foo", 7),
@@ -107,7 +107,7 @@ public class TreeMultimapNaturalTest extends TestCase {
 
   public void testOrderedValues() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.values()).has().exactly(
+    assertThat(multimap.values()).containsExactly(
         1, 3, 7, 2, 6, 0, 4).inOrder();
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
index 65f1a95..8391dc7 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
@@ -83,9 +83,9 @@ public class TreeMultisetTest extends TestCase {
     assertEquals("c", elementSet.last());
     assertEquals(Ordering.natural(), elementSet.comparator());
 
-    assertThat(elementSet.headSet("b")).has().exactly("a").inOrder();
-    assertThat(elementSet.tailSet("b")).has().exactly("b", "c").inOrder();
-    assertThat(elementSet.subSet("a", "c")).has().exactly("a", "b").inOrder();
+    assertThat(elementSet.headSet("b")).containsExactly("a");
+    assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder();
+    assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder();
   }
 
   public void testElementSetSubsetRemove() {
@@ -98,18 +98,18 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.remove("c"));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
 
     assertFalse(subset.remove("a"));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
   }
 
@@ -123,13 +123,13 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.removeAll(Arrays.asList("a", "c")));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
   }
 
@@ -143,13 +143,13 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.retainAll(Arrays.asList("a", "c")));
-    assertThat(elementSet).has().exactly("a", "c", "f").inOrder();
-    assertThat(subset).has().exactly("c").inOrder();
+    assertThat(elementSet).containsExactly("a", "c", "f").inOrder();
+    assertThat(subset).containsExactly("c");
     assertEquals(5, ms.size());
   }
 
@@ -163,12 +163,12 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     subset.clear();
-    assertThat(elementSet).has().exactly("a", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "f").inOrder();
     assertThat(subset).isEmpty();
     assertEquals(3, ms.size());
   }
@@ -188,7 +188,7 @@ public class TreeMultisetTest extends TestCase {
     ms.add("b");
     ms.add("d");
 
-    assertThat(ms).has().exactly("d", "c", "b", "b", "a").inOrder();
+    assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder();
 
     SortedSet<String> elementSet = ms.elementSet();
     assertEquals("d", elementSet.first());
@@ -206,7 +206,7 @@ public class TreeMultisetTest extends TestCase {
     ms.add("b");
     ms.add(null, 2);
 
-    assertThat(ms).has().exactly(null, null, null, "a", "b", "b").inOrder();
+    assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder();
     assertEquals(3, ms.count(null));
 
     SortedSet<String> elementSet = ms.elementSet();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
index 1674ba9..b2b6b4f 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
@@ -107,16 +107,16 @@ public abstract class AbstractMultisetSetCountTester<E>
   // Unconditional setCount no-ops.
 
   private void assertZeroToZero() {
-    assertSetCount(samples.e3, 0);
+    assertSetCount(e3(), 0);
   }
 
   private void assertOneToOne() {
-    assertSetCount(samples.e0, 1);
+    assertSetCount(e0(), 1);
   }
 
   private void assertThreeToThree() {
     initThreeCopies();
-    assertSetCount(samples.e0, 3);
+    assertSetCount(e0(), 3);
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
@@ -183,7 +183,7 @@ public abstract class AbstractMultisetSetCountTester<E>
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_zeroToOne_supported() {
-    assertSetCount(samples.e3, 1);
+    assertSetCount(e3(), 1);
   }
 
   @CollectionFeature.Require({SUPPORTS_ADD,
@@ -191,7 +191,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountZeroToOneConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertSetCount(samples.e3, 1);
+      assertSetCount(e3(), 1);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -204,7 +204,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountZeroToOneConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
-      assertSetCount(samples.e3, 1);
+      assertSetCount(e3(), 1);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -214,29 +214,29 @@ public abstract class AbstractMultisetSetCountTester<E>
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_zeroToThree_supported() {
-    assertSetCount(samples.e3, 3);
+    assertSetCount(e3(), 3);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_oneToThree_supported() {
-    assertSetCount(samples.e0, 3);
+    assertSetCount(e0(), 3);
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_zeroToOne_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 1);
+    assertSetCountIncreasingFailure(e3(), 1);
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_zeroToThree_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 3);
+    assertSetCountIncreasingFailure(e3(), 3);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_oneToThree_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 3);
+    assertSetCountIncreasingFailure(e3(), 3);
   }
 
   // Unconditional setCount size decreases:
@@ -244,7 +244,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_oneToZero_supported() {
-    assertSetCount(samples.e0, 0);
+    assertSetCount(e0(), 0);
   }
 
   @CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -253,7 +253,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountOneToZeroConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertSetCount(samples.e0, 0);
+      assertSetCount(e0(), 0);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -267,7 +267,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountOneToZeroConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
-      assertSetCount(samples.e0, 0);
+      assertSetCount(e0(), 0);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -279,34 +279,34 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_threeToZero_supported() {
     initThreeCopies();
-    assertSetCount(samples.e0, 0);
+    assertSetCount(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_threeToOne_supported() {
     initThreeCopies();
-    assertSetCount(samples.e0, 1);
+    assertSetCount(e0(), 1);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_oneToZero_unsupported() {
-    assertSetCountDecreasingFailure(samples.e0, 0);
+    assertSetCountDecreasingFailure(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_threeToZero_unsupported() {
     initThreeCopies();
-    assertSetCountDecreasingFailure(samples.e0, 0);
+    assertSetCountDecreasingFailure(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_threeToOne_unsupported() {
     initThreeCopies();
-    assertSetCountDecreasingFailure(samples.e0, 1);
+    assertSetCountDecreasingFailure(e0(), 1);
   }
 
   // setCount with nulls:
@@ -365,7 +365,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_negative_removeSupported() {
     try {
-      setCountNoCheckReturnValue(samples.e3, -1);
+      setCountNoCheckReturnValue(e3(), -1);
       fail("calling setCount() with a negative count should throw "
           + "IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
@@ -375,7 +375,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_negative_removeUnsupported() {
     try {
-      setCountNoCheckReturnValue(samples.e3, -1);
+      setCountNoCheckReturnValue(e3(), -1);
       fail("calling setCount() with a negative count should throw "
           + "IllegalArgumentException or UnsupportedOperationException");
     } catch (IllegalArgumentException expected) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
index 7955df5..0f8356a 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
@@ -36,20 +36,20 @@ public class MultisetCountTester<E> extends AbstractMultisetTester<E> {
 
   public void testCount_0() {
     assertEquals("multiset.count(missing) didn't return 0",
-        0, getMultiset().count(samples.e3));
+        0, getMultiset().count(e3()));
   }
 
   @CollectionSize.Require(absent = ZERO)
   public void testCount_1() {
     assertEquals("multiset.count(present) didn't return 1",
-        1, getMultiset().count(samples.e0));
+        1, getMultiset().count(e0()));
   }
 
   @CollectionSize.Require(SEVERAL)
   public void testCount_3() {
     initThreeCopies();
     assertEquals("multiset.count(thriceContained) didn't return 3",
-        3, getMultiset().count(samples.e0));
+        3, getMultiset().count(e0()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_QUERIES)
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
index 9c129ab..fb8cb80 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
@@ -14,11 +14,12 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
+import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
 import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.testing.IteratorFeature;
 import com.google.common.collect.testing.IteratorTester;
 import com.google.common.collect.testing.features.CollectionFeature;
 
@@ -36,12 +37,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require({SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
   public void testRemovingIteratorKnownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, getSubjectGenerator().order(
-        Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+    new IteratorTester<E>(4, MODIFIABLE, getSubjectGenerator().order(
+        Arrays.asList(e0(), e1(), e1(), e2())),
         IteratorTester.KnownOrder.KNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -50,11 +51,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(value = SUPPORTS_ITERATOR_REMOVE, absent = KNOWN_ORDER)
   public void testRemovingIteratorUnknownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, Arrays.asList(samples.e0, samples.e1,
-        samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+    new IteratorTester<E>(4, MODIFIABLE, Arrays.asList(e0(), e1(),
+        e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -63,12 +64,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(value = KNOWN_ORDER, absent = SUPPORTS_ITERATOR_REMOVE)
   public void testIteratorKnownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, getSubjectGenerator().order(
-        Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+    new IteratorTester<E>(4, UNMODIFIABLE, getSubjectGenerator().order(
+        Arrays.asList(e0(), e1(), e1(), e2())),
         IteratorTester.KnownOrder.KNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -77,11 +78,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(absent = {SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
   public void testIteratorUnknownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, Arrays.asList(samples.e0, samples.e1,
-        samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+    new IteratorTester<E>(4, UNMODIFIABLE, Arrays.asList(e0(), e1(),
+        e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
index 46148b9..05ee270 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
@@ -16,12 +16,12 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.testing.Helpers;
@@ -35,32 +35,32 @@ import java.util.List;
 /**
  * Tests for {@code Multiset#remove}, {@code Multiset.removeAll}, and {@code Multiset.retainAll}
  * not already covered by the corresponding Collection testers.
- * 
+ *
  * @author Jared Levy
  */
 @GwtCompatible(emulated = true)
-public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {  
+public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveNegative() {
     try {
-      getMultiset().remove(samples.e0, -1);
+      getMultiset().remove(e0(), -1);
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {}
     expectUnchanged();
   }
-  
+
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testRemoveUnsupported() {
     try {
-      getMultiset().remove(samples.e0, 2);
+      getMultiset().remove(e0(), 2);
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {}
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveZeroNoOp() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertEquals("old count", originalCount, getMultiset().remove(samples.e0, 0));
+    int originalCount = getMultiset().count(e0());
+    assertEquals("old count", originalCount, getMultiset().remove(e0(), 0));
     expectUnchanged();
   }
 
@@ -68,10 +68,10 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_present() {
     assertEquals("multiset.remove(present, 2) didn't return the old count",
-        1, getMultiset().remove(samples.e0, 2));
+        1, getMultiset().remove(e0(), 2));
     assertFalse("multiset contains present after multiset.remove(present, 2)",
-        getMultiset().contains(samples.e0));
-    assertEquals(0, getMultiset().count(samples.e0));
+        getMultiset().contains(e0()));
+    assertEquals(0, getMultiset().count(e0()));
   }
 
   @CollectionSize.Require(SEVERAL)
@@ -79,16 +79,16 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   public void testRemove_some_occurrences_present() {
     initThreeCopies();
     assertEquals("multiset.remove(present, 2) didn't return the old count",
-        3, getMultiset().remove(samples.e0, 2));
+        3, getMultiset().remove(e0(), 2));
     assertTrue("multiset contains present after multiset.remove(present, 2)",
-        getMultiset().contains(samples.e0));
-    assertEquals(1, getMultiset().count(samples.e0));
+        getMultiset().contains(e0()));
+    assertEquals(1, getMultiset().count(e0()));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_absent() {
     assertEquals("multiset.remove(absent, 0) didn't return 0",
-        0, getMultiset().remove(samples.e3, 2));
+        0, getMultiset().remove(e3(), 2));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -97,21 +97,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
     try {
       assertEquals(
           "multiset.remove(absent, 2) didn't return 0 or throw an exception",
-          0, getMultiset().remove(samples.e3, 2));
+          0, getMultiset().remove(e3(), 2));
     } catch (UnsupportedOperationException ok) {}
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_0() {
-    int oldCount = getMultiset().count(samples.e0);
+    int oldCount = getMultiset().count(e0());
     assertEquals("multiset.remove(E, 0) didn't return the old count",
-        oldCount, getMultiset().remove(samples.e0, 0));
+        oldCount, getMultiset().remove(e0(), 0));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_negative() {
     try {
-      getMultiset().remove(samples.e0, -1);
+      getMultiset().remove(e0(), -1);
       fail("multiset.remove(E, -1) didn't throw an exception");
     } catch (IllegalArgumentException required) {}
   }
@@ -121,7 +121,7 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
     assertEquals("multiset.remove(wrongType, 1) didn't return 0",
         0, getMultiset().remove(WrongType.VALUE, 1));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
   public void testRemove_nullPresent() {
@@ -131,12 +131,12 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
         getMultiset().contains(null));
     assertEquals(0, getMultiset().count(null));
   }
-  
+
   @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
   public void testRemove_nullAbsent() {
     assertEquals(0, getMultiset().remove(null, 2));
   }
-  
+
   @CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
   public void testRemove_nullForbidden() {
     try {
@@ -144,21 +144,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {}
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllIgnoresCount() {
     initThreeCopies();
-    assertTrue(getMultiset().removeAll(Collections.singleton(samples.e0)));
-    assertThat(getMultiset()).isEmpty();
+    assertTrue(getMultiset().removeAll(Collections.singleton(e0())));
+    assertEmpty(getMultiset());
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRetainAllIgnoresCount() {
     initThreeCopies();
     List<E> contents = Helpers.copyToList(getMultiset());
-    assertFalse(getMultiset().retainAll(Collections.singleton(samples.e0)));
+    assertFalse(getMultiset().retainAll(Collections.singleton(e0())));
     expectContents(contents);
   }
 }
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
index b4d12b8..2b71e6e 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
@@ -17,7 +17,8 @@
 package com.google.common.collect.testing;
 
 import com.google.gwt.core.client.GwtScriptOnly;
-import com.google.gwt.lang.Array;
+
+import java.util.Arrays;
 
 /**
  * Version of {@link GwtPlatform} used in web-mode.  It includes methods in
@@ -33,6 +34,6 @@ public final class GwtPlatform {
   private GwtPlatform() {}
 
   public static <T> T[] clone(T[] array) {
-    return (T[]) Array.clone(array);
+    return (T[]) Arrays.copyOfRange(array, 0, array.length);
   }
 }
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
index 28f5571..6546131 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
@@ -74,6 +74,49 @@ public class Helpers {
     return Collections.singletonMap(key, value).entrySet().iterator().next();
   }
 
+  private static boolean isEmpty(Iterable<?> iterable) {
+    return iterable instanceof Collection
+        ? ((Collection<?>) iterable).isEmpty()
+        : iterable.iterator().hasNext();
+  }
+
+  public static void assertEmpty(Iterable<?> iterable) {
+    if (!isEmpty(iterable)) {
+      Assert.fail("Not true that " + iterable + " is empty");
+    }
+  }
+
+  public static void assertEmpty(Map<?, ?> map) {
+    if (!map.isEmpty()) {
+      Assert.fail("Not true that " + map + " is empty");
+    }
+  }
+
+  public static void assertEqualInOrder(
+      Iterable<?> expected, Iterable<?> actual) {
+    Iterator<?> expectedIter = expected.iterator();
+    Iterator<?> actualIter = actual.iterator();
+
+    while (expectedIter.hasNext() && actualIter.hasNext()) {
+      if (!equal(expectedIter.next(), actualIter.next())) {
+        Assert.fail(
+            "contents were not equal and in the same order: "
+                + "expected = " + expected + ", actual = " + actual);
+      }
+    }
+
+    if (expectedIter.hasNext() || actualIter.hasNext()) {
+      // actual either had too few or too many elements
+      Assert.fail(
+          "contents were not equal and in the same order: "
+              + "expected = " + expected + ", actual = " + actual);
+    }
+  }
+
+  public static void assertContentsInOrder(Iterable<?> actual, Object... expected) {
+    assertEqualInOrder(Arrays.asList(expected), actual);
+  }
+
   public static void assertEqualIgnoringOrder(
       Iterable<?> expected, Iterable<?> actual) {
     List<?> exp = copyToList(expected);
@@ -98,6 +141,39 @@ public class Helpers {
     assertEqualIgnoringOrder(Arrays.asList(expected), actual);
   }
 
+  public static void assertContains(Iterable<?> actual, Object expected) {
+    boolean contained = false;
+    if (actual instanceof Collection) {
+      contained = ((Collection<?>) actual).contains(expected);
+    } else {
+      for (Object o : actual) {
+        if (equal(o, expected)) {
+          contained = true;
+          break;
+        }
+      }
+    }
+
+    if (!contained) {
+      Assert.fail("Not true that " + actual + " contains " + expected);
+    }
+  }
+
+  public static void assertContainsAllOf(
+      Iterable<?> actual, Object... expected) {
+    List<Object> expectedList = new ArrayList<Object>();
+    expectedList.addAll(Arrays.asList(expected));
+
+    for (Object o : actual) {
+      expectedList.remove(o);
+    }
+
+    if (!expectedList.isEmpty()) {
+      Assert.fail(
+          "Not true that " + actual + " contains all of " + Arrays.asList(expected));
+    }
+  }
+
   public static <E> boolean addAll(
       Collection<E> addTo, Iterable<? extends E> elementsToAdd) {
     boolean modified = false;
@@ -178,11 +254,31 @@ public class Helpers {
     };
   }
 
+  /**
+   * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+   * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+   * the given {@code comparator}.
+   *
+   * @see #testComparator(Comparator, List)
+   */
   public static <T> void testComparator(
       Comparator<? super T> comparator, T... valuesInExpectedOrder) {
     testComparator(comparator, Arrays.asList(valuesInExpectedOrder));
   }
 
+  /**
+   * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+   * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+   * the given {@code comparator}.
+   *
+   * <p>In detail, this method asserts
+   * <ul>
+   * <li><i>reflexivity</i>: {@code comparator.compare(t, t) = 0} for all {@code t} in
+   * {@code valuesInExpectedOrder}; and
+   * <li><i>consistency</i>: {@code comparator.compare(ti, tj) < 0} and
+   * {@code comparator.compare(tj, ti) > 0} for {@code i < j}, where
+   * {@code ti = valuesInExpectedOrder.get(i)} and {@code tj = valuesInExpectedOrder.get(j)}.
+   */
   public static <T> void testComparator(
       Comparator<? super T> comparator, List<T> valuesInExpectedOrder) {
     // This does an O(n^2) test of all pairs of values in both orders
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
index f521cf3..07f5349 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
@@ -65,7 +65,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAll_supportedNonePresent() {
     assertTrue("addAll(nonePresent) should return true",
         collection.addAll(createDisjointCollection()));
-    expectAdded(samples.e3, samples.e4);
+    expectAdded(e3(), e4());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -76,23 +76,23 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3, samples.e4);
+    expectMissing(e3(), e4());
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_supportedSomePresent() {
     assertTrue("addAll(somePresent) should return true",
-        collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
-    assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
-    assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
+        collection.addAll(MinimalCollection.of(e3(), e0())));
+    assertTrue("should contain " + e3(), collection.contains(e3()));
+    assertTrue("should contain " + e0(), collection.contains(e0()));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_unsupportedSomePresent() {
     try {
-      collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
+      collection.addAll(MinimalCollection.of(e3(), e0()));
       fail("addAll(somePresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -105,7 +105,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAllConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
+      assertTrue(collection.addAll(MinimalCollection.of(e3(), e0())));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -118,7 +118,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAll_unsupportedAllPresent() {
     try {
       assertFalse("addAll(allPresent) should return false or throw",
-          collection.addAll(MinimalCollection.of(samples.e0)));
+          collection.addAll(MinimalCollection.of(e0())));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
index dd8c3dd..16ca4bf 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
@@ -44,19 +44,19 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAdd_supportedNotPresent() {
     assertTrue("add(notPresent) should return true",
-        collection.add(samples.e3));
-    expectAdded(samples.e3);
+        collection.add(e3()));
+    expectAdded(e3());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testAdd_unsupportedNotPresent() {
     try {
-      collection.add(samples.e3);
+      collection.add(e3());
       fail("add(notPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -64,7 +64,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   public void testAdd_unsupportedPresent() {
     try {
       assertFalse("add(present) should return false or throw",
-          collection.add(samples.e0));
+          collection.add(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
@@ -97,7 +97,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   public void testAddConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.add(samples.e3));
+      assertTrue(collection.add(e3()));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
index e3dfb67..6b8ac48 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
@@ -118,8 +118,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
 
   public void testToArray_oversizedArray() {
     E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
-    array[getNumElements()] = samples.e3;
-    array[getNumElements() + 1] = samples.e3;
+    array[getNumElements()] = e3();
+    array[getNumElements() + 1] = e3();
     assertSame("toArray(overSizedE[]) should return the given array",
         array, collection.toArray(array));
 
@@ -139,8 +139,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(KNOWN_ORDER)
   public void testToArray_oversizedArray_ordered() {
     E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
-    array[getNumElements()] = samples.e3;
-    array[getNumElements() + 1] = samples.e3;
+    array[getNumElements()] = e3();
+    array[getNumElements() + 1] = e3();
     assertSame("toArray(overSizedE[]) should return the given array",
         array, collection.toArray(array));
 
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
index 75e953f..5371d5e 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
@@ -43,8 +43,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAtIndex_supportedPresent() {
-    getList().add(0, samples.e0);
-    expectAdded(0, samples.e0);
+    getList().add(0, e0());
+    expectAdded(0, e0());
   }
 
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@@ -55,7 +55,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
    */
   public void testAddAtIndex_unsupportedPresent() {
     try {
-      getList().add(0, samples.e0);
+      getList().add(0, e0());
       fail("add(n, present) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -64,8 +64,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_supportedNotPresent() {
-    getList().add(0, samples.e3);
-    expectAdded(0, samples.e3);
+    getList().add(0, e3());
+    expectAdded(0, e3());
   }
 
   @CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
@@ -73,7 +73,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   public void testAddAtIndexConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      getList().add(0, samples.e3);
+      getList().add(0, e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -84,26 +84,26 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_unsupportedNotPresent() {
     try {
-      getList().add(0, samples.e3);
+      getList().add(0, e3());
       fail("add(n, notPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testAddAtIndex_middle() {
-    getList().add(getNumElements() / 2, samples.e3);
-    expectAdded(getNumElements() / 2, samples.e3);
+    getList().add(getNumElements() / 2, e3());
+    expectAdded(getNumElements() / 2, e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAtIndex_end() {
-    getList().add(getNumElements(), samples.e3);
-    expectAdded(getNumElements(), samples.e3);
+    getList().add(getNumElements(), e3());
+    expectAdded(getNumElements(), e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -129,23 +129,23 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_negative() {
     try {
-      getList().add(-1, samples.e3);
+      getList().add(-1, e3());
       fail("add(-1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_tooLarge() {
     try {
-      getList().add(getNumElements() + 1, samples.e3);
+      getList().add(getNumElements() + 1, e3());
       fail("add(size + 1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
index c4c8b2c..51be66d 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
@@ -40,8 +40,8 @@ public class ListAddTester<E> extends AbstractListTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAdd_supportedPresent() {
-    assertTrue("add(present) should return true", getList().add(samples.e0));
-    expectAdded(samples.e0);
+    assertTrue("add(present) should return true", getList().add(e0()));
+    expectAdded(e0());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -52,7 +52,7 @@ public class ListAddTester<E> extends AbstractListTester<E> {
    */
   public void testAdd_unsupportedPresent() {
     try {
-      getList().add(samples.e0);
+      getList().add(e0());
       fail("add(present) should throw");
     } catch (UnsupportedOperationException expected) {
     }
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
index 6c62083..049c320 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
@@ -65,7 +65,7 @@ public class ListListIteratorTester<E> extends AbstractListTester<E> {
 
   private void runListIteratorTest(Set<IteratorFeature> features) {
     new ListIteratorTester<E>(
-        listListIteratorTesterNumIterations(), singleton(samples.e4), features,
+        listListIteratorTesterNumIterations(), singleton(e4()), features,
         Helpers.copyToList(getOrderedElements()), 0) {
       {
         // TODO: don't set this universally
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
index 121d7b0..ccacc53 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
@@ -37,7 +37,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = ZERO)
   public void testSet() {
-    doTestSet(samples.e3);
+    doTestSet(e3());
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -56,7 +56,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
     elements[i] = null;
     collection = getSubjectGenerator().create(elements);
 
-    doTestSet(samples.e3);
+    doTestSet(e3());
   }
 
   private void doTestSet(E newValue) {
@@ -73,7 +73,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_SET)
   public void testSet_indexTooLow() {
     try {
-      getList().set(-1, samples.e3);
+      getList().set(-1, e3());
       fail("set(-1) should throw IndexOutOfBoundsException");
     } catch (IndexOutOfBoundsException expected) {
     }
@@ -84,7 +84,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   public void testSet_indexTooHigh() {
     int index = getNumElements();
     try {
-      getList().set(index, samples.e3);
+      getList().set(index, e3());
       fail("set(size) should throw IndexOutOfBoundsException");
     } catch (IndexOutOfBoundsException expected) {
     }
@@ -95,7 +95,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_SET)
   public void testSet_unsupported() {
     try {
-      getList().set(aValidIndex(), samples.e3);
+      getList().set(aValidIndex(), e3());
       fail("set() should throw UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
     }
@@ -106,7 +106,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_SET)
   public void testSet_unsupportedByEmptyList() {
     try {
-      getList().set(0, samples.e3);
+      getList().set(0, e3());
       fail("set() should throw UnsupportedOperationException "
           + "or IndexOutOfBoundsException");
     } catch (UnsupportedOperationException tolerated) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
index c2fc1b7..52bd42c 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
@@ -109,17 +109,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testSubList_subListAddAffectsOriginal() {
     List<E> subList = getList().subList(0, 0);
-    subList.add(samples.e3);
-    expectAdded(0, samples.e3);
+    subList.add(e3());
+    expectAdded(0, e3());
   }
 
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = ZERO)
   public void testSubList_subListSetAffectsOriginal() {
     List<E> subList = getList().subList(0, 1);
-    subList.set(0, samples.e3);
+    subList.set(0, e3());
     List<E> expected = Helpers.copyToList(createSamplesArray());
-    expected.set(0, samples.e3);
+    expected.set(0, e3());
     expectContents(expected);
   }
 
@@ -127,17 +127,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testSubList_originalListSetAffectsSubList() {
     List<E> subList = getList().subList(0, 1);
-    getList().set(0, samples.e3);
+    getList().set(0, e3());
     assertEquals("A set() call to a list after a sublist has been created "
         + "should be reflected in the sublist",
-        Collections.singletonList(samples.e3), subList);
+        Collections.singletonList(e3()), subList);
   }
 
   @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListRemoveAffectsOriginalLargeList() {
     List<E> subList = getList().subList(1, 3);
-    subList.remove(samples.e2);
+    subList.remove(e2());
     List<E> expected = Helpers.copyToList(createSamplesArray());
     expected.remove(2);
     expectContents(expected);
@@ -147,17 +147,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListAddAtIndexAffectsOriginalLargeList() {
     List<E> subList = getList().subList(2, 3);
-    subList.add(0, samples.e3);
-    expectAdded(2, samples.e3);
+    subList.add(0, e3());
+    expectAdded(2, e3());
   }
 
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListSetAffectsOriginalLargeList() {
     List<E> subList = getList().subList(1, 2);
-    subList.set(0, samples.e3);
+    subList.set(0, e3());
     List<E> expected = Helpers.copyToList(createSamplesArray());
-    expected.set(1, samples.e3);
+    expected.set(1, e3());
     expectContents(expected);
   }
 
@@ -165,10 +165,10 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_originalListSetAffectsSubListLargeList() {
     List<E> subList = getList().subList(1, 3);
-    getList().set(1, samples.e3);
+    getList().set(1, e3());
     assertEquals("A set() call to a list after a sublist has been created "
         + "should be reflected in the sublist",
-        Arrays.asList(samples.e3, samples.e2), subList);
+        Arrays.asList(e3(), e2()), subList);
   }
 
   public void testSubList_ofSubListEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
index 5870e6f..93eec35 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
@@ -127,7 +127,7 @@ public class MapCreationTester<K, V> extends AbstractMapTester<K, V> {
 
   private Entry<K, V>[] getEntriesMultipleNonNullKeys() {
     Entry<K, V>[] entries = createSamplesArray();
-    entries[0] = entry(samples.e1.getKey(), samples.e0.getValue());
+    entries[0] = entry(k1(), v0());
     return entries;
   }
 
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
index 7ece1c7..3357792 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
@@ -53,8 +53,8 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
 
   @Override public void setUp() throws Exception {
     super.setUp();
-    containsNullKey = singletonList(entry(null, samples.e3.getValue()));
-    containsNullValue = singletonList(entry(samples.e3.getKey(), null));
+    containsNullKey = singletonList(entry(null, v3()));
+    containsNullValue = singletonList(entry(k3(), null));
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
@@ -75,7 +75,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAll_supportedNonePresent() {
     putAll(createDisjointCollection());
-    expectAdded(samples.e3, samples.e4);
+    expectAdded(e3(), e4());
   }
 
   @MapFeature.Require(absent = SUPPORTS_PUT)
@@ -86,14 +86,14 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3, samples.e4);
+    expectMissing(e3(), e4());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_supportedSomePresent() {
-    putAll(MinimalCollection.of(samples.e3, samples.e0));
-    expectAdded(samples.e3);
+    putAll(MinimalCollection.of(e3(), e0()));
+    expectAdded(e3());
   }
 
   @MapFeature.Require({ FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -102,7 +102,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAllSomePresentConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
-      putAll(MinimalCollection.of(samples.e3, samples.e0));
+      putAll(MinimalCollection.of(e3(), e0()));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -114,7 +114,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_unsupportedSomePresent() {
     try {
-      putAll(MinimalCollection.of(samples.e3, samples.e0));
+      putAll(MinimalCollection.of(e3(), e0()));
       fail("putAll(somePresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -125,7 +125,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_unsupportedAllPresent() {
     try {
-      putAll(MinimalCollection.of(samples.e0));
+      putAll(MinimalCollection.of(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
index 014bdb2..58f647a 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
@@ -50,16 +50,16 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
 
   @Override public void setUp() throws Exception {
     super.setUp();
-    nullKeyEntry = entry(null, samples.e3.getValue());
-    nullValueEntry = entry(samples.e3.getKey(), null);
+    nullKeyEntry = entry(null, v3());
+    nullValueEntry = entry(k3(), null);
     nullKeyValueEntry = entry(null, null);
-    presentKeyNullValueEntry = entry(samples.e0.getKey(), null);
+    presentKeyNullValueEntry = entry(k0(), null);
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPut_supportedNotPresent() {
-    assertNull("put(notPresent, value) should return null", put(samples.e3));
-    expectAdded(samples.e3);
+    assertNull("put(notPresent, value) should return null", put(e3()));
+    expectAdded(e3());
   }
 
   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
@@ -67,7 +67,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -80,7 +80,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithKeySetIteration() {
     try {
       Iterator<K> iterator = getMap().keySet().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -93,7 +93,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithValueIteration() {
     try {
       Iterator<V> iterator = getMap().values().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -104,12 +104,12 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(absent = SUPPORTS_PUT)
   public void testPut_unsupportedNotPresent() {
     try {
-      put(samples.e3);
+      put(e3());
       fail("put(notPresent, value) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @MapFeature.Require(absent = SUPPORTS_PUT)
@@ -117,7 +117,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPut_unsupportedPresentExistingValue() {
     try {
       assertEquals("put(present, existingValue) should return present or throw",
-          samples.e0.getValue(), put(samples.e0));
+          v0(), put(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
@@ -127,7 +127,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPut_unsupportedPresentDifferentValue() {
     try {
-      getMap().put(samples.e0.getKey(), samples.e3.getValue());
+      getMap().put(k0(), v3());
       fail("put(present, differentValue) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -143,7 +143,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
   @CollectionSize.Require(absent = ZERO)
   public void testPut_nullKeySupportedPresent() {
-    Entry<K, V> newEntry = entry(null, samples.e3.getValue());
+    Entry<K, V> newEntry = entry(null, v3());
     initMapWithNullKey();
     assertEquals("put(present, value) should return the associated value",
         getValueForNullKey(), put(newEntry));
@@ -187,7 +187,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPut_replaceWithNullValueSupported() {
     assertEquals("put(present, null) should return the associated value",
-        samples.e0.getValue(), put(presentKeyNullValueEntry));
+        v0(), put(presentKeyNullValueEntry));
     expectReplacement(presentKeyNullValueEntry);
   }
 
@@ -216,7 +216,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   @CollectionSize.Require(absent = ZERO)
   public void testPut_replaceNullValueWithNonNullSupported() {
-    Entry<K, V> newEntry = entry(getKeyForNullValue(), samples.e3.getValue());
+    Entry<K, V> newEntry = entry(getKeyForNullValue(), v3());
     initMapWithNullValue();
     assertNull("put(present, value) should return the associated value (null)",
         put(newEntry));
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
index ba84654..5e07e1f 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
@@ -36,7 +36,7 @@ public class SetAddTester<E> extends AbstractSetTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAdd_supportedPresent() {
-    assertFalse("add(present) should return false", getSet().add(samples.e0));
+    assertFalse("add(present) should return false", getSet().add(e0()));
     expectUnchanged();
   }
 
diff --git a/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java b/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
index cbfa51f..9374350 100644
--- a/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
+++ b/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
@@ -18,6 +18,7 @@ import static com.google.common.io.BaseEncoding.base16;
 import static com.google.common.io.BaseEncoding.base32;
 import static com.google.common.io.BaseEncoding.base32Hex;
 import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Ascii;
@@ -30,6 +31,8 @@ import junit.framework.TestCase;
 
 import java.io.UnsupportedEncodingException;
 
+import javax.annotation.Nullable;
+
 /**
  * Tests for {@code BaseEncoding}.
  *
@@ -93,12 +96,16 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase64InvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base64(), "\u007f");
-    assertFailsToDecode(base64(), "Wf2!");
+    assertFailsToDecode(base64(), "A\u007f", "Unrecognized character: 0x7f");
+    assertFailsToDecode(base64(), "Wf2!", "Unrecognized character: !");
     // This sentence just isn't base64() encoded.
     assertFailsToDecode(base64(), "let's not talk of love or chains!");
     // A 4n+1 length string is never legal base64().
-    assertFailsToDecode(base64(), "12345");
+    assertFailsToDecode(base64(), "12345", "Invalid input length 5");
+    // These have a combination of invalid length, unrecognized characters and wrong padding.
+    assertFailsToDecode(base64(), "AB=C", "Unrecognized character: =");
+    assertFailsToDecode(base64(), "A=BCD", "Invalid input length 5");
+    assertFailsToDecode(base64(), "?", "Invalid input length 1");
   }
 
   @SuppressWarnings("ReturnValueIgnored")
@@ -143,6 +150,14 @@ public class BaseEncodingTest extends TestCase {
     testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
   }
 
+  public void testBase64Offset() {
+    testEncodesWithOffset(base64(), "foobar", 0, 6, "Zm9vYmFy");
+    testEncodesWithOffset(base64(), "foobar", 1, 5, "b29iYXI=");
+    testEncodesWithOffset(base64(), "foobar", 2, 3, "b2Jh");
+    testEncodesWithOffset(base64(), "foobar", 3, 1, "Yg==");
+    testEncodesWithOffset(base64(), "foobar", 4, 0, "");
+  }
+
   public void testBase32() {
     // The following test vectors are specified in RFC 4648 itself
     testEncodingWithCasing(base32(), "", "");
@@ -176,20 +191,32 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase32InvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base32(), "\u007f");
-    assertFailsToDecode(base32(), "Wf2!");
+    assertFailsToDecode(base32(), "A ", "Unrecognized character: 0x20");
+    assertFailsToDecode(base32(), "Wf2!", "Unrecognized character: f");
     // This sentence just isn't base32() encoded.
     assertFailsToDecode(base32(), "let's not talk of love or chains!");
     // An 8n+{1,3,6} length string is never legal base32.
-    assertFailsToDecode(base32(), "A");
+    assertFailsToDecode(base32(), "A", "Invalid input length 1");
     assertFailsToDecode(base32(), "ABC");
     assertFailsToDecode(base32(), "ABCDEF");
+    // These have a combination of invalid length, unrecognized characters and wrong padding.
+    assertFailsToDecode(base32(), "AB=C", "Unrecognized character: =");
+    assertFailsToDecode(base32(), "A=BCDE", "Invalid input length 6");
+    assertFailsToDecode(base32(), "?", "Invalid input length 1");
   }
 
   public void testBase32UpperCaseIsNoOp() {
     assertSame(base32(), base32().upperCase());
   }
 
+  public void testBase32Offset() {
+    testEncodesWithOffset(base32(), "foobar", 0, 6, "MZXW6YTBOI======");
+    testEncodesWithOffset(base32(), "foobar", 1, 5, "N5XWEYLS");
+    testEncodesWithOffset(base32(), "foobar", 2, 3, "N5RGC===");
+    testEncodesWithOffset(base32(), "foobar", 3, 1, "MI======");
+    testEncodesWithOffset(base32(), "foobar", 4, 0, "");
+  }
+
   public void testBase32Hex() {
     // The following test vectors are specified in RFC 4648 itself
     testEncodingWithCasing(base32Hex(), "", "");
@@ -212,8 +239,8 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase32HexInvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base32Hex(), "\u007f");
-    assertFailsToDecode(base32Hex(), "Wf2!");
+    assertFailsToDecode(base32Hex(), "A\u007f", "Unrecognized character: 0x7f");
+    assertFailsToDecode(base32Hex(), "Wf2!", "Unrecognized character: W");
     // This sentence just isn't base32 encoded.
     assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
     // An 8n+{1,3,6} length string is never legal base32.
@@ -240,6 +267,25 @@ public class BaseEncodingTest extends TestCase {
     assertSame(base16(), base16().upperCase());
   }
 
+  public void testBase16InvalidDecodings() {
+    // These contain bytes not in the decodabet.
+    assertFailsToDecode(base16(), "\n\n", "Unrecognized character: 0xa");
+    assertFailsToDecode(base16(), "EFGH", "Unrecognized character: G");
+    // Valid base16 strings always have an even length.
+    assertFailsToDecode(base16(), "A", "Invalid input length 1");
+    assertFailsToDecode(base16(), "ABC");
+    // These have a combination of invalid length and unrecognized characters.
+    assertFailsToDecode(base16(), "?", "Invalid input length 1");
+  }
+
+  public void testBase16Offset() {
+    testEncodesWithOffset(base16(), "foobar", 0, 6, "666F6F626172");
+    testEncodesWithOffset(base16(), "foobar", 1, 5, "6F6F626172");
+    testEncodesWithOffset(base16(), "foobar", 2, 3, "6F6261");
+    testEncodesWithOffset(base16(), "foobar", 3, 1, "62");
+    testEncodesWithOffset(base16(), "foobar", 4, 0, "");
+  }
+
   private static void testEncodingWithCasing(
       BaseEncoding encoding, String decoded, String encoded) {
     testEncodingWithSeparators(encoding, decoded, encoded);
@@ -266,39 +312,48 @@ public class BaseEncodingTest extends TestCase {
   }
 
   private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
-    assertEquals(encoded, encoding.encode(bytes));
+    assertEquals(encoded, encoding.encode(getBytes(decoded)));
+  }
+
+  private static void testEncodesWithOffset(
+      BaseEncoding encoding, String decoded, int offset, int len, String encoded) {
+    assertEquals(encoded, encoding.encode(getBytes(decoded), offset, len));
   }
 
   private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
-    assertEquals(bytes, encoding.decode(encoded));
+    assertEquals(getBytes(decoded), encoding.decode(encoded));
   }
 
   private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
+    assertFailsToDecode(encoding, cannotDecode, null);
+  }
+
+  private static void assertFailsToDecode(
+      BaseEncoding encoding, String cannotDecode, @Nullable String expectedMessage) {
     try {
       encoding.decode(cannotDecode);
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
-      // success
+      if (expectedMessage != null) {
+        assertThat(expected.getCause()).hasMessage(expectedMessage);
+      }
     }
     try {
       encoding.decodeChecked(cannotDecode);
       fail("Expected DecodingException");
     } catch (DecodingException expected) {
-      // success
+      if (expectedMessage != null) {
+        assertThat(expected).hasMessage(expectedMessage);
+      }
+    }
+  }
+
+  private static byte[] getBytes(String decoded) {
+    try {
+      // GWT does not support String.getBytes(Charset)
+      return decoded.getBytes("UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new AssertionError();
     }
   }
 
diff --git a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
index 8dda0c5..ae4ccf2 100644
--- a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
+++ b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
@@ -109,7 +109,7 @@ public final class InternetDomainNameTest extends TestCase {
   );
 
   private static final ImmutableSet<String> NO_PS = ImmutableSet.of(
-      "www", "foo.google", "x.y.z");
+      "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z");
 
   private static final ImmutableSet<String> NON_PS = ImmutableSet.of(
       "foo.bar.com", "foo.ca", "foo.bar.ca",
diff --git a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
index a6eef7e..571c7f9 100644
--- a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
+++ b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
@@ -26,10 +26,9 @@ import static com.google.common.net.MediaType.ANY_VIDEO_TYPE;
 import static com.google.common.net.MediaType.HTML_UTF_8;
 import static com.google.common.net.MediaType.JPEG;
 import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
+import static com.google.common.truth.Truth.assertThat;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.testing.EqualsTester;
@@ -44,7 +43,6 @@ import java.nio.charset.UnsupportedCharsetException;
  *
  * @author Gregory Kick
  */
- at Beta
 @GwtCompatible(emulated = true)
 public class MediaTypeTest extends TestCase {
 
@@ -273,9 +271,8 @@ public class MediaTypeTest extends TestCase {
   }
 
   public void testGetCharset() {
-    assertEquals(Optional.absent(), MediaType.parse("text/plain").charset());
-    assertEquals(Optional.of(UTF_8),
-        MediaType.parse("text/plain; charset=utf-8").charset());
+    assertThat(MediaType.parse("text/plain").charset()).isAbsent();
+    assertThat(MediaType.parse("text/plain; charset=utf-8").charset()).hasValue(UTF_8);
   }
 
   public void testGetCharset_tooMany() {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
index 0488aa9..2ebd5af 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
@@ -120,6 +120,7 @@ public class BooleansTest extends TestCase {
         Booleans.ensureCapacity(new boolean[] {true}, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Booleans.ensureCapacity(ARRAY_FALSE, -1, 1);
@@ -193,6 +194,7 @@ public class BooleansTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Boolean> list = Arrays.asList(false, true, null);
     try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
index 44de341..56c5872 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
@@ -143,6 +143,7 @@ public class BytesTest extends TestCase {
         Bytes.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Bytes.ensureCapacity(ARRAY1, -1, 1);
@@ -189,6 +190,7 @@ public class BytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Byte> list = Arrays.asList((byte) 0, (byte) 1, null);
     try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
index 18dcf97..84dd2eb 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
@@ -72,6 +72,7 @@ public class CharsTest extends TestCase {
     assertEquals(LEAST, Chars.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private void assertCastFails(long value) {
     try {
       Chars.checkedCast(value);
@@ -165,6 +166,7 @@ public class CharsTest extends TestCase {
         (char) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Chars.max();
@@ -181,6 +183,7 @@ public class CharsTest extends TestCase {
         (char) 5, (char) 3, (char) 0, (char) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Chars.min();
@@ -221,6 +224,7 @@ public class CharsTest extends TestCase {
         Chars.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Chars.ensureCapacity(ARRAY1, -1, 1);
@@ -290,6 +294,7 @@ public class CharsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Character> list = Arrays.asList((char) 0, (char) 1, null);
     try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
index 84717f3..dfa66a4 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
@@ -177,6 +177,7 @@ public class DoublesTest extends TestCase {
     assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Doubles.max();
@@ -198,6 +199,7 @@ public class DoublesTest extends TestCase {
     assertTrue(Double.isNaN(Doubles.max(VALUES)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Doubles.min();
@@ -243,6 +245,7 @@ public class DoublesTest extends TestCase {
         Doubles.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Doubles.ensureCapacity(ARRAY1, -1, 1);
@@ -312,6 +315,7 @@ public class DoublesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Double> list = Arrays.asList((double) 0, (double) 1, null);
     try {
@@ -345,7 +349,7 @@ public class DoublesTest extends TestCase {
     list.set(0, (double) 2);
     assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
     array[1] = (double) 3;
-    assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
+    assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
   }
 
   public void testAsList_toArray_roundTrip() {
@@ -406,6 +410,7 @@ public class DoublesTest extends TestCase {
     assertEquals((Double) 1e-6, converter.convert("1e-6"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Doubles.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
index d136719..d3c884c 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
@@ -174,6 +174,7 @@ public class FloatsTest extends TestCase {
     assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Floats.max();
@@ -195,6 +196,7 @@ public class FloatsTest extends TestCase {
     assertTrue(Float.isNaN(Floats.max(VALUES)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Floats.min();
@@ -240,6 +242,7 @@ public class FloatsTest extends TestCase {
         Floats.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Floats.ensureCapacity(ARRAY1, -1, 1);
@@ -302,6 +305,7 @@ public class FloatsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Float> list = Arrays.asList((float) 0, (float) 1, null);
     try {
@@ -335,7 +339,7 @@ public class FloatsTest extends TestCase {
     list.set(0, (float) 2);
     assertTrue(Arrays.equals(new float[] {(float) 2, (float) 1}, array));
     array[1] = (float) 3;
-    assertThat(list).has().exactly((float) 2, (float) 3).inOrder();
+    assertThat(list).containsExactly((float) 2, (float) 3).inOrder();
   }
 
   public void testAsList_toArray_roundTrip() {
@@ -384,6 +388,7 @@ public class FloatsTest extends TestCase {
     { "", "+-", "+-0", " 5", "32 ", " 55 ", "infinity", "POSITIVE_INFINITY", "0x9A", "0x9A.bE-5",
       ".", ".e5", "NaNd", "InfinityF" };
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Floats.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
index f1e7ed1..36aef0e 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
@@ -73,6 +73,7 @@ public class IntsTest extends TestCase {
     assertEquals(LEAST, Ints.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       Ints.checkedCast(value);
@@ -166,6 +167,7 @@ public class IntsTest extends TestCase {
         (int) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Ints.max();
@@ -182,6 +184,7 @@ public class IntsTest extends TestCase {
         (int) 5, (int) 3, (int) 0, (int) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Ints.min();
@@ -222,6 +225,7 @@ public class IntsTest extends TestCase {
         Ints.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Ints.ensureCapacity(ARRAY1, -1, 1);
@@ -292,6 +296,7 @@ public class IntsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Integer> list = Arrays.asList((int) 0, (int) 1, null);
     try {
@@ -367,6 +372,7 @@ public class IntsTest extends TestCase {
     assertEquals((Integer) 438, converter.convert("0666"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Ints.stringConverter().convert("notanumber");
@@ -424,4 +430,52 @@ public class IntsTest extends TestCase {
   private static void tryParseAndAssertEquals(Integer expected, String value) {
     assertEquals(expected, Ints.tryParse(value));
   }
+
+  public void testTryParse_radix() {
+    for (int radix = Character.MIN_RADIX;
+        radix <= Character.MAX_RADIX; radix++) {
+      radixEncodeParseAndAssertEquals(0, radix);
+      radixEncodeParseAndAssertEquals(8000, radix);
+      radixEncodeParseAndAssertEquals(-8000, radix);
+      radixEncodeParseAndAssertEquals(GREATEST, radix);
+      radixEncodeParseAndAssertEquals(LEAST, radix);
+      assertNull("Radix: " + radix, Ints.tryParse("9999999999999999", radix));
+      assertNull("Radix: " + radix,
+          Ints.tryParse(Long.toString((long) GREATEST + 1, radix), radix));
+      assertNull("Radix: " + radix,
+          Ints.tryParse(Long.toString((long) LEAST - 1, radix), radix));
+    }
+    assertNull("Hex string and dec parm", Ints.tryParse("FFFF", 10));
+    assertEquals("Mixed hex case", 65535, (int) Ints.tryParse("ffFF", 16));
+  }
+
+  /**
+   * Encodes the an integer as a string with given radix, then uses
+   * {@link Ints#tryParse(String, int)} to parse the result. Asserts the result
+   * is the same as what we started with.
+   */
+  private static void radixEncodeParseAndAssertEquals(Integer value,
+      int radix) {
+    assertEquals("Radix: " + radix, value,
+        Ints.tryParse(Integer.toString(value, radix), radix));
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooBig() {
+    try {
+      Ints.tryParse("0", Character.MAX_RADIX + 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooSmall() {
+    try {
+      Ints.tryParse("0", Character.MIN_RADIX - 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
 }
+
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
index c1556cc..863837e 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
@@ -132,6 +132,7 @@ public class LongsTest extends TestCase {
         (long) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Longs.max();
@@ -148,6 +149,7 @@ public class LongsTest extends TestCase {
         (long) 5, (long) 3, (long) 0, (long) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Longs.min();
@@ -203,7 +205,10 @@ public class LongsTest extends TestCase {
         new byte[] {
             (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
             (byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88}));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testFromByteArrayFails() {
     try {
       Longs.fromByteArray(new byte[Longs.BYTES - 1]);
       fail();
@@ -244,6 +249,7 @@ public class LongsTest extends TestCase {
         Longs.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Longs.ensureCapacity(ARRAY1, -1, 1);
@@ -314,6 +320,7 @@ public class LongsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Long> list = Arrays.asList((long) 0, (long) 1, null);
     try {
@@ -444,5 +451,51 @@ public class LongsTest extends TestCase {
   private static void tryParseAndAssertEquals(Long expected, String value) {
     assertEquals(expected, Longs.tryParse(value));
   }
+
+  public void testTryParse_radix() {
+    for (int radix = Character.MIN_RADIX;
+        radix <= Character.MAX_RADIX; radix++) {
+      radixEncodeParseAndAssertEquals((long) 0, radix);
+      radixEncodeParseAndAssertEquals((long) 8000, radix);
+      radixEncodeParseAndAssertEquals((long) -8000, radix);
+      radixEncodeParseAndAssertEquals(MAX_VALUE, radix);
+      radixEncodeParseAndAssertEquals(MIN_VALUE, radix);
+      assertNull("Radix: " + radix, Longs.tryParse("999999999999999999999999", radix));
+      assertNull("Radix: " + radix,
+          Longs.tryParse(BigInteger.valueOf(MAX_VALUE).add(BigInteger.ONE).toString(), radix));
+      assertNull("Radix: " + radix,
+          Longs.tryParse(BigInteger.valueOf(MIN_VALUE).subtract(BigInteger.ONE).toString(), radix));
+    }
+    assertNull("Hex string and dec parm", Longs.tryParse("FFFF", 10));
+    assertEquals("Mixed hex case", 65535, Longs.tryParse("ffFF", 16).longValue());
+  }
+
+  /**
+   * Encodes the long as a string with given radix, then uses
+   * {@link Longs#tryParse(String, int)} to parse the result. Asserts the result
+   * is the same as what we started with.
+   */
+  private static void radixEncodeParseAndAssertEquals(Long value, int radix) {
+    assertEquals("Radix: " + radix, value,
+        Longs.tryParse(Long.toString(value, radix), radix));
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooBig() {
+    try {
+      Longs.tryParse("0", Character.MAX_RADIX + 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooSmall() {
+    try {
+      Longs.tryParse("0", Character.MIN_RADIX - 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
 }
 
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
index 1447f27..958028f 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
@@ -73,6 +73,7 @@ public class ShortsTest extends TestCase {
     assertEquals(LEAST, Shorts.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       Shorts.checkedCast(value);
@@ -174,6 +175,7 @@ public class ShortsTest extends TestCase {
         (short) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Shorts.max();
@@ -190,6 +192,7 @@ public class ShortsTest extends TestCase {
         (short) 5, (short) 3, (short) 0, (short) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Shorts.min();
@@ -230,6 +233,7 @@ public class ShortsTest extends TestCase {
         Shorts.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Shorts.ensureCapacity(ARRAY1, -1, 1);
@@ -300,6 +304,7 @@ public class ShortsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Short> list = Arrays.asList((short) 0, (short) 1, null);
     try {
@@ -375,6 +380,7 @@ public class ShortsTest extends TestCase {
     assertEquals((Short) (short) 438, converter.convert("0666"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Shorts.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
index e753df8..8f2074d 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
@@ -62,6 +62,7 @@ public class SignedBytesTest extends TestCase {
     assertEquals(LEAST, SignedBytes.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       SignedBytes.checkedCast(value);
@@ -91,6 +92,7 @@ public class SignedBytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       SignedBytes.max();
@@ -106,6 +108,7 @@ public class SignedBytesTest extends TestCase {
         (byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       SignedBytes.min();
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
index 6e8035d..6bf836f 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
@@ -42,7 +42,7 @@ public class UnsignedIntsTest extends TestCase {
       0xfffffffdL,
       0xfffffffeL,
       0xffffffffL};
-  
+
   private static final int LEAST = (int) 0L;
   private static final int GREATEST = (int) 0xffffffffL;
 
@@ -61,7 +61,8 @@ public class UnsignedIntsTest extends TestCase {
       }
     }
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       UnsignedInts.max();
@@ -69,7 +70,7 @@ public class UnsignedIntsTest extends TestCase {
     } catch (IllegalArgumentException expected) {
     }
   }
-  
+
   public void testMax() {
     assertEquals(LEAST, UnsignedInts.max(LEAST));
     assertEquals(GREATEST, UnsignedInts.max(GREATEST));
@@ -78,7 +79,8 @@ public class UnsignedIntsTest extends TestCase {
         (int) 0x12345678L, (int) 0x5a4316b8L,
         (int) 0xff1a618bL, (int) 0L));
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       UnsignedInts.min();
@@ -140,27 +142,29 @@ public class UnsignedIntsTest extends TestCase {
   }
 
   public void testParseInt() {
-    try {
-      for (long a : UNSIGNED_INTS) {
-        assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
-      }
-    } catch (NumberFormatException e) {
-      fail(e.getMessage());
+    for (long a : UNSIGNED_INTS) {
+      assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
     }
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseIntFail() {
     try {
       UnsignedInts.parseUnsignedInt(Long.toString(1L << 32));
       fail("Expected NumberFormatException");
     } catch (NumberFormatException expected) {}
   }
 
-  public void testParseIntWithRadix() throws NumberFormatException {
+  public void testParseIntWithRadix() {
     for (long a : UNSIGNED_INTS) {
       for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
         assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a, radix), radix));
       }
     }
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseIntWithRadixLimits() {
     // loops through all legal radix values.
     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
       // tests can successfully parse a number string with this radix.
@@ -177,6 +181,7 @@ public class UnsignedIntsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testParseIntThrowsExceptionForInvalidRadix() {
     // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
     // inclusive.
@@ -207,6 +212,7 @@ public class UnsignedIntsTest extends TestCase {
     assertEquals(0, UnsignedInts.decode("0"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testDecodeIntFails() {
     try {
       // One more than maximum value
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
index 81947d5..4c05236 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
@@ -219,7 +219,7 @@ public class UnsignedLongTest extends TestCase {
     }
   }
 
-  @SuppressWarnings("ReturnValueIgnored")
+  @SuppressWarnings("CheckReturnValue")
   public void testModByZero() {
     for (long a : TEST_LONGS) {
       try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
index 0ecf473..ec7050b 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
@@ -58,6 +58,7 @@ public class UnsignedLongsTest extends TestCase {
     assertTrue(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xff1a618b7f65ea12L) == 0);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       UnsignedLongs.max();
@@ -73,7 +74,8 @@ public class UnsignedLongsTest extends TestCase {
         0x5a4316b8c153ac4dL, 8L, 100L,
         0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L));
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       UnsignedLongs.min();
@@ -133,7 +135,10 @@ public class UnsignedLongsTest extends TestCase {
     assertEquals(0xff1a618b7f65ea12L, UnsignedLongs.parseUnsignedLong("18382112080831834642"));
     assertEquals(0x5a4316b8c153ac4dL, UnsignedLongs.parseUnsignedLong("6504067269626408013"));
     assertEquals(0x6cf78a4b139a4e2aL, UnsignedLongs.parseUnsignedLong("7851896530399809066"));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseLongFails() {
     try {
       // One more than maximum value
       UnsignedLongs.parseUnsignedLong("18446744073709551616");
@@ -152,6 +157,7 @@ public class UnsignedLongsTest extends TestCase {
     assertEquals(0L, UnsignedLongs.decode("0"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testDecodeLongFails() {
     try {
       // One more than maximum value
@@ -182,7 +188,10 @@ public class UnsignedLongsTest extends TestCase {
   public void testParseLongWithRadix() {
     assertEquals(0xffffffffffffffffL, UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16));
     assertEquals(0x1234567890abcdefL, UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseLongWithRadixLimits() {
     BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE);
     // loops through all legal radix values.
     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
@@ -207,6 +216,7 @@ public class UnsignedLongsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testParseLongThrowsExceptionForInvalidRadix() {
     // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive.
     try {
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
similarity index 53%
copy from guava/src/com/google/common/collect/ComputationException.java
copy to guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
index ac80d6a..78afff9 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
@@ -14,25 +14,29 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
 import com.google.common.annotations.GwtCompatible;
 
-import javax.annotation.Nullable;
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
 
 /**
- * Wraps an exception that occurred during a computation.
+ * Unit tests for {@link Callables}.
  *
- * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @author Isaac Shum
  */
- at GwtCompatible
-public class ComputationException extends RuntimeException {
-  /**
-   * Creates a new instance with the given cause.
-   */
-  public ComputationException(@Nullable Throwable cause) {
-    super(cause);
+ at GwtCompatible(emulated = true)
+public class CallablesTest extends TestCase {
+
+  public void testReturning() throws Exception {
+    assertNull(Callables.returning(null).call());
+
+    Object value = new Object();
+    Callable<Object> callable = Callables.returning(value);
+    assertSame(value, callable.call());
+    // Expect the same value on subsequent calls
+    assertSame(value, callable.call());
   }
-  private static final long serialVersionUID = 0;
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
similarity index 80%
copy from guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
copy to guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
index 14e0179..c05813f 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
@@ -16,15 +16,15 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Preconditions;
 
 import junit.framework.TestCase;
 
-import org.mockito.Mockito;
-
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Nullable;
@@ -34,6 +34,7 @@ import javax.annotation.Nullable;
  *
  * @author Anthony Zana
  */
+ at GwtCompatible(emulated = true)
 public class FutureCallbackTest extends TestCase {
   public void testSameThreadSuccess() {
     SettableFuture<String> f = SettableFuture.create();
@@ -65,6 +66,7 @@ public class FutureCallbackTest extends TestCase {
     FutureCallback<String> callback =
         new FutureCallback<String>() {
           private boolean called = false;
+
           @Override
           public void onSuccess(String result) {
             fail("Was not expecting onSuccess() to be called.");
@@ -73,7 +75,7 @@ public class FutureCallbackTest extends TestCase {
           @Override
           public synchronized void onFailure(Throwable t) {
             assertFalse(called);
-            assertTrue(t instanceof CancellationException);
+            assertThat(t).isInstanceOf(CancellationException.class);
             called = true;
           }
         };
@@ -95,40 +97,6 @@ public class FutureCallbackTest extends TestCase {
     Futures.addCallback(f, callback);
   }
 
-  public void testOnSuccessThrowsRuntimeException() throws Exception {
-    RuntimeException exception = new RuntimeException();
-    String result = "result";
-    SettableFuture<String> future = SettableFuture.create();
-    @SuppressWarnings("unchecked") // Safe for a mock
-    FutureCallback<String> callback = Mockito.mock(FutureCallback.class);
-    Futures.addCallback(future, callback);
-    Mockito.doThrow(exception).when(callback).onSuccess(result);
-    future.set(result);
-    assertEquals(result, future.get());
-    Mockito.verify(callback).onSuccess(result);
-    Mockito.verifyNoMoreInteractions(callback);
-  }
-
-  public void testOnSuccessThrowsError() throws Exception {
-    class TestError extends Error {}
-    TestError error = new TestError();
-    String result = "result";
-    SettableFuture<String> future = SettableFuture.create();
-    @SuppressWarnings("unchecked") // Safe for a mock
-    FutureCallback<String> callback = Mockito.mock(FutureCallback.class);
-    Futures.addCallback(future, callback);
-    Mockito.doThrow(error).when(callback).onSuccess(result);
-    try {
-      future.set(result);
-      fail("Should have thrown");
-    } catch (TestError e) {
-      assertSame(error, e);
-    }
-    assertEquals(result, future.get());
-    Mockito.verify(callback).onSuccess(result);
-    Mockito.verifyNoMoreInteractions(callback);
-  }
-
   public void testWildcardFuture() {
     SettableFuture<String> settable = SettableFuture.create();
     ListenableFuture<?> f = settable;
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java
new file mode 100644
index 0000000..1299f58
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java
@@ -0,0 +1,1518 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.allAsList;
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.TestPlatform.clearInterrupt;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.collect.Lists;
+import com.google.common.testing.TestLogHandler;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * Unit tests for {@link Futures}.
+ *
+ * @author Nishant Thakkar
+ */
+ at SuppressWarnings("CheckReturnValue")
+ at GwtCompatible(emulated = true)
+public class FuturesTest extends TestCase {
+  private static final Logger aggregateFutureLogger =
+      Logger.getLogger(AggregateFuture.class.getName());
+  private final TestLogHandler aggregateFutureLogHandler = new TestLogHandler();
+
+  private static final String DATA1 = "data";
+  private static final String DATA2 = "more data";
+  private static final String DATA3 = "most data";
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    aggregateFutureLogger.addHandler(aggregateFutureLogHandler);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    /*
+     * Clear interrupt for future tests.
+     *
+     * (Ideally we would perform interrupts only in threads that we create, but
+     * it's hard to imagine that anything will break in practice.)
+     */
+    clearInterrupt();
+    aggregateFutureLogger.removeHandler(aggregateFutureLogHandler);
+    super.tearDown();
+  }
+
+  public void testImmediateFuture() throws Exception {
+    ListenableFuture<String> future = Futures.immediateFuture(DATA1);
+
+    // Verify that the proper object is returned without waiting
+    assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS));
+  }
+
+  public void testMultipleImmediateFutures() throws Exception {
+    ListenableFuture<String> future1 = Futures.immediateFuture(DATA1);
+    ListenableFuture<String> future2 = Futures.immediateFuture(DATA2);
+
+    // Verify that the proper objects are returned without waiting
+    assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS));
+    assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS));
+  }
+
+  public void testImmediateFailedFuture() throws Exception {
+    Exception exception = new Exception();
+    ListenableFuture<String> future =
+        Futures.immediateFailedFuture(exception);
+
+    try {
+      future.get(0L, TimeUnit.MILLISECONDS);
+      fail("This call was supposed to throw an ExecutionException");
+    } catch (ExecutionException expected) {
+      // This is good and expected
+      assertSame(exception, expected.getCause());
+    }
+  }
+
+  public void testImmediateFailedFuture_cancellationException() throws Exception {
+    CancellationException exception = new CancellationException();
+    ListenableFuture<String> future =
+        Futures.immediateFailedFuture(exception);
+
+    try {
+      future.get(0L, TimeUnit.MILLISECONDS);
+      fail("This call was supposed to throw an ExecutionException");
+    } catch (ExecutionException expected) {
+      // This is good and expected
+      assertSame(exception, expected.getCause());
+      assertFalse(future.isCancelled());
+    }
+  }
+
+  private static class MyException extends Exception {
+
+  }
+
+  // Class hierarchy for generics sanity checks
+  private static class Foo {
+
+  }
+
+  private static class FooChild extends Foo {
+
+  }
+
+  private static class Bar {
+
+  }
+
+  private static class BarChild extends Bar {
+
+  }
+
+  public void testTransform_genericsNull() throws Exception {
+    ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
+    ListenableFuture<?> transformedFuture =
+        Futures.transform(nullFuture, Functions.constant(null));
+    assertNull(transformedFuture.get());
+  }
+
+  public void testTransform_genericsHierarchy() throws Exception {
+    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+    final BarChild barChild = new BarChild();
+    Function<Foo, BarChild> function = new Function<Foo, BarChild>() {
+      @Override
+      public BarChild apply(Foo unused) {
+        return barChild;
+      }
+    };
+    Bar bar = Futures.transform(future, function).get();
+    assertSame(barChild, bar);
+  }
+
+  public void testTransform_cancelPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transform(input, function).cancel(false));
+    assertTrue(input.isCancelled());
+    assertFalse(input.wasInterrupted());
+  }
+
+  public void testTransform_interruptPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transform(input, function).cancel(true));
+    assertTrue(input.isCancelled());
+    assertTrue(input.wasInterrupted());
+  }
+
+  public void testTransform_cancelPropagatesToAsyncOutput() throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transform(immediate, function).cancel(false));
+    assertTrue(secondary.isCancelled());
+    assertFalse(secondary.wasInterrupted());
+  }
+
+  public void testTransform_interruptPropagatesToAsyncOutput()
+      throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transform(immediate, function).cancel(true));
+    assertTrue(secondary.isCancelled());
+    assertTrue(secondary.wasInterrupted());
+  }
+
+  public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transformAsync(input, function).cancel(false));
+    assertTrue(input.isCancelled());
+    assertFalse(input.wasInterrupted());
+  }
+
+  public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transformAsync(input, function).cancel(true));
+    assertTrue(input.isCancelled());
+    assertTrue(input.wasInterrupted());
+  }
+
+  public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transformAsync(immediate, function).cancel(false));
+    assertTrue(secondary.isCancelled());
+    assertFalse(secondary.wasInterrupted());
+  }
+
+  public void testTransformAsync_interruptPropagatesToAsyncOutput()
+      throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transformAsync(immediate, function).cancel(true));
+    assertTrue(secondary.isCancelled());
+    assertTrue(secondary.wasInterrupted());
+  }
+
+  /**
+   * Tests that the function is invoked only once, even if it throws an exception.
+   */
+  public void testTransformValueRemainsMemoized() throws Exception {
+    class Holder {
+
+      int value = 2;
+    }
+    final Holder holder = new Holder();
+
+    // This function adds the holder's value to the input value.
+    Function<Integer, Integer> adder = new Function<Integer, Integer>() {
+      @Override
+      public Integer apply(Integer from) {
+        return from + holder.value;
+      }
+    };
+
+    // Since holder.value is 2, applying 4 should yield 6.
+    assertEquals(6, adder.apply(4).intValue());
+
+    ListenableFuture<Integer> immediateFuture = Futures.immediateFuture(4);
+    Future<Integer> transformedFuture = Futures.transform(immediateFuture, adder);
+
+    // The composed future also yields 6.
+    assertEquals(6, transformedFuture.get().intValue());
+
+    // Repeated calls yield the same value even though the function's behavior
+    // changes
+    holder.value = 3;
+    assertEquals(6, transformedFuture.get().intValue());
+    assertEquals(7, adder.apply(4).intValue());
+
+    // Once more, with feeling.
+    holder.value = 4;
+    assertEquals(6, transformedFuture.get().intValue());
+    assertEquals(8, adder.apply(4).intValue());
+
+    // Memoized get also retains the value.
+    assertEquals(6, transformedFuture.get(1000, TimeUnit.SECONDS).intValue());
+
+    // Unsurprisingly, recomposing the future will return an updated value.
+    assertEquals(8, Futures.transform(immediateFuture, adder).get().intValue());
+
+    // Repeating, with the timeout version
+    assertEquals(8, Futures.transform(immediateFuture, adder).get(
+        1000, TimeUnit.SECONDS).intValue());
+  }
+
+  static class MyError extends Error {
+
+  }
+
+  static class MyRuntimeException extends RuntimeException {
+
+  }
+
+  // TODO(cpovirk): top-level class?
+  static class ExecutorSpy implements Executor {
+
+    Executor delegate;
+    boolean wasExecuted;
+
+    public ExecutorSpy(Executor delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public void execute(Runnable command) {
+      delegate.execute(command);
+      wasExecuted = true;
+    }
+  }
+
+  public void testTransform_Executor() throws Exception {
+    Object value = new Object();
+    ExecutorSpy spy = new ExecutorSpy(directExecutor());
+
+    assertFalse(spy.wasExecuted);
+
+    ListenableFuture<Object> future = Futures.transform(
+        Futures.immediateFuture(value),
+        Functions.identity(), spy);
+
+    assertSame(value, future.get());
+    assertTrue(spy.wasExecuted);
+  }
+
+  private static class FunctionSpy<I, O> implements Function<I, O> {
+    private int applyCount;
+    private final Function<I, O> delegate;
+
+    public FunctionSpy(Function<I, O> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public O apply(I input) {
+      applyCount++;
+      return delegate.apply(input);
+    }
+
+    void verifyCallCount(int expected) {
+      assertThat(applyCount).isEqualTo(expected);
+    }
+  }
+
+  private static <I, O> FunctionSpy<I, O> spy(Function<I, O> delegate) {
+    return new FunctionSpy<I, O>(delegate);
+  }
+
+  private static <X extends Throwable, V> Function<X, V> unexpectedFunction() {
+    return new Function<X, V>() {
+      @Override
+      public V apply(X t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  private static class FutureFallbackSpy<V> implements FutureFallback<V> {
+
+    private int count;
+    private final FutureFallback<V> delegate;
+
+    public FutureFallbackSpy(FutureFallback<V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public final ListenableFuture<V> create(Throwable t) throws Exception {
+      count++;
+      return delegate.create(t);
+    }
+
+    void verifyCallCount(int expected) {
+      assertThat(count).isEqualTo(expected);
+    }
+  }
+
+  private static <V> FutureFallbackSpy<V> spy(FutureFallback<V> delegate) {
+    return new FutureFallbackSpy<V>(delegate);
+  }
+
+  private static <V> FutureFallback<V> unexpectedFallback() {
+    return new FutureFallback<V>() {
+      @Override
+      public ListenableFuture<V> create(Throwable t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  private static class AsyncFunctionSpy<X extends Throwable, V> implements AsyncFunction<X, V> {
+    private int count;
+    private final AsyncFunction<X, V> delegate;
+
+    public AsyncFunctionSpy(AsyncFunction<X, V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public final ListenableFuture<V> apply(X t) throws Exception {
+      count++;
+      return delegate.apply(t);
+    }
+
+    void verifyCallCount(int expected) {
+      assertThat(count).isEqualTo(expected);
+    }
+  }
+
+  private static <X extends Throwable, V> AsyncFunctionSpy<X, V> spy(AsyncFunction<X, V> delegate) {
+    return new AsyncFunctionSpy<X, V>(delegate);
+  }
+
+  private static <X extends Throwable, V> AsyncFunction<X, V> unexpectedAsyncFunction() {
+    return new AsyncFunction<X, V>() {
+      @Override
+      public ListenableFuture<V> apply(X t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  /** Alternative to AssertionError(String, Throwable), which doesn't exist in GWT 2.6.1. */
+  private static AssertionError newAssertionError(String message, Throwable cause) {
+    AssertionError e = new AssertionError(message);
+    e.initCause(cause);
+    return e;
+  }
+
+  public void testWithFallback_inputDoesNotRaiseException() throws Exception {
+    FutureFallback<Integer> fallback = unexpectedFallback();
+    ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+    ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(originalFuture, fallback);
+    assertEquals(7, faultToleranteFuture.get().intValue());
+  }
+
+  public void testWithFallback_inputRaisesException() throws Exception {
+    final RuntimeException raisedException = new RuntimeException();
+    FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return Futures.immediateFuture(20);
+      }
+    });
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(failingFuture, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
+  }
+
+  public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionFallbackTest(expectedException, false);
+  }
+
+  public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionFallbackTest(expectedException, false);
+  }
+
+  public void testWithFallback_fallbackGeneratesError() throws Exception {
+    final Error error = new Error("deliberate");
+    FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        throw error;
+      }
+    };
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+    try {
+      Futures.withFallback(failingFuture, fallback).get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException expected) {
+      assertSame(error, expected.getCause());
+    }
+  }
+
+  public void testWithFallback_fallbackReturnsRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionFallbackTest(expectedException, true);
+  }
+
+  public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionFallbackTest(expectedException, true);
+  }
+
+  private void runExpectedExceptionFallbackTest(
+      final Exception expectedException, final boolean wrapInFuture) throws Exception {
+    FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        if (!wrapInFuture) {
+          throw expectedException;
+        } else {
+          return Futures.immediateFailedFuture(expectedException);
+        }
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+    ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
+    try {
+      faultToleranteFuture.get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException ee) {
+      assertSame(expectedException, ee.getCause());
+    }
+    fallback.verifyCallCount(1);
+  }
+
+  public void testWithFallback_fallbackNotReady() throws Exception {
+    ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+    final SettableFuture<Integer> secondary = SettableFuture.create();
+    FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) {
+        return secondary;
+      }
+    };
+    ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+    secondary.set(1);
+    assertEquals(1, (int) derived.get());
+  }
+
+  public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    FutureFallback<Integer> fallback = unexpectedFallback();
+    ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+    derived.cancel(true);
+    assertTrue(primary.isCancelled());
+    assertTrue(primary.wasInterrupted());
+  }
+
+  public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    FutureFallback<Integer> fallback = unexpectedFallback();
+    ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+    derived.cancel(false);
+    assertTrue(primary.isCancelled());
+    assertFalse(primary.wasInterrupted());
+  }
+
+  public void testWithFallback_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+    ListenableFuture<?> chainedFuture =
+        Futures.withFallback(inputFuture, new FutureFallback<Integer>() {
+          @Override
+          public ListenableFuture<Integer> create(Throwable t) {
+            return null;
+          }
+        });
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("FutureFallback.create returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  // catchingAsync tests cloned from the old withFallback tests:
+
+  public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+    assertEquals(7, faultToleranteFuture.get().intValue());
+  }
+
+  public void testCatchingAsync_inputRaisesException() throws Exception {
+    final RuntimeException raisedException = new RuntimeException();
+    AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return Futures.immediateFuture(20);
+      }
+    });
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingAsyncTest(expectedException, false);
+  }
+
+  public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionCatchingAsyncTest(expectedException, false);
+  }
+
+  public void testCatchingAsync_fallbackGeneratesError() throws Exception {
+    final Error error = new Error("deliberate");
+    AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        throw error;
+      }
+    };
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+    try {
+      Futures.catchingAsync(failingFuture, Throwable.class, fallback).get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException expected) {
+      assertSame(error, expected.getCause());
+    }
+  }
+
+  public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingAsyncTest(expectedException, true);
+  }
+
+  public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionCatchingAsyncTest(expectedException, true);
+  }
+
+  private void runExpectedExceptionCatchingAsyncTest(
+      final Exception expectedException, final boolean wrapInFuture) throws Exception {
+    AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        if (!wrapInFuture) {
+          throw expectedException;
+        } else {
+          return Futures.immediateFailedFuture(expectedException);
+        }
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+    try {
+      faultToleranteFuture.get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException ee) {
+      assertSame(expectedException, ee.getCause());
+    }
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatchingAsync_fallbackNotReady() throws Exception {
+    ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+    final SettableFuture<Integer> secondary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) {
+        return secondary;
+      }
+    };
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    secondary.set(1);
+    assertEquals(1, (int) derived.get());
+  }
+
+  public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    derived.cancel(true);
+    assertTrue(primary.isCancelled());
+    assertTrue(primary.wasInterrupted());
+  }
+
+  public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    derived.cancel(false);
+    assertTrue(primary.isCancelled());
+    assertFalse(primary.wasInterrupted());
+  }
+
+  public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+    ListenableFuture<?> chainedFuture = Futures.catchingAsync(inputFuture, Throwable.class,
+        new AsyncFunction<Throwable, Integer>() {
+          @Override
+          @SuppressWarnings("AsyncFunctionReturnsNull")
+          public ListenableFuture<Integer> apply(Throwable t) {
+            return null;
+          }
+        });
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  // catching tests cloned from the old withFallback tests:
+
+  public void testCatching_inputDoesNotRaiseException() throws Exception {
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catching(originalFuture, Throwable.class, fallback);
+    assertEquals(7, faultToleranteFuture.get().intValue());
+  }
+
+  public void testCatching_inputRaisesException() throws Exception {
+    final RuntimeException raisedException = new RuntimeException();
+    FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        assertThat(t).isSameAs(raisedException);
+        return 20;
+      }
+    });
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(failingFuture, Throwable.class, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingTest(expectedException);
+  }
+
+  /*
+   * catching() uses a plain Function, so there's no
+   * testCatching_fallbackGeneratesCheckedException().
+   */
+
+  public void testCatching_fallbackGeneratesError() throws Exception {
+    final Error error = new Error("deliberate");
+    Function<Throwable, Integer> fallback = new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        throw error;
+      }
+    };
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+    try {
+      Futures.catching(failingFuture, Throwable.class, fallback).get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException expected) {
+      assertSame(error, expected.getCause());
+    }
+  }
+
+  /*
+   * catching() uses a plain Function, so there's no testCatching_fallbackReturnsRuntimeException()
+   * or testCatching_fallbackReturnsCheckedException().
+   */
+
+  private void runExpectedExceptionCatchingTest(final RuntimeException expectedException)
+      throws Exception {
+    FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        throw expectedException;
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catching(failingFuture, Throwable.class, fallback);
+    try {
+      faultToleranteFuture.get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException ee) {
+      assertSame(expectedException, ee.getCause());
+    }
+    fallback.verifyCallCount(1);
+  }
+
+  // catching() uses a plain Function, so there's no testCatching_fallbackNotReady().
+
+  public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+    derived.cancel(true);
+    assertTrue(primary.isCancelled());
+    assertTrue(primary.wasInterrupted());
+  }
+
+  public void testCatching_resultCancelledBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+    derived.cancel(false);
+    assertTrue(primary.isCancelled());
+    assertFalse(primary.wasInterrupted());
+  }
+
+  // catching() uses a plain Function, so there's no testCatching_resultCancelledAfterFallback().
+
+  // catching() uses a plain Function, so there's no testCatching_nullInsteadOfFuture().
+
+  // Some tests of the exceptionType parameter:
+
+  public void testCatching_Throwable() throws Exception {
+    Function<Throwable, Integer> fallback = functionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(originalFuture, Throwable.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  public void testCatchingAsync_Throwable() throws Exception {
+    AsyncFunction<Throwable, Integer> fallback = asyncFunctionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  private <X extends Throwable> Function<X, Integer> functionReturningOne() {
+    return new Function<X, Integer>() {
+      @Override
+      public Integer apply(X t) {
+        return 1;
+      }
+    };
+  }
+
+  private <X extends Throwable> AsyncFunction<X, Integer> asyncFunctionReturningOne() {
+    return new AsyncFunction<X, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(X t) {
+        return immediateFuture(1);
+      }
+    };
+  }
+
+  private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
+      final ListenableFuture<O> output) {
+    return new AsyncFunction<I, O>() {
+      @Override
+      public ListenableFuture<O> apply(I input) {
+        return output;
+      }
+    };
+  }
+
+  public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+    ListenableFuture<?> nullFuture = immediateFuture(null);
+    ListenableFuture<?> chainedFuture =
+        Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
+    assertNull(chainedFuture.get());
+  }
+
+  public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+    final BarChild barChild = new BarChild();
+    AsyncFunction<Foo, BarChild> function =
+        new AsyncFunction<Foo, BarChild>() {
+          @Override
+          public AbstractFuture<BarChild> apply(Foo unused) {
+            AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+            };
+            future.set(barChild);
+            return future;
+          }
+        };
+    Bar bar = Futures.transform(future, function).get();
+    assertSame(barChild, bar);
+  }
+
+  public void testTransform_asyncFunction_error() throws InterruptedException {
+    final Error error = new Error("deliberate");
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) {
+        throw error;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
+    inputFuture.set("value");
+    try {
+      outputFuture.get();
+      fail("should have thrown error");
+    } catch (ExecutionException e) {
+      assertSame(error, e.getCause());
+    }
+  }
+
+  public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<?> inputFuture = immediateFuture("a");
+    ListenableFuture<?> chainedFuture =
+        Futures.transform(inputFuture, constantAsyncFunction(null));
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+    ListenableFuture<?> nullFuture = immediateFuture(null);
+    ListenableFuture<?> chainedFuture =
+        Futures.transformAsync(nullFuture, constantAsyncFunction(nullFuture));
+    assertNull(chainedFuture.get());
+  }
+
+  public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+    final BarChild barChild = new BarChild();
+    AsyncFunction<Foo, BarChild> function =
+        new AsyncFunction<Foo, BarChild>() {
+          @Override
+          public AbstractFuture<BarChild> apply(Foo unused) {
+            AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+            };
+            future.set(barChild);
+            return future;
+          }
+        };
+    Bar bar = Futures.transformAsync(future, function).get();
+    assertSame(barChild, bar);
+  }
+
+  public void testTransformAsync_asyncFunction_error() throws InterruptedException {
+    final Error error = new Error("deliberate");
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) {
+        throw error;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ListenableFuture<Integer> outputFuture = Futures.transformAsync(inputFuture, function);
+    inputFuture.set("value");
+    try {
+      outputFuture.get();
+      fail("should have thrown error");
+    } catch (ExecutionException e) {
+      assertSame(error, e.getCause());
+    }
+  }
+
+  public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<?> inputFuture = immediateFuture("a");
+    ListenableFuture<?> chainedFuture =
+        Futures.transformAsync(inputFuture, constantAsyncFunction(null));
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  public void testDereference_genericsWildcard() throws Exception {
+    ListenableFuture<?> inner = Futures.immediateFuture(null);
+    ListenableFuture<ListenableFuture<?>> outer =
+        Futures.<ListenableFuture<?>>immediateFuture(inner);
+    ListenableFuture<?> dereferenced = Futures.dereference(outer);
+    assertNull(dereferenced.get());
+  }
+
+  public void testDereference_genericsHierarchy() throws Exception {
+    FooChild fooChild = new FooChild();
+    ListenableFuture<FooChild> inner = Futures.immediateFuture(fooChild);
+    ListenableFuture<ListenableFuture<FooChild>> outer = Futures.immediateFuture(inner);
+    ListenableFuture<Foo> dereferenced = Futures.<Foo>dereference(outer);
+    assertSame(fooChild, dereferenced.get());
+  }
+
+  public void testDereference_resultCancelsOuter() throws Exception {
+    ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
+    ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+    dereferenced.cancel(true);
+    assertTrue(outer.isCancelled());
+  }
+
+  public void testDereference_resultCancelsInner() throws Exception {
+    ListenableFuture<Foo> inner = SettableFuture.create();
+    ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
+    ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+    dereferenced.cancel(true);
+    assertTrue(inner.isCancelled());
+  }
+
+  public void testDereference_outerCancelsResult() throws Exception {
+    ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
+    ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+    outer.cancel(true);
+    assertTrue(dereferenced.isCancelled());
+  }
+
+  public void testDereference_innerCancelsResult() throws Exception {
+    ListenableFuture<Foo> inner = SettableFuture.create();
+    ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
+    ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+    inner.cancel(true);
+    assertTrue(dereferenced.isCancelled());
+  }
+
+  /**
+   * Runnable which can be called a single time, and only after {@link #expectCall} is called.
+   */
+  // TODO(cpovirk): top-level class?
+  static class SingleCallListener implements Runnable {
+
+    private boolean expectCall = false;
+    private final CountDownLatch calledCountDown =
+        new CountDownLatch(1);
+
+    @Override
+    public void run() {
+      assertTrue("Listener called before it was expected", expectCall);
+      assertFalse("Listener called more than once", wasCalled());
+      calledCountDown.countDown();
+    }
+
+    public void expectCall() {
+      assertFalse("expectCall is already true", expectCall);
+      expectCall = true;
+    }
+
+    public boolean wasCalled() {
+      return calledCountDown.getCount() == 0;
+    }
+
+    public void waitForCall() throws InterruptedException {
+      assertTrue("expectCall is false", expectCall);
+      calledCountDown.await();
+    }
+  }
+
+  public void testAllAsList() throws Exception {
+    // Create input and output
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    SettableFuture<String> future3 = SettableFuture.create();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2, future3);
+
+    // Attach a listener
+    SingleCallListener listener = new SingleCallListener();
+    compound.addListener(listener, directExecutor());
+
+    // Satisfy each input and check the output
+    assertFalse(compound.isDone());
+    future1.set(DATA1);
+    assertFalse(compound.isDone());
+    future2.set(DATA2);
+    assertFalse(compound.isDone());
+    listener.expectCall();
+    future3.set(DATA3);
+    assertTrue(compound.isDone());
+    assertTrue(listener.wasCalled());
+
+    List<String> results = compound.get();
+    assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
+  }
+
+  public void testAllAsList_emptyArray() throws Exception {
+    SingleCallListener listener = new SingleCallListener();
+    listener.expectCall();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound = Futures.allAsList();
+    compound.addListener(listener, directExecutor());
+    assertTrue(compound.isDone());
+    assertTrue(compound.get().isEmpty());
+    assertTrue(listener.wasCalled());
+  }
+
+  public void testAllAsList_failure() throws Exception {
+    SingleCallListener listener = new SingleCallListener();
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    compound.addListener(listener, directExecutor());
+
+    listener.expectCall();
+    Throwable exception = new Throwable("failed1");
+    future1.setException(exception);
+    assertTrue(compound.isDone());
+    assertTrue(listener.wasCalled());
+    future2.set("result2");
+
+    try {
+      compound.get();
+      fail("Expected exception not thrown");
+    } catch (ExecutionException e) {
+      assertSame(exception, e.getCause());
+    }
+  }
+
+  public void testAllAsList_cancelled() throws Exception {
+    SingleCallListener listener = new SingleCallListener();
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    compound.addListener(listener, directExecutor());
+
+    listener.expectCall();
+    future1.cancel(true);
+    assertTrue(compound.isDone());
+    assertTrue(listener.wasCalled());
+    future2.setException(new Throwable("failed2"));
+
+    try {
+      compound.get();
+      fail("Expected exception not thrown");
+    } catch (CancellationException e) {
+      // Expected
+    }
+  }
+
+  public void testAllAsList_resultCancelled() throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+
+    future2.set(DATA2);
+    assertFalse(compound.isDone());
+    assertTrue(compound.cancel(false));
+    assertTrue(compound.isCancelled());
+    assertTrue(future1.isCancelled());
+    assertFalse(future1.wasInterrupted());
+  }
+
+  public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture()
+      throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    // There was a bug where the event listener for the combined future would
+    // result in the sub-futures being cancelled without being interrupted.
+    ListenableFuture<List<String>> otherCompound =
+        Futures.allAsList(future1, future2);
+
+    assertTrue(compound.cancel(true));
+    assertTrue(future1.isCancelled());
+    assertTrue(future1.wasInterrupted());
+    assertTrue(future2.isCancelled());
+    assertTrue(future2.wasInterrupted());
+    assertTrue(otherCompound.isCancelled());
+  }
+
+  public void testAllAsList_resultCancelled_withSecondaryListFuture()
+      throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    // This next call is "unused," but it is an important part of the test. Don't remove it!
+    Futures.allAsList(future1, future2);
+
+    assertTrue(compound.cancel(false));
+    assertTrue(future1.isCancelled());
+    assertFalse(future1.wasInterrupted());
+    assertTrue(future2.isCancelled());
+    assertFalse(future2.wasInterrupted());
+  }
+
+  public void testAllAsList_resultInterrupted() throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+
+    future2.set(DATA2);
+    assertFalse(compound.isDone());
+    assertTrue(compound.cancel(true));
+    assertTrue(compound.isCancelled());
+    assertTrue(future1.isCancelled());
+    assertTrue(future1.wasInterrupted());
+  }
+
+  /**
+   * Test the case where the futures are fulfilled prior to constructing the ListFuture.  There was
+   * a bug where the loop that connects a Listener to each of the futures would die on the last
+   * loop-check as done() on ListFuture nulled out the variable being looped over (the list of
+   * futures).
+   */
+  public void testAllAsList_doneFutures() throws Exception {
+    // Create input and output
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    SettableFuture<String> future3 = SettableFuture.create();
+
+    // Satisfy each input prior to creating compound and check the output
+    future1.set(DATA1);
+    future2.set(DATA2);
+    future3.set(DATA3);
+
+    @SuppressWarnings("unchecked") // array is never modified
+        ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2, future3);
+
+    // Attach a listener
+    SingleCallListener listener = new SingleCallListener();
+    listener.expectCall();
+    compound.addListener(listener, directExecutor());
+
+    assertTrue(compound.isDone());
+    assertTrue(listener.wasCalled());
+
+    List<String> results = compound.get();
+    assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
+  }
+
+  /**
+   * A single non-error failure is not logged because it is reported via the output future.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_exception() throws Exception {
+    try {
+      Futures.allAsList(immediateFailedFuture(new MyException())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+    }
+  }
+
+  /**
+   * Ensure that errors are always logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_error() throws Exception {
+    try {
+      Futures.allAsList(immediateFailedFuture(new MyError())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyError.class);
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(1); // errors are always logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+    }
+  }
+
+  /**
+   * All as list will log extra exceptions that have already occurred.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+    try {
+      Futures.allAsList(immediateFailedFuture(new MyException()),
+          immediateFailedFuture(new MyException())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(1); // the second failure is logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+    }
+  }
+
+  /**
+   * All as list will log extra exceptions that occur later.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+    SettableFuture<Object> future1 = SettableFuture.create();
+    SettableFuture<Object> future2 = SettableFuture.create();
+    SettableFuture<Object> future3 = SettableFuture.create();
+    ListenableFuture<List<Object>> all = Futures.allAsList(future1, future2, future3);
+
+    future1.setException(new MyException());
+    future2.setException(new MyException());
+    future3.setException(new MyException());
+
+    try {
+      all.get();
+    } catch (ExecutionException e) {
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(2); // failures after the first are logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+      assertThat(logged.get(1).getThrown()).isInstanceOf(MyException.class);
+    }
+  }
+
+  /**
+   * The same exception happening on multiple futures should not be logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_same_exception() throws Exception {
+    try {
+      MyException sameInstance = new MyException();
+      Futures.allAsList(immediateFailedFuture(sameInstance),
+          immediateFailedFuture(sameInstance)).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+    }
+  }
+
+  public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+    final MyException sameInstance = new MyException();
+    SettableFuture<Object> firstFuture = SettableFuture.create();
+    final SettableFuture<Object> secondFuture = SettableFuture.create();
+    ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+    bulkFuture.addListener(new Runnable() {
+      @Override
+      public void run() {
+        /*
+         * firstFuture just completed, but AggregateFuture hasn't yet had time to record the
+         * exception in seenExceptions. When we complete secondFuture with the same exception,
+         * we want for AggregateFuture to still detect that it's been previously seen.
+         */
+        secondFuture.setException(sameInstance);
+      }
+    }, directExecutor());
+    firstFuture.setException(sameInstance);
+
+    try {
+      bulkFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      assertThat(expected.getCause()).isInstanceOf(MyException.class);
+      assertThat(aggregateFutureLogHandler.getStoredLogRecords()).isEmpty();
+    }
+  }
+
+  public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+    final MyException subsequentFailure = new MyException();
+    SettableFuture<Object> firstFuture = SettableFuture.create();
+    final SettableFuture<Object> secondFuture = SettableFuture.create();
+    ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+    bulkFuture.addListener(new Runnable() {
+      @Override
+      public void run() {
+        /*
+         * This is similar to the above test, but this time we're making sure that we recognize that
+         * the output Future is done early not because of an exception but because of a
+         * cancellation.
+         */
+        secondFuture.setException(subsequentFailure);
+      }
+    }, directExecutor());
+    firstFuture.cancel(false);
+
+    try {
+      bulkFuture.get();
+      fail();
+    } catch (CancellationException expected) {
+      assertThat(getOnlyElement(aggregateFutureLogHandler.getStoredLogRecords()).getThrown())
+          .isSameAs(subsequentFailure);
+    }
+  }
+
+  /**
+   * Different exceptions happening on multiple futures with the same cause should not be logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_same_cause() throws Exception {
+    try {
+      MyException exception1 = new MyException();
+      MyException exception2 = new MyException();
+      MyException exception3 = new MyException();
+
+      MyException sameInstance = new MyException();
+      exception1.initCause(sameInstance);
+      exception2.initCause(sameInstance);
+      exception3.initCause(exception2);
+      Futures.allAsList(immediateFailedFuture(exception1),
+          immediateFailedFuture(exception3)).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+    }
+  }
+
+  private static String createCombinedResult(Integer i, Boolean b) {
+    return "-" + i + "-" + b;
+  }
+
+  /*
+   * TODO(cpovirk): maybe pass around TestFuture instances instead of
+   * ListenableFuture instances
+   */
+
+  /**
+   * Non-Error exceptions are never logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testSuccessfulAsList_logging_exception() throws Exception {
+    assertEquals(Lists.newArrayList((Object) null),
+        Futures.successfulAsList(
+            immediateFailedFuture(new MyException())).get());
+    assertEquals("Nothing should be logged", 0,
+        aggregateFutureLogHandler.getStoredLogRecords().size());
+
+    // Not even if there are a bunch of failures.
+    assertEquals(Lists.newArrayList(null, null, null),
+        Futures.successfulAsList(
+            immediateFailedFuture(new MyException()),
+            immediateFailedFuture(new MyException()),
+            immediateFailedFuture(new MyException())).get());
+    assertEquals("Nothing should be logged", 0,
+        aggregateFutureLogHandler.getStoredLogRecords().size());
+  }
+
+  /**
+   * Ensure that errors are always logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testSuccessfulAsList_logging_error() throws Exception {
+    assertEquals(Lists.newArrayList((Object) null),
+        Futures.successfulAsList(
+            immediateFailedFuture(new MyError())).get());
+    List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+    assertThat(logged).hasSize(1); // errors are always logged
+    assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+  }
+
+  // Mostly an example of how it would look like to use a list of mixed types
+
+  static AssertionFailedError failureWithCause(Throwable cause, String message) {
+    AssertionFailedError failure = new AssertionFailedError(message);
+    failure.initCause(cause);
+    return failure;
+  }
+
+  /**
+   * A future that throws a runtime exception from get.
+   */
+  static class BuggyFuture extends AbstractFuture<String> {
+
+    @Override
+    public String get() {
+      throw new RuntimeException();
+    }
+
+    @Override
+    public boolean set(String v) {
+      return super.set(v);
+    }
+  }
+
+  // This test covers a bug where an Error thrown from a callback could cause the TimeoutFuture to
+  // never complete when timing out.  Notably, nothing would get logged since the Error would get
+  // stuck in the ScheduledFuture inside of TimeoutFuture and nothing ever calls get on it.
+
+  // Simulate a timeout that fires before the call the SES.schedule returns but the future is
+  // already completed.
+}
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java
new file mode 100644
index 0000000..54fa63e
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.fail;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Methods factored out so that they can be emulated differently in GWT.
+ */
+ at GwtCompatible(emulated = true)
+final class TestPlatform {
+  static void verifyGetOnPendingFuture(Future<?> future) {
+    try {
+      future.get();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e).hasMessage("Cannot get() on a pending future.");
+    }
+  }
+
+  static void verifyTimedGetOnPendingFuture(Future<?> future) {
+    try {
+      future.get(0, TimeUnit.SECONDS);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalStateException.class);
+      assertThat(e).hasMessage("Cannot get() on a pending future.");
+    }
+  }
+
+  static void verifyThreadWasNotInterrupted() {
+    // There is no thread interruption in GWT, so there's nothing to do.
+  }
+
+  static void clearInterrupt() {
+    // There is no thread interruption in GWT, so there's nothing to do.
+  }
+
+  private TestPlatform() {}
+}
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
new file mode 100644
index 0000000..0510e13
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Callables.returning;
+import static com.google.common.util.concurrent.TestPlatform.verifyThreadWasNotInterrupted;
+
+import com.google.common.annotations.GwtCompatible;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Test case for {@link TrustedListenableFutureTask}.
+ */
+ at GwtCompatible(emulated = true)
+public class TrustedListenableFutureTaskTest extends TestCase {
+
+  public void testSuccessful() throws Exception {
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+    assertFalse(task.isDone());
+    task.run();
+    assertTrue(task.isDone());
+    assertFalse(task.isCancelled());
+    assertEquals(2, task.get().intValue());
+  }
+
+  public void testCancelled() throws Exception {
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+    assertFalse(task.isDone());
+    task.cancel(false);
+    assertTrue(task.isDone());
+    assertTrue(task.isCancelled());
+    assertFalse(task.wasInterrupted());
+    try {
+      task.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
+    verifyThreadWasNotInterrupted();
+  }
+
+  public void testFailed() throws Exception {
+    final Exception e = new Exception();
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+        new Callable<Integer>() {
+          @Override public Integer call() throws Exception {
+            throw e;
+          }
+        });
+    task.run();
+    assertTrue(task.isDone());
+    assertFalse(task.isCancelled());
+    try {
+      task.get();
+      fail();
+    } catch (ExecutionException executionException) {
+      assertEquals(e, executionException.getCause());
+    }
+  }
+}
+
diff --git a/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java b/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
index 8372cbf..af16639 100644
--- a/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
+++ b/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
@@ -28,26 +28,6 @@ public void testCreateUnstarted() throws Exception {
   testCase.testCreateUnstarted();
 }
 
-public void testElapsedMillis() throws Exception {
-  com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
-  testCase.testElapsedMillis();
-}
-
-public void testElapsedMillis_multipleSegments() throws Exception {
-  com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
-  testCase.testElapsedMillis_multipleSegments();
-}
-
-public void testElapsedMillis_notRunning() throws Exception {
-  com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
-  testCase.testElapsedMillis_notRunning();
-}
-
-public void testElapsedMillis_whileRunning() throws Exception {
-  com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
-  testCase.testElapsedMillis_whileRunning();
-}
-
 public void testElapsed_micros() throws Exception {
   com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
   testCase.testElapsed_micros();
diff --git a/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java b/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
index 96c65d4..f844ec5 100644
--- a/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
+++ b/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
@@ -28,6 +28,11 @@ public void testEncodedLength_validStrings() throws Exception {
   testCase.testEncodedLength_validStrings();
 }
 
+public void testEncodedLength_validStrings2() throws Exception {
+  com.google.common.base.Utf8Test testCase = new com.google.common.base.Utf8Test();
+  testCase.testEncodedLength_validStrings2();
+}
+
 public void testIsWellFormed_4BytesSamples() throws Exception {
   com.google.common.base.Utf8Test testCase = new com.google.common.base.Utf8Test();
   testCase.testIsWellFormed_4BytesSamples();
diff --git a/guava-gwt/test/com/google/common/base/testModule.gwt.xml b/guava-gwt/test/com/google/common/base/testModule.gwt.xml
index 6dcc754..afefbb8 100644
--- a/guava-gwt/test/com/google/common/base/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/base/testModule.gwt.xml
@@ -2,10 +2,10 @@
 <module>
   <inherits name="com.google.gwt.user.User"/>
   <inherits name="com.google.gwt.junit.JUnit"/>
+  <inherits name="com.google.common.annotations.Annotations"/>
   <inherits name="com.google.common.base.Base"/>
   <inherits name="com.google.common.collect.Collect"/>
   <inherits name="com.google.common.testing.Testing"/>
-  <inherits name="com.google.common.annotations.Annotations"/>
   <inherits name="com.google.common.truth.Truth"/>
   <entry-point class="com.google.common.base.TestModuleEntryPoint"/>
    
diff --git a/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java b/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
index 9aaf37e..7aa24af 100644
--- a/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
+++ b/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
@@ -107,4 +107,9 @@ public void testTimeToLive_small() throws Exception {
   com.google.common.cache.CacheBuilderTest testCase = new com.google.common.cache.CacheBuilderTest();
   testCase.testTimeToLive_small();
 }
+
+public void testValuesIsNotASet() throws Exception {
+  com.google.common.cache.CacheBuilderTest testCase = new com.google.common.cache.CacheBuilderTest();
+  testCase.testValuesIsNotASet();
+}
 }
diff --git a/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java b/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
index 9582390..795d238 100644
--- a/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
@@ -18,6 +18,11 @@ public class ComparisonChainTest_gwt extends com.google.gwt.junit.client.GWTTest
 @Override public String getModuleName() {
   return "com.google.common.collect.testModule";
 }
+public void testCompareBooleans() throws Exception {
+  com.google.common.collect.ComparisonChainTest testCase = new com.google.common.collect.ComparisonChainTest();
+  testCase.testCompareBooleans();
+}
+
 public void testCompareFalseFirst() throws Exception {
   com.google.common.collect.ComparisonChainTest testCase = new com.google.common.collect.ComparisonChainTest();
   testCase.testCompareFalseFirst();
diff --git a/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java b/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java
new file mode 100644
index 0000000..ad403c8
--- /dev/null
+++ b/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+public class EvictingQueueTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.collect.testModule";
+}
+public void testAddAll() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testAddAll();
+}
+
+public void testCreateWithNegativeSize() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testCreateWithNegativeSize();
+}
+
+public void testCreateWithZeroSize() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testCreateWithZeroSize();
+}
+
+public void testEvictingAfterOne() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testEvictingAfterOne();
+}
+
+public void testEvictingAfterThree() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testEvictingAfterThree();
+}
+
+public void testRemainingCapacity_maxSize0() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testRemainingCapacity_maxSize0();
+}
+
+public void testRemainingCapacity_maxSize1() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testRemainingCapacity_maxSize1();
+}
+
+public void testRemainingCapacity_maxSize3() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testRemainingCapacity_maxSize3();
+}
+
+public void testSerialization() throws Exception {
+  com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+  testCase.testSerialization();
+}
+}
diff --git a/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
index a5b2aba..38ca4f3 100644
--- a/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
@@ -28,6 +28,11 @@ public void testBiMapEntrySetIteratorRemove() throws Exception {
   testCase.testBiMapEntrySetIteratorRemove();
 }
 
+public void testInverseEntrySetValue() throws Exception {
+  com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
+  testCase.testInverseEntrySetValue();
+}
+
 public void testMapConstructor() throws Exception {
   com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
   testCase.testMapConstructor();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
index c215361..edb69b6 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
@@ -78,6 +78,26 @@ public void testBuilderReuse__CreationTests() throws Exception {
   testCase.testBuilderReuse();
 }
 
+public void testBuilder_orderEntriesByValue__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValue();
+}
+
+public void testBuilder_orderEntriesByValueAfterExactSizeBuild__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValueAfterExactSizeBuild();
+}
+
+public void testBuilder_orderEntriesByValue_usedTwiceFails__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValue_usedTwiceFails();
+}
+
+public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+  testCase.testBuilder_withImmutableEntry();
+}
+
 public void testCopyOf__CreationTests() throws Exception {
   com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
   testCase.testCopyOf();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
index 8103049..6f17c67 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
@@ -108,6 +108,21 @@ public void testBuilderReuse__CreationTests() throws Exception {
   testCase.testBuilderReuse();
 }
 
+public void testBuilder_orderEntriesByValue__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValue();
+}
+
+public void testBuilder_orderEntriesByValueAfterExactSizeBuild__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValueAfterExactSizeBuild();
+}
+
+public void testBuilder_orderEntriesByValue_usedTwiceFails__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValue_usedTwiceFails();
+}
+
 public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
   com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
   testCase.testBuilder_withImmutableEntry();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
index 49cbaea..cf99a03 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
@@ -128,6 +128,11 @@ public void testBuilderReverseOrder__CreationTests() throws Exception {
   testCase.testBuilderReverseOrder();
 }
 
+public void testBuilder_orderEntriesByValueFails__CreationTests() throws Exception {
+  com.google.common.collect.ImmutableSortedMapTest.CreationTests testCase = new com.google.common.collect.ImmutableSortedMapTest.CreationTests();
+  testCase.testBuilder_orderEntriesByValueFails();
+}
+
 public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
   com.google.common.collect.ImmutableSortedMapTest.CreationTests testCase = new com.google.common.collect.ImmutableSortedMapTest.CreationTests();
   testCase.testBuilder_withImmutableEntry();
diff --git a/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java b/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
index 9089b3e..725b278 100644
--- a/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
@@ -123,6 +123,11 @@ public void testCycleRemoveAfterHasNext() throws Exception {
   testCase.testCycleRemoveAfterHasNext();
 }
 
+public void testCycleRemoveAfterHasNextExtraPicky() throws Exception {
+  com.google.common.collect.IteratorsTest testCase = new com.google.common.collect.IteratorsTest();
+  testCase.testCycleRemoveAfterHasNextExtraPicky();
+}
+
 public void testCycleRemoveSameElementTwice() throws Exception {
   com.google.common.collect.IteratorsTest testCase = new com.google.common.collect.IteratorsTest();
   testCase.testCycleRemoveSameElementTwice();
diff --git a/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java b/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
index e648992..576fc46 100644
--- a/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
@@ -43,6 +43,11 @@ public void testCombinationsExhaustively_startingFromNatural() throws Exception
   testCase.testCombinationsExhaustively_startingFromNatural();
 }
 
+public void testComplicatedOrderingExample() throws Exception {
+  com.google.common.collect.OrderingTest testCase = new com.google.common.collect.OrderingTest();
+  testCase.testComplicatedOrderingExample();
+}
+
 public void testCompound_instance() throws Exception {
   com.google.common.collect.OrderingTest testCase = new com.google.common.collect.OrderingTest();
   testCase.testCompound_instance();
diff --git a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java b/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
index 90022e9..ef380ef 100644
--- a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
@@ -18,6 +18,36 @@ public class HelpersTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
 @Override public String getModuleName() {
   return "com.google.common.collect.testing.testModule";
 }
+public void testAssertContains() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testAssertContains();
+}
+
+public void testAssertContainsAllOf() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testAssertContainsAllOf();
+}
+
+public void testAssertContentsInOrder() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testAssertContentsInOrder();
+}
+
+public void testAssertEqualInOrder() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testAssertEqualInOrder();
+}
+
+public void testIsEmpty_iterable() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testIsEmpty_iterable();
+}
+
+public void testIsEmpty_map() throws Exception {
+  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+  testCase.testIsEmpty_map();
+}
+
 public void testNullsBeforeB() throws Exception {
   com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
   testCase.testNullsBeforeB();
diff --git a/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml b/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
index 184e212..6c1afa1 100644
--- a/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
+++ b/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
@@ -19,9 +19,9 @@
   <inherits name="com.google.common.annotations.Annotations"/>
    
   <inherits name="com.google.common.testing.Testing"/>
-     
-  <inherits name="com.google.common.truth.Truth"/>
    
+  <inherits name="java.lang.Lang"/>
+    
   <inherits name="com.google.gwt.core.Core"/>
    
 </module>
diff --git a/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml b/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
index 6f4c380..304b05a 100644
--- a/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
+++ b/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
@@ -28,6 +28,5 @@
 <inherits name="com.google.common.collect.testing.Testing"/>
 <inherits name="com.google.common.primitives.Primitives"/>
 <inherits name="com.google.common.testing.Testing"/>
-<inherits name="com.google.common.truth.Truth"/>
 <inherits name="com.google.gwt.core.Core"/>
 </module>
diff --git a/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java b/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
index c8f61ae..37deb9d 100644
--- a/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
+++ b/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
@@ -28,6 +28,16 @@ public void testBase16() throws Exception {
   testCase.testBase16();
 }
 
+public void testBase16InvalidDecodings() throws Exception {
+  com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+  testCase.testBase16InvalidDecodings();
+}
+
+public void testBase16Offset() throws Exception {
+  com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+  testCase.testBase16Offset();
+}
+
 public void testBase16UpperCaseIsNoOp() throws Exception {
   com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
   testCase.testBase16UpperCaseIsNoOp();
@@ -73,6 +83,11 @@ public void testBase32LenientPadding() throws Exception {
   testCase.testBase32LenientPadding();
 }
 
+public void testBase32Offset() throws Exception {
+  com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+  testCase.testBase32Offset();
+}
+
 public void testBase32UpperCaseIsNoOp() throws Exception {
   com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
   testCase.testBase32UpperCaseIsNoOp();
@@ -108,6 +123,11 @@ public void testBase64LenientPadding() throws Exception {
   testCase.testBase64LenientPadding();
 }
 
+public void testBase64Offset() throws Exception {
+  com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+  testCase.testBase64Offset();
+}
+
 public void testBase64OmitPadding() throws Exception {
   com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
   testCase.testBase64OmitPadding();
diff --git a/guava-gwt/test/com/google/common/io/testModule.gwt.xml b/guava-gwt/test/com/google/common/io/testModule.gwt.xml
index 088e68d..9af7456 100644
--- a/guava-gwt/test/com/google/common/io/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/io/testModule.gwt.xml
@@ -7,6 +7,7 @@
   <inherits name="com.google.common.collect.Collect"/>
   <inherits name="com.google.common.io.Io"/>
   <inherits name="com.google.common.math.Math"/>
+  <inherits name="com.google.common.truth.Truth"/>
   <entry-point class="com.google.common.io.TestModuleEntryPoint"/>
    
   <source path=""/>
diff --git a/guava-gwt/test/com/google/common/math/testModule.gwt.xml b/guava-gwt/test/com/google/common/math/testModule.gwt.xml
index 91255e3..afbc79c 100644
--- a/guava-gwt/test/com/google/common/math/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/math/testModule.gwt.xml
@@ -11,7 +11,7 @@
   <entry-point class="com.google.common.math.TestModuleEntryPoint"/>
    
   <source path=""/>
-    
+   
   <super-source path="super"/>
    
 </module>
diff --git a/guava-gwt/test/com/google/common/net/testModule.gwt.xml b/guava-gwt/test/com/google/common/net/testModule.gwt.xml
index bc826a6..5e49aa2 100644
--- a/guava-gwt/test/com/google/common/net/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/net/testModule.gwt.xml
@@ -13,7 +13,7 @@
   <entry-point class="com.google.common.net.TestModuleEntryPoint"/>
    
   <source path=""/>
-    
+   
   <super-source path="super"/>
    
 </module>
diff --git a/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
index 7021487..25b1e28 100644
--- a/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
@@ -167,4 +167,19 @@ public void testTryParse() throws Exception {
   com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
   testCase.testTryParse();
 }
+
+public void testTryParse_radix() throws Exception {
+  com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+  testCase.testTryParse_radix();
+}
+
+public void testTryParse_radixTooBig() throws Exception {
+  com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+  testCase.testTryParse_radixTooBig();
+}
+
+public void testTryParse_radixTooSmall() throws Exception {
+  com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+  testCase.testTryParse_radixTooSmall();
+}
 }
diff --git a/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
index b865b9e..928cead 100644
--- a/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
@@ -73,6 +73,11 @@ public void testFromByteArray() throws Exception {
   testCase.testFromByteArray();
 }
 
+public void testFromByteArrayFails() throws Exception {
+  com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+  testCase.testFromByteArrayFails();
+}
+
 public void testFromBytes() throws Exception {
   com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
   testCase.testFromBytes();
@@ -172,4 +177,19 @@ public void testTryParse() throws Exception {
   com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
   testCase.testTryParse();
 }
+
+public void testTryParse_radix() throws Exception {
+  com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+  testCase.testTryParse_radix();
+}
+
+public void testTryParse_radixTooBig() throws Exception {
+  com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+  testCase.testTryParse_radixTooBig();
+}
+
+public void testTryParse_radixTooSmall() throws Exception {
+  com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+  testCase.testTryParse_radixTooSmall();
+}
 }
diff --git a/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
index 394001e..818b46e 100644
--- a/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
@@ -73,6 +73,11 @@ public void testParseInt() throws Exception {
   testCase.testParseInt();
 }
 
+public void testParseIntFail() throws Exception {
+  com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
+  testCase.testParseIntFail();
+}
+
 public void testParseIntThrowsExceptionForInvalidRadix() throws Exception {
   com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
   testCase.testParseIntThrowsExceptionForInvalidRadix();
@@ -83,6 +88,11 @@ public void testParseIntWithRadix() throws Exception {
   testCase.testParseIntWithRadix();
 }
 
+public void testParseIntWithRadixLimits() throws Exception {
+  com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
+  testCase.testParseIntWithRadixLimits();
+}
+
 public void testRemainder() throws Exception {
   com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
   testCase.testRemainder();
diff --git a/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
index 13374a5..0b4aca5 100644
--- a/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
@@ -73,6 +73,11 @@ public void testParseLong() throws Exception {
   testCase.testParseLong();
 }
 
+public void testParseLongFails() throws Exception {
+  com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
+  testCase.testParseLongFails();
+}
+
 public void testParseLongThrowsExceptionForInvalidRadix() throws Exception {
   com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
   testCase.testParseLongThrowsExceptionForInvalidRadix();
@@ -83,6 +88,11 @@ public void testParseLongWithRadix() throws Exception {
   testCase.testParseLongWithRadix();
 }
 
+public void testParseLongWithRadixLimits() throws Exception {
+  com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
+  testCase.testParseLongWithRadixLimits();
+}
+
 public void testRemainder() throws Exception {
   com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
   testCase.testRemainder();
diff --git a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
similarity index 63%
copy from guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
copy to guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
index 90022e9..f055cf3 100644
--- a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
+++ b/guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
@@ -13,13 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.google.common.collect.testing;
-public class HelpersTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+package com.google.common.util.concurrent;
+public class CallablesTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
 @Override public String getModuleName() {
-  return "com.google.common.collect.testing.testModule";
+  return "com.google.common.util.concurrent.testModule";
 }
-public void testNullsBeforeB() throws Exception {
-  com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
-  testCase.testNullsBeforeB();
+public void testReturning() throws Exception {
+  com.google.common.util.concurrent.CallablesTest testCase = new com.google.common.util.concurrent.CallablesTest();
+  testCase.testReturning();
 }
 }
diff --git a/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java
new file mode 100644
index 0000000..e960766
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util.concurrent;
+public class FutureCallbackTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.util.concurrent.testModule";
+}
+public void testCancel() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testCancel();
+}
+
+public void testExecutorSuccess() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testExecutorSuccess();
+}
+
+public void testRuntimeExeceptionFromGet() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testRuntimeExeceptionFromGet();
+}
+
+public void testSameThreadExecutionException() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testSameThreadExecutionException();
+}
+
+public void testSameThreadSuccess() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testSameThreadSuccess();
+}
+
+public void testThrowErrorFromGet() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testThrowErrorFromGet();
+}
+
+public void testWildcardFuture() throws Exception {
+  com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+  testCase.testWildcardFuture();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java
new file mode 100644
index 0000000..0bdb8e4
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java
@@ -0,0 +1,2153 @@
+/*
+ * 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.util.concurrent;
+public class FuturesTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.util.concurrent.testModule";
+}
+public void testAllAsList() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_cancelled() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_cancelled();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_doneFutures() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_doneFutures();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_emptyArray() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_emptyArray();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_failure() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_failure();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_error() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_error();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_exception() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_exception();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_multipleExceptions_alreadyDone();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_multipleExceptions_doneLater();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_same_cause() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_same_cause();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_same_exception() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_same_exception();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_seenExceptionUpdateCancelRace();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_logging_seenExceptionUpdateRace();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_resultCancelled() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_resultCancelled();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_resultCancelledInterrupted_withSecondaryListFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_resultCancelled_withSecondaryListFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_resultCancelled_withSecondaryListFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testAllAsList_resultInterrupted() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testAllAsList_resultInterrupted();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_Throwable() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_Throwable();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackGeneratesCheckedException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackGeneratesError() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackGeneratesError();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackGeneratesRuntimeException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackNotReady() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackNotReady();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackReturnsCheckedException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_fallbackReturnsRuntimeException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_inputDoesNotRaiseException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_inputRaisesException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_inputRaisesException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_nullInsteadOfFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_resultCancelledBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatchingAsync_resultInterruptedBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_Throwable() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_Throwable();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_fallbackGeneratesError() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_fallbackGeneratesError();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_fallbackGeneratesRuntimeException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_inputDoesNotRaiseException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_inputDoesNotRaiseException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_inputRaisesException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_inputRaisesException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_resultCancelledBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_resultCancelledBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testCatching_resultInterruptedBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_genericsHierarchy() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_genericsHierarchy();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_genericsWildcard() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_genericsWildcard();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_innerCancelsResult() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_innerCancelsResult();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_outerCancelsResult() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_outerCancelsResult();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_resultCancelsInner() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_resultCancelsInner();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testDereference_resultCancelsOuter() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testDereference_resultCancelsOuter();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testImmediateFailedFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testImmediateFailedFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testImmediateFailedFuture_cancellationException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testImmediateFailedFuture_cancellationException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testImmediateFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testImmediateFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testMultipleImmediateFutures() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testMultipleImmediateFutures();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testSuccessfulAsList_logging_error() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testSuccessfulAsList_logging_error();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testSuccessfulAsList_logging_exception() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testSuccessfulAsList_logging_exception();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_asyncFunction_error() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_asyncFunction_error();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_asyncFunction_nullInsteadOfFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_cancelPropagatesToAsyncOutput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_cancelPropagatesToInput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_genericsHierarchy_AsyncFunction();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_genericsWildcard_AsyncFunction();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_interruptPropagatesToAsyncOutput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_interruptPropagatesToAsyncOutput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformAsync_interruptPropagatesToInput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransformValueRemainsMemoized() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransformValueRemainsMemoized();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_Executor() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_Executor();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_asyncFunction_error() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_asyncFunction_error();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_asyncFunction_nullInsteadOfFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_cancelPropagatesToAsyncOutput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_cancelPropagatesToAsyncOutput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_cancelPropagatesToInput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_cancelPropagatesToInput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_genericsHierarchy() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_genericsHierarchy();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_genericsHierarchy_AsyncFunction();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_genericsNull() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_genericsNull();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_genericsWildcard_AsyncFunction();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_interruptPropagatesToAsyncOutput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_interruptPropagatesToAsyncOutput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testTransform_interruptPropagatesToInput() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testTransform_interruptPropagatesToInput();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackGeneratesCheckedException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackGeneratesError() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackGeneratesError();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackGeneratesRuntimeException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackNotReady() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackNotReady();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackReturnsCheckedException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_fallbackReturnsRuntimeException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_fallbackReturnsRuntimeException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_inputDoesNotRaiseException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_inputDoesNotRaiseException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_inputRaisesException() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_inputRaisesException();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_nullInsteadOfFuture() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_nullInsteadOfFuture();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_resultCancelledBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+
+public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
+  com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+  testCase.setUp();
+  Throwable failure = null;
+  try {
+    testCase.testWithFallback_resultInterruptedBeforeFallback();
+  } catch (Throwable t) {
+    failure = t;
+  }
+  try {
+    testCase.tearDown();
+  } catch (Throwable t) {
+    if (failure == null) {
+      failure = t;
+    }
+  }
+  if (failure instanceof Exception) {
+    throw (Exception) failure;
+  }
+  if (failure instanceof Error) {
+    throw (Error) failure;
+  }
+  if (failure != null) {
+    throw new RuntimeException(failure);
+  }
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java
new file mode 100644
index 0000000..a1b62cf
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java
@@ -0,0 +1,218 @@
+/*
+ * 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.util.concurrent;
+public class TrustedInputFutureTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.util.concurrent.testModule";
+}
+public void testCanceled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testCanceled();
+}
+
+public void testFailed() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testFailed();
+}
+
+public void testInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testInterrupted();
+}
+
+public void testListenLaterCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterCancelled();
+}
+
+public void testListenLaterFailed() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterFailed();
+}
+
+public void testListenLaterInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterInterrupted();
+}
+
+public void testListenLaterSetAsynchronously() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronously();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateFailed() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateFailed();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateInterrupted();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateSuccessful();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterSelfCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterSelfInterrupted();
+}
+
+public void testListenLaterSuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSuccessful();
+}
+
+public void testMisbehavingListenerAlreadyDone() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testMisbehavingListenerAlreadyDone();
+}
+
+public void testMisbehavingListenerLaterDone() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testMisbehavingListenerLaterDone();
+}
+
+public void testNullExecutor() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullExecutor();
+}
+
+public void testNullListener() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullListener();
+}
+
+public void testNullTimeUnit() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullTimeUnit();
+}
+
+public void testPending() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testPending();
+}
+
+public void testSetExceptionNull() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetExceptionNull();
+}
+
+public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadyCancelled();
+}
+
+public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadyInterrupted();
+}
+
+public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadySuccessful();
+}
+
+public void testSetFutureDelegateLaterCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterCancelled();
+}
+
+public void testSetFutureDelegateLaterInterrupted() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterInterrupted();
+}
+
+public void testSetFutureDelegateLaterSuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterSuccessful();
+}
+
+public void testSetFutureNull() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureNull();
+}
+
+public void testSetFuturePending() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFuturePending();
+}
+
+public void testSetFutureThenCancel() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureThenCancel();
+}
+
+public void testSetFutureThenInterrupt() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureThenInterrupt();
+}
+
+public void testSetNull() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetNull();
+}
+
+public void testSuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java
new file mode 100644
index 0000000..f91659d
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java
@@ -0,0 +1,35 @@
+/*
+ * 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.util.concurrent;
+public class TrustedListenableFutureTaskTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.util.concurrent.testModule";
+}
+public void testCancelled() throws Exception {
+  com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+  testCase.testCancelled();
+}
+
+public void testFailed() throws Exception {
+  com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+  testCase.testFailed();
+}
+
+public void testSuccessful() throws Exception {
+  com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+  testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java
new file mode 100644
index 0000000..9bb0baa
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java
@@ -0,0 +1,218 @@
+/*
+ * 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.util.concurrent;
+public class UntrustedInputFutureTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+  return "com.google.common.util.concurrent.testModule";
+}
+public void testCanceled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testCanceled();
+}
+
+public void testFailed() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testFailed();
+}
+
+public void testInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testInterrupted();
+}
+
+public void testListenLaterCancelled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterCancelled();
+}
+
+public void testListenLaterFailed() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterFailed();
+}
+
+public void testListenLaterInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterInterrupted();
+}
+
+public void testListenLaterSetAsynchronously() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronously();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateFailed() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateFailed();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateInterrupted();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterDelegateSuccessful();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfCancelled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterSelfCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSetAsynchronouslyLaterSelfInterrupted();
+}
+
+public void testListenLaterSuccessful() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testListenLaterSuccessful();
+}
+
+public void testMisbehavingListenerAlreadyDone() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testMisbehavingListenerAlreadyDone();
+}
+
+public void testMisbehavingListenerLaterDone() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testMisbehavingListenerLaterDone();
+}
+
+public void testNullExecutor() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullExecutor();
+}
+
+public void testNullListener() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullListener();
+}
+
+public void testNullTimeUnit() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testNullTimeUnit();
+}
+
+public void testPending() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testPending();
+}
+
+public void testSetExceptionNull() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetExceptionNull();
+}
+
+public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadyCancelled();
+}
+
+public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadyInterrupted();
+}
+
+public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateAlreadySuccessful();
+}
+
+public void testSetFutureDelegateLaterCancelled() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterCancelled();
+}
+
+public void testSetFutureDelegateLaterInterrupted() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterInterrupted();
+}
+
+public void testSetFutureDelegateLaterSuccessful() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureDelegateLaterSuccessful();
+}
+
+public void testSetFutureNull() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureNull();
+}
+
+public void testSetFuturePending() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFuturePending();
+}
+
+public void testSetFutureThenCancel() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureThenCancel();
+}
+
+public void testSetFutureThenInterrupt() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetFutureThenInterrupt();
+}
+
+public void testSetNull() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSetNull();
+}
+
+public void testSuccessful() throws Exception {
+  com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+  testCase.setUp();
+  testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml b/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
index c9f489f..c7b559a 100644
--- a/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
@@ -5,11 +5,13 @@
   <inherits name="com.google.common.annotations.Annotations"/>
   <inherits name="com.google.common.base.Base"/>
   <inherits name="com.google.common.collect.Collect"/>
+  <inherits name="com.google.common.testing.Testing"/>
   <inherits name="com.google.common.util.concurrent.Concurrent"/>
+  <inherits name="com.google.common.truth.Truth"/>
   <entry-point class="com.google.common.util.concurrent.TestModuleEntryPoint"/>
    
   <source path=""/>
-    
+   
   <super-source path="super"/>
    
 </module>
diff --git a/guava-testlib/pom.xml b/guava-testlib/pom.xml
index 5fe40f1..45b6a6f 100644
--- a/guava-testlib/pom.xml
+++ b/guava-testlib/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>com.google.guava</groupId>
     <artifactId>guava-parent</artifactId>
-    <version>18.0</version>
+    <version>19.0</version>
   </parent>
   <artifactId>guava-testlib</artifactId>
   <name>Guava Testing Library</name>
@@ -19,6 +19,15 @@
       <artifactId>jsr305</artifactId>
     </dependency>
     <dependency>
+      <groupId>com.google.errorprone</groupId>
+      <artifactId>error_prone_annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.j2objc</groupId>
+      <artifactId>j2objc-annotations</artifactId>
+      <optional>true</optional><!-- needed only for annotations -->
+    </dependency>
+    <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>guava</artifactId>
       <version>${project.version}</version>
@@ -29,9 +38,12 @@
       <scope>compile</scope><!-- testlib must carry these transitively -->
     </dependency>
     <dependency>
+      <!--
+      Do not include Truth in non-test scope! Doing so creates a problematic dependency cycle.
+      -->
       <groupId>com.google.truth</groupId>
       <artifactId>truth</artifactId>
-      <scope>compile</scope><!-- testlib must carry these transitively -->
+      <scope>test</scope>
     </dependency>
   </dependencies>
   <build>
@@ -51,9 +63,9 @@
       </plugin>
       <plugin>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.3.1</version>
         <executions>
           <execution>
+            <id>create-test-jar</id>
             <goals><goal>test-jar</goal></goals>
           </execution>
         </executions>
@@ -65,6 +77,12 @@
       <plugin>
         <artifactId>maven-javadoc-plugin</artifactId>
       </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java b/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
index a650f28..fbf44b6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
@@ -237,11 +237,31 @@ public abstract class AbstractContainerTester<C, E>
 
   @SuppressWarnings("unchecked")
   protected MinimalCollection<E> createDisjointCollection() {
-    return MinimalCollection.of(samples.e3, samples.e4);
+    return MinimalCollection.of(e3(), e4());
   }
 
   @SuppressWarnings("unchecked")
   protected MinimalCollection<E> emptyCollection() {
     return MinimalCollection.<E>of();
   }
+
+  protected final E e0() {
+    return samples.e0();
+  }
+
+  protected final E e1() {
+    return samples.e1();
+  }
+
+  protected final E e2() {
+    return samples.e2();
+  }
+
+  protected final E e3() {
+    return samples.e3();
+  }
+
+  protected final E e4() {
+    return samples.e4();
+  }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java b/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
index 4dd6298..5d57ea1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
@@ -154,7 +154,7 @@ public abstract class AbstractMapTester<K, V> extends
   @SuppressWarnings("unchecked")
   @Override protected MinimalCollection<Map.Entry<K, V>>
       createDisjointCollection() {
-    return MinimalCollection.of(samples.e3, samples.e4);
+    return MinimalCollection.of(e3(), e4());
   }
 
   protected int getNumEntries() {
@@ -228,4 +228,44 @@ public abstract class AbstractMapTester<K, V> extends
   protected void resetMap(Entry<K, V>[] entries) {
     resetContainer(getSubjectGenerator().create((Object[]) entries));
   }
+
+  protected final K k0() {
+    return e0().getKey();
+  }
+
+  protected final V v0() {
+    return e0().getValue();
+  }
+
+  protected final K k1() {
+    return e1().getKey();
+  }
+
+  protected final V v1() {
+    return e1().getValue();
+  }
+
+  protected final K k2() {
+    return e2().getKey();
+  }
+
+  protected final V v2() {
+    return e2().getValue();
+  }
+
+  protected final K k3() {
+    return e3().getKey();
+  }
+
+  protected final V v3() {
+    return e3().getValue();
+  }
+
+  protected final K k4() {
+    return e4().getKey();
+  }
+
+  protected final V v4() {
+    return e4().getValue();
+  }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
index d4143b5..02b3917 100644
--- a/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
@@ -16,7 +16,9 @@
 
 package com.google.common.collect.testing;
 
-import com.google.common.collect.testing.features.CollectionFeature;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.testing.SerializableTester;
 
@@ -53,7 +55,7 @@ public class CollectionTestSuiteBuilder<E>
     List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
         super.createDerivedSuites(parentBuilder));
 
-    if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+    if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
       derivedSuites.add(CollectionTestSuiteBuilder
           .using(new ReserializedCollectionGenerator<E>(parentBuilder.getSubjectGenerator()))
           .named(getName() + " reserialized")
@@ -95,8 +97,8 @@ public class CollectionTestSuiteBuilder<E>
   private static Set<Feature<?>> computeReserializedCollectionFeatures(Set<Feature<?>> features) {
     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
     derivedFeatures.addAll(features);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+    derivedFeatures.remove(SERIALIZABLE);
+    derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
     return derivedFeatures;
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java
new file mode 100644
index 0000000..37e7765
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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.testing;
+
+import com.google.common.collect.testing.testers.ConcurrentMapPutIfAbsentTester;
+import com.google.common.collect.testing.testers.ConcurrentMapRemoveTester;
+import com.google.common.collect.testing.testers.ConcurrentMapReplaceEntryTester;
+import com.google.common.collect.testing.testers.ConcurrentMapReplaceTester;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Creates, based on your criteria, a JUnit test suite that exhaustively tests a ConcurrentMap
+ * implementation.
+ *
+ * @author Louis Wasserman
+ */
+public class ConcurrentMapTestSuiteBuilder<K, V> extends MapTestSuiteBuilder<K, V> {
+  public static <K, V> ConcurrentMapTestSuiteBuilder<K, V> using(
+      TestMapGenerator<K, V> generator) {
+    ConcurrentMapTestSuiteBuilder<K, V> result = new ConcurrentMapTestSuiteBuilder<K, V>();
+    result.usingGenerator(generator);
+    return result;
+  }
+  
+  static final List<? extends Class<? extends AbstractTester>> TESTERS = 
+      Arrays.asList(
+          ConcurrentMapPutIfAbsentTester.class,
+          ConcurrentMapRemoveTester.class,
+          ConcurrentMapReplaceTester.class,
+          ConcurrentMapReplaceEntryTester.class);
+  
+  @Override
+  protected List<Class<? extends AbstractTester>> getTesters() {
+    List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters());
+    testers.addAll(TESTERS);
+    return testers;
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java
new file mode 100644
index 0000000..e82a964
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 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.testing;
+
+import java.util.List;
+
+/**
+ * Creates, based on your criteria, a JUnit test suite that exhaustively tests
+ * a ConcurrentNavigableMap implementation.
+ * 
+ * @author Louis Wasserman
+ */
+public class ConcurrentNavigableMapTestSuiteBuilder<K, V> extends
+    NavigableMapTestSuiteBuilder<K, V> {
+
+  public static <K, V> ConcurrentNavigableMapTestSuiteBuilder<K, V> using(
+      TestSortedMapGenerator<K, V> generator) {
+    ConcurrentNavigableMapTestSuiteBuilder<K, V> result =
+        new ConcurrentNavigableMapTestSuiteBuilder<K, V>();
+    result.usingGenerator(generator);
+    return result;
+  }
+
+  @Override
+  protected List<Class<? extends AbstractTester>> getTesters() {
+    List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters());
+    testers.addAll(ConcurrentMapTestSuiteBuilder.TESTERS);
+    return testers;
+  }
+
+  @Override
+  NavigableMapTestSuiteBuilder<K, V> subSuiteUsing(TestSortedMapGenerator<K, V> generator) {
+    return using(generator);
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java b/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
index e91d08d..08d1866 100644
--- a/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
@@ -107,11 +107,11 @@ public final class DerivedCollectionGenerators {
       final SampleElements<Map.Entry<K, V>> mapSamples =
           this.mapGenerator.samples();
       this.samples = new SampleElements<K>(
-          mapSamples.e0.getKey(),
-          mapSamples.e1.getKey(),
-          mapSamples.e2.getKey(),
-          mapSamples.e3.getKey(),
-          mapSamples.e4.getKey());
+          mapSamples.e0().getKey(),
+          mapSamples.e1().getKey(),
+          mapSamples.e2().getKey(),
+          mapSamples.e3().getKey(),
+          mapSamples.e4().getKey());
     }
 
     @Override
@@ -151,7 +151,7 @@ public final class DerivedCollectionGenerators {
 
     @Override
     public Iterable<K> order(List<K> insertionOrder) {
-      V v = ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).samples().e0.getValue();
+      V v = ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).samples().e0().getValue();
       List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
       for (K element : insertionOrder) {
         entries.add(mapEntry(element, v));
@@ -220,11 +220,11 @@ public final class DerivedCollectionGenerators {
       final SampleElements<Map.Entry<K, V>> mapSamples =
           this.mapGenerator.samples();
       this.samples = new SampleElements<V>(
-          mapSamples.e0.getValue(),
-          mapSamples.e1.getValue(),
-          mapSamples.e2.getValue(),
-          mapSamples.e3.getValue(),
-          mapSamples.e4.getValue());
+          mapSamples.e0().getValue(),
+          mapSamples.e1().getValue(),
+          mapSamples.e2().getValue(),
+          mapSamples.e3().getValue(),
+          mapSamples.e4().getValue());
     }
 
     @Override
@@ -484,7 +484,7 @@ public final class DerivedCollectionGenerators {
       SampleElements<Entry<K, V>> samples = delegate.samples();
       @SuppressWarnings("unchecked") // no elements are inserted into the array
       List<Entry<K, V>> samplesList = Arrays.asList(
-          samples.e0, samples.e1, samples.e2, samples.e3, samples.e4);
+          samples.e0(), samples.e1(), samples.e2(), samples.e3(), samples.e4());
       Collections.sort(samplesList, entryComparator);
       this.firstInclusive = samplesList.get(0).getKey();
       this.lastInclusive = samplesList.get(samplesList.size() - 1).getKey();
diff --git a/guava-testlib/src/com/google/common/collect/testing/Helpers.java b/guava-testlib/src/com/google/common/collect/testing/Helpers.java
index 277f50d..7377626 100644
--- a/guava-testlib/src/com/google/common/collect/testing/Helpers.java
+++ b/guava-testlib/src/com/google/common/collect/testing/Helpers.java
@@ -76,6 +76,49 @@ public class Helpers {
     return Collections.singletonMap(key, value).entrySet().iterator().next();
   }
 
+  private static boolean isEmpty(Iterable<?> iterable) {
+    return iterable instanceof Collection
+        ? ((Collection<?>) iterable).isEmpty()
+        : iterable.iterator().hasNext();
+  }
+
+  public static void assertEmpty(Iterable<?> iterable) {
+    if (!isEmpty(iterable)) {
+      Assert.fail("Not true that " + iterable + " is empty");
+    }
+  }
+
+  public static void assertEmpty(Map<?, ?> map) {
+    if (!map.isEmpty()) {
+      Assert.fail("Not true that " + map + " is empty");
+    }
+  }
+
+  public static void assertEqualInOrder(
+      Iterable<?> expected, Iterable<?> actual) {
+    Iterator<?> expectedIter = expected.iterator();
+    Iterator<?> actualIter = actual.iterator();
+
+    while (expectedIter.hasNext() && actualIter.hasNext()) {
+      if (!equal(expectedIter.next(), actualIter.next())) {
+        Assert.fail(
+            "contents were not equal and in the same order: "
+                + "expected = " + expected + ", actual = " + actual);
+      }
+    }
+
+    if (expectedIter.hasNext() || actualIter.hasNext()) {
+      // actual either had too few or too many elements
+      Assert.fail(
+          "contents were not equal and in the same order: "
+              + "expected = " + expected + ", actual = " + actual);
+    }
+  }
+
+  public static void assertContentsInOrder(Iterable<?> actual, Object... expected) {
+    assertEqualInOrder(Arrays.asList(expected), actual);
+  }
+
   public static void assertEqualIgnoringOrder(
       Iterable<?> expected, Iterable<?> actual) {
     List<?> exp = copyToList(expected);
@@ -100,6 +143,39 @@ public class Helpers {
     assertEqualIgnoringOrder(Arrays.asList(expected), actual);
   }
 
+  public static void assertContains(Iterable<?> actual, Object expected) {
+    boolean contained = false;
+    if (actual instanceof Collection) {
+      contained = ((Collection<?>) actual).contains(expected);
+    } else {
+      for (Object o : actual) {
+        if (equal(o, expected)) {
+          contained = true;
+          break;
+        }
+      }
+    }
+
+    if (!contained) {
+      Assert.fail("Not true that " + actual + " contains " + expected);
+    }
+  }
+
+  public static void assertContainsAllOf(
+      Iterable<?> actual, Object... expected) {
+    List<Object> expectedList = new ArrayList<Object>();
+    expectedList.addAll(Arrays.asList(expected));
+
+    for (Object o : actual) {
+      expectedList.remove(o);
+    }
+
+    if (!expectedList.isEmpty()) {
+      Assert.fail(
+          "Not true that " + actual + " contains all of " + Arrays.asList(expected));
+    }
+  }
+
   public static <E> boolean addAll(
       Collection<E> addTo, Iterable<? extends E> elementsToAdd) {
     boolean modified = false;
@@ -180,11 +256,31 @@ public class Helpers {
     };
   }
 
+  /**
+   * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+   * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+   * the given {@code comparator}.
+   *
+   * @see #testComparator(Comparator, List)
+   */
   public static <T> void testComparator(
       Comparator<? super T> comparator, T... valuesInExpectedOrder) {
     testComparator(comparator, Arrays.asList(valuesInExpectedOrder));
   }
 
+  /**
+   * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+   * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+   * the given {@code comparator}.
+   *
+   * <p>In detail, this method asserts
+   * <ul>
+   * <li><i>reflexivity</i>: {@code comparator.compare(t, t) = 0} for all {@code t} in
+   * {@code valuesInExpectedOrder}; and
+   * <li><i>consistency</i>: {@code comparator.compare(ti, tj) < 0} and
+   * {@code comparator.compare(tj, ti) > 0} for {@code i < j}, where
+   * {@code ti = valuesInExpectedOrder.get(i)} and {@code tj = valuesInExpectedOrder.get(j)}.
+   */
   public static <T> void testComparator(
       Comparator<? super T> comparator, List<T> valuesInExpectedOrder) {
     // This does an O(n^2) test of all pairs of values in both orders
diff --git a/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
index 03f16cf..71b410c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
@@ -16,6 +16,10 @@
 
 package com.google.common.collect.testing;
 
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.collect.testing.testers.CollectionSerializationEqualTester;
@@ -91,7 +95,7 @@ public final class ListTestSuiteBuilder<E> extends
    * lists have an iteration ordering corresponding to the insertion order.
    */
   @Override public TestSuite createTestSuite() {
-    withFeatures(CollectionFeature.KNOWN_ORDER);
+    withFeatures(KNOWN_ORDER);
     return super.createTestSuite();
   }
 
@@ -104,7 +108,7 @@ public final class ListTestSuiteBuilder<E> extends
     List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
         super.createDerivedSuites(parentBuilder));
 
-    if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+    if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
       derivedSuites.add(ListTestSuiteBuilder
           .using(new ReserializedListGenerator<E>(parentBuilder.getSubjectGenerator()))
           .named(getName() + " reserialized")
@@ -147,8 +151,8 @@ public final class ListTestSuiteBuilder<E> extends
       Set<Feature<?>> features) {
     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
     derivedFeatures.addAll(features);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+    derivedFeatures.remove(SERIALIZABLE);
+    derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
     return derivedFeatures;
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
index c8390f0..3f3fc1a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
@@ -169,7 +169,7 @@ public class MapTestSuiteBuilder<K, V>
     Set<Feature<?>> keySetFeatures =
         computeCommonDerivedCollectionFeatures(mapFeatures);
 
-    // TODO(user): make this trigger only if the map is a submap
+    // TODO(lowasser): make this trigger only if the map is a submap
     // currently, the KeySetGenerator won't work properly for a subset of a keyset of a submap
     keySetFeatures.add(CollectionFeature.SUBSET_VIEW);
     if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEYS)) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
index c31cc61..aa91337 100644
--- a/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
@@ -20,6 +20,7 @@ import static com.google.common.collect.testing.Helpers.castOrCopyToList;
 import static java.util.Collections.reverse;
 
 import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
+import com.google.common.collect.testing.DerivedCollectionGenerators.ForwardingTestMapGenerator;
 import com.google.common.collect.testing.DerivedCollectionGenerators.SortedMapSubmapTestMapGenerator;
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.collect.testing.testers.NavigableMapNavigationTester;
@@ -106,7 +107,7 @@ public class NavigableMapTestSuiteBuilder<K, V> extends SortedMapTestSuiteBuilde
   @Override
   public NavigableMapTestSuiteBuilder<K, V> newBuilderUsing(
       TestSortedMapGenerator<K, V> delegate, Bound to, Bound from) {
-    return using(new NavigableMapSubmapTestMapGenerator<K, V>(delegate, to, from));
+    return subSuiteUsing(new NavigableMapSubmapTestMapGenerator<K, V>(delegate, to, from));
   }
 
   /**
@@ -114,68 +115,64 @@ public class NavigableMapTestSuiteBuilder<K, V> extends SortedMapTestSuiteBuilde
    */
   private TestSuite createDescendingSuite(final FeatureSpecificTestSuiteBuilder<?,
           ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) {
-    final TestMapGenerator<K, V> delegate
-        = (TestMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
+    final TestSortedMapGenerator<K, V> delegate
+        = (TestSortedMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
 
     List<Feature<?>> features = new ArrayList<Feature<?>>();
     features.add(NoRecurse.DESCENDING);
     features.addAll(parentBuilder.getFeatures());
 
-    return NavigableMapTestSuiteBuilder
-        .using(new ForwardingTestMapGenerator<K, V>(delegate) {
-          @Override public Map<K, V> create(Object... entries) {
-            NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries);
-            return map.descendingMap();
-          }
-
-          @Override
-          public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
-            insertionOrder = castOrCopyToList(delegate.order(insertionOrder));
-            reverse(insertionOrder);
-            return insertionOrder;
-          }
-        })
+    return subSuiteUsing(new DescendingTestMapGenerator<K, V>(delegate))
         .named(parentBuilder.getName() + " descending")
         .withFeatures(features)
         .suppressing(parentBuilder.getSuppressedTests())
         .createTestSuite();
   }
+  
+  NavigableMapTestSuiteBuilder<K, V> subSuiteUsing(TestSortedMapGenerator<K, V> generator) {
+    return using(generator);
+  }
+  
+  static class DescendingTestMapGenerator<K, V>
+      extends ForwardingTestMapGenerator<K, V> implements TestSortedMapGenerator<K, V> {
+    DescendingTestMapGenerator(TestSortedMapGenerator<K, V> delegate) {
+      super(delegate);
+    }
 
-  static class ForwardingTestMapGenerator<K, V> implements TestMapGenerator<K, V> {
-    private TestMapGenerator<K, V> delegate;
-
-    ForwardingTestMapGenerator(TestMapGenerator<K, V> delegate) {
-      this.delegate = delegate;
+    @Override public NavigableMap<K, V> create(Object... entries) {
+      NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries);
+      return map.descendingMap();
     }
 
     @Override
     public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
-      return delegate.order(insertionOrder);
+      insertionOrder = castOrCopyToList(delegate.order(insertionOrder));
+      reverse(insertionOrder);
+      return insertionOrder;
     }
-
-    @Override
-    public K[] createKeyArray(int length) {
-      return delegate.createKeyArray(length);
+    
+    TestSortedMapGenerator<K, V> delegate() {
+      return (TestSortedMapGenerator<K, V>) delegate;
     }
 
     @Override
-    public V[] createValueArray(int length) {
-      return delegate.createValueArray(length);
+    public Entry<K, V> belowSamplesLesser() {
+      return delegate().aboveSamplesGreater();
     }
 
     @Override
-    public SampleElements<Entry<K, V>> samples() {
-      return delegate.samples();
+    public Entry<K, V> belowSamplesGreater() {
+      return delegate().aboveSamplesLesser();
     }
 
     @Override
-    public Map<K, V> create(Object... elements) {
-      return delegate.create(elements);
+    public Entry<K, V> aboveSamplesLesser() {
+      return delegate().belowSamplesGreater();
     }
 
     @Override
-    public Entry<K, V>[] createArray(int length) {
-      return delegate.createArray(length);
-    }
+    public Entry<K, V> aboveSamplesGreater() {
+      return delegate().belowSamplesLesser();
+    }    
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
index 4642147..524d721 100644
--- a/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
@@ -16,9 +16,11 @@
 
 package com.google.common.collect.testing;
 
+import static com.google.common.collect.testing.features.CollectionFeature.DESCENDING_VIEW;
+import static com.google.common.collect.testing.features.CollectionFeature.SUBSET_VIEW;
+
 import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
 import com.google.common.collect.testing.DerivedCollectionGenerators.SortedSetSubsetTestSetGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.collect.testing.testers.NavigableSetNavigationTester;
 
@@ -52,7 +54,7 @@ public final class NavigableSetTestSuiteBuilder<E>
     List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
         super.createDerivedSuites(parentBuilder));
 
-    if (!parentBuilder.getFeatures().contains(CollectionFeature.SUBSET_VIEW)) {
+    if (!parentBuilder.getFeatures().contains(SUBSET_VIEW)) {
       // Other combinations are inherited from SortedSetTestSuiteBuilder.
       derivedSuites.add(createSubsetSuite(parentBuilder, Bound.NO_BOUND, Bound.INCLUSIVE));
       derivedSuites.add(createSubsetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.NO_BOUND));
@@ -60,7 +62,7 @@ public final class NavigableSetTestSuiteBuilder<E>
       derivedSuites.add(createSubsetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.INCLUSIVE));
       derivedSuites.add(createSubsetSuite(parentBuilder, Bound.INCLUSIVE, Bound.INCLUSIVE));
     }
-    if (!parentBuilder.getFeatures().contains(CollectionFeature.DESCENDING_VIEW)) {
+    if (!parentBuilder.getFeatures().contains(DESCENDING_VIEW)) {
       derivedSuites.add(createDescendingSuite(parentBuilder));
     }
     return derivedSuites;
@@ -107,7 +109,7 @@ public final class NavigableSetTestSuiteBuilder<E>
         (TestSetGenerator<E>) parentBuilder.getSubjectGenerator().getInnerGenerator();
 
     List<Feature<?>> features = new ArrayList<Feature<?>>();
-    features.add(CollectionFeature.DESCENDING_VIEW);
+    features.add(DESCENDING_VIEW);
     features.addAll(parentBuilder.getFeatures());
 
     return NavigableSetTestSuiteBuilder.using(new TestSetGenerator<E>() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java b/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
index cb61997..5046e6d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
+++ b/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
@@ -73,7 +73,7 @@ public final class OneSizeGenerator<T, E>
     SampleElements<E> samples = samples();
     @SuppressWarnings("unchecked")
     List<E> allSampleElements = Arrays.asList(
-        samples.e0, samples.e1, samples.e2, samples.e3, samples.e4);
+        samples.e0(), samples.e1(), samples.e2(), samples.e3(), samples.e4());
     return new ArrayList<E>(allSampleElements.subList(0, howMany));
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/Platform.java b/guava-testlib/src/com/google/common/collect/testing/Platform.java
index 99eeb06..fe1e9af 100644
--- a/guava-testlib/src/com/google/common/collect/testing/Platform.java
+++ b/guava-testlib/src/com/google/common/collect/testing/Platform.java
@@ -18,6 +18,8 @@ package com.google.common.collect.testing;
 
 import com.google.common.annotations.GwtCompatible;
 
+import java.util.Locale;
+
 /**
  * Methods factored out so that they can be emulated differently in GWT.
  *
@@ -48,7 +50,7 @@ final class Platform {
   }
 
   static String format(String template, Object... args) {
-    return String.format(template, args);
+    return String.format(Locale.ROOT, template, args);
   }
 
   private Platform() {}
diff --git a/guava-testlib/src/com/google/common/collect/testing/SampleElements.java b/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
index d0b7638..092eac3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
@@ -31,11 +31,11 @@ import java.util.Map;
 @GwtCompatible
 public class SampleElements<E> implements Iterable<E> {
   // TODO: rename e3, e4 => missing1, missing2
-  public final E e0;
-  public final E e1;
-  public final E e2;
-  public final E e3;
-  public final E e4;
+  private final E e0;
+  private final E e1;
+  private final E e2;
+  private final E e3;
+  private final E e4;
 
   public SampleElements(E e0, E e1, E e2, E e3, E e4) {
     this.e0 = e0;
@@ -51,7 +51,7 @@ public class SampleElements<E> implements Iterable<E> {
   }
   
   public List<E> asList() {
-    return Arrays.asList(e0, e1, e2, e3, e4);
+    return Arrays.asList(e0(), e1(), e2(), e3(), e4());
   }
 
   public static class Strings extends SampleElements<String> {
@@ -92,11 +92,31 @@ public class SampleElements<E> implements Iterable<E> {
   public static <K, V> SampleElements<Map.Entry<K, V>> mapEntries(
       SampleElements<K> keys, SampleElements<V> values) {
     return new SampleElements<Map.Entry<K, V>>(
-        Helpers.mapEntry(keys.e0, values.e0),
-        Helpers.mapEntry(keys.e1, values.e1),
-        Helpers.mapEntry(keys.e2, values.e2),
-        Helpers.mapEntry(keys.e3, values.e3),
-        Helpers.mapEntry(keys.e4, values.e4));
+        Helpers.mapEntry(keys.e0(), values.e0()),
+        Helpers.mapEntry(keys.e1(), values.e1()),
+        Helpers.mapEntry(keys.e2(), values.e2()),
+        Helpers.mapEntry(keys.e3(), values.e3()),
+        Helpers.mapEntry(keys.e4(), values.e4()));
+  }
+
+  public E e0() {
+    return e0;
+  }
+
+  public E e1() {
+    return e1;
+  }
+
+  public E e2() {
+    return e2;
+  }
+
+  public E e3() {
+    return e3;
+  }
+
+  public E e4() {
+    return e4;
   }
 
   public static class Unhashables extends SampleElements<UnhashableObject> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
index 7437760..321dd5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
@@ -16,7 +16,9 @@
 
 package com.google.common.collect.testing;
 
-import com.google.common.collect.testing.features.CollectionFeature;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.collect.testing.testers.CollectionSerializationEqualTester;
 import com.google.common.collect.testing.testers.SetAddAllTester;
@@ -74,7 +76,7 @@ public class SetTestSuiteBuilder<E>
     List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
         super.createDerivedSuites(parentBuilder));
 
-    if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+    if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
       derivedSuites.add(SetTestSuiteBuilder
           .using(new ReserializedSetGenerator<E>(parentBuilder.getSubjectGenerator()))
           .named(getName() + " reserialized")
@@ -117,8 +119,8 @@ public class SetTestSuiteBuilder<E>
       Set<Feature<?>> features) {
     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
     derivedFeatures.addAll(features);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
-    derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+    derivedFeatures.remove(SERIALIZABLE);
+    derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
     return derivedFeatures;
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
index f5cad51..82ef33b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
@@ -16,9 +16,10 @@
 
 package com.google.common.collect.testing;
 
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+
 import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
 import com.google.common.collect.testing.DerivedCollectionGenerators.SortedMapSubmapTestMapGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.collect.testing.testers.SortedMapNavigationTester;
 
@@ -50,9 +51,9 @@ public class SortedMapTestSuiteBuilder<K, V> extends MapTestSuiteBuilder<K, V> {
   }
 
   @Override public TestSuite createTestSuite() {
-    if (!getFeatures().contains(CollectionFeature.KNOWN_ORDER)) {
+    if (!getFeatures().contains(KNOWN_ORDER)) {
       List<Feature<?>> features = Helpers.copyToList(getFeatures());
-      features.add(CollectionFeature.KNOWN_ORDER);
+      features.add(KNOWN_ORDER);
       withFeatures(features);
     }
     return super.createTestSuite();
diff --git a/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java b/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
index 72db7f6..e28e8ef 100644
--- a/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
+++ b/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
@@ -247,10 +247,9 @@ public class TestsForMapsInJavaUtil {
   }
 
   public Test testsForConcurrentHashMap() {
-    return MapTestSuiteBuilder
+    return ConcurrentMapTestSuiteBuilder
         .using(new TestStringMapGenerator() {
-          @Override protected Map<String, String> create(
-              Entry<String, String>[] entries) {
+          @Override protected Map<String, String> create(Entry<String, String>[] entries) {
             return populate(new ConcurrentHashMap<String, String>(), entries);
           }
         })
@@ -265,7 +264,7 @@ public class TestsForMapsInJavaUtil {
   }
 
   public Test testsForConcurrentSkipListMapNatural() {
-    return NavigableMapTestSuiteBuilder
+    return ConcurrentNavigableMapTestSuiteBuilder
         .using(new TestStringSortedMapGenerator() {
           @Override protected SortedMap<String, String> create(
               Entry<String, String>[] entries) {
@@ -284,7 +283,7 @@ public class TestsForMapsInJavaUtil {
   }
 
   public Test testsForConcurrentSkipListMapWithComparator() {
-    return NavigableMapTestSuiteBuilder
+    return ConcurrentNavigableMapTestSuiteBuilder
         .using(new TestStringSortedMapGenerator() {
           @Override protected SortedMap<String, String> create(
               Entry<String, String>[] entries) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java b/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
index 491fe08..cb18aa1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
+++ b/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -233,9 +234,9 @@ public class FeatureUtil {
     Set<Feature<?>> conflictingFeatures =
         intersection(allPresentFeatures, allAbsentFeatures);
     if (!conflictingFeatures.isEmpty()) {
-      throw new ConflictingRequirementsException("Annotation explicitly or " +
-          "implicitly requires one or more features to be both present " +
-          "and absent.",
+      throw new ConflictingRequirementsException("Annotation explicitly or "
+          + "implicitly requires one or more features to be both present "
+          + "and absent.",
           conflictingFeatures, testerAnnotation);
     }
     return new TesterRequirements(allPresentFeatures, allAbsentFeatures);
@@ -278,9 +279,9 @@ public class FeatureUtil {
     Set<Feature<?>> conflictingFeatures;
     conflictingFeatures = intersection(newFeatures, earlierFeatures);
     if (!conflictingFeatures.isEmpty()) {
-      throw new ConflictingRequirementsException(String.format(
-          "Annotation requires to be %s features that earlier " +
-          "annotations required to be %s.",
+      throw new ConflictingRequirementsException(String.format(Locale.ROOT,
+          "Annotation requires to be %s features that earlier "
+          + "annotations required to be %s.",
               newRequirement, earlierRequirement),
           conflictingFeatures, source);
     }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
index acf973c..1f30f24 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
@@ -14,7 +14,7 @@
 
 package com.google.common.collect.testing.google;
 
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ListMultimap;
@@ -36,13 +36,13 @@ public class AbstractListMultimapTester<K, V>
   }
 
   protected void assertGet(K key, Collection<V> values) {
-    assertThat(multimap().get(key)).has().exactlyAs(values).inOrder();
+    assertEqualInOrder(values, multimap().get(key));
 
     if (!values.isEmpty()) {
-      assertThat(multimap().asMap().get(key)).has().exactlyAs(values).inOrder();
+      assertEqualInOrder(values, multimap().asMap().get(key));
       assertFalse(multimap().isEmpty());
     } else {
-      assertThat(multimap().asMap().get(key)).isNull();
+      assertNull(multimap().asMap().get(key));
     }
 
     assertEquals(values.size(), multimap().get(key).size());
@@ -51,4 +51,3 @@ public class AbstractListMultimapTester<K, V>
     assertEquals(values.size() > 0, multimap().keys().contains(key));
   }
 }
-
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
index f307c36..80074e7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
@@ -16,7 +16,7 @@
 
 package com.google.common.collect.testing.google;
 
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -145,21 +145,59 @@ public abstract class AbstractMultimapTester<K, V, M extends Multimap<K, V>>
   }
 
   protected void assertGet(K key, Collection<V> values) {
-    assertThat(multimap().get(key)).has().exactlyAs(values);
+    assertEqualIgnoringOrder(values, multimap().get(key));
 
     if (!values.isEmpty()) {
-      assertThat(multimap().asMap().get(key)).has().exactlyAs(values);
+      assertEqualIgnoringOrder(values, multimap().asMap().get(key));
       assertFalse(multimap().isEmpty());
     } else {
-      assertThat(multimap().asMap().get(key)).isNull();
+      assertNull(multimap().asMap().get(key));
     }
 
-    // TODO(user): Add proper overrides to prevent autoboxing.
-    // Truth+autoboxing == compile error. Cast int to long to fix:
-    assertThat(multimap().get(key).size()).isEqualTo((long) values.size());
+    assertEquals(values.size(), multimap().get(key).size());
 
     assertEquals(values.size() > 0, multimap().containsKey(key));
     assertEquals(values.size() > 0, multimap().keySet().contains(key));
     assertEquals(values.size() > 0, multimap().keys().contains(key));
   }
+
+  protected final K k0() {
+    return e0().getKey();
+  }
+
+  protected final V v0() {
+    return e0().getValue();
+  }
+
+  protected final K k1() {
+    return e1().getKey();
+  }
+
+  protected final V v1() {
+    return e1().getValue();
+  }
+
+  protected final K k2() {
+    return e2().getKey();
+  }
+
+  protected final V v2() {
+    return e2().getValue();
+  }
+
+  protected final K k3() {
+    return e3().getKey();
+  }
+
+  protected final V v3() {
+    return e3().getValue();
+  }
+
+  protected final K k4() {
+    return e4().getKey();
+  }
+
+  protected final V v4() {
+    return e4().getValue();
+  }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
index 25772a3..3f33a1a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
@@ -112,16 +112,16 @@ public abstract class AbstractMultisetSetCountTester<E>
   // Unconditional setCount no-ops.
 
   private void assertZeroToZero() {
-    assertSetCount(samples.e3, 0);
+    assertSetCount(e3(), 0);
   }
 
   private void assertOneToOne() {
-    assertSetCount(samples.e0, 1);
+    assertSetCount(e0(), 1);
   }
 
   private void assertThreeToThree() {
     initThreeCopies();
-    assertSetCount(samples.e0, 3);
+    assertSetCount(e0(), 3);
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
@@ -188,7 +188,7 @@ public abstract class AbstractMultisetSetCountTester<E>
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_zeroToOne_supported() {
-    assertSetCount(samples.e3, 1);
+    assertSetCount(e3(), 1);
   }
 
   @CollectionFeature.Require({SUPPORTS_ADD,
@@ -196,7 +196,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountZeroToOneConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertSetCount(samples.e3, 1);
+      assertSetCount(e3(), 1);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -209,7 +209,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountZeroToOneConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
-      assertSetCount(samples.e3, 1);
+      assertSetCount(e3(), 1);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -219,29 +219,29 @@ public abstract class AbstractMultisetSetCountTester<E>
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_zeroToThree_supported() {
-    assertSetCount(samples.e3, 3);
+    assertSetCount(e3(), 3);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCount_oneToThree_supported() {
-    assertSetCount(samples.e0, 3);
+    assertSetCount(e0(), 3);
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_zeroToOne_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 1);
+    assertSetCountIncreasingFailure(e3(), 1);
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_zeroToThree_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 3);
+    assertSetCountIncreasingFailure(e3(), 3);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testSetCount_oneToThree_unsupported() {
-    assertSetCountIncreasingFailure(samples.e3, 3);
+    assertSetCountIncreasingFailure(e3(), 3);
   }
 
   // Unconditional setCount size decreases:
@@ -249,7 +249,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_oneToZero_supported() {
-    assertSetCount(samples.e0, 0);
+    assertSetCount(e0(), 0);
   }
 
   @CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -258,7 +258,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountOneToZeroConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertSetCount(samples.e0, 0);
+      assertSetCount(e0(), 0);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -272,7 +272,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   public void testSetCountOneToZeroConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
-      assertSetCount(samples.e0, 0);
+      assertSetCount(e0(), 0);
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -284,34 +284,34 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_threeToZero_supported() {
     initThreeCopies();
-    assertSetCount(samples.e0, 0);
+    assertSetCount(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_threeToOne_supported() {
     initThreeCopies();
-    assertSetCount(samples.e0, 1);
+    assertSetCount(e0(), 1);
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_oneToZero_unsupported() {
-    assertSetCountDecreasingFailure(samples.e0, 0);
+    assertSetCountDecreasingFailure(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_threeToZero_unsupported() {
     initThreeCopies();
-    assertSetCountDecreasingFailure(samples.e0, 0);
+    assertSetCountDecreasingFailure(e0(), 0);
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_threeToOne_unsupported() {
     initThreeCopies();
-    assertSetCountDecreasingFailure(samples.e0, 1);
+    assertSetCountDecreasingFailure(e0(), 1);
   }
 
   // setCount with nulls:
@@ -370,7 +370,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testSetCount_negative_removeSupported() {
     try {
-      setCountNoCheckReturnValue(samples.e3, -1);
+      setCountNoCheckReturnValue(e3(), -1);
       fail("calling setCount() with a negative count should throw "
           + "IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
@@ -380,7 +380,7 @@ public abstract class AbstractMultisetSetCountTester<E>
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testSetCount_negative_removeUnsupported() {
     try {
-      setCountNoCheckReturnValue(samples.e3, -1);
+      setCountNoCheckReturnValue(e3(), -1);
       fail("calling setCount() with a negative count should throw "
           + "IllegalArgumentException or UnsupportedOperationException");
     } catch (IllegalArgumentException expected) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
index c4317d1..f9c4f52 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
@@ -33,6 +33,6 @@ public class AbstractMultisetTester<E> extends AbstractCollectionTester<E> {
 
   protected void initThreeCopies() {
     collection =
-        getSubjectGenerator().create(samples.e0, samples.e0, samples.e0);
+        getSubjectGenerator().create(e0(), e0(), e0());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
index fc850e5..eb055fe 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
@@ -21,6 +21,7 @@ import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.Maps;
 
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -52,4 +53,10 @@ public class BiMapGenerators {
       return ImmutableBiMap.copyOf(builder);
     }
   }
+  
+  public static class ImmutableBiMapCopyOfEntriesGenerator extends TestStringBiMapGenerator {
+    @Override protected BiMap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableBiMap.copyOf(Arrays.asList(entries));
+    }
+  }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
index 8c31aa3..1f017e6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
@@ -34,66 +34,53 @@ public class BiMapPutTester<K, V> extends AbstractBiMapTester<K, V> {
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(ZERO)
   public void testPutWithSameValueFails() {
-    K k0 = samples.e0.getKey();
-    K k1 = samples.e1.getKey();
-    V v0 = samples.e0.getValue();
-    getMap().put(k0, v0);
+    getMap().put(k0(), v0());
     try {
-      getMap().put(k1, v0);
+      getMap().put(k1(), v0());
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
       // success
     }
     // verify that the bimap is unchanged
-    expectAdded(samples.e0);
+    expectAdded(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(ZERO)
   public void testPutPresentKeyDifferentValue() {
-    K k0 = samples.e0.getKey();
-    V v0 = samples.e0.getValue();
-    V v1 = samples.e1.getValue();
-    getMap().put(k0, v0);
-    getMap().put(k0, v1);
+    getMap().put(k0(), v0());
+    getMap().put(k0(), v1());
     // verify that the bimap is changed, and that the old inverse mapping 
     // from v1 -> v0 is deleted
-    expectContents(Helpers.mapEntry(k0, v1));
+    expectContents(Helpers.mapEntry(k0(), v1()));
   }
   
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(ZERO)
   public void putDistinctKeysDistinctValues() {
-    getMap().put(samples.e0.getKey(), samples.e0.getValue());
-    getMap().put(samples.e1.getKey(), samples.e1.getValue());
-    expectAdded(samples.e0, samples.e1);
+    getMap().put(k0(), v0());
+    getMap().put(k1(), v1());
+    expectAdded(e0(), e1());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(ZERO)
   public void testForcePutOverwritesOldValueEntry() {
-    K k0 = samples.e0.getKey();
-    K k1 = samples.e1.getKey();
-    V v0 = samples.e0.getValue();
-    getMap().put(k0, v0);
-    getMap().forcePut(k1, v0);
+    getMap().put(k0(), v0());
+    getMap().forcePut(k1(), v0());
     // verify that the bimap is unchanged
-    expectAdded(Helpers.mapEntry(k1, v0));
+    expectAdded(Helpers.mapEntry(k1(), v0()));
   }
   
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(ZERO)
   public void testInversePut() {
-    K k0 = samples.e0.getKey();
-    V v0 = samples.e0.getValue();
-    K k1 = samples.e1.getKey();
-    V v1 = samples.e1.getValue();
-    getMap().put(k0, v0);
-    getMap().inverse().put(v1, k1);
-    expectAdded(samples.e0, samples.e1);
+    getMap().put(k0(), v0());
+    getMap().inverse().put(v1(), k1());
+    expectAdded(e0(), e1());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
index 4f875a0..8ba0ede 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
@@ -38,48 +38,48 @@ public class BiMapRemoveTester<K, V> extends AbstractBiMapTester<K, V> {
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveKeyRemovesFromInverse() {
-    getMap().remove(samples.e0.getKey());
-    expectMissing(samples.e0);
+    getMap().remove(k0());
+    expectMissing(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveKeyFromKeySetRemovesFromInverse() {
-    getMap().keySet().remove(samples.e0.getKey());
-    expectMissing(samples.e0);
+    getMap().keySet().remove(k0());
+    expectMissing(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveFromValuesRemovesFromInverse() {
-    getMap().values().remove(samples.e0.getValue());
-    expectMissing(samples.e0);
+    getMap().values().remove(v0());
+    expectMissing(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveFromInverseRemovesFromForward() {
-    getMap().inverse().remove(samples.e0.getValue());
-    expectMissing(samples.e0);
+    getMap().inverse().remove(v0());
+    expectMissing(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveFromInverseKeySetRemovesFromForward() {
-    getMap().inverse().keySet().remove(samples.e0.getValue());
-    expectMissing(samples.e0);
+    getMap().inverse().keySet().remove(v0());
+    expectMissing(e0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveFromInverseValuesRemovesFromInverse() {
-    getMap().inverse().values().remove(samples.e0.getKey());
-    expectMissing(samples.e0);
+    getMap().inverse().values().remove(k0());
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
index 037231b..67d0fea 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
@@ -135,7 +135,7 @@ public class BiMapTestSuiteBuilder<K, V>
     return inverseFeatures;
   }
 
-  // TODO(user): can we eliminate the duplication from MapTestSuiteBuilder here?
+  // TODO(lowasser): can we eliminate the duplication from MapTestSuiteBuilder here?
 
   private static Set<Feature<?>> computeValuesSetFeatures(
       Set<Feature<?>> mapFeatures) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
index e385bf9..9dec389 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
@@ -100,8 +100,8 @@ public final class DerivedGoogleCollectionGenerators {
     @Override
     public SampleElements<Map.Entry<V, K>> samples() {
       SampleElements<Entry<K, V>> samples = generator.samples();
-      return new SampleElements<Map.Entry<V, K>>(reverse(samples.e0), reverse(samples.e1),
-          reverse(samples.e2), reverse(samples.e3), reverse(samples.e4));
+      return new SampleElements<Map.Entry<V, K>>(reverse(samples.e0()), reverse(samples.e1()),
+          reverse(samples.e2()), reverse(samples.e3()), reverse(samples.e4()));
     }
 
     private Map.Entry<V, K> reverse(Map.Entry<K, V> entry) {
@@ -158,11 +158,11 @@ public final class DerivedGoogleCollectionGenerators {
       final SampleElements<Map.Entry<K, V>> mapSamples =
           this.mapGenerator.samples();
       this.samples = new SampleElements<V>(
-          mapSamples.e0.getValue(),
-          mapSamples.e1.getValue(),
-          mapSamples.e2.getValue(),
-          mapSamples.e3.getValue(),
-          mapSamples.e4.getValue());
+          mapSamples.e0().getValue(),
+          mapSamples.e1().getValue(),
+          mapSamples.e2().getValue(),
+          mapSamples.e3().getValue(),
+          mapSamples.e4().getValue());
     }
 
     @Override
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
similarity index 61%
copy from guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
copy to guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
index ee703d8..cf856fa 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -16,20 +16,24 @@
 
 package com.google.common.collect.testing.google;
 
+import static junit.framework.Assert.fail;
+
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.SortedSetMultimap;
+import com.google.common.collect.Multimap;
 
 /**
- * Tester for {@link SortedSetMultimap#get(Object)}.
+ * Helper methods/assertions for use with {@code com.google.common.collect} types.
  *
- * @author Louis Wasserman
+ * @author Colin Decker
  */
 @GwtCompatible
-public class SortedSetMultimapGetTester<K, V>
-    extends AbstractMultimapTester<K, V, SortedSetMultimap<K, V>> {
-  public void testValueComparator() {
-    assertEquals(
-        multimap().valueComparator(),
-        multimap().get(sampleKeys().e0).comparator());
+final class GoogleHelpers {
+
+  private GoogleHelpers() {}
+
+  static void assertEmpty(Multimap<?, ?> multimap) {
+    if (!multimap.isEmpty()) {
+      fail("Not true that " + multimap + " is empty");
+    }
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
index ab18c2c..bd3b11d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
@@ -67,12 +67,12 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
   @CollectionSize.Require(SEVERAL)
   public void testEquals() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Map<K, Collection<V>> expected = Maps.newHashMap();
-    expected.put(sampleKeys().e0, Lists.newArrayList(sampleValues().e0, sampleValues().e3));
-    expected.put(sampleKeys().e1, Lists.newArrayList(sampleValues().e0));
+    expected.put(k0(), Lists.newArrayList(v0(), v3()));
+    expected.put(k1(), Lists.newArrayList(v0()));
     new EqualsTester()
         .addEqualityGroup(expected, multimap().asMap())
         .testEquals();
@@ -81,16 +81,16 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
   @CollectionSize.Require(SEVERAL)
   public void testEntrySetEquals() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Set<Entry<K, Collection<V>>> expected = Sets.newHashSet();
     expected.add(Helpers.mapEntry(
-        sampleKeys().e0, 
-        (Collection<V>) Lists.newArrayList(sampleValues().e0, sampleValues().e3)));
+        k0(), 
+        (Collection<V>) Lists.newArrayList(v0(), v3())));
     expected.add(Helpers.mapEntry(
-        sampleKeys().e1, 
-        (Collection<V>) Lists.newArrayList(sampleValues().e0)));
+        k1(), 
+        (Collection<V>) Lists.newArrayList(v0())));
     new EqualsTester()
         .addEqualityGroup(expected, multimap().asMap().entrySet())
         .testEquals();
@@ -100,14 +100,14 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testValuesRemove() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-    assertTrue(multimap().asMap().values().remove(Collections.singletonList(sampleValues().e0)));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
+    assertTrue(multimap().asMap().values().remove(Collections.singletonList(v0())));
     assertEquals(2, multimap().size());
     assertEquals(
         Collections.singletonMap(
-            sampleKeys().e0, Lists.newArrayList(sampleValues().e0, sampleValues().e3)),
+            k0(), Lists.newArrayList(v0(), v3())),
         multimap().asMap());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
index 31c4611..3b22a0c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
@@ -32,13 +32,13 @@ public class ListMultimapEqualsTester<K, V> extends AbstractListMultimapTester<K
   @CollectionSize.Require(SEVERAL)
   public void testOrderingAffectsEqualsComparisons() {
     ListMultimap<K, V> multimap1 = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v0()));
     ListMultimap<K, V> multimap2 = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v0()));
     new EqualsTester()
         .addEqualityGroup(multimap1)
         .addEqualityGroup(multimap2)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
index 9a3c966..4cf0d04 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
@@ -35,9 +35,9 @@ public class ListMultimapPutAllTester<K, V> extends AbstractListMultimapTester<K
   public void testPutAllAddsAtEndInOrder() {
     @SuppressWarnings("unchecked")
     List<V> values = Arrays.asList(
-        sampleValues().e3,
-        sampleValues().e1,
-        sampleValues().e4);
+        v3(),
+        v1(),
+        v4());
 
     for (K k : sampleKeys()) {
       resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
index e84e4bb..eb8d190 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
@@ -14,11 +14,11 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
 import static com.google.common.collect.testing.Helpers.copyToList;
 import static com.google.common.collect.testing.Helpers.mapEntry;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ListMultimap;
@@ -41,33 +41,27 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(SEVERAL)
   public void testMultimapRemoveDeletesFirstOccurrence() {
-    K k = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-    V v1 = sampleValues().e2;
-    resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
-
-    List<V> list = multimap().get(k);
-    multimap().remove(k, v0);
-    assertThat(list).has().exactly(v1, v0).inOrder();
+    resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
+
+    List<V> list = multimap().get(k0());
+    multimap().remove(k0(), v0());
+    assertContentsInOrder(list, v1(), v0());
   }
 
   @SuppressWarnings("unchecked")
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(SEVERAL)
   public void testRemoveAtIndexFromGetPropagates() {
-    K k = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-    V v1 = sampleValues().e2;
-    List<V> values = Arrays.asList(v0, v1, v0);
+    List<V> values = Arrays.asList(v0(), v1(), v0());
 
     for (int i = 0; i < 3; i++) {
-      resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+      resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
       List<V> expectedValues = copyToList(values);
 
-      multimap().get(k).remove(i);
+      multimap().get(k0()).remove(i);
       expectedValues.remove(i);
 
-      assertGet(k, expectedValues);
+      assertGet(k0(), expectedValues);
     }
   }
 
@@ -75,20 +69,17 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(SEVERAL)
   public void testRemoveAtIndexFromAsMapPropagates() {
-    K k = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-    V v1 = sampleValues().e2;
-    List<V> values = Arrays.asList(v0, v1, v0);
+    List<V> values = Arrays.asList(v0(), v1(), v0());
 
     for (int i = 0; i < 3; i++) {
-      resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+      resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
       List<V> expectedValues = copyToList(values);
 
-      List<V> asMapValue = (List<V>) multimap().asMap().get(k);
+      List<V> asMapValue = (List<V>) multimap().asMap().get(k0());
       asMapValue.remove(i);
       expectedValues.remove(i);
 
-      assertGet(k, expectedValues);
+      assertGet(k0(), expectedValues);
     }
   }
 
@@ -96,13 +87,10 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(SEVERAL)
   public void testRemoveAtIndexFromAsMapEntrySetPropagates() {
-    K k = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-    V v1 = sampleValues().e2;
-    List<V> values = Arrays.asList(v0, v1, v0);
+    List<V> values = Arrays.asList(v0(), v1(), v0());
 
     for (int i = 0; i < 3; i++) {
-      resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+      resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
       List<V> expectedValues = copyToList(values);
 
       Map.Entry<K, Collection<V>> asMapEntry = multimap().asMap().entrySet().iterator().next();
@@ -110,7 +98,7 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
       asMapValue.remove(i);
       expectedValues.remove(i);
 
-      assertGet(k, expectedValues);
+      assertGet(k0(), expectedValues);
     }
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
index b7551af..640b256 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
@@ -35,9 +35,9 @@ public class ListMultimapReplaceValuesTester<K, V> extends AbstractListMultimapT
   public void testReplaceValuesPreservesOrder() {
     @SuppressWarnings("unchecked")
     List<V> values = Arrays.asList(
-        sampleValues().e3,
-        sampleValues().e1,
-        sampleValues().e4);
+        v3(),
+        v1(),
+        v4());
 
     for (K k : sampleKeys()) {
       resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
index 090eed9..b71ae5b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
@@ -31,6 +31,7 @@ import com.google.common.collect.testing.TestStringMapGenerator;
 import com.google.common.collect.testing.TestUnhashableCollectionGenerator;
 import com.google.common.collect.testing.UnhashableObject;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumMap;
 import java.util.List;
@@ -66,6 +67,13 @@ public class MapGenerators {
       return ImmutableMap.copyOf(builder);
     }
   }
+  
+  public static class ImmutableMapCopyOfEntriesGenerator
+      extends TestStringMapGenerator {
+    @Override protected Map<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableMap.copyOf(Arrays.asList(entries));
+    }
+  }
 
   public static class ImmutableMapUnhashableValuesGenerator
       extends TestUnhashableCollectionGenerator<Collection<UnhashableObject>> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
index 88e576e..da5fbb5 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
@@ -16,13 +16,14 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -39,56 +40,56 @@ import java.util.Collection;
  */
 @GwtCompatible
 public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
-  
+
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testPropagatesRemoveToMultimap() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
-    assertTrue(result.remove(sampleValues().e0));
-    assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()),
+        Helpers.mapEntry(k0(), v2()));
+    Collection<V> result = multimap().asMap().get(k0());
+    assertTrue(result.remove(v0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
     assertEquals(2, multimap().size());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testPropagatesRemoveLastElementToMultimap() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
-    assertTrue(result.remove(sampleValues().e0));
-    assertGet(sampleKeys().e0);
+    Collection<V> result = multimap().asMap().get(k0());
+    assertTrue(result.remove(v0()));
+    assertGet(k0());
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testPropagatesClearToMultimap() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+    Collection<V> result = multimap().asMap().get(k0());
     result.clear();
-    assertGet(sampleKeys().e0);
-    assertThat(result).isEmpty();
+    assertGet(k0());
+    assertEmpty(result);
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   public void testAddNullValue() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+    Collection<V> result = multimap().asMap().get(k0());
     assertTrue(result.add(null));
-    assertTrue(multimap().containsEntry(sampleKeys().e0, null));
+    assertTrue(multimap().containsEntry(k0(), null));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUE_QUERIES})
   public void testRemoveNullValue() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+    Collection<V> result = multimap().asMap().get(k0());
     assertFalse(result.remove(null));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
   public void testAddNullValueUnsupported() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+    Collection<V> result = multimap().asMap().get(k0());
     try {
       result.add(null);
       fail("Expected NullPointerException");
@@ -98,10 +99,11 @@ public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, M
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPropagatesAddToMultimap() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
-    result.add(sampleValues().e3);
-    assertThat(multimap().get(sampleKeys().e0))
-        .has().exactly(sampleValues().e0, sampleValues().e3);
+    Collection<V> result = multimap().asMap().get(k0());
+    result.add(v3());
+    assertContentsAnyOrder(
+        multimap().get(k0()),
+        v0(), v3());
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -109,35 +111,29 @@ public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, M
   public void testPropagatesRemoveThenAddToMultimap() {
     int oldSize = getNumElements();
 
-    K k0 = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-
-    Collection<V> result = multimap().asMap().get(k0);
-    assertTrue(result.remove(v0));
+    Collection<V> result = multimap().asMap().get(k0());
+    assertTrue(result.remove(v0()));
 
-    assertFalse(multimap().containsKey(k0));
-    assertFalse(multimap().containsEntry(k0, v0));
-    assertThat(result).isEmpty();
+    assertFalse(multimap().containsKey(k0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
+    assertEmpty(result);
 
-    V v1 = sampleValues().e1;
-    V v2 = sampleValues().e2;
+    assertTrue(result.add(v1()));
+    assertTrue(result.add(v2()));
 
-    assertTrue(result.add(v1));
-    assertTrue(result.add(v2));
-
-    assertThat(result).has().exactly(v1, v2);
-    assertThat(multimap().get(k0)).has().exactly(v1, v2);
-    assertTrue(multimap().containsKey(k0));
-    assertFalse(multimap().containsEntry(k0, v0));
-    assertTrue(multimap().containsEntry(k0, v2));
+    assertContentsAnyOrder(result, v1(), v2());
+    assertContentsAnyOrder(multimap().get(k0()), v1(), v2());
+    assertTrue(multimap().containsKey(k0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
+    assertTrue(multimap().containsEntry(k0(), v2()));
     assertEquals(oldSize + 1, multimap().size());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testReflectsMultimapRemove() {
-    Collection<V> result = multimap().asMap().get(sampleKeys().e0);
-    multimap().removeAll(sampleKeys().e0);
-    assertThat(result).isEmpty();
+    Collection<V> result = multimap().asMap().get(k0());
+    multimap().removeAll(k0());
+    assertEmpty(result);
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
index b18f35b..0d0eb0d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
@@ -14,6 +14,9 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
@@ -21,7 +24,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Iterables;
@@ -56,25 +58,24 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
 
       Collection<V> collection = multimap().asMap().get(key);
       if (expectedValues.isEmpty()) {
-        assertThat(collection).isNull();
+        assertNull(collection);
       } else {
-        assertThat(collection).has().exactlyAs(expectedValues);
+        assertEqualIgnoringOrder(expectedValues, collection);
       }
     }
   }
- 
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(ALLOWS_NULL_KEYS)
   public void testAsMapGetNullKeyPresent() {
     initMultimapWithNullKey();
-    assertThat(multimap().asMap().get(null)).has().exactly(getValueForNullKey());
+    assertContentsAnyOrder(multimap().asMap().get(null), getValueForNullKey());
   }
- 
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
   public void testAsMapGetNullKeyAbsent() {
-    assertThat(multimap().asMap().get(null)).isNull();
+    assertNull(multimap().asMap().get(null));
   }
- 
+
   @MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
   public void testAsMapGetNullKeyUnsupported() {
     try {
@@ -82,12 +83,12 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {}
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testAsMapRemove() {
-    assertThat(multimap().asMap().remove(sampleKeys().e0)).iteratesAs(sampleValues().e0);
-    assertGet(sampleKeys().e0);
+    assertContentsInOrder(multimap().asMap().remove(k0()), v0());
+    assertGet(k0());
     assertEquals(getNumElements() - 1, multimap().size());
   }
 
@@ -95,27 +96,25 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
   @MapFeature.Require(SUPPORTS_PUT)
   public void testAsMapEntrySetReflectsPutSameKey() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-    
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()));
+
     Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
     Collection<V> valueCollection = Iterables.getOnlyElement(asMapEntrySet).getValue();
-    assertThat(valueCollection)
-        .has().exactly(sampleValues().e0, sampleValues().e3);
-    assertTrue(multimap().put(sampleKeys().e0, sampleValues().e4));
-    assertThat(valueCollection)
-        .has().exactly(sampleValues().e0, sampleValues().e3, sampleValues().e4);
+    assertContentsAnyOrder(valueCollection, v0(), v3());
+    assertTrue(multimap().put(k0(), v4()));
+    assertContentsAnyOrder(valueCollection, v0(), v3(), v4());
   }
 
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testAsMapEntrySetReflectsPutDifferentKey() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-    
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()));
+
     Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
-    assertTrue(multimap().put(sampleKeys().e1, sampleValues().e4));
+    assertTrue(multimap().put(k1(), v4()));
     assertEquals(2, asMapEntrySet.size());
   }
 
@@ -123,22 +122,22 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testAsMapEntrySetRemovePropagatesToMultimap() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
     Entry<K, Collection<V>> asMapEntry0 = Iterables.getOnlyElement(asMapEntrySet);
-    assertTrue(multimap().put(sampleKeys().e1, sampleValues().e4));
+    assertTrue(multimap().put(k1(), v4()));
     assertTrue(asMapEntrySet.remove(asMapEntry0));
     assertEquals(1, multimap().size());
-    assertThat(multimap().keySet()).iteratesAs(sampleKeys().e1);
+    assertContentsInOrder(multimap().keySet(), k1());
   }
 
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
   public void testAsMapEntrySetIteratorRemovePropagatesToMultimap() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
     Iterator<Entry<K, Collection<V>>> asMapEntryItr = asMapEntrySet.iterator();
     asMapEntryItr.next();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
index 5c25fe4..1aa661a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
@@ -16,9 +16,10 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.google.GoogleHelpers.assertEmpty;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -47,54 +48,54 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
 
   private void assertCleared() {
     assertEquals(0, multimap().size());
-    assertTrue(multimap().isEmpty());
+    assertEmpty(multimap());
     assertEquals(multimap(), getSubjectGenerator().create());
-    assertThat(multimap().entries()).isEmpty();
-    assertThat(multimap().asMap()).isEmpty();
-    assertThat(multimap().keySet()).isEmpty();
-    assertThat(multimap().keys()).isEmpty();
-    assertThat(multimap().values()).isEmpty();
+    assertEmpty(multimap().entries());
+    assertEmpty(multimap().asMap());
+    assertEmpty(multimap().keySet());
+    assertEmpty(multimap().keys());
+    assertEmpty(multimap().values());
     for (K key : sampleKeys()) {
       assertGet(key);
     }
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClear() {
     multimap().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearThroughEntries() {
     multimap().entries().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearThroughAsMap() {
     multimap().asMap().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearThroughKeySet() {
     multimap().keySet().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearThroughKeys() {
     multimap().keys().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearThroughValues() {
     multimap().values().clear();
     assertCleared();
   }
-  
+
   @MapFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testClearPropagatesToGet() {
@@ -102,7 +103,7 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
       resetContainer();
       Collection<V> collection = multimap().get(key);
       multimap().clear();
-      assertThat(collection).isEmpty();
+      assertEmpty(collection);
     }
   }
 
@@ -114,7 +115,7 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
       Collection<V> collection = multimap().asMap().get(key);
       if (collection != null) {
         multimap().clear();
-        assertThat(collection).isEmpty();
+        assertEmpty(collection);
       }
     }
   }
@@ -123,13 +124,13 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
   public void testClearPropagatesToAsMap() {
     Map<K, Collection<V>> asMap = multimap().asMap();
     multimap().clear();
-    assertThat(asMap).isEmpty();
+    assertEmpty(asMap);
   }
 
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testClearPropagatesToEntries() {
     Collection<Entry<K, V>> entries = multimap().entries();
     multimap().clear();
-    assertThat(entries).isEmpty();
+    assertEmpty(entries);
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
index 91bcd44..ab65e4c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
@@ -37,11 +37,11 @@ public class MultimapContainsEntryTester<K, V>
     extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   @CollectionSize.Require(absent = ZERO)
   public void testContainsEntryYes() {
-    assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+    assertTrue(multimap().containsEntry(k0(), v0()));
   }
 
   public void testContainsEntryNo() {
-    assertFalse(multimap().containsEntry(sampleKeys().e3, sampleValues().e3));
+    assertFalse(multimap().containsEntry(k3(), v3()));
   }
 
   public void testContainsEntryAgreesWithGet() {
@@ -68,7 +68,7 @@ public class MultimapContainsEntryTester<K, V>
   @MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
   public void testContainsEntryNullDisallowedBecauseKeyQueriesDisallowed() {
     try {
-      multimap().containsEntry(null, sampleValues().e3);
+      multimap().containsEntry(null, v3());
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {
       // success
@@ -82,7 +82,7 @@ public class MultimapContainsEntryTester<K, V>
   @MapFeature.Require(absent = ALLOWS_NULL_VALUE_QUERIES)
   public void testContainsEntryNullDisallowedBecauseValueQueriesDisallowed() {
     try {
-      multimap().containsEntry(sampleKeys().e3, null);
+      multimap().containsEntry(k3(), null);
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {
       // success
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
index 958af87..07e69bc 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
@@ -35,11 +35,11 @@ public class MultimapContainsKeyTester<K, V>
     extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   @CollectionSize.Require(absent = ZERO)
   public void testContainsKeyYes() {
-    assertTrue(multimap().containsKey(sampleKeys().e0));
+    assertTrue(multimap().containsKey(k0()));
   }
 
   public void testContainsKeyNo() {
-    assertFalse(multimap().containsKey(sampleKeys().e3));
+    assertFalse(multimap().containsKey(k3()));
   }
 
   public void testContainsKeysFromKeySet() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
index 7ccaa41..a201d5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
@@ -35,11 +35,11 @@ public class MultimapContainsValueTester<K, V>
     extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   @CollectionSize.Require(absent = ZERO)
   public void testContainsValueYes() {
-    assertTrue(multimap().containsValue(sampleValues().e0));
+    assertTrue(multimap().containsValue(v0()));
   }
 
   public void testContainsValueNo() {
-    assertFalse(multimap().containsValue(sampleValues().e3));
+    assertFalse(multimap().containsValue(v3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
index c815631..f51ea75 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
@@ -14,6 +14,8 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContains;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.ONE;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
@@ -22,7 +24,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -43,79 +44,77 @@ import java.util.Map.Entry;
 @GwtCompatible
 public class MultimapEntriesTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   public void testEntries() {
-    assertThat(multimap().entries()).has().exactlyAs(getSampleElements());
+    assertEqualIgnoringOrder(getSampleElements(), multimap().entries());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(ALLOWS_NULL_KEYS)
   public void testContainsEntryWithNullKeyPresent() {
     initMultimapWithNullKey();
-    assertThat(multimap().entries()).has().allOf(
-        Helpers.mapEntry((K) null, getValueForNullKey()));
+    assertContains(multimap().entries(), Helpers.mapEntry((K) null, getValueForNullKey()));
   }
-  
+
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
   public void testContainsEntryWithNullKeyAbsent() {
-    assertFalse(multimap().entries().contains(Helpers.mapEntry(null, sampleValues().e0)));
+    assertFalse(multimap().entries().contains(Helpers.mapEntry(null, v0())));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(ALLOWS_NULL_VALUES)
   public void testContainsEntryWithNullValuePresent() {
     initMultimapWithNullValue();
-    assertThat(multimap().entries()).has().allOf(
-        Helpers.mapEntry(getKeyForNullValue(), (V) null));
+    assertContains(multimap().entries(), Helpers.mapEntry(getKeyForNullValue(), (V) null));
   }
-  
+
   @MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
   public void testContainsEntryWithNullValueAbsent() {
     assertFalse(multimap().entries().contains(
-        Helpers.mapEntry(sampleKeys().e0, null)));
+        Helpers.mapEntry(k0(), null)));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemovePropagatesToMultimap() {
     assertTrue(multimap().entries().remove(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)));
-    expectMissing(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0())));
+    expectMissing(Helpers.mapEntry(k0(), v0()));
     assertEquals(getNumElements() - 1, multimap().size());
-    assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+    assertFalse(multimap().containsEntry(k0(), v0()));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllPropagatesToMultimap() {
     assertTrue(multimap().entries().removeAll(
-        Collections.singleton(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0))));
-    expectMissing(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+        Collections.singleton(Helpers.mapEntry(k0(), v0()))));
+    expectMissing(Helpers.mapEntry(k0(), v0()));
     assertEquals(getNumElements() - 1, multimap().size());
-    assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+    assertFalse(multimap().containsEntry(k0(), v0()));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRetainAllPropagatesToMultimap() {
     multimap().entries().retainAll(
-        Collections.singleton(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)));
+        Collections.singleton(Helpers.mapEntry(k0(), v0())));
     assertEquals(
-        getSubjectGenerator().create(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)),
+        getSubjectGenerator().create(Helpers.mapEntry(k0(), v0())),
         multimap());
     assertEquals(1, multimap().size());
-    assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+    assertTrue(multimap().containsEntry(k0(), v0()));
   }
-  
+
   @CollectionSize.Require(ONE)
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
   public void testIteratorRemovePropagatesToMultimap() {
     Iterator<Entry<K, V>> iterator = multimap().entries().iterator();
     assertEquals(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
+        Helpers.mapEntry(k0(), v0()),
         iterator.next());
     iterator.remove();
     assertTrue(multimap().isEmpty());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testEntriesRemainValidAfterRemove() {
@@ -128,4 +127,3 @@ public class MultimapEntriesTester<K, V> extends AbstractMultimapTester<K, V, Mu
     assertEquals(value, entry.getValue());
   }
 }
-
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
index 5d66f4e..6eb1ca7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
@@ -44,7 +44,7 @@ public class MultimapEqualsTester<K, V> extends AbstractMultimapTester<K, V, Mul
 
   public void testEqualsFalse() {
     List<Entry<K, V>> targetEntries = new ArrayList<Entry<K, V>>(getSampleElements());
-    targetEntries.add(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+    targetEntries.add(Helpers.mapEntry(k0(), v3()));
     new EqualsTester()
         .addEqualityGroup(multimap())
         .addEqualityGroup(getSubjectGenerator().create(targetEntries.toArray()))
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
index 1dc82d6..b6010c0 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
@@ -15,7 +15,9 @@
  */
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContains;
 import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
@@ -23,7 +25,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -42,71 +43,71 @@ import java.util.Collections;
 @GwtCompatible
 public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   public void testGetEmpty() {
-    Collection<V> result = multimap().get(sampleKeys().e3);
-    assertTrue(result.isEmpty());
+    Collection<V> result = multimap().get(k3());
+    assertEmpty(result);
     assertEquals(0, result.size());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   public void testGetNonEmpty() {
-    Collection<V> result = multimap().get(sampleKeys().e0);
+    Collection<V> result = multimap().get(k0());
     assertFalse(result.isEmpty());
-    assertContentsAnyOrder(result, sampleValues().e0);
+    assertContentsAnyOrder(result, v0());
   }
 
   @CollectionSize.Require(SEVERAL)
   public void testGetMultiple() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
-    assertGet(sampleKeys().e0,
-        sampleValues().e0,
-        sampleValues().e1,
-        sampleValues().e2);
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v2()));
+    assertGet(k0(),
+        v0(),
+        v1(),
+        v2());
   }
-  
+
   public void testGetAbsentKey() {
-    assertGet(sampleKeys().e4);
+    assertGet(k4());
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testPropagatesRemoveToMultimap() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
-    Collection<V> result = multimap().get(sampleKeys().e0);
-    assertTrue(result.remove(sampleValues().e0));
-    assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v3()),
+        Helpers.mapEntry(k0(), v2()));
+    Collection<V> result = multimap().get(k0());
+    assertTrue(result.remove(v0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
     assertEquals(2, multimap().size());
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testPropagatesRemoveLastElementToMultimap() {
-    Collection<V> result = multimap().get(sampleKeys().e0);
-    assertTrue(result.remove(sampleValues().e0));
-    assertGet(sampleKeys().e0);
-  }  
+    Collection<V> result = multimap().get(k0());
+    assertTrue(result.remove(v0()));
+    assertGet(k0());
+  }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPropagatesAddToMultimap() {
-    Collection<V> result = multimap().get(sampleKeys().e0);
-    assertTrue(result.add(sampleValues().e3));
-    assertTrue(multimap().containsKey(sampleKeys().e0));
+    Collection<V> result = multimap().get(k0());
+    assertTrue(result.add(v3()));
+    assertTrue(multimap().containsKey(k0()));
     assertEquals(getNumElements() + 1, multimap().size());
-    assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
+    assertTrue(multimap().containsEntry(k0(), v3()));
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPropagatesAddAllToMultimap() {
-    Collection<V> result = multimap().get(sampleKeys().e0);
-    assertTrue(result.addAll(Collections.singletonList(sampleValues().e3)));
-    assertTrue(multimap().containsKey(sampleKeys().e0));
+    Collection<V> result = multimap().get(k0());
+    assertTrue(result.addAll(Collections.singletonList(v3())));
+    assertTrue(multimap().containsKey(k0()));
     assertEquals(getNumElements() + 1, multimap().size());
-    assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
+    assertTrue(multimap().containsEntry(k0(), v3()));
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -114,27 +115,21 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
   public void testPropagatesRemoveLastThenAddToMultimap() {
     int oldSize = getNumElements();
 
-    K k0 = sampleKeys().e0;
-    V v0 = sampleValues().e0;
-
-    Collection<V> result = multimap().get(k0);
-    assertTrue(result.remove(v0));
-
-    assertFalse(multimap().containsKey(k0));
-    assertFalse(multimap().containsEntry(k0, v0));
-    assertThat(result).isEmpty();
+    Collection<V> result = multimap().get(k0());
+    assertTrue(result.remove(v0()));
 
-    V v1 = sampleValues().e1;
-    V v2 = sampleValues().e2;
+    assertFalse(multimap().containsKey(k0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
+    assertEmpty(result);
 
-    assertTrue(result.add(v1));
-    assertTrue(result.add(v2));
+    assertTrue(result.add(v1()));
+    assertTrue(result.add(v2()));
 
-    assertThat(result).has().exactly(v1, v2);
-    assertThat(multimap().get(k0)).has().exactly(v1, v2);
-    assertTrue(multimap().containsKey(k0));
-    assertFalse(multimap().containsEntry(k0, v0));
-    assertTrue(multimap().containsEntry(k0, v2));
+    assertContentsAnyOrder(result, v1(), v2());
+    assertContentsAnyOrder(multimap().get(k0()), v1(), v2());
+    assertTrue(multimap().containsKey(k0()));
+    assertFalse(multimap().containsEntry(k0(), v0()));
+    assertTrue(multimap().containsEntry(k0(), v2()));
     assertEquals(oldSize + 1, multimap().size());
   }
 
@@ -142,12 +137,12 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
   @CollectionSize.Require(absent = ZERO)
   public void testGetNullPresent() {
     initMultimapWithNullKey();
-    assertThat(multimap().get(null)).has().item(getValueForNullKey());
+    assertContains(multimap().get(null), getValueForNullKey());
   }
 
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
   public void testGetNullAbsent() {
-    assertThat(multimap().get(null)).isEmpty();
+    assertEmpty(multimap().get(null));
   }
 
   @MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
@@ -164,7 +159,6 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
   @CollectionSize.Require(absent = ZERO)
   public void testGetWithNullValue() {
     initMultimapWithNullValue();
-    assertThat(multimap().get(getKeyForNullValue()))
-        .has().item(null);
+    assertContains(multimap().get(getKeyForNullValue()), null);
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
index 6ccb993..fe7f143 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
@@ -56,23 +56,23 @@ public class MultimapKeySetTester<K, V> extends AbstractMultimapTester<K, V, Mul
   
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testKeySetRemovePropagatesToMultimap() {
-    int key0Count = multimap().get(sampleKeys().e0).size();
-    assertEquals(key0Count > 0, multimap().keySet().remove(sampleKeys().e0));
+    int key0Count = multimap().get(k0()).size();
+    assertEquals(key0Count > 0, multimap().keySet().remove(k0()));
     assertEquals(getNumElements() - key0Count, multimap().size());
-    assertGet(sampleKeys().e0);
+    assertGet(k0());
   }
   
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
   public void testKeySetIteratorRemove() {
-    int key0Count = multimap().get(sampleKeys().e0).size();
+    int key0Count = multimap().get(k0()).size();
     Iterator<K> keyItr = multimap().keySet().iterator();
     while (keyItr.hasNext()) {
-      if (keyItr.next().equals(sampleKeys().e0)) {
+      if (keyItr.next().equals(k0())) {
         keyItr.remove();
       }
     }
     assertEquals(getNumElements() - key0Count, multimap().size());
-    assertGet(sampleKeys().e0);
+    assertGet(k0());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
index b331030..3ebfd55 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
@@ -14,13 +14,13 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContainsAllOf;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.ONE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -43,72 +43,72 @@ public class MultimapKeysTester<K, V> extends AbstractMultimapTester<K, V, Multi
   @CollectionSize.Require(SEVERAL)
   public void testKeys() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k1(), v0()));
     Multiset<K> keys = multimap().keys();
-    assertEquals(2, keys.count(sampleKeys().e0));
-    assertEquals(1, keys.count(sampleKeys().e1));
+    assertEquals(2, keys.count(k0()));
+    assertEquals(1, keys.count(k1()));
     assertEquals(3, keys.size());
-    assertThat(keys).has().allOf(sampleKeys().e0, sampleKeys().e1);
-    assertThat(keys.entrySet()).has().allOf(
-        Multisets.immutableEntry(sampleKeys().e0, 2),
-        Multisets.immutableEntry(sampleKeys().e1, 1));
+    assertContainsAllOf(keys, k0(), k1());
+    assertContainsAllOf(keys.entrySet(),
+        Multisets.immutableEntry(k0(), 2),
+        Multisets.immutableEntry(k1(), 1));
   }
-  
+
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
   public void testKeysCountAbsentNullKey() {
     assertEquals(0, multimap().keys().count(null));
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(ALLOWS_NULL_KEYS)
   public void testKeysWithNullKey() {
     resetContainer(
-        Helpers.mapEntry((K) null, sampleValues().e0),
-        Helpers.mapEntry((K) null, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+        Helpers.mapEntry((K) null, v0()),
+        Helpers.mapEntry((K) null, v1()),
+        Helpers.mapEntry(k1(), v0()));
     Multiset<K> keys = multimap().keys();
     assertEquals(2, keys.count(null));
-    assertEquals(1, keys.count(sampleKeys().e1));
+    assertEquals(1, keys.count(k1()));
     assertEquals(3, keys.size());
-    assertThat(keys).has().allOf(null, sampleKeys().e1);
-    assertThat(keys.entrySet()).has().allOf(
+    assertContainsAllOf(keys, null, k1());
+    assertContainsAllOf(keys.entrySet(),
         Multisets.immutableEntry((K) null, 2),
-        Multisets.immutableEntry(sampleKeys().e1, 1));
+        Multisets.immutableEntry(k1(), 1));
   }
-  
+
   public void testKeysElementSet() {
     assertEquals(multimap().keySet(), multimap().keys().elementSet());
   }
 
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testKeysRemove() {
-    int original = multimap().keys().remove(sampleKeys().e0, 1);
-    assertEquals(Math.max(original - 1, 0), multimap().get(sampleKeys().e0).size());
+    int original = multimap().keys().remove(k0(), 1);
+    assertEquals(Math.max(original - 1, 0), multimap().get(k0()).size());
   }
-  
+
   @CollectionSize.Require(ONE)
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
   public void testKeysEntrySetIteratorRemove() {
     Multiset<K> keys = multimap().keys();
     Iterator<Multiset.Entry<K>> itr = keys.entrySet().iterator();
-    assertEquals(Multisets.immutableEntry(sampleKeys().e0, 1),
+    assertEquals(Multisets.immutableEntry(k0(), 1),
         itr.next());
     itr.remove();
     assertTrue(multimap().isEmpty());
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testKeysEntrySetRemove() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k1(), v0()));
     assertTrue(multimap().keys().entrySet().remove(
-        Multisets.immutableEntry(sampleKeys().e0, 2)));
+        Multisets.immutableEntry(k0(), 2)));
     assertEquals(1, multimap().size());
-    assertTrue(multimap().containsEntry(sampleKeys().e1, sampleValues().e0));
+    assertTrue(multimap().containsEntry(k1(), v0()));
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
index fc65e5c..b258cf1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
@@ -16,10 +16,10 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContains;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -40,59 +40,59 @@ public class MultimapPutAllMultimapTester<K, V>
   public void testPutUnsupported() {
     try {
       multimap().putAll(getSubjectGenerator().create(
-          Helpers.mapEntry(sampleKeys().e3, sampleValues().e3)));
+          Helpers.mapEntry(k3(), v3())));
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {}
   }
-  
+
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllIntoEmpty() {
     Multimap<K, V> target = getSubjectGenerator().create();
     assertEquals(!multimap().isEmpty(), target.putAll(multimap()));
-    assertEquals(multimap(), target);    
+    assertEquals(multimap(), target);
   }
-  
+
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAll() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
-        Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
+        Helpers.mapEntry(k0(), v3()),
+        Helpers.mapEntry(k3(), v3()));
     assertTrue(multimap().putAll(source));
-    assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
-    assertTrue(multimap().containsEntry(sampleKeys().e3, sampleValues().e3));
+    assertTrue(multimap().containsEntry(k0(), v3()));
+    assertTrue(multimap().containsEntry(k3(), v3()));
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   public void testPutAllWithNullValue() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, null));
+        Helpers.mapEntry(k0(), null));
     assertTrue(multimap().putAll(source));
-    assertTrue(multimap().containsEntry(sampleKeys().e0, null));
+    assertTrue(multimap().containsEntry(k0(), null));
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
   public void testPutAllWithNullKey() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(null, sampleValues().e0));
+        Helpers.mapEntry(null, v0()));
     assertTrue(multimap().putAll(source));
-    assertTrue(multimap().containsEntry(null, sampleValues().e0));
+    assertTrue(multimap().containsEntry(null, v0()));
   }
-  
+
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
   public void testPutAllRejectsNullValue() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, null));
+        Helpers.mapEntry(k0(), null));
     try {
       multimap().putAll(source);
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {}
     expectUnchanged();
   }
-  
+
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
   public void testPutAllRejectsNullKey() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(null, sampleValues().e0));
+        Helpers.mapEntry(null, v0()));
     try {
       multimap().putAll(source);
       fail("Expected NullPointerException");
@@ -103,12 +103,12 @@ public class MultimapPutAllMultimapTester<K, V>
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllPropagatesToGet() {
     Multimap<K, V> source = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
-        Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
-    Collection<V> getCollection = multimap().get(sampleKeys().e0);
+        Helpers.mapEntry(k0(), v3()),
+        Helpers.mapEntry(k3(), v3()));
+    Collection<V> getCollection = multimap().get(k0());
     int getCollectionSize = getCollection.size();
     assertTrue(multimap().putAll(source));
     assertEquals(getCollectionSize + 1, getCollection.size());
-    assertThat(getCollection).has().allOf(sampleValues().e3);
+    assertContains(getCollection, v3());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
index 5e2768c..9440ff4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
@@ -16,13 +16,14 @@
 package com.google.common.collect.testing.google;
 
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.testing.Helpers.assertContainsAllOf;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
@@ -43,80 +44,80 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllNonEmptyIterableOnPresentKey() {
-    assertTrue(multimap().putAll(sampleKeys().e0, new Iterable<V>() {
+    assertTrue(multimap().putAll(k0(), new Iterable<V>() {
       @Override
       public Iterator<V> iterator() {
-        return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator();
+        return Lists.newArrayList(v3(), v4()).iterator();
       }
     }));
-    assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4);
+    assertGet(k0(), v0(), v3(), v4());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllNonEmptyCollectionOnPresentKey() {
     assertTrue(multimap().putAll(
-        sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
-    assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4);
+        k0(), Lists.newArrayList(v3(), v4())));
+    assertGet(k0(), v0(), v3(), v4());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllNonEmptyIterableOnAbsentKey() {
-    assertTrue(multimap().putAll(sampleKeys().e3, new Iterable<V>() {
+    assertTrue(multimap().putAll(k3(), new Iterable<V>() {
       @Override
       public Iterator<V> iterator() {
-        return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator();
+        return Lists.newArrayList(v3(), v4()).iterator();
       }
     }));
-    assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4);
+    assertGet(k3(), v3(), v4());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllNonEmptyCollectionOnAbsentKey() {
     assertTrue(multimap().putAll(
-        sampleKeys().e3, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
-    assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4);
+        k3(), Lists.newArrayList(v3(), v4())));
+    assertGet(k3(), v3(), v4());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   public void testPutAllNullValueOnPresentKey_supported() {
-    assertTrue(multimap().putAll(sampleKeys().e0, Lists.newArrayList(sampleValues().e3, null)));
-    assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, null);
+    assertTrue(multimap().putAll(k0(), Lists.newArrayList(v3(), null)));
+    assertGet(k0(), v0(), v3(), null);
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   public void testPutAllNullValueOnAbsentKey_supported() {
-    assertTrue(multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null)));
-    assertGet(sampleKeys().e3, sampleValues().e3, null);
+    assertTrue(multimap().putAll(k3(), Lists.newArrayList(v3(), null)));
+    assertGet(k3(), v3(), null);
   }
 
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
   public void testPutAllNullValueSingle_unsupported() {
-    multimap().putAll(sampleKeys().e1, Lists.newArrayList((V) null));
+    multimap().putAll(k1(), Lists.newArrayList((V) null));
     expectUnchanged();
   }
 
   // In principle, it would be nice to apply these two tests to keys with existing values, too.
-  
+
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
   public void testPutAllNullValueNullLast_unsupported() {
     int size = getNumElements();
 
     try {
-      multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null));
+      multimap().putAll(k3(), Lists.newArrayList(v3(), null));
       fail();
     } catch (NullPointerException expected) {
     }
 
-    Collection<V> values = multimap().get(sampleKeys().e3);
+    Collection<V> values = multimap().get(k3());
     if (values.size() == 0) {
       expectUnchanged();
       // Be extra thorough in case internal state was corrupted by the expected null.
       assertEquals(Lists.newArrayList(), Lists.newArrayList(values));
       assertEquals(size, multimap().size());
     } else {
-      assertEquals(Lists.newArrayList(sampleValues().e3), Lists.newArrayList(values));
+      assertEquals(Lists.newArrayList(v3()), Lists.newArrayList(values));
       assertEquals(size + 1, multimap().size());
     }
   }
@@ -126,7 +127,7 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
     int size = getNumElements();
 
     try {
-      multimap().putAll(sampleKeys().e3, Lists.newArrayList(null, sampleValues().e3));
+      multimap().putAll(k3(), Lists.newArrayList(null, v3()));
       fail();
     } catch (NullPointerException expected) {
     }
@@ -138,31 +139,30 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
      */
     expectUnchanged();
     // Be extra thorough in case internal state was corrupted by the expected null.
-    assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(sampleKeys().e3)));
+    assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(k3())));
     assertEquals(size, multimap().size());
   }
 
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
   public void testPutAllOnPresentNullKey() {
-    assertTrue(multimap().putAll(null, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
-    assertGet(null, sampleValues().e3, sampleValues().e4);
+    assertTrue(
+        multimap().putAll(null, Lists.newArrayList(v3(), v4())));
+    assertGet(null, v3(), v4());
   }
 
   @MapFeature.Require(absent = ALLOWS_NULL_KEYS)
   public void testPutAllNullForbidden() {
     try {
-      multimap().putAll(null, Collections.singletonList(sampleValues().e3));
+      multimap().putAll(null, Collections.singletonList(v3()));
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {
       // success
     }
   }
 
-  private static final Object[] EMPTY = new Object[0];
-
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllEmptyCollectionOnAbsentKey() {
-    assertFalse(multimap().putAll(sampleKeys().e3, Collections.<V>emptyList()));
+    assertFalse(multimap().putAll(k3(), Collections.<V>emptyList()));
     expectUnchanged();
   }
 
@@ -171,21 +171,21 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
     Iterable<V> iterable = new Iterable<V>() {
       @Override
       public Iterator<V> iterator() {
-        return Iterators.emptyIterator();
+        return ImmutableSet.<V>of().iterator();
       }
     };
 
-    assertFalse(multimap().putAll(sampleKeys().e3, iterable));
+    assertFalse(multimap().putAll(k3(), iterable));
     expectUnchanged();
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllEmptyIterableOnPresentKey() {
-    multimap().putAll(sampleKeys().e0, Collections.<V>emptyList());
+    multimap().putAll(k0(), Collections.<V>emptyList());
     expectUnchanged();
   }
-  
+
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllOnlyCallsIteratorOnce() {
     Iterable<V> iterable = new Iterable<V>() {
@@ -195,20 +195,20 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
       public Iterator<V> iterator() {
         checkState(!calledIteratorAlready);
         calledIteratorAlready = true;
-        return Iterators.forArray(sampleValues().e3);
+        return Iterators.forArray(v3());
       }
     };
-    
-    multimap().putAll(sampleKeys().e3, iterable);
+
+    multimap().putAll(k3(), iterable);
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllPropagatesToGet() {
-    Collection<V> getCollection = multimap().get(sampleKeys().e0);
+    Collection<V> getCollection = multimap().get(k0());
     int getCollectionSize = getCollection.size();
     assertTrue(multimap().putAll(
-        sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
+        k0(), Lists.newArrayList(v3(), v4())));
     assertEquals(getCollectionSize + 2, getCollection.size());
-    assertThat(getCollection).has().allOf(sampleValues().e3, sampleValues().e4);
+    assertContainsAllOf(getCollection, v3(), v4());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
index 5ac36a4..409b74a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
@@ -16,11 +16,13 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContains;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ImmutableList;
@@ -45,23 +47,20 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
   @MapFeature.Require(absent = SUPPORTS_PUT)
   public void testPutUnsupported() {
     try {
-      multimap().put(sampleKeys().e3, sampleValues().e3);
+      multimap().put(k3(), v3());
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {}
   }
-  
+
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutEmpty() {
     int size = getNumElements();
 
-    K key = sampleKeys().e3;
-    V value = sampleValues().e3;
-
-    assertGet(key, ImmutableList.<V>of());
+    assertGet(k3(), ImmutableList.<V>of());
 
-    assertTrue(multimap().put(key, value));
+    assertTrue(multimap().put(k3(), v3()));
 
-    assertGet(key, value);
+    assertGet(k3(), v3());
     assertEquals(size + 1, multimap().size());
   }
 
@@ -70,15 +69,11 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
   public void testPutPresent() {
     int size = getNumElements();
 
-    K key = sampleKeys().e0;
-    V oldValue = sampleValues().e0;
-    V newValue = sampleValues().e3;
+    assertGet(k0(), v0());
 
-    assertGet(key, oldValue);
+    assertTrue(multimap().put(k0(), v3()));
 
-    assertTrue(multimap().put(key, newValue));
-
-    assertGet(key, oldValue, newValue);
+    assertGet(k0(), v0(), v3());
     assertEquals(size + 1, multimap().size());
   }
 
@@ -86,19 +81,15 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
   public void testPutTwoElements() {
     int size = getNumElements();
 
-    K key = sampleKeys().e0;
-    V v1 = sampleValues().e3;
-    V v2 = sampleValues().e4;
-
-    List<V> values = Helpers.copyToList(multimap().get(key));
+    List<V> values = Helpers.copyToList(multimap().get(k0()));
 
-    assertTrue(multimap().put(key, v1));
-    assertTrue(multimap().put(key, v2));
+    assertTrue(multimap().put(k0(), v1()));
+    assertTrue(multimap().put(k0(), v2()));
 
-    values.add(v1);
-    values.add(v2);
+    values.add(v1());
+    values.add(v2());
 
-    assertGet(key, values);
+    assertGet(k0(), values);
     assertEquals(size + 2, multimap().size());
   }
 
@@ -106,16 +97,16 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
   public void testPutNullValue_supported() {
     int size = getNumElements();
 
-    multimap().put(sampleKeys().e3, null);
+    multimap().put(k3(), null);
 
-    assertGet(sampleKeys().e3, Lists.newArrayList((V) null)); // ImmutableList.of can't take null.
+    assertGet(k3(), Lists.newArrayList((V) null)); // ImmutableList.of can't take null.
     assertEquals(size + 1, multimap().size());
   }
 
   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
   public void testPutNullValue_unsupported() {
     try {
-      multimap().put(sampleKeys().e1, null);
+      multimap().put(k1(), null);
       fail();
     } catch (NullPointerException expected) {
     }
@@ -127,37 +118,37 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
   public void testPutNullKey() {
     int size = getNumElements();
 
-    multimap().put(null, sampleValues().e3);
+    multimap().put(null, v3());
 
-    assertGet(null, sampleValues().e3);
+    assertGet(null, v3());
     assertEquals(size + 1, multimap().size());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutNotPresentKeyPropagatesToGet() {
     int size = getNumElements();
-    Collection<V> collection = multimap().get(sampleKeys().e3);
-    assertThat(collection).isEmpty();
-    multimap().put(sampleKeys().e3, sampleValues().e3);
-    assertThat(collection).has().item(sampleValues().e3);
+    Collection<V> collection = multimap().get(k3());
+    assertEmpty(collection);
+    multimap().put(k3(), v3());
+    assertContains(collection, v3());
     assertEquals(size + 1, multimap().size());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutNotPresentKeyPropagatesToEntries() {
     Collection<Entry<K, V>> entries = multimap().entries();
-    assertFalse(entries.contains(Helpers.mapEntry(sampleKeys().e3, sampleValues().e3)));
-    multimap().put(sampleKeys().e3, sampleValues().e3);
-    assertThat(entries).has().allOf(Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
+    assertFalse(entries.contains(Helpers.mapEntry(k3(), v3())));
+    multimap().put(k3(), v3());
+    assertContains(entries, Helpers.mapEntry(k3(), v3()));
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutPresentKeyPropagatesToEntries() {
     Collection<Entry<K, V>> entries = multimap().entries();
-    assertFalse(entries.contains(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3)));
-    multimap().put(sampleKeys().e0, sampleValues().e3);
-    assertThat(entries).has().allOf(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+    assertFalse(entries.contains(Helpers.mapEntry(k0(), v3())));
+    multimap().put(k0(), v3());
+    assertContains(entries, Helpers.mapEntry(k0(), v3()));
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
@@ -172,9 +163,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
       Collection<V> collection = multimap().get(key);
       Collection<V> expectedCollection = Helpers.copyToList(collection);
 
-      multimap().put(key, sampleValues().e3);
-      expectedCollection.add(sampleValues().e3);
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      multimap().put(key, v3());
+      expectedCollection.add(v3());
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(size + 1, multimap().size());
     }
   }
@@ -192,9 +183,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
       assertNotNull(collection);
       Collection<V> expectedCollection = Helpers.copyToList(collection);
 
-      multimap().put(key, sampleValues().e3);
-      expectedCollection.add(sampleValues().e3);
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      multimap().put(key, v3());
+      expectedCollection.add(v3());
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(size + 1, multimap().size());
     }
   }
@@ -220,9 +211,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
       assertNotNull(collection);
       Collection<V> expectedCollection = Helpers.copyToList(collection);
 
-      multimap().put(key, sampleValues().e3);
-      expectedCollection.add(sampleValues().e3);
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      multimap().put(key, v3());
+      expectedCollection.add(v3());
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(size + 1, multimap().size());
     }
   }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
index cbd84c9..7ab2e9b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
@@ -16,12 +16,14 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.google.GoogleHelpers.assertEmpty;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -40,40 +42,38 @@ import java.util.Collection;
 public class MultimapRemoveAllTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllAbsentKey() {
-    assertThat(multimap().removeAll(sampleKeys().e3)).isEmpty();
+    assertEmpty(multimap().removeAll(k3()));
     expectUnchanged();
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllPresentKey() {
-    assertThat(multimap().removeAll(sampleKeys().e0))
-        .has().exactly(sampleValues().e0).inOrder();
-    expectMissing(samples.e0);
+    assertContentsAnyOrder(multimap().removeAll(k0()), v0());
+    expectMissing(e0());
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllPropagatesToGet() {
-    Collection<V> getResult = multimap().get(sampleKeys().e0);
+    Collection<V> getResult = multimap().get(k0());
 
-    multimap().removeAll(sampleKeys().e0);
+    multimap().removeAll(k0());
 
-    assertThat(getResult).isEmpty();
-    expectMissing(samples.e0);
+    assertEmpty(getResult);
+    expectMissing(e0());
   }
 
   @CollectionSize.Require(SEVERAL)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllMultipleValues() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v2()));
 
-    assertThat(multimap().removeAll(sampleKeys().e0))
-        .has().exactly(sampleValues().e0, sampleValues().e1, sampleValues().e2);
-    assertTrue(multimap().isEmpty());
+    assertContentsAnyOrder(multimap().removeAll(k0()), v0(), v1(), v2());
+    assertEmpty(multimap());
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -81,14 +81,14 @@ public class MultimapRemoveAllTester<K, V> extends AbstractMultimapTester<K, V,
   public void testRemoveAllNullKeyPresent() {
     initMultimapWithNullKey();
 
-    assertThat(multimap().removeAll(null)).has().exactly(getValueForNullKey()).inOrder();
+    assertContentsAnyOrder(multimap().removeAll(null), getValueForNullKey());
 
     expectMissing(Helpers.mapEntry((K) null, getValueForNullKey()));
   }
 
   @MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_ANY_NULL_QUERIES})
   public void testRemoveAllNullKeyAbsent() {
-    assertThat(multimap().removeAll(null)).isEmpty();
+    assertEmpty(multimap().removeAll(null));
     expectUnchanged();
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
index c1d6783..8f131f3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
@@ -16,13 +16,13 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ImmutableList;
@@ -45,19 +45,19 @@ import java.util.Map.Entry;
 public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAbsent() {
-    assertFalse(multimap().remove(sampleKeys().e0, sampleValues().e1));
+    assertFalse(multimap().remove(k0(), v1()));
     expectUnchanged();
   }
 
   @CollectionSize.Require(absent = ZERO)
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemovePresent() {
-    assertTrue(multimap().remove(sampleKeys().e0, sampleValues().e0));
+    assertTrue(multimap().remove(k0(), v0()));
 
-    assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
-    expectMissing(samples.e0);
+    assertFalse(multimap().containsEntry(k0(), v0()));
+    expectMissing(e0());
     assertEquals(getNumElements() - 1, multimap().size());
-    assertGet(sampleKeys().e0, ImmutableList.<V>of());
+    assertGet(k0(), ImmutableList.<V>of());
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -84,20 +84,20 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
 
   @MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_NULL_KEY_QUERIES})
   public void testRemoveNullKeyAbsent() {
-    assertFalse(multimap().remove(null, sampleValues().e0));
+    assertFalse(multimap().remove(null, v0()));
     expectUnchanged();
   }
 
   @MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_NULL_VALUE_QUERIES})
   public void testRemoveNullValueAbsent() {
-    assertFalse(multimap().remove(sampleKeys().e0, null));
+    assertFalse(multimap().remove(k0(), null));
     expectUnchanged();
   }
 
   @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_VALUE_QUERIES)
   public void testRemoveNullValueForbidden() {
     try {
-      multimap().remove(sampleKeys().e0, null);
+      multimap().remove(k0(), null);
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {
       // success
@@ -108,7 +108,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
   @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_KEY_QUERIES)
   public void testRemoveNullKeyForbidden() {
     try {
-      multimap().remove(null, sampleValues().e0);
+      multimap().remove(null, v0());
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {
       // success
@@ -132,7 +132,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
       multimap().remove(key, value);
       expectedCollection.remove(value);
 
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
     }
   }
@@ -153,7 +153,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
       multimap().remove(key, value);
       expectedCollection.remove(value);
 
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
     }
   }
@@ -183,7 +183,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
       multimap().remove(key, value);
       expectedCollection.remove(value);
 
-      assertThat(collection).has().exactlyAs(expectedCollection);
+      assertEqualIgnoringOrder(expectedCollection, collection);
       assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
     }
   }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
index 930d16f..d8ae346 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
@@ -16,12 +16,12 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -46,61 +46,54 @@ public class MultimapReplaceValuesTester<K, V>
 
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
   public void testReplaceValuesWithNullValue() {
-    int size = multimap().size();
-    K key = sampleKeys().e0;
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(sampleValues().e0, null, sampleValues().e3);
-    multimap().replaceValues(key, values);
-    assertGet(key, values);
+    List<V> values = Arrays.asList(v0(), null, v3());
+    multimap().replaceValues(k0(), values);
+    assertGet(k0(), values);
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_KEYS})
   public void testReplaceValuesWithNullKey() {
-    int size = multimap().size();
-    K key = null;
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
-    multimap().replaceValues(key, values);
-    assertGet(key, values);
+    List<V> values = Arrays.asList(v0(), v2(), v3());
+    multimap().replaceValues(null, values);
+    assertGet(null, values);
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testReplaceEmptyValues() {
     int size = multimap().size();
-    K key = sampleKeys().e3;
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
-    multimap().replaceValues(key, values);
-    assertGet(key, values);
+    List<V> values = Arrays.asList(v0(), v2(), v3());
+    multimap().replaceValues(k3(), values);
+    assertGet(k3(), values);
     assertEquals(size + values.size(), multimap().size());
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testReplaceValuesWithEmpty() {
     int size = multimap().size();
-    K key = sampleKeys().e0;
-    List<V> oldValues = new ArrayList<V>(multimap().get(key));
+    List<V> oldValues = new ArrayList<V>(multimap().get(k0()));
     @SuppressWarnings("unchecked")
     List<V> values = Collections.emptyList();
-    assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(key, values)));
-    assertGet(key);
+    assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(k0(), values)));
+    assertGet(k0());
     assertEquals(size - oldValues.size(), multimap().size());
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testReplaceValuesWithDuplicates() {
     int size = multimap().size();
-    K key = sampleKeys().e0;
-    List<V> oldValues = new ArrayList<V>(multimap().get(key));
+    List<V> oldValues = new ArrayList<V>(multimap().get(k0()));
     List<V> values = Arrays.asList(
-        sampleValues().e0,
-        sampleValues().e3,
-        sampleValues().e0);
-    assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(key, values)));
+        v0(),
+        v3(),
+        v0());
+    assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(k0(), values)));
     assertEquals(
-        size - oldValues.size() + multimap().get(key).size(),
+        size - oldValues.size() + multimap().get(k0()).size(),
         multimap().size());
-    assertTrue(multimap().get(key).containsAll(values));
+    assertTrue(multimap().get(k0()).containsAll(values));
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -108,7 +101,7 @@ public class MultimapReplaceValuesTester<K, V>
   public void testReplaceNonEmptyValues() {
     List<K> keys = Helpers.copyToList(multimap().keySet());
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
+    List<V> values = Arrays.asList(v0(), v2(), v3());
 
     for (K k : keys) {
       resetContainer();
@@ -120,24 +113,22 @@ public class MultimapReplaceValuesTester<K, V>
       assertEquals(size + values.size() - oldKeyValues.size(), multimap().size());
     }
   }
-  
+
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testReplaceValuesPropagatesToGet() {
-    K key = sampleKeys().e0;
-    Collection<V> getCollection = multimap().get(key);
+    Collection<V> getCollection = multimap().get(k0());
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
-    multimap().replaceValues(key, values);
-    assertThat(getCollection).has().exactly(
-        sampleValues().e0, sampleValues().e2, sampleValues().e3);
+    List<V> values = Arrays.asList(v0(), v2(), v3());
+    multimap().replaceValues(k0(), values);
+    assertContentsAnyOrder(getCollection, v0(), v2(), v3());
   }
 
   @MapFeature.Require(absent = SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testReplaceValuesRemoveNotSupported() {
-    List<V> values = Collections.singletonList(sampleValues().e3);
+    List<V> values = Collections.singletonList(v3());
     try {
-      multimap().replaceValues(sampleKeys().e0, values);
+      multimap().replaceValues(k0(), values);
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
       // success
@@ -146,9 +137,9 @@ public class MultimapReplaceValuesTester<K, V>
 
   @MapFeature.Require(absent = SUPPORTS_PUT)
   public void testReplaceValuesPutNotSupported() {
-    List<V> values = Collections.singletonList(sampleValues().e3);
+    List<V> values = Collections.singletonList(v3());
     try {
-      multimap().replaceValues(sampleKeys().e0, values);
+      multimap().replaceValues(k0(), values);
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
       // success
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
index 894c165..fbcb8da 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
@@ -19,7 +19,8 @@ package com.google.common.collect.testing.google;
 import static com.google.common.collect.testing.Helpers.mapEntry;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.collect.testing.features.MapFeature.*;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Multimap;
@@ -93,9 +94,9 @@ public class MultimapSizeTester<K, V> extends AbstractMultimapTester<K, V, Multi
   @CollectionSize.Require(SEVERAL)
   public void testSizeMultipleValues() {
     resetContainer(
-        mapEntry(sampleKeys().e0, sampleValues().e0),
-        mapEntry(sampleKeys().e0, sampleValues().e1),
-        mapEntry(sampleKeys().e0, sampleValues().e2));
+        mapEntry(k0(), v0()),
+        mapEntry(k0(), v1()),
+        mapEntry(k0(), v2()));
 
     assertEquals(3, multimap().size());
     assertEquals(3, multimap().entries().size());
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
index 6f419f8..15261dd 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
@@ -332,11 +332,11 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
       SampleElements<V> sampleValues =
           ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleValues();
       return new SampleElements<Entry<K, Collection<V>>>(
-          mapEntry(sampleKeys.e0, createCollection(sampleValues.e0)),
-          mapEntry(sampleKeys.e1, createCollection(sampleValues.e1)),
-          mapEntry(sampleKeys.e2, createCollection(sampleValues.e2)),
-          mapEntry(sampleKeys.e3, createCollection(sampleValues.e3)),
-          mapEntry(sampleKeys.e4, createCollection(sampleValues.e4)));
+          mapEntry(sampleKeys.e0(), createCollection(sampleValues.e0())),
+          mapEntry(sampleKeys.e1(), createCollection(sampleValues.e1())),
+          mapEntry(sampleKeys.e2(), createCollection(sampleValues.e2())),
+          mapEntry(sampleKeys.e3(), createCollection(sampleValues.e3())),
+          mapEntry(sampleKeys.e4(), createCollection(sampleValues.e4())));
     }
 
     @Override
@@ -444,8 +444,8 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
 
     @Override
     public Collection<V> create(Object... elements) {
-      K k =
-          ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys().e0;
+      K k = ((TestMultimapGenerator<K, V, M>)
+          multimapGenerator.getInnerGenerator()).sampleKeys().e0();
       Entry<K, V>[] entries = new Entry[elements.length];
       for (int i = 0; i < elements.length; i++) {
         entries[i] = mapEntry(k, (V) elements[i]);
@@ -462,8 +462,8 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
 
     @Override
     public Iterable<V> order(List<V> insertionOrder) {
-      K k =
-          ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys().e0;
+      K k = ((TestMultimapGenerator<K, V, M>)
+          multimapGenerator.getInnerGenerator()).sampleKeys().e0();
       List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
       for (V v : insertionOrder) {
         entries.add(mapEntry(k, v));
@@ -570,7 +570,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
     @Override
     public Iterable<V> order(List<V> insertionOrder) {
       K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
-          .sampleKeys().e0;
+          .sampleKeys().e0();
       List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
       for (V v : insertionOrder) {
         entries.add(mapEntry(k, v));
@@ -587,7 +587,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
     public Collection<V> create(Object... elements) {
       Entry<K, V>[] array = multimapGenerator.createArray(elements.length);
       K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
-          .sampleKeys().e0;
+          .sampleKeys().e0();
       for (int i = 0; i < elements.length; i++) {
         array[i] = mapEntry(k, (V) elements[i]);
       }
@@ -608,7 +608,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
     public Collection<V> create(Object... elements) {
       Entry<K, V>[] array = multimapGenerator.createArray(elements.length);
       K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
-          .sampleKeys().e0;
+          .sampleKeys().e0();
       for (int i = 0; i < elements.length; i++) {
         array[i] = mapEntry(k, (V) elements[i]);
       }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
index 29896f3..b85a1ff 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
@@ -38,7 +38,8 @@ public class MultimapToStringTester<K, V> extends AbstractMultimapTester<K, V, M
 
   @CollectionSize.Require(ONE)
   public void testToStringSingleton() {
-    assertEquals("{" + sampleKeys().e0 + "=[" + sampleValues().e0 + "]}", multimap().toString());
+    assertEquals(
+        "{" + k0() + "=[" + v0() + "]}", multimap().toString());
   }
 
   @CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
index e7da59e..f0b791d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
@@ -14,10 +14,11 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
 import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.ONE;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.Lists;
@@ -41,19 +42,18 @@ public class MultimapValuesTester<K, V> extends AbstractMultimapTester<K, V, Mul
     for (Map.Entry<K, V> entry : getSampleElements()) {
       expected.add(entry.getValue());
     }
-    assertThat(multimap().values()).has().exactlyAs(expected);
+    assertEqualIgnoringOrder(expected, multimap().values());
   }
-  
+
   @CollectionFeature.Require(KNOWN_ORDER)
   public void testValuesInOrder() {
     List<V> expected = Lists.newArrayList();
     for (Map.Entry<K, V> entry : getOrderedElements()) {
       expected.add(entry.getValue());
     }
-    assertThat(multimap().values()).has().exactlyAs(expected).inOrder();
+    assertEqualInOrder(expected, multimap().values());
   }
-  
-  
+
   @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
   @CollectionSize.Require(ONE)
   public void testValuesIteratorRemove() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
index 365e0a3..a11276f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
@@ -34,45 +34,45 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testAddUnsupported() {
     try {
-      getMultiset().add(samples.e0);
+      getMultiset().add(e0());
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {}
   }
   
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddMeansAddOne() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertTrue(getMultiset().add(samples.e0));
-    assertEquals(originalCount + 1, getMultiset().count(samples.e0));
+    int originalCount = getMultiset().count(e0());
+    assertTrue(getMultiset().add(e0()));
+    assertEquals(originalCount + 1, getMultiset().count(e0()));
   }
   
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddOccurrencesZero() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertEquals("old count", originalCount, getMultiset().add(samples.e0, 0));
+    int originalCount = getMultiset().count(e0());
+    assertEquals("old count", originalCount, getMultiset().add(e0(), 0));
     expectUnchanged();
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddOccurrences() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertEquals("old count", originalCount, getMultiset().add(samples.e0, 2));
-    assertEquals("old count", originalCount + 2, getMultiset().count(samples.e0));
+    int originalCount = getMultiset().count(e0());
+    assertEquals("old count", originalCount, getMultiset().add(e0(), 2));
+    assertEquals("old count", originalCount + 2, getMultiset().count(e0()));
   }
   
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddSeveralTimes() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertEquals(originalCount, getMultiset().add(samples.e0, 2));
-    assertTrue(getMultiset().add(samples.e0));
-    assertEquals(originalCount + 3, getMultiset().add(samples.e0, 1));
-    assertEquals(originalCount + 4, getMultiset().count(samples.e0));
+    int originalCount = getMultiset().count(e0());
+    assertEquals(originalCount, getMultiset().add(e0(), 2));
+    assertTrue(getMultiset().add(e0()));
+    assertEquals(originalCount + 3, getMultiset().add(e0(), 1));
+    assertEquals(originalCount + 4, getMultiset().count(e0()));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testAddOccurrences_unsupported() {
     try {
-      getMultiset().add(samples.e0, 2);
+      getMultiset().add(e0(), 2);
       fail("unsupported multiset.add(E, int) didn't throw exception");
     } catch (UnsupportedOperationException required) {}
   }
@@ -80,19 +80,19 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddOccurrencesNegative() {
     try {
-      getMultiset().add(samples.e0, -1);
+      getMultiset().add(e0(), -1);
       fail("multiset.add(E, -1) didn't throw an exception");
     } catch (IllegalArgumentException required) {}
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddTooMany() {
-    getMultiset().add(samples.e3, Integer.MAX_VALUE);
+    getMultiset().add(e3(), Integer.MAX_VALUE);
     try {
-      getMultiset().add(samples.e3);
+      getMultiset().add(e3());
       fail();
     } catch (IllegalArgumentException expected) {}
-    assertEquals(Integer.MAX_VALUE, getMultiset().count(samples.e3));
+    assertEquals(Integer.MAX_VALUE, getMultiset().count(e3()));
     assertEquals(Integer.MAX_VALUE, getMultiset().size());
   }
   
@@ -110,14 +110,14 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
   
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddAll_nonEmptyList() {
-    assertTrue(getMultiset().addAll(Arrays.asList(samples.e3, samples.e4, samples.e3)));
-    expectAdded(samples.e3, samples.e4, samples.e3);
+    assertTrue(getMultiset().addAll(Arrays.asList(e3(), e4(), e3())));
+    expectAdded(e3(), e4(), e3());
   }
   
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddAll_nonEmptyMultiset() {
     assertTrue(getMultiset().addAll(
-        getSubjectGenerator().create(samples.e3, samples.e4, samples.e3)));
-    expectAdded(samples.e3, samples.e4, samples.e3);
+        getSubjectGenerator().create(e3(), e4(), e3())));
+    expectAdded(e3(), e4(), e3());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
index 11cb686..5e4910e 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
@@ -31,11 +31,11 @@ public class MultisetContainsTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testContainsAllMultisetIgnoresFrequency() {
     assertTrue(getMultiset()
-        .containsAll(getSubjectGenerator().create(samples.e0, samples.e0, samples.e0)));
+        .containsAll(getSubjectGenerator().create(e0(), e0(), e0())));
   }
   
   @CollectionSize.Require(absent = ZERO)
   public void testContainsAllListIgnoresFrequency() {
-    assertTrue(getMultiset().containsAll(Arrays.asList(samples.e0, samples.e0, samples.e0)));
+    assertTrue(getMultiset().containsAll(Arrays.asList(e0(), e0(), e0())));
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
index e1ceb81..ffeee88 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
@@ -42,20 +42,20 @@ public class MultisetCountTester<E> extends AbstractMultisetTester<E> {
 
   public void testCount_0() {
     assertEquals("multiset.count(missing) didn't return 0",
-        0, getMultiset().count(samples.e3));
+        0, getMultiset().count(e3()));
   }
 
   @CollectionSize.Require(absent = ZERO)
   public void testCount_1() {
     assertEquals("multiset.count(present) didn't return 1",
-        1, getMultiset().count(samples.e0));
+        1, getMultiset().count(e0()));
   }
 
   @CollectionSize.Require(SEVERAL)
   public void testCount_3() {
     initThreeCopies();
     assertEquals("multiset.count(thriceContained) didn't return 3",
-        3, getMultiset().count(samples.e0));
+        3, getMultiset().count(e0()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_QUERIES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
index 0ad79cc..29cb7e4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
@@ -16,11 +16,11 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.testing.features.CollectionFeature;
@@ -31,7 +31,7 @@ import java.util.Set;
 
 /**
  * Tests for {@code Multiset.elementSet()} not covered by the derived {@code SetTestSuiteBuilder}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -39,26 +39,26 @@ public class MultisetElementSetTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testElementSetReflectsAddAbsent() {
     Set<E> elementSet = getMultiset().elementSet();
-    assertFalse(elementSet.contains(samples.e3));
-    getMultiset().add(samples.e3, 4);
-    assertTrue(elementSet.contains(samples.e3));
+    assertFalse(elementSet.contains(e3()));
+    getMultiset().add(e3(), 4);
+    assertTrue(elementSet.contains(e3()));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testElementSetReflectsRemove() {
     Set<E> elementSet = getMultiset().elementSet();
-    assertTrue(elementSet.contains(samples.e0));
-    getMultiset().removeAll(Collections.singleton(samples.e0));
-    assertFalse(elementSet.contains(samples.e0));
+    assertTrue(elementSet.contains(e0()));
+    getMultiset().removeAll(Collections.singleton(e0()));
+    assertFalse(elementSet.contains(e0()));
   }
 
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testElementSetRemovePropagatesToMultiset() {
     Set<E> elementSet = getMultiset().elementSet();
-    assertTrue(elementSet.remove(samples.e0));
-    assertFalse(getMultiset().contains(samples.e0));
+    assertTrue(elementSet.remove(e0()));
+    assertFalse(getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(SEVERAL)
@@ -66,20 +66,20 @@ public class MultisetElementSetTester<E> extends AbstractMultisetTester<E> {
   public void testElementSetRemoveDuplicatePropagatesToMultiset() {
     initThreeCopies();
     Set<E> elementSet = getMultiset().elementSet();
-    assertTrue(elementSet.remove(samples.e0));
-    assertThat(getMultiset()).isEmpty();
+    assertTrue(elementSet.remove(e0()));
+    assertEmpty(getMultiset());
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testElementSetRemoveAbsent() {
     Set<E> elementSet = getMultiset().elementSet();
-    assertFalse(elementSet.remove(samples.e3));
+    assertFalse(elementSet.remove(e3()));
     expectUnchanged();
   }
-  
+
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testElementSetClear() {
     getMultiset().elementSet().clear();
-    assertThat(getMultiset()).isEmpty();    
+    assertEmpty(getMultiset());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
index e172243..b1a8a90 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
@@ -57,7 +57,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
         "non-empty multiset.entrySet() iterator.hasNext() returned false",
         iterator.hasNext());
     assertEquals("multiset.entrySet() iterator.next() returned incorrect entry",
-        Multisets.immutableEntry(samples.e0, 1), iterator.next());
+        Multisets.immutableEntry(e0(), 1), iterator.next());
     assertFalse(
         "size 1 multiset.entrySet() iterator.hasNext() returned true "
             + "after next()",
@@ -74,10 +74,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertTrue(
         "multiset.entrySet.remove(presentEntry) returned false",
         getMultiset().entrySet().remove(
-            Multisets.immutableEntry(samples.e0, 1)));
+            Multisets.immutableEntry(e0(), 1)));
     assertFalse(
         "multiset contains element after removing its entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -86,10 +86,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertFalse(
         "multiset.entrySet.remove(missingEntry) returned true",
         getMultiset().entrySet().remove(
-            Multisets.immutableEntry(samples.e0, 2)));
+            Multisets.immutableEntry(e0(), 2)));
     assertTrue(
         "multiset didn't contain element after removing a missing entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -98,10 +98,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertTrue(
         "multiset.entrySet.removeAll(presentEntry) returned false",
         getMultiset().entrySet().removeAll(
-            Collections.singleton(Multisets.immutableEntry(samples.e0, 1))));
+            Collections.singleton(Multisets.immutableEntry(e0(), 1))));
     assertFalse(
         "multiset contains element after removing its entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -110,10 +110,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertFalse(
         "multiset.entrySet.remove(missingEntry) returned true",
         getMultiset().entrySet().removeAll(
-            Collections.singleton(Multisets.immutableEntry(samples.e0, 2))));
+            Collections.singleton(Multisets.immutableEntry(e0(), 2))));
     assertTrue(
         "multiset didn't contain element after removing a missing entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(ONE)
@@ -122,10 +122,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertFalse(
         "multiset.entrySet.retainAll(presentEntry) returned false",
         getMultiset().entrySet().retainAll(
-            Collections.singleton(Multisets.immutableEntry(samples.e0, 1))));
+            Collections.singleton(Multisets.immutableEntry(e0(), 1))));
     assertTrue(
         "multiset doesn't contains element after retaining its entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
 
   @CollectionSize.Require(ONE)
@@ -134,10 +134,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
     assertTrue(
         "multiset.entrySet.retainAll(missingEntry) returned true",
         getMultiset().entrySet().retainAll(
-            Collections.singleton(Multisets.immutableEntry(samples.e0, 2))));
+            Collections.singleton(Multisets.immutableEntry(e0(), 2))));
     assertFalse(
         "multiset contains element after retaining a different entry",
-        getMultiset().contains(samples.e0));
+        getMultiset().contains(e0()));
   }
   
   @CollectionSize.Require(SEVERAL)
@@ -145,12 +145,12 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryViewReflectsRemove() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
-    assertTrue(getMultiset().remove(samples.e0));
+    assertTrue(getMultiset().remove(e0()));
     assertEquals(2, entry.getCount());
-    assertTrue(getMultiset().elementSet().remove(samples.e0));
+    assertTrue(getMultiset().elementSet().remove(e0()));
     assertEquals(0, entry.getCount());
   }
   
@@ -159,7 +159,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsIteratorRemove() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
     Iterator<E> itr = getMultiset().iterator();
@@ -178,7 +178,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsClear() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
     getMultiset().clear();
@@ -190,7 +190,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsEntrySetClear() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
     getMultiset().entrySet().clear();
@@ -202,7 +202,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsEntrySetIteratorRemove() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Iterator<Multiset.Entry<E>> entryItr = getMultiset().entrySet().iterator();
     Multiset.Entry<E> entry = entryItr.next();
     entryItr.remove();
@@ -214,7 +214,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsElementSetClear() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
     getMultiset().elementSet().clear();
@@ -226,7 +226,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsElementSetIteratorRemove() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
     Iterator<E> elementItr = getMultiset().elementSet().iterator();
@@ -240,14 +240,14 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
   @MultisetFeature.Require(ENTRIES_ARE_VIEWS)
   public void testEntryReflectsRemoveThenAdd() {
     initThreeCopies();
-    assertEquals(3, getMultiset().count(samples.e0));
+    assertEquals(3, getMultiset().count(e0()));
     Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
     assertEquals(3, entry.getCount());
-    assertTrue(getMultiset().remove(samples.e0));
+    assertTrue(getMultiset().remove(e0()));
     assertEquals(2, entry.getCount());
-    assertTrue(getMultiset().elementSet().remove(samples.e0));
+    assertTrue(getMultiset().elementSet().remove(e0()));
     assertEquals(0, entry.getCount());
-    getMultiset().add(samples.e0, 2);
+    getMultiset().add(e0(), 2);
     assertEquals(2, entry.getCount());
   }
   
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
index 2df8b42..2ea2168 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
@@ -14,13 +14,14 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
+import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
 import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.testing.Helpers;
-import com.google.common.collect.testing.IteratorFeature;
 import com.google.common.collect.testing.IteratorTester;
 import com.google.common.collect.testing.features.CollectionFeature;
 
@@ -40,12 +41,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require({SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
   public void testRemovingIteratorKnownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, getSubjectGenerator().order(
-        Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+    new IteratorTester<E>(4, MODIFIABLE, getSubjectGenerator().order(
+        Arrays.asList(e0(), e1(), e1(), e2())),
         IteratorTester.KnownOrder.KNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -54,11 +55,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(value = SUPPORTS_ITERATOR_REMOVE, absent = KNOWN_ORDER)
   public void testRemovingIteratorUnknownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, Arrays.asList(samples.e0, samples.e1,
-        samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+    new IteratorTester<E>(4, MODIFIABLE, Arrays.asList(e0(), e1(),
+        e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -67,12 +68,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(value = KNOWN_ORDER, absent = SUPPORTS_ITERATOR_REMOVE)
   public void testIteratorKnownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, getSubjectGenerator().order(
-        Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+    new IteratorTester<E>(4, UNMODIFIABLE, getSubjectGenerator().order(
+        Arrays.asList(e0(), e1(), e1(), e2())),
         IteratorTester.KnownOrder.KNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
@@ -81,11 +82,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(absent = {SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
   public void testIteratorUnknownOrder() {
-    new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, Arrays.asList(samples.e0, samples.e1,
-        samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+    new IteratorTester<E>(4, UNMODIFIABLE, Arrays.asList(e0(), e1(),
+        e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
       @Override
       protected Iterator<E> newTargetIterator() {
-        return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+        return getSubjectGenerator().create(e0(), e1(), e1(), e2())
             .iterator();
       }
     }.test();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
index 9c844e8..efb2e64 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
@@ -109,8 +109,8 @@ public class MultisetNavigationTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(ZERO)
   public void testEmptyMultisetNearby() {
     for (BoundType type : BoundType.values()) {
-      assertNull(sortedMultiset.headMultiset(samples.e0, type).lastEntry());
-      assertNull(sortedMultiset.tailMultiset(samples.e0, type).firstEntry());
+      assertNull(sortedMultiset.headMultiset(e0(), type).lastEntry());
+      assertNull(sortedMultiset.tailMultiset(e0(), type).firstEntry());
     }
   }
 
@@ -143,11 +143,11 @@ public class MultisetNavigationTester<E> extends AbstractMultisetTester<E> {
 
   @CollectionSize.Require(ONE)
   public void testSingletonMultisetNearby() {
-    assertNull(sortedMultiset.headMultiset(samples.e0, OPEN).lastEntry());
-    assertNull(sortedMultiset.tailMultiset(samples.e0, OPEN).lastEntry());
+    assertNull(sortedMultiset.headMultiset(e0(), OPEN).lastEntry());
+    assertNull(sortedMultiset.tailMultiset(e0(), OPEN).lastEntry());
 
-    assertEquals(a, sortedMultiset.headMultiset(samples.e0, CLOSED).lastEntry());
-    assertEquals(a, sortedMultiset.tailMultiset(samples.e0, CLOSED).firstEntry());
+    assertEquals(a, sortedMultiset.headMultiset(e0(), CLOSED).lastEntry());
+    assertEquals(a, sortedMultiset.tailMultiset(e0(), CLOSED).firstEntry());
   }
 
   @CollectionSize.Require(ONE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
index bdb1d28..9c05ef1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
@@ -38,25 +38,25 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testElementSet_contains() {
     assertTrue("multiset.elementSet().contains(present) returned false",
-        getMultiset().elementSet().contains(samples.e0));
+        getMultiset().elementSet().contains(e0()));
   }
 
   @CollectionSize.Require(absent = ZERO)
   public void testEntrySet_contains() {
     assertTrue("multiset.entrySet() didn't contain [present, 1]",
         getMultiset().entrySet().contains(
-            Multisets.immutableEntry(samples.e0, 1)));
+            Multisets.immutableEntry(e0(), 1)));
   }
 
   public void testEntrySet_contains_count0() {
     assertFalse("multiset.entrySet() contains [missing, 0]",
         getMultiset().entrySet().contains(
-            Multisets.immutableEntry(samples.e3, 0)));
+            Multisets.immutableEntry(e3(), 0)));
   }
 
   public void testEntrySet_contains_nonentry() {
     assertFalse("multiset.entrySet() contains a non-entry",
-        getMultiset().entrySet().contains(samples.e0));
+        getMultiset().entrySet().contains(e0()));
   }
 
   public void testEntrySet_twice() {
@@ -73,7 +73,7 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(ONE)
   public void testEntrySet_hashCode_size1() {
     assertEquals("multiset.entrySet() has incorrect hash code",
-        1 ^ samples.e0.hashCode(), getMultiset().entrySet().hashCode());
+        1 ^ e0().hashCode(), getMultiset().entrySet().hashCode());
   }
 
   public void testEquals_yes() {
@@ -83,7 +83,7 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
 
   public void testEquals_differentSize() {
     Multiset<E> other = HashMultiset.create(getSampleElements());
-    other.add(samples.e0);
+    other.add(e0());
     assertFalse("multiset equals a multiset with a different size",
         getMultiset().equals(other));
   }
@@ -91,8 +91,8 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testEquals_differentElements() {
     Multiset<E> other = HashMultiset.create(getSampleElements());
-    other.remove(samples.e0);
-    other.add(samples.e3);
+    other.remove(e0());
+    other.add(e3());
     assertFalse("multiset equals a multiset with different elements",
         getMultiset().equals(other));
   }
@@ -106,6 +106,6 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
   @CollectionSize.Require(ONE)
   public void testHashCode_size1() {
     assertEquals("multiset has incorrect hash code",
-        1 ^ samples.e0.hashCode(), getMultiset().hashCode());
+        1 ^ e0().hashCode(), getMultiset().hashCode());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
index 7a76116..525b412 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
@@ -16,12 +16,12 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.Helpers.assertEmpty;
 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
@@ -38,32 +38,32 @@ import java.util.List;
 /**
  * Tests for {@code Multiset#remove}, {@code Multiset.removeAll}, and {@code Multiset.retainAll}
  * not already covered by the corresponding Collection testers.
- * 
+ *
  * @author Jared Levy
  */
 @GwtCompatible(emulated = true)
-public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {  
+public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveNegative() {
     try {
-      getMultiset().remove(samples.e0, -1);
+      getMultiset().remove(e0(), -1);
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {}
     expectUnchanged();
   }
-  
+
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
   public void testRemoveUnsupported() {
     try {
-      getMultiset().remove(samples.e0, 2);
+      getMultiset().remove(e0(), 2);
       fail("Expected UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {}
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveZeroNoOp() {
-    int originalCount = getMultiset().count(samples.e0);
-    assertEquals("old count", originalCount, getMultiset().remove(samples.e0, 0));
+    int originalCount = getMultiset().count(e0());
+    assertEquals("old count", originalCount, getMultiset().remove(e0(), 0));
     expectUnchanged();
   }
 
@@ -71,10 +71,10 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_present() {
     assertEquals("multiset.remove(present, 2) didn't return the old count",
-        1, getMultiset().remove(samples.e0, 2));
+        1, getMultiset().remove(e0(), 2));
     assertFalse("multiset contains present after multiset.remove(present, 2)",
-        getMultiset().contains(samples.e0));
-    assertEquals(0, getMultiset().count(samples.e0));
+        getMultiset().contains(e0()));
+    assertEquals(0, getMultiset().count(e0()));
   }
 
   @CollectionSize.Require(SEVERAL)
@@ -82,16 +82,16 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
   public void testRemove_some_occurrences_present() {
     initThreeCopies();
     assertEquals("multiset.remove(present, 2) didn't return the old count",
-        3, getMultiset().remove(samples.e0, 2));
+        3, getMultiset().remove(e0(), 2));
     assertTrue("multiset contains present after multiset.remove(present, 2)",
-        getMultiset().contains(samples.e0));
-    assertEquals(1, getMultiset().count(samples.e0));
+        getMultiset().contains(e0()));
+    assertEquals(1, getMultiset().count(e0()));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_absent() {
     assertEquals("multiset.remove(absent, 0) didn't return 0",
-        0, getMultiset().remove(samples.e3, 2));
+        0, getMultiset().remove(e3(), 2));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -100,21 +100,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
     try {
       assertEquals(
           "multiset.remove(absent, 2) didn't return 0 or throw an exception",
-          0, getMultiset().remove(samples.e3, 2));
+          0, getMultiset().remove(e3(), 2));
     } catch (UnsupportedOperationException ok) {}
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_0() {
-    int oldCount = getMultiset().count(samples.e0);
+    int oldCount = getMultiset().count(e0());
     assertEquals("multiset.remove(E, 0) didn't return the old count",
-        oldCount, getMultiset().remove(samples.e0, 0));
+        oldCount, getMultiset().remove(e0(), 0));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_occurrences_negative() {
     try {
-      getMultiset().remove(samples.e0, -1);
+      getMultiset().remove(e0(), -1);
       fail("multiset.remove(E, -1) didn't throw an exception");
     } catch (IllegalArgumentException required) {}
   }
@@ -124,7 +124,7 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
     assertEquals("multiset.remove(wrongType, 1) didn't return 0",
         0, getMultiset().remove(WrongType.VALUE, 1));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
   public void testRemove_nullPresent() {
@@ -134,12 +134,12 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
         getMultiset().contains(null));
     assertEquals(0, getMultiset().count(null));
   }
-  
+
   @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
   public void testRemove_nullAbsent() {
     assertEquals(0, getMultiset().remove(null, 2));
   }
-  
+
   @CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
   public void testRemove_nullForbidden() {
     try {
@@ -147,24 +147,24 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
       fail("Expected NullPointerException");
     } catch (NullPointerException expected) {}
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAllIgnoresCount() {
     initThreeCopies();
-    assertTrue(getMultiset().removeAll(Collections.singleton(samples.e0)));
-    assertThat(getMultiset()).isEmpty();
+    assertTrue(getMultiset().removeAll(Collections.singleton(e0())));
+    assertEmpty(getMultiset());
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRetainAllIgnoresCount() {
     initThreeCopies();
     List<E> contents = Helpers.copyToList(getMultiset());
-    assertFalse(getMultiset().retainAll(Collections.singleton(samples.e0)));
+    assertFalse(getMultiset().retainAll(Collections.singleton(e0())));
     expectContents(contents);
   }
-  
+
   /**
    * Returns {@link Method} instances for the remove tests that assume multisets
    * support duplicates so that the test of {@code Multisets.forSet()} can
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
index 3973434..6a07397 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
@@ -51,7 +51,7 @@ public class MultisetSetCountConditionallyTester<E> extends
 
   private void assertSetCountNegativeOldCount() {
     try {
-      getMultiset().setCount(samples.e3, -1, 1);
+      getMultiset().setCount(e3(), -1, 1);
       fail("calling setCount() with a negative oldCount should throw "
           + "IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
@@ -78,7 +78,7 @@ public class MultisetSetCountConditionallyTester<E> extends
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCountConditional_oldCountTooLarge() {
     assertFalse("setCount() with a too-large oldCount should return false",
-        getMultiset().setCount(samples.e0, 2, 3));
+        getMultiset().setCount(e0(), 2, 3));
     expectUnchanged();
   }
 
@@ -86,7 +86,7 @@ public class MultisetSetCountConditionallyTester<E> extends
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testSetCountConditional_oldCountTooSmallZero() {
     assertFalse("setCount() with a too-small oldCount should return false",
-        getMultiset().setCount(samples.e0, 0, 2));
+        getMultiset().setCount(e0(), 0, 2));
     expectUnchanged();
   }
 
@@ -95,8 +95,8 @@ public class MultisetSetCountConditionallyTester<E> extends
   public void testSetCountConditional_oldCountTooSmallNonzero() {
     initThreeCopies();
     assertFalse("setCount() with a too-small oldCount should return false",
-        getMultiset().setCount(samples.e0, 1, 5));
-    expectContents(nCopies(3, samples.e0));
+        getMultiset().setCount(e0(), 1, 5));
+    expectContents(nCopies(3, e0()));
   }
 
   /*
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
index f460b5d..007a29a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
@@ -205,11 +205,11 @@ public class MultisetTestSuiteBuilder<E> extends
     public SampleElements<Multiset.Entry<E>> samples() {
       SampleElements<E> samples = gen.samples();
       return new SampleElements<Multiset.Entry<E>>(
-          Multisets.immutableEntry(samples.e0, 3),
-          Multisets.immutableEntry(samples.e1, 4),
-          Multisets.immutableEntry(samples.e2, 1),
-          Multisets.immutableEntry(samples.e3, 5),
-          Multisets.immutableEntry(samples.e4, 2));
+          Multisets.immutableEntry(samples.e0(), 3),
+          Multisets.immutableEntry(samples.e1(), 4),
+          Multisets.immutableEntry(samples.e2(), 1),
+          Multisets.immutableEntry(samples.e3(), 5),
+          Multisets.immutableEntry(samples.e4(), 2));
     }
 
     @Override
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
index 29cced4..50df987 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
@@ -67,12 +67,12 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
   @CollectionSize.Require(SEVERAL)
   public void testEquals() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Map<K, Collection<V>> expected = Maps.newHashMap();
-    expected.put(sampleKeys().e0, Sets.newHashSet(sampleValues().e0, sampleValues().e3));
-    expected.put(sampleKeys().e1, Sets.newHashSet(sampleValues().e0));
+    expected.put(k0(), Sets.newHashSet(v0(), v3()));
+    expected.put(k1(), Sets.newHashSet(v0()));
     new EqualsTester()
         .addEqualityGroup(expected, multimap().asMap())
         .testEquals();
@@ -81,16 +81,16 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
   @CollectionSize.Require(SEVERAL)
   public void testEntrySetEquals() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
     Set<Entry<K, Collection<V>>> expected = Sets.newHashSet();
     expected.add(Helpers.mapEntry(
-        sampleKeys().e0, 
-        (Collection<V>) Sets.newHashSet(sampleValues().e0, sampleValues().e3)));
+        k0(), 
+        (Collection<V>) Sets.newHashSet(v0(), v3())));
     expected.add(Helpers.mapEntry(
-        sampleKeys().e1, 
-        (Collection<V>) Sets.newHashSet(sampleValues().e0)));
+        k1(), 
+        (Collection<V>) Sets.newHashSet(v0())));
     new EqualsTester()
         .addEqualityGroup(expected, multimap().asMap().entrySet())
         .testEquals();
@@ -100,14 +100,14 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testValuesRemove() {
     resetContainer(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-    assertTrue(multimap().asMap().values().remove(Collections.singleton(sampleValues().e0)));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k1(), v0()),
+        Helpers.mapEntry(k0(), v3()));
+    assertTrue(multimap().asMap().values().remove(Collections.singleton(v0())));
     assertEquals(2, multimap().size());
     assertEquals(
         Collections.singletonMap(
-            sampleKeys().e0, Sets.newHashSet(sampleValues().e0, sampleValues().e3)),
+            k0(), Sets.newHashSet(v0(), v3())),
         multimap().asMap());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
index 6d832d3..c1ddbe6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
@@ -33,13 +33,13 @@ public class SetMultimapEqualsTester<K, V>
   @CollectionSize.Require(SEVERAL)
   public void testOrderingDoesntAffectEqualsComparisons() {
     SetMultimap<K, V> multimap1 = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e4));
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v4()));
     SetMultimap<K, V> multimap2 = getSubjectGenerator().create(
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
-        Helpers.mapEntry(sampleKeys().e0, sampleValues().e4));
+        Helpers.mapEntry(k0(), v1()),
+        Helpers.mapEntry(k0(), v0()),
+        Helpers.mapEntry(k0(), v4()));
     new EqualsTester()
         .addEqualityGroup(multimap1, multimap2)
         .testEquals();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
index 8e56542..b518a09 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
@@ -36,10 +36,8 @@ public class SetMultimapPutAllTester<K, V>
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAllHandlesDuplicates() {
-    V v0 = sampleValues().e3;
-    V v1 = sampleValues().e2;
     @SuppressWarnings("unchecked")
-    List<V> valuesToPut = Arrays.asList(v0, v1, v0);
+    List<V> valuesToPut = Arrays.asList(v0(), v1(), v0());
 
     for (K k : sampleKeys()) {
       resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
index 6b7b6c5..833b5e3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
@@ -42,7 +42,7 @@ public class SetMultimapPutTester<K, V>
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(absent = ZERO)
   public void testPutDuplicateValuePreservesSize() {
-    assertFalse(multimap().put(sampleKeys().e0, sampleValues().e0));
+    assertFalse(multimap().put(k0(), v0()));
     assertEquals(getNumElements(), multimap().size());
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
index fa95309..31f81be 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
@@ -35,15 +35,13 @@ public class SetMultimapReplaceValuesTester<K, V>
 
   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
   public void testReplaceValuesHandlesDuplicates() {
-    V v0 = sampleValues().e3;
-    V v1 = sampleValues().e2;
     @SuppressWarnings("unchecked")
-    List<V> values = Arrays.asList(v0, v1, v0);
+    List<V> values = Arrays.asList(v0(), v1(), v0());
 
     for (K k : sampleKeys()) {
       resetContainer();
       multimap().replaceValues(k, values);
-      assertGet(k, v0, v1);
+      assertGet(k, v0(), v1());
     }
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
index e37ae5f..f27ab7f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
@@ -27,6 +27,7 @@ import com.google.common.collect.testing.TestListGenerator;
 import com.google.common.collect.testing.TestStringListGenerator;
 import com.google.common.collect.testing.TestStringSortedMapGenerator;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.SortedMap;
@@ -53,6 +54,12 @@ public class SortedMapGenerators {
       return builder.build();
     }
   }
+  public static class ImmutableSortedMapCopyOfEntriesGenerator 
+      extends TestStringSortedMapGenerator {
+    @Override public SortedMap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableSortedMap.copyOf(Arrays.asList(entries));
+    }
+  }
 
   public static class ImmutableSortedMapEntryListGenerator
       implements TestListGenerator<Entry<String, Integer>> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
index 1b1abbd..47f354d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
@@ -16,6 +16,11 @@
 
 package com.google.common.collect.testing.google;
 
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
 import com.google.common.collect.BoundType;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
@@ -27,7 +32,6 @@ import com.google.common.collect.testing.Helpers;
 import com.google.common.collect.testing.OneSizeTestContainerGenerator;
 import com.google.common.collect.testing.SampleElements;
 import com.google.common.collect.testing.SetTestSuiteBuilder;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.Feature;
 import com.google.common.testing.SerializableTester;
 
@@ -62,7 +66,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
 
   @Override
   public TestSuite createTestSuite() {
-    withFeatures(CollectionFeature.KNOWN_ORDER);
+    withFeatures(KNOWN_ORDER);
     TestSuite suite = super.createTestSuite();
     for (TestSuite subSuite : createDerivedSuites(this)) {
       suite.addTest(subSuite);
@@ -81,7 +85,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
   @Override
   TestSuite createElementSetTestSuite(FeatureSpecificTestSuiteBuilder<
       ?, ? extends OneSizeTestContainerGenerator<Collection<E>, E>> parentBuilder) {
-    // TODO(user): make a SortedElementSetGenerator
+    // TODO(lowasser): make a SortedElementSetGenerator
     return SetTestSuiteBuilder
         .using(new ElementSetGenerator<E>(parentBuilder.getSubjectGenerator()))
         .named(getName() + ".elementSet")
@@ -118,7 +122,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
       derivedSuites.add(createDescendingSuite(parentBuilder));
     }
 
-    if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+    if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
       derivedSuites.add(createReserializedSuite(parentBuilder));
     }
 
@@ -152,11 +156,11 @@ public class SortedMultisetTestSuiteBuilder<E> extends
 
     Set<Feature<?>> features = new HashSet<Feature<?>>();
     features.add(NoRecurse.SUBMULTISET);
-    features.add(CollectionFeature.RESTRICTS_ELEMENTS);
+    features.add(RESTRICTS_ELEMENTS);
     features.addAll(parentBuilder.getFeatures());
 
-    if (!features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
-      features.remove(CollectionFeature.SERIALIZABLE);
+    if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) {
+      features.remove(SERIALIZABLE);
     }
 
     SortedMultiset<E> emptyMultiset = (SortedMultiset<E>) delegate.create();
@@ -164,8 +168,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
     SampleElements<E> samples = delegate.samples();
     @SuppressWarnings("unchecked")
     List<E> samplesList =
-        Arrays.asList(samples.e0, samples.e1, samples.e2, samples.e3,
-            samples.e4);
+        Arrays.asList(samples.e0(), samples.e1(), samples.e2(), samples.e3(),
+            samples.e4());
 
     Collections.sort(samplesList, comparator);
     final E firstInclusive = samplesList.get(0);
@@ -252,8 +256,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
     Set<Feature<?>> features = new HashSet<Feature<?>>();
     features.add(NoRecurse.DESCENDING);
     features.addAll(parentBuilder.getFeatures());
-    if (!features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
-      features.remove(CollectionFeature.SERIALIZABLE);
+    if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) {
+      features.remove(SERIALIZABLE);
     }
 
     return SortedMultisetTestSuiteBuilder
@@ -282,8 +286,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
 
     Set<Feature<?>> features = new HashSet<Feature<?>>();
     features.addAll(parentBuilder.getFeatures());
-    features.remove(CollectionFeature.SERIALIZABLE);
-    features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+    features.remove(SERIALIZABLE);
+    features.remove(SERIALIZABLE_INCLUDING_VIEWS);
 
     return SortedMultisetTestSuiteBuilder
         .using(new ForwardingTestMultisetGenerator<E>(delegate) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
index ee703d8..27af557 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
@@ -30,6 +30,6 @@ public class SortedSetMultimapGetTester<K, V>
   public void testValueComparator() {
     assertEquals(
         multimap().valueComparator(),
-        multimap().get(sampleKeys().e0).comparator());
+        multimap().get(k0()).comparator());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java b/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
index b136ff3..9c19699 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
@@ -22,6 +22,7 @@ import static junit.framework.TestCase.fail;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Iterators;
 import com.google.common.collect.LinkedHashMultiset;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -115,8 +116,12 @@ public class UnmodifiableCollectionTests {
       Collection<E> collection, E sampleElement) {
     Collection<E> siblingCollection = new ArrayList<E>();
     siblingCollection.add(sampleElement);
+
     Collection<E> copy = new ArrayList<E>();
-    copy.addAll(collection);
+    // Avoid copy.addAll(collection), which runs afoul of an Android bug in older versions:
+    // http://b.android.com/72073 http://r.android.com/98929
+    Iterators.addAll(copy, collection.iterator());
+
     try {
       collection.add(sampleElement);
       fail("add succeeded on unmodifiable collection");
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
index 1153d7e..28cdf9c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
@@ -50,7 +50,7 @@ public abstract class AbstractListIndexOfTester<E>
 
   public void testFind_no() {
     assertEquals(getMethodName() + "(notPresent) should return -1",
-        -1, find(samples.e3));
+        -1, find(e3()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_VALUES)
@@ -74,7 +74,7 @@ public abstract class AbstractListIndexOfTester<E>
   public void testFind_nonNullWhenNullContained() {
     initCollectionWithNullElement();
     assertEquals(getMethodName() + "(notPresent) should return -1",
-        -1, find(samples.e3));
+        -1, find(e3()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
index 4add759..ac62c67 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
@@ -68,7 +68,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAll_supportedNonePresent() {
     assertTrue("addAll(nonePresent) should return true",
         collection.addAll(createDisjointCollection()));
-    expectAdded(samples.e3, samples.e4);
+    expectAdded(e3(), e4());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -79,23 +79,23 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3, samples.e4);
+    expectMissing(e3(), e4());
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_supportedSomePresent() {
     assertTrue("addAll(somePresent) should return true",
-        collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
-    assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
-    assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
+        collection.addAll(MinimalCollection.of(e3(), e0())));
+    assertTrue("should contain " + e3(), collection.contains(e3()));
+    assertTrue("should contain " + e0(), collection.contains(e0()));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_unsupportedSomePresent() {
     try {
-      collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
+      collection.addAll(MinimalCollection.of(e3(), e0()));
       fail("addAll(somePresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -108,7 +108,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAllConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
+      assertTrue(collection.addAll(MinimalCollection.of(e3(), e0())));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -121,7 +121,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
   public void testAddAll_unsupportedAllPresent() {
     try {
       assertFalse("addAll(allPresent) should return false or throw",
-          collection.addAll(MinimalCollection.of(samples.e0)));
+          collection.addAll(MinimalCollection.of(e0())));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
index 1d1b84b..f00e092 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
@@ -47,19 +47,19 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAdd_supportedNotPresent() {
     assertTrue("add(notPresent) should return true",
-        collection.add(samples.e3));
-    expectAdded(samples.e3);
+        collection.add(e3()));
+    expectAdded(e3());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   public void testAdd_unsupportedNotPresent() {
     try {
-      collection.add(samples.e3);
+      collection.add(e3());
       fail("add(notPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -67,7 +67,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   public void testAdd_unsupportedPresent() {
     try {
       assertFalse("add(present) should return false or throw",
-          collection.add(samples.e0));
+          collection.add(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
@@ -100,7 +100,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
   public void testAddConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.add(samples.e3));
+      assertTrue(collection.add(e3()));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
index 9a2a9fc..276a4aa 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
@@ -43,6 +43,8 @@ public class CollectionClearTester<E> extends AbstractCollectionTester<E> {
     collection.clear();
     assertTrue("After clear(), a collection should be empty.",
         collection.isEmpty());
+    assertEquals(0, collection.size());
+    assertFalse(collection.iterator().hasNext());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
index 766b2c2..0f0efb8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
@@ -49,7 +49,7 @@ public class CollectionContainsAllTester<E>
   @CollectionSize.Require(absent = ZERO)
   public void testContainsAll_subset() {
     assertTrue("containsAll(subset) should return true",
-        collection.containsAll(MinimalCollection.of(samples.e0)));
+        collection.containsAll(MinimalCollection.of(e0())));
   }
 
   public void testContainsAll_sameElements() {
@@ -65,12 +65,12 @@ public class CollectionContainsAllTester<E>
 
   public void testContainsAll_partialOverlap() {
     assertFalse("containsAll(partialOverlap) should return false",
-        collection.containsAll(MinimalCollection.of(samples.e0, samples.e3)));
+        collection.containsAll(MinimalCollection.of(e0(), e3())));
   }
 
   public void testContainsAll_disjoint() {
     assertFalse("containsAll(disjoint) should return false",
-        collection.containsAll(MinimalCollection.of(samples.e3)));
+        collection.containsAll(MinimalCollection.of(e3())));
   }
 
   @CollectionFeature.Require(absent = ALLOWS_NULL_QUERIES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
index e9806fc..fded53d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
@@ -39,12 +39,12 @@ public class CollectionContainsTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testContains_yes() {
     assertTrue("contains(present) should return true",
-        collection.contains(samples.e0));
+        collection.contains(e0()));
   }
 
   public void testContains_no() {
     assertFalse("contains(notPresent) should return false",
-        collection.contains(samples.e3));
+        collection.contains(e3()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_QUERIES)
@@ -64,7 +64,7 @@ public class CollectionContainsTester<E> extends AbstractCollectionTester<E> {
   public void testContains_nonNullWhenNullContained() {
     initCollectionWithNullElement();
     assertFalse("contains(notPresent) should return false",
-        collection.contains(samples.e3));
+        collection.contains(e3()));
   }
 
   @CollectionFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
index 361d783..def85cf 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
@@ -55,7 +55,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemoveAll_nonePresent() {
     assertFalse("removeAll(disjointCollection) should return false",
-        collection.removeAll(MinimalCollection.of(samples.e3)));
+        collection.removeAll(MinimalCollection.of(e3())));
     expectUnchanged();
   }
 
@@ -63,16 +63,16 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveAll_allPresent() {
     assertTrue("removeAll(intersectingCollection) should return true",
-        collection.removeAll(MinimalCollection.of(samples.e0)));
-    expectMissing(samples.e0);
+        collection.removeAll(MinimalCollection.of(e0())));
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveAll_somePresent() {
     assertTrue("removeAll(intersectingCollection) should return true",
-        collection.removeAll(MinimalCollection.of(samples.e0, samples.e3)));
-    expectMissing(samples.e0);
+        collection.removeAll(MinimalCollection.of(e0(), e3())));
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -81,7 +81,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
   public void testRemoveAllSomePresentConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.removeAll(MinimalCollection.of(samples.e0, samples.e3)));
+      assertTrue(collection.removeAll(MinimalCollection.of(e0(), e3())));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -97,9 +97,9 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
   public void testRemoveAll_somePresentLargeCollectionToRemove() {
     assertTrue("removeAll(largeIntersectingCollection) should return true",
         collection.removeAll(MinimalCollection.of(
-            samples.e0, samples.e0, samples.e0,
-            samples.e3, samples.e3, samples.e3)));
-    expectMissing(samples.e0);
+            e0(), e0(), e0(),
+            e3(), e3(), e3())));
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -118,7 +118,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
     try {
       assertFalse("removeAll(disjointCollection) should return false or throw "
           + "UnsupportedOperationException",
-        collection.removeAll(MinimalCollection.of(samples.e3)));
+        collection.removeAll(MinimalCollection.of(e3())));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
@@ -128,13 +128,13 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testRemoveAll_unsupportedPresent() {
     try {
-      collection.removeAll(MinimalCollection.of(samples.e0));
+      collection.removeAll(MinimalCollection.of(e0()));
       fail("removeAll(intersectingCollection) should throw "
           + "UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    assertTrue(collection.contains(samples.e0));
+    assertTrue(collection.contains(e0()));
   }
 
   /*
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
index a1b67bc..c3bf265 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
@@ -47,10 +47,10 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
   public void testRemove_present() {
     int initialSize = collection.size();
     assertTrue("remove(present) should return true",
-        collection.remove(samples.e0));
+        collection.remove(e0()));
     assertEquals("remove(present) should decrease a collection's size by one.",
         initialSize - 1, collection.size());
-    expectMissing(samples.e0);
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -59,7 +59,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
   public void testRemovePresentConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      assertTrue(collection.remove(samples.e0));
+      assertTrue(collection.remove(e0()));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -70,7 +70,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_notPresent() {
     assertFalse("remove(notPresent) should return false",
-        collection.remove(samples.e3));
+        collection.remove(e3()));
     expectUnchanged();
   }
 
@@ -90,13 +90,13 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testRemove_unsupported() {
     try {
-      collection.remove(samples.e0);
+      collection.remove(e0());
       fail("remove(present) should throw UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
     assertTrue("remove(present) should not remove the element",
-        collection.contains(samples.e0));
+        collection.contains(e0()));
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -104,11 +104,11 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
     try {
       assertFalse("remove(notPresent) should return false or throw "
           + "UnsupportedOperationException",
-          collection.remove(samples.e3));
+          collection.remove(e3()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @CollectionFeature.Require(
@@ -141,7 +141,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    assertTrue(collection.contains(samples.e0));
+    assertTrue(collection.contains(e0()));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
index 73fd682..624c2ee 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
@@ -80,22 +80,22 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
      * MinimalCollection, which throws NullPointerException on calls to
      * contains(null).
      */
-    List<E> disjointList = Arrays.asList(samples.e3, samples.e4);
+    List<E> disjointList = Arrays.asList(e3(), e4());
     disjoint
         = new Target(disjointList, "disjoint");
     superset
         = new Target(MinimalCollection.of(
-            samples.e0, samples.e1, samples.e2, samples.e3, samples.e4),
+            e0(), e1(), e2(), e3(), e4()),
             "superset");
     nonEmptyProperSubset
-        = new Target(MinimalCollection.of(samples.e1), "subset");
+        = new Target(MinimalCollection.of(e1()), "subset");
     sameElements
         = new Target(Arrays.asList(createSamplesArray()), "sameElements");
     containsDuplicates = new Target(
-        MinimalCollection.of(samples.e0, samples.e0, samples.e3, samples.e3),
+        MinimalCollection.of(e0(), e0(), e3(), e3()),
         "containsDuplicates");
     partialOverlap
-        = new Target(MinimalCollection.of(samples.e2, samples.e3),
+        = new Target(MinimalCollection.of(e2(), e3()),
             "partialOverlap");
     nullSingleton
         = new Target(Collections.<E>singleton(null), "nullSingleton");
@@ -122,7 +122,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
   public void testRetainAll_emptyPreviouslyNonEmpty() {
     expectReturnsTrue(empty);
     expectContents();
-    expectMissing(samples.e0, samples.e1, samples.e2);
+    expectMissing(e0(), e1(), e2());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -153,7 +153,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
   public void testRetainAll_disjointPreviouslyNonEmpty() {
     expectReturnsTrue(disjoint);
     expectContents();
-    expectMissing(samples.e0, samples.e1, samples.e2);
+    expectMissing(e0(), e1(), e2());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -213,7 +213,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testRetainAll_partialOverlap() {
     expectReturnsTrue(partialOverlap);
-    expectContents(samples.e2);
+    expectContents(e2());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -229,14 +229,14 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
   @CollectionSize.Require(ONE)
   public void testRetainAll_containsDuplicatesSizeOne() {
     expectReturnsFalse(containsDuplicates);
-    expectContents(samples.e0);
+    expectContents(e0());
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testRetainAll_containsDuplicatesSizeSeveral() {
     expectReturnsTrue(containsDuplicates);
-    expectContents(samples.e0);
+    expectContents(e0());
   }
 
   // retainAll(nullSingleton)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
index 810dfaa..307af33 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
@@ -121,8 +121,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
 
   public void testToArray_oversizedArray() {
     E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
-    array[getNumElements()] = samples.e3;
-    array[getNumElements() + 1] = samples.e3;
+    array[getNumElements()] = e3();
+    array[getNumElements() + 1] = e3();
     assertSame("toArray(overSizedE[]) should return the given array",
         array, collection.toArray(array));
 
@@ -142,8 +142,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(KNOWN_ORDER)
   public void testToArray_oversizedArray_ordered() {
     E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
-    array[getNumElements()] = samples.e3;
-    array[getNumElements() + 1] = samples.e3;
+    array[getNumElements()] = e3();
+    array[getNumElements() + 1] = e3();
     assertSame("toArray(overSizedE[]) should return the given array",
         array, collection.toArray(array));
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
index 084ac6f..44d7177 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
@@ -54,7 +54,7 @@ public class CollectionToStringTester<E> extends AbstractCollectionTester<E> {
   @CollectionFeature.Require(absent = NON_STANDARD_TOSTRING)
   public void testToString_size1() {
     assertEquals("size1Collection.toString should return [{element}]",
-        "[" + samples.e0 + "]", collection.toString());
+        "[" + e0() + "]", collection.toString());
   }
 
   @CollectionSize.Require(SEVERAL)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java
new file mode 100644
index 0000000..c2cc16f
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 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.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code putIfAbsent} operations on a concurrent map. Can't be
+ * invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ * 
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapPutIfAbsentTester<K, V> extends AbstractMapTester<K, V> {
+  @Override
+  protected ConcurrentMap<K, V> getMap() {
+    return (ConcurrentMap<K, V>) super.getMap();
+  }
+
+  @MapFeature.Require(SUPPORTS_PUT)
+  public void testPutIfAbsent_supportedAbsent() {
+    assertNull("putIfAbsent(notPresent, value) should return null", putIfAbsent(e3()));
+    expectAdded(e3());
+  }
+  
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testPutIfAbsent_supportedPresent() {
+    assertEquals("putIfAbsent(present, value) should return existing value", 
+        v0(), getMap().putIfAbsent(k0(), v3()));
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  public void testPutIfAbsent_unsupportedAbsent() {
+    try {
+      putIfAbsent(e3());
+      fail("putIfAbsent(notPresent, value) should throw");
+    } catch (UnsupportedOperationException expected) {
+    }
+    expectUnchanged();
+    expectMissing(e3());
+  }
+
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testPutIfAbsent_unsupportedPresentExistingValue() {
+    try {
+      assertEquals("putIfAbsent(present, existingValue) should return present or throw",
+          v0(), putIfAbsent(e0()));
+    } catch (UnsupportedOperationException tolerated) {
+    }
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testPutIfAbsent_unsupportedPresentDifferentValue() {
+    try {
+      getMap().putIfAbsent(k0(), v3());
+    } catch (UnsupportedOperationException tolerated) {
+    }
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
+  public void testPutIfAbsent_nullKeyUnsupported() {
+    try {
+      getMap().putIfAbsent(null, v3());
+      fail("putIfAbsent(null, value) should throw");
+    } catch (NullPointerException expected) {
+    }
+    expectUnchanged();
+    expectNullKeyMissingWhenNullKeysUnsupported(
+        "Should not contain null key after unsupported putIfAbsent(null, value)");
+  }
+
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+  public void testPutIfAbsent_nullValueUnsupported() {
+    try {
+      getMap().putIfAbsent(k3(), null);
+      fail("putIfAbsent(key, null) should throw");
+    } catch (NullPointerException expected) {
+    }
+    expectUnchanged();
+    expectNullValueMissingWhenNullValuesUnsupported(
+        "Should not contain null value after unsupported put(key, null)");
+  }
+
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+  @CollectionSize.Require(absent = ZERO)
+  public void testPutIfAbsent_putWithNullValueUnsupported() {
+    try {
+      getMap().putIfAbsent(k0(), null);
+    } catch (NullPointerException tolerated) {
+    }
+    expectUnchanged();
+    expectNullValueMissingWhenNullValuesUnsupported(
+        "Should not contain null after unsupported putIfAbsent(present, null)");
+  }
+
+  private V putIfAbsent(Map.Entry<K, V> entry) {
+    return getMap().putIfAbsent(entry.getKey(), entry.getValue());
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java
new file mode 100644
index 0000000..1eaf340
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 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.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Tester for {@link ConcurrentMap#remove}.  Can't be invoked directly; please see 
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}. 
+ *
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapRemoveTester<K, V> extends AbstractMapTester<K, V> {
+  @Override
+  protected ConcurrentMap<K, V> getMap() {
+    return (ConcurrentMap<K, V>) super.getMap();
+  }
+
+  @MapFeature.Require(SUPPORTS_REMOVE)
+  @CollectionSize.Require(absent = ZERO)
+  public void testRemove_supportedPresent() {
+    assertTrue(getMap().remove(k0(), v0()));
+    expectMissing(e0());
+  }
+
+  @MapFeature.Require(SUPPORTS_REMOVE)
+  public void testRemove_supportedPresentKeyWrongValue() {
+    assertFalse(getMap().remove(k0(), v3()));
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(SUPPORTS_REMOVE)
+  public void testRemove_supportedWrongKeyPresentValue() {
+    assertFalse(getMap().remove(k3(), v0()));
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(SUPPORTS_REMOVE)
+  public void testRemove_supportedAbsentKeyAbsentValue() {
+    assertFalse(getMap().remove(k3(), v3()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_KEY_QUERIES)
+  public void testRemove_nullKeyQueriesUnsupported() {
+    try {
+      assertFalse(getMap().remove(null, v3()));
+    } catch (NullPointerException tolerated) {
+      // since the operation would be a no-op, the exception is not required
+    }
+    expectUnchanged();    
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_VALUE_QUERIES)
+  public void testRemove_nullValueQueriesUnsupported() {
+    try {
+      assertFalse(getMap().remove(k3(), null));
+    } catch (NullPointerException tolerated) {
+      // since the operation would be a no-op, the exception is not required
+    }
+    expectUnchanged();    
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_REMOVE)
+  @CollectionSize.Require(absent = ZERO)
+  public void testRemove_unsupportedPresent() {
+    try {
+      getMap().remove(k0(), v0());
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {}
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_REMOVE)
+  public void testRemove_unsupportedAbsent() {
+    try {
+      assertFalse(getMap().remove(k0(), v3()));
+    } catch (UnsupportedOperationException tolerated) {
+      // since the operation would be a no-op, the exception is not required
+    }
+    expectUnchanged();
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java
new file mode 100644
index 0000000..92f9be1
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 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.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code replace(K, V, V)} operations on a concurrent map. Can't 
+ * be invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ * 
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapReplaceEntryTester<K, V> extends AbstractMapTester<K, V> {
+  @Override
+  protected ConcurrentMap<K, V> getMap() {
+    return (ConcurrentMap<K, V>) super.getMap();
+  }
+  
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_supportedPresent() {
+    assertTrue(getMap().replace(k0(), v0(), v3()));
+    expectReplacement(entry(k0(), v3()));
+  }
+  
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_supportedPresentUnchanged() {
+    assertTrue(getMap().replace(k0(), v0(), v0()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_supportedWrongValue() {
+    assertFalse(getMap().replace(k0(), v3(), v4()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(SUPPORTS_PUT)
+  public void testReplaceEntry_supportedAbsentKey() {
+    assertFalse(getMap().replace(k3(), v3(), v4()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_presentNullValueUnsupported() {
+    try {
+      getMap().replace(k0(), v0(), null);
+      fail("Expected NullPointerException");
+    } catch (NullPointerException expected) {}
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES) 
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_wrongValueNullValueUnsupported() {
+    try {
+      assertFalse(getMap().replace(k0(), v3(), null));
+    } catch (NullPointerException tolerated) {
+      // the operation would be a no-op, so exceptions are allowed but not required
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES) 
+  public void testReplaceEntry_absentKeyNullValueUnsupported() {
+    try {
+      assertFalse(getMap().replace(k3(), v3(), null));
+    } catch (NullPointerException tolerated) {
+      // the operation would be a no-op, so exceptions are allowed but not required
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUE_QUERIES})
+  public void testReplaceEntry_nullDifferentFromAbsent() {
+    assertFalse(getMap().replace(k3(), null, v3()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+  public void testReplaceEntry_expectNullUnsupported() {
+    try {
+      assertFalse(getMap().replace(k3(), null, v3())); 
+    } catch (NullPointerException tolerated) {
+      // the operation would be a no-op, so exceptions are allowed but not required
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_unsupportedPresent() {
+    try {
+      getMap().replace(k0(), v0(), v3());
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {}
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplaceEntry_unsupportedWrongValue() {
+    try {
+      getMap().replace(k0(), v3(), v4());
+    } catch (UnsupportedOperationException tolerated) {
+      // the operation would be a no-op, so exceptions are allowed but not required
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  public void testReplaceEntry_unsupportedAbsentKey() {
+    try {
+      getMap().replace(k3(), v3(), v4());
+    } catch (UnsupportedOperationException tolerated) {
+      // the operation would be a no-op, so exceptions are allowed but not required
+    }
+    expectUnchanged();
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java
new file mode 100644
index 0000000..34657be
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 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.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code replace(K, V)} operations on a concurrent map. Can't be
+ * invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ * 
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapReplaceTester<K, V> extends AbstractMapTester<K, V> {
+  @Override
+  protected ConcurrentMap<K, V> getMap() {
+    return (ConcurrentMap<K, V>) super.getMap();
+  }
+
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplace_supportedPresent() {
+    assertEquals(v0(), getMap().replace(k0(), v3()));
+    expectReplacement(entry(k0(), v3()));
+  }
+
+  @MapFeature.Require(SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplace_supportedPresentNoChange() {
+    assertEquals(v0(), getMap().replace(k0(), v0()));
+    expectUnchanged();
+  }
+
+  @MapFeature.Require(SUPPORTS_PUT)
+  public void testReplace_supportedAbsent() {
+    assertNull(getMap().replace(k3(), v3()));
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplace_presentNullValueUnsupported() {
+    try {
+      getMap().replace(k0(), null);
+      fail("Expected NullPointerException");
+    } catch (NullPointerException expected) {}
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+  public void testReplace_absentNullValueUnsupported() {
+    try {
+      getMap().replace(k3(), null);
+    } catch (NullPointerException tolerated) {
+      // permitted not to throw because it would be a no-op
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEY_QUERIES)
+  public void testReplace_absentNullKeyUnsupported() {
+    try {
+      getMap().replace(null, v3());
+    } catch (NullPointerException tolerated) {
+      // permitted not to throw because it would be a no-op
+    }
+    expectUnchanged();
+  }
+  
+  @MapFeature.Require(absent = SUPPORTS_PUT)
+  @CollectionSize.Require(absent = ZERO)
+  public void testReplace_unsupportedPresent() {
+    try {
+      getMap().replace(k0(), v3());
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {}
+    expectUnchanged();
+  }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
index c1e03fd..35486cd 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
@@ -44,15 +44,15 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testAddAllAtIndex_supportedAllPresent() {
     assertTrue("addAll(n, allPresent) should return true",
-        getList().addAll(0, MinimalCollection.of(samples.e0)));
-    expectAdded(0, samples.e0);
+        getList().addAll(0, MinimalCollection.of(e0())));
+    expectAdded(0, e0());
   }
 
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAllAtIndex_unsupportedAllPresent() {
     try {
-      getList().addAll(0, MinimalCollection.of(samples.e0));
+      getList().addAll(0, MinimalCollection.of(e0()));
       fail("addAll(n, allPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -63,20 +63,20 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testAddAllAtIndex_supportedSomePresent() {
     assertTrue("addAll(n, allPresent) should return true",
-        getList().addAll(0, MinimalCollection.of(samples.e0, samples.e3)));
-    expectAdded(0, samples.e0, samples.e3);
+        getList().addAll(0, MinimalCollection.of(e0(), e3())));
+    expectAdded(0, e0(), e3());
   }
 
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAllAtIndex_unsupportedSomePresent() {
     try {
-      getList().addAll(0, MinimalCollection.of(samples.e0, samples.e3));
+      getList().addAll(0, MinimalCollection.of(e0(), e3()));
       fail("addAll(n, allPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -99,10 +99,10 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAllAtIndex_withDuplicates() {
     MinimalCollection<E> elementsToAdd
-        = MinimalCollection.of(samples.e0, samples.e1, samples.e0, samples.e1);
+        = MinimalCollection.of(e0(), e1(), e0(), e1());
     assertTrue("addAll(n, hasDuplicates) should return true",
         getList().addAll(0, elementsToAdd));
-    expectAdded(0, samples.e0, samples.e1, samples.e0, samples.e1);
+    expectAdded(0, e0(), e1(), e0(), e1());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -161,22 +161,22 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAllAtIndex_negative() {
     try {
-      getList().addAll(-1, MinimalCollection.of(samples.e3));
+      getList().addAll(-1, MinimalCollection.of(e3()));
       fail("addAll(-1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAllAtIndex_tooLarge() {
     try {
-      getList().addAll(getNumElements() + 1, MinimalCollection.of(samples.e3));
+      getList().addAll(getNumElements() + 1, MinimalCollection.of(e3()));
       fail("addAll(size + 1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
index c667937..c799c5b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
@@ -38,15 +38,15 @@ public class ListAddAllTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_supportedAllPresent() {
     assertTrue("addAll(allPresent) should return true",
-        getList().addAll(MinimalCollection.of(samples.e0)));
-    expectAdded(samples.e0);
+        getList().addAll(MinimalCollection.of(e0())));
+    expectAdded(e0());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_unsupportedAllPresent() {
     try {
-      getList().addAll(MinimalCollection.of(samples.e0));
+      getList().addAll(MinimalCollection.of(e0()));
       fail("addAll(allPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -56,9 +56,9 @@ public class ListAddAllTester<E> extends AbstractListTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddAll_withDuplicates() {
     MinimalCollection<E> elementsToAdd
-        = MinimalCollection.of(samples.e0, samples.e1, samples.e0, samples.e1);
+        = MinimalCollection.of(e0(), e1(), e0(), e1());
     assertTrue("addAll(hasDuplicates) should return true",
         getList().addAll(elementsToAdd));
-    expectAdded(samples.e0, samples.e1, samples.e0, samples.e1);
+    expectAdded(e0(), e1(), e0(), e1());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
index 7e6acd4..c9b21d3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
@@ -46,8 +46,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAtIndex_supportedPresent() {
-    getList().add(0, samples.e0);
-    expectAdded(0, samples.e0);
+    getList().add(0, e0());
+    expectAdded(0, e0());
   }
 
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@@ -58,7 +58,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
    */
   public void testAddAtIndex_unsupportedPresent() {
     try {
-      getList().add(0, samples.e0);
+      getList().add(0, e0());
       fail("add(n, present) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -67,8 +67,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_supportedNotPresent() {
-    getList().add(0, samples.e3);
-    expectAdded(0, samples.e3);
+    getList().add(0, e3());
+    expectAdded(0, e3());
   }
 
   @CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
@@ -76,7 +76,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   public void testAddAtIndexConcurrentWithIteration() {
     try {
       Iterator<E> iterator = collection.iterator();
-      getList().add(0, samples.e3);
+      getList().add(0, e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -87,26 +87,26 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_unsupportedNotPresent() {
     try {
-      getList().add(0, samples.e3);
+      getList().add(0, e3());
       fail("add(n, notPresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testAddAtIndex_middle() {
-    getList().add(getNumElements() / 2, samples.e3);
-    expectAdded(getNumElements() / 2, samples.e3);
+    getList().add(getNumElements() / 2, e3());
+    expectAdded(getNumElements() / 2, e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAtIndex_end() {
-    getList().add(getNumElements(), samples.e3);
-    expectAdded(getNumElements(), samples.e3);
+    getList().add(getNumElements(), e3());
+    expectAdded(getNumElements(), e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -132,23 +132,23 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_negative() {
     try {
-      getList().add(-1, samples.e3);
+      getList().add(-1, e3());
       fail("add(-1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testAddAtIndex_tooLarge() {
     try {
-      getList().add(getNumElements() + 1, samples.e3);
+      getList().add(getNumElements() + 1, e3());
       fail("add(size + 1, e) should throw");
     } catch (IndexOutOfBoundsException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   /**
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
index 9a65375..a2b80f0 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
@@ -42,8 +42,8 @@ public class ListAddTester<E> extends AbstractListTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAdd_supportedPresent() {
-    assertTrue("add(present) should return true", getList().add(samples.e0));
-    expectAdded(samples.e0);
+    assertTrue("add(present) should return true", getList().add(e0()));
+    expectAdded(e0());
   }
 
   @CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -54,7 +54,7 @@ public class ListAddTester<E> extends AbstractListTester<E> {
    */
   public void testAdd_unsupportedPresent() {
     try {
-      getList().add(samples.e0);
+      getList().add(e0());
       fail("add(present) should throw");
     } catch (UnsupportedOperationException expected) {
     }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
index af1cd76..bf4f142 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
@@ -37,7 +37,7 @@ public class ListCreationTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testCreateWithDuplicates() {
     E[] array = createSamplesArray();
-    array[1] = samples.e0;
+    array[1] = e0();
     collection = getSubjectGenerator().create(array);
 
     expectContents(array);
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
index 937ed6a..31e5352 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
@@ -43,7 +43,7 @@ public class ListEqualsTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   public void testEquals_otherListWithDifferentElements() {
     ArrayList<E> other = new ArrayList<E>(getSampleElements());
-    other.set(other.size() / 2, getSubjectGenerator().samples().e3);
+    other.set(other.size() / 2, getSubjectGenerator().samples().e3());
     assertFalse(
         "A List should not equal another List containing different elements.",
         getList().equals(other));
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
index d92b191..8798b02 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
@@ -45,9 +45,9 @@ public class ListIndexOfTester<E> extends AbstractListIndexOfTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testIndexOf_duplicate() {
     E[] array = createSamplesArray();
-    array[getNumElements() / 2] = samples.e0;
+    array[getNumElements() / 2] = e0();
     collection = getSubjectGenerator().create(array);
     assertEquals("indexOf(duplicate) should return index of first occurrence",
-        0, getList().indexOf(samples.e0));
+        0, getList().indexOf(e0()));
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
index b750878..5950faf 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
@@ -45,10 +45,10 @@ public class ListLastIndexOfTester<E> extends AbstractListIndexOfTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testLastIndexOf_duplicate() {
     E[] array = createSamplesArray();
-    array[getNumElements() / 2] = samples.e0;
+    array[getNumElements() / 2] = e0();
     collection = getSubjectGenerator().create(array);
     assertEquals(
         "lastIndexOf(duplicate) should return index of last occurrence",
-        getNumElements() / 2, getList().lastIndexOf(samples.e0));
+        getNumElements() / 2, getList().lastIndexOf(e0()));
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
index 589273d..e87c764 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
@@ -68,7 +68,7 @@ public class ListListIteratorTester<E> extends AbstractListTester<E> {
 
   private void runListIteratorTest(Set<IteratorFeature> features) {
     new ListIteratorTester<E>(
-        listListIteratorTesterNumIterations(), singleton(samples.e4), features,
+        listListIteratorTesterNumIterations(), singleton(e4()), features,
         Helpers.copyToList(getOrderedElements()), 0) {
       {
         // TODO: don't set this universally
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
index 96a005d..befc3d2 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
@@ -16,11 +16,11 @@
 
 package com.google.common.collect.testing.testers;
 
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
 import static com.google.common.collect.testing.features.CollectionSize.ONE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.testing.MinimalCollection;
@@ -42,7 +42,7 @@ public class ListRetainAllTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testRetainAll_duplicatesKept() {
     E[] array = createSamplesArray();
-    array[1] = samples.e0;
+    array[1] = e0();
     collection = getSubjectGenerator().create(array);
     assertFalse("containsDuplicates.retainAll(superset) should return false",
         collection.retainAll(MinimalCollection.of(createSamplesArray())));
@@ -54,19 +54,20 @@ public class ListRetainAllTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(SEVERAL)
   public void testRetainAll_duplicatesRemoved() {
     E[] array = createSamplesArray();
-    array[1] = samples.e0;
+    array[1] = e0();
     collection = getSubjectGenerator().create(array);
     assertTrue("containsDuplicates.retainAll(subset) should return true",
-        collection.retainAll(MinimalCollection.of(samples.e2)));
-    expectContents(samples.e2);
+        collection.retainAll(MinimalCollection.of(e2())));
+    expectContents(e2());
   }
-  
+
   @SuppressWarnings("unchecked")
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(SEVERAL)
   public void testRetainAll_countIgnored() {
-    resetContainer(getSubjectGenerator().create(samples.e0, samples.e2, samples.e1, samples.e0));
-    assertTrue(getList().retainAll(Arrays.asList(samples.e0, samples.e1)));
-    assertThat(getList()).has().exactly(samples.e0, samples.e1, samples.e0).inOrder();
+    resetContainer(
+        getSubjectGenerator().create(e0(), e2(), e1(), e0()));
+    assertTrue(getList().retainAll(Arrays.asList(e0(), e1())));
+    assertContentsInOrder(getList(), e0(), e1(), e0());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
index 94f418c..768173b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
@@ -41,7 +41,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = ZERO)
   public void testSet() {
-    doTestSet(samples.e3);
+    doTestSet(e3());
   }
 
   @CollectionSize.Require(absent = ZERO)
@@ -60,7 +60,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
     elements[i] = null;
     collection = getSubjectGenerator().create(elements);
 
-    doTestSet(samples.e3);
+    doTestSet(e3());
   }
 
   private void doTestSet(E newValue) {
@@ -77,7 +77,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_SET)
   public void testSet_indexTooLow() {
     try {
-      getList().set(-1, samples.e3);
+      getList().set(-1, e3());
       fail("set(-1) should throw IndexOutOfBoundsException");
     } catch (IndexOutOfBoundsException expected) {
     }
@@ -88,7 +88,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   public void testSet_indexTooHigh() {
     int index = getNumElements();
     try {
-      getList().set(index, samples.e3);
+      getList().set(index, e3());
       fail("set(size) should throw IndexOutOfBoundsException");
     } catch (IndexOutOfBoundsException expected) {
     }
@@ -99,7 +99,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_SET)
   public void testSet_unsupported() {
     try {
-      getList().set(aValidIndex(), samples.e3);
+      getList().set(aValidIndex(), e3());
       fail("set() should throw UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
     }
@@ -110,7 +110,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(absent = SUPPORTS_SET)
   public void testSet_unsupportedByEmptyList() {
     try {
-      getList().set(0, samples.e3);
+      getList().set(0, e3());
       fail("set() should throw UnsupportedOperationException "
           + "or IndexOutOfBoundsException");
     } catch (UnsupportedOperationException tolerated) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
index 2883f3d..5309ca8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
@@ -113,17 +113,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
   public void testSubList_subListAddAffectsOriginal() {
     List<E> subList = getList().subList(0, 0);
-    subList.add(samples.e3);
-    expectAdded(0, samples.e3);
+    subList.add(e3());
+    expectAdded(0, e3());
   }
 
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = ZERO)
   public void testSubList_subListSetAffectsOriginal() {
     List<E> subList = getList().subList(0, 1);
-    subList.set(0, samples.e3);
+    subList.set(0, e3());
     List<E> expected = Helpers.copyToList(createSamplesArray());
-    expected.set(0, samples.e3);
+    expected.set(0, e3());
     expectContents(expected);
   }
 
@@ -131,17 +131,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testSubList_originalListSetAffectsSubList() {
     List<E> subList = getList().subList(0, 1);
-    getList().set(0, samples.e3);
+    getList().set(0, e3());
     assertEquals("A set() call to a list after a sublist has been created "
         + "should be reflected in the sublist",
-        Collections.singletonList(samples.e3), subList);
+        Collections.singletonList(e3()), subList);
   }
 
   @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListRemoveAffectsOriginalLargeList() {
     List<E> subList = getList().subList(1, 3);
-    subList.remove(samples.e2);
+    subList.remove(e2());
     List<E> expected = Helpers.copyToList(createSamplesArray());
     expected.remove(2);
     expectContents(expected);
@@ -151,17 +151,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListAddAtIndexAffectsOriginalLargeList() {
     List<E> subList = getList().subList(2, 3);
-    subList.add(0, samples.e3);
-    expectAdded(2, samples.e3);
+    subList.add(0, e3());
+    expectAdded(2, e3());
   }
 
   @ListFeature.Require(SUPPORTS_SET)
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_subListSetAffectsOriginalLargeList() {
     List<E> subList = getList().subList(1, 2);
-    subList.set(0, samples.e3);
+    subList.set(0, e3());
     List<E> expected = Helpers.copyToList(createSamplesArray());
-    expected.set(1, samples.e3);
+    expected.set(1, e3());
     expectContents(expected);
   }
 
@@ -169,10 +169,10 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testSubList_originalListSetAffectsSubListLargeList() {
     List<E> subList = getList().subList(1, 3);
-    getList().set(1, samples.e3);
+    getList().set(1, e3());
     assertEquals("A set() call to a list after a sublist has been created "
         + "should be reflected in the sublist",
-        Arrays.asList(samples.e3, samples.e2), subList);
+        Arrays.asList(e3(), e2()), subList);
   }
 
   public void testSubList_ofSubListEmpty() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
index 8de9998..92640a4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
@@ -45,6 +45,8 @@ public class MapClearTester<K, V> extends AbstractMapTester<K, V> {
     getMap().clear();
     assertTrue("After clear(), a map should be empty.",
         getMap().isEmpty());
+    assertEquals(0, getMap().size());
+    assertFalse(getMap().entrySet().iterator().hasNext());
   }
 
   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION,
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
index d933efd..8c49b74 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
@@ -38,12 +38,12 @@ public class MapContainsKeyTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testContains_yes() {
     assertTrue("containsKey(present) should return true",
-        getMap().containsKey(samples.e0.getKey()));
+        getMap().containsKey(k0()));
   }
 
   public void testContains_no() {
     assertFalse("containsKey(notPresent) should return false",
-        getMap().containsKey(samples.e3.getKey()));
+        getMap().containsKey(k3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
@@ -63,7 +63,7 @@ public class MapContainsKeyTester<K, V> extends AbstractMapTester<K, V> {
   public void testContains_nonNullWhenNullContained() {
     initMapWithNullKey();
     assertFalse("containsKey(notPresent) should return false",
-        getMap().containsKey(samples.e3.getKey()));
+        getMap().containsKey(k3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_KEYS)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
index 8ddfe27..a114dce 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
@@ -17,7 +17,8 @@
 package com.google.common.collect.testing.testers;
 
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.collect.testing.features.MapFeature.*;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.testing.AbstractMapTester;
@@ -38,12 +39,12 @@ public class MapContainsValueTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testContains_yes() {
     assertTrue("containsValue(present) should return true",
-        getMap().containsValue(samples.e0.getValue()));
+        getMap().containsValue(v0()));
   }
 
   public void testContains_no() {
     assertFalse("containsValue(notPresent) should return false",
-        getMap().containsValue(samples.e3.getValue()));
+        getMap().containsValue(v3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
@@ -63,7 +64,7 @@ public class MapContainsValueTester<K, V> extends AbstractMapTester<K, V> {
   public void testContains_nonNullWhenNullContained() {
     initMapWithNullValue();
     assertFalse("containsValue(notPresent) should return false",
-        getMap().containsValue(samples.e3.getValue()));
+        getMap().containsValue(v3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
index 1a3f86b..2369fca 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
@@ -130,7 +130,7 @@ public class MapCreationTester<K, V> extends AbstractMapTester<K, V> {
 
   private Entry<K, V>[] getEntriesMultipleNonNullKeys() {
     Entry<K, V>[] entries = createSamplesArray();
-    entries[0] = entry(samples.e1.getKey(), samples.e0.getValue());
+    entries[0] = entry(k1(), v0());
     return entries;
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
index 447cc06..b7fe855 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
@@ -55,26 +55,34 @@ public class MapEntrySetTester<K, V> extends AbstractMapTester<K, V> {
   public void testEntrySetIteratorRemove() {
     Set<Entry<K, V>> entrySet = getMap().entrySet();
     Iterator<Entry<K, V>> entryItr = entrySet.iterator();
-    assertEquals(samples.e0, entryItr.next());
+    assertEquals(e0(), entryItr.next());
     entryItr.remove();
     assertTrue(getMap().isEmpty());
-    assertFalse(entrySet.contains(samples.e0));
+    assertFalse(entrySet.contains(e0()));
   }
 
   public void testContainsEntryWithIncomparableKey() {
-    assertFalse(getMap()
-        .entrySet().contains(Helpers.mapEntry(IncomparableType.INSTANCE, samples.e0.getValue())));
+    try {
+      assertFalse(getMap()
+          .entrySet().contains(Helpers.mapEntry(IncomparableType.INSTANCE, v0())));
+    } catch (ClassCastException acceptable) {
+      // allowed by the spec
+    }
   }
 
   public void testContainsEntryWithIncomparableValue() {
-    assertFalse(getMap()
-        .entrySet().contains(Helpers.mapEntry(samples.e0.getKey(), IncomparableType.INSTANCE)));
+    try {
+      assertFalse(getMap()
+          .entrySet().contains(Helpers.mapEntry(k0(), IncomparableType.INSTANCE)));
+    } catch (ClassCastException acceptable) {
+      // allowed by the spec
+    }
   }
   
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
   public void testContainsEntryWithNullKeyAbsent() {
     assertFalse(getMap()
-        .entrySet().contains(Helpers.mapEntry(null, samples.e0.getValue())));
+        .entrySet().contains(Helpers.mapEntry(null, v0())));
   }
   
   @CollectionSize.Require(absent = ZERO)
@@ -88,7 +96,7 @@ public class MapEntrySetTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
   public void testContainsEntryWithNullValueAbsent() {
     assertFalse(getMap()
-        .entrySet().contains(Helpers.mapEntry(samples.e0.getKey(), null)));
+        .entrySet().contains(Helpers.mapEntry(k0(), null)));
   }
   
   @CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
index f2b2cbc..a01b206 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
@@ -28,7 +28,6 @@ import com.google.common.collect.testing.features.MapFeature;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 
 /**
  * Tests {@link java.util.Map#equals}.
@@ -47,8 +46,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   public void testEquals_otherMapWithDifferentEntries() {
     Map<K, V> other = newHashMap(getSampleEntries(getNumEntries() - 1));
-    Entry<K, V> e3 = getSubjectGenerator().samples().e3;
-    other.put(e3.getKey(), e3.getValue());
+    other.put(k3(), v3());
     assertFalse(
         "A Map should not equal another Map containing different entries.",
         getMap().equals(other)
@@ -59,7 +57,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(ALLOWS_NULL_KEYS)
   public void testEquals_containingNullKey() {
     Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
-    entries.add(entry(null, samples.e3.getValue()));
+    entries.add(entry(null, v3()));
 
     resetContainer(getSubjectGenerator().create(entries.toArray()));
     assertTrue("A Map should equal any other Map containing the same entries,"
@@ -70,7 +68,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   public void testEquals_otherContainsNullKey() {
     Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
-    entries.add(entry(null, samples.e3.getValue()));
+    entries.add(entry(null, v3()));
     Map<K, V> other = newHashMap(entries);
 
     assertFalse(
@@ -83,7 +81,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(ALLOWS_NULL_VALUES)
   public void testEquals_containingNullValue() {
     Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
-    entries.add(entry(samples.e3.getKey(), null));
+    entries.add(entry(k3(), null));
 
     resetContainer(getSubjectGenerator().create(entries.toArray()));
     assertTrue("A Map should equal any other Map containing the same entries,"
@@ -94,7 +92,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   public void testEquals_otherContainsNullValue() {
     Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
-    entries.add(entry(samples.e3.getKey(), null));
+    entries.add(entry(k3(), null));
     Map<K, V> other = newHashMap(entries);
 
     assertFalse(
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
index f5e0ba7..8aa817d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
@@ -39,11 +39,11 @@ public class MapGetTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testGet_yes() {
     assertEquals("get(present) should return the associated value",
-        samples.e0.getValue(), get(samples.e0.getKey()));
+        v0(), get(k0()));
   }
 
   public void testGet_no() {
-    assertNull("get(notPresent) should return null", get(samples.e3.getKey()));
+    assertNull("get(notPresent) should return null", get(k3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
@@ -63,7 +63,7 @@ public class MapGetTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testGet_nonNullWhenNullContained() {
     initMapWithNullKey();
-    assertNull("get(notPresent) should return null", get(samples.e3.getKey()));
+    assertNull("get(notPresent) should return null", get(k3()));
   }
 
   @MapFeature.Require(ALLOWS_NULL_KEYS)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
index e030a54..712b124 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
@@ -48,14 +48,14 @@ public class MapHashCodeTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   @MapFeature.Require(ALLOWS_NULL_KEYS)
   public void testHashCode_containingNullKey() {
-    Map.Entry<K, V> entryWithNull = entry(null, samples.e3.getValue());
+    Map.Entry<K, V> entryWithNull = entry(null, v3());
     runEntryWithNullTest(entryWithNull);
   }
 
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   @MapFeature.Require(ALLOWS_NULL_VALUES)
   public void testHashCode_containingNullValue() {
-    Map.Entry<K, V> entryWithNull = entry(samples.e3.getKey(), null);
+    Map.Entry<K, V> entryWithNull = entry(k3(), null);
     runEntryWithNullTest(entryWithNull);
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
index 075fa82..3bef211 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
@@ -56,8 +56,8 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
 
   @Override public void setUp() throws Exception {
     super.setUp();
-    containsNullKey = singletonList(entry(null, samples.e3.getValue()));
-    containsNullValue = singletonList(entry(samples.e3.getKey(), null));
+    containsNullKey = singletonList(entry(null, v3()));
+    containsNullValue = singletonList(entry(k3(), null));
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
@@ -78,7 +78,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPutAll_supportedNonePresent() {
     putAll(createDisjointCollection());
-    expectAdded(samples.e3, samples.e4);
+    expectAdded(e3(), e4());
   }
 
   @MapFeature.Require(absent = SUPPORTS_PUT)
@@ -89,14 +89,14 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3, samples.e4);
+    expectMissing(e3(), e4());
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_supportedSomePresent() {
-    putAll(MinimalCollection.of(samples.e3, samples.e0));
-    expectAdded(samples.e3);
+    putAll(MinimalCollection.of(e3(), e0()));
+    expectAdded(e3());
   }
 
   @MapFeature.Require({ FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -105,7 +105,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAllSomePresentConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
-      putAll(MinimalCollection.of(samples.e3, samples.e0));
+      putAll(MinimalCollection.of(e3(), e0()));
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -117,7 +117,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_unsupportedSomePresent() {
     try {
-      putAll(MinimalCollection.of(samples.e3, samples.e0));
+      putAll(MinimalCollection.of(e3(), e0()));
       fail("putAll(somePresent) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -128,7 +128,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPutAll_unsupportedAllPresent() {
     try {
-      putAll(MinimalCollection.of(samples.e0));
+      putAll(MinimalCollection.of(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
index 6fb2918..13ee949 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
@@ -53,16 +53,16 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
 
   @Override public void setUp() throws Exception {
     super.setUp();
-    nullKeyEntry = entry(null, samples.e3.getValue());
-    nullValueEntry = entry(samples.e3.getKey(), null);
+    nullKeyEntry = entry(null, v3());
+    nullValueEntry = entry(k3(), null);
     nullKeyValueEntry = entry(null, null);
-    presentKeyNullValueEntry = entry(samples.e0.getKey(), null);
+    presentKeyNullValueEntry = entry(k0(), null);
   }
 
   @MapFeature.Require(SUPPORTS_PUT)
   public void testPut_supportedNotPresent() {
-    assertNull("put(notPresent, value) should return null", put(samples.e3));
-    expectAdded(samples.e3);
+    assertNull("put(notPresent, value) should return null", put(e3()));
+    expectAdded(e3());
   }
 
   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
@@ -70,7 +70,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -83,7 +83,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithKeySetIteration() {
     try {
       Iterator<K> iterator = getMap().keySet().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -96,7 +96,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPutAbsentConcurrentWithValueIteration() {
     try {
       Iterator<V> iterator = getMap().values().iterator();
-      put(samples.e3);
+      put(e3());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -107,12 +107,12 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(absent = SUPPORTS_PUT)
   public void testPut_unsupportedNotPresent() {
     try {
-      put(samples.e3);
+      put(e3());
       fail("put(notPresent, value) should throw");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @MapFeature.Require(absent = SUPPORTS_PUT)
@@ -120,7 +120,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   public void testPut_unsupportedPresentExistingValue() {
     try {
       assertEquals("put(present, existingValue) should return present or throw",
-          samples.e0.getValue(), put(samples.e0));
+          v0(), put(e0()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
@@ -130,7 +130,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPut_unsupportedPresentDifferentValue() {
     try {
-      getMap().put(samples.e0.getKey(), samples.e3.getValue());
+      getMap().put(k0(), v3());
       fail("put(present, differentValue) should throw");
     } catch (UnsupportedOperationException expected) {
     }
@@ -146,7 +146,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
   @CollectionSize.Require(absent = ZERO)
   public void testPut_nullKeySupportedPresent() {
-    Entry<K, V> newEntry = entry(null, samples.e3.getValue());
+    Entry<K, V> newEntry = entry(null, v3());
     initMapWithNullKey();
     assertEquals("put(present, value) should return the associated value",
         getValueForNullKey(), put(newEntry));
@@ -190,7 +190,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testPut_replaceWithNullValueSupported() {
     assertEquals("put(present, null) should return the associated value",
-        samples.e0.getValue(), put(presentKeyNullValueEntry));
+        v0(), put(presentKeyNullValueEntry));
     expectReplacement(presentKeyNullValueEntry);
   }
 
@@ -219,7 +219,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
   @CollectionSize.Require(absent = ZERO)
   public void testPut_replaceNullValueWithNonNullSupported() {
-    Entry<K, V> newEntry = entry(getKeyForNullValue(), samples.e3.getValue());
+    Entry<K, V> newEntry = entry(getKeyForNullValue(), v3());
     initMapWithNullValue();
     assertNull("put(present, value) should return the associated value (null)",
         put(newEntry));
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
index 5310a8e..7cc960e 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
@@ -49,10 +49,10 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   public void testRemove_present() {
     int initialSize = getMap().size();
     assertEquals("remove(present) should return the associated value",
-        samples.e0.getValue(), getMap().remove(samples.e0.getKey()));
+        v0(), getMap().remove(k0()));
     assertEquals("remove(present) should decrease a map's size by one.",
         initialSize - 1, getMap().size());
-    expectMissing(samples.e0);
+    expectMissing(e0());
   }
 
   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -61,7 +61,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   public void testRemovePresentConcurrentWithEntrySetIteration() {
     try {
       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
-      getMap().remove(samples.e0.getKey());
+      getMap().remove(k0());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -75,7 +75,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   public void testRemovePresentConcurrentWithKeySetIteration() {
     try {
       Iterator<K> iterator = getMap().keySet().iterator();
-      getMap().remove(samples.e0.getKey());
+      getMap().remove(k0());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -89,7 +89,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   public void testRemovePresentConcurrentWithValuesIteration() {
     try {
       Iterator<V> iterator = getMap().values().iterator();
-      getMap().remove(samples.e0.getKey());
+      getMap().remove(k0());
       iterator.next();
       fail("Expected ConcurrentModificationException");
     } catch (ConcurrentModificationException expected) {
@@ -100,7 +100,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   @MapFeature.Require(SUPPORTS_REMOVE)
   public void testRemove_notPresent() {
     assertNull("remove(notPresent) should return null",
-        getMap().remove(samples.e3.getKey()));
+        getMap().remove(k3()));
     expectUnchanged();
   }
 
@@ -121,13 +121,13 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(absent = ZERO)
   public void testRemove_unsupported() {
     try {
-      getMap().remove(samples.e0.getKey());
+      getMap().remove(k0());
       fail("remove(present) should throw UnsupportedOperationException");
     } catch (UnsupportedOperationException expected) {
     }
     expectUnchanged();
     assertEquals("remove(present) should not remove the element",
-        samples.e0.getValue(), get(samples.e0.getKey()));
+        v0(), get(k0()));
   }
 
   @MapFeature.Require(absent = SUPPORTS_REMOVE)
@@ -135,11 +135,11 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
     try {
       assertNull("remove(notPresent) should return null or throw "
           + "UnsupportedOperationException",
-          getMap().remove(samples.e3.getKey()));
+          getMap().remove(k3()));
     } catch (UnsupportedOperationException tolerated) {
     }
     expectUnchanged();
-    expectMissing(samples.e3);
+    expectMissing(e3());
   }
 
   @MapFeature.Require(
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
index 2d01349..2b9709f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
@@ -50,7 +50,7 @@ public class MapToStringTester<K, V> extends AbstractMapTester<K, V> {
   @CollectionSize.Require(ONE)
   public void testToString_size1() {
     assertEquals(
-        "size1Map.toString should return {entry}", "{" + samples.e0 + "}", getMap().toString());
+        "size1Map.toString should return {entry}", "{" + e0() + "}", getMap().toString());
   }
 
   @CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
index daf46ff..dbb3489 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
@@ -88,14 +88,14 @@ public class NavigableMapNavigationTester<K, V> extends AbstractMapTester<K, V>
 
   @CollectionSize.Require(ZERO)
   public void testEmptyMapNearby() {
-    assertNull(navigableMap.lowerEntry(samples.e0.getKey()));
-    assertNull(navigableMap.lowerKey(samples.e0.getKey()));
-    assertNull(navigableMap.floorEntry(samples.e0.getKey()));
-    assertNull(navigableMap.floorKey(samples.e0.getKey()));
-    assertNull(navigableMap.ceilingEntry(samples.e0.getKey()));
-    assertNull(navigableMap.ceilingKey(samples.e0.getKey()));
-    assertNull(navigableMap.higherEntry(samples.e0.getKey()));
-    assertNull(navigableMap.higherKey(samples.e0.getKey()));
+    assertNull(navigableMap.lowerEntry(k0()));
+    assertNull(navigableMap.lowerKey(k0()));
+    assertNull(navigableMap.floorEntry(k0()));
+    assertNull(navigableMap.floorKey(k0()));
+    assertNull(navigableMap.ceilingEntry(k0()));
+    assertNull(navigableMap.ceilingKey(k0()));
+    assertNull(navigableMap.higherEntry(k0()));
+    assertNull(navigableMap.higherKey(k0()));
   }
 
   @CollectionSize.Require(ZERO)
@@ -123,14 +123,14 @@ public class NavigableMapNavigationTester<K, V> extends AbstractMapTester<K, V>
 
   @CollectionSize.Require(ONE)
   public void testSingletonMapNearby() {
-    assertNull(navigableMap.lowerEntry(samples.e0.getKey()));
-    assertNull(navigableMap.lowerKey(samples.e0.getKey()));
-    assertEquals(a, navigableMap.floorEntry(samples.e0.getKey()));
-    assertEquals(a.getKey(), navigableMap.floorKey(samples.e0.getKey()));
-    assertEquals(a, navigableMap.ceilingEntry(samples.e0.getKey()));
-    assertEquals(a.getKey(), navigableMap.ceilingKey(samples.e0.getKey()));
-    assertNull(navigableMap.higherEntry(samples.e0.getKey()));
-    assertNull(navigableMap.higherKey(samples.e0.getKey()));
+    assertNull(navigableMap.lowerEntry(k0()));
+    assertNull(navigableMap.lowerKey(k0()));
+    assertEquals(a, navigableMap.floorEntry(k0()));
+    assertEquals(a.getKey(), navigableMap.floorKey(k0()));
+    assertEquals(a, navigableMap.ceilingEntry(k0()));
+    assertEquals(a.getKey(), navigableMap.ceilingKey(k0()));
+    assertNull(navigableMap.higherEntry(k0()));
+    assertNull(navigableMap.higherKey(k0()));
   }
 
   @CollectionSize.Require(ONE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
index 14c6a47..b1ba7ff 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
@@ -82,10 +82,10 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
 
   @CollectionSize.Require(ZERO)
   public void testEmptySetNearby() {
-    assertNull(navigableSet.lower(samples.e0));
-    assertNull(navigableSet.floor(samples.e0));
-    assertNull(navigableSet.ceiling(samples.e0));
-    assertNull(navigableSet.higher(samples.e0));
+    assertNull(navigableSet.lower(e0()));
+    assertNull(navigableSet.floor(e0()));
+    assertNull(navigableSet.ceiling(e0()));
+    assertNull(navigableSet.higher(e0()));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
@@ -103,10 +103,10 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
 
   @CollectionSize.Require(ONE)
   public void testSingletonSetNearby() {
-    assertNull(navigableSet.lower(samples.e0));
-    assertEquals(a, navigableSet.floor(samples.e0));
-    assertEquals(a, navigableSet.ceiling(samples.e0));
-    assertNull(navigableSet.higher(samples.e0));
+    assertNull(navigableSet.lower(e0()));
+    assertEquals(a, navigableSet.floor(e0()));
+    assertEquals(a, navigableSet.ceiling(e0()));
+    assertNull(navigableSet.higher(e0()));
   }
 
   @CollectionFeature.Require(SUPPORTS_REMOVE)
@@ -226,7 +226,7 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
   }
 
   public void testEmptySubSet() {
-    NavigableSet<E> empty = navigableSet.subSet(samples.e0, false, samples.e0, false);
+    NavigableSet<E> empty = navigableSet.subSet(e0(), false, e0(), false);
     assertEquals(new TreeSet<E>(), empty);
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java b/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
index bb40f8e..e76f5f2 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
@@ -18,6 +18,8 @@ package com.google.common.collect.testing.testers;
 
 import com.google.common.annotations.GwtCompatible;
 
+import java.util.Locale;
+
 /**
  * This class is emulated in GWT.
  *
@@ -31,7 +33,7 @@ final class Platform {
    * {@code %s}.
    */
   static String format(String template, Object... args) {
-    return String.format(template, args);
+    return String.format(Locale.ROOT, template, args);
   }
 
   /** See {@link ListListIteratorTester} */
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
index 6282c1b..efa6b0f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
@@ -48,7 +48,7 @@ public class QueueElementTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(ONE)
   public void testElement_size1() {
     assertEquals("size1Queue.element() should return first element",
-        samples.e0, getQueue().element());
+        e0(), getQueue().element());
     expectUnchanged();
   }
 
@@ -56,7 +56,7 @@ public class QueueElementTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(SEVERAL)
   public void testElement_sizeMany() {
     assertEquals("sizeManyQueue.element() should return first element",
-        samples.e0, getQueue().element());
+        e0(), getQueue().element());
     expectUnchanged();
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
index e38b6a2..92a9a23 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
@@ -35,8 +35,8 @@ public class QueueOfferTester<E> extends AbstractQueueTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testOffer_supportedNotPresent() {
     assertTrue("offer(notPresent) should return true",
-        getQueue().offer(samples.e3));
-    expectAdded(samples.e3);
+        getQueue().offer(e3()));
+    expectAdded(e3());
   }
 
   @CollectionFeature.Require({SUPPORTS_ADD, ALLOWS_NULL_VALUES})
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
index 5d270c5..fa83281 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
@@ -43,7 +43,7 @@ public class QueuePeekTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(ONE)
   public void testPeek_size1() {
     assertEquals("size1Queue.peek() should return first element",
-        samples.e0, getQueue().peek());
+        e0(), getQueue().peek());
     expectUnchanged();
   }
 
@@ -51,7 +51,7 @@ public class QueuePeekTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(SEVERAL)
   public void testPeek_sizeMany() {
     assertEquals("sizeManyQueue.peek() should return first element",
-        samples.e0, getQueue().peek());
+        e0(), getQueue().peek());
     expectUnchanged();
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
index fd10a3d..ae0cba8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
@@ -47,15 +47,15 @@ public class QueuePollTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(ONE)
   public void testPoll_size1() {
     assertEquals("size1Queue.poll() should return first element",
-        samples.e0, getQueue().poll());
-    expectMissing(samples.e0);
+        e0(), getQueue().poll());
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
   @CollectionSize.Require(SEVERAL)
   public void testPoll_sizeMany() {
     assertEquals("sizeManyQueue.poll() should return first element",
-        samples.e0, getQueue().poll());
-    expectMissing(samples.e0);
+        e0(), getQueue().poll());
+    expectMissing(e0());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
index 07f447f..70c9513 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
@@ -52,15 +52,15 @@ public class QueueRemoveTester<E> extends AbstractQueueTester<E> {
   @CollectionSize.Require(ONE)
   public void testRemove_size1() {
     assertEquals("size1Queue.remove() should return first element",
-        samples.e0, getQueue().remove());
-    expectMissing(samples.e0);
+        e0(), getQueue().remove());
+    expectMissing(e0());
   }
 
   @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
   @CollectionSize.Require(SEVERAL)
   public void testRemove_sizeMany() {
     assertEquals("sizeManyQueue.remove() should return first element",
-        samples.e0, getQueue().remove());
-    expectMissing(samples.e0);
+        e0(), getQueue().remove());
+    expectMissing(e0());
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
index 4d2bfcc..b9d55f7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
@@ -38,24 +38,24 @@ public class SetAddAllTester<E> extends AbstractSetTester<E> {
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_supportedSomePresent() {
     assertTrue("add(somePresent) should return true",
-        getSet().addAll(MinimalCollection.of(samples.e3, samples.e0)));
-    expectAdded(samples.e3);
+        getSet().addAll(MinimalCollection.of(e3(), e0())));
+    expectAdded(e3());
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   public void testAddAll_withDuplicates() {
     MinimalCollection<E> elementsToAdd
-        = MinimalCollection.of(samples.e3, samples.e4, samples.e3, samples.e4);
+        = MinimalCollection.of(e3(), e4(), e3(), e4());
     assertTrue("add(hasDuplicates) should return true",
         getSet().addAll(elementsToAdd));
-    expectAdded(samples.e3, samples.e4);
+    expectAdded(e3(), e4());
   }
 
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAddAll_supportedAllPresent() {
     assertFalse("add(allPresent) should return false",
-        getSet().addAll(MinimalCollection.of(samples.e0)));
+        getSet().addAll(MinimalCollection.of(e0())));
     expectUnchanged();
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
index 47755e3..90dab5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
@@ -40,7 +40,7 @@ public class SetAddTester<E> extends AbstractSetTester<E> {
   @CollectionFeature.Require(SUPPORTS_ADD)
   @CollectionSize.Require(absent = ZERO)
   public void testAdd_supportedPresent() {
-    assertFalse("add(present) should return false", getSet().add(samples.e0));
+    assertFalse("add(present) should return false", getSet().add(e0()));
     expectUnchanged();
   }
 
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
index 6602852..6a25297 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
@@ -54,7 +54,7 @@ public class SetCreationTester<E> extends AbstractSetTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testCreateWithDuplicates_nonNullDuplicatesNotRejected() {
     E[] array = createSamplesArray();
-    array[1] = samples.e0;
+    array[1] = e0();
     collection = getSubjectGenerator().create(array);
 
     List<E> expectedWithDuplicateRemoved =
@@ -79,7 +79,7 @@ public class SetCreationTester<E> extends AbstractSetTester<E> {
   @CollectionSize.Require(absent = {ZERO, ONE})
   public void testCreateWithDuplicates_nonNullDuplicatesRejected() {
     E[] array = createSamplesArray();
-    array[1] = samples.e0;
+    array[1] = e0();
     try {
       collection = getSubjectGenerator().create(array);
       fail("Should reject duplicate non-null elements at creation");
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
index 25e0dc6..8d94ac4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
@@ -43,7 +43,7 @@ public class SetEqualsTester<E> extends AbstractSetTester<E> {
   @CollectionSize.Require(absent = CollectionSize.ZERO)
   public void testEquals_otherSetWithDifferentElements() {
     Collection<E> elements = getSampleElements(getNumElements() - 1);
-    elements.add(getSubjectGenerator().samples().e3);
+    elements.add(getSubjectGenerator().samples().e3());
 
     assertFalse(
         "A Set should not equal another Set containing different elements.",
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
index 5bef4c4..e700e00 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
@@ -35,9 +35,9 @@ public class SetRemoveTester<E> extends AbstractSetTester<E> {
   @CollectionFeature.Require(SUPPORTS_REMOVE)
   @CollectionSize.Require(absent = ZERO)
   public void testRemove_present() {
-    getSet().remove(samples.e0);
+    getSet().remove(e0());
     assertFalse("After remove(present) a set should not contain "
         + "the removed element.",
-        getSet().contains(samples.e0));
+        getSet().contains(e0()));
   }
 }
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
index 99446b5..94655d9 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
@@ -16,10 +16,10 @@
 
 package com.google.common.collect.testing.testers;
 
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
 import static com.google.common.collect.testing.features.CollectionSize.ONE;
 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.testing.AbstractMapTester;
@@ -101,51 +101,49 @@ public class SortedMapNavigationTester<K, V> extends AbstractMapTester<K, V> {
   public void testLast() {
     assertEquals(c.getKey(), navigableMap.lastKey());
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   public void testHeadMapExclusive() {
     assertFalse(navigableMap.headMap(a.getKey()).containsKey(a.getKey()));
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   public void testTailMapInclusive() {
     assertTrue(navigableMap.tailMap(a.getKey()).containsKey(a.getKey()));
   }
-  
+
   public void testHeadMap() {
     List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
         getSubjectGenerator().getCollectionSize().getNumElements()));
     Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
     for (int i = 0; i < entries.size(); i++) {
-      assertThat(navigableMap.headMap(entries.get(i).getKey()).entrySet())
-          .iteratesAs(entries.subList(0, i));
+      assertEqualInOrder(entries.subList(0, i),
+          navigableMap.headMap(entries.get(i).getKey()).entrySet());
     }
   }
-  
+
   public void testTailMap() {
     List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
         getSubjectGenerator().getCollectionSize().getNumElements()));
     Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
     for (int i = 0; i < entries.size(); i++) {
-      assertThat(navigableMap.tailMap(entries.get(i).getKey()).entrySet())
-          .iteratesAs(entries.subList(i, entries.size()));
+      assertEqualInOrder(entries.subList(i, entries.size()),
+          navigableMap.tailMap(entries.get(i).getKey()).entrySet());
     }
   }
-  
+
   public void testSubMap() {
     List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
         getSubjectGenerator().getCollectionSize().getNumElements()));
     Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
     for (int i = 0; i < entries.size(); i++) {
       for (int j = i + 1; j < entries.size(); j++) {
-        assertThat(navigableMap
-                 .subMap(entries.get(i).getKey(), entries.get(j).getKey())
-                 .entrySet())
-            .iteratesAs(entries.subList(i, j)); 
+        assertEqualInOrder(entries.subList(i, j),
+            navigableMap.subMap(entries.get(i).getKey(), entries.get(j).getKey()).entrySet());
       }
     }
   }
-  
+
   @CollectionSize.Require(SEVERAL)
   public void testSubMapIllegal() {
     try {
@@ -153,7 +151,7 @@ public class SortedMapNavigationTester<K, V> extends AbstractMapTester<K, V> {
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {}
   }
-  
+
   @CollectionSize.Require(absent = ZERO)
   public void testOrderedByComparator() {
     @SuppressWarnings("unchecked")
diff --git a/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java b/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
index d324a38..228e795 100644
--- a/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
+++ b/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
@@ -33,6 +33,7 @@ import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 import com.google.common.reflect.ClassPath;
 import com.google.common.testing.NullPointerTester.Visibility;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
@@ -43,6 +44,7 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.TreeMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -84,7 +86,9 @@ import java.util.logging.Logger;
  * <p>please use {@link ClassSanityTester#forAllPublicStaticMethods}.
  *
  * <p>If not all classes on the classpath should be covered, {@link
- * #ignoreClasses} can be used to exclude certain classes.
+ * #ignoreClasses} can be used to exclude certain classes. As a special case, classes with an
+ * underscore in the name (like {@code AutoValue_Foo}) can be excluded using
+ * <code>ignoreClasses({@link #UNDERSCORE_IN_NAME})</code>.
  *
  * <p>{@link #setDefault} allows subclasses to specify default values for types.
  *
@@ -95,8 +99,22 @@ import java.util.logging.Logger;
  */
 @Beta
 // TODO: Switch to JUnit 4 and use @Parameterized and @BeforeClass
+ at J2ObjCIncompatible // com.google.common.reflect.ClassPath
 public abstract class AbstractPackageSanityTests extends TestCase {
 
+  /**
+   * A predicate that matches classes with an underscore in the class name. This can be used with
+   * {@link #ignoreClasses} to exclude generated classes, such as the {@code AutoValue_Foo} classes
+   * generated by <a href="https://github.com/google/auto/tree/master/value">AutoValue</a>.
+   *
+   * @since 19.0
+   */
+  public static final Predicate<Class<?>> UNDERSCORE_IN_NAME = new Predicate<Class<?>>() {
+    @Override public boolean apply(Class<?> c) {
+      return c.getSimpleName().contains("_");
+    }
+  };
+
   /* The names of the expected method that tests null checks. */
   private static final ImmutableList<String> NULL_TEST_METHOD_NAMES = ImmutableList.of(
       "testNulls", "testNull",
@@ -281,7 +299,7 @@ public abstract class AbstractPackageSanityTests extends TestCase {
 
   private static AssertionFailedError sanityError(
       Class<?> cls, List<String> explicitTestNames, String description, Throwable e) {
-    String message = String.format(
+    String message = String.format(Locale.ROOT,
         "Error in automated %s of %s\n"
             + "If the class is better tested explicitly, you can add %s() to %sTest",
         description, cls, explicitTestNames.get(0), cls.getName());
@@ -368,7 +386,7 @@ public abstract class AbstractPackageSanityTests extends TestCase {
     }
   }
 
-  static abstract class Chopper {
+  abstract static class Chopper {
 
     final Chopper or(final Chopper you) {
       final Chopper i = this;
diff --git a/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java b/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
index 6e28db7..846ee9b 100644
--- a/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
+++ b/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
@@ -150,7 +150,7 @@ import javax.annotation.Nullable;
 /**
  * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
  * utilities.
- * 
+ *
  * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
  * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
  * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
@@ -158,7 +158,7 @@ import javax.annotation.Nullable;
  * exposes at least one public static final constant of the same type, one of the constants will be
  * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
  * returned.
- * 
+ *
  * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
  * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
  * Immutable empty instances are returned for collection types; {@code ""} for string;
@@ -235,7 +235,7 @@ public final class ArbitraryInstances {
       .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
       // All collections are immutable empty. So safe for any type parameter.
       .put(Iterator.class, ImmutableSet.of().iterator())
-      .put(PeekingIterator.class, Iterators.peekingIterator(Iterators.emptyIterator()))
+      .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
       .put(ListIterator.class, ImmutableList.of().listIterator())
       .put(Iterable.class, ImmutableSet.of())
       .put(Collection.class, ImmutableList.of())
@@ -420,7 +420,6 @@ public final class ArbitraryInstances {
     }
 
     public static final class DeterministicRandom extends Random {
-      @SuppressWarnings("unused") // invoked by reflection
       public DeterministicRandom() {
         super(0);
       }
diff --git a/guava-testlib/src/com/google/common/testing/ClassSanityTester.java b/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
index 3eeb1f1..c7d70e8 100644
--- a/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
+++ b/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
@@ -124,7 +124,7 @@ public final class ClassSanityTester {
   /**
    * Sets the default value for {@code type}. The default value isn't used in testing {@link
    * Object#equals} because more than one sample instances are needed for testing inequality.
-   * To set sample instances for equality testing, use {@link #setSampleInstances} instead.
+   * To set distinct values for equality testing, use {@link #setDistinctValues} instead.
    */
   public <T> ClassSanityTester setDefault(Class<T> type, T value) {
     nullPointerTester.setDefault(type, value);
@@ -142,13 +142,14 @@ public final class ClassSanityTester {
    * exception that if the sample instance is to be passed to a {@link Nullable} parameter, one
    * non-null sample is sufficient. Setting an empty list will clear sample instances for {@code
    * type}.
-
    *
-
-   * @deprecated Use {@link #setDistinctValues} instead.
+   * @deprecated To supply multiple values, use {@link #setDistinctValues}. It accepts only two
+   *     values, which is enough for any {@code equals} testing. To supply a single value, use
+   *     {@link #setDefault}. This method will be removed in Guava release 20.0.
    */
   @Deprecated
-  public <T> ClassSanityTester setSampleInstances(Class<T> type, Iterable<? extends T> instances) {
+  public <T> ClassSanityTester setSampleInstances(
+      Class<T> type, Iterable<? extends T> instances) {
     ImmutableList<? extends T> samples = ImmutableList.copyOf(instances);
     Set<Object> uniqueValues = new HashSet<Object>();
     for (T instance : instances) {
@@ -300,7 +301,7 @@ public final class ClassSanityTester {
       throw Throwables.propagate(e);
     }
   }
- 
+
   void doTestEquals(Class<?> cls)
       throws ParameterNotInstantiableException, ParameterHasNoDistinctValueException,
              IllegalAccessException, InvocationTargetException, FactoryMethodReturnsNullException {
@@ -594,7 +595,7 @@ public final class ClassSanityTester {
     tester.addEqualityGroup(instance, createInstance(factory, equalArgs));
     for (int i = 0; i < params.size(); i++) {
       List<Object> newArgs = Lists.newArrayList(args);
-      Object newArg = argGenerators.get(i).generate(params.get(i).getType());
+      Object newArg = argGenerators.get(i).generateFresh(params.get(i).getType());
 
       if (newArg == null || Objects.equal(args.get(i), newArg)) {
         if (params.get(i).getType().getRawType().isEnum()) {
@@ -662,12 +663,12 @@ public final class ClassSanityTester {
     return generator;
   }
 
-  private static @Nullable Object generateDummyArg(Parameter param, FreshValueGenerator generator)
+  @Nullable private static Object generateDummyArg(Parameter param, FreshValueGenerator generator)
       throws ParameterNotInstantiableException {
     if (param.isAnnotationPresent(Nullable.class)) {
       return null;
     }
-    Object arg = generator.generate(param.getType());
+    Object arg = generator.generateFresh(param.getType());
     if (arg == null) {
       throw new ParameterNotInstantiableException(param);
     }
@@ -688,7 +689,7 @@ public final class ClassSanityTester {
       if (!invokable.isPrivate()
           && !invokable.isSynthetic()
           && invokable.isStatic()
-          && type.isAssignableFrom(invokable.getReturnType())) {
+          && type.isSupertypeOf(invokable.getReturnType())) {
         @SuppressWarnings("unchecked") // guarded by isAssignableFrom()
         Invokable<?, ? extends T> factory = (Invokable<?, ? extends T>) invokable;
         factories.add(factory);
@@ -802,7 +803,7 @@ public final class ClassSanityTester {
   private static final class SerializableDummyProxy extends DummyProxy
       implements Serializable {
 
-    private transient final ClassSanityTester tester;
+    private final transient ClassSanityTester tester;
 
     SerializableDummyProxy(ClassSanityTester tester) {
       this.tester = tester;
@@ -821,4 +822,3 @@ public final class ClassSanityTester {
     }
   }
 }
-
diff --git a/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java b/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
index 74710e3..d3f0c75 100644
--- a/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
+++ b/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
@@ -148,17 +148,17 @@ public final class ForwardingWrapperTester {
   private static <T> void testEquals(
       Class<T> interfaceType, Function<? super T, ? extends T> wrapperFunction) {
     FreshValueGenerator generator = new FreshValueGenerator();
-    T instance = generator.newProxy(interfaceType);
+    T instance = generator.newFreshProxy(interfaceType);
     new EqualsTester()
         .addEqualityGroup(wrapperFunction.apply(instance), wrapperFunction.apply(instance))
-        .addEqualityGroup(wrapperFunction.apply(generator.newProxy(interfaceType)))
+        .addEqualityGroup(wrapperFunction.apply(generator.newFreshProxy(interfaceType)))
         // TODO: add an overload to EqualsTester to print custom error message?
         .testEquals();
   }
 
   private static <T> void testToString(
       Class<T> interfaceType, Function<? super T, ? extends T> wrapperFunction) {
-    T proxy = new FreshValueGenerator().newProxy(interfaceType);
+    T proxy = new FreshValueGenerator().newFreshProxy(interfaceType);
     assertEquals("toString() isn't properly forwarded",
         proxy.toString(), wrapperFunction.apply(proxy).toString());
   }
@@ -167,7 +167,7 @@ public final class ForwardingWrapperTester {
     FreshValueGenerator paramValues = new FreshValueGenerator();
     final List<Object> passedArgs = Lists.newArrayList();
     for (Class<?> paramType : method.getParameterTypes()) {
-      passedArgs.add(paramValues.generate(paramType));
+      passedArgs.add(paramValues.generateFresh(paramType));
     }
     return passedArgs.toArray();
   }
@@ -185,7 +185,7 @@ public final class ForwardingWrapperTester {
       this.interfaceType = interfaceType;
       this.method = method;
       this.passedArgs = getParameterValues(method);
-      this.returnValue = new FreshValueGenerator().generate(method.getReturnType());
+      this.returnValue = new FreshValueGenerator().generateFresh(method.getReturnType());
     }
 
     @Override protected Object handleInvocation(Object p, Method calledMethod, Object[] args)
diff --git a/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java b/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
index a656c83..9a178f3 100644
--- a/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
+++ b/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
@@ -141,11 +141,28 @@ class FreshValueGenerator {
     GENERATORS = builder.build();
   }
 
-  private final AtomicInteger differentiator = new AtomicInteger(1);
+  private static final ImmutableMap<Class<?>, Method> EMPTY_GENERATORS;
+  static {
+    ImmutableMap.Builder<Class<?>, Method> builder =
+        ImmutableMap.builder();
+    for (Method method : FreshValueGenerator.class.getDeclaredMethods()) {
+      if (method.isAnnotationPresent(Empty.class)) {
+        builder.put(method.getReturnType(), method);
+      }
+    }
+    EMPTY_GENERATORS = builder.build();
+  }
+
+  private final AtomicInteger freshness = new AtomicInteger(1);
   private final ListMultimap<Class<?>, Object> sampleInstances = ArrayListMultimap.create();
-  private final Set<Type> generatedOptionalTypes = Sets.newHashSet();
 
-  <T> void addSampleInstances(Class<T> type, Iterable<? extends T> instances) {
+  /**
+   * The freshness level at which the {@link Empty @Empty} annotated method was invoked to generate
+   * instance.
+   */
+  private final Map<Type, Integer> emptyInstanceGenerated = new HashMap<Type, Integer>();
+
+  final <T> void addSampleInstances(Class<T> type, Iterable<? extends T> instances) {
     sampleInstances.putAll(checkNotNull(type), checkNotNull(instances));
   }
 
@@ -155,18 +172,40 @@ class FreshValueGenerator {
    * <li>exactly of the given type, including generic type parameters, such as
    *     {@code ImmutableList<String>};
    * <li>of the raw type;
-   * <li>null if no fresh value can be generated.
+   * <li>null if no value can be generated.
    * </ul>
    */
-  @Nullable Object generate(TypeToken<?> type) {
+  @Nullable final Object generateFresh(TypeToken<?> type) {
+    Object generated = generate(type);
+    if (generated != null) {
+      freshness.incrementAndGet();
+    }
+    return generated;
+  }
+
+  @Nullable final <T> T generateFresh(Class<T> type) {
+    return Primitives.wrap(type).cast(generateFresh(TypeToken.of(type)));
+  }
+
+  final <T> T newFreshProxy(final Class<T> interfaceType) {
+    T proxy = newProxy(interfaceType);
+    freshness.incrementAndGet();
+    return proxy;
+  }
+
+  /**
+   * Generates an instance for {@code type} using the current {@link #freshness}.
+   * The generated instance may or may not be unique across different calls.
+   */
+  private Object generate(TypeToken<?> type) {
     Class<?> rawType = type.getRawType();
     List<Object> samples = sampleInstances.get(rawType);
-    Object sample = nextInstance(samples, null);
+    Object sample = pickInstance(samples, null);
     if (sample != null) {
       return sample;
     }
     if (rawType.isEnum()) {
-      return nextInstance(rawType.getEnumConstants(), null);
+      return pickInstance(rawType.getEnumConstants(), null);
     }
     if (type.isArray()) {
       TypeToken<?> componentType = type.getComponentType();
@@ -174,20 +213,32 @@ class FreshValueGenerator {
       Array.set(array, 0, generate(componentType));
       return array;
     }
-    if (rawType == Optional.class && generatedOptionalTypes.add(type.getType())) {
-      // For any Optional<T>, we'll first generate absent(). The next call generates a distinct
-      // value of T to be wrapped in Optional.of().
-      return Optional.absent();
+    Method emptyGenerate = EMPTY_GENERATORS.get(rawType);
+    if (emptyGenerate != null) {
+      if (emptyInstanceGenerated.containsKey(type.getType())) {
+        // empty instance already generated
+        if (emptyInstanceGenerated.get(type.getType()).intValue() == freshness.get()) {
+          // same freshness, generate again.
+          return invokeGeneratorMethod(emptyGenerate);
+        } else {
+          // Cannot use empty generator. Proceed with other generators.
+        }
+      } else {
+        // never generated empty instance for this type before.
+        Object emptyInstance = invokeGeneratorMethod(emptyGenerate);
+        emptyInstanceGenerated.put(type.getType(), freshness.get());
+        return emptyInstance;
+      }
     }
-    Method generator = GENERATORS.get(rawType);
-    if (generator != null) {
-      ImmutableList<Parameter> params = Invokable.from(generator).getParameters();
+    Method generate = GENERATORS.get(rawType);
+    if (generate != null) {
+      ImmutableList<Parameter> params = Invokable.from(generate).getParameters();
       List<Object> args = Lists.newArrayListWithCapacity(params.size());
       TypeVariable<?>[] typeVars = rawType.getTypeParameters();
       for (int i = 0; i < params.size(); i++) {
         TypeToken<?> paramType = type.resolveType(typeVars[i]);
         // We require all @Generates methods to either be parameter-less or accept non-null
-        // fresh values for their generic parameter types.
+        // values for their generic parameter types.
         Object argValue = generate(paramType);
         if (argValue == null) {
           // When a parameter of a @Generates method cannot be created,
@@ -198,21 +249,11 @@ class FreshValueGenerator {
         }
         args.add(argValue);
       }
-      try {
-        return generator.invoke(this, args.toArray());
-      } catch (InvocationTargetException e) {
-        Throwables.propagate(e.getCause());
-      } catch (Exception e) {
-        throw Throwables.propagate(e);
-      }
+      return invokeGeneratorMethod(generate, args.toArray());
     }
     return defaultGenerate(rawType);
   }
 
-  @Nullable final <T> T generate(Class<T> type) {
-    return Primitives.wrap(type).cast(generate(TypeToken.of(type)));
-  }
-
   private <T> T defaultGenerate(Class<T> rawType) {
     if (rawType.isInterface()) {
       // always create a new proxy
@@ -221,12 +262,22 @@ class FreshValueGenerator {
     return ArbitraryInstances.get(rawType);
   }
 
-  final <T> T newProxy(final Class<T> interfaceType) {
+  private <T> T newProxy(final Class<T> interfaceType) {
     return Reflection.newProxy(interfaceType, new FreshInvocationHandler(interfaceType));
   }
 
+  private Object invokeGeneratorMethod(Method generator, Object... args) {
+    try {
+      return generator.invoke(this, args);
+    } catch (InvocationTargetException e) {
+      throw Throwables.propagate(e.getCause());
+    } catch (Exception e) {
+      throw Throwables.propagate(e);
+    }
+  }
+
   private final class FreshInvocationHandler extends AbstractInvocationHandler {
-    private final int identity = freshInt();
+    private final int identity = generateInt();
     private final Class<?> interfaceType;
 
     FreshInvocationHandler(Class<?> interfaceType) {
@@ -255,22 +306,20 @@ class FreshValueGenerator {
   }
 
   /** Subclasses can override to provide different return value for proxied interface methods. */
-  Object interfaceMethodCalled(
-      @SuppressWarnings("unused") Class<?> interfaceType,
-      @SuppressWarnings("unused") Method method) {
+  Object interfaceMethodCalled(Class<?> interfaceType, Method method) {
     throw new UnsupportedOperationException();
   }
 
-  private <T> T nextInstance(T[] instances, T defaultValue) {
-    return nextInstance(Arrays.asList(instances), defaultValue);
+  private <T> T pickInstance(T[] instances, T defaultValue) {
+    return pickInstance(Arrays.asList(instances), defaultValue);
   }
 
-  private <T> T nextInstance(Collection<T> instances, T defaultValue) {
+  private <T> T pickInstance(Collection<T> instances, T defaultValue) {
     if (instances.isEmpty()) {
       return defaultValue;
     }
-    // freshInt() is 1-based.
-    return Iterables.get(instances, (freshInt() - 1) % instances.size());
+    // generateInt() is 1-based.
+    return Iterables.get(instances, (generateInt() - 1) % instances.size());
   }
 
   private static String paramString(Class<?> type, int i) {
@@ -279,136 +328,161 @@ class FreshValueGenerator {
 
   /**
    * Annotates a method to be the instance generator of a certain type. The return type is the
-   * generated type. The method parameters are non-null fresh values for each method type variable
-   * in the same type variable declaration order of the return type.
+   * generated type. The method parameters correspond to the generated type's type parameters.
+   * For example, if the annotated method returns {@code Map<K, V>}, the method signature should be:
+   * {@code Map<K, V> generateMap(K key, V value)}.
    */
   @Target(ElementType.METHOD)
   @Retention(RetentionPolicy.RUNTIME)
   private @interface Generates {}
 
-  @Generates private Class<?> freshClass() {
-    return nextInstance(
+  /**
+   * Annotates a method to generate the "empty" instance of a collection. This method should accept
+   * no parameter. The value it generates should be unequal to the values generated by methods
+   * annotated with {@link Generates}.
+   */
+  @Target(ElementType.METHOD)
+  @Retention(RetentionPolicy.RUNTIME)
+  private @interface Empty {}
+
+  @Generates private Class<?> generateClass() {
+    return pickInstance(
         ImmutableList.of(
             int.class, long.class, void.class,
             Object.class, Object[].class, Iterable.class),
         Object.class);
   }
 
-  @Generates private Object freshObject() {
-    return freshString();
+  @Generates private Object generateObject() {
+    return generateString();
   }
 
-  @Generates private Number freshNumber() {
-    return freshInt();
+  @Generates private Number generateNumber() {
+    return generateInt();
   }
 
-  @Generates private int freshInt() {
-    return differentiator.getAndIncrement();
+  @Generates private int generateInt() {
+    return freshness.get();
   }
 
-  @Generates private Integer freshInteger() {
-    return new Integer(freshInt());
+  @Generates private Integer generateInteger() {
+    return new Integer(generateInt());
   }
 
-  @Generates private long freshLong() {
-    return freshInt();
+  @Generates private long generateLong() {
+    return generateInt();
   }
 
-  @Generates private Long freshLongObject() {
-    return new Long(freshLong());
+  @Generates private Long generateLongObject() {
+    return new Long(generateLong());
   }
 
-  @Generates private float freshFloat() {
-    return freshInt();
+  @Generates private float generateFloat() {
+    return generateInt();
   }
 
-  @Generates private Float freshFloatObject() {
-    return new Float(freshFloat());
+  @Generates private Float generateFloatObject() {
+    return new Float(generateFloat());
   }
 
-  @Generates private double freshDouble() {
-    return freshInt();
+  @Generates private double generateDouble() {
+    return generateInt();
   }
 
-  @Generates private Double freshDoubleObject() {
-    return new Double(freshDouble());
+  @Generates private Double generateDoubleObject() {
+    return new Double(generateDouble());
   }
 
-  @Generates private short freshShort() {
-    return (short) freshInt();
+  @Generates private short generateShort() {
+    return (short) generateInt();
   }
 
-  @Generates private Short freshShortObject() {
-    return new Short(freshShort());
+  @Generates private Short generateShortObject() {
+    return new Short(generateShort());
   }
 
-  @Generates private byte freshByte() {
-    return (byte) freshInt();
+  @Generates private byte generateByte() {
+    return (byte) generateInt();
   }
 
-  @Generates private Byte freshByteObject() {
-    return new Byte(freshByte());
+  @Generates private Byte generateByteObject() {
+    return new Byte(generateByte());
   }
 
-  @Generates private char freshChar() {
-    return freshString().charAt(0);
+  @Generates private char generateChar() {
+    return generateString().charAt(0);
   }
 
-  @Generates private Character freshCharacter() {
-    return new Character(freshChar());
+  @Generates private Character generateCharacter() {
+    return new Character(generateChar());
   }
 
-  @Generates private boolean freshBoolean() {
-    return freshInt() % 2 == 0;
+  @Generates private boolean generateBoolean() {
+    return generateInt() % 2 == 0;
   }
 
-  @Generates private Boolean freshBooleanObject() {
-    return new Boolean(freshBoolean());
+  @Generates private Boolean generateBooleanObject() {
+    return new Boolean(generateBoolean());
   }
 
-  @Generates private UnsignedInteger freshUnsignedInteger() {
-    return UnsignedInteger.fromIntBits(freshInt());
+  @Generates private UnsignedInteger generateUnsignedInteger() {
+    return UnsignedInteger.fromIntBits(generateInt());
   }
 
-  @Generates private UnsignedLong freshUnsignedLong() {
-    return UnsignedLong.fromLongBits(freshLong());
+  @Generates private UnsignedLong generateUnsignedLong() {
+    return UnsignedLong.fromLongBits(generateLong());
   }
 
-  @Generates private BigInteger freshBigInteger() {
-    return BigInteger.valueOf(freshInt());
+  @Generates private BigInteger generateBigInteger() {
+    return BigInteger.valueOf(generateInt());
   }
 
-  @Generates private BigDecimal freshBigDecimal() {
-    return BigDecimal.valueOf(freshInt());
+  @Generates private BigDecimal generateBigDecimal() {
+    return BigDecimal.valueOf(generateInt());
   }
 
-  @Generates private CharSequence freshCharSequence() {
-    return freshString();
+  @Generates private CharSequence generateCharSequence() {
+    return generateString();
   }
 
-  @Generates private String freshString() {
-    return Integer.toString(freshInt());
+  @Generates private String generateString() {
+    return Integer.toString(generateInt());
   }
 
-  @Generates private Comparable<?> freshComparable() {
-    return freshString();
+  @Generates private Comparable<?> generateComparable() {
+    return generateString();
   }
 
-  @Generates private Pattern freshPattern() {
-    return Pattern.compile(freshString());
+  @Generates private Pattern generatePattern() {
+    return Pattern.compile(generateString());
   }
 
-  @Generates private Charset freshCharset() {
-    return nextInstance(Charset.availableCharsets().values(), Charsets.UTF_8);
+  @Generates private Charset generateCharset() {
+    return pickInstance(Charset.availableCharsets().values(), Charsets.UTF_8);
   }
 
-  @Generates private Locale freshLocale() {
-    return nextInstance(Locale.getAvailableLocales(), Locale.US);
+  @Generates private Locale generateLocale() {
+    return pickInstance(Locale.getAvailableLocales(), Locale.US);
   }
 
-  @Generates private Currency freshCurrency() {
+  @Generates private Currency generateCurrency() {
+    try {
+      Method method = Currency.class.getMethod("getAvailableCurrencies");
+      @SuppressWarnings("unchecked") // getAvailableCurrencies() returns Set<Currency>.
+      Set<Currency> currencies = (Set<Currency>) method.invoke(null);
+      return pickInstance(currencies, Currency.getInstance(Locale.US));
+    } catch (NoSuchMethodException notJava7) {
+      return preJava7FreshCurrency();
+    } catch (InvocationTargetException cantCallGetAvailableCurrencies) {
+      return preJava7FreshCurrency();
+    } catch (IllegalAccessException impossible) {
+      throw new AssertionError(impossible);
+    }
+  }
+
+  private Currency preJava7FreshCurrency() {
     for (Set<Locale> uselessLocales = Sets.newHashSet(); ; ) {
-      Locale locale = freshLocale();
+      Locale locale = generateLocale();
       if (uselessLocales.contains(locale)) { // exhausted all locales
         return Currency.getInstance(Locale.US);
       }
@@ -421,19 +495,23 @@ class FreshValueGenerator {
   }
 
   // common.base
-  @Generates private <T> Optional<T> freshOptional(T value) {
+  @Empty private <T> Optional<T> generateOptional() {
+    return Optional.absent();
+  }
+
+  @Generates private <T> Optional<T> generateOptional(T value) {
     return Optional.of(value);
   }
 
-  @Generates private Joiner freshJoiner() {
-    return Joiner.on(freshString());
+  @Generates private Joiner generateJoiner() {
+    return Joiner.on(generateString());
   }
 
-  @Generates private Splitter freshSplitter() {
-    return Splitter.on(freshString());
+  @Generates private Splitter generateSplitter() {
+    return Splitter.on(generateString());
   }
 
-  @Generates private <T> Equivalence<T> freshEquivalence() {
+  @Generates private <T> Equivalence<T> generateEquivalence() {
     return new Equivalence<T>() {
       @Override protected boolean doEquivalent(T a, T b) {
         return false;
@@ -441,31 +519,31 @@ class FreshValueGenerator {
       @Override protected int doHash(T t) {
         return 0;
       }
-      final String string = paramString(Equivalence.class, freshInt());
+      final String string = paramString(Equivalence.class, generateInt());
       @Override public String toString() {
         return string;
       }
     };
   }
 
-  @Generates private CharMatcher freshCharMatcher() {
+  @Generates private CharMatcher generateCharMatcher() {
     return new CharMatcher() {
       @Override public boolean matches(char c) {
         return false;
       }
-      final String string = paramString(CharMatcher.class, freshInt());
+      final String string = paramString(CharMatcher.class, generateInt());
       @Override public String toString() {
         return string;
       }
     };
   }
 
-  @Generates private Ticker freshTicker() {
+  @Generates private Ticker generateTicker() {
     return new Ticker() {
       @Override public long read() {
         return 0;
       }
-      final String string = paramString(Ticker.class, freshInt());
+      final String string = paramString(Ticker.class, generateInt());
       @Override public String toString() {
         return string;
       }
@@ -473,87 +551,91 @@ class FreshValueGenerator {
   }
 
   // collect
-  @Generates private <T> Comparator<T> freshComparator() {
-    return freshOrdering();
+  @Generates private <T> Comparator<T> generateComparator() {
+    return generateOrdering();
   }
 
-  @Generates private <T> Ordering<T> freshOrdering() {
+  @Generates private <T> Ordering<T> generateOrdering() {
     return new Ordering<T>() {
       @Override public int compare(T left, T right) {
         return 0;
       }
-      final String string = paramString(Ordering.class, freshInt());
+      final String string = paramString(Ordering.class, generateInt());
       @Override public String toString() {
         return string;
       }
     };
   }
 
-  @Generates private static <C extends Comparable> Range<C> freshRange(C freshElement) {
+  @Empty private static <C extends Comparable<?>> Range<C> generateRange() {
+    return Range.all();
+  }
+
+  @Generates private static <C extends Comparable<?>> Range<C> generateRange(C freshElement) {
     return Range.singleton(freshElement);
   }
 
-  @Generates private static <E> Iterable<E> freshIterable(E freshElement) {
-    return freshList(freshElement);
+  @Generates private static <E> Iterable<E> generateIterable(E freshElement) {
+    return generateList(freshElement);
   }
 
-  @Generates private static <E> Collection<E> freshCollection(E freshElement) {
-    return freshList(freshElement);
+  @Generates private static <E> Collection<E> generateCollection(E freshElement) {
+    return generateList(freshElement);
   }
 
-  @Generates private static <E> List<E> freshList(E freshElement) {
-    return freshArrayList(freshElement);
+  @Generates private static <E> List<E> generateList(E freshElement) {
+    return generateArrayList(freshElement);
   }
 
-  @Generates private static <E> ArrayList<E> freshArrayList(E freshElement) {
+  @Generates private static <E> ArrayList<E> generateArrayList(E freshElement) {
     ArrayList<E> list = Lists.newArrayList();
     list.add(freshElement);
     return list;
   }
 
-  @Generates private static <E> LinkedList<E> freshLinkedList(E freshElement) {
+  @Generates private static <E> LinkedList<E> generateLinkedList(E freshElement) {
     LinkedList<E> list = Lists.newLinkedList();
     list.add(freshElement);
     return list;
   }
 
-  @Generates private static <E> ImmutableList<E> freshImmutableList(E freshElement) {
+  @Generates private static <E> ImmutableList<E> generateImmutableList(E freshElement) {
     return ImmutableList.of(freshElement);
   }
 
-  @Generates private static <E> ImmutableCollection<E> freshImmutableCollection(E freshElement) {
-    return freshImmutableList(freshElement);
+  @Generates private static <E> ImmutableCollection<E> generateImmutableCollection(E freshElement) {
+    return generateImmutableList(freshElement);
   }
 
-  @Generates private static <E> Set<E> freshSet(E freshElement) {
-    return freshHashSet(freshElement);
+  @Generates private static <E> Set<E> generateSet(E freshElement) {
+    return generateHashSet(freshElement);
   }
 
-  @Generates private static <E> HashSet<E> freshHashSet(E freshElement) {
-    return freshLinkedHashSet(freshElement);
+  @Generates private static <E> HashSet<E> generateHashSet(E freshElement) {
+    return generateLinkedHashSet(freshElement);
   }
 
-  @Generates private static <E> LinkedHashSet<E> freshLinkedHashSet(E freshElement) {
+  @Generates private static <E> LinkedHashSet<E> generateLinkedHashSet(E freshElement) {
     LinkedHashSet<E> set = Sets.newLinkedHashSet();
     set.add(freshElement);
     return set;
   }
 
-  @Generates private static <E> ImmutableSet<E> freshImmutableSet(E freshElement) {
+  @Generates private static <E> ImmutableSet<E> generateImmutableSet(E freshElement) {
     return ImmutableSet.of(freshElement);
   }
 
   @Generates private static <E extends Comparable<? super E>> SortedSet<E>
-      freshSortedSet(E freshElement) {
-    return freshNavigableSet(freshElement);
+      generateSortedSet(E freshElement) {
+    return generateNavigableSet(freshElement);
   }
 
   @Generates private static <E extends Comparable<? super E>> NavigableSet<E>
-      freshNavigableSet(E freshElement) {
-    return freshTreeSet(freshElement);
+      generateNavigableSet(E freshElement) {
+    return generateTreeSet(freshElement);
   }
 
-  @Generates private static <E extends Comparable<? super E>> TreeSet<E> freshTreeSet(
+  @Generates private static <E extends Comparable<? super E>> TreeSet<E> generateTreeSet(
       E freshElement) {
     TreeSet<E> set = Sets.newTreeSet();
     set.add(freshElement);
@@ -561,36 +643,36 @@ class FreshValueGenerator {
   }
 
   @Generates private static <E extends Comparable<? super E>> ImmutableSortedSet<E>
-      freshImmutableSortedSet(E freshElement) {
+      generateImmutableSortedSet(E freshElement) {
     return ImmutableSortedSet.of(freshElement);
   }
 
-  @Generates private static <E> Multiset<E> freshMultiset(E freshElement) {
-    return freshHashMultiset(freshElement);
+  @Generates private static <E> Multiset<E> generateMultiset(E freshElement) {
+    return generateHashMultiset(freshElement);
   }
 
-  @Generates private static <E> HashMultiset<E> freshHashMultiset(E freshElement) {
+  @Generates private static <E> HashMultiset<E> generateHashMultiset(E freshElement) {
     HashMultiset<E> multiset = HashMultiset.create();
     multiset.add(freshElement);
     return multiset;
   }
 
-  @Generates private static <E> LinkedHashMultiset<E> freshLinkedHashMultiset(E freshElement) {
+  @Generates private static <E> LinkedHashMultiset<E> generateLinkedHashMultiset(E freshElement) {
     LinkedHashMultiset<E> multiset = LinkedHashMultiset.create();
     multiset.add(freshElement);
     return multiset;
   }
 
-  @Generates private static <E> ImmutableMultiset<E> freshImmutableMultiset(E freshElement) {
+  @Generates private static <E> ImmutableMultiset<E> generateImmutableMultiset(E freshElement) {
     return ImmutableMultiset.of(freshElement);
   }
 
-  @Generates private static <E extends Comparable<E>> SortedMultiset<E> freshSortedMultiset(
+  @Generates private static <E extends Comparable<E>> SortedMultiset<E> generateSortedMultiset(
       E freshElement) {
-    return freshTreeMultiset(freshElement);
+    return generateTreeMultiset(freshElement);
   }
 
-  @Generates private static <E extends Comparable<E>> TreeMultiset<E> freshTreeMultiset(
+  @Generates private static <E extends Comparable<E>> TreeMultiset<E> generateTreeMultiset(
       E freshElement) {
     TreeMultiset<E> multiset = TreeMultiset.create();
     multiset.add(freshElement);
@@ -598,45 +680,49 @@ class FreshValueGenerator {
   }
 
   @Generates private static <E extends Comparable<E>> ImmutableSortedMultiset<E>
-      freshImmutableSortedMultiset(E freshElement) {
+      generateImmutableSortedMultiset(E freshElement) {
     return ImmutableSortedMultiset.of(freshElement);
   }
 
-  @Generates private static <K, V> Map<K, V> freshMap(K key, V value) {
-    return freshHashdMap(key, value);
+  @Generates private static <K, V> Map<K, V> generateMap(K key, V value) {
+    return generateHashdMap(key, value);
   }
 
-  @Generates private static <K, V> HashMap<K, V> freshHashdMap(K key, V value) {
-    return freshLinkedHashMap(key, value);
+  @Generates private static <K, V> HashMap<K, V> generateHashdMap(K key, V value) {
+    return generateLinkedHashMap(key, value);
   }
 
-  @Generates private static <K, V> LinkedHashMap<K, V> freshLinkedHashMap(K key, V value) {
+  @Generates private static <K, V> LinkedHashMap<K, V> generateLinkedHashMap(K key, V value) {
     LinkedHashMap<K, V> map = Maps.newLinkedHashMap();
     map.put(key, value);
     return map;
   }
 
-  @Generates private static <K, V> ImmutableMap<K, V> freshImmutableMap(K key, V value) {
+  @Generates private static <K, V> ImmutableMap<K, V> generateImmutableMap(K key, V value) {
     return ImmutableMap.of(key, value);
   }
 
-  @Generates private static <K, V> ConcurrentMap<K, V> freshConcurrentMap(K key, V value) {
+  @Empty private static <K, V> ConcurrentMap<K, V> generateConcurrentMap() {
+    return Maps.newConcurrentMap();
+  }
+
+  @Generates private static <K, V> ConcurrentMap<K, V> generateConcurrentMap(K key, V value) {
     ConcurrentMap<K, V> map = Maps.newConcurrentMap();
     map.put(key, value);
     return map;
   }
 
   @Generates private static <K extends Comparable<? super K>, V> SortedMap<K, V>
-      freshSortedMap(K key, V value) {
-    return freshNavigableMap(key, value);
+      generateSortedMap(K key, V value) {
+    return generateNavigableMap(key, value);
   }
 
   @Generates private static <K extends Comparable<? super K>, V> NavigableMap<K, V>
-      freshNavigableMap(K key, V value) {
-    return freshTreeMap(key, value);
+      generateNavigableMap(K key, V value) {
+    return generateTreeMap(key, value);
   }
 
-  @Generates private static <K extends Comparable<? super K>, V> TreeMap<K, V> freshTreeMap(
+  @Generates private static <K extends Comparable<? super K>, V> TreeMap<K, V> generateTreeMap(
       K key, V value) {
     TreeMap<K, V> map = Maps.newTreeMap();
     map.put(key, value);
@@ -644,75 +730,77 @@ class FreshValueGenerator {
   }
 
   @Generates private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
-      freshImmutableSortedMap(K key, V value) {
+      generateImmutableSortedMap(K key, V value) {
     return ImmutableSortedMap.of(key, value);
   }
 
-  @Generates private static <K, V> Multimap<K, V> freshMultimap(K key, V value) {
-    return freshListMultimap(key, value);
+  @Generates private static <K, V> Multimap<K, V> generateMultimap(K key, V value) {
+    return generateListMultimap(key, value);
   }
 
-  @Generates private static <K, V> ImmutableMultimap<K, V> freshImmutableMultimap(K key, V value) {
+  @Generates private static <K, V> ImmutableMultimap<K, V> generateImmutableMultimap(
+      K key, V value) {
     return ImmutableMultimap.of(key, value);
   }
 
-  @Generates private static <K, V> ListMultimap<K, V> freshListMultimap(K key, V value) {
-    return freshArrayListMultimap(key, value);
+  @Generates private static <K, V> ListMultimap<K, V> generateListMultimap(K key, V value) {
+    return generateArrayListMultimap(key, value);
   }
 
-  @Generates private static <K, V> ArrayListMultimap<K, V> freshArrayListMultimap(K key, V value) {
+  @Generates private static <K, V> ArrayListMultimap<K, V> generateArrayListMultimap(
+      K key, V value) {
     ArrayListMultimap<K, V> multimap = ArrayListMultimap.create();
     multimap.put(key, value);
     return multimap;
   }
 
-  @Generates private static <K, V> ImmutableListMultimap<K, V> freshImmutableListMultimap(
+  @Generates private static <K, V> ImmutableListMultimap<K, V> generateImmutableListMultimap(
       K key, V value) {
     return ImmutableListMultimap.of(key, value);
   }
 
-  @Generates private static <K, V> SetMultimap<K, V> freshSetMultimap(K key, V value) {
-    return freshLinkedHashMultimap(key, value);
+  @Generates private static <K, V> SetMultimap<K, V> generateSetMultimap(K key, V value) {
+    return generateLinkedHashMultimap(key, value);
   }
 
-  @Generates private static <K, V> HashMultimap<K, V> freshHashMultimap(K key, V value) {
+  @Generates private static <K, V> HashMultimap<K, V> generateHashMultimap(K key, V value) {
     HashMultimap<K, V> multimap = HashMultimap.create();
     multimap.put(key, value);
     return multimap;
   }
 
-  @Generates private static <K, V> LinkedHashMultimap<K, V> freshLinkedHashMultimap(
+  @Generates private static <K, V> LinkedHashMultimap<K, V> generateLinkedHashMultimap(
       K key, V value) {
     LinkedHashMultimap<K, V> multimap = LinkedHashMultimap.create();
     multimap.put(key, value);
     return multimap;
   }
 
-  @Generates private static <K, V> ImmutableSetMultimap<K, V> freshImmutableSetMultimap(
+  @Generates private static <K, V> ImmutableSetMultimap<K, V> generateImmutableSetMultimap(
       K key, V value) {
     return ImmutableSetMultimap.of(key, value);
   }
 
-  @Generates private static <K, V> BiMap<K, V> freshBimap(K key, V value) {
-    return freshHashBiMap(key, value);
+  @Generates private static <K, V> BiMap<K, V> generateBimap(K key, V value) {
+    return generateHashBiMap(key, value);
   }
 
-  @Generates private static <K, V> HashBiMap<K, V> freshHashBiMap(K key, V value) {
+  @Generates private static <K, V> HashBiMap<K, V> generateHashBiMap(K key, V value) {
     HashBiMap<K, V> bimap = HashBiMap.create();
     bimap.put(key, value);
     return bimap;
   }
 
-  @Generates private static <K, V> ImmutableBiMap<K, V> freshImmutableBimap(
+  @Generates private static <K, V> ImmutableBiMap<K, V> generateImmutableBimap(
       K key, V value) {
     return ImmutableBiMap.of(key, value);
   }
 
-  @Generates private static <R, C, V> Table<R, C, V> freshTable(R row, C column, V value) {
-    return freshHashBasedTable(row, column, value);
+  @Generates private static <R, C, V> Table<R, C, V> generateTable(R row, C column, V value) {
+    return generateHashBasedTable(row, column, value);
   }
 
-  @Generates private static <R, C, V> HashBasedTable<R, C, V> freshHashBasedTable(
+  @Generates private static <R, C, V> HashBasedTable<R, C, V> generateHashBasedTable(
       R row, C column, V value) {
     HashBasedTable<R, C, V> table = HashBasedTable.create();
     table.put(row, column, value);
@@ -721,82 +809,82 @@ class FreshValueGenerator {
 
   @SuppressWarnings("rawtypes") // TreeBasedTable.create() is defined as such
   @Generates private static <R extends Comparable, C extends Comparable, V> RowSortedTable<R, C, V>
-      freshRowSortedTable(R row, C column, V value) {
-    return freshTreeBasedTable(row, column, value);
+      generateRowSortedTable(R row, C column, V value) {
+    return generateTreeBasedTable(row, column, value);
   }
 
   @SuppressWarnings("rawtypes") // TreeBasedTable.create() is defined as such
   @Generates private static <R extends Comparable, C extends Comparable, V> TreeBasedTable<R, C, V>
-      freshTreeBasedTable(R row, C column, V value) {
+      generateTreeBasedTable(R row, C column, V value) {
     TreeBasedTable<R, C, V> table = TreeBasedTable.create();
     table.put(row, column, value);
     return table;
   }
 
-  @Generates private static <R, C, V> ImmutableTable<R, C, V> freshImmutableTable(
+  @Generates private static <R, C, V> ImmutableTable<R, C, V> generateImmutableTable(
       R row, C column, V value) {
     return ImmutableTable.of(row, column, value);
   }
 
   // common.reflect
-  @Generates private TypeToken<?> freshTypeToken() {
-    return TypeToken.of(freshClass());
+  @Generates private TypeToken<?> generateTypeToken() {
+    return TypeToken.of(generateClass());
   }
 
   // io types
-  @Generates private File freshFile() {
-    return new File(freshString());
+  @Generates private File generateFile() {
+    return new File(generateString());
   }
 
-  @Generates private static ByteArrayInputStream freshByteArrayInputStream() {
+  @Generates private static ByteArrayInputStream generateByteArrayInputStream() {
     return new ByteArrayInputStream(new byte[0]);
   }
 
-  @Generates private static InputStream freshInputStream() {
-    return freshByteArrayInputStream();
+  @Generates private static InputStream generateInputStream() {
+    return generateByteArrayInputStream();
   }
 
-  @Generates private StringReader freshStringReader() {
-    return new StringReader(freshString());
+  @Generates private StringReader generateStringReader() {
+    return new StringReader(generateString());
   }
 
-  @Generates private Reader freshReader() {
-    return freshStringReader();
+  @Generates private Reader generateReader() {
+    return generateStringReader();
   }
 
-  @Generates private Readable freshReadable() {
-    return freshReader();
+  @Generates private Readable generateReadable() {
+    return generateReader();
   }
 
-  @Generates private Buffer freshBuffer() {
-    return freshCharBuffer();
+  @Generates private Buffer generateBuffer() {
+    return generateCharBuffer();
   }
 
-  @Generates private CharBuffer freshCharBuffer() {
-    return CharBuffer.allocate(freshInt());
+  @Generates private CharBuffer generateCharBuffer() {
+    return CharBuffer.allocate(generateInt());
   }
 
-  @Generates private ByteBuffer freshByteBuffer() {
-    return ByteBuffer.allocate(freshInt());
+  @Generates private ByteBuffer generateByteBuffer() {
+    return ByteBuffer.allocate(generateInt());
   }
 
-  @Generates private ShortBuffer freshShortBuffer() {
-    return ShortBuffer.allocate(freshInt());
+  @Generates private ShortBuffer generateShortBuffer() {
+    return ShortBuffer.allocate(generateInt());
   }
 
-  @Generates private IntBuffer freshIntBuffer() {
-    return IntBuffer.allocate(freshInt());
+  @Generates private IntBuffer generateIntBuffer() {
+    return IntBuffer.allocate(generateInt());
   }
 
-  @Generates private LongBuffer freshLongBuffer() {
-    return LongBuffer.allocate(freshInt());
+  @Generates private LongBuffer generateLongBuffer() {
+    return LongBuffer.allocate(generateInt());
   }
 
-  @Generates private FloatBuffer freshFloatBuffer() {
-    return FloatBuffer.allocate(freshInt());
+  @Generates private FloatBuffer generateFloatBuffer() {
+    return FloatBuffer.allocate(generateInt());
   }
 
-  @Generates private DoubleBuffer freshDoubleBuffer() {
-    return DoubleBuffer.allocate(freshInt());
+  @Generates private DoubleBuffer generateDoubleBuffer() {
+    return DoubleBuffer.allocate(generateInt());
   }
 }
diff --git a/guava-testlib/src/com/google/common/testing/GcFinalization.java b/guava-testlib/src/com/google/common/testing/GcFinalization.java
index f1371b5..7041450 100644
--- a/guava-testlib/src/com/google/common/testing/GcFinalization.java
+++ b/guava-testlib/src/com/google/common/testing/GcFinalization.java
@@ -19,8 +19,10 @@ package com.google.common.testing;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import com.google.common.annotations.Beta;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
 
 import java.lang.ref.WeakReference;
+import java.util.Locale;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
@@ -99,6 +101,7 @@ import java.util.concurrent.TimeoutException;
  * @since 11.0
  */
 @Beta
+ at J2ObjCIncompatible // gc
 public final class GcFinalization {
   private GcFinalization() {}
 
@@ -152,8 +155,7 @@ public final class GcFinalization {
         /* OK */
       }
     } while (System.nanoTime() - deadline < 0);
-    throw new RuntimeException(
-        String.format("Future not done within %d second timeout", timeoutSeconds));
+    throw formatRuntimeException("Future not done within %d second timeout", timeoutSeconds);
   }
 
   /**
@@ -182,8 +184,8 @@ public final class GcFinalization {
         throw new RuntimeException("Unexpected interrupt while waiting for latch", ie);
       }
     } while (System.nanoTime() - deadline < 0);
-    throw new RuntimeException(
-        String.format("Latch failed to count down within %d second timeout", timeoutSeconds));
+    throw formatRuntimeException(
+        "Latch failed to count down within %d second timeout", timeoutSeconds);
   }
 
   /**
@@ -233,8 +235,8 @@ public final class GcFinalization {
         return;
       }
     } while (System.nanoTime() - deadline < 0);
-    throw new RuntimeException(
-        String.format("Predicate did not become true within %d second timeout", timeoutSeconds));
+    throw formatRuntimeException(
+        "Predicate did not become true within %d second timeout", timeoutSeconds);
   }
 
   /**
@@ -294,4 +296,8 @@ public final class GcFinalization {
     // Hope to catch some stragglers queued up behind our finalizable object
     System.runFinalization();
   }
+
+  private static RuntimeException formatRuntimeException(String format, Object... args) {
+    return new RuntimeException(String.format(Locale.ROOT, format, args));
+  }
 }
diff --git a/guava-testlib/src/com/google/common/testing/NullPointerTester.java b/guava-testlib/src/com/google/common/testing/NullPointerTester.java
index 209b949..190d0d0 100644
--- a/guava-testlib/src/com/google/common/testing/NullPointerTester.java
+++ b/guava-testlib/src/com/google/common/testing/NullPointerTester.java
@@ -291,7 +291,6 @@ public final class NullPointerTester {
     }
   }
 
-  // TODO(benyu): Use labs/reflect/Signature if it graduates.
   private static final class Signature {
     private final String name;
     private final ImmutableList<Class<?>> parameterTypes;
diff --git a/guava-testlib/src/com/google/common/testing/TestLogHandler.java b/guava-testlib/src/com/google/common/testing/TestLogHandler.java
index cb5bcbd..6ef3018 100644
--- a/guava-testlib/src/com/google/common/testing/TestLogHandler.java
+++ b/guava-testlib/src/com/google/common/testing/TestLogHandler.java
@@ -17,6 +17,7 @@
 package com.google.common.testing;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -54,16 +55,16 @@ import javax.annotation.Nullable;
  * @since 10.0
  */
 @Beta
+ at GwtCompatible
 public class TestLogHandler extends Handler {
   /** We will keep a private list of all logged records */
-  private final List<LogRecord> list =
-      Collections.synchronizedList(new ArrayList<LogRecord>());
+  private final List<LogRecord> list = new ArrayList<LogRecord>();
 
   /**
    * Adds the most recently logged record to our list.
    */
   @Override
-  public void publish(@Nullable LogRecord record) {
+  public synchronized void publish(@Nullable LogRecord record) {
     list.add(record);
   }
 
@@ -73,15 +74,21 @@ public class TestLogHandler extends Handler {
   @Override
   public void close() {}
 
-  public void clear() {
+  public synchronized void clear() {
     list.clear();
   }
 
   /**
-   * Fetch the list of logged records
-   * @return unmodifiable LogRecord list of all logged records
+   * Returns a snapshot of the logged records.
    */
-  public List<LogRecord> getStoredLogRecords() {
+  /*
+   * TODO(cpovirk): consider higher-level APIs here (say, assertNoRecordsLogged(),
+   * getOnlyRecordLogged(), getAndClearLogRecords()...)
+   *
+   * TODO(cpovirk): consider renaming this method to reflect that it takes a snapshot (and/or return
+   * an ImmutableList)
+   */
+  public synchronized List<LogRecord> getStoredLogRecords() {
     List<LogRecord> result = new ArrayList<LogRecord>(list);
     return Collections.unmodifiableList(result);
   }
diff --git a/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java b/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
index 68b9cfa..682ef97 100644
--- a/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
@@ -23,6 +23,12 @@ import com.google.common.annotations.GwtCompatible;
 
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Unit test for {@link Helpers}.
  *
@@ -33,4 +39,127 @@ public class HelpersTest extends TestCase {
   public void testNullsBeforeB() {
     testComparator(NullsBeforeB.INSTANCE, "a", "azzzzzz", null, "b", "c");
   }
+
+  public void testIsEmpty_iterable() {
+    List<Object> list = new ArrayList<Object>();
+    Helpers.assertEmpty(list);
+
+    list.add("a");
+    try {
+      Helpers.assertEmpty(list);
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
+
+  public void testIsEmpty_map() {
+    Map<Object, Object> map = new HashMap<Object, Object>();
+    Helpers.assertEmpty(map);
+
+    map.put("a", "b");
+    try {
+      Helpers.assertEmpty(map);
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
+
+  public void testAssertEqualInOrder() {
+    List<?> list = Arrays.asList("a", "b", "c");
+    Helpers.assertEqualInOrder(list, list);
+
+    List<?> fewer = Arrays.asList("a", "b");
+    try {
+      Helpers.assertEqualInOrder(list, fewer);
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertEqualInOrder(fewer, list);
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    List<?> differentOrder = Arrays.asList("a", "c", "b");
+    try {
+      Helpers.assertEqualInOrder(list, differentOrder);
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    List<?> differentContents = Arrays.asList("a", "b", "C");
+    try {
+      Helpers.assertEqualInOrder(list, differentContents);
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
+
+  public void testAssertContentsInOrder() {
+    List<?> list = Arrays.asList("a", "b", "c");
+    Helpers.assertContentsInOrder(list, "a", "b", "c");
+
+    try {
+      Helpers.assertContentsInOrder(list, "a", "b");
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertContentsInOrder(list, "a", "b", "c", "d");
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertContentsInOrder(list, "a", "c", "b");
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertContentsInOrder(list, "a", "B", "c");
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
+
+  public void testAssertContains() {
+    List<?> list = Arrays.asList("a", "b");
+    Helpers.assertContains(list, "a");
+    Helpers.assertContains(list, "b");
+
+    try {
+      Helpers.assertContains(list, "c");
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
+
+  public void testAssertContainsAllOf() {
+    List<?> list = Arrays.asList("a", "a", "b", "c");
+    Helpers.assertContainsAllOf(list, "a");
+    Helpers.assertContainsAllOf(list, "a", "a");
+    Helpers.assertContainsAllOf(list, "a", "b", "c");
+    Helpers.assertContainsAllOf(list, "a", "b", "c", "a");
+
+    try {
+      Helpers.assertContainsAllOf(list, "d");
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertContainsAllOf(list, "a", "b", "c", "d");
+      fail();
+    } catch (AssertionError expected) {
+    }
+
+    try {
+      Helpers.assertContainsAllOf(list, "a", "a", "a");
+      fail();
+    } catch (AssertionError expected) {
+    }
+  }
 }
diff --git a/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java b/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
index 394dcd4..7ebcae0 100644
--- a/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
@@ -23,6 +23,7 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Method;
+import java.util.Locale;
 
 /**
  * Since annotations have some reusability issues that force copy and paste
@@ -35,19 +36,19 @@ public class FeatureEnumTest extends TestCase {
   private static void assertGoodTesterAnnotation(
       Class<? extends Annotation> annotationClass) {
     assertNotNull(
-        String.format("%s must be annotated with @TesterAnnotation.",
+        rootLocaleFormat("%s must be annotated with @TesterAnnotation.",
             annotationClass),
         annotationClass.getAnnotation(TesterAnnotation.class));
     final Retention retentionPolicy =
         annotationClass.getAnnotation(Retention.class);
     assertNotNull(
-        String.format("%s must have a @Retention annotation.", annotationClass),
+        rootLocaleFormat("%s must have a @Retention annotation.", annotationClass),
         retentionPolicy);
     assertEquals(
-        String.format("%s must have RUNTIME RetentionPolicy.", annotationClass),
+        rootLocaleFormat("%s must have RUNTIME RetentionPolicy.", annotationClass),
         RetentionPolicy.RUNTIME, retentionPolicy.value());
     assertNotNull(
-        String.format("%s must be inherited.", annotationClass),
+        rootLocaleFormat("%s must be inherited.", annotationClass),
         annotationClass.getAnnotation(Inherited.class));
 
     for (String propertyName : new String[]{"value", "absent"}) {
@@ -55,14 +56,14 @@ public class FeatureEnumTest extends TestCase {
       try {
         method = annotationClass.getMethod(propertyName);
       } catch (NoSuchMethodException e) {
-        fail(String.format("%s must have a property named '%s'.",
+        fail(rootLocaleFormat("%s must have a property named '%s'.",
             annotationClass, propertyName));
       }
       final Class<?> returnType = method.getReturnType();
-      assertTrue(String.format("%s.%s() must return an array.",
+      assertTrue(rootLocaleFormat("%s.%s() must return an array.",
           annotationClass, propertyName),
           returnType.isArray());
-      assertSame(String.format("%s.%s() must return an array of %s.",
+      assertSame(rootLocaleFormat("%s.%s() must return an array of %s.",
           annotationClass, propertyName, annotationClass.getDeclaringClass()),
           annotationClass.getDeclaringClass(), returnType.getComponentType());
     }
@@ -78,14 +79,14 @@ public class FeatureEnumTest extends TestCase {
         if (containedClass.isAnnotation()) {
           assertGoodTesterAnnotation(asAnnotation(containedClass));
         } else {
-          fail(String.format("Feature enum %s contains a class named " +
-              "'Require' but it is not an annotation.", featureEnumClass));
+          fail(rootLocaleFormat("Feature enum %s contains a class named "
+              + "'Require' but it is not an annotation.", featureEnumClass));
         }
         return;
       }
     }
-    fail(String.format("Feature enum %s should contain an " +
-        "annotation named 'Require'.", featureEnumClass));
+    fail(rootLocaleFormat("Feature enum %s should contain an "
+        + "annotation named 'Require'.", featureEnumClass));
   }
 
   @SuppressWarnings("unchecked")
@@ -94,7 +95,7 @@ public class FeatureEnumTest extends TestCase {
       return (Class<? extends Annotation>) clazz;
     } else {
       throw new IllegalArgumentException(
-          String.format("%s is not an annotation.", clazz));
+          rootLocaleFormat("%s is not an annotation.", clazz));
     }
   }
 
@@ -105,4 +106,8 @@ public class FeatureEnumTest extends TestCase {
     assertGoodFeatureEnum(CollectionSize.class);
     assertGoodFeatureEnum(MapFeature.class);
   }
+
+  private static String rootLocaleFormat(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java b/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
index 70ec78a..9fcfa51 100644
--- a/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
@@ -159,18 +159,17 @@ public class FeatureUtilTest extends TestCase {
 
     features = Sets.<Feature<?>>newHashSet(
         ExampleDerivedFeature.DERIVED_FEATURE_1);
-    assertThat(FeatureUtil.addImpliedFeatures(features)).has().item(
-        ExampleDerivedFeature.DERIVED_FEATURE_1);
+    assertThat(FeatureUtil.addImpliedFeatures(features))
+        .contains(ExampleDerivedFeature.DERIVED_FEATURE_1);
 
-    features = Sets.<Feature<?>>newHashSet(
-        ExampleDerivedFeature.DERIVED_FEATURE_2);
-    assertThat(FeatureUtil.addImpliedFeatures(features)).has().exactly(
+    features = Sets.<Feature<?>>newHashSet(ExampleDerivedFeature.DERIVED_FEATURE_2);
+    assertThat(FeatureUtil.addImpliedFeatures(features)).containsExactly(
         ExampleDerivedFeature.DERIVED_FEATURE_2,
         ExampleBaseFeature.BASE_FEATURE_1);
 
     features = Sets.<Feature<?>>newHashSet(
         ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
-    assertThat(FeatureUtil.addImpliedFeatures(features)).has().exactly(
+    assertThat(FeatureUtil.addImpliedFeatures(features)).containsExactly(
         ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE,
         ExampleDerivedFeature.DERIVED_FEATURE_1,
         ExampleDerivedFeature.DERIVED_FEATURE_2,
@@ -193,12 +192,10 @@ public class FeatureUtilTest extends TestCase {
 
     features = Sets.<Feature<?>>newHashSet(
         ExampleDerivedFeature.DERIVED_FEATURE_2);
-    assertThat(FeatureUtil.impliedFeatures(features)).has().item(
-        ExampleBaseFeature.BASE_FEATURE_1);
+    assertThat(FeatureUtil.impliedFeatures(features)).contains(ExampleBaseFeature.BASE_FEATURE_1);
 
-    features = Sets.<Feature<?>>newHashSet(
-        ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
-    assertThat(FeatureUtil.impliedFeatures(features)).has().exactly(
+    features = Sets.<Feature<?>>newHashSet(ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
+    assertThat(FeatureUtil.impliedFeatures(features)).containsExactly(
         ExampleDerivedFeature.DERIVED_FEATURE_1,
         ExampleDerivedFeature.DERIVED_FEATURE_2,
         ExampleBaseFeature.BASE_FEATURE_1,
@@ -250,8 +247,7 @@ public class FeatureUtilTest extends TestCase {
           ExampleDerivedInterfaceTester_Conflict.class);
       fail("Expected ConflictingRequirementsException");
     } catch (ConflictingRequirementsException e) {
-      assertThat(e.getConflicts()).has().item(
-          ExampleBaseFeature.BASE_FEATURE_1);
+      assertThat(e.getConflicts()).contains(ExampleBaseFeature.BASE_FEATURE_1);
       assertEquals(ExampleDerivedInterfaceTester_Conflict.class, e.getSource());
     }
   }
@@ -264,8 +260,7 @@ public class FeatureUtilTest extends TestCase {
       FeatureUtil.buildTesterRequirements(method);
       fail("Expected ConflictingRequirementsException");
     } catch (ConflictingRequirementsException e) {
-      assertThat(e.getConflicts()).has().item(
-          ExampleBaseFeature.BASE_FEATURE_1);
+      assertThat(e.getConflicts()).contains(ExampleBaseFeature.BASE_FEATURE_1);
       assertEquals(method, e.getSource());
     }
   }
diff --git a/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java b/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
index 43dcc1c..b0f2787 100644
--- a/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
+++ b/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
@@ -47,31 +47,38 @@ public class AbstractPackageSanityTestsTest extends TestCase {
   }
 
   public void testFindClassesToTest_noCorrespondingTestClass() {
-    assertThat(findClassesToTest(ImmutableList.of(Foo.class)))
-        .has().exactly(Foo.class).inOrder();
+    assertThat(findClassesToTest(ImmutableList.of(Foo.class))).containsExactly(Foo.class);
     assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo2Test.class)))
-        .has().exactly(Foo.class).inOrder();
+        .containsExactly(Foo.class);
   }
 
   public void testFindClassesToTest_publicApiOnly() {
     sanityTests.publicApiOnly();
     assertThat(findClassesToTest(ImmutableList.of(Foo.class)))
         .isEmpty();
-    assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class))).has().item(PublicFoo.class);
+    assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class))).contains(PublicFoo.class);
   }
 
   public void testFindClassesToTest_ignoreClasses() {
     sanityTests.ignoreClasses(Predicates.<Object>equalTo(PublicFoo.class));
     assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class)))
         .isEmpty();
-    assertThat(findClassesToTest(ImmutableList.of(Foo.class))).has().item(Foo.class);
+    assertThat(findClassesToTest(ImmutableList.of(Foo.class))).contains(Foo.class);
+  }
+
+  public void testFindClassesToTeset_ignoreUnderscores() {
+    assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo_Bar.class)))
+        .containsExactly(Foo.class, Foo_Bar.class);
+    sanityTests.ignoreClasses(AbstractPackageSanityTests.UNDERSCORE_IN_NAME);
+    assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo_Bar.class)))
+        .containsExactly(Foo.class);
   }
 
   public void testFindClassesToTest_withCorrespondingTestClassButNotExplicitlyTested() {
     assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class), "testNotThere"))
-        .has().exactly(Foo.class).inOrder();
+        .containsExactly(Foo.class);
     assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class), "testNotPublic"))
-        .has().exactly(Foo.class).inOrder();
+        .containsExactly(Foo.class);
   }
 
   public void testFindClassesToTest_withCorrespondingTestClassAndExplicitlyTested() {
@@ -84,7 +91,7 @@ public class AbstractPackageSanityTestsTest extends TestCase {
 
   public void testFindClassesToTest_withCorrespondingTestClass_noTestName() {
     assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class)))
-        .has().exactly(Foo.class).inOrder();
+        .containsExactly(Foo.class);
   }
 
   static class EmptyTestCase {}
@@ -97,6 +104,8 @@ public class AbstractPackageSanityTestsTest extends TestCase {
 
   static class Foo {}
 
+  static class Foo_Bar {}
+
   public static class PublicFoo {}
 
   static class FooTest {
diff --git a/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java b/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
index bf2be65..e94d283 100644
--- a/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
+++ b/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.testing;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Charsets;
 import com.google.common.base.Equivalence;
@@ -222,9 +224,9 @@ public class ArbitraryInstancesTest extends TestCase {
     assertNotNull(ArbitraryInstances.get(CharMatcher.class));
     assertNotNull(ArbitraryInstances.get(Currency.class).getCurrencyCode());
     assertNotNull(ArbitraryInstances.get(Locale.class));
-    ArbitraryInstances.get(Joiner.class).join(ImmutableList.of("a"));
-    ArbitraryInstances.get(Splitter.class).split("a,b");
-    assertFalse(ArbitraryInstances.get(Optional.class).isPresent());
+    assertNotNull(ArbitraryInstances.get(Joiner.class).join(ImmutableList.of("a")));
+    assertNotNull(ArbitraryInstances.get(Splitter.class).split("a,b"));
+    assertThat(ArbitraryInstances.get(Optional.class)).isAbsent();
     ArbitraryInstances.get(Stopwatch.class).start();
     assertNotNull(ArbitraryInstances.get(Ticker.class));
     assertNotNull(ArbitraryInstances.get(MapConstraint.class));
@@ -271,9 +273,9 @@ public class ArbitraryInstancesTest extends TestCase {
   }
 
   public void testGet_array() {
-    assertEquals(0, ArbitraryInstances.get(int[].class).length);
-    assertEquals(0, ArbitraryInstances.get(Object[].class).length);
-    assertEquals(0, ArbitraryInstances.get(String[].class).length);
+    assertThat(ArbitraryInstances.get(int[].class)).isEmpty();
+    assertThat(ArbitraryInstances.get(Object[].class)).isEmpty();
+    assertThat(ArbitraryInstances.get(String[].class)).isEmpty();
   }
 
   public void testGet_enum() {
@@ -302,13 +304,17 @@ public class ArbitraryInstancesTest extends TestCase {
   public void testGet_mutable() {
     assertEquals(0, ArbitraryInstances.get(ArrayList.class).size());
     assertEquals(0, ArbitraryInstances.get(HashMap.class).size());
-    assertEquals("", ArbitraryInstances.get(Appendable.class).toString());
-    assertEquals("", ArbitraryInstances.get(StringBuilder.class).toString());
-    assertEquals("", ArbitraryInstances.get(StringBuffer.class).toString());
+    assertThat(ArbitraryInstances.get(Appendable.class).toString()).isEmpty();
+    assertThat(ArbitraryInstances.get(StringBuilder.class).toString()).isEmpty();
+    assertThat(ArbitraryInstances.get(StringBuffer.class).toString()).isEmpty();
     assertFreshInstanceReturned(
-        ArrayList.class, HashMap.class,
-        Appendable.class, StringBuilder.class, StringBuffer.class,
-        Throwable.class, Exception.class);
+        ArrayList.class,
+        HashMap.class,
+        Appendable.class,
+        StringBuilder.class,
+        StringBuffer.class,
+        Throwable.class,
+        Exception.class);
   }
 
   public void testGet_io() throws IOException {
diff --git a/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java b/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
index 4848293..639b73f 100644
--- a/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
@@ -35,6 +35,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -83,10 +84,11 @@ public class ClassSanityTesterTest extends TestCase {
     try {
       tester.forAllPublicStaticMethods(NoPublicStaticMethods.class).testEquals();
     } catch (AssertionFailedError expected) {
-      assertEquals(
-          "No public static methods that return java.lang.Object or subtype are found in "
-              + NoPublicStaticMethods.class + ".",
-          expected.getMessage());
+      assertThat(expected)
+          .hasMessage(
+              "No public static methods that return java.lang.Object or subtype are found in "
+                  + NoPublicStaticMethods.class
+                  + ".");
       return;
     }
     fail();
@@ -140,10 +142,11 @@ public class ClassSanityTesterTest extends TestCase {
           .thatReturn(Iterable.class)
           .testNulls();
     } catch (AssertionFailedError expected) {
-      assertEquals(
-          "No public static methods that return java.lang.Iterable or subtype are found in "
-              + BadNullsFactory.class + ".",
-          expected.getMessage());
+      assertThat(expected)
+          .hasMessage(
+              "No public static methods that return java.lang.Iterable or subtype are found in "
+                  + BadNullsFactory.class
+                  + ".");
       return;
     }
     fail();
@@ -543,6 +546,7 @@ public class ClassSanityTesterTest extends TestCase {
     NotInstantiable y = new NotInstantiable();
     tester.setDistinctValues(NotInstantiable.class, x, y);
     assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class));
+    tester.testEquals(ConstructorParameterMapOfNotInstantiable.class);
   }
 
   public void testInstantiate_setSampleInstances_empty() throws Exception {
@@ -1185,6 +1189,25 @@ public class ClassSanityTesterTest extends TestCase {
     public ConstructorParameterNotInstantiable(@SuppressWarnings("unused") NotInstantiable x) {}
   }
 
+  static class ConstructorParameterMapOfNotInstantiable {
+    private final Map<NotInstantiable, NotInstantiable> m;
+    
+    public ConstructorParameterMapOfNotInstantiable(
+        Map<NotInstantiable, NotInstantiable> m) {
+      this.m = checkNotNull(m);
+    }
+    @Override public boolean equals(@Nullable Object obj) {
+      if (obj instanceof ConstructorParameterMapOfNotInstantiable) {
+        return m.equals(((ConstructorParameterMapOfNotInstantiable) obj).m);
+      } else {
+        return false;
+      }
+    }
+    @Override public int hashCode() {
+      return m.hashCode();
+    }
+  }
+
   // Test that we should get a distinct parameter error when doing equals test.
   static class ConstructorParameterWithOptionalNotInstantiable {
     public ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x) {
diff --git a/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java b/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
index 9c5bf13..2476a12 100644
--- a/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
@@ -389,10 +389,7 @@ public class EqualsTesterTest extends TestCase {
   private static class InvalidEqualsIncompatibleClassObject {
 
     @Override public boolean equals(Object o) {
-      if (o == null) {
-        return false;
-      }
-      return true;
+      return o != null;
     }
 
     @Override public int hashCode() {
diff --git a/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java b/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
index b45fc03..b0547d1 100644
--- a/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
+++ b/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
@@ -46,7 +46,6 @@ import com.google.common.collect.ImmutableTable;
 import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.LinkedHashMultiset;
 import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multiset;
@@ -54,7 +53,6 @@ import com.google.common.collect.Ordering;
 import com.google.common.collect.Range;
 import com.google.common.collect.RowSortedTable;
 import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
 import com.google.common.collect.SortedMultiset;
 import com.google.common.collect.Table;
 import com.google.common.collect.TreeBasedTable;
@@ -153,15 +151,15 @@ public class FreshValueGeneratorTest extends TestCase {
 
   public void testStringArray() {
     FreshValueGenerator generator = new FreshValueGenerator();
-    String[] a1 = generator.generate(String[].class);
-    String[] a2 = generator.generate(String[].class);
+    String[] a1 = generator.generateFresh(String[].class);
+    String[] a2 = generator.generateFresh(String[].class);
     assertFalse(a1[0].equals(a2[0]));
   }
 
   public void testPrimitiveArray() {
     FreshValueGenerator generator = new FreshValueGenerator();
-    int[] a1 = generator.generate(int[].class);
-    int[] a2 = generator.generate(int[].class);
+    int[] a1 = generator.generateFresh(int[].class);
+    int[] a2 = generator.generateFresh(int[].class);
     assertTrue(a1[0] != a2[0]);
   }
 
@@ -171,503 +169,261 @@ public class FreshValueGeneratorTest extends TestCase {
 
   public void testImmutableList() {
     assertFreshInstance(new TypeToken<ImmutableList<String>>() {});
-    assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableList<String>>() {}));
-    assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(int.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableList<Integer>>() {}));
-    assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableList<?>>() {}));
   }
 
   public void testImmutableSet() {
     assertFreshInstance(new TypeToken<ImmutableSet<String>>() {});
-    assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableSet<String>>() {}));
-    assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableSet<Number>>() {}));
-    assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableSet<? extends Number>>() {}));
   }
 
   public void testImmutableSortedSet() {
     assertFreshInstance(new TypeToken<ImmutableSortedSet<String>>() {});
-    assertValueAndTypeEquals(
-        ImmutableSortedSet.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableSortedSet<String>>() {}));
   }
 
   public void testImmutableMultiset() {
     assertFreshInstance(new TypeToken<ImmutableSortedSet<String>>() {});
-    assertValueAndTypeEquals(ImmutableMultiset.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableMultiset<String>>() {}));
-    assertValueAndTypeEquals(ImmutableMultiset.of(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableMultiset<Number>>() {}));
     assertNotInstantiable(new TypeToken<ImmutableMultiset<EmptyEnum>>() {});
   }
 
   public void testImmutableCollection() {
     assertFreshInstance(new TypeToken<ImmutableCollection<String>>() {});
-    assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableCollection<String>>() {}));
     assertNotInstantiable(new TypeToken<ImmutableCollection<EmptyEnum>>() {});
   }
 
   public void testImmutableMap() {
     assertFreshInstance(new TypeToken<ImmutableMap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableMap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableMap<String, Integer>>() {}));
   }
 
   public void testImmutableSortedMap() {
     assertFreshInstance(new TypeToken<ImmutableSortedMap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableSortedMap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(
-            new TypeToken<ImmutableSortedMap<String, Integer>>() {}));
   }
 
   public void testImmutableMultimap() {
     assertFreshInstance(new TypeToken<ImmutableMultimap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableMultimap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableMultimap<String, Integer>>() {}));
     assertNotInstantiable(new TypeToken<ImmutableMultimap<EmptyEnum, String>>() {});
   }
 
   public void testImmutableListMultimap() {
     assertFreshInstance(new TypeToken<ImmutableListMultimap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableListMultimap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(
-            new TypeToken<ImmutableListMultimap<String, Integer>>() {}));
   }
 
   public void testImmutableSetMultimap() {
     assertFreshInstance(new TypeToken<ImmutableSetMultimap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableSetMultimap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(
-            new TypeToken<ImmutableSetMultimap<String, Integer>>() {}));
   }
 
   public void testImmutableBiMap() {
     assertFreshInstance(new TypeToken<ImmutableBiMap<String, Integer>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableBiMap.of(generator.generate(String.class), generator.generate(int.class)),
-        new FreshValueGenerator().generate(
-            new TypeToken<ImmutableBiMap<String, Integer>>() {}));
   }
 
   public void testImmutableTable() {
     assertFreshInstance(new TypeToken<ImmutableTable<String, Integer, ImmutableList<String>>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    assertValueAndTypeEquals(
-        ImmutableTable.of(
-            generator.generate(String.class), generator.generate(int.class),
-            generator.generate(new TypeToken<ImmutableList<String>>() {})),
-        new FreshValueGenerator().generate(
-            new TypeToken<ImmutableTable<String, Integer, ImmutableList<String>>>() {}));
   }
 
   public void testList() {
     assertFreshInstance(new TypeToken<List<String>>() {});
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<List<String>>() {}));
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(int.class)),
-        new FreshValueGenerator().generate(new TypeToken<List<Integer>>() {}));
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<List<?>>() {}));
     assertNotInstantiable(new TypeToken<List<EmptyEnum>>() {});
   }
 
   public void testArrayList() {
     assertFreshInstance(new TypeToken<ArrayList<String>>() {});
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ArrayList<String>>() {}));
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(int.class)),
-        new FreshValueGenerator().generate(new TypeToken<ArrayList<Integer>>() {}));
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ArrayList<?>>() {}));
     assertNotInstantiable(new TypeToken<ArrayList<EmptyEnum>>() {});
   }
 
   public void testLinkedList() {
     assertFreshInstance(new TypeToken<LinkedList<String>>() {});
-    assertValueAndTypeEquals(newLinkedList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<LinkedList<String>>() {}));
   }
 
   public void testSet() {
     assertFreshInstance(new TypeToken<Set<String>>() {});
-    assertValueAndTypeEquals(
-        newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<Set<? extends Number>>() {}));
     assertNotInstantiable(new TypeToken<Set<EmptyEnum>>() {});
   }
 
   public void testHashSet() {
     assertFreshInstance(new TypeToken<HashSet<String>>() {});
-    assertValueAndTypeEquals(
-        newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<HashSet<? extends Number>>() {}));
   }
 
   public void testLinkedHashSet() {
     assertFreshInstance(new TypeToken<LinkedHashSet<String>>() {});
-    assertValueAndTypeEquals(
-        newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
-        new FreshValueGenerator().generate(new TypeToken<LinkedHashSet<? extends Number>>() {}));
   }
 
   public void testTreeSet() {
     assertFreshInstance(new TypeToken<TreeSet<String>>() {});
-    TreeSet<String> expected = Sets.newTreeSet();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<TreeSet<? extends CharSequence>>() {}));
-    assertNotInstantiable(new TypeToken<TreeSet<EmptyEnum>>() {});
   }
 
   public void testSortedSet() {
     assertFreshInstance(new TypeToken<SortedSet<String>>() {});
-    TreeSet<String> expected = Sets.newTreeSet();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<SortedSet<String>>() {}));
-    assertNotInstantiable(new TypeToken<SortedSet<EmptyEnum>>() {});
   }
 
   public void testNavigableSet() {
     assertFreshInstance(new TypeToken<NavigableSet<String>>() {});
-    TreeSet<String> expected = Sets.newTreeSet();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<NavigableSet<String>>() {}));
-    assertNotInstantiable(new TypeToken<NavigableSet<EmptyEnum>>() {});
   }
 
   public void testMultiset() {
     assertFreshInstance(new TypeToken<Multiset<String>>() {});
-    Multiset<String> expected = HashMultiset.create();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<Multiset<String>>() {}));
-    assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
   }
 
   public void testSortedMultiset() {
     assertFreshInstance(new TypeToken<SortedMultiset<String>>() {});
-    SortedMultiset<String> expected = TreeMultiset.create();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<SortedMultiset<String>>() {}));
-    assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
   }
 
   public void testHashMultiset() {
     assertFreshInstance(new TypeToken<HashMultiset<String>>() {});
-    HashMultiset<String> expected = HashMultiset.create();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<HashMultiset<String>>() {}));
   }
 
   public void testLinkedHashMultiset() {
     assertFreshInstance(new TypeToken<LinkedHashMultiset<String>>() {});
-    LinkedHashMultiset<String> expected = LinkedHashMultiset.create();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<LinkedHashMultiset<String>>() {}));
   }
 
   public void testTreeMultiset() {
     assertFreshInstance(new TypeToken<TreeMultiset<String>>() {});
-    TreeMultiset<String> expected = TreeMultiset.create();
-    expected.add(new FreshValueGenerator().generate(String.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<TreeMultiset<String>>() {}));
   }
 
   public void testImmutableSortedMultiset() {
     assertFreshInstance(new TypeToken<ImmutableSortedMultiset<String>>() {});
-    assertValueAndTypeEquals(
-        ImmutableSortedMultiset.of(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<ImmutableSortedMultiset<String>>() {}));
-    assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
   }
 
   public void testCollection() {
     assertFreshInstance(new TypeToken<Collection<String>>() {});
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<Collection<String>>() {}));
-    assertNotInstantiable(new TypeToken<Collection<EmptyEnum>>() {});
   }
 
   public void testIterable() {
     assertFreshInstance(new TypeToken<Iterable<String>>() {});
-    assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
-        new FreshValueGenerator().generate(new TypeToken<Iterable<String>>() {}));
-    assertNotInstantiable(new TypeToken<Iterable<EmptyEnum>>() {});
   }
 
   public void testMap() {
     assertFreshInstance(new TypeToken<Map<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    Map<String, Integer> expected = Maps.newLinkedHashMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<Map<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<Map<EmptyEnum, String>>() {});
   }
 
   public void testHashMap() {
     assertFreshInstance(new TypeToken<HashMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    HashMap<String, Integer> expected = Maps.newLinkedHashMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<HashMap<String, Integer>>() {}));
   }
 
   public void testLinkedHashMap() {
     assertFreshInstance(new TypeToken<LinkedHashMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    LinkedHashMap<String, Integer> expected = Maps.newLinkedHashMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<LinkedHashMap<String, Integer>>() {}));
   }
 
   public void testTreeMap() {
     assertFreshInstance(new TypeToken<TreeMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    TreeMap<String, Integer> expected = Maps.newTreeMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<TreeMap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<LinkedHashSet<EmptyEnum>>() {});
   }
 
   public void testSortedMap() {
     assertFreshInstance(new TypeToken<SortedMap<?, String>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    TreeMap<String, Integer> expected = Maps.newTreeMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<SortedMap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<SortedMap<EmptyEnum, String>>() {});
   }
 
   public void testNavigableMap() {
     assertFreshInstance(new TypeToken<NavigableMap<?, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    TreeMap<String, Integer> expected = Maps.newTreeMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<NavigableMap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<NavigableMap<EmptyEnum, String>>() {});
   }
 
   public void testConcurrentMap() {
     assertFreshInstance(new TypeToken<ConcurrentMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    ConcurrentMap<String, Integer> expected = Maps.newConcurrentMap();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<ConcurrentMap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<ConcurrentMap<EmptyEnum, String>>() {});
+    assertCanGenerateOnly(new TypeToken<ConcurrentMap<EmptyEnum, String>>() {},
+        Maps.newConcurrentMap());
   }
 
   public void testMultimap() {
     assertFreshInstance(new TypeToken<Multimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    Multimap<String, Integer> expected = ArrayListMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<Multimap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<Multimap<EmptyEnum, String>>() {});
   }
 
   public void testHashMultimap() {
     assertFreshInstance(new TypeToken<HashMultimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    HashMultimap<String, Integer> expected = HashMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(new TypeToken<HashMultimap<String, Integer>>() {}));
   }
 
   public void testLinkedHashMultimap() {
     assertFreshInstance(new TypeToken<LinkedHashMultimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    LinkedHashMultimap<String, Integer> expected = LinkedHashMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<LinkedHashMultimap<String, Integer>>() {}));
   }
 
   public void testListMultimap() {
     assertFreshInstance(new TypeToken<ListMultimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    ListMultimap<String, Integer> expected = ArrayListMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<ListMultimap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<ListMultimap<EmptyEnum, String>>() {});
   }
 
   public void testArrayListMultimap() {
     assertFreshInstance(new TypeToken<ArrayListMultimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    ArrayListMultimap<String, Integer> expected = ArrayListMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<ArrayListMultimap<String, Integer>>() {}));
   }
 
   public void testSetMultimap() {
     assertFreshInstance(new TypeToken<SetMultimap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    SetMultimap<String, Integer> expected = LinkedHashMultimap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<SetMultimap<String, Integer>>() {}));
-    assertNotInstantiable(new TypeToken<SetMultimap<EmptyEnum, String>>() {});
   }
 
   public void testBiMap() {
     assertFreshInstance(new TypeToken<BiMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    BiMap<String, Integer> expected = HashBiMap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<BiMap<String, Integer>>() {}));
     assertNotInstantiable(new TypeToken<BiMap<EmptyEnum, String>>() {});
   }
 
   public void testHashBiMap() {
     assertFreshInstance(new TypeToken<HashBiMap<String, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    HashBiMap<String, Integer> expected = HashBiMap.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<HashBiMap<String, Integer>>() {}));
   }
 
   public void testTable() {
     assertFreshInstance(new TypeToken<Table<String, ?, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    Table<String, Integer, Object> expected = HashBasedTable.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class),
-            generator.generate(new TypeToken<List<String>>() {}));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<Table<String, Integer, List<String>>>() {}));
     assertNotInstantiable(new TypeToken<Table<EmptyEnum, String, Integer>>() {});
   }
 
   public void testHashBasedTable() {
     assertFreshInstance(new TypeToken<HashBasedTable<String, ?, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    HashBasedTable<String, Integer, Object> expected = HashBasedTable.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class),
-            generator.generate(new TypeToken<List<String>>() {}));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<HashBasedTable<String, Integer, List<String>>>() {}));
   }
 
   public void testRowSortedTable() {
     assertFreshInstance(new TypeToken<RowSortedTable<String, ?, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    RowSortedTable<String, Integer, Object> expected = TreeBasedTable.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class),
-            generator.generate(new TypeToken<List<String>>() {}));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<RowSortedTable<String, Integer, List<String>>>() {}));
-    assertNotInstantiable(new TypeToken<RowSortedTable<EmptyEnum, String, Integer>>() {});
   }
 
   public void testTreeBasedTable() {
     assertFreshInstance(new TypeToken<TreeBasedTable<String, ?, ?>>() {});
-    FreshValueGenerator generator = new FreshValueGenerator();
-    TreeBasedTable<String, Integer, Object> expected = TreeBasedTable.create();
-    expected.put(generator.generate(String.class), generator.generate(int.class),
-            generator.generate(new TypeToken<List<String>>() {}));
-    assertValueAndTypeEquals(expected,
-        new FreshValueGenerator().generate(
-            new TypeToken<TreeBasedTable<String, Integer, List<String>>>() {}));
   }
 
   public void testObject() {
-    assertEquals(new FreshValueGenerator().generate(String.class),
-        new FreshValueGenerator().generate(Object.class));
+    assertEquals(new FreshValueGenerator().generateFresh(String.class),
+        new FreshValueGenerator().generateFresh(Object.class));
   }
 
   public void testEnums() {
     assertEqualInstance(EmptyEnum.class, null);
     assertEqualInstance(OneConstantEnum.class, OneConstantEnum.CONSTANT1);
-    assertFreshInstance(TwoConstantEnum.class);
-    assertFreshInstance(new TypeToken<Optional<OneConstantEnum>>() {});
+    assertFreshInstance(TwoConstantEnum.class, 2);
+    assertFreshInstance(new TypeToken<Optional<OneConstantEnum>>() {}, 2);
+    assertFreshInstance(new TypeToken<List<OneConstantEnum>>() {}, 1);
+    assertFreshInstance(new TypeToken<List<TwoConstantEnum>>() {}, 2);
   }
 
   public void testOptional() {
     FreshValueGenerator generator = new FreshValueGenerator();
-    assertEquals(Optional.absent(), generator.generate(new TypeToken<Optional<String>>() {}));
-    assertEquals(Optional.of("1"), generator.generate(new TypeToken<Optional<String>>() {}));
+    assertEquals(Optional.absent(), generator.generateFresh(new TypeToken<Optional<String>>() {}));
+    assertEquals(Optional.of("2"), generator.generateFresh(new TypeToken<Optional<String>>() {}));
     // Test that the first generated instance for different Optional<T> is always absent().
     // Having generated Optional<String> instances doesn't prevent absent() from being generated for
     // other Optional types.
     assertEquals(Optional.absent(),
-        generator.generate(new TypeToken<Optional<OneConstantEnum>>() {}));
+        generator.generateFresh(new TypeToken<Optional<OneConstantEnum>>() {}));
     assertEquals(Optional.of(OneConstantEnum.CONSTANT1),
-        generator.generate(new TypeToken<Optional<OneConstantEnum>>() {}));
+        generator.generateFresh(new TypeToken<Optional<OneConstantEnum>>() {}));
   }
 
   public void testAddSampleInstances_twoInstances() {
     FreshValueGenerator generator = new FreshValueGenerator();
     generator.addSampleInstances(String.class, ImmutableList.of("a", "b"));
-    assertEquals("a", generator.generate(String.class));
-    assertEquals("b", generator.generate(String.class));
-    assertEquals("a", generator.generate(String.class));
+    assertEquals("a", generator.generateFresh(String.class));
+    assertEquals("b", generator.generateFresh(String.class));
+    assertEquals("a", generator.generateFresh(String.class));
   }
 
   public void testAddSampleInstances_oneInstance() {
     FreshValueGenerator generator = new FreshValueGenerator();
     generator.addSampleInstances(String.class, ImmutableList.of("a"));
-    assertEquals("a", generator.generate(String.class));
-    assertEquals("a", generator.generate(String.class));
+    assertEquals("a", generator.generateFresh(String.class));
+    assertEquals("a", generator.generateFresh(String.class));
   }
 
   public void testAddSampleInstances_noInstance() {
     FreshValueGenerator generator = new FreshValueGenerator();
     generator.addSampleInstances(String.class, ImmutableList.<String>of());
-    assertEquals(new FreshValueGenerator().generate(String.class),
-        generator.generate(String.class));
+    assertEquals(new FreshValueGenerator().generateFresh(String.class),
+        generator.generateFresh(String.class));
   }
 
   public void testFreshCurrency() {
     FreshValueGenerator generator = new FreshValueGenerator();
     // repeat a few times to make sure we don't stumble upon a bad Locale
-    assertNotNull(generator.generate(Currency.class));
-    assertNotNull(generator.generate(Currency.class));
-    assertNotNull(generator.generate(Currency.class));
+    assertNotNull(generator.generateFresh(Currency.class));
+    assertNotNull(generator.generateFresh(Currency.class));
+    assertNotNull(generator.generateFresh(Currency.class));
   }
 
   public void testNulls() throws Exception {
@@ -678,26 +434,31 @@ public class FreshValueGeneratorTest extends TestCase {
 
   private static void assertFreshInstances(Class<?>... types) {
     for (Class<?> type : types) {
-      assertFreshInstance(type);
+      assertFreshInstance(type, 2);
     }
   }
 
   private static void assertFreshInstance(TypeToken<?> type) {
-    FreshValueGenerator generator = new FreshValueGenerator();
-    Object value1 = generator.generate(type);
-    Object value2 = generator.generate(type);
-    assertNotNull("Null returned for " + type, value1);
-    assertFalse("Equal instance " + value1 + " returned for " + type, value1.equals(value2));
+    assertFreshInstance(type, 3);
   }
 
-  private static <T> void assertFreshInstance(Class<T> type) {
-    assertFreshInstance(TypeToken.of(type));
+  private static void assertFreshInstance(Class<?> type, int instances) {
+    assertFreshInstance(TypeToken.of(type), instances);
+  }
+
+  private static void assertFreshInstance(TypeToken<?> type, int instances) {
+    FreshValueGenerator generator = new FreshValueGenerator();
+    EqualsTester tester = new EqualsTester();
+    for (int i = 0; i < instances; i++) {
+      tester.addEqualityGroup(generator.generateFresh(type));
+    }
+    tester.testEquals();
   }
 
   private static <T> void assertEqualInstance(Class<T> type, T value) {
     FreshValueGenerator generator = new FreshValueGenerator();
-    assertEquals(value, generator.generate(type));
-    assertEquals(value, generator.generate(type));
+    assertEquals(value, generator.generateFresh(type));
+    assertEquals(value, generator.generateFresh(type));
   }
 
   private enum EmptyEnum {}
@@ -710,24 +471,18 @@ public class FreshValueGeneratorTest extends TestCase {
     CONSTANT1, CONSTANT2
   }
 
-  private static void assertValueAndTypeEquals(Object expected, Object actual) {
-    assertEquals(expected, actual);
-    assertEquals(expected.getClass(), actual.getClass());
+  private static void assertCanGenerateOnly(TypeToken<?> type, Object expected) {
+    FreshValueGenerator generator = new FreshValueGenerator();
+    assertValueAndTypeEquals(expected, generator.generateFresh(type));
+    assertNull(generator.generateFresh(type));
   }
 
   private static void assertNotInstantiable(TypeToken<?> type) {
-    assertNull(new FreshValueGenerator().generate(type));
+    assertNull(new FreshValueGenerator().generateFresh(type));
   }
 
-  private static <E> LinkedHashSet<E> newLinkedHashSet(E element) {
-    LinkedHashSet<E> set = Sets.newLinkedHashSet();
-    set.add(element);
-    return set;
-  }
-
-  private static <E> LinkedList<E> newLinkedList(E element) {
-    LinkedList<E> list = Lists.newLinkedList();
-    list.add(element);
-    return list;
+  private static void assertValueAndTypeEquals(Object expected, Object actual) {
+    assertEquals(expected, actual);
+    assertEquals(expected.getClass(), actual.getClass());
   }
 }
diff --git a/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java b/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
index 117186f..bcf501b 100644
--- a/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
+++ b/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.testing;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.testing.GcFinalization.FinalizationPredicate;
 import com.google.common.util.concurrent.SettableFuture;
 
@@ -118,8 +120,8 @@ public class GcFinalizationTest extends TestCase {
   }
 
   void assertWrapsInterruptedException(RuntimeException e) {
-    assertTrue(e.getMessage().contains("Unexpected interrupt"));
-    assertTrue(e.getCause() instanceof InterruptedException);
+    assertThat(e.getMessage()).contains("Unexpected interrupt");
+    assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
   }
 
   public void testAwait_CountDownLatch_Interrupted() {
diff --git a/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java b/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
index 5b44d7e..8bedfd9 100644
--- a/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
@@ -44,6 +44,7 @@ import junit.framework.TestCase;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
@@ -290,7 +291,7 @@ public class NullPointerTesterTest extends TestCase {
 
     /** To provide sanity during debugging. */
     @Override public String toString() {
-      return String.format("Bar(%s, %s)",
+      return rootLocaleFormat("Bar(%s, %s)",
           actionWhenFirstParamIsNull, actionWhenSecondParamIsNull);
     }
   }
@@ -299,7 +300,7 @@ public class NullPointerTesterTest extends TestCase {
     try {
       new NullPointerTester().testMethod(bar, method);
     } catch (AssertionFailedError incorrectError) {
-      String errorMessage = String.format(
+      String errorMessage = rootLocaleFormat(
           "Should not have flagged method %s for %s", method.getName(), bar);
       assertNull(errorMessage, incorrectError);
     }
@@ -311,7 +312,7 @@ public class NullPointerTesterTest extends TestCase {
     } catch (AssertionFailedError expected) {
       return; // good...we wanted a failure
     }
-    String errorMessage = String.format(
+    String errorMessage = rootLocaleFormat(
         "Should have flagged method %s for %s", method.getName(), bar);
     fail(errorMessage);
   }
@@ -622,7 +623,7 @@ public class NullPointerTesterTest extends TestCase {
   }
 
   @SuppressWarnings("unused") // for NullPointerTester
-  private static abstract class BaseClassThatFailsToThrow {
+  private abstract static class BaseClassThatFailsToThrow {
     public void oneArg(String s) {}
   }
 
@@ -634,7 +635,7 @@ public class NullPointerTesterTest extends TestCase {
   }
 
   @SuppressWarnings("unused") // for NullPointerTester
-  private static abstract class BaseClassThatFailsToThrowForPackagePrivate {
+  private abstract static class BaseClassThatFailsToThrowForPackagePrivate {
     void packagePrivateOneArg(String s) {}
   }
 
@@ -647,7 +648,7 @@ public class NullPointerTesterTest extends TestCase {
   }
 
   @SuppressWarnings("unused") // for NullPointerTester
-  private static abstract class BaseClassThatFailsToThrowForProtected {
+  private abstract static class BaseClassThatFailsToThrowForProtected {
     protected void protectedOneArg(String s) {}
   }
 
@@ -799,7 +800,7 @@ public class NullPointerTesterTest extends TestCase {
     new NullPointerTester().testAllPublicInstanceMethods(new StringFoo());
   }
 
-  private static abstract class DefaultValueChecker {
+  private abstract static class DefaultValueChecker {
 
     private final Map<Integer, Object> arguments = Maps.newHashMap();
 
@@ -901,7 +902,7 @@ public class NullPointerTesterTest extends TestCase {
     void check() {
       runTester();
       Object[] defaultArray = (Object[]) getDefaultParameterValue(0);
-      assertEquals(0, defaultArray.length);
+      assertThat(defaultArray).isEmpty();
     }
   }
 
@@ -920,7 +921,7 @@ public class NullPointerTesterTest extends TestCase {
     void check() {
       runTester();
       String[] defaultArray = (String[]) getDefaultParameterValue(0);
-      assertEquals(0, defaultArray.length);
+      assertThat(defaultArray).isEmpty();
     }
   }
 
@@ -1022,7 +1023,7 @@ public class NullPointerTesterTest extends TestCase {
       runTester();
       TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
       assertTrue(new TypeToken<List<? super Number>>() {}
-          .isAssignableFrom(defaultType));
+          .isSupertypeOf(defaultType));
     }
   }
 
@@ -1141,7 +1142,7 @@ public class NullPointerTesterTest extends TestCase {
     new GenericInterface2DefaultValueChecker().check();
   }
 
-  private static abstract class AbstractGenericDefaultValueChecker<T>
+  private abstract static class AbstractGenericDefaultValueChecker<T>
       extends DefaultValueChecker {
 
     @SuppressWarnings("unused") // called by NullPointerTester
@@ -1162,7 +1163,7 @@ public class NullPointerTesterTest extends TestCase {
     new GenericDefaultValueResolvedToStringChecker().check();
   }
 
-  private static abstract
+  private abstract static
   class AbstractGenericDefaultValueForPackagePrivateMethodChecker<T>
       extends DefaultValueChecker {
 
@@ -1272,4 +1273,8 @@ public class NullPointerTesterTest extends TestCase {
       assertThat(expected.getMessage()).contains("inner class");
     }
   }
+
+  private static String rootLocaleFormat(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava-testlib/test/com/google/common/testing/TearDownStackTest.java b/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
index 7c3aa6e..30c0db8 100644
--- a/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
+++ b/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.testing;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 
 import junit.framework.TestCase;
@@ -83,7 +85,7 @@ public class TearDownStackTest extends TestCase {
       stack.runTearDown();
       fail("runTearDown should have thrown an exception");
     } catch (ClusterException expected) {
-      assertEquals("two", expected.getCause().getMessage());
+      assertThat(expected.getCause()).hasMessage("two");
     } catch (RuntimeException e) {
       throw new RuntimeException(
         "A ClusterException should have been thrown, rather than a " + e.getClass().getName(), e);
diff --git a/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java b/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
index 76e47c7..ec951e7 100644
--- a/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
@@ -65,10 +65,12 @@ public class EnumsBenchmark {
   }
 
   @Benchmark
-  void getIfPresent(int repetitions) {
+  boolean getIfPresent(int repetitions) {
+    boolean retVal = false;
     for (int i = 0; i < repetitions; ++i) {
-      Enums.getIfPresent(enumType, sampleData[i & 255]);
+      retVal &= Enums.getIfPresent(enumType, sampleData[i & 255]).isPresent();
     }
+    return retVal;
   }
 
   private enum SmallEnum {
diff --git a/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java b/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java
new file mode 100644
index 0000000..9b17b58
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java
@@ -0,0 +1,93 @@
+/*
+ * 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.Throwables.lazyStackTrace;
+import static java.util.Arrays.asList;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.SkipThisScenarioException;
+
+import java.util.List;
+
+/**
+ * Quick and dirty benchmark of {@link Throwables#lazyStackTrace(Throwable)}. We benchmark a "caller
+ * finder" implementation that might be used in a logging framework.
+ */
+public class LazyStackTraceBenchmark {
+  @Param({"20", "200", "2000"}) int stackDepth;
+  @Param({"-1", "3", "15"}) int breakAt;
+
+  int recursionCount;
+
+  private static final Object duh = new Object();
+
+  @Param Mode mode;
+
+  enum Mode {
+    LAZY_STACK_TRACE {
+      @Override
+      List<StackTraceElement> getStackTrace(Throwable t) {
+        return lazyStackTrace(t);
+      }
+    },
+    GET_STACK_TRACE {
+      @Override
+      List<StackTraceElement> getStackTrace(Throwable t) {
+        return asList(t.getStackTrace());
+      }
+    };
+
+    boolean timeIt(int reps, int breakAt) {
+      boolean dummy = false;
+      for (int i = 0; i < reps; i++) {
+        int f = 0;
+        Throwable t = new Throwable();
+        for (StackTraceElement ste : getStackTrace(t)) {
+          dummy |= ste == duh;
+          if (f++ == breakAt) {
+            break;
+          }
+        }
+      }
+      return dummy;
+    }
+
+    abstract List<StackTraceElement> getStackTrace(Throwable t);
+  }
+
+  @BeforeExperiment
+  public void doBefore() {
+    recursionCount = stackDepth - new Throwable().getStackTrace().length - 1;
+    if (recursionCount < 0) {
+      throw new SkipThisScenarioException();
+    }
+  }
+
+  @Benchmark
+  public boolean timeFindCaller(int reps) {
+    return timeFindCaller(reps, recursionCount);
+  }
+
+  private boolean timeFindCaller(int reps, int recurse) {
+    return recurse > 0
+        ? timeFindCaller(reps, recurse - 1)
+        : mode.timeIt(reps, breakAt);
+  }
+}
diff --git a/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java b/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java
deleted file mode 100644
index d30f6b4..0000000
--- a/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.caliper.BeforeExperiment;
-import com.google.caliper.Benchmark;
-import com.google.caliper.Param;
-
-import java.util.Random;
-
-/**
- * Benchmark for the {@link Utf8} class.
- *
- *
- * @author Martin Buchholz
- */
-public class Utf8Benchmark {
-
-  static class MaxCodePoint {
-    final int value;
-
-    /**
-     * Convert the input string to a code point.  Accepts regular
-     * decimal numerals, hex strings, and some symbolic names
-     * meaningful to humans.
-     */
-    private static int decode(String userFriendly) {
-      try {
-        return Integer.decode(userFriendly);
-      } catch (NumberFormatException ignored) {
-        if (userFriendly.matches("(?i)(?:American|English|ASCII)")) {
-          // 1-byte UTF-8 sequences - "American" ASCII text
-          return 0x80;
-        } else if (userFriendly.matches("(?i)(?:French|Latin|Western.*European)")) {
-          // Mostly 1-byte UTF-8 sequences, mixed with occasional 2-byte
-          // sequences - "Western European" text
-          return 0x90;
-        } else if (userFriendly.matches("(?i)(?:Branch.*Prediction.*Hostile)")) {
-          // Defeat branch predictor for: c < 0x80 ; branch taken 50% of the time.
-          return 0x100;
-        } else if (userFriendly.matches("(?i)(?:Greek|Cyrillic|European|ISO.?8859)")) {
-          // Mostly 2-byte UTF-8 sequences - "European" text
-          return 0x800;
-        } else if (userFriendly.matches("(?i)(?:Chinese|Han|Asian|BMP)")) {
-          // Mostly 3-byte UTF-8 sequences - "Asian" text
-          return Character.MIN_SUPPLEMENTARY_CODE_POINT;
-        } else if (userFriendly.matches("(?i)(?:Cuneiform|rare|exotic|supplementary.*)")) {
-          // Mostly 4-byte UTF-8 sequences - "rare exotic" text
-          return Character.MAX_CODE_POINT;
-        } else {
-          throw new IllegalArgumentException("Can't decode codepoint " + userFriendly);
-        }
-      }
-    }
-
-    public static MaxCodePoint valueOf(String userFriendly) {
-      return new MaxCodePoint(userFriendly);
-    }
-
-    public MaxCodePoint(String userFriendly) {
-      value = decode(userFriendly);
-    }
-  }
-
-  /**
-   * The default values of maxCodePoint below provide pretty good
-   * performance models of different kinds of common human text.
-   * @see MaxCodePoint#decode
-   */
-  @Param({"0x80", "0x90", "0x100", "0x800", "0x10000", "0x10ffff"}) MaxCodePoint maxCodePoint;
-
-  @Param({"100"}) int stringCount;
-  @Param({"16384"}) int charCount;
-  private CharSequence[] seqs;  // actually, all StringBuilders
-  private String[] strings;
-  private byte[][] byteArrays;
-
-  /**
-   * Compute arrays of valid unicode text, and store it in 3 forms:
-   * byte arrays, Strings, and StringBuilders (in a CharSequence[] to
-   * make it a little harder for the JVM).
-   */
-  @BeforeExperiment void setUp() {
-    final long seed = 99;
-    final Random rnd = new Random(seed);
-    seqs = new CharSequence[stringCount];
-    strings = new String[stringCount];
-    byteArrays = new byte[stringCount][];
-    for (int i = 0; i < stringCount; i++) {
-      StringBuilder sb = new StringBuilder();
-      for (int j = 0; j < charCount; j++) {
-        int codePoint;
-        // discard illegal surrogate "codepoints"
-        do {
-          codePoint = rnd.nextInt(maxCodePoint.value);
-        } while (isSurrogate(codePoint));
-        sb.appendCodePoint(codePoint);
-      }
-      seqs[i] = sb;
-      strings[i] = sb.toString();
-      byteArrays[i] = strings[i].getBytes(Charsets.UTF_8);
-    }
-  }
-
-  /**
-   * Benchmarks {@link Utf8#isWellFormed} on valid byte arrays
-   * containing pseudo-randomly-generated codePoints less than {@code
-   * maxCodePoint}.  A constant seed is used, so separate runs perform
-   * identical computations.
-   */
-  @Benchmark void isWellFormed(int reps) {
-    for (int i = 0; i < reps; i++) {
-      for (byte[] byteArray : byteArrays) {
-        if (!Utf8.isWellFormed(byteArray)) {
-          throw new Error("unexpected invalid UTF-8");
-        }
-      }
-    }
-  }
-
-  /**
-   * Benchmarks {@link Utf8#length} on valid strings containing
-   * pseudo-randomly-generated codePoints less than {@code
-   * maxCodePoint}.  A constant seed is used, so separate runs perform
-   * identical computations.
-   */
-  @Benchmark void lengthOfString(int reps) {
-    for (int i = 0; i < reps; i++) {
-      for (String string : strings) {
-        if (Utf8.encodedLength(string) == 1237482374) {
-          throw new Error("Unlikely! We're just defeating the optimizer!");
-        }
-      }
-    }
-  }
-
-  /**
-   * Benchmarks {@link Utf8#length} on valid StringBuilders containing
-   * pseudo-randomly-generated codePoints less than {@code
-   * maxCodePoint}.  A constant seed is used, so separate runs perform
-   * identical computations.
-   */
-  @Benchmark void lengthOfStringBuilder(int reps) {
-    for (int i = 0; i < reps; i++) {
-      for (CharSequence seq : seqs) {
-        if (Utf8.encodedLength(seq) == 1237482374) {
-          throw new Error("Unlikely! We're just defeating the optimizer!");
-        }
-      }
-    }
-  }
-
-  /** Character.isSurrogate was added in Java SE 7. */
-  private boolean isSurrogate(int c) {
-    return (Character.MIN_HIGH_SURROGATE <= c &&
-            c <= Character.MAX_LOW_SURROGATE);
-  }
-}
diff --git a/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java b/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
index 8a9ed60..f26902c 100644
--- a/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
@@ -20,7 +20,6 @@ import com.google.caliper.BeforeExperiment;
 import com.google.caliper.Benchmark;
 import com.google.caliper.Param;
 import com.google.caliper.runner.CaliperMain;
-import com.google.common.base.CharMatcher.FastMatcher;
 
 import java.util.BitSet;
 import java.util.Random;
@@ -39,7 +38,7 @@ public class WhitespaceMatcherBenchmark {
       + "\u0000\u0000\u0085\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a"
       + "\u0000\u0000\u0000\u0000\u0000\u205f\u1680\u0000\u0000\u180e\u0000\u0000\u0000";
 
-  public static final CharMatcher OLD_WHITESPACE = new FastMatcher("CharMatcher.WHITESPACE") {
+  public static final CharMatcher OLD_WHITESPACE = new CharMatcher() {
     @Override public boolean matches(char c) {
       return OLD_WHITESPACE_TABLE.charAt(c % 79) == c;
     }
diff --git a/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java b/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
index 966e3e6..d5a9bbf 100644
--- a/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
@@ -18,8 +18,6 @@ package com.google.common.cache;
 
 import com.google.caliper.BeforeExperiment;
 import com.google.caliper.Benchmark;
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
 import com.google.common.collect.MapMaker;
 
 import java.util.Map;
@@ -33,15 +31,6 @@ public class MapMakerComparisonBenchmark {
   private static final String TEST_KEY = "test key";
   private static final String TEST_VALUE = "test value";
 
-  private static final Function<Object, Object> IDENTITY = Functions.identity();
-
-  // Loading/computing versions:
-  private final Map<Object, Object> computingMap = new MapMaker().makeComputingMap(IDENTITY);
-  private final LoadingCache<Object, Object> loadingCache =
-      CacheBuilder.newBuilder().recordStats().build(CacheLoader.from(IDENTITY));
-  private final LoadingCache<Object, Object> loadingCacheNoStats =
-      CacheBuilder.newBuilder().build(CacheLoader.from(IDENTITY));
-
   // Non-loading versions:
   private final Map<Object, Object> map = new MapMaker().makeMap(); // Returns ConcurrentHashMap
   private final Cache<Object, Object> cache = CacheBuilder.newBuilder().recordStats().build();
@@ -54,24 +43,6 @@ public class MapMakerComparisonBenchmark {
     cacheNoStats.put(TEST_KEY, TEST_VALUE);
   }
 
-  @Benchmark void computingMapMaker(int rep) {
-    for (int i = 0; i < rep; i++) {
-      computingMap.get(TEST_KEY);
-    }
-  }
-
-  @Benchmark void loadingCacheBuilder_stats(int rep) {
-    for (int i = 0; i < rep; i++) {
-      loadingCache.getUnchecked(TEST_KEY);
-    }
-  }
-
-  @Benchmark void loadingCacheBuilder(int rep) {
-    for (int i = 0; i < rep; i++) {
-      loadingCacheNoStats.getUnchecked(TEST_KEY);
-    }
-  }
-
   @Benchmark void concurrentHashMap(int rep) {
     for (int i = 0; i < rep; i++) {
       map.get(TEST_KEY);
diff --git a/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java b/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java
new file mode 100644
index 0000000..c0063ad
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 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.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.SkipThisScenarioException;
+
+import java.util.Random;
+
+/**
+ * A benchmark that tries invoking {@code Set.contains} on many different sets.
+ */
+public class MultipleSetContainsBenchmark {
+  
+  @Param({"0.0", "0.1", "0.7", "1.0"})
+  double emptySetProportion;
+  
+  @Param({"0.0", "0.1", "0.7", "1.0"})
+  double singletonSetProportion;
+  
+  @Param({"0.2", "0.8"})
+  double hitRate;
+  
+  static final Object PRESENT = new Object();
+  static final Object ABSENT = new Object();
+  
+  @SuppressWarnings("unchecked")
+  private final ImmutableSet<Object>[] sets = new ImmutableSet[0x1000];
+  
+  private final Object[] queries = new Object[0x1000];
+  
+  @BeforeExperiment void setUp() {
+    if (emptySetProportion + singletonSetProportion > 1.01) {
+      throw new SkipThisScenarioException();
+    }
+    
+    Random rng = new Random();
+    for (int i = 0; i < 0x1000; i++) {
+      double setSize = rng.nextDouble();
+      if (setSize < emptySetProportion) {
+        sets[i] = ImmutableSet.of();
+      } else if (setSize < emptySetProportion + singletonSetProportion) {
+        sets[i] = ImmutableSet.of(PRESENT);
+      } else {
+        sets[i] = ImmutableSet.of(PRESENT, new Object());
+      }
+      
+      if (rng.nextDouble() < hitRate) {
+        queries[i] = PRESENT;
+      } else {
+        queries[i] = ABSENT;
+      }
+    }
+  }
+  
+  @Benchmark public boolean contains(int reps) {
+    ImmutableSet<Object>[] sets = this.sets;
+    Object[] queries = this.queries;
+    boolean result = false;
+    for (int i = 0; i < reps; i++) {
+      int j = i & 0xFFF;
+      result ^= sets[j].contains(queries[j]);
+    }
+    return result;
+  }
+
+}
diff --git a/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java b/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
index b8e5d73..28d75fa 100644
--- a/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
@@ -59,7 +59,7 @@ public class ChecksumBenchmark {
     for (int i = 0; i < reps; i++) {
       CRC32 checksum = new CRC32();
       checksum.update(testBytes);
-      result ^= checksum.getValue();
+      result = (byte) (result ^ checksum.getValue());
     }
     return result;
   }
@@ -75,7 +75,7 @@ public class ChecksumBenchmark {
     for (int i = 0; i < reps; i++) {
       Adler32 checksum = new Adler32();
       checksum.update(testBytes);
-      result ^= checksum.getValue();
+      result = (byte) (result ^ checksum.getValue());
     }
     return result;
   }
diff --git a/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java b/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java
new file mode 100644
index 0000000..78fd17c
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 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.hash;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Benchmarks for comparing the various {@link HashCode#equals} methods.
+ *
+ * <p>Parameters for the benchmark are:
+ * <ul>
+ * <li>size: the length of the byte array to hash
+ * <li>whereToDiffer: where in the array the bytes should differ
+ * <li>equalsImpl: which implementation of array equality to use
+ * </ul>
+ *
+ * <p><b>Important note:</b> the primary goal of this benchmark is to ensure that varying {@code
+ * whereToDiffer} produces no observable change in performance. We want to make sure that the
+ * array equals implementation is *not* short-circuiting to prevent timing-based attacks. Being
+ * fast is only a secondary goal.
+ *
+ * @author Kurt Alfred Kluever
+ */
+public class HashCodeBenchmark {
+
+  // Use a statically configured random instance for all of the benchmarks
+  private static final Random random = new Random(42);
+
+  @Param({"1000", "100000"})
+  private int size;
+
+  @Param WhereToDiffer whereToDiffer;
+
+  @Param EqualsImplementation equalsImpl;
+
+  private enum WhereToDiffer {
+    ONE_PERCENT_IN,
+    LAST_BYTE,
+    NOT_AT_ALL;
+  }
+
+  private enum EqualsImplementation {
+    ANDING_BOOLEANS {
+      @Override boolean doEquals(byte[] a, byte[] b) {
+        if (a.length != b.length) {
+          return false;
+        }
+        boolean areEqual = true;
+        for (int i = 0; i < a.length; i++) {
+          areEqual &= (a[i] == b[i]);
+        }
+        return areEqual;
+      }
+    },
+    XORING_TO_BYTE {
+      @Override boolean doEquals(byte[] a, byte[] b) {
+        if (a.length != b.length) {
+          return false;
+        }
+        byte result = 0;
+        for (int i = 0; i < a.length; i++) {
+          result = (byte) (result | a[i] ^ b[i]);
+        }
+        return (result == 0);
+      }
+    },
+    XORING_TO_INT {
+      @Override boolean doEquals(byte[] a, byte[] b) {
+        if (a.length != b.length) {
+          return false;
+        }
+        int result = 0;
+        for (int i = 0; i < a.length; i++) {
+          result |= a[i] ^ b[i];
+        }
+        return (result == 0);
+      }
+    },
+    MESSAGE_DIGEST_IS_EQUAL {
+      @Override boolean doEquals(byte[] a, byte[] b) {
+        return MessageDigest.isEqual(a, b);
+      }
+    },
+    ARRAYS_EQUALS {
+      @Override boolean doEquals(byte[] a, byte[] b) {
+        return Arrays.equals(a, b);
+      }
+    };
+
+    abstract boolean doEquals(byte[] a, byte[] b);
+  }
+
+  private byte[] testBytesA;
+  private byte[] testBytesB;
+
+  @BeforeExperiment void setUp() {
+    testBytesA = new byte[size];
+    random.nextBytes(testBytesA);
+    testBytesB = Arrays.copyOf(testBytesA, size);
+    int indexToDifferAt = -1;
+    switch (whereToDiffer) {
+      case ONE_PERCENT_IN:
+        indexToDifferAt = (int) (size * 0.01);
+        break;
+      case LAST_BYTE:
+        indexToDifferAt = size - 1;
+        break;
+      case NOT_AT_ALL:
+    }
+    if (indexToDifferAt != -1) {
+      testBytesA[indexToDifferAt] = (byte) (testBytesB[indexToDifferAt] - 1);
+    }
+  }
+
+  @Benchmark boolean hashFunction(int reps) {
+    boolean result = true;
+    for (int i = 0; i < reps; i++) {
+      result ^= equalsImpl.doEquals(testBytesA, testBytesB);
+    }
+    return result;
+  }
+}
diff --git a/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java b/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
index faeaee6..dbabd33 100644
--- a/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
@@ -19,7 +19,6 @@ package com.google.common.hash;
 import com.google.caliper.BeforeExperiment;
 import com.google.caliper.Benchmark;
 import com.google.caliper.Param;
-import com.google.common.hash.HashFunction;
 
 import java.util.Random;
 
@@ -59,4 +58,13 @@ public class HashFunctionBenchmark {
     }
     return result;
   }
+
+  @Benchmark int hashFunctionWithOffset(int reps) {
+    HashFunction hashFunction = hashFunctionEnum.getHashFunction();
+    int result = 37;
+    for (int i = 0; i < reps; i++) {
+      result ^= hashFunction.hashBytes(testBytes, 1, testBytes.length - 1).asBytes()[0];
+    }
+    return result;
+  }
 }
diff --git a/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java b/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
index e45d582..ff80e96 100644
--- a/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
@@ -64,6 +64,7 @@ public class MessageDigestAlgorithmBenchmark {
     MD5("MD5", Hashing.md5()),
     SHA_1("SHA-1", Hashing.sha1()),
     SHA_256("SHA-256", Hashing.sha256()),
+    SHA_384("SHA-384", Hashing.sha384()),
     SHA_512("SHA-512", Hashing.sha512());
 
     private final String algorithmName;
diff --git a/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java b/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
index a35b424..22d6d85 100644
--- a/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
@@ -29,7 +29,7 @@ import java.security.MessageDigest;
  */
 public class MessageDigestCreationBenchmark {
 
-  @Param({"MD5", "SHA-1", "SHA-256", "SHA-512"})
+  @Param({"MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"})
   private String algorithm;
 
   private MessageDigest md;
diff --git a/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java b/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java
new file mode 100644
index 0000000..5131676
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 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.io;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Random;
+
+/**
+ * Benchmark for {@code BaseEncoding} performance.
+ */
+public class BaseEncodingBenchmark {
+  private static final int INPUTS_COUNT = 0x1000;
+  private static final int INPUTS_MASK = 0xFFF;
+
+  enum EncodingOption {
+    BASE64(BaseEncoding.base64()),
+    BASE64_URL(BaseEncoding.base64Url()),
+    BASE32(BaseEncoding.base32()),
+    BASE32_HEX(BaseEncoding.base32Hex()),
+    BASE16(BaseEncoding.base16());
+    
+    final BaseEncoding encoding;
+    
+    EncodingOption(BaseEncoding encoding) {
+      this.encoding = encoding;
+    }
+  }
+  
+  @Param
+  EncodingOption encoding;
+  
+  @Param({"10", "100", "10000"})
+  int n;
+  
+  private final byte[][] encodingInputs = new byte[INPUTS_COUNT][];
+  private final String[] decodingInputs = new String[INPUTS_COUNT];
+
+  @BeforeExperiment
+  public void setUp() {
+    Random rng = new Random();
+    for (int i = 0; i < encodingInputs.length; i++) {
+      encodingInputs[i] = new byte[n];
+      rng.nextBytes(encodingInputs[i]);
+      decodingInputs[i] = encoding.encoding.encode(encodingInputs[i]);
+    }
+  }
+  
+  @Benchmark public int encode(int reps) {
+    int tmp = 0;
+    for (int i = 0; i < reps; i++) {
+      tmp += System.identityHashCode(encoding.encoding.encode(encodingInputs[i & INPUTS_MASK]));
+    }
+    return tmp;
+  }
+
+  @Benchmark public int decode(int reps) {
+    int tmp = 0;
+    for (int i = 0; i < reps; i++) {
+      tmp += System.identityHashCode(encoding.encoding.decode(decodingInputs[i & INPUTS_MASK]));
+    }
+    return tmp;
+  }
+
+  @Benchmark public int encodingStream(int reps) throws IOException {
+    int tmp = 0;
+    for (int i = 0; i < reps; i++) {
+      StringWriter target = new StringWriter(2 * n);
+      OutputStream encodingStream = encoding.encoding.encodingStream(target);
+      encodingStream.write(encodingInputs[i & INPUTS_MASK]);
+      encodingStream.close();
+      tmp += target.getBuffer().length();
+    }
+    return tmp;
+  }
+
+  @Benchmark public int decodingStream(int reps) throws IOException {
+    int tmp = 0;
+    byte[] target = new byte[n];
+    for (int i = 0; i < reps; i++) {
+      StringReader source = new StringReader(decodingInputs[i & INPUTS_MASK]);
+      InputStream decodingStream = encoding.encoding.decodingStream(source);
+      decodingStream.read(target);
+      decodingStream.close();
+      tmp += target[0];
+    }
+    return tmp;
+  }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java
new file mode 100644
index 0000000..3c9fac5
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Param;
+import com.google.caliper.api.Footprint;
+import com.google.caliper.api.SkipThisScenarioException;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Facade;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Impl;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/**
+ * Measures the size of AbstractFuture implementations.
+ */
+public class AbstractFutureFootprintBenchmark {
+
+  enum State { NOT_DONE, FINISHED, CANCELLED, FAILED}
+
+  @Param State state;
+  @Param Impl impl;
+  @Param({"0", "1", "5", "10"}) int numListeners;
+  @Param({"0", "1", "5", "10"}) int numThreads;
+
+  private final Set<Thread> blockedThreads = new HashSet<Thread>();
+
+  @BeforeExperiment void setUp() throws Exception {
+    if (state != State.NOT_DONE && (numListeners != 0 || numThreads != 0)) {
+      throw new SkipThisScenarioException();
+    }
+  }
+
+  // This exclusion doesn't exclude the TOMBSTONE objects we set. So 'done' NEW futures will look
+  // larger than they are.
+  @Footprint(exclude = {Runnable.class, Executor.class, Thread.class, Exception.class})
+  public Object measureSize() {
+    for (Thread thread : blockedThreads) {
+      thread.interrupt();
+    }
+    blockedThreads.clear();
+    final Facade<Object> f = impl.newFacade();
+    for (int i = 0; i < numThreads; i++) {
+      Thread thread = new Thread() {
+        @Override public void run() {
+          try {
+            f.get();
+          } catch (Throwable expected) {}
+        }
+      };
+      thread.start();
+      blockedThreads.add(thread);
+    }
+    for (int i = 0; i < numListeners; i++) {
+      f.addListener(Runnables.doNothing(), directExecutor());
+    }
+    for (Thread thread : blockedThreads) {
+      AbstractFutureBenchmarks.awaitWaiting(thread);
+    }
+    switch (state) {
+      case NOT_DONE:
+        break;
+      case FINISHED:
+        f.set(null);
+        break;
+      case CANCELLED:
+        f.cancel(false);
+        break;
+      case FAILED:
+        f.setException(new Exception());
+        break;
+      default:
+        throw new AssertionError();
+    }
+    return f;
+  }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
index 4e86043..9cfc814 100644
--- a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
@@ -26,12 +26,12 @@ import com.google.caliper.api.Footprint;
 import com.google.caliper.api.VmOptions;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture;
 
 import java.util.Queue;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -44,7 +44,7 @@ import javax.annotation.concurrent.GuardedBy;
 /**
  * Benchmarks for {@link ExecutionList}.
  */
- at VmOptions({"-Xms3g", "-Xmx3g"})
+ at VmOptions({"-Xms8g", "-Xmx8g"})
 public class ExecutionListBenchmark {
   private static final int NUM_THREADS = 10;  // make a param?
 
@@ -55,7 +55,7 @@ public class ExecutionListBenchmark {
     /** Returns the underlying implementation, useful for the Footprint benchmark. */
     Object getImpl();
   }
-
+  
   enum Impl {
     NEW {
       @Override ExecutionListWrapper newExecutionList() {
@@ -68,7 +68,7 @@ public class ExecutionListBenchmark {
           @Override public void execute() {
             list.execute();
           }
-
+          
           @Override public Object getImpl() {
             return list;
           }
@@ -86,7 +86,7 @@ public class ExecutionListBenchmark {
           @Override public void execute() {
             list.execute();
           }
-
+          
           @Override public Object getImpl() {
             return list;
           }
@@ -104,7 +104,7 @@ public class ExecutionListBenchmark {
           @Override public void execute() {
             list.execute();
           }
-
+          
           @Override public Object getImpl() {
             return list;
           }
@@ -122,7 +122,7 @@ public class ExecutionListBenchmark {
           @Override public void execute() {
             list.execute();
           }
-
+          
           @Override public Object getImpl() {
             return list;
           }
@@ -140,49 +140,87 @@ public class ExecutionListBenchmark {
           @Override public void execute() {
             list.execute();
           }
-
+          
           @Override public Object getImpl() {
             return list;
           }
         };
       }
+    },
+    ABSTRACT_FUTURE {
+      @Override ExecutionListWrapper newExecutionList() {
+        return new ExecutionListWrapper() {
+          final AbstractFuture<?> future = new AbstractFuture<Object>() {};
+          @Override public void add(Runnable runnable, Executor executor) {
+            future.addListener(runnable, executor);
+          }
+
+          @Override public void execute() {
+            future.set(null);
+          }
+
+          @Override public Object getImpl() {
+            return future;
+          }
+        };
+      }
+    },
+    OLD_ABSTRACT_FUTURE {
+      @Override ExecutionListWrapper newExecutionList() {
+        return new ExecutionListWrapper() {
+          final OldAbstractFuture<Object> future = new OldAbstractFuture<Object>() {};
+          @Override public void add(Runnable runnable, Executor executor) {
+            future.addListener(runnable, executor);
+          }
+
+          @Override public void execute() {
+            future.set(null);
+          }
+
+          @Override public Object getImpl() {
+            return future;
+          }
+        };
+      }
     };
     abstract ExecutionListWrapper newExecutionList();
   }
-
-  private ExecutorService executorService;
+  
+  private ThreadPoolExecutor executorService;
   private CountDownLatch listenerLatch;
   private ExecutionListWrapper list;
-
+  
   @Param Impl impl;
   @Param({"1", "5", "10"}) int numListeners;
-
+  
   private final Runnable listener = new Runnable() {
     @Override public void run() {
       listenerLatch.countDown();
     }
   };
-
+  
   @BeforeExperiment void setUp() throws Exception {
-    executorService = new ThreadPoolExecutor(NUM_THREADS,
-        NUM_THREADS,
-        Long.MAX_VALUE,
-        TimeUnit.SECONDS,
+    executorService = new ThreadPoolExecutor(NUM_THREADS, 
+        NUM_THREADS, 
+        Long.MAX_VALUE, 
+        TimeUnit.SECONDS, 
         new ArrayBlockingQueue<Runnable>(1000));
+    executorService.prestartAllCoreThreads();
     final AtomicInteger integer = new AtomicInteger();
-    // Execute a bunch of tasks to ensure that our threads are allocated and hot
+    // Execute a bunch of tasks to ensure that our threads are allocated and hot 
     for (int i = 0; i < NUM_THREADS * 10; i++) {
       executorService.submit(new Runnable() {
         @Override public void run() {
           integer.getAndIncrement();
-        }});
+        }
+      });
     }
   }
-
+  
   @AfterExperiment void tearDown() throws Exception {
     executorService.shutdown();
   }
-
+  
   @Footprint(exclude = {Runnable.class, Executor.class})
   public Object measureSize() {
     list = impl.newExecutionList();
@@ -191,7 +229,7 @@ public class ExecutionListBenchmark {
     }
     return list.getImpl();
   }
-
+  
   @Benchmark int addThenExecute_singleThreaded(int reps) {
     int returnValue = 0;
     for (int i = 0; i < reps; i++) {
@@ -206,7 +244,7 @@ public class ExecutionListBenchmark {
     }
     return returnValue;
   }
-
+  
   @Benchmark int executeThenAdd_singleThreaded(int reps) {
     int returnValue = 0;
     for (int i = 0; i < reps; i++) {
@@ -221,13 +259,13 @@ public class ExecutionListBenchmark {
     }
     return returnValue;
   }
-
+  
   private final Runnable executeTask = new Runnable() {
     @Override public void run() {
       list.execute();
     }
   };
-
+  
   @Benchmark int addThenExecute_multiThreaded(final int reps) throws InterruptedException {
     Runnable addTask = new Runnable() {
       @Override public void run() {
@@ -244,12 +282,12 @@ public class ExecutionListBenchmark {
         executorService.submit(addTask);
       }
       executorService.submit(executeTask);
-      returnValue = (int) listenerLatch.getCount();
+      returnValue += (int) listenerLatch.getCount();
       listenerLatch.await();
     }
     return returnValue;
   }
-
+  
   @Benchmark int executeThenAdd_multiThreaded(final int reps) throws InterruptedException {
     Runnable addTask = new Runnable() {
       @Override public void run() {
@@ -266,12 +304,12 @@ public class ExecutionListBenchmark {
       for (int j = 0; j < NUM_THREADS; j++) {
         executorService.submit(addTask);
       }
-      returnValue = (int) listenerLatch.getCount();
+      returnValue += (int) listenerLatch.getCount();
       listenerLatch.await();
     }
     return returnValue;
   }
-
+  
   // This is the old implementation of ExecutionList using a LinkedList.
   private static final class OldExecutionList {
     static final Logger log = Logger.getLogger(OldExecutionList.class.getName());
@@ -389,7 +427,7 @@ public class ExecutionListBenchmark {
       }
     }
   }
-
+  
   // A version of the ExecutionList that uses an explicit tail pointer to keep the nodes in order
   // rather than flipping the stack in execute().
   private static final class NewExecutionListQueue {
@@ -459,14 +497,14 @@ public class ExecutionListBenchmark {
       }
     }
   }
-
+  
   // A version of the list that uses compare and swap to manage the stack without locks.
   private static final class ExecutionListCAS {
     static final Logger log = Logger.getLogger(ExecutionListCAS.class.getName());
 
     private static final sun.misc.Unsafe UNSAFE;
     private static final long HEAD_OFFSET;
-
+    
     /**
      * A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the
      * bottom of the stack.
@@ -477,13 +515,13 @@ public class ExecutionListBenchmark {
       try {
         UNSAFE = getUnsafe();
         HEAD_OFFSET = UNSAFE.objectFieldOffset(ExecutionListCAS.class.getDeclaredField("head"));
-      } catch (Exception ex) {
-        throw new Error(ex);
+      } catch (Exception ex) { 
+        throw new Error(ex); 
       }
     }
-
+    
     /**
-     * TODO(user):  This was copied verbatim from Striped64.java... standardize this?
+     * TODO(lukes):  This was copied verbatim from Striped64.java... standardize this?
      */
     private static sun.misc.Unsafe getUnsafe() {
         try {
@@ -512,13 +550,13 @@ public class ExecutionListBenchmark {
     public void add(Runnable runnable, Executor executor) {
       Preconditions.checkNotNull(runnable, "Runnable was null.");
       Preconditions.checkNotNull(executor, "Executor was null.");
-
+      
       RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor);
       RunnableExecutorPair oldHead;
       do {
         oldHead = head;
         if (oldHead == null) {
-          // If runnables == null then execute() has been called so we should just execute our
+          // If runnables == null then execute() has been called so we should just execute our 
           // listener immediately.
           newHead.execute();
           return;
@@ -538,7 +576,7 @@ public class ExecutionListBenchmark {
         }
         // try to swap null into head.
       } while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null));
-
+      
       RunnableExecutorPair reversedStack = null;
       while (stack != NULL_PAIR) {
         RunnableExecutorPair head = stack;
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java
deleted file mode 100644
index 60b5e5c..0000000
--- a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2014 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.util.concurrent;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.caliper.Benchmark;
-import com.google.caliper.Param;
-import com.google.caliper.api.VmOptions;
-import com.google.common.collect.ImmutableList;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-
-/**
- * A benchmark for {@link Futures#combine}
- */
- at VmOptions({"-Xms12g", "-Xmx12g", "-d64"})
-public class FuturesCombineBenchmark {
-
-  enum Impl {
-    OLD {
-      @Override <V> ListenableFuture<V> combine(final Callable<V> combiner, Executor executor,
-          Iterable<? extends ListenableFuture<?>> futures) {
-        ListenableFuture<?> trigger = Futures.successfulAsList(futures);
-        checkNotNull(combiner);
-        checkNotNull(trigger);
-        return Futures.transform(trigger, new AsyncFunction<Object, V>() {
-          @Override public ListenableFuture<V> apply(Object arg) throws Exception {
-            try {
-              return Futures.immediateFuture(combiner.call());
-            } catch (CancellationException e) {
-              return Futures.immediateCancelledFuture();
-            } catch (ExecutionException e) {
-              return Futures.immediateFailedFuture(e.getCause()); // OK to rethrow on Error
-            }
-          }
-        }, executor);
-      }
-    },
-    NEW {
-      @Override
-      <V> ListenableFuture<V> combine(Callable<V> combiner, final Executor executor,
-          Iterable<? extends ListenableFuture<?>> futures) {
-        return Futures.combine(combiner, executor, futures);
-      }
-    };
-
-    abstract <V> ListenableFuture<V> combine(
-        Callable<V> combiner, Executor executor,
-        Iterable<? extends ListenableFuture<?>> futures);
-  }
-
-  private static final Executor INLINE_EXECUTOR = new Executor() {
-    @Override public void execute(Runnable command) {
-      command.run();
-    }
-  };
-
-  @Param Impl impl;
-  @Param({"1", "5", "10"}) int numInputs;
-
-  @Benchmark int timeDoneSuccesfulFutures(int reps) throws Exception {
-    ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder();
-    for (int i = 0; i < numInputs; i++) {
-      futuresBuilder.add(Futures.immediateFuture(i));
-    }
-    ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build();
-    Impl impl = this.impl;
-    Callable<Integer> callable = Callables.returning(12);
-    int sum = 0;
-    for (int i = 0; i < reps; i++) {
-      sum += impl.combine(callable, INLINE_EXECUTOR, futures).get();
-    }
-    return sum;
-  }
-  
-  @Benchmark int timeDoneFailedFutures(int reps) throws Exception {
-    ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder();
-    for (int i = 0; i < numInputs; i++) {
-      futuresBuilder.add(Futures.immediateFailedFuture(new Exception("boom")));
-    }
-    ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build();
-    Impl impl = this.impl;
-    Callable<Integer> callable = Callables.returning(12);
-    int sum = 0;
-    for (int i = 0; i < reps; i++) {
-      sum += impl.combine(callable, INLINE_EXECUTOR, futures).get();
-    }
-    return sum;
-  }
-  
-  @Benchmark int timeSuccesfulFutures(int reps) throws Exception {
-    Impl impl = this.impl;
-    Callable<Integer> callable = Callables.returning(12);
-    int sum = 0;
-    for (int i = 0; i < reps; i++) {
-      ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList();
-      ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures);
-      for (SettableFuture<Integer> future : futures) {
-        future.set(i);
-      }
-      sum += combined.get();
-    }
-    return sum;
-  }
-
-  @Benchmark int timeFailedFutures(int reps) throws Exception {
-    Impl impl = this.impl;
-    Callable<Integer> callable = Callables.returning(12);
-    int sum = 0;
-    Exception throwable = new Exception("boom");
-    for (int i = 0; i < reps; i++) {
-      ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList();
-      ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures);
-      for (SettableFuture<Integer> future : futures) {
-        future.setException(throwable);
-      }
-      sum += combined.get();
-    }
-    return sum;
-  }
-
-  private ImmutableList<SettableFuture<Integer>> getSettableFutureList() {
-    ImmutableList.Builder<SettableFuture<Integer>> futuresBuilder = ImmutableList.builder();
-    for (int i = 0; i < numInputs; i++) {
-      futuresBuilder.add(SettableFuture.<Integer>create());
-    }
-    return futuresBuilder.build();
-  }
-}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java
new file mode 100644
index 0000000..7a7bd21
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetChecked.checkExceptionClassValidity;
+import static com.google.common.util.concurrent.FuturesGetChecked.classValueValidator;
+import static com.google.common.util.concurrent.FuturesGetChecked.getChecked;
+import static com.google.common.util.concurrent.FuturesGetChecked.isCheckedException;
+import static com.google.common.util.concurrent.FuturesGetChecked.weakSetValidator;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.FuturesGetChecked.GetCheckedTypeValidator;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.security.GeneralSecurityException;
+import java.security.acl.NotOwnerException;
+import java.util.List;
+import java.util.TooManyListenersException;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.InvalidPreferencesFormatException;
+import java.util.zip.DataFormatException;
+
+import javax.security.auth.RefreshFailedException;
+
+/**
+ * Microbenchmark for {@link Futures#getChecked}.
+ */
+public class FuturesGetCheckedBenchmark {
+  private enum Validator {
+    NON_CACHING_WITH_CONSTRUCTOR_CHECK(nonCachingWithConstructorCheckValidator()),
+    NON_CACHING_WITHOUT_CONSTRUCTOR_CHECK(nonCachingWithoutConstructorCheckValidator()),
+    WEAK_SET(weakSetValidator()),
+    CLASS_VALUE(classValueValidator());
+
+    final GetCheckedTypeValidator validator;
+
+    private Validator(GetCheckedTypeValidator validator) {
+      this.validator = validator;
+    }
+  }
+
+  private enum Result {
+    SUCCESS(immediateFuture(new Object())),
+    FAILURE(immediateFailedFuture(new Exception()));
+
+    final Future<Object> future;
+
+    private Result(Future<Object> result) {
+      this.future = result;
+    }
+  }
+
+  private enum ExceptionType {
+    CHECKED(IOException.class),
+    UNCHECKED(RuntimeException.class);
+
+    final Class<? extends Exception> exceptionType;
+
+    private ExceptionType(Class<? extends Exception> exceptionType) {
+      this.exceptionType = exceptionType;
+    }
+  }
+
+  private static final ImmutableSet<Class<? extends Exception>> OTHER_EXCEPTION_TYPES =
+      ImmutableSet.of(
+          BackingStoreException.class,
+          BrokenBarrierException.class,
+          CloneNotSupportedException.class,
+          DataFormatException.class,
+          ExecutionException.class,
+          GeneralSecurityException.class,
+          InvalidPreferencesFormatException.class,
+          NotOwnerException.class,
+          RefreshFailedException.class,
+          TimeoutException.class,
+          TooManyListenersException.class,
+          URISyntaxException.class);
+
+  @Param
+  Validator validator;
+  @Param
+  Result result;
+  @Param
+  ExceptionType exceptionType;
+  /**
+   * The number of other exception types in the cache of known-good exceptions and the number of
+   * other {@code ClassValue} entries for the exception type to be tested. This lets us evaluate
+   * whether our solution scales to use with multiple exception types and to whether it is affected
+   * by other {@code ClassValue} users. Some of the benchmarked implementations don't use one or
+   * both of these mechanisms, so they will be unaffected.
+   */
+  @Param({"0", "1", "12"})
+  int otherEntriesInDataStructure;
+
+  final List<ClassValue<?>> retainedReferencesToOtherClassValues = newArrayList();
+
+  @BeforeExperiment
+  void addOtherEntries() throws Exception {
+    GetCheckedTypeValidator validator = this.validator.validator;
+    Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
+
+    for (Class<? extends Exception> exceptionClass :
+          OTHER_EXCEPTION_TYPES.asList().subList(0, otherEntriesInDataStructure)) {
+      getChecked(validator, immediateFuture(""), exceptionClass);
+    }
+
+    for (int i = 0; i < otherEntriesInDataStructure; i++) {
+      ClassValue<Boolean> classValue = 
+          new ClassValue<Boolean>() {
+            @Override
+            protected Boolean computeValue(Class<?> type) {
+              return true;
+            }
+          };
+      classValue.get(exceptionType);
+      retainedReferencesToOtherClassValues.add(classValue);
+    }
+  }
+
+  @Benchmark
+  int benchmarkGetChecked(int reps) {
+    int tmp = 0;
+    GetCheckedTypeValidator validator = this.validator.validator;
+    Future<Object> future = this.result.future;
+    Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
+    for (int i = 0; i < reps; ++i) {
+      try {
+        tmp += getChecked(validator, future, exceptionType).hashCode();
+      } catch (Exception e) {
+        tmp += e.hashCode();
+      }
+    }
+    return tmp;
+  }
+
+  private static GetCheckedTypeValidator nonCachingWithoutConstructorCheckValidator() {
+    return NonCachingWithoutConstructorCheckValidator.INSTANCE;
+  }
+
+  private enum NonCachingWithoutConstructorCheckValidator implements GetCheckedTypeValidator {
+    INSTANCE;
+
+    @Override
+    public void validateClass(Class<? extends Exception> exceptionClass) {
+      checkArgument(isCheckedException(exceptionClass),
+          "Futures.getChecked exception type (%s) must not be a RuntimeException", exceptionClass);
+    }
+  }
+
+  private static GetCheckedTypeValidator nonCachingWithConstructorCheckValidator() {
+    return NonCachingWithConstructorCheckValidator.INSTANCE;
+  }
+
+  private enum NonCachingWithConstructorCheckValidator implements GetCheckedTypeValidator {
+    INSTANCE;
+
+    @Override
+    public void validateClass(Class<? extends Exception> exceptionClass) {
+      checkExceptionClassValidity(exceptionClass);
+    }
+  }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java
new file mode 100644
index 0000000..2357b9d
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.VmOptions;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Facade;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A benchmark that times how long it takes to add a given number of 
+ */
+ at VmOptions({"-Xms8g", "-Xmx8g"})
+public class SingleThreadAbstractFutureBenchmark {
+  @Param Impl impl;
+
+  private final Exception exception = new Exception();
+  private Facade<?> notDoneFuture;
+
+  @BeforeExperiment void setUp() throws Exception {
+    notDoneFuture = impl.newFacade();
+  }
+
+  @Benchmark public long timeComplete_Normal(int reps) throws Exception {
+    long r = 0;
+    List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+    for (int i = 0; i < reps; i++) {
+      final Facade<Integer> localFuture = impl.newFacade();
+      list.add(localFuture);
+      localFuture.set(i);
+    }
+    for (int i = 0; i < reps; i++) {
+      r += list.get(i).get();
+    }
+    return r;
+  }
+
+  @Benchmark public long timeComplete_Failure(int reps) throws Exception {
+    long r = 0;
+    List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+    for (int i = 0; i < reps; i++) {
+      final Facade<Integer> localFuture = impl.newFacade();
+      list.add(localFuture);
+      localFuture.setException(exception);
+    }
+    for (int i = 0; i < reps; i++) {
+      Facade<Integer> facade = list.get(i);
+      try {
+        facade.get();
+        r++;
+      } catch (ExecutionException e) {
+        r += 2;
+      }
+    }
+    return r;
+  }
+
+  @Benchmark public long timeComplete_Cancel(int reps) throws Exception {
+    long r = 0;
+    List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+    for (int i = 0; i < reps; i++) {
+      final Facade<Integer> localFuture = impl.newFacade();
+      list.add(localFuture);
+      localFuture.cancel(false);
+    }
+    for (int i = 0; i < reps; i++) {
+      Facade<Integer> facade = list.get(i);
+      try {
+        facade.get();
+        r++;
+      } catch (CancellationException e) {
+        r += 2;
+      }
+    }
+    return r;
+  }
+
+  @Benchmark public long timeGetWith0Timeout(long reps) throws Exception {
+    Facade<?> f = notDoneFuture;
+    long r = 0;
+    for (int i = 0; i < reps; i++) {
+      try {
+        f.get(0, TimeUnit.SECONDS);
+        r += 1;
+      } catch (TimeoutException e) {
+        r += 2;
+      }
+    }
+    return r;
+  }
+  @Benchmark public long timeGetWithSmallTimeout(long reps) throws Exception {
+    Facade<?> f = notDoneFuture;
+    long r = 0;
+    for (int i = 0; i < reps; i++) {
+      try {
+        f.get(500, TimeUnit.NANOSECONDS);
+        r += 1;
+      } catch (TimeoutException e) {
+        r += 2;
+      }
+    }
+    return r;
+  }
+}
diff --git a/guava-tests/pom.xml b/guava-tests/pom.xml
index ea1e303..dcb6351 100644
--- a/guava-tests/pom.xml
+++ b/guava-tests/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>com.google.guava</groupId>
     <artifactId>guava-parent</artifactId>
-    <version>18.0</version>
+    <version>19.0</version>
   </parent>
   <artifactId>guava-tests</artifactId>
   <name>Guava Unit Tests</name>
@@ -26,6 +26,10 @@
       <artifactId>jsr305</artifactId>
     </dependency>
     <dependency>
+      <groupId>com.google.errorprone</groupId>
+      <artifactId>error_prone_annotations</artifactId>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
@@ -63,12 +67,18 @@
       </plugin>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+          <!-- Set max heap for tests. -->
+          <!-- Catch dependencies on the default locale by setting it to hi-IN. -->
+          <argLine>-Xmx1536M -Duser.language=hi -Duser.country=IN</argLine>
+        </configuration>
       </plugin>
       <plugin>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.3.1</version>
         <executions>
           <execution>
+            <id>create-test-jar</id>
             <goals><goal>test-jar</goal></goals>
           </execution>
         </executions>
@@ -77,7 +87,6 @@
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>animal-sniffer-maven-plugin</artifactId>
       </plugin>
-      <!-- TODO(cpovirk): reenable after a matching Caliper snapshot is pushed to Maven Central
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
@@ -95,7 +104,6 @@
           </execution>
         </executions>
       </plugin>
-      -->
     </plugins>
   </build>
 </project>
diff --git a/guava-tests/test/com/google/common/base/CharMatcherTest.java b/guava-tests/test/com/google/common/base/CharMatcherTest.java
index 19dad23..228d91e 100644
--- a/guava-tests/test/com/google/common/base/CharMatcherTest.java
+++ b/guava-tests/test/com/google/common/base/CharMatcherTest.java
@@ -16,14 +16,14 @@
 
 package com.google.common.base;
 
-import static com.google.common.base.CharMatcher.BREAKING_WHITESPACE;
-import static com.google.common.base.CharMatcher.WHITESPACE;
 import static com.google.common.base.CharMatcher.anyOf;
+import static com.google.common.base.CharMatcher.breakingWhitespace;
 import static com.google.common.base.CharMatcher.forPredicate;
 import static com.google.common.base.CharMatcher.inRange;
 import static com.google.common.base.CharMatcher.is;
 import static com.google.common.base.CharMatcher.isNot;
 import static com.google.common.base.CharMatcher.noneOf;
+import static com.google.common.base.CharMatcher.whitespace;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
@@ -51,7 +51,7 @@ public class CharMatcherTest extends TestCase {
   public void testStaticNullPointers() throws Exception {
     NullPointerTester tester = new NullPointerTester();
     tester.testAllPublicStaticMethods(CharMatcher.class);
-    tester.testAllPublicInstanceMethods(CharMatcher.ANY);
+    tester.testAllPublicInstanceMethods(CharMatcher.any());
     tester.testAllPublicInstanceMethods(CharMatcher.anyOf("abc"));
   }
 
@@ -67,14 +67,14 @@ public class CharMatcherTest extends TestCase {
     // we're lucky enough that these do pass, it saves us from having to write
     // more excruciating tests! Hooray!
 
-    assertSame(CharMatcher.ANY, CharMatcher.NONE.negate());
-    assertSame(CharMatcher.NONE, CharMatcher.ANY.negate());
+    assertSame(CharMatcher.any(), CharMatcher.none().negate());
+    assertSame(CharMatcher.none(), CharMatcher.any().negate());
 
-    assertSame(WHATEVER, CharMatcher.ANY.and(WHATEVER));
-    assertSame(CharMatcher.ANY, CharMatcher.ANY.or(WHATEVER));
+    assertSame(WHATEVER, CharMatcher.any().and(WHATEVER));
+    assertSame(CharMatcher.any(), CharMatcher.any().or(WHATEVER));
 
-    assertSame(CharMatcher.NONE, CharMatcher.NONE.and(WHATEVER));
-    assertSame(WHATEVER, CharMatcher.NONE.or(WHATEVER));
+    assertSame(CharMatcher.none(), CharMatcher.none().and(WHATEVER));
+    assertSame(WHATEVER, CharMatcher.none().or(WHATEVER));
   }
 
   // The rest of the behavior of ANY and DEFAULT will be covered in the tests for
@@ -82,8 +82,8 @@ public class CharMatcherTest extends TestCase {
 
   public void testWhitespaceBreakingWhitespaceSubset() throws Exception {
     for (int c = 0; c <= Character.MAX_VALUE; c++) {
-      if (BREAKING_WHITESPACE.apply((char) c)) {
-        assertTrue(Integer.toHexString(c), WHITESPACE.apply((char) c));
+      if (breakingWhitespace().matches((char) c)) {
+        assertTrue(Integer.toHexString(c), whitespace().matches((char) c));
       }
     }
   }
@@ -95,7 +95,7 @@ public class CharMatcherTest extends TestCase {
   public void testJavaIsoControl() {
     for (int c = 0; c <= Character.MAX_VALUE; c++) {
       assertEquals("" + c, Character.isISOControl(c),
-          CharMatcher.JAVA_ISO_CONTROL.matches((char) c));
+          CharMatcher.javaIsoControl().matches((char) c));
     }
   }
 
@@ -111,8 +111,8 @@ public class CharMatcherTest extends TestCase {
 
   @GwtIncompatible("java.util.BitSet")
   public void testSetBits() {
-    doTestSetBits(CharMatcher.ANY);
-    doTestSetBits(CharMatcher.NONE);
+    doTestSetBits(CharMatcher.any());
+    doTestSetBits(CharMatcher.none());
     doTestSetBits(is('a'));
     doTestSetBits(isNot('a'));
     doTestSetBits(anyOf(""));
@@ -122,10 +122,10 @@ public class CharMatcherTest extends TestCase {
     doTestSetBits(noneOf("CharMatcher"));
     doTestSetBits(inRange('n', 'q'));
     doTestSetBits(forPredicate(Predicates.equalTo('c')));
-    doTestSetBits(CharMatcher.ASCII);
-    doTestSetBits(CharMatcher.DIGIT);
-    doTestSetBits(CharMatcher.INVISIBLE);
-    doTestSetBits(CharMatcher.WHITESPACE);
+    doTestSetBits(CharMatcher.ascii());
+    doTestSetBits(CharMatcher.digit());
+    doTestSetBits(CharMatcher.invisible());
+    doTestSetBits(CharMatcher.whitespace());
     doTestSetBits(inRange('A', 'Z').and(inRange('F', 'K').negate()));
   }
 
@@ -139,8 +139,8 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testEmpty() throws Exception {
-    doTestEmpty(CharMatcher.ANY);
-    doTestEmpty(CharMatcher.NONE);
+    doTestEmpty(CharMatcher.any());
+    doTestEmpty(CharMatcher.none());
     doTestEmpty(is('a'));
     doTestEmpty(isNot('a'));
     doTestEmpty(anyOf(""));
@@ -154,8 +154,8 @@ public class CharMatcherTest extends TestCase {
 
   @GwtIncompatible("NullPointerTester")
   public void testNull() throws Exception {
-    doTestNull(CharMatcher.ANY);
-    doTestNull(CharMatcher.NONE);
+    doTestNull(CharMatcher.any());
+    doTestNull(CharMatcher.none());
     doTestNull(is('a'));
     doTestNull(isNot('a'));
     doTestNull(anyOf(""));
@@ -204,7 +204,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testNoMatches() {
-    doTestNoMatches(CharMatcher.NONE, "blah");
+    doTestNoMatches(CharMatcher.none(), "blah");
     doTestNoMatches(is('a'), "bcde");
     doTestNoMatches(isNot('a'), "aaaa");
     doTestNoMatches(anyOf(""), "abcd");
@@ -215,10 +215,10 @@ public class CharMatcherTest extends TestCase {
     doTestNoMatches(inRange('p', 'x'), "mom");
     doTestNoMatches(forPredicate(Predicates.equalTo('c')), "abe");
     doTestNoMatches(inRange('A', 'Z').and(inRange('F', 'K').negate()), "F1a");
-    doTestNoMatches(CharMatcher.DIGIT, "\tAz()");
-    doTestNoMatches(CharMatcher.JAVA_DIGIT, "\tAz()");
-    doTestNoMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "\tAz()");
-    doTestNoMatches(CharMatcher.SINGLE_WIDTH, "\u05bf\u3000");
+    doTestNoMatches(CharMatcher.digit(), "\tAz()");
+    doTestNoMatches(CharMatcher.javaDigit(), "\tAz()");
+    doTestNoMatches(CharMatcher.digit().and(CharMatcher.ascii()), "\tAz()");
+    doTestNoMatches(CharMatcher.singleWidth(), "\u05bf\u3000");
   }
 
   private void doTestNoMatches(CharMatcher matcher, String s) {
@@ -233,7 +233,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testAllMatches() {
-    doTestAllMatches(CharMatcher.ANY, "blah");
+    doTestAllMatches(CharMatcher.any(), "blah");
     doTestAllMatches(isNot('a'), "bcde");
     doTestAllMatches(is('a'), "aaaa");
     doTestAllMatches(noneOf("CharMatcher"), "zxqy");
@@ -242,10 +242,10 @@ public class CharMatcherTest extends TestCase {
     doTestAllMatches(anyOf("CharMatcher"), "ChMa");
     doTestAllMatches(inRange('m', 'p'), "mom");
     doTestAllMatches(forPredicate(Predicates.equalTo('c')), "ccc");
-    doTestAllMatches(CharMatcher.DIGIT, "0123456789\u0ED0\u1B59");
-    doTestAllMatches(CharMatcher.JAVA_DIGIT, "0123456789");
-    doTestAllMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "0123456789");
-    doTestAllMatches(CharMatcher.SINGLE_WIDTH, "\t0123ABCdef~\u00A0\u2111");
+    doTestAllMatches(CharMatcher.digit(), "0123456789\u0ED0\u1B59");
+    doTestAllMatches(CharMatcher.javaDigit(), "0123456789");
+    doTestAllMatches(CharMatcher.digit().and(CharMatcher.ascii()), "0123456789");
+    doTestAllMatches(CharMatcher.singleWidth(), "\t0123ABCdef~\u00A0\u2111");
   }
 
   private void doTestAllMatches(CharMatcher matcher, String s) {
@@ -355,6 +355,7 @@ public class CharMatcherTest extends TestCase {
     reallyTestMatchThenNoMatch(matcher.precomputed().negate(), s);
   }
 
+  @SuppressWarnings("deprecation") // intentionally testing apply() method
   private void reallyTestOneCharMatch(CharMatcher matcher, String s) {
     assertTrue(matcher.matches(s.charAt(0)));
     assertTrue(matcher.apply(s.charAt(0)));
@@ -372,6 +373,7 @@ public class CharMatcherTest extends TestCase {
     assertEquals(1, matcher.countIn(s));
   }
 
+  @SuppressWarnings("deprecation") // intentionally testing apply() method
   private void reallyTestOneCharNoMatch(CharMatcher matcher, String s) {
     assertFalse(matcher.matches(s.charAt(0)));
     assertFalse(matcher.apply(s.charAt(0)));
@@ -487,14 +489,14 @@ public class CharMatcherTest extends TestCase {
     assertSame(inout, anyOf("-").collapseFrom(inout, '_'));
     assertSame(inout, anyOf("-#").collapseFrom(inout, '_'));
     assertSame(inout, anyOf("-#123").collapseFrom(inout, '_'));
-    assertSame(inout, CharMatcher.NONE.collapseFrom(inout, '_'));
+    assertSame(inout, CharMatcher.none().collapseFrom(inout, '_'));
   }
 
   public void testCollapse_any() {
-    assertEquals("", CharMatcher.ANY.collapseFrom("", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("a", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("ab", '_'));
-    assertEquals("_", CharMatcher.ANY.collapseFrom("abcd", '_'));
+    assertEquals("", CharMatcher.any().collapseFrom("", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("a", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("ab", '_'));
+    assertEquals("_", CharMatcher.any().collapseFrom("abcd", '_'));
   }
 
   public void testTrimFrom() {
@@ -652,18 +654,18 @@ public class CharMatcherTest extends TestCase {
     // build a precomputed version.
     CharMatcher m1 = is('x');
     assertSame(m1, m1.precomputed());
-    assertSame(m1.toString(), m1.precomputed().toString());
+    assertEquals(m1.toString(), m1.precomputed().toString());
 
     CharMatcher m2 = anyOf("Az");
     assertSame(m2, m2.precomputed());
-    assertSame(m2.toString(), m2.precomputed().toString());
+    assertEquals(m2.toString(), m2.precomputed().toString());
 
     CharMatcher m3 = inRange('A', 'Z');
     assertSame(m3, m3.precomputed());
-    assertSame(m3.toString(), m3.precomputed().toString());
+    assertEquals(m3.toString(), m3.precomputed().toString());
 
-    assertSame(CharMatcher.NONE, CharMatcher.NONE.precomputed());
-    assertSame(CharMatcher.ANY, CharMatcher.ANY.precomputed());
+    assertSame(CharMatcher.none(), CharMatcher.none().precomputed());
+    assertSame(CharMatcher.any(), CharMatcher.any().precomputed());
   }
 
   @GwtIncompatible("java.util.BitSet")
@@ -674,8 +676,8 @@ public class CharMatcherTest extends TestCase {
   @GwtIncompatible("java.util.BitSet")
   private static BitSet bitSet(char[] chars) {
     BitSet tmp = new BitSet();
-    for (int i = 0; i < chars.length; i++) {
-      tmp.set(chars[i]);
+    for (char c : chars) {
+      tmp.set(c);
     }
     return tmp;
   }
@@ -717,8 +719,8 @@ public class CharMatcherTest extends TestCase {
 
   static void checkExactMatches(CharMatcher m, char[] chars) {
     Set<Character> positive = Sets.newHashSetWithExpectedSize(chars.length);
-    for (int i = 0; i < chars.length; i++) {
-      positive.add(chars[i]);
+    for (char c : chars) {
+      positive.add(c);
     }
     for (int c = 0; c <= Character.MAX_VALUE; c++) {
       assertFalse(positive.contains(new Character((char) c)) ^ m.matches((char) c));
@@ -747,7 +749,7 @@ public class CharMatcherTest extends TestCase {
   }
 
   public void testToString() {
-    assertToStringWorks("CharMatcher.NONE", CharMatcher.anyOf(""));
+    assertToStringWorks("CharMatcher.none()", CharMatcher.anyOf(""));
     assertToStringWorks("CharMatcher.is('\\u0031')", CharMatcher.anyOf("1"));
     assertToStringWorks("CharMatcher.isNot('\\u0031')", CharMatcher.isNot('1'));
     assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\")", CharMatcher.anyOf("12"));
diff --git a/guava-tests/test/com/google/common/base/EnumsTest.java b/guava-tests/test/com/google/common/base/EnumsTest.java
index a5faed2..69c65fc 100644
--- a/guava-tests/test/com/google/common/base/EnumsTest.java
+++ b/guava-tests/test/com/google/common/base/EnumsTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.ImmutableSet;
@@ -50,27 +52,27 @@ public class EnumsTest extends TestCase {
   private enum OtherEnum {}
 
   public void testGetIfPresent() {
-    assertEquals(Optional.of(TestEnum.CHEETO), Enums.getIfPresent(TestEnum.class, "CHEETO"));
-    assertEquals(Optional.of(TestEnum.HONDA), Enums.getIfPresent(TestEnum.class, "HONDA"));
-    assertEquals(Optional.of(TestEnum.POODLE), Enums.getIfPresent(TestEnum.class, "POODLE"));
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
 
-    assertTrue(Enums.getIfPresent(TestEnum.class, "CHEETO").isPresent());
-    assertTrue(Enums.getIfPresent(TestEnum.class, "HONDA").isPresent());
-    assertTrue(Enums.getIfPresent(TestEnum.class, "POODLE").isPresent());
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).isPresent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).isPresent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).isPresent();
 
-    assertEquals(TestEnum.CHEETO, Enums.getIfPresent(TestEnum.class, "CHEETO").get());
-    assertEquals(TestEnum.HONDA, Enums.getIfPresent(TestEnum.class, "HONDA").get());
-    assertEquals(TestEnum.POODLE, Enums.getIfPresent(TestEnum.class, "POODLE").get());
+    assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+    assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+    assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
   }
 
   public void testGetIfPresent_caseSensitive() {
-    assertFalse(Enums.getIfPresent(TestEnum.class, "cHEETO").isPresent());
-    assertFalse(Enums.getIfPresent(TestEnum.class, "Honda").isPresent());
-    assertFalse(Enums.getIfPresent(TestEnum.class, "poodlE").isPresent());
+    assertThat(Enums.getIfPresent(TestEnum.class, "cHEETO")).isAbsent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "Honda")).isAbsent();
+    assertThat(Enums.getIfPresent(TestEnum.class, "poodlE")).isAbsent();
   }
 
   public void testGetIfPresent_whenNoMatchingConstant() {
-    assertEquals(Optional.absent(), Enums.getIfPresent(TestEnum.class, "WOMBAT"));
+    assertThat(Enums.getIfPresent(TestEnum.class, "WOMBAT")).isAbsent();
   }
 
   @GwtIncompatible("weak references")
@@ -95,12 +97,12 @@ public class EnumsTest extends TestCase {
     Set<TestEnum> shadowConstants = new HashSet<TestEnum>();
     for (TestEnum constant : TestEnum.values()) {
       Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, constant.name());
-      assertTrue(result.isPresent());
+      assertThat(result).isPresent();
       shadowConstants.add(result.get());
     }
     assertEquals(ImmutableSet.copyOf(shadowTestEnum.getEnumConstants()), shadowConstants);
     Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, "blibby");
-    assertFalse(result.isPresent());
+    assertThat(result).isAbsent();
     return new WeakReference<ClassLoader>(shadowLoader);
   }
 
diff --git a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
index de52bbe..60b481a 100644
--- a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
+++ b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
@@ -107,6 +107,7 @@ public class FinalizableReferenceQueueTest extends TestCase {
     };
   }
 
+  @SuppressUnderAndroid // no concept of separate ClassLoaders
   public void testDecoupledLoader() {
     FinalizableReferenceQueue.DecoupledLoader decoupledLoader =
         new FinalizableReferenceQueue.DecoupledLoader() {
@@ -146,6 +147,7 @@ public class FinalizableReferenceQueueTest extends TestCase {
     }
   }
 
+  @SuppressUnderAndroid // TODO(cpovirk): How significant is this failure?
   public void testGetFinalizerUrl() {
     assertNotNull(getClass().getResource("internal/Finalizer.class"));
   }
diff --git a/guava-tests/test/com/google/common/base/FunctionsTest.java b/guava-tests/test/com/google/common/base/FunctionsTest.java
index cc7b4f2..90304c5 100644
--- a/guava-tests/test/com/google/common/base/FunctionsTest.java
+++ b/guava-tests/test/com/google/common/base/FunctionsTest.java
@@ -434,6 +434,8 @@ public class FunctionsTest extends TestCase {
   }
 
   @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
+  // (I suspect that this and the other similar failures happen with ArbitraryInstances proxies.)
   public void testEqualsAndSerializable() throws Exception {
     new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testEqualsAndSerializable();
   }
diff --git a/guava-tests/test/com/google/common/base/JoinerTest.java b/guava-tests/test/com/google/common/base/JoinerTest.java
index 32f22e2..c0322f6 100644
--- a/guava-tests/test/com/google/common/base/JoinerTest.java
+++ b/guava-tests/test/com/google/common/base/JoinerTest.java
@@ -58,6 +58,7 @@ public class JoinerTest extends TestCase {
   private static final Iterable<Integer> ITERABLE_FOUR_NULLS
       = Arrays.asList((Integer) null, null, null, null);
 
+  @SuppressWarnings("CheckReturnValue")
   public void testNoSpecialNullBehavior() {
     checkNoOutput(J, ITERABLE_);
     checkResult(J, ITERABLE_1, "1");
@@ -237,6 +238,7 @@ public class JoinerTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMap() {
     MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
     assertEquals("", j.join(ImmutableMap.of()));
@@ -259,6 +261,7 @@ public class JoinerTest extends TestCase {
     assertEquals("1:2;3:4;5:6", sb.toString());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEntries() {
     MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
     assertEquals("", j.join(ImmutableMultimap.of().entries()));
diff --git a/guava-tests/test/com/google/common/base/ObjectsTest.java b/guava-tests/test/com/google/common/base/ObjectsTest.java
index c8de82b..6eb4952 100644
--- a/guava-tests/test/com/google/common/base/ObjectsTest.java
+++ b/guava-tests/test/com/google/common/base/ObjectsTest.java
@@ -70,6 +70,7 @@ public class ObjectsTest extends TestCase {
     assertSame(n1, n2);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFirstNonNull_throwsNullPointerException() throws Exception {
     try {
       Objects.firstNonNull(null, null);
diff --git a/guava-tests/test/com/google/common/base/OptionalTest.java b/guava-tests/test/com/google/common/base/OptionalTest.java
index daa8920..7ad2c19 100644
--- a/guava-tests/test/com/google/common/base/OptionalTest.java
+++ b/guava-tests/test/com/google/common/base/OptionalTest.java
@@ -47,6 +47,7 @@ public final class OptionalTest extends TestCase {
     assertEquals("training", Optional.of("training").get());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testOf_null() {
     try {
       Optional.of(null);
@@ -73,6 +74,7 @@ public final class OptionalTest extends TestCase {
     assertTrue(Optional.of("training").isPresent());
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testGet_absent() {
     Optional<String> optional = Optional.absent();
     try {
@@ -102,6 +104,7 @@ public final class OptionalTest extends TestCase {
     assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testOr_nullSupplier_absent() {
     Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
     Optional<Object> absentOptional = Optional.absent();
@@ -173,6 +176,7 @@ public final class OptionalTest extends TestCase {
     assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testTransform_present_functionReturnsNull() {
     try {
       Optional.of("a").transform(
@@ -201,6 +205,8 @@ public final class OptionalTest extends TestCase {
   public void testEqualsAndHashCode_absent() {
     assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
     assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
+    assertThat(Optional.absent().hashCode())
+        .isNotEqualTo(Optional.of(0).hashCode());
   }
 
   public void testEqualsAndHashCode_present() {
@@ -221,7 +227,7 @@ public final class OptionalTest extends TestCase {
   public void testPresentInstances_allPresent() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
-    assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
+    assertThat(Optional.presentInstances(optionals)).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testPresentInstances_allAbsent() {
@@ -233,22 +239,22 @@ public final class OptionalTest extends TestCase {
   public void testPresentInstances_somePresent() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
-    assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
+    assertThat(Optional.presentInstances(optionals)).containsExactly("a", "c").inOrder();
   }
 
   public void testPresentInstances_callingIteratorTwice() {
     List<Optional<String>> optionals =
         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
     Iterable<String> onlyPresent = Optional.presentInstances(optionals);
-    assertThat(onlyPresent).iteratesAs("a", "c");
-    assertThat(onlyPresent).iteratesAs("a", "c");
+    assertThat(onlyPresent).containsExactly("a", "c").inOrder();
+    assertThat(onlyPresent).containsExactly("a", "c").inOrder();
   }
 
   public void testPresentInstances_wildcards() {
     List<Optional<? extends Number>> optionals =
         ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
     Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
-    assertThat(onlyPresent).iteratesAs(2);
+    assertThat(onlyPresent).containsExactly(2).inOrder();
   }
 
   private static Optional<Integer> getSomeOptionalInt() {
diff --git a/guava-tests/test/com/google/common/base/PreconditionsTest.java b/guava-tests/test/com/google/common/base/PreconditionsTest.java
index df44a3f..e4b1aa8 100644
--- a/guava-tests/test/com/google/common/base/PreconditionsTest.java
+++ b/guava-tests/test/com/google/common/base/PreconditionsTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.testing.NullPointerTester;
@@ -61,7 +63,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkArgument(false, null);
       fail("no exception thrown");
     } catch (IllegalArgumentException expected) {
-      assertEquals("null", expected.getMessage());
+      assertThat(expected).hasMessage("null");
     }
   }
 
@@ -108,7 +110,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkState(false, null);
       fail("no exception thrown");
     } catch (IllegalStateException expected) {
-      assertEquals("null", expected.getMessage());
+      assertThat(expected).hasMessage("null");
     }
   }
 
@@ -190,7 +192,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(-1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("index (-1) must not be negative");
     }
   }
 
@@ -199,8 +201,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (1) must be less than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("index (1) must be less than size (1)");
     }
   }
 
@@ -209,7 +210,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(-1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("foo (-1) must not be negative");
     }
   }
 
@@ -218,8 +219,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkElementIndex(1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (1) must be less than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("foo (1) must be less than size (1)");
     }
   }
 
@@ -244,7 +244,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(-1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("index (-1) must not be negative");
     }
   }
 
@@ -253,8 +253,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(2, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("index (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("index (2) must not be greater than size (1)");
     }
   }
 
@@ -263,7 +262,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(-1, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (-1) must not be negative", expected.getMessage());
+      assertThat(expected).hasMessage("foo (-1) must not be negative");
     }
   }
 
@@ -272,8 +271,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndex(2, 1, "foo");
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("foo (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("foo (2) must not be greater than size (1)");
     }
   }
 
@@ -297,8 +295,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(-1, 1, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("start index (-1) must not be negative",
-          expected.getMessage());
+      assertThat(expected).hasMessage("start index (-1) must not be negative");
     }
   }
 
@@ -307,8 +304,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(0, 2, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("end index (2) must not be greater than size (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("end index (2) must not be greater than size (1)");
     }
   }
 
@@ -317,8 +313,7 @@ public class PreconditionsTest extends TestCase {
       Preconditions.checkPositionIndexes(1, 0, 1);
       fail();
     } catch (IndexOutOfBoundsException expected) {
-      assertEquals("end index (0) must not be less than start index (1)",
-          expected.getMessage());
+      assertThat(expected).hasMessage("end index (0) must not be less than start index (1)");
     }
   }
 
@@ -364,10 +359,10 @@ public class PreconditionsTest extends TestCase {
   private static final String FORMAT = "I ate %s pies.";
 
   private static void verifySimpleMessage(Exception e) {
-    assertEquals("A message", e.getMessage());
+    assertThat(e).hasMessage("A message");
   }
 
   private static void verifyComplexMessage(Exception e) {
-    assertEquals("I ate 5 pies.", e.getMessage());
+    assertThat(e).hasMessage("I ate 5 pies.");
   }
 }
diff --git a/guava-tests/test/com/google/common/base/PredicatesTest.java b/guava-tests/test/com/google/common/base/PredicatesTest.java
index 3864dda..4e78b74 100644
--- a/guava-tests/test/com/google/common/base/PredicatesTest.java
+++ b/guava-tests/test/com/google/common/base/PredicatesTest.java
@@ -918,6 +918,7 @@ public class PredicatesTest extends TestCase {
   }
 
   @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
   public void testEqualsAndSerializable() throws Exception {
     new ClassSanityTester().forAllPublicStaticMethods(Predicates.class).testEqualsAndSerializable();
   }
diff --git a/guava-tests/test/com/google/common/base/SplitterTest.java b/guava-tests/test/com/google/common/base/SplitterTest.java
index 88b4c80..49b8082 100644
--- a/guava-tests/test/com/google/common/base/SplitterTest.java
+++ b/guava-tests/test/com/google/common/base/SplitterTest.java
@@ -20,13 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.testing.NullPointerTester;
 
 import junit.framework.TestCase;
 
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -40,6 +38,7 @@ public class SplitterTest extends TestCase {
 
   private static final Splitter COMMA_SPLITTER = Splitter.on(',');
 
+  @SuppressWarnings("CheckReturnValue")
   public void testSplitNullString() {
     try {
       COMMA_SPLITTER.split(null);
@@ -51,7 +50,7 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplit() {
     String simple = "a,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   /**
@@ -65,7 +64,7 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplitToList() {
     String simple = "a,b,c";
     List<String> letters = COMMA_SPLITTER.splitToList(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testToString() {
@@ -77,72 +76,74 @@ public class SplitterTest extends TestCase {
   public void testCharacterSimpleSplitWithNoDelimiter() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on('.').split(simple);
-    assertThat(letters).iteratesAs("a,b,c");
+    assertThat(letters).containsExactly("a,b,c").inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiter() {
     String doubled = "a,,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(doubled);
-    assertThat(letters).iteratesAs("a", "", "b", "c");
+    assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiterAndSpace() {
     String doubled = "a,, b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(doubled);
-    assertThat(letters).iteratesAs("a", "", " b", "c");
+    assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
   }
 
   public void testCharacterSplitWithTrailingDelimiter() {
     String trailing = "a,b,c,";
     Iterable<String> letters = COMMA_SPLITTER.split(trailing);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testCharacterSplitWithLeadingDelimiter() {
     String leading = ",a,b,c";
     Iterable<String> letters = COMMA_SPLITTER.split(leading);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testCharacterSplitWithMulitpleLetters() {
     Iterable<String> testCharacteringMotto = Splitter.on('-').split(
         "Testing-rocks-Debugging-sucks");
-    assertThat(testCharacteringMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testCharacteringMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testCharacterSplitWithMatcherDelimiter() {
     Iterable<String> testCharacteringMotto = Splitter
         .on(CharMatcher.WHITESPACE)
         .split("Testing\nrocks\tDebugging sucks");
-    assertThat(testCharacteringMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testCharacteringMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
     String doubled = "a..b.c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().split(doubled);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testCharacterSplitEmptyToken() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.').trimResults()
         .split(emptyToken);
-    assertThat(letters).iteratesAs("a", "", "c");
+    assertThat(letters).containsExactly("a", "", "c").inOrder();
   }
 
   public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "c");
+    assertThat(letters).containsExactly("a", "c").inOrder();
   }
 
   public void testCharacterSplitOnEmptyString() {
     Iterable<String> nothing = Splitter.on('.').split("");
-    assertThat(nothing).iteratesAs("");
+    assertThat(nothing).containsExactly("").inOrder();
   }
 
   public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
@@ -151,7 +152,7 @@ public class SplitterTest extends TestCase {
 
   public void testCharacterSplitOnOnlyDelimiter() {
     Iterable<String> blankblank = Splitter.on('.').split(".");
-    assertThat(blankblank).iteratesAs("", "");
+    assertThat(blankblank).containsExactly("", "").inOrder();
   }
 
   public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -165,99 +166,102 @@ public class SplitterTest extends TestCase {
     Iterable<String> family = COMMA_SPLITTER
         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
         .split(jacksons);
-    assertThat(family).iteratesAs(
-        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+    assertThat(family)
+        .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+        .inOrder();
   }
 
   public void testStringSimpleSplit() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on(',').split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSimpleSplitWithNoDelimiter() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.on('.').split(simple);
-    assertThat(letters).iteratesAs("a,b,c");
+    assertThat(letters).containsExactly("a,b,c").inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiter() {
     String doubled = "a,,b,c";
     Iterable<String> letters = Splitter.on(',').split(doubled);
-    assertThat(letters).iteratesAs("a", "", "b", "c");
+    assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiterAndSpace() {
     String doubled = "a,, b,c";
     Iterable<String> letters = Splitter.on(',').split(doubled);
-    assertThat(letters).iteratesAs("a", "", " b", "c");
+    assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
   }
 
   public void testStringSplitWithTrailingDelimiter() {
     String trailing = "a,b,c,";
     Iterable<String> letters = Splitter.on(',').split(trailing);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testStringSplitWithLeadingDelimiter() {
     String leading = ",a,b,c";
     Iterable<String> letters = Splitter.on(',').split(leading);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithMultipleLetters() {
     Iterable<String> testStringingMotto = Splitter.on('-').split(
         "Testing-rocks-Debugging-sucks");
-    assertThat(testStringingMotto).iteratesAs(
-        "Testing", "rocks", "Debugging", "sucks");
+    assertThat(testStringingMotto)
+        .containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
     String doubled = "a..b.c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().split(doubled);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSplitEmptyToken() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.').trimResults()
         .split(emptyToken);
-    assertThat(letters).iteratesAs("a", "", "c");
+    assertThat(letters).containsExactly("a", "", "c").inOrder();
   }
 
   public void testStringSplitEmptyTokenOmitEmptyStrings() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on('.')
         .omitEmptyStrings().trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "c");
+    assertThat(letters).containsExactly("a", "c").inOrder();
   }
 
   public void testStringSplitWithLongDelimiter() {
     String longDelimiter = "a, b, c";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithLongLeadingDelimiter() {
     String longDelimiter = ", a, b, c";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   public void testStringSplitWithLongTrailingDelimiter() {
     String longDelimiter = "a, b, c, ";
     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   public void testStringSplitWithDelimiterSubstringInValue() {
     String fourCommasAndFourSpaces = ",,,,    ";
     Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
         fourCommasAndFourSpaces);
-    assertThat(threeCommasThenThreeSpaces).iteratesAs(",,,", "   ");
+    assertThat(threeCommasThenThreeSpaces).containsExactly(",,,", "   ").inOrder();
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringSplitWithEmptyString() {
     try {
       Splitter.on("");
@@ -268,7 +272,7 @@ public class SplitterTest extends TestCase {
 
   public void testStringSplitOnEmptyString() {
     Iterable<String> notMuch = Splitter.on('.').split("");
-    assertThat(notMuch).iteratesAs("");
+    assertThat(notMuch).containsExactly("").inOrder();
   }
 
   public void testStringSplitOnEmptyStringOmitEmptyString() {
@@ -277,7 +281,7 @@ public class SplitterTest extends TestCase {
 
   public void testStringSplitOnOnlyDelimiter() {
     Iterable<String> blankblank = Splitter.on('.').split(".");
-    assertThat(blankblank).iteratesAs("", "");
+    assertThat(blankblank).containsExactly("", "").inOrder();
   }
 
   public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -291,50 +295,51 @@ public class SplitterTest extends TestCase {
     Iterable<String> family = Splitter.on(',')
         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
         .split(jacksons);
-    assertThat(family).iteratesAs(
-        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+    assertThat(family)
+        .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+        .inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSimpleSplit() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.onPattern(",").split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSimpleSplitWithNoDelimiter() {
     String simple = "a,b,c";
     Iterable<String> letters = Splitter.onPattern("foo").split(simple);
-    assertThat(letters).iteratesAs("a,b,c");
+    assertThat(letters).containsExactly("a,b,c").inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSplitWithDoubleDelimiter() {
     String doubled = "a,,b,c";
     Iterable<String> letters = Splitter.onPattern(",").split(doubled);
-    assertThat(letters).iteratesAs("a", "", "b", "c");
+    assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSplitWithDoubleDelimiterAndSpace() {
     String doubled = "a,, b,c";
     Iterable<String> letters = Splitter.onPattern(",").split(doubled);
-    assertThat(letters).iteratesAs("a", "", " b", "c");
+    assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSplitWithTrailingDelimiter() {
     String trailing = "a,b,c,";
     Iterable<String> letters = Splitter.onPattern(",").split(trailing);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
   @GwtIncompatible("Splitter.onPattern")
   public void testPatternSplitWithLeadingDelimiter() {
     String leading = ",a,b,c";
     Iterable<String> letters = Splitter.onPattern(",").split(leading);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   // TODO(kevinb): the name of this method suggests it might not actually be testing what it
@@ -343,7 +348,8 @@ public class SplitterTest extends TestCase {
   public void testPatternSplitWithMultipleLetters() {
     Iterable<String> testPatterningMotto = Splitter.onPattern("-").split(
         "Testing-rocks-Debugging-sucks");
-    assertThat(testPatterningMotto).iteratesAs("Testing", "rocks", "Debugging", "sucks");
+    assertThat(testPatterningMotto).containsExactly("Testing", "rocks", "Debugging", "sucks")
+        .inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
@@ -356,30 +362,32 @@ public class SplitterTest extends TestCase {
     String doubled = "a..b.c";
     Iterable<String> letters = Splitter.on(literalDotPattern())
         .omitEmptyStrings().split(doubled);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
+  @SuppressUnderAndroid // TODO(cpovirk): File Android bug.
   public void testPatternSplitLookBehind() {
     String toSplit = ":foo::barbaz:";
     String regexPattern = "(?<=:)";
     Iterable<String> split = Splitter.onPattern(regexPattern).split(toSplit);
-    assertThat(split).iteratesAs(":", "foo:", ":", "barbaz:");
+    assertThat(split).containsExactly(":", "foo:", ":", "barbaz:").inOrder();
     // splits into chunks ending in :
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
+  @SuppressUnderAndroid // TODO(cpovirk): File Android bug.
   public void testPatternSplitWordBoundary() {
     String string = "foo<bar>bletch";
     Iterable<String> words = Splitter.on(Pattern.compile("\\b")).split(string);
-    assertThat(words).iteratesAs("foo", "<", "bar", ">", "bletch");
+    assertThat(words).containsExactly("foo", "<", "bar", ">", "bletch").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
   public void testPatternSplitEmptyToken() {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on(literalDotPattern()).trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "", "c");
+    assertThat(letters).containsExactly("a", "", "c").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
@@ -387,14 +395,14 @@ public class SplitterTest extends TestCase {
     String emptyToken = "a. .c";
     Iterable<String> letters = Splitter.on(literalDotPattern())
         .omitEmptyStrings().trimResults().split(emptyToken);
-    assertThat(letters).iteratesAs("a", "c");
+    assertThat(letters).containsExactly("a", "c").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
   public void testPatternSplitOnOnlyDelimiter() {
     Iterable<String> blankblank = Splitter.on(literalDotPattern()).split(".");
 
-    assertThat(blankblank).iteratesAs("", "");
+    assertThat(blankblank).containsExactly("", "").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
@@ -409,7 +417,7 @@ public class SplitterTest extends TestCase {
     String longDelimiter = "a, b,   c";
     Iterable<String> letters = Splitter.on(Pattern.compile(",\\s*"))
         .split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c");
+    assertThat(letters).containsExactly("a", "b", "c").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
@@ -417,7 +425,7 @@ public class SplitterTest extends TestCase {
     String longDelimiter = ", a, b, c";
     Iterable<String> letters = Splitter.on(Pattern.compile(", "))
         .split(longDelimiter);
-    assertThat(letters).iteratesAs("", "a", "b", "c");
+    assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
@@ -425,9 +433,10 @@ public class SplitterTest extends TestCase {
     String longDelimiter = "a, b, c/ ";
     Iterable<String> letters = Splitter.on(Pattern.compile("[,/]\\s"))
         .split(longDelimiter);
-    assertThat(letters).iteratesAs("a", "b", "c", "");
+    assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
   }
 
+  @SuppressWarnings("CheckReturnValue")
   @GwtIncompatible("java.util.regex.Pattern")
   public void testPatternSplitInvalidPattern() {
     try {
@@ -444,8 +453,9 @@ public class SplitterTest extends TestCase {
     Iterable<String> family = Splitter.on(Pattern.compile(","))
         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
         .split(jacksons);
-    assertThat(family).iteratesAs(
-        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+    assertThat(family)
+        .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+        .inOrder();
   }
 
   public void testSplitterIterableIsUnmodifiable_char() {
@@ -480,6 +490,7 @@ public class SplitterTest extends TestCase {
   }
 
   @GwtIncompatible("java.util.regex.Pattern")
+  @SuppressUnderAndroid // TODO(cpovirk): File Android bug (different from the two above).
   public void testSplitterIterableIsLazy_pattern() {
     assertSplitterIterableIsLazy(Splitter.onPattern(","));
   }
@@ -505,31 +516,31 @@ public class SplitterTest extends TestCase {
   public void testFixedLengthSimpleSplit() {
     String simple = "abcde";
     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
-    assertThat(letters).iteratesAs("ab", "cd", "e");
+    assertThat(letters).containsExactly("ab", "cd", "e").inOrder();
   }
 
   public void testFixedLengthSplitEqualChunkLength() {
     String simple = "abcdef";
     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
-    assertThat(letters).iteratesAs("ab", "cd", "ef");
+    assertThat(letters).containsExactly("ab", "cd", "ef").inOrder();
   }
 
   public void testFixedLengthSplitOnlyOneChunk() {
     String simple = "abc";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("abc");
+    assertThat(letters).containsExactly("abc").inOrder();
   }
 
   public void testFixedLengthSplitSmallerString() {
     String simple = "ab";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("ab");
+    assertThat(letters).containsExactly("ab").inOrder();
   }
 
   public void testFixedLengthSplitEmptyString() {
     String simple = "";
     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
-    assertThat(letters).iteratesAs("");
+    assertThat(letters).containsExactly("").inOrder();
   }
 
   public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
@@ -539,9 +550,10 @@ public class SplitterTest extends TestCase {
   public void testFixedLengthSplitIntoChars() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c", "d");
+    assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFixedLengthSplitZeroChunkLen() {
     try {
       Splitter.fixedLength(0);
@@ -550,6 +562,7 @@ public class SplitterTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFixedLengthSplitNegativeChunkLen() {
     try {
       Splitter.fixedLength(-1);
@@ -561,73 +574,73 @@ public class SplitterTest extends TestCase {
   public void testLimitLarge() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
-    assertThat(letters).iteratesAs("a", "b", "c", "d");
+    assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
   }
 
   public void testLimitOne() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
-    assertThat(letters).iteratesAs("abcd");
+    assertThat(letters).containsExactly("abcd").inOrder();
   }
 
   public void testLimitFixedLength() {
     String simple = "abcd";
     Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
-    assertThat(letters).iteratesAs("a", "bcd");
+    assertThat(letters).containsExactly("a", "bcd").inOrder();
   }
 
   public void testLimitSeparator() {
     String simple = "a,b,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
-    assertThat(items).iteratesAs("a", "b,c,d");
+    assertThat(items).containsExactly("a", "b,c,d").inOrder();
   }
 
   public void testLimitExtraSeparators() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
-    assertThat(items).iteratesAs("a", ",,b,,c,d");
+    assertThat(items).containsExactly("a", ",,b,,c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsOmitEmpty() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
-    assertThat(items).iteratesAs("a", "b,,c,d");
+    assertThat(items).containsExactly("a", "b,,c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsOmitEmpty3() {
     String text = "a,,,b,,c,d";
     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
-    assertThat(items).iteratesAs("a", "b", "c,d");
+    assertThat(items).containsExactly("a", "b", "c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a", "b ,, c,d");
+    assertThat(items).containsExactly("a", "b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim3() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a", "b", "c,d");
+    assertThat(items).containsExactly("a", "b", "c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
-    assertThat(items).iteratesAs("a,,  , b ,, c,d");
+    assertThat(items).containsExactly("a,,  , b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1NoOmit() {
     String text = ",,a,,  , b ,, c,d ";
     Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
-    assertThat(items).iteratesAs(",,a,,  , b ,, c,d");
+    assertThat(items).containsExactly(",,a,,  , b ,, c,d").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1Empty() {
     String text = "";
     Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
-    assertThat(items).iteratesAs("");
+    assertThat(items).containsExactly("").inOrder();
   }
 
   public void testLimitExtraSeparatorsTrim1EmptyOmit() {
@@ -653,19 +666,15 @@ public class SplitterTest extends TestCase {
     tester.testAllPublicInstanceMethods(Splitter.on(',').trimResults());
   }
 
-  private static <E> List<E> asList(Collection<E> collection) {
-    return ImmutableList.copyOf(collection);
-  }
-
   public void testMapSplitter_trimmedBoth() {
     Map<String, String> m = COMMA_SPLITTER
         .trimResults()
         .withKeyValueSeparator(Splitter.on(':').trimResults())
         .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
     ImmutableMap<String, String> expected =
-          ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
+        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_trimmedEntries() {
@@ -677,7 +686,7 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy  ", " tom", "girl", " tina", "cat  ", " kitty", "dog", " tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_trimmedKeyValue() {
@@ -687,7 +696,7 @@ public class SplitterTest extends TestCase {
     ImmutableMap<String, String> expected =
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_notTrimmed() {
@@ -696,7 +705,7 @@ public class SplitterTest extends TestCase {
     ImmutableMap<String, String> expected =
         ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", "  tommy ");
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_CharacterSeparator() {
@@ -709,7 +718,7 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
   public void testMapSplitter_multiCharacterSeparator() {
@@ -722,10 +731,10 @@ public class SplitterTest extends TestCase {
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
 
     assertThat(m).isEqualTo(expected);
-    assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+    assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
   }
 
-  @SuppressWarnings("ReturnValueIgnored") // testing for exception
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_emptySeparator() {
     try {
       COMMA_SPLITTER.withKeyValueSeparator("");
@@ -734,6 +743,7 @@ public class SplitterTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_malformedEntry() {
     try {
       COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
@@ -747,7 +757,7 @@ public class SplitterTest extends TestCase {
         .withKeyValueSeparator(":")
         .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
 
-    assertThat(m.keySet()).iteratesAs("boy", "girl", "cat", "dog");
+    assertThat(m.keySet()).containsExactly("boy", "girl", "cat", "dog").inOrder();
     assertThat(m).isEqualTo(
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
 
@@ -756,11 +766,12 @@ public class SplitterTest extends TestCase {
         .withKeyValueSeparator(":")
         .split("girl:tina,boy:tom,dog:tommy,cat:kitty");
 
-    assertThat(m.keySet()).iteratesAs("girl", "boy", "dog", "cat");
+    assertThat(m.keySet()).containsExactly("girl", "boy", "dog", "cat").inOrder();
     assertThat(m).isEqualTo(
         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMapSplitter_duplicateKeys() {
     try {
       Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
diff --git a/guava-tests/test/com/google/common/base/StopwatchTest.java b/guava-tests/test/com/google/common/base/StopwatchTest.java
index bd6b2d2..44101dc 100644
--- a/guava-tests/test/com/google/common/base/StopwatchTest.java
+++ b/guava-tests/test/com/google/common/base/StopwatchTest.java
@@ -168,49 +168,6 @@ public class StopwatchTest extends TestCase {
     assertEquals(1, stopwatch.elapsed(MILLISECONDS));
   }
 
-  public void testElapsedMillis() {
-    stopwatch.start();
-    ticker.advance(999999);
-    assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-    ticker.advance(1);
-    assertEquals(1, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_whileRunning() {
-    ticker.advance(78000000);
-    stopwatch.start();
-    assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-
-    ticker.advance(345000000);
-    assertEquals(345, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_notRunning() {
-    ticker.advance(1000000);
-    stopwatch.start();
-    ticker.advance(4000000);
-    stopwatch.stop();
-    ticker.advance(9000000);
-    assertEquals(4, stopwatch.elapsed(MILLISECONDS));
-  }
-
-  public void testElapsedMillis_multipleSegments() {
-    stopwatch.start();
-    ticker.advance(9000000);
-    stopwatch.stop();
-
-    ticker.advance(16000000);
-
-    stopwatch.start();
-    assertEquals(9, stopwatch.elapsed(MILLISECONDS));
-    ticker.advance(25000000);
-    assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-
-    stopwatch.stop();
-    ticker.advance(36000000);
-    assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-  }
-
   @GwtIncompatible("String.format()")
   public void testToString() {
     stopwatch.start();
diff --git a/guava-tests/test/com/google/common/base/StringsTest.java b/guava-tests/test/com/google/common/base/StringsTest.java
index fb6ff1c..957f93a 100644
--- a/guava-tests/test/com/google/common/base/StringsTest.java
+++ b/guava-tests/test/com/google/common/base/StringsTest.java
@@ -68,6 +68,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testPadStart_null() {
     try {
       Strings.padStart(null, 5, '0');
@@ -97,6 +98,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testPadEnd_null() {
     try {
       Strings.padEnd(null, 5, '0');
@@ -105,6 +107,7 @@ public class StringsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testRepeat() {
     String input = "20";
     assertEquals("", Strings.repeat(input, 0));
@@ -132,6 +135,7 @@ public class StringsTest extends TestCase {
   }
 
   // TODO: could remove if we got NPT working in GWT somehow
+  @SuppressWarnings("CheckReturnValue")
   public void testRepeat_null() {
     try {
       Strings.repeat(null, 5);
diff --git a/guava-tests/test/com/google/common/base/SuppliersTest.java b/guava-tests/test/com/google/common/base/SuppliersTest.java
index 6e6ea9c..1bd784d 100644
--- a/guava-tests/test/com/google/common/base/SuppliersTest.java
+++ b/guava-tests/test/com/google/common/base/SuppliersTest.java
@@ -399,6 +399,7 @@ public class SuppliersTest extends TestCase {
   }
 
   @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
   public void testSuppliersSerializable() throws Exception {
     new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class)
         .testSerializable();
diff --git a/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java
new file mode 100644
index 0000000..b22c697
--- /dev/null
+++ b/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 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 java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>Why use a custom annotation instead of {@code android.test.suitebuilder.annotation.Suppress}?
+ * I'm not completely sure that this is the right choice, but it has various advantages:
+ *
+ * <ul>
+ * <li>An annotation named just "Suppress" might someday be treated by a non-Android tool as a
+ * suppression. This would follow the precedent of many of our annotation processors, which look for
+ * any annotation named, e.g., "GwtIncompatible," regardless of package.
+ * <li>An annotation named just "Suppress" might suggest to users that the test is suppressed under
+ * all environments. We could fight this by fully qualifying the annotation, but the result will be
+ * verbose and attention-grabbing.
+ * <li>We need to be careful about how we suppress {@code suite()} methods in {@code common.io}. The
+ * generated suite for {@code FooTest} ends up containing {@code FooTest} itself plus some other
+ * tests. We want to exclude the other tests (which Android can't handle) while continuing to run
+ * {@code FooTest} itself. This is exactly what happens with {@code SuppressUnderAndroid}. (But:
+ * TODO(cpovirk): Consider renaming this to "AndroidIncompatible," which would make this clearer by
+ * following the precedent of {@code GwtIncompatible}.) But I'm not sure what would happen if we
+ * annotated the {@code suite()} method with {@code Suppress}. Would {@code FooTest} itself be
+ * suppressed, too?
+ * <li>In at least one case, a use of {@code sun.misc.FpUtils}, the test will not even
+ * <i>compile</i> against Android. Now, this might be an artifact of our build system, one that we
+ * could probably work around. Or we could manually strip the test from open-source Guava while
+ * continuing to run it internally, as we do with many other tests. This would suffice because we
+ * our Android users and tests are using the open-source version, which would no longer have the
+ * problematic test. But why bother when we can instead strip it with a more precisely named
+ * annotation?
+ * <li>While a dependency on Android ought to be easy if it's for annotations only, it will probably
+ * require adding the dep to various whitelists, license files, and Proguard configurations, and
+ * there's always the potential that something will go wrong. It <i>probably</i> won't, since the
+ * deps are needed only in tests (and maybe someday in testlib), but why bother?
+ * <li>Stripping code entirely might help us keep under the method limit someday. Even if it never
+ * comes to that, it may at least help with build and startup times.
+ * </ul>
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/base/ThrowablesTest.java b/guava-tests/test/com/google/common/base/ThrowablesTest.java
index 52d8a74..0af9302 100644
--- a/guava-tests/test/com/google/common/base/ThrowablesTest.java
+++ b/guava-tests/test/com/google/common/base/ThrowablesTest.java
@@ -17,6 +17,9 @@
 package com.google.common.base;
 
 import static com.google.common.base.Throwables.getStackTraceAsString;
+import static com.google.common.base.Throwables.lazyStackTrace;
+import static com.google.common.base.Throwables.lazyStackTraceIsLazy;
+import static com.google.common.truth.Truth.assertThat;
 import static java.util.Arrays.asList;
 import static java.util.regex.Pattern.quote;
 
@@ -26,6 +29,9 @@ import com.google.common.testing.NullPointerTester;
 import junit.framework.TestCase;
 
 import java.io.FileNotFoundException;
+import java.security.Permission;
+import java.security.Policy;
+import java.security.ProtectionDomain;
 import java.util.List;
 
 /**
@@ -335,7 +341,7 @@ public class ThrowablesTest extends TestCase {
       sample.noneDeclared();
       fail();
     } catch (RuntimeException expected) {
-      assertTrue(expected.getCause() instanceof SomeCheckedException);
+      assertThat(expected.getCause()).isInstanceOf(SomeCheckedException.class);
     }
   }
 
@@ -372,7 +378,7 @@ public class ThrowablesTest extends TestCase {
     try {
       sample.oneDeclared();
       fail();
-    } catch (SomeCheckedException e) {
+    } catch (SomeCheckedException expected) {
     }
   }
 
@@ -393,7 +399,7 @@ public class ThrowablesTest extends TestCase {
     try {
       sample.oneDeclared();
       fail();
-    } catch (SomeUncheckedException e) {
+    } catch (SomeUncheckedException expected) {
     }
   }
 
@@ -414,8 +420,8 @@ public class ThrowablesTest extends TestCase {
     try {
       sample.oneDeclared();
       fail();
-    } catch (RuntimeException e) {
-      assertTrue(e.getCause() instanceof SomeOtherCheckedException);
+    } catch (RuntimeException expected) {
+      assertThat(expected.getCause()).isInstanceOf(SomeOtherCheckedException.class);
     }
   }
 
@@ -489,7 +495,7 @@ public class ThrowablesTest extends TestCase {
     String secondLine = "\\s*at " + ThrowablesTest.class.getName() + "\\..*";
     String moreLines = "(?:.*\n?)*";
     String expected = firstLine + "\n" + secondLine + "\n" + moreLines;
-    assertTrue(getStackTraceAsString(e).matches(expected));
+    assertThat(getStackTraceAsString(e)).matches(expected);
   }
 
   public void testGetCausalChain() {
@@ -500,18 +506,74 @@ public class ThrowablesTest extends TestCase {
 
     assertEquals(asList(ex, re, iae, fnfe), Throwables.getCausalChain(ex));
     assertSame(fnfe, Iterables.getOnlyElement(Throwables.getCausalChain(fnfe)));
+
+    List<Throwable> causes = Throwables.getCausalChain(ex);
+    try {
+      causes.add(new RuntimeException());
+      fail("List should be unmodifiable");
+    } catch (UnsupportedOperationException expected) {
+    }
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testGetCasualChainNull() {
     try {
       Throwables.getCausalChain(null);
       fail("Should have throw NPE");
     } catch (NullPointerException expected) {
     }
+  }
+
+  @SuppressUnderAndroid // No getJavaLangAccess in Android (at least not in the version we use).
+  public void testLazyStackTraceWorksInProd() {
+    // Obviously this isn't guaranteed in every environment, but it works well enough for now:
+    assertTrue(lazyStackTraceIsLazy());
+  }
+
+  public void testLazyStackTrace() {
+    Exception e = new Exception();
+    StackTraceElement[] originalStackTrace = e.getStackTrace();
+
+    assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
 
-    List<Throwable> causes = Throwables.getCausalChain(ex);
     try {
-      causes.add(new RuntimeException());
-      fail("List should be unmodifiable");
+      lazyStackTrace(e).set(0, null);
+      fail();
     } catch (UnsupportedOperationException expected) {
     }
+
+    // Now we test a property that holds only for the lazy implementation.
+
+    if (!lazyStackTraceIsLazy()) {
+      return;
+    }
+
+    e.setStackTrace(new StackTraceElement[0]);
+    assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
+  }
+
+  private void doTestLazyStackTraceFallback() {
+    assertFalse(lazyStackTraceIsLazy());
+
+    Exception e = new Exception();
+
+    assertThat(lazyStackTrace(e)).containsExactly((Object[]) e.getStackTrace()).inOrder();
+
+    try {
+      lazyStackTrace(e).set(0, null);
+      fail();
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    e.setStackTrace(new StackTraceElement[0]);
+    assertThat(lazyStackTrace(e)).isEmpty();
+  }
+
+  private static class AllowSettingSecurityManagerPolicy extends Policy {
+    @Override
+    public boolean implies(ProtectionDomain pd, Permission perm) {
+      return true;
+    }
   }
 
   public void testNullPointers() {
diff --git a/guava-tests/test/com/google/common/base/Utf8Test.java b/guava-tests/test/com/google/common/base/Utf8Test.java
index f098123..88741e7 100644
--- a/guava-tests/test/com/google/common/base/Utf8Test.java
+++ b/guava-tests/test/com/google/common/base/Utf8Test.java
@@ -16,8 +16,17 @@
 
 package com.google.common.base;
 
+import static com.google.common.truth.Truth.assertThat;
+import static java.lang.Character.MAX_CODE_POINT;
+import static java.lang.Character.MAX_HIGH_SURROGATE;
+import static java.lang.Character.MAX_LOW_SURROGATE;
+import static java.lang.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.common.collect.ImmutableList;
 
 import junit.framework.TestCase;
 
@@ -34,6 +43,26 @@ import java.util.Random;
  */
 @GwtCompatible(emulated = true)
 public class Utf8Test extends TestCase {
+
+  private static final ImmutableList<String> ILL_FORMED_STRINGS;
+  static {
+    ImmutableList.Builder<String> builder = ImmutableList.builder();
+    char[] surrogates = {
+      MAX_LOW_SURROGATE,
+      MAX_HIGH_SURROGATE,
+      MIN_LOW_SURROGATE,
+      MIN_HIGH_SURROGATE,
+    };
+    for (char surrogate : surrogates) {
+      builder.add(newString(surrogate));
+      builder.add(newString(surrogate, 'n'));
+      builder.add(newString('n', surrogate));
+      builder.add(newString(surrogate, surrogate));
+    }
+    builder.add(newString(MIN_LOW_SURROGATE, MAX_HIGH_SURROGATE));
+    ILL_FORMED_STRINGS = builder.build();
+  }
+
   public void testEncodedLength_validStrings() {
     assertEquals(0, Utf8.encodedLength(""));
     assertEquals(11, Utf8.encodedLength("Hello world"));
@@ -45,11 +74,9 @@ public class Utf8Test extends TestCase {
         + "狹斯丕爾。[2]莎士比亞編寫過好多作品,佢嗰劇作響西洋文學好有影響,"
         + "哈都拕人翻譯做好多話。"));
     // A surrogate pair
-    assertEquals(4, Utf8.encodedLength(
-        newString(Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE)));
+    assertEquals(4, Utf8.encodedLength(newString(MIN_HIGH_SURROGATE, MIN_LOW_SURROGATE)));
   }
 
-  @GwtIncompatible("StringBuilder.appendCodePoint()")
   public void testEncodedLength_validStrings2() {
     HashMap<Integer, Integer> utf8Lengths = new HashMap<Integer, Integer>();
     utf8Lengths.put(0x00, 1);
@@ -57,9 +84,9 @@ public class Utf8Test extends TestCase {
     utf8Lengths.put(0x80, 2);
     utf8Lengths.put(0x7ff, 2);
     utf8Lengths.put(0x800, 3);
-    utf8Lengths.put(Character.MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
-    utf8Lengths.put(Character.MIN_SUPPLEMENTARY_CODE_POINT, 4);
-    utf8Lengths.put(Character.MAX_CODE_POINT, 4);
+    utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
+    utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT, 4);
+    utf8Lengths.put(MAX_CODE_POINT, 4);
 
     Integer[] codePoints = utf8Lengths.keySet().toArray(new Integer[]{});
     StringBuilder sb = new StringBuilder();
@@ -83,24 +110,21 @@ public class Utf8Test extends TestCase {
   }
 
   public void testEncodedLength_invalidStrings() {
-    testEncodedLengthFails(newString(Character.MIN_HIGH_SURROGATE), 0);
-    testEncodedLengthFails("foobar" + newString(Character.MIN_HIGH_SURROGATE), 6);
-    testEncodedLengthFails(newString(Character.MIN_LOW_SURROGATE), 0);
-    testEncodedLengthFails("foobar" + newString(Character.MIN_LOW_SURROGATE), 6);
-    testEncodedLengthFails(
-        newString(
-            Character.MIN_HIGH_SURROGATE,
-            Character.MIN_HIGH_SURROGATE), 0);
+    testEncodedLengthFails(newString(MIN_HIGH_SURROGATE), 0);
+    testEncodedLengthFails("foobar" + newString(MIN_HIGH_SURROGATE), 6);
+    testEncodedLengthFails(newString(MIN_LOW_SURROGATE), 0);
+    testEncodedLengthFails("foobar" + newString(MIN_LOW_SURROGATE), 6);
+    testEncodedLengthFails(newString(MIN_HIGH_SURROGATE, MIN_HIGH_SURROGATE), 0);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void testEncodedLengthFails(String invalidString,
       int invalidCodePointIndex) {
     try {
       Utf8.encodedLength(invalidString);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Unpaired surrogate at index " + invalidCodePointIndex,
-          expected.getMessage());
+      assertThat(expected).hasMessage("Unpaired surrogate at index " + invalidCodePointIndex);
     }
   }
 
@@ -174,6 +198,7 @@ public class Utf8Test extends TestCase {
 
   /** Tests that round tripping of all three byte permutations work. */
   @GwtIncompatible("java.nio.charset.Charset")
+
   public void testIsWellFormed_3Bytes() {
     testBytes(3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
   }
@@ -225,11 +250,11 @@ public class Utf8Test extends TestCase {
     assertEquals(EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
   }
 
-  private String newString(char... chars) {
+  private static String newString(char... chars) {
     return new String(chars);
   }
 
-  private byte[] toByteArray(int... bytes) {
+  private static byte[] toByteArray(int... bytes) {
     byte[] realBytes = new byte[bytes.length];
     for (int i = 0; i < bytes.length; i++) {
       realBytes[i] = (byte) bytes[i];
@@ -237,11 +262,11 @@ public class Utf8Test extends TestCase {
     return realBytes;
   }
 
-  private void assertWellFormed(int... bytes) {
+  private static void assertWellFormed(int... bytes) {
     assertTrue(Utf8.isWellFormed(toByteArray(bytes)));
   }
 
-  private void assertNotWellFormed(int... bytes) {
+  private static void assertNotWellFormed(int... bytes) {
     assertFalse(Utf8.isWellFormed(toByteArray(bytes)));
   }
 
diff --git a/guava-tests/test/com/google/common/base/VerifyTest.java b/guava-tests/test/com/google/common/base/VerifyTest.java
index bb08980..fb40263 100644
--- a/guava-tests/test/com/google/common/base/VerifyTest.java
+++ b/guava-tests/test/com/google/common/base/VerifyTest.java
@@ -16,6 +16,7 @@ package com.google.common.base;
 
 import static com.google.common.base.Verify.verify;
 import static com.google.common.base.Verify.verifyNotNull;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 
@@ -48,7 +49,7 @@ public class VerifyTest extends TestCase {
       verify(false, "message");
       fail();
     } catch (VerifyException expected) {
-      assertEquals("message", expected.getMessage());
+      assertThat(expected).hasMessage("message");
     }
   }
 
@@ -103,6 +104,6 @@ public class VerifyTest extends TestCase {
   private static final String FORMAT = "I ate %s pies.";
 
   private static void checkMessage(Exception e) {
-    assertEquals("I ate 5 pies.", e.getMessage());
+    assertThat(e).hasMessage("I ate 5 pies.");
   }
 }
diff --git a/guava-tests/test/com/google/common/cache/CacheBuilderTest.java b/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
index 1d882e6..3795db8 100644
--- a/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
@@ -22,6 +22,7 @@ import static com.google.common.cache.TestingRemovalListeners.countingRemovalLis
 import static com.google.common.cache.TestingRemovalListeners.nullRemovalListener;
 import static com.google.common.cache.TestingRemovalListeners.queuingRemovalListener;
 import static com.google.common.cache.TestingWeighers.constantWeigher;
+import static com.google.common.truth.Truth.assertThat;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
@@ -87,7 +88,7 @@ public class CacheBuilderTest extends TestCase {
         .build(identityLoader());
     LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
 
-    assertEquals(4, map.segments.length);
+    assertThat(map.segments).hasLength(4);
     assertEquals(2, map.segments[0].table.length());
     assertEquals(2, map.segments[1].table.length());
     assertEquals(2, map.segments[2].table.length());
@@ -101,7 +102,7 @@ public class CacheBuilderTest extends TestCase {
         .build(identityLoader());
     LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
 
-    assertEquals(4, map.segments.length);
+    assertThat(map.segments).hasLength(4);
     // 1 is as low as it goes, not 0. it feels dirty to know this/test this.
     assertEquals(1, map.segments[0].table.length());
     assertEquals(1, map.segments[1].table.length());
@@ -138,7 +139,7 @@ public class CacheBuilderTest extends TestCase {
         .concurrencyLevel(1)
         .build(identityLoader());
     LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
-    assertEquals(1, map.segments.length);
+    assertThat(map.segments).hasLength(1);
   }
 
   public void testConcurrencyLevel_large() {
@@ -218,15 +219,11 @@ public class CacheBuilderTest extends TestCase {
   @GwtIncompatible("weigher")
   public void testWeigher_withMaximumSize() {
     try {
-      CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
-          .weigher(constantWeigher(42))
-          .maximumSize(1);
+      new CacheBuilder<Object, Object>().weigher(constantWeigher(42)).maximumSize(1);
       fail();
     } catch (IllegalStateException expected) {}
     try {
-      CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
-          .maximumSize(1)
-          .weigher(constantWeigher(42));
+      new CacheBuilder<Object, Object>().maximumSize(1).weigher(constantWeigher(42));
       fail();
     } catch (IllegalStateException expected) {}
   }
@@ -363,6 +360,11 @@ public class CacheBuilderTest extends TestCase {
     } catch (IllegalStateException expected) {}
   }
 
+  public void testValuesIsNotASet() {
+    assertThat(new CacheBuilder<Object, Object>().build().asMap().values())
+        .isNotInstanceOf(Set.class);
+  }
+
   @GwtIncompatible("CacheTesting")
   public void testNullCache() {
     CountingRemovalListener<Object, Object> listener = countingRemovalListener();
@@ -606,7 +608,7 @@ public class CacheBuilderTest extends TestCase {
   public void testSizingDefaults() {
     LoadingCache<?, ?> cache = CacheBuilder.newBuilder().build(identityLoader());
     LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
-    assertEquals(4, map.segments.length); // concurrency level
+    assertThat(map.segments).hasLength(4); // concurrency level
     assertEquals(4, map.segments[0].table.length()); // capacity / conc level
   }
 
diff --git a/guava-tests/test/com/google/common/cache/CacheEvictionTest.java b/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
index 351af8b..041a212 100644
--- a/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
@@ -18,6 +18,7 @@ import static com.google.common.cache.TestingCacheLoaders.identityLoader;
 import static com.google.common.cache.TestingRemovalListeners.countingRemovalListener;
 import static com.google.common.cache.TestingWeighers.constantWeigher;
 import static com.google.common.cache.TestingWeighers.intKeyWeigher;
+import static com.google.common.cache.TestingWeighers.intValueWeigher;
 import static com.google.common.truth.Truth.assertThat;
 import static java.util.Arrays.asList;
 
@@ -131,6 +132,116 @@ public class CacheEvictionTest extends TestCase {
     CacheTesting.checkValidState(cache);
   }
 
+  /**
+   * With an unlimited-size cache with maxWeight of 0, entries weighing 0 should still be cached.
+   * Entries with positive weight should not be cached (nor dump existing cache).
+   */
+  public void testEviction_maxWeight_zero() {
+    CountingRemovalListener<Integer, Integer> removalListener = countingRemovalListener();
+    IdentityLoader<Integer> loader = identityLoader();
+
+    // Even numbers are free, odd are too expensive
+    Weigher<Integer, Integer> evensOnly =
+        new Weigher<Integer, Integer>() {
+          @Override public int weigh(Integer k, Integer v) {
+            return k % 2;
+          }
+        };
+
+    LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
+        .concurrencyLevel(1)
+        .maximumWeight(0)
+        .weigher(evensOnly)
+        .removalListener(removalListener)
+        .build(loader);
+
+    // 1 won't be cached
+    assertThat(cache.getUnchecked(1)).isEqualTo(1);
+    assertThat(cache.asMap().keySet()).isEmpty();
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(1);
+
+    // 2 will be cached
+    assertThat(cache.getUnchecked(2)).isEqualTo(2);
+    assertThat(cache.asMap().keySet()).containsExactly(2);
+
+    CacheTesting.processPendingNotifications(cache);
+    CacheTesting.checkValidState(cache);
+    assertThat(removalListener.getCount()).isEqualTo(1);
+
+    // 4 will be cached
+    assertThat(cache.getUnchecked(4)).isEqualTo(4);
+    assertThat(cache.asMap().keySet()).containsExactly(2, 4);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(1);
+
+    // 5 won't be cached, won't dump cache
+    assertThat(cache.getUnchecked(5)).isEqualTo(5);
+    assertThat(cache.asMap().keySet()).containsExactly(2, 4);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(2);
+
+    // Should we pepper more of these calls throughout the above? Where?
+    CacheTesting.checkValidState(cache);
+  }
+
+  /**
+   * Tests that when a single entry exceeds the segment's max weight, the new entry is
+   * immediately evicted and nothing else.
+   */
+  public void testEviction_maxWeight_entryTooBig() {
+    CountingRemovalListener<Integer, Integer> removalListener = countingRemovalListener();
+    IdentityLoader<Integer> loader = identityLoader();
+
+    LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
+        .concurrencyLevel(1)
+        .maximumWeight(4)
+        .weigher(intValueWeigher())
+        .removalListener(removalListener)
+        .build(loader);
+
+    // caches 2
+    assertThat(cache.getUnchecked(2)).isEqualTo(2);
+    assertThat(cache.asMap().keySet()).containsExactly(2);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(0);
+
+    // caches 3, evicts 2
+    assertThat(cache.getUnchecked(3)).isEqualTo(3);
+    assertThat(cache.asMap().keySet()).containsExactly(3);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(1);
+
+    // doesn't cache 5, doesn't evict
+    assertThat(cache.getUnchecked(5)).isEqualTo(5);
+    assertThat(cache.asMap().keySet()).containsExactly(3);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(2);
+
+    // caches 1, evicts nothing
+    assertThat(cache.getUnchecked(1)).isEqualTo(1);
+    assertThat(cache.asMap().keySet()).containsExactly(3, 1);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(2);
+
+    // caches 4, evicts 1 and 3
+    assertThat(cache.getUnchecked(4)).isEqualTo(4);
+    assertThat(cache.asMap().keySet()).containsExactly(4);
+
+    CacheTesting.processPendingNotifications(cache);
+    assertThat(removalListener.getCount()).isEqualTo(4);
+
+    // Should we pepper more of these calls throughout the above? Where?
+    CacheTesting.checkValidState(cache);
+  }
+
   public void testEviction_overflow() {
     CountingRemovalListener<Object, Object> removalListener = countingRemovalListener();
     IdentityLoader<Object> loader = identityLoader();
@@ -184,27 +295,27 @@ public class CacheEvictionTest extends TestCase {
         .build(loader);
     CacheTesting.warmUp(cache, 0, 10);
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // re-order
     getAll(cache, asList(0, 1, 2));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+    assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
 
     // evict 3, 4, 5
     getAll(cache, asList(10, 11, 12));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 1, 2, 10, 11, 12);
+    assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 1, 2, 10, 11, 12);
 
     // re-order
     getAll(cache, asList(6, 7, 8));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(9, 0, 1, 2, 10, 11, 12, 6, 7, 8);
+    assertThat(keySet).containsExactly(9, 0, 1, 2, 10, 11, 12, 6, 7, 8);
 
     // evict 9, 0, 1
     getAll(cache, asList(13, 14, 15));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(2, 10, 11, 12, 6, 7, 8, 13, 14, 15);
+    assertThat(keySet).containsExactly(2, 10, 11, 12, 6, 7, 8, 13, 14, 15);
   }
 
   public void testEviction_weightedLru() {
@@ -217,37 +328,37 @@ public class CacheEvictionTest extends TestCase {
         .build(loader);
     CacheTesting.warmUp(cache, 0, 10);
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // re-order
     getAll(cache, asList(0, 1, 2));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+    assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
 
     // evict 3, 4, 5
     getAll(cache, asList(10));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 1, 2, 10);
+    assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 1, 2, 10);
 
     // re-order
     getAll(cache, asList(6, 7, 8));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(9, 0, 1, 2, 10, 6, 7, 8);
+    assertThat(keySet).containsExactly(9, 0, 1, 2, 10, 6, 7, 8);
 
     // evict 9, 1, 2, 10
     getAll(cache, asList(15));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(0, 6, 7, 8, 15);
+    assertThat(keySet).containsExactly(0, 6, 7, 8, 15);
 
     // fill empty space
     getAll(cache, asList(9));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(0, 6, 7, 8, 15, 9);
+    assertThat(keySet).containsExactly(0, 6, 7, 8, 15, 9);
 
     // evict 6
     getAll(cache, asList(1));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(0, 7, 8, 15, 9, 1);
+    assertThat(keySet).containsExactly(0, 7, 8, 15, 9, 1);
   }
 
   public void testEviction_overweight() {
@@ -260,17 +371,17 @@ public class CacheEvictionTest extends TestCase {
         .build(loader);
     CacheTesting.warmUp(cache, 0, 10);
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // add an at-the-maximum-weight entry
     getAll(cache, asList(45));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(0, 45);
+    assertThat(keySet).containsExactly(0, 45);
 
     // add an over-the-maximum-weight entry
     getAll(cache, asList(46));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().item(0);
+    assertThat(keySet).contains(0);
   }
 
   public void testEviction_invalidateAll() {
@@ -287,7 +398,7 @@ public class CacheEvictionTest extends TestCase {
     // add 0, 1, 2, 3, 4
     getAll(cache, asList(0, 1, 2, 3, 4));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4);
 
     // invalidate all
     cache.invalidateAll();
@@ -297,7 +408,7 @@ public class CacheEvictionTest extends TestCase {
     // add 5, 6, 7, 8, 9, 10, 11, 12
     getAll(cache, asList(5, 6, 7, 8, 9, 10, 11, 12));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 10, 11, 12);
+    assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 10, 11, 12);
   }
 
   private void getAll(LoadingCache<Integer, Integer> cache, List<Integer> keys) {
diff --git a/guava-tests/test/com/google/common/cache/CacheExpirationTest.java b/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
index b5c8266..c2c221e 100644
--- a/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
@@ -260,42 +260,42 @@ public class CacheExpirationTest extends TestCase {
       ticker.advance(1, MILLISECONDS);
     }
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // 0 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // reorder
     getAll(cache, asList(0, 1, 2));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(2, MILLISECONDS);
-    assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+    assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
 
     // 3 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(4, 5, 6, 7, 8, 9, 0, 1, 2);
+    assertThat(keySet).containsExactly(4, 5, 6, 7, 8, 9, 0, 1, 2);
 
     // reorder
     getAll(cache, asList(5, 7, 9));
     CacheTesting.drainRecencyQueues(cache);
-    assertThat(keySet).has().exactly(4, 6, 8, 0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(4, 6, 8, 0, 1, 2, 5, 7, 9);
 
     // 4 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(6, 8, 0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(6, 8, 0, 1, 2, 5, 7, 9);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(6, 8, 0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(6, 8, 0, 1, 2, 5, 7, 9);
 
     // 6 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(8, 0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(8, 0, 1, 2, 5, 7, 9);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(8, 0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(8, 0, 1, 2, 5, 7, 9);
 
     // 8 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(0, 1, 2, 5, 7, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 5, 7, 9);
   }
 
   public void testExpirationOrder_write() throws ExecutionException {
@@ -312,37 +312,37 @@ public class CacheExpirationTest extends TestCase {
       ticker.advance(1, MILLISECONDS);
     }
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // 0 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // get doesn't stop 1 from expiring
     getAll(cache, asList(0, 1, 2));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(2, 3, 4, 5, 6, 7, 8, 9, 0);
+    assertThat(keySet).containsExactly(2, 3, 4, 5, 6, 7, 8, 9, 0);
 
     // get(K, Callable) doesn't stop 2 from expiring
     cache.get(2, Callables.returning(-2));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0);
+    assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0);
 
     // asMap.put saves 3
     cache.asMap().put(3, -3);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(4, 5, 6, 7, 8, 9, 0, 3);
+    assertThat(keySet).containsExactly(4, 5, 6, 7, 8, 9, 0, 3);
 
     // asMap.replace saves 4
     cache.asMap().replace(4, -4);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 0, 3, 4);
+    assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 0, 3, 4);
 
     // 5 expires
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 3, 4);
+    assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 3, 4);
   }
 
   public void testExpirationOrder_writeAccess() throws ExecutionException {
@@ -365,33 +365,33 @@ public class CacheExpirationTest extends TestCase {
     ticker.advance(1, MILLISECONDS);
 
     Set<Integer> keySet = cache.asMap().keySet();
-    assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 
     // get saves 1, 3; 0, 2, 4 expire
     getAll(cache, asList(1, 3));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 1, 3);
+    assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 1, 3);
 
     // get saves 6, 8; 5, 7, 9 expire
     getAll(cache, asList(6, 8));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(1, 3, 6, 8);
+    assertThat(keySet).containsExactly(1, 3, 6, 8);
 
     // get fails to save 1, put saves 3
     cache.asMap().put(3, -3);
     getAll(cache, asList(1));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(6, 8, 3);
+    assertThat(keySet).containsExactly(6, 8, 3);
 
     // get(K, Callable) fails to save 8, replace saves 6
     cache.asMap().replace(6, -6);
     cache.get(8, Callables.returning(-8));
     CacheTesting.drainRecencyQueues(cache);
     ticker.advance(1, MILLISECONDS);
-    assertThat(keySet).has().exactly(3, 6);
+    assertThat(keySet).containsExactly(3, 6);
   }
 
   private void runRemovalScheduler(LoadingCache<String, Integer> cache,
diff --git a/guava-tests/test/com/google/common/cache/CacheLoadingTest.java b/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
index a08114d..3cf35b1 100644
--- a/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
@@ -96,7 +96,7 @@ public class CacheLoadingTest extends TestCase {
   }
 
   private void checkLoggedInvalidLoad() {
-    assertTrue(popLoggedThrowable() instanceof InvalidCacheLoadException);
+    assertThat(popLoggedThrowable()).isInstanceOf(InvalidCacheLoadException.class);
   }
 
   public void testLoad() throws ExecutionException {
@@ -440,7 +440,7 @@ public class CacheLoadingTest extends TestCase {
 
     Object[] lookupKeys = new Object[] { new Object(), new Object(), new Object() };
     Map<Object, Object> result = cache.getAll(asList(lookupKeys));
-    assertThat(result.keySet()).has().exactlyAs(asList(lookupKeys));
+    assertThat(result.keySet()).containsExactlyElementsIn(asList(lookupKeys));
     for (Map.Entry<Object, Object> entry : result.entrySet()) {
       Object key = entry.getKey();
       Object value = entry.getValue();
@@ -477,7 +477,7 @@ public class CacheLoadingTest extends TestCase {
 
     Object[] lookupKeys = new Object[] { new Object(), new Object(), new Object() };
     Map<Object, Object> result = cache.getAll(asList(lookupKeys));
-    assertThat(result.keySet()).has().exactlyAs(asList(lookupKeys));
+    assertThat(result.keySet()).containsExactlyElementsIn(asList(lookupKeys));
     for (Map.Entry<Object, Object> entry : result.entrySet()) {
       Object key = entry.getKey();
       Object value = entry.getValue();
@@ -1983,7 +1983,7 @@ public class CacheLoadingTest extends TestCase {
 
     assertEquals(1, callCount.get());
     for (int i = 0; i < count; i++) {
-      assertTrue(result.get(i) instanceof InvalidCacheLoadException);
+      assertThat(result.get(i)).isInstanceOf(InvalidCacheLoadException.class);
     }
 
     // subsequent calls should call the loader again, not get the old exception
@@ -2023,7 +2023,7 @@ public class CacheLoadingTest extends TestCase {
     for (int i = 0; i < count; i++) {
       // doConcurrentGet alternates between calling getUnchecked and calling get, but an unchecked
       // exception thrown by the loader is always wrapped as an UncheckedExecutionException.
-      assertTrue(result.get(i) instanceof UncheckedExecutionException);
+      assertThat(result.get(i)).isInstanceOf(UncheckedExecutionException.class);
       assertSame(e, ((UncheckedExecutionException) result.get(i)).getCause());
     }
 
@@ -2067,10 +2067,10 @@ public class CacheLoadingTest extends TestCase {
       // UncheckedExecutionException.
       int mod = i % 3;
       if (mod == 0 || mod == 2) {
-        assertTrue(result.get(i) instanceof ExecutionException);
+        assertThat(result.get(i)).isInstanceOf(ExecutionException.class);
         assertSame(e, ((ExecutionException) result.get(i)).getCause());
       } else {
-        assertTrue(result.get(i) instanceof UncheckedExecutionException);
+        assertThat(result.get(i)).isInstanceOf(UncheckedExecutionException.class);
         assertSame(e, ((UncheckedExecutionException) result.get(i)).getCause());
       }
     }
@@ -2413,7 +2413,11 @@ public class CacheLoadingTest extends TestCase {
     assertEquals("barfoo", cache.getUnchecked(key));
   }
 
-  public void testExpandDuringRefresh() throws InterruptedException, ExecutionException {
+  // Test ignored because it is extremely flaky in CI builds
+
+  public void
+      ignoreTestExpandDuringRefresh()
+      throws InterruptedException, ExecutionException {
     final AtomicInteger callCount = new AtomicInteger();
     // tells the computing thread when to start computing
     final CountDownLatch computeSignal = new CountDownLatch(1);
diff --git a/guava-tests/test/com/google/common/cache/CacheReferencesTest.java b/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
index 88d6b23..0750f74 100644
--- a/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
@@ -94,7 +94,7 @@ public class CacheReferencesTest extends TestCase {
       assertSame(value1, cache.getUnchecked(key1));
       assertSame(value2, cache.getUnchecked(key2));
       assertEquals(ImmutableSet.of(key1, key2), cache.asMap().keySet());
-      assertThat(cache.asMap().values()).has().exactly(value1, value2);
+      assertThat(cache.asMap().values()).containsExactly(value1, value2);
       assertEquals(ImmutableSet.of(immutableEntry(key1, value1), immutableEntry(key2, value2)),
           cache.asMap().entrySet());
     }
@@ -113,7 +113,7 @@ public class CacheReferencesTest extends TestCase {
       assertTrue(cache.asMap().containsKey(key2));
       assertEquals(1, cache.size());
       assertEquals(ImmutableSet.of(key2), cache.asMap().keySet());
-      assertThat(cache.asMap().values()).has().item(value2);
+      assertThat(cache.asMap().values()).contains(value2);
       assertEquals(ImmutableSet.of(immutableEntry(key2, value2)), cache.asMap().entrySet());
     }
   }
diff --git a/guava-tests/test/com/google/common/cache/CacheTesting.java b/guava-tests/test/com/google/common/cache/CacheTesting.java
index 660fecd..83614da 100644
--- a/guava-tests/test/com/google/common/cache/CacheTesting.java
+++ b/guava-tests/test/com/google/common/cache/CacheTesting.java
@@ -15,6 +15,7 @@
 package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.truth.Truth.assertThat;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -199,7 +200,7 @@ class CacheTesting {
       // cleanup and then check count after we have a strong reference to all entries
       segment.cleanUp();
       // under high memory pressure keys/values may be nulled out but not yet enqueued
-      assertTrue(table.size() <= segment.count);
+      assertThat(table.size()).isAtMost(segment.count);
       for (Entry<?, ?> entry : table.entrySet()) {
         assertNotNull(entry.getKey());
         assertNotNull(entry.getValue());
@@ -232,7 +233,7 @@ class CacheTesting {
           if (prev != null) {
             assertSame(prev, current.getPreviousInWriteQueue());
             assertSame(prev.getNextInWriteQueue(), current);
-            assertTrue(prev.getWriteTime() <= current.getWriteTime());
+            assertThat(prev.getWriteTime()).isAtMost(current.getWriteTime());
           }
           Object key = current.getKey();
           if (key != null) {
@@ -480,8 +481,8 @@ class CacheTesting {
     assertTrue(collection.isEmpty());
     assertEquals(0, collection.size());
     assertFalse(collection.iterator().hasNext());
-    assertEquals(0, collection.toArray().length);
-    assertEquals(0, collection.toArray(new Object[0]).length);
+    assertThat(collection.toArray()).isEmpty();
+    assertThat(collection.toArray(new Object[0])).isEmpty();
     if (collection instanceof Set) {
       new EqualsTester()
           .addEqualityGroup(ImmutableSet.of(), collection)
diff --git a/guava-tests/test/com/google/common/cache/LocalCacheTest.java b/guava-tests/test/com/google/common/cache/LocalCacheTest.java
index 7e1d614..c959d54 100644
--- a/guava-tests/test/com/google/common/cache/LocalCacheTest.java
+++ b/guava-tests/test/com/google/common/cache/LocalCacheTest.java
@@ -27,6 +27,7 @@ import static com.google.common.cache.TestingRemovalListeners.queuingRemovalList
 import static com.google.common.cache.TestingWeighers.constantWeigher;
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.immutableEntry;
+import static com.google.common.truth.Truth.assertThat;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -49,7 +50,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.testing.MapTestSuiteBuilder;
+import com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder;
 import com.google.common.collect.testing.TestStringMapGenerator;
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
@@ -83,21 +84,101 @@ import java.util.logging.LogRecord;
  * @author Charles Fry
  */
 public class LocalCacheTest extends TestCase {
+  private static class TestStringCacheGenerator extends TestStringMapGenerator {
+    private final CacheBuilder<? super String, ? super String> builder;
+
+    TestStringCacheGenerator(CacheBuilder<? super String, ? super String> builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    protected Map<String, String> create(Entry<String, String>[] entries) {
+      LocalCache<String, String> map = makeLocalCache(builder);
+      for (Entry<String, String> entry : entries) {
+        map.put(entry.getKey(), entry.getValue());
+      }
+      return map;
+    }
+  }
 
   public static Test suite() {
     TestSuite suite = new TestSuite();
     suite.addTestSuite(LocalCacheTest.class);
-    suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
-          @Override public Map<String, String> create(
-              Entry<String, String>[] entries) {
-            LocalCache<String, String> map = makeLocalCache(createCacheBuilder());
-            for (Entry<String, String> entry : entries) {
-              map.put(entry.getKey(), entry.getValue());
-            }
-            return map;
-          }
-
-        }).named("LocalCache with defaults")
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(createCacheBuilder()))
+        .named("LocalCache with defaults")
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().concurrencyLevel(1)))
+        .named("LocalCache with concurrencyLevel[1]")
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().maximumSize(Integer.MAX_VALUE)))
+        .named("LocalCache with maximumSize")
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder()
+                .maximumWeight(Integer.MAX_VALUE)
+                .weigher(new SerializableWeigher<String, String>())))
+        .named("LocalCache with maximumWeight")
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().weakKeys()))
+        .named("LocalCache with weakKeys") // keys are string literals and won't be GC'd
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().weakValues()))
+        .named("LocalCache with weakValues") // values are string literals and won't be GC'd
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().softValues()))
+        .named("LocalCache with softValues") // values are string literals and won't be GC'd
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().expireAfterAccess(1, SECONDS).ticker(new SerializableTicker())))
+        .named("LocalCache with expireAfterAccess") // SerializableTicker never advances
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder().expireAfterWrite(1, SECONDS).ticker(new SerializableTicker())))
+        .named("LocalCache with expireAfterWrite") // SerializableTicker never advances
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(
+            createCacheBuilder()
+                .removalListener(new SerializableRemovalListener<String, String>())))
+        .named("LocalCache with removalListener")
+        .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+            CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+        .createTestSuite());
+    suite.addTest(ConcurrentMapTestSuiteBuilder
+        .using(new TestStringCacheGenerator(createCacheBuilder().recordStats()))
+        .named("LocalCache with recordStats")
         .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
             CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
         .createTestSuite());
@@ -169,7 +250,7 @@ public class LocalCacheTest extends TestCase {
     assertEquals(4, map.concurrencyLevel);
 
     // concurrency level
-    assertEquals(4, map.segments.length);
+    assertThat(map.segments).hasLength(4);
     // initial capacity / concurrency level
     assertEquals(16 / map.segments.length, map.segments[0].table.length());
 
@@ -234,7 +315,7 @@ public class LocalCacheTest extends TestCase {
   private static void checkConcurrencyLevel(int concurrencyLevel, int segmentCount) {
     LocalCache<Object, Object> map =
         makeLocalCache(createCacheBuilder().concurrencyLevel(concurrencyLevel));
-    assertEquals(segmentCount, map.segments.length);
+    assertThat(map.segments).hasLength(segmentCount);
   }
 
   public void testSetInitialCapacity() {
@@ -581,7 +662,7 @@ public class LocalCacheTest extends TestCase {
     map.put("foo", "bar");
     map.put("baz", "bar");
     map.put("quux", "quux");
-    assertFalse(map.values() instanceof Set);
+    assertThat(map.values()).isNotInstanceOf(Set.class);
     assertTrue(map.values().removeAll(ImmutableSet.of("bar")));
     assertEquals(1, map.size());
   }
@@ -2248,7 +2329,7 @@ public class LocalCacheTest extends TestCase {
       it.next();
       it.remove();
     }
-    segment.evictEntries();
+    segment.evictEntries(entry);
     assertEquals(maxSize, map.size());
     assertEquals(originalMap, map);
   }
diff --git a/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java b/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
index 5ae1b45..0c07b94 100644
--- a/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
+++ b/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
@@ -160,17 +160,17 @@ public class LocalLoadingCacheTest extends TestCase {
     assertNull(map.put(three, one));
     assertNull(map.put(one, two));
 
-    assertThat(map).hasKey(three).withValue(one);
-    assertThat(map).hasKey(one).withValue(two);
+    assertThat(map).containsEntry(three, one);
+    assertThat(map).containsEntry(one, two);
 
-    //TODO(user): Confirm with fry@ that this is a reasonable substitute.
+    //TODO(cgruber): Confirm with fry@ that this is a reasonable substitute.
     //Set<Map.Entry<Object, Object>> entries = map.entrySet();
-    //assertThat(entries).has().exactly(
+    //assertThat(entries).containsExactly(
     //    Maps.immutableEntry(three, one), Maps.immutableEntry(one, two));
     //Set<Object> keys = map.keySet();
-    //assertThat(keys).has().exactly(one, three);
+    //assertThat(keys).containsExactly(one, three);
     //Collection<Object> values = map.values();
-    //assertThat(values).has().exactly(one, two);
+    //assertThat(values).containsExactly(one, two);
 
     map.clear();
 
diff --git a/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java b/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
index d7fee82..a98238b 100644
--- a/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
+++ b/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
@@ -195,9 +195,9 @@ public class PopulatedCachesTest extends TestCase {
       List<Entry<Object, Object>> warmed = warmUp(cache);
 
       Set<Object> expected = Maps.newHashMap(cache.asMap()).keySet();
-      assertThat(keys).has().exactlyAs(expected);
-      assertThat(keys.toArray()).asList().has().exactlyAs(expected);
-      assertThat(keys.toArray(new Object[0])).asList().has().exactlyAs(expected);
+      assertThat(keys).containsExactlyElementsIn(expected);
+      assertThat(keys.toArray()).asList().containsExactlyElementsIn(expected);
+      assertThat(keys.toArray(new Object[0])).asList().containsExactlyElementsIn(expected);
 
       new EqualsTester()
           .addEqualityGroup(cache.asMap().keySet(), keys)
@@ -222,9 +222,9 @@ public class PopulatedCachesTest extends TestCase {
       List<Entry<Object, Object>> warmed = warmUp(cache);
 
       Collection<Object> expected = Maps.newHashMap(cache.asMap()).values();
-      assertThat(values).has().exactlyAs(expected);
-      assertThat(values.toArray()).asList().has().exactlyAs(expected);
-      assertThat(values.toArray(new Object[0])).asList().has().exactlyAs(expected);
+      assertThat(values).containsExactlyElementsIn(expected);
+      assertThat(values.toArray()).asList().containsExactlyElementsIn(expected);
+      assertThat(values.toArray(new Object[0])).asList().containsExactlyElementsIn(expected);
 
       assertEquals(WARMUP_SIZE, values.size());
       for (int i = WARMUP_MIN; i < WARMUP_MAX; i++) {
@@ -247,10 +247,13 @@ public class PopulatedCachesTest extends TestCase {
       List<Entry<Object, Object>> warmed = warmUp(cache, WARMUP_MIN, WARMUP_MAX);
 
       Set<?> expected = Maps.newHashMap(cache.asMap()).entrySet();
-      assertThat(entries).has().exactlyAs((Collection<Entry<Object, Object>>) expected);
-      assertThat(entries.toArray()).asList().has().exactlyAs((Collection<Object>) expected);
-      assertThat(entries.toArray(new Entry[0])).asList()
-          .has().exactlyAs((Collection<Entry>) expected);
+      assertThat(entries).containsExactlyElementsIn((Collection<Entry<Object, Object>>) expected);
+      assertThat(entries.toArray())
+          .asList()
+          .containsExactlyElementsIn((Collection<Object>) expected);
+      assertThat(entries.toArray(new Entry[0]))
+          .asList()
+          .containsExactlyElementsIn((Collection<Entry>) expected);
 
       new EqualsTester()
           .addEqualityGroup(cache.asMap().entrySet(), entries)
diff --git a/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java b/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
index 0932829..273f0e1 100644
--- a/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
+++ b/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
@@ -30,12 +30,12 @@ public class RemovalNotificationTest extends TestCase {
   public void testEquals() {
     new EqualsTester()
         .addEqualityGroup(
-            new RemovalNotification<String, Integer>("one", 1, RemovalCause.EXPLICIT),
-            new RemovalNotification<String, Integer>("one", 1, RemovalCause.REPLACED))
+            RemovalNotification.create("one", 1, RemovalCause.EXPLICIT),
+            RemovalNotification.create("one", 1, RemovalCause.REPLACED))
         .addEqualityGroup(
-            new RemovalNotification<String, Integer>("1", 1, RemovalCause.EXPLICIT))
+            RemovalNotification.create("1", 1, RemovalCause.EXPLICIT))
         .addEqualityGroup(
-            new RemovalNotification<String, Integer>("one", 2, RemovalCause.EXPLICIT))
+            RemovalNotification.create("one", 2, RemovalCause.EXPLICIT))
         .testEquals();
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java b/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
index ea309f4..854eb74 100644
--- a/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
@@ -295,7 +295,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .add("d", "e", "f")
         .add("g", "h", "i", "j")
         .build();
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j").inOrder();
   }
 
@@ -303,9 +303,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
     ImmutableSet.Builder<String> builder = this.<String>builder()
         .add("a")
         .add("b");
-    assertThat(builder.build()).has().exactly("a", "b").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b").inOrder();
     builder.add("c", "d");
-    assertThat(builder.build()).has().exactly("a", "b", "c", "d").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b", "c", "d").inOrder();
   }
 
   public void testBuilderWithDuplicateElements() {
@@ -325,9 +325,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .add("a")
         .add("a", "a")
         .add("b");
-    assertThat(builder.build()).has().exactly("a", "b").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b").inOrder();
     builder.add("a", "b", "c", "c");
-    assertThat(builder.build()).has().exactly("a", "b", "c").inOrder();
+    assertThat(builder.build()).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testBuilderAddAll() {
@@ -337,7 +337,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
         .addAll(a)
         .addAll(b)
         .build();
-    assertThat(set).has().exactly("a", "b", "c", "d", "e").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e").inOrder();
   }
 
   static final int LAST_COLOR_ADDED = 0x00BFFF;
diff --git a/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java b/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
index 1a44e87..26e71ed 100644
--- a/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
@@ -36,7 +36,9 @@ public abstract class AbstractRangeSetTest extends TestCase {
 
   private static <C extends Comparable> void testInvariantsInternal(RangeSet<C> rangeSet) {
     assertEquals(rangeSet.asRanges().isEmpty(), rangeSet.isEmpty());
+    assertEquals(rangeSet.asDescendingSetOfRanges().isEmpty(), rangeSet.isEmpty());
     assertEquals(!rangeSet.asRanges().iterator().hasNext(), rangeSet.isEmpty());
+    assertEquals(!rangeSet.asDescendingSetOfRanges().iterator().hasNext(), rangeSet.isEmpty());
 
     List<Range<C>> asRanges = ImmutableList.copyOf(rangeSet.asRanges());
 
@@ -52,6 +54,7 @@ public abstract class AbstractRangeSetTest extends TestCase {
       assertFalse(range.isEmpty());
     }
 
+    // test that the RangeSet's span is the span of all the ranges
     Iterator<Range<C>> itr = rangeSet.asRanges().iterator();
     Range<C> expectedSpan = null;
     if (itr.hasNext()) {
@@ -67,5 +70,8 @@ public abstract class AbstractRangeSetTest extends TestCase {
     } catch (NoSuchElementException e) {
       assertNull(expectedSpan);
     }
+
+    // test that asDescendingSetOfRanges is the reverse of asRanges
+    assertEquals(Lists.reverse(asRanges), ImmutableList.copyOf(rangeSet.asDescendingSetOfRanges()));
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java b/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
index 83b3900..0892847 100644
--- a/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
@@ -50,7 +50,7 @@ public class AbstractSequentialIteratorTest extends TestCase {
         return newDoubler(2, 32);
       }
     };
-    assertThat(doubled).iteratesAs(2, 4, 8, 16, 32);
+    assertThat(doubled).containsExactly(2, 4, 8, 16, 32).inOrder();
   }
 
   public void testSampleCode() {
@@ -65,9 +65,11 @@ public class AbstractSequentialIteratorTest extends TestCase {
         return powersOfTwo;
       }
     };
-    assertThat(actual).iteratesAs(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
-        4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
-        8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824);
+    assertThat(actual)
+        .containsExactly(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
+            32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216,
+            33554432, 67108864, 134217728, 268435456, 536870912, 1073741824)
+        .inOrder();
   }
 
   public void testEmpty() {
diff --git a/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java b/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
index 45a08c5..d5fd444 100644
--- a/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
@@ -183,7 +183,7 @@ public abstract class AbstractTableReadTest extends TestCase {
   public void testColumnSetPartialOverlap() {
     table = create(
         "foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd');
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3);
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3);
   }
 
   @GwtIncompatible("NullPointerTester")
diff --git a/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java b/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
index 6a567d8..a7b4ba0 100644
--- a/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
@@ -119,9 +119,9 @@ public class ArrayListMultimapTest extends TestCase {
     ListMultimap<String, Integer> multimap = create();
     multimap.putAll("foo", asList(1, 2, 3, 4, 5));
     List<Integer> list = multimap.get("foo");
-    assertThat(multimap.get("foo")).has().exactly(1, 2, 3, 4, 5).inOrder();
+    assertThat(multimap.get("foo")).containsExactly(1, 2, 3, 4, 5).inOrder();
     List<Integer> sublist = list.subList(0, 5);
-    assertThat(sublist).has().exactly(1, 2, 3, 4, 5).inOrder();
+    assertThat(sublist).containsExactly(1, 2, 3, 4, 5).inOrder();
 
     sublist.clear();
     assertTrue(sublist.isEmpty());
@@ -190,7 +190,7 @@ public class ArrayListMultimapTest extends TestCase {
     multimap.put("bar", 3);
     multimap.trimToSize();
     assertEquals(3, multimap.size());
-    assertThat(multimap.get("foo")).has().exactly(1, 2).inOrder();
-    assertThat(multimap.get("bar")).has().item(3);
+    assertThat(multimap.get("foo")).containsExactly(1, 2).inOrder();
+    assertThat(multimap.get("bar")).contains(3);
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/ArrayTableTest.java b/guava-tests/test/com/google/common/collect/ArrayTableTest.java
index c535619..bf68e09 100644
--- a/guava-tests/test/com/google/common/collect/ArrayTableTest.java
+++ b/guava-tests/test/com/google/common/collect/ArrayTableTest.java
@@ -286,13 +286,13 @@ public class ArrayTableTest extends AbstractTableTest {
   public void testRowKeyList() {
     ArrayTable<String, Integer, Character> table
         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
-    assertThat(table.rowKeyList()).has().exactly("foo", "bar", "cat").inOrder();
+    assertThat(table.rowKeyList()).containsExactly("foo", "bar", "cat").inOrder();
   }
 
   public void testColumnKeyList() {
     ArrayTable<String, Integer, Character> table
         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
-    assertThat(table.columnKeyList()).has().exactly(1, 2, 3).inOrder();
+    assertThat(table.columnKeyList()).containsExactly(1, 2, 3).inOrder();
   }
 
   public void testGetMissingKeys() {
@@ -369,13 +369,13 @@ public class ArrayTableTest extends AbstractTableTest {
       table.put("dog", 1, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+      assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
     }
     try {
       table.put("foo", 4, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+      assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
     }
     assertFalse(table.containsValue('d'));
   }
@@ -399,10 +399,10 @@ public class ArrayTableTest extends AbstractTableTest {
     ArrayTable<String, Integer, Character> table
         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
     Character[][] array = table.toArray(Character.class);
-    assertEquals(3, array.length);
-    assertThat(array[0]).asList().has().exactly('a', null, 'c').inOrder();
-    assertThat(array[1]).asList().has().exactly('b', null, null).inOrder();
-    assertThat(array[2]).asList().has().exactly(null, null, null).inOrder();
+    assertThat(array).hasLength(3);
+    assertThat(array[0]).asList().containsExactly('a', null, 'c').inOrder();
+    assertThat(array[1]).asList().containsExactly('b', null, null).inOrder();
+    assertThat(array[2]).asList().containsExactly(null, null, null).inOrder();
     table.set(0, 2, 'd');
     assertEquals((Character) 'c', array[0][2]);
     array[0][2] = 'e';
@@ -444,7 +444,7 @@ public class ArrayTableTest extends AbstractTableTest {
       map.put(4, 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+      assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
     }
   }
 
@@ -455,7 +455,7 @@ public class ArrayTableTest extends AbstractTableTest {
       map.put("dog", 'd');
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+      assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/collect/Collections2Test.java b/guava-tests/test/com/google/common/collect/Collections2Test.java
index 83d9014..2968ddf 100644
--- a/guava-tests/test/com/google/common/collect/Collections2Test.java
+++ b/guava-tests/test/com/google/common/collect/Collections2Test.java
@@ -237,7 +237,7 @@ public class Collections2Test extends TestCase {
         Collections2.orderedPermutations(list);
 
     assertEquals(1, permutationSet.size());
-    assertThat(permutationSet).has().item(list);
+    assertThat(permutationSet).contains(list);
 
     Iterator<List<Integer>> permutations = permutationSet.iterator();
 
diff --git a/guava-tests/test/com/google/common/collect/ComparisonChainTest.java b/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
index e24ed46..b9ad14b 100644
--- a/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
+++ b/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
@@ -37,6 +37,15 @@ public class ComparisonChainTest extends TestCase {
     }
   }
 
+  public void testCompareBooleans() {
+    assertEquals(0, ComparisonChain.start()
+        .compare(true, true)
+        .compare(true, Boolean.TRUE)
+        .compare(Boolean.TRUE, true)
+        .compare(Boolean.TRUE, Boolean.TRUE)
+        .result());
+  }
+
   public void testDegenerate() {
     // kinda bogus, but who cares?
     assertEquals(0, ComparisonChain.start().result());
diff --git a/guava-tests/test/com/google/common/collect/ConstraintsTest.java b/guava-tests/test/com/google/common/collect/ConstraintsTest.java
index d93c642..f6c112a 100644
--- a/guava-tests/test/com/google/common/collect/ConstraintsTest.java
+++ b/guava-tests/test/com/google/common/collect/ConstraintsTest.java
@@ -68,10 +68,10 @@ public class ConstraintsTest extends TestCase {
     constrained.add("qux");
     constrained.addAll(asList("cat", "dog"));
     /* equals and hashCode aren't defined for Collection */
-    assertThat(collection).has()
-        .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
-    assertThat(constrained).has()
-        .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+    assertThat(collection)
+        .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+    assertThat(constrained)
+        .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
   }
 
   public void testConstrainedCollectionIllegal() {
@@ -86,8 +86,8 @@ public class ConstraintsTest extends TestCase {
       constrained.addAll(asList("baz", TEST_ELEMENT));
       fail("TestElementException expected");
     } catch (TestElementException expected) {}
-    assertThat(constrained).has().exactly("foo", "bar").inOrder();
-    assertThat(collection).has().exactly("foo", "bar").inOrder();
+    assertThat(constrained).containsExactly("foo", "bar").inOrder();
+    assertThat(collection).containsExactly("foo", "bar").inOrder();
   }
 
   public void testConstrainedSetLegal() {
@@ -100,9 +100,9 @@ public class ConstraintsTest extends TestCase {
     assertTrue(constrained.equals(set));
     assertEquals(set.toString(), constrained.toString());
     assertEquals(set.hashCode(), constrained.hashCode());
-    assertThat(set).has().exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
-    assertThat(constrained).has()
-        .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+    assertThat(set).containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+    assertThat(constrained)
+        .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
   }
 
   public void testConstrainedSetIllegal() {
@@ -116,8 +116,8 @@ public class ConstraintsTest extends TestCase {
       constrained.addAll(asList("baz", TEST_ELEMENT));
       fail("TestElementException expected");
     } catch (TestElementException expected) {}
-    assertThat(constrained).has().exactly("foo", "bar").inOrder();
-    assertThat(set).has().exactly("foo", "bar").inOrder();
+    assertThat(constrained).containsExactly("foo", "bar").inOrder();
+    assertThat(set).containsExactly("foo", "bar").inOrder();
   }
 
   public void testConstrainedSortedSetLegal() {
@@ -131,9 +131,10 @@ public class ConstraintsTest extends TestCase {
     assertTrue(constrained.equals(sortedSet));
     assertEquals(sortedSet.toString(), constrained.toString());
     assertEquals(sortedSet.hashCode(), constrained.hashCode());
-    assertThat(sortedSet).has().exactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
-    assertThat(constrained).has()
-        .exactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
+    assertThat(sortedSet)
+        .containsExactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
+    assertThat(constrained)
+        .containsExactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
     assertNull(constrained.comparator());
     assertEquals("bar", constrained.first());
     assertEquals(TEST_ELEMENT, constrained.last());
@@ -163,8 +164,8 @@ public class ConstraintsTest extends TestCase {
       constrained.addAll(asList("baz", TEST_ELEMENT));
       fail("TestElementException expected");
     } catch (TestElementException expected) {}
-    assertThat(constrained).has().exactly("bar", "foo").inOrder();
-    assertThat(sortedSet).has().exactly("bar", "foo").inOrder();
+    assertThat(constrained).containsExactly("bar", "foo").inOrder();
+    assertThat(sortedSet).containsExactly("bar", "foo").inOrder();
   }
 
   public void testConstrainedListLegal() {
@@ -181,17 +182,17 @@ public class ConstraintsTest extends TestCase {
     assertTrue(constrained.equals(list));
     assertEquals(list.toString(), constrained.toString());
     assertEquals(list.hashCode(), constrained.hashCode());
-    assertThat(list).has().exactly(
+    assertThat(list).containsExactly(
         "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
-    assertThat(constrained).has().exactly(
+    assertThat(constrained).containsExactly(
         "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
     ListIterator<String> iterator = constrained.listIterator();
     iterator.next();
     iterator.set("sun");
     constrained.listIterator(2).add("sky");
-    assertThat(list).has().exactly(
+    assertThat(list).containsExactly(
         "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
-    assertThat(constrained).has().exactly(
+    assertThat(constrained).containsExactly(
         "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
     assertTrue(constrained instanceof RandomAccess);
   }
@@ -202,7 +203,7 @@ public class ConstraintsTest extends TestCase {
         list, TEST_CONSTRAINT);
     list.add(TEST_ELEMENT);
     constrained.add("qux");
-    assertFalse(constrained instanceof RandomAccess);
+    assertThat(constrained).isNotInstanceOf(RandomAccess.class);
   }
 
   public void testConstrainedListIllegal() {
@@ -249,8 +250,8 @@ public class ConstraintsTest extends TestCase {
       constrained.addAll(1, asList("baz", TEST_ELEMENT));
       fail("TestElementException expected");
     } catch (TestElementException expected) {}
-    assertThat(constrained).has().exactly("foo", "bar").inOrder();
-    assertThat(list).has().exactly("foo", "bar").inOrder();
+    assertThat(constrained).containsExactly("foo", "bar").inOrder();
+    assertThat(list).containsExactly("foo", "bar").inOrder();
   }
 
   public void testNefariousAddAll() {
@@ -259,8 +260,8 @@ public class ConstraintsTest extends TestCase {
         list, TEST_CONSTRAINT);
     Collection<String> onceIterable = onceIterableCollection("baz");
     constrained.addAll(onceIterable);
-    assertThat(constrained).has().exactly("foo", "bar", "baz").inOrder();
-    assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(constrained).containsExactly("foo", "bar", "baz").inOrder();
+    assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
   }
 
   /**
diff --git a/guava-tests/test/com/google/common/collect/ContiguousSetTest.java b/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
index 5e01e02..74d740f 100644
--- a/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
@@ -84,6 +84,10 @@ public class ContiguousSetTest extends TestCase {
             ContiguousSet.create(Range.openClosed(0, 3), NOT_EQUAL_TO_INTEGERS),
             ContiguousSet.create(Range.open(0, 4), NOT_EQUAL_TO_INTEGERS),
             ImmutableSortedSet.of(1, 2, 3))
+        .addEqualityGroup(
+            ContiguousSet.create(Range.closedOpen(1, 1), integers()),
+            ImmutableSortedSet.of(),
+            ImmutableSet.of())
         .testEquals();
     // not testing hashCode for these because it takes forever to compute
     assertEquals(
@@ -146,15 +150,15 @@ public class ContiguousSetTest extends TestCase {
   public void testHeadSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
     assertThat(set.headSet(1)).isEmpty();
-    assertThat(set.headSet(2)).has().item(1);
-    assertThat(set.headSet(3)).has().exactly(1, 2).inOrder();
-    assertThat(set.headSet(4)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(1, true)).has().item(1);
-    assertThat(set.headSet(2, true)).has().exactly(1, 2).inOrder();
-    assertThat(set.headSet(3, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(4, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.headSet(Integer.MAX_VALUE, true)).has().exactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(2)).contains(1);
+    assertThat(set.headSet(3)).containsExactly(1, 2).inOrder();
+    assertThat(set.headSet(4)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(1, true)).contains(1);
+    assertThat(set.headSet(2, true)).containsExactly(1, 2).inOrder();
+    assertThat(set.headSet(3, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(4, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.headSet(Integer.MAX_VALUE, true)).containsExactly(1, 2, 3).inOrder();
   }
 
   public void testHeadSet_tooSmall() {
@@ -163,13 +167,13 @@ public class ContiguousSetTest extends TestCase {
 
   public void testTailSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
-    assertThat(set.tailSet(Integer.MIN_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(1)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(2)).has().exactly(2, 3).inOrder();
-    assertThat(set.tailSet(3)).has().item(3);
-    assertThat(set.tailSet(Integer.MIN_VALUE, false)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.tailSet(1, false)).has().exactly(2, 3).inOrder();
-    assertThat(set.tailSet(2, false)).has().item(3);
+    assertThat(set.tailSet(Integer.MIN_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(1)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(2)).containsExactly(2, 3).inOrder();
+    assertThat(set.tailSet(3)).contains(3);
+    assertThat(set.tailSet(Integer.MIN_VALUE, false)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.tailSet(1, false)).containsExactly(2, 3).inOrder();
+    assertThat(set.tailSet(2, false)).contains(3);
     assertThat(set.tailSet(3, false)).isEmpty();
   }
 
@@ -179,19 +183,19 @@ public class ContiguousSetTest extends TestCase {
 
   public void testSubSet() {
     ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
-    assertThat(set.subSet(1, 4)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(2, 4)).has().exactly(2, 3).inOrder();
-    assertThat(set.subSet(3, 4)).has().item(3);
+    assertThat(set.subSet(1, 4)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(2, 4)).containsExactly(2, 3).inOrder();
+    assertThat(set.subSet(3, 4)).contains(3);
     assertThat(set.subSet(3, 3)).isEmpty();
-    assertThat(set.subSet(2, 3)).has().item(2);
-    assertThat(set.subSet(1, 3)).has().exactly(1, 2).inOrder();
-    assertThat(set.subSet(1, 2)).has().item(1);
+    assertThat(set.subSet(2, 3)).contains(2);
+    assertThat(set.subSet(1, 3)).containsExactly(1, 2).inOrder();
+    assertThat(set.subSet(1, 2)).contains(1);
     assertThat(set.subSet(2, 2)).isEmpty();
-    assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(1, true, 3, true)).has().exactly(1, 2, 3).inOrder();
-    assertThat(set.subSet(1, false, 3, true)).has().exactly(2, 3).inOrder();
-    assertThat(set.subSet(1, true, 3, false)).has().exactly(1, 2).inOrder();
-    assertThat(set.subSet(1, false, 3, false)).has().item(2);
+    assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(1, true, 3, true)).containsExactly(1, 2, 3).inOrder();
+    assertThat(set.subSet(1, false, 3, true)).containsExactly(2, 3).inOrder();
+    assertThat(set.subSet(1, true, 3, false)).containsExactly(1, 2).inOrder();
+    assertThat(set.subSet(1, false, 3, false)).contains(2);
   }
 
   public void testSubSet_outOfOrder() {
diff --git a/guava-tests/test/com/google/common/collect/EnumBiMapTest.java b/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
index 6d75bf3..a0c312c 100644
--- a/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
@@ -197,16 +197,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
   }
 
   public void testKeySetIteratorRemove() {
@@ -224,16 +224,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.FRANC, Currency.PESO).inOrder();
+        .containsExactly(Currency.FRANC, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.SWITZERLAND, Country.CHILE).inOrder();
+        .containsExactly(Country.SWITZERLAND, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CHILE, Country.SWITZERLAND).inOrder();
+        .containsExactly(Country.CHILE, Country.SWITZERLAND).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.PESO, Currency.FRANC).inOrder();
+        .containsExactly(Currency.PESO, Currency.FRANC).inOrder();
   }
 
   public void testValuesIteratorRemove() {
@@ -252,16 +252,16 @@ public class EnumBiMapTest extends TestCase {
 
     // forward map ordered by currency
     assertThat(bimap.keySet())
-        .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
     // forward map ordered by currency (even for country values)
     assertThat(bimap.values())
-        .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE).inOrder();
     // backward map ordered by country
     assertThat(bimap.inverse().keySet())
-        .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+        .containsExactly(Country.CANADA, Country.CHILE).inOrder();
     // backward map ordered by country (even for currency values)
     assertThat(bimap.inverse().values())
-        .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+        .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
   }
 
   public void testEntrySet() {
diff --git a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java b/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
index 9567dee..d2c44ab 100644
--- a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
+++ b/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
@@ -18,6 +18,8 @@ package com.google.common.collect;
 
 import static java.util.Arrays.asList;
 
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.testing.NullPointerTester;
 import com.google.common.testing.SerializableTester;
 
@@ -30,6 +32,7 @@ import java.util.NoSuchElementException;
  *
  * @author Kurt Alfred Kluever
  */
+ at GwtCompatible(emulated = true)
 public class EvictingQueueTest extends TestCase {
 
   public void testCreateWithNegativeSize() throws Exception {
@@ -157,6 +160,7 @@ public class EvictingQueueTest extends TestCase {
     assertEquals(1, queue.remainingCapacity());
   }
 
+  @GwtIncompatible("NullPointerTester")
   public void testNullPointerExceptions() {
     NullPointerTester tester = new NullPointerTester();
     tester.testAllPublicStaticMethods(EvictingQueue.class);
diff --git a/guava-tests/test/com/google/common/collect/FauxveridesTest.java b/guava-tests/test/com/google/common/collect/FauxveridesTest.java
index c1d861c..10c71f6 100644
--- a/guava-tests/test/com/google/common/collect/FauxveridesTest.java
+++ b/guava-tests/test/com/google/common/collect/FauxveridesTest.java
@@ -17,8 +17,8 @@
 package com.google.common.collect;
 
 import static com.google.common.collect.Lists.transform;
+import static com.google.common.collect.Sets.difference;
 import static com.google.common.collect.Sets.newHashSet;
-import static com.google.common.collect.Sets.newTreeSet;
 import static java.lang.reflect.Modifier.isPublic;
 import static java.lang.reflect.Modifier.isStatic;
 
@@ -32,8 +32,8 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -112,10 +112,11 @@ public class FauxveridesTest extends TestCase {
   private void doHasAllFauxveridesTest(Class<?> descendant, Class<?> ancestor) {
     Set<MethodSignature> required = getAllRequiredToFauxveride(ancestor);
     Set<MethodSignature> found = getAllFauxveridden(descendant, ancestor);
-    required.removeAll(found);
-
-    assertEquals("Must hide public static methods from ancestor classes",
-        Collections.emptySet(), newTreeSet(required));
+    Set<MethodSignature> missing = ImmutableSortedSet.copyOf(difference(required, found));
+    if (!missing.isEmpty()) {
+      fail(rootLocaleFormat("%s should hide the public static methods declared in %s: %s",
+          descendant.getSimpleName(), ancestor.getSimpleName(), missing));
+    }
   }
 
   private static Set<MethodSignature> getAllRequiredToFauxveride(Class<?> ancestor) {
@@ -196,7 +197,7 @@ public class FauxveridesTest extends TestCase {
     }
 
     @Override public String toString() {
-      return String.format("%s%s(%s)",
+      return rootLocaleFormat("%s%s(%s)",
           typeSignature, name, getTypesString(parameterTypes));
     }
 
@@ -287,4 +288,8 @@ public class FauxveridesTest extends TestCase {
           return from.toString();
         }
       };
+
+  private static String rootLocaleFormat(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java b/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
index 579d378..59d5538 100644
--- a/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
+++ b/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
@@ -101,7 +101,7 @@ public class FilteredCollectionsTest extends TestCase {
         target.add(4);
         C addThenFilter = filter(createUnfiltered(target), EVEN);
 
-        assertThat(filterThenAdd).has().exactlyAs(addThenFilter);
+        assertThat(filterThenAdd).containsExactlyElementsIn(addThenFilter);
       }
     }
 
@@ -157,7 +157,7 @@ public class FilteredCollectionsTest extends TestCase {
         } catch (IllegalArgumentException expected) {
         }
 
-        assertThat(filteredToModify).has().exactlyAs(filtered);
+        assertThat(filteredToModify).containsExactlyElementsIn(filtered);
       }
     }
 
@@ -191,7 +191,7 @@ public class FilteredCollectionsTest extends TestCase {
             Predicates.not(Predicates.and(EVEN, PRIME_DIGIT)));
 
         filtered2.clear();
-        assertThat(unfiltered).has().exactlyAs(inverseFiltered);
+        assertThat(unfiltered).containsExactlyElementsIn(inverseFiltered);
       }
     }
   }
@@ -328,7 +328,9 @@ public class FilteredCollectionsTest extends TestCase {
         NavigableSet<Integer> filtered = filter(createUnfiltered(contents), EVEN);
         NavigableSet<Integer> unfiltered = createUnfiltered(filtered);
 
-        assertThat(filtered.descendingSet()).has().exactlyAs(unfiltered.descendingSet()).inOrder();
+        assertThat(filtered.descendingSet())
+            .containsExactlyElementsIn(unfiltered.descendingSet())
+            .inOrder();
       }
     }
 
diff --git a/guava-tests/test/com/google/common/collect/FluentIterableTest.java b/guava-tests/test/com/google/common/collect/FluentIterableTest.java
index 674c642..af70b4c 100644
--- a/guava-tests/test/com/google/common/collect/FluentIterableTest.java
+++ b/guava-tests/test/com/google/common/collect/FluentIterableTest.java
@@ -24,7 +24,6 @@ import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.testing.IteratorFeature;
@@ -49,6 +48,7 @@ import javax.annotation.Nullable;
  *
  * @author Marcin Mikosik
  */
+ at SuppressWarnings("CheckReturnValue")
 @GwtCompatible(emulated = true)
 public class FluentIterableTest extends TestCase {
 
@@ -221,7 +221,7 @@ public class FluentIterableTest extends TestCase {
     FluentIterable<TypeA> alist =
         FluentIterable.from(asList(new TypeA(), new TypeA(), hasBoth, new TypeA()));
     Iterable<TypeB> blist = alist.filter(TypeB.class);
-    assertThat(blist).iteratesAs(hasBoth);
+    assertThat(blist).containsExactly(hasBoth).inOrder();
   }
 
   public void testAnyMatch() {
@@ -250,10 +250,10 @@ public class FluentIterableTest extends TestCase {
 
   public void testFirstMatch() {
     FluentIterable<String> iterable = FluentIterable.from(Lists.newArrayList("cool", "pants"));
-    assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.equalTo("cool")));
-    assertEquals(Optional.of("pants"), iterable.firstMatch(Predicates.equalTo("pants")));
-    assertEquals(Optional.absent(), iterable.firstMatch(Predicates.alwaysFalse()));
-    assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.alwaysTrue()));
+    assertThat(iterable.firstMatch(Predicates.equalTo("cool"))).hasValue("cool");
+    assertThat(iterable.firstMatch(Predicates.equalTo("pants"))).hasValue("pants");
+    assertThat(iterable.firstMatch(Predicates.alwaysFalse())).isAbsent();
+    assertThat(iterable.firstMatch(Predicates.alwaysTrue())).hasValue("cool");
   }
 
   private static final class IntegerValueOfFunction implements Function<String, Integer> {
@@ -334,7 +334,7 @@ public class FluentIterableTest extends TestCase {
 
   public void testFirst_list() {
     List<String> list = Lists.newArrayList("a", "b", "c");
-    assertEquals("a", FluentIterable.from(list).first().get());
+    assertThat(FluentIterable.from(list).first()).hasValue("a");
   }
 
   public void testFirst_null() {
@@ -348,32 +348,32 @@ public class FluentIterableTest extends TestCase {
 
   public void testFirst_emptyList() {
     List<String> list = Collections.emptyList();
-    assertEquals(Optional.absent(), FluentIterable.from(list).first());
+    assertThat(FluentIterable.from(list).first()).isAbsent();
   }
 
   public void testFirst_sortedSet() {
     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
-    assertEquals("a", FluentIterable.from(sortedSet).first().get());
+    assertThat(FluentIterable.from(sortedSet).first()).hasValue("a");
   }
 
   public void testFirst_emptySortedSet() {
     SortedSet<String> sortedSet = ImmutableSortedSet.of();
-    assertEquals(Optional.absent(), FluentIterable.from(sortedSet).first());
+    assertThat(FluentIterable.from(sortedSet).first()).isAbsent();
   }
 
   public void testFirst_iterable() {
     Set<String> set = ImmutableSet.of("a", "b", "c");
-    assertEquals("a", FluentIterable.from(set).first().get());
+    assertThat(FluentIterable.from(set).first()).hasValue("a");
   }
 
   public void testFirst_emptyIterable() {
     Set<String> set = Sets.newHashSet();
-    assertEquals(Optional.absent(), FluentIterable.from(set).first());
+    assertThat(FluentIterable.from(set).first()).isAbsent();
   }
 
   public void testLast_list() {
     List<String> list = Lists.newArrayList("a", "b", "c");
-    assertEquals("c", FluentIterable.from(list).last().get());
+    assertThat(FluentIterable.from(list).last()).hasValue("c");
   }
 
   public void testLast_null() {
@@ -387,27 +387,27 @@ public class FluentIterableTest extends TestCase {
 
   public void testLast_emptyList() {
     List<String> list = Collections.emptyList();
-    assertEquals(Optional.absent(), FluentIterable.from(list).last());
+    assertThat(FluentIterable.from(list).last()).isAbsent();
   }
 
   public void testLast_sortedSet() {
     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
-    assertEquals("c", FluentIterable.from(sortedSet).last().get());
+    assertThat(FluentIterable.from(sortedSet).last()).hasValue("c");
   }
 
   public void testLast_emptySortedSet() {
     SortedSet<String> sortedSet = ImmutableSortedSet.of();
-    assertEquals(Optional.absent(), FluentIterable.from(sortedSet).last());
+    assertThat(FluentIterable.from(sortedSet).last()).isAbsent();
   }
 
   public void testLast_iterable() {
     Set<String> set = ImmutableSet.of("a", "b", "c");
-    assertEquals("c", FluentIterable.from(set).last().get());
+    assertThat(FluentIterable.from(set).last()).hasValue("c");
   }
 
   public void testLast_emptyIterable() {
     Set<String> set = Sets.newHashSet();
-    assertEquals(Optional.absent(), FluentIterable.from(set).last());
+    assertThat(FluentIterable.from(set).last()).isAbsent();
   }
 
   public void testSkip_simple() {
@@ -482,7 +482,7 @@ public class FluentIterableTest extends TestCase {
     FluentIterable<String> tail = FluentIterable.from(set).skip(1);
     set.remove("b");
     set.addAll(Lists.newArrayList("X", "Y", "Z"));
-    assertThat(tail).iteratesAs("c", "X", "Y", "Z");
+    assertThat(tail).containsExactly("c", "X", "Y", "Z").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -490,7 +490,7 @@ public class FluentIterableTest extends TestCase {
     FluentIterable<String> tail = FluentIterable.from(list).skip(1);
     list.subList(1, 3).clear();
     list.addAll(0, Lists.newArrayList("X", "Y", "Z"));
-    assertThat(tail).iteratesAs("Y", "Z", "a");
+    assertThat(tail).containsExactly("Y", "Z", "a").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -560,11 +560,11 @@ public class FluentIterableTest extends TestCase {
   }
 
   public void testToSet() {
-    assertThat(fluent(1, 2, 3, 4).toSet()).has().exactly(1, 2, 3, 4).inOrder();
+    assertThat(fluent(1, 2, 3, 4).toSet()).containsExactly(1, 2, 3, 4).inOrder();
   }
 
   public void testToSet_removeDuplicates() {
-    assertThat(fluent(1, 2, 1, 2).toSet()).has().exactly(1, 2).inOrder();
+    assertThat(fluent(1, 2, 1, 2).toSet()).containsExactly(1, 2).inOrder();
   }
 
   public void testToSet_empty() {
@@ -573,17 +573,25 @@ public class FluentIterableTest extends TestCase {
 
   public void testToSortedSet() {
     assertThat(fluent(1, 4, 2, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
-        .has().exactly(4, 3, 2, 1).inOrder();
+        .containsExactly(4, 3, 2, 1).inOrder();
   }
 
   public void testToSortedSet_removeDuplicates() {
     assertThat(fluent(1, 4, 1, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
-        .has().exactly(4, 3, 1).inOrder();
+        .containsExactly(4, 3, 1).inOrder();
+  }
+
+  public void testToMultiset() {
+    assertThat(fluent(1, 2, 1, 3, 2, 4).toMultiset()).containsExactly(1, 1, 2, 2, 3, 4).inOrder();
+  }
+
+  public void testToMultiset_empty() {
+    assertThat(fluent().toMultiset()).isEmpty();
   }
 
   public void testToMap() {
     assertThat(fluent(1, 2, 3).toMap(Functions.toStringFunction()).entrySet())
-        .has().exactly(
+        .containsExactly(
             Maps.immutableEntry(1, "1"),
             Maps.immutableEntry(2, "2"),
             Maps.immutableEntry(3, "3")).inOrder();
@@ -690,17 +698,17 @@ public class FluentIterableTest extends TestCase {
 
   public void testCopyInto_List() {
     assertThat(fluent(1, 3, 5).copyInto(Lists.newArrayList(1, 2)))
-        .has().exactly(1, 2, 1, 3, 5).inOrder();
+        .containsExactly(1, 2, 1, 3, 5).inOrder();
   }
 
   public void testCopyInto_Set() {
     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2)))
-        .has().exactly(1, 2, 3, 5);
+        .containsExactly(1, 2, 3, 5);
   }
 
   public void testCopyInto_SetAllDuplicates() {
     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2, 3, 5)))
-        .has().exactly(1, 2, 3, 5);
+        .containsExactly(1, 2, 3, 5);
   }
 
   public void testCopyInto_NonCollection() {
@@ -715,7 +723,7 @@ public class FluentIterableTest extends TestCase {
     };
 
     assertThat(FluentIterable.from(iterable).copyInto(list))
-        .has().exactly(1, 2, 3, 9, 8, 7).inOrder();
+        .containsExactly(1, 2, 3, 9, 8, 7).inOrder();
   }
 
   public void testJoin() {
diff --git a/guava-tests/test/com/google/common/collect/ForwardingListTest.java b/guava-tests/test/com/google/common/collect/ForwardingListTest.java
index a6a71b4..d292768 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingListTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingListTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.collect;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.collect.testing.ListTestSuiteBuilder;
 import com.google.common.collect.testing.TestStringListGenerator;
 import com.google.common.collect.testing.features.CollectionFeature;
@@ -305,7 +307,7 @@ public class ForwardingListTest extends ForwardingTestCase {
   }
 
   public void testRandomAccess() {
-    assertFalse(forward instanceof RandomAccess);
+    assertThat(forward).isNotInstanceOf(RandomAccess.class);
   }
 
   public void testToString() {
diff --git a/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java b/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
index 0cf4e4a..af36238 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
@@ -385,6 +385,7 @@ public class ForwardingMultisetTest extends ForwardingTestCase {
     assertEquals("[setCount(Object,int,int)]", getCalls());
   }
 
+  @SuppressUnderAndroid // Proxy problem, perhaps around SortedMultisetBridge?
   public void testElementSet() {
     forward().elementSet();
     assertEquals("[elementSet]", getCalls());
diff --git a/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java b/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
index d10ff09..6889376 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
@@ -249,7 +249,7 @@ public class ForwardingNavigableMapTest extends ForwardingSortedMapTest {
         CollectionFeature.KNOWN_ORDER, MapFeature.ALLOWS_NULL_VALUES,
         CollectionFeature.SUPPORTS_ITERATOR_REMOVE, MapFeature.GENERAL_PURPOSE)
         .createTestSuite());
-    // TODO(user): add forwarding-to-ImmutableSortedMap test
+    // TODO(lowasser): add forwarding-to-ImmutableSortedMap test
     return suite;
   }
 
diff --git a/guava-tests/test/com/google/common/collect/HashBiMapTest.java b/guava-tests/test/com/google/common/collect/HashBiMapTest.java
index b547bc1..d2035fb 100644
--- a/guava-tests/test/com/google/common/collect/HashBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/HashBiMapTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.collect;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.testing.features.CollectionFeature;
@@ -60,6 +62,7 @@ public class HashBiMapTest extends TestCase {
       .withFeatures(CollectionSize.ANY,
           CollectionFeature.SERIALIZABLE,
           CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
+          CollectionFeature.KNOWN_ORDER,
           MapFeature.ALLOWS_NULL_KEYS,
           MapFeature.ALLOWS_NULL_VALUES,
           MapFeature.ALLOWS_ANY_NULL_QUERIES,
@@ -126,4 +129,102 @@ public class HashBiMapTest extends TestCase {
     iterator.remove(); // removes the updated entry
     assertTrue(map.isEmpty());
   }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrder() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("foo", 1),
+        Maps.immutableEntry("bar", 2),
+        Maps.immutableEntry("quux", 3)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrderAfterRemoveFirst() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.remove("foo");
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("bar", 2),
+        Maps.immutableEntry("quux", 3)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrderAfterRemoveMiddle() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.remove("bar");
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("foo", 1),
+        Maps.immutableEntry("quux", 3)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrderAfterRemoveLast() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.remove("quux");
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("foo", 1),
+        Maps.immutableEntry("bar", 2)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrderAfterForcePut() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.forcePut("quux", 1);
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("bar", 2),
+        Maps.immutableEntry("quux", 1)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInsertionOrderAfterInverseForcePut() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.inverse().forcePut(1, "quux");
+    assertThat(map.entrySet()).containsExactly(
+        Maps.immutableEntry("bar", 2),
+        Maps.immutableEntry("quux", 1)).inOrder();
+  }
+
+  @GwtIncompatible("insertion order currently not preserved in GWT")
+  public void testInverseInsertionOrderAfterInverseForcePut() {
+    BiMap<String, Integer> map = HashBiMap.create();
+    map.put("foo", 1);
+    map.put("bar", 2);
+    map.put("quux", 3);
+
+    map.inverse().forcePut(1, "quux");
+    assertThat(map.inverse().entrySet()).containsExactly(
+        Maps.immutableEntry(2, "bar"),
+        Maps.immutableEntry(1, "quux")).inOrder();
+  }
+
+  public void testInverseEntrySetValue() {
+    BiMap<Integer, String> map = HashBiMap.create();
+    map.put(1, "one");
+    Entry<String, Integer> inverseEntry = Iterables.getOnlyElement(map.inverse().entrySet());
+    inverseEntry.setValue(2);
+    assertEquals(Integer.valueOf(2), inverseEntry.getValue());
+  }
 }
diff --git a/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
index 8609e05..69534e9 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
@@ -26,6 +26,7 @@ import com.google.common.collect.testing.MapInterfaceTest;
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfEntriesGenerator;
 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfGenerator;
 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapGenerator;
 import com.google.common.collect.testing.google.BiMapInverseTester;
@@ -71,13 +72,22 @@ public class ImmutableBiMapTest extends TestCase {
         .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
         .createTestSuite());
     suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfGenerator())
-        .named("ImmutableBiMap.copyOf")
+        .named("ImmutableBiMap.copyOf[Map]")
         .withFeatures(CollectionSize.ANY,
             CollectionFeature.SERIALIZABLE,
             CollectionFeature.KNOWN_ORDER,
             MapFeature.ALLOWS_ANY_NULL_QUERIES)
         .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
         .createTestSuite());
+    suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfEntriesGenerator())
+        .named("ImmutableBiMap.copyOf[Iterable<Entry>]")
+        .withFeatures(CollectionSize.ANY,
+            CollectionFeature.SERIALIZABLE,
+            CollectionFeature.KNOWN_ORDER,
+            MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+            MapFeature.ALLOWS_ANY_NULL_QUERIES)
+        .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
+        .createTestSuite());
 
     return suite;
   }
@@ -172,6 +182,13 @@ public class ImmutableBiMapTest extends TestCase {
       assertMapEquals(map.inverse(), 1, "one");
     }
 
+    public void testBuilder_withImmutableEntry() {
+      ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
+          .put(Maps.immutableEntry("one", 1))
+          .build();
+      assertMapEquals(map, "one", 1);
+    }
+
     public void testBuilder() {
       ImmutableBiMap<String, Integer> map
           = ImmutableBiMap.<String, Integer>builder()
@@ -187,6 +204,41 @@ public class ImmutableBiMapTest extends TestCase {
           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
     }
 
+    public void testBuilder_orderEntriesByValue() {
+      ImmutableBiMap<String, Integer> map =
+          ImmutableBiMap.<String, Integer>builder()
+              .orderEntriesByValue(Ordering.natural())
+              .put("three", 3)
+              .put("one", 1)
+              .put("five", 5)
+              .put("four", 4)
+              .put("two", 2)
+              .build();
+      assertMapEquals(map,
+          "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+      assertMapEquals(map.inverse(),
+          1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
+    }
+
+    public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+      ImmutableBiMap.Builder<String, Integer> builder =
+          new ImmutableBiMap.Builder<String, Integer>(2).put("four", 4).put("one", 1);
+      ImmutableMap<String, Integer> keyOrdered = builder.build();
+      ImmutableMap<String, Integer> valueOrdered =
+          builder.orderEntriesByValue(Ordering.natural()).build();
+      assertMapEquals(keyOrdered, "four", 4, "one", 1);
+      assertMapEquals(valueOrdered, "one", 1, "four", 4);
+    }
+
+    public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+      ImmutableBiMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural());
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {}
+    }
+
     public void testBuilderPutAllWithEmptyMap() {
       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
           .putAll(Collections.<String, Integer>emptyMap())
@@ -276,7 +328,7 @@ public class ImmutableBiMapTest extends TestCase {
         builder.build();
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("one"));
+        assertThat(expected.getMessage()).contains("one");
       }
     }
 
@@ -349,7 +401,7 @@ public class ImmutableBiMapTest extends TestCase {
         ImmutableBiMap.of("one", 1, "one", 1);
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("one"));
+        assertThat(expected.getMessage()).contains("one");
       }
     }
 
@@ -423,7 +475,7 @@ public class ImmutableBiMapTest extends TestCase {
         ImmutableBiMap.copyOf(map);
         fail();
       } catch (IllegalArgumentException expected) {
-        assertTrue(expected.getMessage().contains("1"));
+        assertThat(expected.getMessage()).contains("1");
       }
     }
   }
@@ -445,7 +497,7 @@ public class ImmutableBiMapTest extends TestCase {
           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
       Set<String> keys = bimap.keySet();
       assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
-      assertThat(keys).has().exactly("one", "two", "three", "four").inOrder();
+      assertThat(keys).containsExactly("one", "two", "three", "four").inOrder();
     }
 
     public void testValues() {
@@ -453,7 +505,7 @@ public class ImmutableBiMapTest extends TestCase {
           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
       Set<Integer> values = bimap.values();
       assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
-      assertThat(values).has().exactly(1, 2, 3, 4).inOrder();
+      assertThat(values).containsExactly(1, 2, 3, 4).inOrder();
     }
 
     public void testDoubleInverse() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
index 74ca804..4434f8c 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
@@ -22,6 +22,7 @@ import com.google.common.collect.testing.TestMapGenerator;
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.testing.SerializableTester;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -70,14 +71,29 @@ public class ImmutableClassToInstanceMapTest extends TestCase {
 
     return suite;
   }
+  
+  public void testSerialization_empty() {
+    assertSame(ImmutableClassToInstanceMap.of(), 
+        SerializableTester.reserialize(ImmutableClassToInstanceMap.of()));
+  }
 
   public void testCopyOf_map_empty() {
     Map<Class<?>, Object> in = Collections.emptyMap();
     ClassToInstanceMap<Object> map = ImmutableClassToInstanceMap.copyOf(in);
     assertTrue(map.isEmpty());
-
+    assertSame(map, ImmutableClassToInstanceMap.of());
     assertSame(map, ImmutableClassToInstanceMap.copyOf(map));
   }
+  
+  public void testOf_zero() {
+    assertTrue(ImmutableClassToInstanceMap.of().isEmpty());
+  }
+  
+  public void testOf_one() {
+    ImmutableClassToInstanceMap<Number> map =
+        ImmutableClassToInstanceMap.of(int.class, 1);
+    assertEquals(1, map.size());
+  }
 
   public void testCopyOf_map_valid() {
     Map<Class<? extends Number>, Number> in = Maps.newHashMap();
diff --git a/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
index e8244a9..fe641d4 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.collect;
 
+import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
@@ -24,7 +26,6 @@ import com.google.common.collect.testing.AnEnum;
 import com.google.common.collect.testing.Helpers;
 import com.google.common.collect.testing.MapTestSuiteBuilder;
 import com.google.common.collect.testing.TestEnumMapGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 
 import junit.framework.Test;
@@ -58,8 +59,8 @@ public class ImmutableEnumMapTest extends TestCase {
     suite.addTest(MapTestSuiteBuilder.using(new ImmutableEnumMapGenerator())
       .named("Maps.immutableEnumMap")
       .withFeatures(CollectionSize.ANY,
-          CollectionFeature.SERIALIZABLE,
-          CollectionFeature.ALLOWS_NULL_QUERIES)
+          SERIALIZABLE,
+          ALLOWS_NULL_QUERIES)
       .createTestSuite());
     suite.addTestSuite(ImmutableEnumMapTest.class);
     return suite;
@@ -74,7 +75,7 @@ public class ImmutableEnumMapTest extends TestCase {
     ImmutableMap<AnEnum, String> map = Maps.immutableEnumMap(
         ImmutableMap.of(AnEnum.C, "c", AnEnum.A, "a", AnEnum.E, "e"));
 
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Helpers.mapEntry(AnEnum.A, "a"),
         Helpers.mapEntry(AnEnum.C, "c"),
         Helpers.mapEntry(AnEnum.E, "e")).inOrder();
diff --git a/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
index b632735..4360f66 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
@@ -16,14 +16,15 @@
 
 package com.google.common.collect;
 
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.ImmutableListMultimap.Builder;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
-import com.google.common.collect.testing.features.MapFeature;
 import com.google.common.collect.testing.google.ListMultimapTestSuiteBuilder;
 import com.google.common.collect.testing.google.TestStringListMultimapGenerator;
 import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
@@ -56,6 +57,13 @@ public class ImmutableListMultimapTest extends TestCase {
       return builder.build();
     }
   }
+  public static class ImmutableListMultimapCopyOfEntriesGenerator
+      extends TestStringListMultimapGenerator {
+    @Override
+    protected ListMultimap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableListMultimap.copyOf(Arrays.asList(entries));
+    }
+  }
 
   @GwtIncompatible("suite")
   public static Test suite() {
@@ -63,11 +71,20 @@ public class ImmutableListMultimapTest extends TestCase {
     suite.addTest(ListMultimapTestSuiteBuilder.using(new ImmutableListMultimapGenerator())
       .named("ImmutableListMultimap")
       .withFeatures(
-          MapFeature.ALLOWS_ANY_NULL_QUERIES,
-          CollectionFeature.SERIALIZABLE,
-          CollectionFeature.KNOWN_ORDER,
+          ALLOWS_ANY_NULL_QUERIES,
+          SERIALIZABLE,
+          KNOWN_ORDER,
           CollectionSize.ANY)
       .createTestSuite());
+    suite.addTest(ListMultimapTestSuiteBuilder.using(
+            new ImmutableListMultimapCopyOfEntriesGenerator())
+        .named("ImmutableListMultimap.copyOf[Iterable<Entry>]")
+        .withFeatures(
+            ALLOWS_ANY_NULL_QUERIES,
+            SERIALIZABLE,
+            KNOWN_ORDER,
+            CollectionSize.ANY)
+        .createTestSuite());
     suite.addTestSuite(ImmutableListMultimapTest.class);
     return suite;
   }
@@ -263,10 +280,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
   }
 
   public void testBuilderOrderKeysByDuplicates() {
@@ -285,10 +302,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("bb", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
   }
 
   public void testBuilderOrderValuesBy() {
@@ -302,10 +319,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
-    assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+    assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
   }
 
   public void testBuilderOrderKeysAndValuesBy() {
@@ -320,10 +337,10 @@ public class ImmutableListMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableListMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
   }
 
   public void testCopyOf() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableListTest.java b/guava-tests/test/com/google/common/collect/ImmutableListTest.java
index 57c64d2..d7600ab 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableListTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableListTest.java
@@ -19,6 +19,8 @@ package com.google.common.collect;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.collect.Iterables.unmodifiableIterable;
 import static com.google.common.collect.Sets.newHashSet;
+import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
 import static java.lang.reflect.Proxy.newProxyInstance;
 import static java.util.Arrays.asList;
 
@@ -28,7 +30,6 @@ import com.google.common.collect.testing.Helpers;
 import com.google.common.collect.testing.ListTestSuiteBuilder;
 import com.google.common.collect.testing.MinimalCollection;
 import com.google.common.collect.testing.MinimalIterable;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 import com.google.common.collect.testing.google.ListGenerators.BuilderAddAllListGenerator;
 import com.google.common.collect.testing.google.ListGenerators.BuilderReversedListGenerator;
@@ -72,54 +73,54 @@ public class ImmutableListTest extends TestCase {
     suite.addTest(ListTestSuiteBuilder.using(new ImmutableListOfGenerator())
         .named("ImmutableList")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
         .named("ImmutableList, built with Builder.add")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
         .named("ImmutableList, built with Builder.addAll")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(new BuilderReversedListGenerator())
         .named("ImmutableList, reversed")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(
         new ImmutableListHeadSubListGenerator())
         .named("ImmutableList, head subList")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(
         new ImmutableListTailSubListGenerator())
         .named("ImmutableList, tail subList")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(
         new ImmutableListMiddleSubListGenerator())
         .named("ImmutableList, middle subList")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.SERIALIZABLE,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            SERIALIZABLE,
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     suite.addTest(ListTestSuiteBuilder.using(
         new UnhashableElementsImmutableListGenerator())
         .suppressing(ListHashCodeTester.getHashCodeMethod())
         .named("ImmutableList, unhashable values")
         .withFeatures(CollectionSize.ANY,
-            CollectionFeature.ALLOWS_NULL_QUERIES)
+            ALLOWS_NULL_QUERIES)
         .createTestSuite());
     return suite;
   }
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
index e79ab50..749dc4a 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
@@ -34,6 +34,7 @@ import com.google.common.collect.testing.UnhashableObject;
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEntriesGenerator;
 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEnumMapGenerator;
 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfGenerator;
 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapEntryListGenerator;
@@ -87,7 +88,17 @@ public class ImmutableMapTest extends TestCase {
             CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
             CollectionFeature.KNOWN_ORDER,
             CollectionFeature.ALLOWS_NULL_QUERIES)
-        .named("ImmutableMap.copyOf")
+        .named("ImmutableMap.copyOf[Map]")
+        .createTestSuite());
+
+    suite.addTest(MapTestSuiteBuilder.using(new ImmutableMapCopyOfEntriesGenerator())
+        .withFeatures(
+            CollectionSize.ANY,
+            MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+            CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
+            CollectionFeature.KNOWN_ORDER,
+            CollectionFeature.ALLOWS_NULL_QUERIES)
+        .named("ImmutableMap.copyOf[Iterable<Entry>]")
         .createTestSuite());
 
     suite.addTest(MapTestSuiteBuilder.using(new ImmutableMapCopyOfEnumMapGenerator())
@@ -228,14 +239,14 @@ public class ImmutableMapTest extends TestCase {
     @Override protected Map<Object, Integer> makePopulatedMap() {
       Colliders colliders = new Colliders();
       return ImmutableMap.of(
-          colliders.e0, 0,
-          colliders.e1, 1,
-          colliders.e2, 2,
-          colliders.e3, 3);
+          colliders.e0(), 0,
+          colliders.e1(), 1,
+          colliders.e2(), 2,
+          colliders.e3(), 3);
     }
 
     @Override protected Object getKeyNotInPopulatedMap() {
-      return new Colliders().e4;
+      return new Colliders().e4();
     }
 
     @Override protected Integer getValueNotInPopulatedMap() {
@@ -253,7 +264,7 @@ public class ImmutableMapTest extends TestCase {
     @Override protected Map<Integer, UnhashableObject> makePopulatedMap() {
       Unhashables unhashables = new Unhashables();
       return ImmutableMap.of(
-          0, unhashables.e0, 1, unhashables.e1, 2, unhashables.e2);
+          0, unhashables.e0(), 1, unhashables.e1(), 2, unhashables.e2());
     }
 
     @Override protected Integer getKeyNotInPopulatedMap() {
@@ -261,7 +272,7 @@ public class ImmutableMapTest extends TestCase {
     }
 
     @Override protected UnhashableObject getValueNotInPopulatedMap() {
-      return new Unhashables().e3;
+      return new Unhashables().e3();
     }
   }
 
@@ -270,7 +281,7 @@ public class ImmutableMapTest extends TestCase {
       extends MapTestsWithUnhashableValues {
     @Override protected Map<Integer, UnhashableObject> makePopulatedMap() {
       Unhashables unhashables = new Unhashables();
-      return ImmutableMap.of(0, unhashables.e0);
+      return ImmutableMap.of(0, unhashables.e0());
     }
   }
 
@@ -300,6 +311,39 @@ public class ImmutableMapTest extends TestCase {
           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
     }
 
+    public void testBuilder_orderEntriesByValue() {
+      ImmutableMap<String, Integer> map = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural())
+          .put("three", 3)
+          .put("one", 1)
+          .put("five", 5)
+          .put("four", 4)
+          .put("two", 2)
+          .build();
+      assertMapEquals(map,
+          "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+    }
+
+    public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+      Builder<String, Integer> builder = new Builder<String, Integer>(2)
+          .put("four", 4)
+          .put("one", 1);
+      ImmutableMap<String, Integer> keyOrdered = builder.build();
+      ImmutableMap<String, Integer> valueOrdered =
+          builder.orderEntriesByValue(Ordering.natural()).build();
+      assertMapEquals(keyOrdered, "four", 4, "one", 1);
+      assertMapEquals(valueOrdered, "one", 1, "four", 4);
+    }
+
+    public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+      ImmutableMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+          .orderEntriesByValue(Ordering.natural());
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {}
+    }
+
     public void testBuilder_withImmutableEntry() {
       ImmutableMap<String, Integer> map = new Builder<String, Integer>()
           .put(Maps.immutableEntry("one", 1))
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
index d02359c..5896e15 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
@@ -101,18 +101,18 @@ public class ImmutableMultimapTest extends TestCase {
   public void testUnhashableSingletonValue() {
     SampleElements<UnhashableObject> unhashables = new Unhashables();
     Multimap<Integer, UnhashableObject> multimap = ImmutableMultimap.of(
-        0, unhashables.e0);
+        0, unhashables.e0());
     assertEquals(1, multimap.get(0).size());
-    assertTrue(multimap.get(0).contains(unhashables.e0));
+    assertTrue(multimap.get(0).contains(unhashables.e0()));
   }
 
   public void testUnhashableMixedValues() {
     SampleElements<UnhashableObject> unhashables = new Unhashables();
     Multimap<Integer, Object> multimap = ImmutableMultimap.<Integer, Object>of(
-        0, unhashables.e0, 2, "hey you", 0, unhashables.e1);
+        0, unhashables.e0(), 2, "hey you", 0, unhashables.e1());
     assertEquals(2, multimap.get(0).size());
-    assertTrue(multimap.get(0).contains(unhashables.e0));
-    assertTrue(multimap.get(0).contains(unhashables.e1));
+    assertTrue(multimap.get(0).contains(unhashables.e0()));
+    assertTrue(multimap.get(0).contains(unhashables.e1()));
     assertTrue(multimap.get(2).contains("hey you"));
   }
 
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java b/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
index a0ad481..ce2503e 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
@@ -452,7 +452,7 @@ public class ImmutableMultisetTest extends TestCase {
   public void testSerialization_multiple() {
     Collection<String> c = ImmutableMultiset.of("a", "b", "a");
     Collection<String> copy = SerializableTester.reserializeAndAssert(c);
-    assertThat(copy).has().exactly("a", "a", "b").inOrder();
+    assertThat(copy).containsExactly("a", "a", "b").inOrder();
   }
 
   @GwtIncompatible("SerializableTester")
@@ -460,7 +460,7 @@ public class ImmutableMultisetTest extends TestCase {
     Multiset<String> c = ImmutableMultiset.of("a", "b", "a");
     Collection<String> copy =
         LenientSerializableTester.reserializeAndAssertLenient(c.elementSet());
-    assertThat(copy).has().exactly("a", "b").inOrder();
+    assertThat(copy).containsExactly("a", "b").inOrder();
   }
 
   @GwtIncompatible("SerializableTester")
@@ -479,7 +479,7 @@ public class ImmutableMultisetTest extends TestCase {
 
   public void testIterationOrder() {
     Collection<String> c = ImmutableMultiset.of("a", "b", "a");
-    assertThat(c).has().exactly("a", "a", "b").inOrder();
+    assertThat(c).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testMultisetWrites() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
index 3d1d7b4..cedb746 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
@@ -17,6 +17,7 @@ package com.google.common.collect;
 import static com.google.common.collect.BoundType.OPEN;
 
 import com.google.common.annotations.GwtIncompatible;
+import com.google.common.testing.SerializableTester;
 
 import junit.framework.TestCase;
 
@@ -190,7 +191,13 @@ public class ImmutableRangeMapTest extends TestCase {
           ImmutableMap<Range<Integer>, Integer> expectedAsMap =
               ImmutableMap.of(range1, 1, range2, 2);
           ImmutableMap<Range<Integer>, Integer> asMap = rangeMap.asMapOfRanges();
+          ImmutableMap<Range<Integer>, Integer> descendingMap = rangeMap.asDescendingMapOfRanges();
           assertEquals(expectedAsMap, asMap);
+          assertEquals(expectedAsMap, descendingMap);
+          SerializableTester.reserializeAndAssert(asMap);
+          SerializableTester.reserializeAndAssert(descendingMap);
+          assertEquals(ImmutableList.copyOf(asMap.entrySet()).reverse(),
+              ImmutableList.copyOf(descendingMap.entrySet()));
 
           for (Range<Integer> query : RANGES) {
             assertEquals(expectedAsMap.get(query), asMap.get(query));
@@ -225,4 +232,27 @@ public class ImmutableRangeMapTest extends TestCase {
       }
     }
   }
+
+  public void testSerialization() {
+    ImmutableRangeMap<Integer, Integer> emptyRangeMap = ImmutableRangeMap.of();
+    SerializableTester.reserializeAndAssert(emptyRangeMap);
+
+    ImmutableRangeMap<Integer, Integer> nonEmptyRangeMap =
+        new ImmutableRangeMap.Builder<Integer, Integer>()
+            .put(Range.closed(2, 4), 5)
+            .put(Range.open(6, 7), 3)
+            .put(Range.closedOpen(8, 10), 4)
+            .put(Range.openClosed(15, 17), 2)
+        .build();
+
+    ImmutableMap<Range<Integer>, Integer> test = nonEmptyRangeMap.asMapOfRanges();
+
+    for (Range<Integer> range : test.keySet()) {
+      SerializableTester.reserializeAndAssert(range);
+    }
+
+    SerializableTester.reserializeAndAssert(test.keySet());
+
+    SerializableTester.reserializeAndAssert(nonEmptyRangeMap);
+  }
 }
diff --git a/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
index cf7843b..62033c6 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
@@ -154,7 +154,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
   public void testAll() {
     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.all();
 
-    assertThat(rangeSet.asRanges()).has().item(Range.<Integer>all());
+    assertThat(rangeSet.asRanges()).contains(Range.<Integer>all());
     assertTrue(rangeSet.contains(0));
     assertTrue(rangeSet.encloses(Range.<Integer>all()));
     assertTrue(rangeSet.enclosesAll(rangeSet));
@@ -164,7 +164,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
   public void testSingleBoundedRange() {
     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.closedOpen(1, 5));
 
-    assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 5));
+    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 5));
 
     assertTrue(rangeSet.encloses(Range.closed(3, 4)));
     assertTrue(rangeSet.encloses(Range.closedOpen(1, 4)));
@@ -185,7 +185,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
   public void testSingleBoundedBelowRange() {
     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.greaterThan(2));
 
-    assertThat(rangeSet.asRanges()).has().item(Range.greaterThan(2));
+    assertThat(rangeSet.asRanges()).contains(Range.greaterThan(2));
 
     assertTrue(rangeSet.encloses(Range.closed(3, 4)));
     assertTrue(rangeSet.encloses(Range.greaterThan(3)));
@@ -202,7 +202,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
   public void testSingleBoundedAboveRange() {
     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.atMost(3));
 
-    assertThat(rangeSet.asRanges()).has().item(Range.atMost(3));
+    assertThat(rangeSet.asRanges()).contains(Range.atMost(3));
 
     assertTrue(rangeSet.encloses(Range.closed(2, 3)));
     assertTrue(rangeSet.encloses(Range.lessThan(1)));
@@ -221,7 +221,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
 
     assertThat(rangeSet.asRanges())
-        .has().exactly(Range.closedOpen(1, 3), Range.closed(5, 8)).inOrder();
+        .containsExactly(Range.closedOpen(1, 3), Range.closed(5, 8)).inOrder();
 
     assertTrue(rangeSet.encloses(Range.closed(1, 2)));
     assertTrue(rangeSet.encloses(Range.open(5, 8)));
@@ -242,7 +242,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
         .add(Range.greaterThan(6)).add(Range.closedOpen(1, 3)).build();
 
     assertThat(rangeSet.asRanges())
-        .has().exactly(Range.closedOpen(1, 3), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.closedOpen(1, 3), Range.greaterThan(6)).inOrder();
 
     assertTrue(rangeSet.encloses(Range.closed(1, 2)));
     assertTrue(rangeSet.encloses(Range.open(6, 8)));
@@ -262,7 +262,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
         .add(Range.atMost(0)).add(Range.closedOpen(2, 5)).build();
 
     assertThat(rangeSet.asRanges())
-        .has().exactly(Range.atMost(0), Range.closedOpen(2, 5)).inOrder();
+        .containsExactly(Range.atMost(0), Range.closedOpen(2, 5)).inOrder();
 
     assertTrue(rangeSet.encloses(Range.closed(2, 4)));
     assertTrue(rangeSet.encloses(Range.open(-5, -2)));
@@ -378,6 +378,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
       }
 
       SerializableTester.reserializeAndAssert(built);
+      SerializableTester.reserializeAndAssert(built.asRanges());
     }
   }
 
@@ -391,7 +392,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
     ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
     ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
     assertEquals(expectedSet, asSet);
-    assertThat(asSet).has().exactlyAs(expectedSet).inOrder();
+    assertThat(asSet).containsExactlyElementsIn(expectedSet).inOrder();
     assertTrue(asSet.containsAll(expectedSet));
     SerializableTester.reserializeAndAssert(asSet);
   }
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
index cf50625..7a235cd 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
@@ -16,14 +16,15 @@
 
 package com.google.common.collect;
 
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.ImmutableSetMultimap.Builder;
-import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
-import com.google.common.collect.testing.features.MapFeature;
 import com.google.common.collect.testing.google.SetMultimapTestSuiteBuilder;
 import com.google.common.collect.testing.google.TestStringSetMultimapGenerator;
 import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
@@ -46,27 +47,47 @@ import java.util.Map.Entry;
  */
 @GwtCompatible(emulated = true)
 public class ImmutableSetMultimapTest extends TestCase {
+  private static final class ImmutableSetMultimapGenerator extends
+      TestStringSetMultimapGenerator {
+    @Override
+    protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+      ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
+      for (Entry<String, String> entry : entries) {
+        builder.put(entry.getKey(), entry.getValue());
+      }
+      return builder.build();
+    }
+  }
+
+  private static final class ImmutableSetMultimapCopyOfEntriesGenerator extends
+      TestStringSetMultimapGenerator {
+    @Override
+    protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+      return ImmutableSetMultimap.copyOf(Arrays.asList(entries));
+    }
+  }
+
   @GwtIncompatible("suite")
   public static Test suite() {
     TestSuite suite = new TestSuite();
     suite.addTestSuite(ImmutableSetMultimapTest.class);
-    suite.addTest(SetMultimapTestSuiteBuilder.using(new TestStringSetMultimapGenerator() {
-        @Override
-        protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
-          ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
-          for (Entry<String, String> entry : entries) {
-            builder.put(entry.getKey(), entry.getValue());
-          }
-          return builder.build();
-        }
-      })
-      .named("ImmutableSetMultimap")
-      .withFeatures(
-          MapFeature.ALLOWS_ANY_NULL_QUERIES,
-          CollectionFeature.KNOWN_ORDER,
-          CollectionFeature.SERIALIZABLE,
-          CollectionSize.ANY)
-      .createTestSuite());
+    suite.addTest(SetMultimapTestSuiteBuilder.using(new ImmutableSetMultimapGenerator())
+        .named("ImmutableSetMultimap")
+        .withFeatures(
+            ALLOWS_ANY_NULL_QUERIES,
+            KNOWN_ORDER,
+            SERIALIZABLE,
+            CollectionSize.ANY)
+        .createTestSuite());
+    suite.addTest(SetMultimapTestSuiteBuilder.using(
+            new ImmutableSetMultimapCopyOfEntriesGenerator())
+        .named("ImmutableSetMultimap.copyOf[Iterable<Entry>]")
+        .withFeatures(
+            ALLOWS_ANY_NULL_QUERIES,
+            KNOWN_ORDER,
+            SERIALIZABLE,
+            CollectionSize.ANY)
+            .createTestSuite());
     return suite;
   }
 
@@ -249,13 +270,13 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
-    assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
-    assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
-    assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
+    assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
   }
 
   public void testBuilderOrderKeysByDuplicates() {
@@ -274,13 +295,13 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("bb", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
-    assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
-    assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
-    assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+    assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
+    assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+    assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
   }
 
   public void testBuilderOrderValuesBy() {
@@ -294,10 +315,10 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
-    assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+    assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
     assertEquals(Collections.reverseOrder(),
         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -321,10 +342,10 @@ public class ImmutableSetMultimapTest extends TestCase {
     builder.put("a", 2);
     builder.put("b", 6);
     ImmutableSetMultimap<String, Integer> multimap = builder.build();
-    assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
-    assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
-    assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
-    assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+    assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+    assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+    assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
     assertEquals(Collections.reverseOrder(),
         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -536,8 +557,8 @@ public class ImmutableSetMultimapTest extends TestCase {
         .put("b", 1)
         .build();
     multimap = SerializableTester.reserialize(multimap);
-    assertThat(multimap.keySet()).has().exactly("b", "a").inOrder();
-    assertThat(multimap.get("a")).has().exactly(10, 2).inOrder();
+    assertThat(multimap.keySet()).containsExactly("b", "a").inOrder();
+    assertThat(multimap.get("a")).containsExactly(10, 2).inOrder();
     assertEquals(Ordering.usingToString(),
         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
     assertEquals(Ordering.usingToString(),
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
index 43a9352..839671c 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
@@ -153,7 +153,7 @@ public class ImmutableSetTest extends AbstractImmutableSetTest {
     // now we'll get the varargs overload
     ImmutableSet<String> set = ImmutableSet.of(
         "a", "b", "c", "c", "c", "c", "b", "b", "a", "a", "c", "c", "c", "a");
-    assertThat(set).has().exactly("a", "b", "c").inOrder();
+    assertThat(set).containsExactly("a", "b", "c").inOrder();
   }
 
   public void testCreation_arrayOfArray() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
index 8ea6660..daf1ba0 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
@@ -23,11 +23,13 @@ import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableSortedMap.Builder;
 import com.google.common.collect.testing.ListTestSuiteBuilder;
+import com.google.common.collect.testing.MapTestSuiteBuilder;
 import com.google.common.collect.testing.NavigableMapTestSuiteBuilder;
 import com.google.common.collect.testing.SortedMapInterfaceTest;
 import com.google.common.collect.testing.features.CollectionFeature;
 import com.google.common.collect.testing.features.CollectionSize;
 import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapCopyOfEntriesGenerator;
 import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapEntryListGenerator;
 import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapGenerator;
 import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapKeyListGenerator;
@@ -73,6 +75,16 @@ public class ImmutableSortedMapTest extends TestCase {
             MapFeature.ALLOWS_ANY_NULL_QUERIES)
         .named("ImmutableSortedMap")
         .createTestSuite());
+    suite.addTest(MapTestSuiteBuilder.using(
+        new ImmutableSortedMapCopyOfEntriesGenerator())
+        .withFeatures(
+            CollectionSize.ANY,
+            CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
+            CollectionFeature.KNOWN_ORDER,
+            MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+            MapFeature.ALLOWS_ANY_NULL_QUERIES)
+        .named("ImmutableSortedMap.copyOf[Iterable<Entry>]")
+        .createTestSuite());
 
     suite.addTest(ListTestSuiteBuilder.using(
         new ImmutableSortedMapEntryListGenerator())
@@ -290,6 +302,14 @@ public class ImmutableSortedMapTest extends TestCase {
           "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
     }
 
+    public void testBuilder_orderEntriesByValueFails() {
+      ImmutableSortedMap.Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
+      try {
+        builder.orderEntriesByValue(Ordering.natural());
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {}
+    }
+
     public void testBuilder_withImmutableEntry() {
       ImmutableSortedMap<String, Integer> map =
           ImmutableSortedMap.<String, Integer>naturalOrder()
@@ -710,7 +730,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testHeadMapInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3)).inOrder();
   }
@@ -719,14 +739,14 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testHeadMapExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testTailMapInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
         Maps.immutableEntry("two", 2)).inOrder();
   }
 
@@ -734,21 +754,21 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testTailMapExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("two", 2));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testSubMapExclusiveExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3));
   }
 
   @SuppressWarnings("unchecked") // varargs
   public void testSubMapInclusiveExclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3)).inOrder();
   }
 
@@ -756,7 +776,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testSubMapExclusiveInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
         Maps.immutableEntry("two", 2)).inOrder();
   }
 
@@ -764,7 +784,7 @@ public class ImmutableSortedMapTest extends TestCase {
   public void testSubMapInclusiveInclusive() {
     Map<String, Integer> map =
         ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
-    assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+    assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
         Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
   }
 
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
index ed069fb..34df049 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
@@ -422,13 +422,13 @@ public class ImmutableSortedMultisetTest extends TestCase {
   public void testSerialization_multiple() {
     Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
     Collection<String> copy = SerializableTester.reserializeAndAssert(c);
-    assertThat(copy).has().exactly("a", "a", "b").inOrder();
+    assertThat(copy).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testSerialization_elementSet() {
     Multiset<String> c = ImmutableSortedMultiset.of("a", "b", "a");
     Collection<String> copy = SerializableTester.reserializeAndAssert(c.elementSet());
-    assertThat(copy).has().exactly("a", "b").inOrder();
+    assertThat(copy).containsExactly("a", "b").inOrder();
   }
 
   public void testSerialization_entrySet() {
@@ -446,7 +446,7 @@ public class ImmutableSortedMultisetTest extends TestCase {
 
   public void testIterationOrder() {
     Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
-    assertThat(c).has().exactly("a", "a", "b").inOrder();
+    assertThat(c).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testMultisetWrites() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
index ea0c825..9602610 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
@@ -264,7 +264,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSingle_headSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.headSet("g") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("g")).has().item("e");
+    assertThat(set.headSet("g")).contains("e");
     assertSame(of(), set.headSet("c"));
     assertSame(of(), set.headSet("e"));
   }
@@ -272,16 +272,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSingle_tailSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.tailSet("c") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("c")).has().item("e");
-    assertThat(set.tailSet("e")).has().item("e");
+    assertThat(set.tailSet("c")).contains("e");
+    assertThat(set.tailSet("e")).contains("e");
     assertSame(of(), set.tailSet("g"));
   }
 
   public void testSingle_subSet() {
     SortedSet<String> set = of("e");
     assertTrue(set.subSet("c", "g") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("c", "g")).has().item("e");
-    assertThat(set.subSet("e", "g")).has().item("e");
+    assertThat(set.subSet("c", "g")).contains("e");
+    assertThat(set.subSet("e", "g")).contains("e");
     assertSame(of(), set.subSet("f", "g"));
     assertSame(of(), set.subSet("c", "e"));
     assertSame(of(), set.subSet("c", "d"));
@@ -306,7 +306,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testOf_ordering() {
     SortedSet<String> set = of("e", "a", "f", "b", "d", "c");
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   /*
@@ -355,7 +355,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testOf_ordering_dupes() {
     SortedSet<String> set = of("e", "a", "e", "f", "b", "b", "d", "a", "c");
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testOf_comparator() {
@@ -366,8 +366,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testOf_headSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.headSet("e") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("e")).has().exactly("b", "c", "d").inOrder();
-    assertThat(set.headSet("g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.headSet("e")).containsExactly("b", "c", "d").inOrder();
+    assertThat(set.headSet("g")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.headSet("a"));
     assertSame(of(), set.headSet("b"));
   }
@@ -375,16 +375,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testOf_tailSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.tailSet("e") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("e")).has().exactly("e", "f").inOrder();
-    assertThat(set.tailSet("a")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.tailSet("e")).containsExactly("e", "f").inOrder();
+    assertThat(set.tailSet("a")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.tailSet("g"));
   }
 
   public void testOf_subSet() {
     SortedSet<String> set = of("e", "f", "b", "d", "c");
     assertTrue(set.subSet("c", "e") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("c", "e")).has().exactly("c", "d").inOrder();
-    assertThat(set.subSet("a", "g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+    assertThat(set.subSet("c", "e")).containsExactly("c", "d").inOrder();
+    assertThat(set.subSet("a", "g")).containsExactly("b", "c", "d", "e", "f").inOrder();
     assertSame(of(), set.subSet("a", "b"));
     assertSame(of(), set.subSet("g", "h"));
     assertSame(of(), set.subSet("c", "c"));
@@ -424,14 +424,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testExplicit_ordering() {
     SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
         "in", "the", "quick", "jumped", "over", "a").build();
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testExplicit_ordering_dupes() {
     SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
         "in", "the", "quick", "brown", "fox", "jumped",
         "over", "a", "lazy", "dog").build();
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testExplicit_contains() {
@@ -461,9 +461,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.headSet("a") instanceof ImmutableSortedSet);
     assertTrue(set.headSet("fish") instanceof ImmutableSortedSet);
-    assertThat(set.headSet("fish")).has().exactly("a", "in", "the").inOrder();
-    assertThat(set.headSet("california")).has()
-        .exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set.headSet("fish")).containsExactly("a", "in", "the").inOrder();
+    assertThat(set.headSet("california"))
+        .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.headSet("a").isEmpty());
     assertTrue(set.headSet("").isEmpty());
   }
@@ -473,9 +473,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.tailSet("california") instanceof ImmutableSortedSet);
     assertTrue(set.tailSet("fish") instanceof ImmutableSortedSet);
-    assertThat(set.tailSet("fish")).has().exactly("over", "quick", "jumped").inOrder();
+    assertThat(set.tailSet("fish")).containsExactly("over", "quick", "jumped").inOrder();
     assertThat(
-        set.tailSet("a")).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+        set.tailSet("a")).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.tailSet("california").isEmpty());
   }
 
@@ -484,9 +484,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         "in", "the", "quick", "jumped", "over", "a").build();
     assertTrue(set.subSet("the", "quick") instanceof ImmutableSortedSet);
     assertTrue(set.subSet("", "b") instanceof ImmutableSortedSet);
-    assertThat(set.subSet("the", "quick")).has().exactly("the", "over").inOrder();
+    assertThat(set.subSet("the", "quick")).containsExactly("the", "over").inOrder();
     assertThat(set.subSet("a", "california"))
-        .has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+        .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertTrue(set.subSet("", "b").isEmpty());
     assertTrue(set.subSet("vermont", "california").isEmpty());
     assertTrue(set.subSet("aaa", "zzz").isEmpty());
@@ -530,13 +530,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testCopyOf_ordering() {
     SortedSet<String> set =
         copyOf(asList("e", "a", "f", "b", "d", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_ordering_dupes() {
     SortedSet<String> set =
         copyOf(asList("e", "a", "e", "f", "b", "b", "d", "a", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_subSet() {
@@ -567,13 +567,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
 
   public void testCopyOf_iterator_ordering() {
     SortedSet<String> set = copyOf(asIterator("e", "a", "f", "b", "d", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_iterator_ordering_dupes() {
     SortedSet<String> set =
         copyOf(asIterator("e", "a", "e", "f", "b", "b", "d", "a", "c"));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_iterator_comparator() {
@@ -584,7 +584,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testCopyOf_sortedSet_ordering() {
     SortedSet<String> set =
         copyOf(Sets.newTreeSet(asList("e", "a", "f", "b", "d", "c")));
-    assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
   }
 
   public void testCopyOf_sortedSet_comparator() {
@@ -596,7 +596,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> set =
         ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
             "in", "the", "quick", "jumped", "over", "a"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_ordering_dupes() {
@@ -604,7 +604,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
             "in", "the", "quick", "brown", "fox", "jumped", "over", "a",
             "lazy", "dog"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_comparator() {
@@ -618,7 +618,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> set =
         ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
             "in", "the", "quick", "jumped", "over", "a"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_iterator_ordering_dupes() {
@@ -626,7 +626,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
         ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
             "in", "the", "quick", "brown", "fox", "jumped", "over", "a",
             "lazy", "dog"));
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
   }
 
   public void testCopyOfExplicit_iterator_comparator() {
@@ -640,14 +640,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
     Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
     SortedSet<String> set = copyOf(input);
-    assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+    assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
   }
 
   public void testCopyOfSorted_natural_ordering() {
     SortedSet<String> input = Sets.newTreeSet(
         asList("in", "the", "quick", "jumped", "over", "a"));
     SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
-    assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+    assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
   }
 
   public void testCopyOfSorted_natural_comparator() {
@@ -661,7 +661,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
     Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
     SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
-    assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+    assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
     assertSame(STRING_LENGTH, set.comparator());
   }
 
@@ -760,7 +760,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testReverseOrder() {
     SortedSet<String> set = ImmutableSortedSet.<String>reverseOrder()
         .add("a", "b", "c").build();
-    assertThat(set).has().exactly("c", "b", "a").inOrder();
+    assertThat(set).containsExactly("c", "b", "a").inOrder();
     assertEquals(Ordering.natural().reverse(), set.comparator());
   }
 
@@ -775,13 +775,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
   public void testSupertypeComparator() {
     SortedSet<Integer> set = new ImmutableSortedSet.Builder<Integer>(TO_STRING)
         .add(3, 12, 101, 44).build();
-    assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+    assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
   }
 
   public void testSupertypeComparatorSubtypeElements() {
     SortedSet<Number> set = new ImmutableSortedSet.Builder<Number>(TO_STRING)
         .add(3, 12, 101, 44).build();
-    assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+    assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
   }
 
   @Override <E extends Comparable<E>> ImmutableSortedSet.Builder<E> builder() {
@@ -923,7 +923,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
       assertThat(set.headSet(strings[i], true))
-          .has().exactlyAs(sortedNumberNames(0, i + 1)).inOrder();
+          .containsExactlyElementsIn(sortedNumberNames(0, i + 1))
+          .inOrder();
     }
   }
 
@@ -932,8 +933,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.headSet(strings[i], false)).has().exactlyAs(
-          sortedNumberNames(0, i)).inOrder();
+      assertThat(set.headSet(strings[i], false))
+          .containsExactlyElementsIn(sortedNumberNames(0, i))
+          .inOrder();
     }
   }
 
@@ -942,8 +944,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.tailSet(strings[i], true)).has().exactlyAs(
-          sortedNumberNames(i, strings.length)).inOrder();
+      assertThat(set.tailSet(strings[i], true))
+          .containsExactlyElementsIn(sortedNumberNames(i, strings.length))
+          .inOrder();
     }
   }
 
@@ -952,8 +955,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
     Arrays.sort(strings);
     for (int i = 0; i < strings.length; i++) {
-      assertThat(set.tailSet(strings[i], false)).has().exactlyAs(
-          sortedNumberNames(i + 1, strings.length)).inOrder();
+      assertThat(set.tailSet(strings[i], false))
+          .containsExactlyElementsIn(sortedNumberNames(i + 1, strings.length))
+          .inOrder();
     }
   }
 
@@ -964,7 +968,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], false, strings[j], false))
-            .has().exactlyAs(sortedNumberNames(Math.min(i + 1, j), j)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(Math.min(i + 1, j), j))
+            .inOrder();
       }
     }
   }
@@ -976,7 +981,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], true, strings[j], false))
-            .has().exactlyAs(sortedNumberNames(i, j)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i, j))
+            .inOrder();
       }
     }
   }
@@ -988,7 +994,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], false, strings[j], true))
-            .has().exactlyAs(sortedNumberNames(i + 1, j + 1)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i + 1, j + 1))
+            .inOrder();
       }
     }
   }
@@ -1000,7 +1007,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
     for (int i = 0; i < strings.length; i++) {
       for (int j = i; j < strings.length; j++) {
         assertThat(set.subSet(strings[i], true, strings[j], true))
-            .has().exactlyAs(sortedNumberNames(i, j + 1)).inOrder();
+            .containsExactlyElementsIn(sortedNumberNames(i, j + 1))
+            .inOrder();
       }
     }
   }
diff --git a/guava-tests/test/com/google/common/collect/ImmutableTableTest.java b/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
index 7d88619..0a75cf8 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
@@ -185,9 +185,9 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     validateTableCopies(table);
     // Even though rowKeySet, columnKeySet, and cellSet have the same
     // iteration ordering, row has an inconsistent ordering.
-    assertThat(table.row('b').keySet()).has().exactly(1, 2).inOrder();
+    assertThat(table.row('b').keySet()).containsExactly(1, 2).inOrder();
     assertThat(ImmutableTable.copyOf(table).row('b').keySet())
-        .has().exactly(2, 1).inOrder();
+        .containsExactly(2, 1).inOrder();
   }
 
   public void testCopyOfSparse() {
@@ -228,10 +228,10 @@ public class ImmutableTableTest extends AbstractTableReadTest {
         = builder.orderRowsBy(Ordering.natural())
             .orderColumnsBy(Ordering.natural())
             .putAll(table).build();
-    assertThat(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
-    assertThat(copy.columnKeySet()).has().exactly(1, 2).inOrder();
-    assertThat(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
-    assertThat(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
+    assertThat(copy.rowKeySet()).containsExactly('a', 'b').inOrder();
+    assertThat(copy.columnKeySet()).containsExactly(1, 2).inOrder();
+    assertThat(copy.values()).containsExactly("baz", "bar", "foo").inOrder();
+    assertThat(copy.row('b').keySet()).containsExactly(1, 2).inOrder();
   }
 
   public void testBuilder_orderRowsAndColumnsBy_sparse() {
@@ -249,12 +249,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
-    assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
-    assertThat(table.values()).has().exactly("cat", "axe", "baz", "tub",
+    assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+    assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+    assertThat(table.values()).containsExactly("cat", "axe", "baz", "tub",
         "dog", "bar", "foo", "foo", "bar").inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
-    assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
+    assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
   }
 
   public void testBuilder_orderRowsAndColumnsBy_dense() {
@@ -271,12 +271,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.values()).has().exactly("baz", "bar", "foo", "dog",
+    assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.values()).containsExactly("baz", "bar", "foo", "dog",
         "cat", "baz", "bar", "foo").inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
   }
 
   public void testBuilder_orderRowsBy_sparse() {
@@ -293,8 +293,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
-    assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+    assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+    assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
   }
 
   public void testBuilder_orderRowsBy_dense() {
@@ -310,8 +310,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
-    assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+    assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+    assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
   }
 
   public void testBuilder_orderColumnsBy_sparse() {
@@ -328,8 +328,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('r', 4, "foo");
     builder.put('x', 5, "bar");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
+    assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
   }
 
   public void testBuilder_orderColumnsBy_dense() {
@@ -345,11 +345,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
     builder.put('a', 2, "bar");
     builder.put('a', 1, "baz");
     Table<Character, Integer, String> table = builder.build();
-    assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
-    assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
+    assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+    assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
   }
 
   @GwtIncompatible("Mind-bogglingly slow in GWT")
+  @SuppressUnderAndroid // slow
   public void testOverflowCondition() {
     // See https://code.google.com/p/guava-libraries/issues/detail?id=1322 for details.
     ImmutableTable.Builder<Integer, Integer, String> builder = ImmutableTable.builder();
diff --git a/guava-tests/test/com/google/common/collect/IterablesTest.java b/guava-tests/test/com/google/common/collect/IterablesTest.java
index 1dbbb97..9a853cc 100644
--- a/guava-tests/test/com/google/common/collect/IterablesTest.java
+++ b/guava-tests/test/com/google/common/collect/IterablesTest.java
@@ -28,7 +28,6 @@ import static java.util.Collections.emptyList;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.testing.IteratorTester;
@@ -262,14 +261,10 @@ public class IterablesTest extends TestCase {
 
   public void testTryFind() {
     Iterable<String> list = newArrayList("cool", "pants");
-    assertEquals(Optional.of("cool"),
-        Iterables.tryFind(list, Predicates.equalTo("cool")));
-    assertEquals(Optional.of("pants"),
-        Iterables.tryFind(list, Predicates.equalTo("pants")));
-    assertEquals(Optional.of("cool"),
-        Iterables.tryFind(list, Predicates.alwaysTrue()));
-    assertEquals(Optional.absent(),
-        Iterables.tryFind(list, Predicates.alwaysFalse()));
+    assertThat(Iterables.tryFind(list, Predicates.equalTo("cool"))).hasValue("cool");
+    assertThat(Iterables.tryFind(list, Predicates.equalTo("pants"))).hasValue("pants");
+    assertThat(Iterables.tryFind(list, Predicates.alwaysTrue())).hasValue("cool");
+    assertThat(Iterables.tryFind(list, Predicates.alwaysFalse())).isAbsent();
     assertCanIterateAgain(list);
   }
 
@@ -283,7 +278,7 @@ public class IterablesTest extends TestCase {
     Iterable<TypeA> alist = Lists
         .newArrayList(new TypeA(), new TypeA(), hasBoth, new TypeA());
     Iterable<TypeB> blist = Iterables.filter(alist, TypeB.class);
-    assertThat(blist).iteratesAs(hasBoth);
+    assertThat(blist).containsExactly(hasBoth).inOrder();
   }
 
   public void testTransform() {
@@ -411,8 +406,7 @@ public class IterablesTest extends TestCase {
     int n = 4;
     Iterable<Integer> repeated
         = Iterables.concat(Collections.nCopies(n, iterable));
-    assertThat(repeated).iteratesAs(
-        1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3);
+    assertThat(repeated).containsExactly(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3).inOrder();
   }
 
   public void testPartition_badSize() {
@@ -510,7 +504,7 @@ public class IterablesTest extends TestCase {
     List<String> freshlyAdded = newArrayList("freshly", "added");
 
     boolean changed = Iterables.addAll(alreadyThere, freshlyAdded);
-    assertThat(alreadyThere).has().exactly(
+    assertThat(alreadyThere).containsExactly(
         "already", "there", "freshly", "added").inOrder();
     assertTrue(changed);
   }
@@ -688,7 +682,7 @@ public class IterablesTest extends TestCase {
     Iterable<String> tail = skip(set, 1);
     set.remove("b");
     set.addAll(newArrayList("A", "B", "C"));
-    assertThat(tail).iteratesAs("c", "A", "B", "C");
+    assertThat(tail).containsExactly("c", "A", "B", "C").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -696,7 +690,7 @@ public class IterablesTest extends TestCase {
     Iterable<String> tail = skip(list, 1);
     list.subList(1, 3).clear();
     list.addAll(0, newArrayList("A", "B", "C"));
-    assertThat(tail).iteratesAs("B", "C", "a");
+    assertThat(tail).containsExactly("B", "C", "a").inOrder();
   }
 
   public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -1127,12 +1121,12 @@ public class IterablesTest extends TestCase {
     assertEquals("Iterables.consumingIterable(...)", consumingIterable.toString());
     Iterator<String> consumingIterator = consumingIterable.iterator();
 
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
 
     assertTrue(consumingIterator.hasNext());
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
     assertEquals("a", consumingIterator.next());
-    assertThat(list).has().item("b");
+    assertThat(list).contains("b");
 
     assertTrue(consumingIterator.hasNext());
     assertEquals("b", consumingIterator.next());
diff --git a/guava-tests/test/com/google/common/collect/IteratorsTest.java b/guava-tests/test/com/google/common/collect/IteratorsTest.java
index c3f9263..92e9b1f 100644
--- a/guava-tests/test/com/google/common/collect/IteratorsTest.java
+++ b/guava-tests/test/com/google/common/collect/IteratorsTest.java
@@ -16,6 +16,7 @@
 
 package com.google.common.collect;
 
+import static com.google.common.collect.CollectPreconditions.checkRemove;
 import static com.google.common.collect.Iterators.advance;
 import static com.google.common.collect.Iterators.get;
 import static com.google.common.collect.Iterators.getLast;
@@ -45,6 +46,7 @@ import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -194,8 +196,7 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: <one, two>",
-                   expected.getMessage());
+      assertThat(expected).hasMessage("expected one element but was: <one, two>");
     }
   }
 
@@ -206,9 +207,8 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: "
-                   + "<one, two, three, four, five>",
-                   expected.getMessage());
+      assertThat(expected)
+          .hasMessage("expected one element but was: " + "<one, two, three, four, five>");
     }
   }
 
@@ -219,9 +219,8 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator);
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: "
-                   + "<one, two, three, four, five, ...>",
-                   expected.getMessage());
+      assertThat(expected)
+          .hasMessage("expected one element but was: " + "<one, two, three, four, five, ...>");
     }
   }
 
@@ -246,8 +245,7 @@ public class IteratorsTest extends TestCase {
       Iterators.getOnlyElement(iterator, "x");
       fail();
     } catch (IllegalArgumentException expected) {
-      assertEquals("expected one element but was: <foo, bar>",
-                   expected.getMessage());
+      assertThat(expected).hasMessage("expected one element but was: <foo, bar>");
     }
   }
 
@@ -429,22 +427,19 @@ public class IteratorsTest extends TestCase {
   public void testTryFind_firstElement() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("cool",
-        Iterators.tryFind(iterator, Predicates.equalTo("cool")).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.equalTo("cool"))).hasValue("cool");
   }
 
   public void testTryFind_lastElement() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("pants",
-        Iterators.tryFind(iterator, Predicates.equalTo("pants")).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.equalTo("pants"))).hasValue("pants");
   }
 
   public void testTryFind_alwaysTrue() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertEquals("cool",
-        Iterators.tryFind(iterator, Predicates.alwaysTrue()).get());
+    assertThat(Iterators.tryFind(iterator, Predicates.alwaysTrue())).hasValue("cool");
   }
 
   public void testTryFind_alwaysFalse_orDefault() {
@@ -458,8 +453,7 @@ public class IteratorsTest extends TestCase {
   public void testTryFind_alwaysFalse_isPresent() {
     Iterable<String> list = Lists.newArrayList("cool", "pants");
     Iterator<String> iterator = list.iterator();
-    assertFalse(
-        Iterators.tryFind(iterator, Predicates.alwaysFalse()).isPresent());
+    assertThat(Iterators.tryFind(iterator, Predicates.alwaysFalse())).isAbsent();
     assertFalse(iterator.hasNext());
   }
 
@@ -626,6 +620,69 @@ public class IteratorsTest extends TestCase {
     assertFalse(cycle.hasNext());
   }
 
+  /** An Iterable whose Iterator is rigorous in checking for concurrent modification. */
+  private static final class PickyIterable<E> implements Iterable<E> {
+    final List<E> elements;
+    int modCount = 0;
+
+    PickyIterable(E... elements) {
+      this.elements = new ArrayList<E>(asList(elements));
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return new PickyIterator();
+    }
+
+    final class PickyIterator implements Iterator<E> {
+      int expectedModCount = modCount;
+      int index = 0;
+      boolean canRemove;
+
+      @Override
+      public boolean hasNext() {
+        checkConcurrentModification();
+        return index < elements.size();
+      }
+
+      @Override
+      public E next() {
+        checkConcurrentModification();
+        if (!hasNext()) {
+          throw new NoSuchElementException();
+        }
+        canRemove = true;
+        return elements.get(index++);
+      }
+
+      @Override
+      public void remove() {
+        checkConcurrentModification();
+        checkRemove(canRemove);
+        elements.remove(--index);
+        expectedModCount = ++modCount;
+        canRemove = false;
+      }
+
+      void checkConcurrentModification() {
+        if (expectedModCount != modCount) {
+          throw new ConcurrentModificationException();
+        }
+      }
+    }
+  }
+
+  public void testCycleRemoveAfterHasNextExtraPicky() {
+    PickyIterable<String> iterable = new PickyIterable("a");
+    Iterator<String> cycle = Iterators.cycle(iterable);
+    assertTrue(cycle.hasNext());
+    assertEquals("a", cycle.next());
+    assertTrue(cycle.hasNext());
+    cycle.remove();
+    assertTrue(iterable.elements.isEmpty());
+    assertFalse(cycle.hasNext());
+  }
+
   public void testCycleNoSuchElementException() {
     Iterable<String> iterable = Lists.newArrayList("a");
     Iterator<String> cycle = Iterators.cycle(iterable);
@@ -765,7 +822,7 @@ public class IteratorsTest extends TestCase {
 
     boolean changed = Iterators.addAll(alreadyThere,
                                        Iterators.<String>emptyIterator());
-    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+    assertThat(alreadyThere).containsExactly("already", "there").inOrder();
     assertFalse(changed);
   }
 
@@ -775,7 +832,7 @@ public class IteratorsTest extends TestCase {
 
     boolean changed = Iterators.addAll(alreadyThere, freshlyAdded.iterator());
 
-    assertThat(alreadyThere).has().exactly("already", "there", "freshly", "added");
+    assertThat(alreadyThere).containsExactly("already", "there", "freshly", "added");
     assertTrue(changed);
   }
 
@@ -785,7 +842,7 @@ public class IteratorsTest extends TestCase {
     List<String> oneMore = Lists.newArrayList("there");
 
     boolean changed = Iterators.addAll(alreadyThere, oneMore.iterator());
-    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+    assertThat(alreadyThere).containsExactly("already", "there").inOrder();
     assertFalse(changed);
   }
 
@@ -1523,12 +1580,12 @@ public class IteratorsTest extends TestCase {
 
     assertEquals("Iterators.consumingIterator(...)", consumingIterator.toString());
 
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
 
     assertTrue(consumingIterator.hasNext());
-    assertThat(list).has().exactly("a", "b").inOrder();
+    assertThat(list).containsExactly("a", "b").inOrder();
     assertEquals("a", consumingIterator.next());
-    assertThat(list).has().item("b");
+    assertThat(list).contains("b");
 
     assertTrue(consumingIterator.hasNext());
     assertEquals("b", consumingIterator.next());
diff --git a/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java b/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
index 80bbcc1..fef4863 100644
--- a/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
@@ -151,8 +151,8 @@ public class LinkedHashMultimapTest extends TestCase {
     multimap.put("c", 4);
     multimap.remove("a", 1);
     multimap = SerializableTester.reserializeAndAssert(multimap);
-    assertThat(multimap.keySet()).has().exactly("a", "b", "c").inOrder();
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.keySet()).containsExactly("a", "b", "c").inOrder();
+    assertThat(multimap.entries()).containsExactly(
         mapEntry("b", 2),
         mapEntry("a", 3),
         mapEntry("c", 4)).inOrder();
@@ -160,12 +160,12 @@ public class LinkedHashMultimapTest extends TestCase {
   }
 
   private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
-    assertThat(multimap.get("foo")).has().exactly(5, 3).inOrder();
-    assertThat(multimap.get("bar")).has().exactly(4, 1).inOrder();
-    assertThat(multimap.get("cow")).has().item(2);
+    assertThat(multimap.get("foo")).containsExactly(5, 3).inOrder();
+    assertThat(multimap.get("bar")).containsExactly(4, 1).inOrder();
+    assertThat(multimap.get("cow")).contains(2);
 
-    assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
-    assertThat(multimap.values()).has().exactly(5, 4, 3, 2, 1).inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+    assertThat(multimap.values()).containsExactly(5, 4, 3, 2, 1).inOrder();
 
     Iterator<Map.Entry<String, Integer>> entryIterator =
         multimap.entries().iterator();
@@ -179,28 +179,28 @@ public class LinkedHashMultimapTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = collectionIterator.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(5, 3).inOrder();
+    assertThat(entry.getValue()).containsExactly(5, 3).inOrder();
     entry = collectionIterator.next();
     assertEquals("bar", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(4, 1).inOrder();
+    assertThat(entry.getValue()).containsExactly(4, 1).inOrder();
     entry = collectionIterator.next();
     assertEquals("cow", entry.getKey());
-    assertThat(entry.getValue()).has().item(2);
+    assertThat(entry.getValue()).contains(2);
   }
 
   public void testOrderingUpdates() {
     Multimap<String, Integer> multimap = initializeMultimap5();
 
-    assertThat(multimap.replaceValues("foo", asList(6, 7))).has().exactly(5, 3).inOrder();
-    assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
-    assertThat(multimap.removeAll("foo")).has().exactly(6, 7).inOrder();
-    assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+    assertThat(multimap.replaceValues("foo", asList(6, 7))).containsExactly(5, 3).inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+    assertThat(multimap.removeAll("foo")).containsExactly(6, 7).inOrder();
+    assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
     assertTrue(multimap.remove("bar", 4));
-    assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+    assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
     assertTrue(multimap.remove("bar", 1));
-    assertThat(multimap.keySet()).has().item("cow");
+    assertThat(multimap.keySet()).contains("cow");
     multimap.put("bar", 9);
-    assertThat(multimap.keySet()).has().exactly("cow", "bar").inOrder();
+    assertThat(multimap.keySet()).containsExactly("cow", "bar").inOrder();
   }
 
   public void testToStringNullExact() {
diff --git a/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java b/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
index ca359cb..ebea3ef 100644
--- a/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
@@ -121,13 +121,13 @@ public class LinkedHashMultisetTest extends TestCase {
     ms.add("a");
     ms.add("b", 2);
     ms.add("c");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.remove("b");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.add("b");
-    assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
     ms.remove("b", 2);
     ms.add("b");
-    assertThat(ms.elementSet()).has().exactly("a", "c", "b").inOrder();
+    assertThat(ms.elementSet()).containsExactly("a", "c", "b").inOrder();
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java b/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
index bc4a2df..ea0f49f 100644
--- a/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
@@ -98,8 +98,8 @@ public class LinkedListMultimapTest extends TestCase {
     Multimap<String, Integer> multimap = create();
     multimap.put("foo", 1);
     multimap.put("foo", 3);
-    assertFalse(multimap.get("foo") instanceof RandomAccess);
-    assertFalse(multimap.get("bar") instanceof RandomAccess);
+    assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+    assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
   }
 
   /**
@@ -136,7 +136,7 @@ public class LinkedListMultimapTest extends TestCase {
     LinkedListMultimap<String, Integer> copy =
         LinkedListMultimap.create(multimap);
     assertEquals(multimap, copy);
-    assertThat(copy.entries()).has().exactlyAs(multimap.entries()).inOrder();
+    assertThat(copy.entries()).containsExactlyElementsIn(multimap.entries()).inOrder();
   }
 
   public void testCreateFromSize() {
@@ -230,7 +230,7 @@ public class LinkedListMultimapTest extends TestCase {
     List<Integer> foos = map.get("foo");
     Collection<Integer> values = map.values();
     assertEquals(asList(1, 2), foos);
-    assertThat(values).has().exactly(1, 2, 3).inOrder();
+    assertThat(values).containsExactly(1, 2, 3).inOrder();
     map.clear();
     assertEquals(Collections.emptyList(), foos);
     assertThat(values).isEmpty();
@@ -257,7 +257,7 @@ public class LinkedListMultimapTest extends TestCase {
     map.put("bar", 4);
     assertEquals("[bar=1, foo=2, bar=3, bar=4]",
         map.entries().toString());
-    assertThat(map.keys()).has().exactly("bar", "foo", "bar", "bar").inOrder();
+    assertThat(map.keys()).containsExactly("bar", "foo", "bar", "bar").inOrder();
     map.keys().remove("bar"); // bar is no longer the first key!
     assertEquals("{foo=[2], bar=[3, 4]}", map.toString());
   }
@@ -303,7 +303,7 @@ public class LinkedListMultimapTest extends TestCase {
         = map.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = entries.next();
     assertEquals("bar", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(1, 3).inOrder();
+    assertThat(entry.getValue()).containsExactly(1, 3).inOrder();
     try {
       entry.setValue(Arrays.<Integer>asList());
       fail("UnsupportedOperationException expected");
@@ -311,7 +311,7 @@ public class LinkedListMultimapTest extends TestCase {
     entries.remove(); // clear
     entry = entries.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().item(2);
+    assertThat(entry.getValue()).contains(2);
     assertFalse(entries.hasNext());
     assertEquals("{foo=[2]}", map.toString());
   }
diff --git a/guava-tests/test/com/google/common/collect/ListsTest.java b/guava-tests/test/com/google/common/collect/ListsTest.java
index 7c422f4..e5a2efb 100644
--- a/guava-tests/test/com/google/common/collect/ListsTest.java
+++ b/guava-tests/test/com/google/common/collect/ListsTest.java
@@ -418,7 +418,7 @@ public class ListsTest extends TestCase {
   }
 
   private void checkFooBarBazList(List<String> list) {
-    assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
     assertEquals(3, list.size());
     assertIndexIsOutOfBounds(list, -1);
     assertEquals("foo", list.get(0));
@@ -429,7 +429,7 @@ public class ListsTest extends TestCase {
 
   public void testAsList1Small() {
     List<String> list = Lists.asList("foo", new String[0]);
-    assertThat(list).has().item("foo");
+    assertThat(list).contains("foo");
     assertEquals(1, list.size());
     assertIndexIsOutOfBounds(list, -1);
     assertEquals("foo", list.get(0));
@@ -460,7 +460,7 @@ public class ListsTest extends TestCase {
   @GwtIncompatible("SerializableTester")
   public void testAsList2Small() {
     List<String> list = Lists.asList("foo", "bar", new String[0]);
-    assertThat(list).has().exactly("foo", "bar").inOrder();
+    assertThat(list).containsExactly("foo", "bar").inOrder();
     assertEquals(2, list.size());
     assertIndexIsOutOfBounds(list, -1);
     assertEquals("foo", list.get(0));
@@ -532,24 +532,24 @@ public class ListsTest extends TestCase {
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x1() {
-    assertThat(Lists.cartesianProduct(list(1), list(2))).has().item(list(1, 2));
+    assertThat(Lists.cartesianProduct(list(1), list(2))).contains(list(1, 2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x2() {
     assertThat(Lists.cartesianProduct(list(1), list(2, 3)))
-        .has().exactly(list(1, 2), list(1, 3)).inOrder();
+        .containsExactly(list(1, 2), list(1, 3)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary2x2() {
     assertThat(Lists.cartesianProduct(list(1, 2), list(3, 4)))
-        .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+        .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_2x2x2() {
-    assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).has().exactly(
+    assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).containsExactly(
         list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
         list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
   }
@@ -575,7 +575,7 @@ public class ListsTest extends TestCase {
     List<Object> exp4 = list((Object) 2, "4");
 
     assertThat(Lists.<Object>cartesianProduct(x, y))
-        .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+        .containsExactly(exp1, exp2, exp3, exp4).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
@@ -666,7 +666,7 @@ public class ListsTest extends TestCase {
 
   public void testTransformSequential() {
     List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
-    assertFalse(list instanceof RandomAccess);
+    assertThat(list).isNotInstanceOf(RandomAccess.class);
   }
 
   public void testTransformListIteratorRandomAccess() {
@@ -861,9 +861,9 @@ public class ListsTest extends TestCase {
   public void testPartitionRandomAccessFalse() {
     List<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
     List<List<Integer>> partitions = Lists.partition(source, 2);
-    assertFalse(partitions instanceof RandomAccess);
-    assertFalse(partitions.get(0) instanceof RandomAccess);
-    assertFalse(partitions.get(1) instanceof RandomAccess);
+    assertThat(partitions).isNotInstanceOf(RandomAccess.class);
+    assertThat(partitions.get(0)).isNotInstanceOf(RandomAccess.class);
+    assertThat(partitions.get(1)).isNotInstanceOf(RandomAccess.class);
   }
 
   // TODO: use the ListTestSuiteBuilder
diff --git a/guava-tests/test/com/google/common/collect/MapConstraintsTest.java b/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
index 70ac072..006b1a8 100644
--- a/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
+++ b/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
@@ -112,10 +112,10 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(map.keySet(), constrained.keySet());
     assertEquals(HashMultiset.create(map.values()),
         HashMultiset.create(constrained.values()));
-    assertFalse(map.values() instanceof Serializable);
+    assertThat(map.values()).isNotInstanceOf(Serializable.class);
     assertEquals(map.toString(), constrained.toString());
     assertEquals(map.hashCode(), constrained.hashCode());
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -163,7 +163,7 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(map.values(), constrained.values());
     assertEquals(map.toString(), constrained.toString());
     assertEquals(map.hashCode(), constrained.hashCode());
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -232,7 +232,7 @@ public class MapConstraintsTest extends TestCase {
     assertTrue(constrained.equals(multimap));
     assertThat(ImmutableList.copyOf(multimap.entries())).isEqualTo(
         ImmutableList.copyOf(constrained.entries()));
-    assertThat(constrained.asMap().get("foo")).has().item(1);
+    assertThat(constrained.asMap().get("foo")).contains(1);
     assertNull(constrained.asMap().get("missing"));
     assertEquals(multimap.asMap(), constrained.asMap());
     assertEquals(multimap.values(), constrained.values());
@@ -240,7 +240,7 @@ public class MapConstraintsTest extends TestCase {
     assertEquals(multimap.keySet(), constrained.keySet());
     assertEquals(multimap.toString(), constrained.toString());
     assertEquals(multimap.hashCode(), constrained.hashCode());
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry(TEST_KEY, TEST_VALUE),
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("bar", 2),
@@ -253,9 +253,8 @@ public class MapConstraintsTest extends TestCase {
         Maps.immutableEntry("bop", 9),
         Maps.immutableEntry("dig", 10),
         Maps.immutableEntry("dag", 11)).inOrder();
-    assertFalse(constrained.asMap().values() instanceof Serializable);
-    Iterator<Collection<Integer>> iterator =
-        constrained.asMap().values().iterator();
+    assertThat(constrained.asMap().values()).isNotInstanceOf(Serializable.class);
+    Iterator<Collection<Integer>> iterator = constrained.asMap().values().iterator();
     iterator.next();
     iterator.next().add(12);
     assertTrue(multimap.containsEntry("foo", 12));
@@ -540,7 +539,18 @@ public class MapConstraintsTest extends TestCase {
     Collection<Map.Entry<String, Integer>> entries = constrained.entries();
     assertFalse(entries.remove(nefariousEntry));
     assertFalse(multimap.containsValue(TEST_VALUE));
-    assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+    /*
+     * Either the Multimap should reject the nefarious internalEntry.setValue() call that
+     * queryEntry.equals() makes, or it should arrange for internalEntry.equals(queryEntry) to be
+     * used instead of the reverse so that queryEntry.equals(internalEntry) is never invoked.
+     *
+     * Probably the other tests should be similarly tolerant of either outcome. But for now, this is
+     * the only one failing in any of our environments.
+     */
+    try {
+      assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+    } catch (TestValueException tolerated) {
+    }
     assertFalse(multimap.containsValue(TEST_VALUE));
   }
 
diff --git a/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java b/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
index c8c4d47..ce4d2d1 100644
--- a/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
+++ b/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
@@ -21,6 +21,7 @@ import static com.google.common.collect.MapMakerInternalMap.DISCARDING_QUEUE;
 import static com.google.common.collect.MapMakerInternalMap.DRAIN_THRESHOLD;
 import static com.google.common.collect.MapMakerInternalMap.nullEntry;
 import static com.google.common.collect.MapMakerInternalMap.unset;
+import static com.google.common.truth.Truth.assertThat;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import com.google.common.base.Equivalence;
@@ -93,7 +94,7 @@ public class MapMakerInternalMapTest extends TestCase {
     assertEquals(4, map.concurrencyLevel);
 
     // concurrency level
-    assertEquals(4, map.segments.length);
+    assertThat(map.segments).hasLength(4);
     // initial capacity / concurrency level
     assertEquals(16 / map.segments.length, map.segments[0].table.length());
 
@@ -138,7 +139,7 @@ public class MapMakerInternalMapTest extends TestCase {
   private static void checkConcurrencyLevel(int concurrencyLevel, int segmentCount) {
     MapMakerInternalMap<Object, Object> map =
         makeMap(createMapMaker().concurrencyLevel(concurrencyLevel));
-    assertEquals(segmentCount, map.segments.length);
+    assertThat(map.segments).hasLength(segmentCount);
   }
 
   public void testSetInitialCapacity() {
diff --git a/guava-tests/test/com/google/common/collect/MapsTest.java b/guava-tests/test/com/google/common/collect/MapsTest.java
index 226d831..6ad3caa 100644
--- a/guava-tests/test/com/google/common/collect/MapsTest.java
+++ b/guava-tests/test/com/google/common/collect/MapsTest.java
@@ -106,7 +106,7 @@ public class MapsTest extends TestCase {
     try {
       Maps.capacity(-1);
       fail("Negative expected size must result in IllegalArgumentException");
-    } catch (IllegalArgumentException ex) {
+    } catch (IllegalArgumentException expected) {
     }
   }
 
@@ -120,35 +120,58 @@ public class MapsTest extends TestCase {
    * This test may fail miserably on non-OpenJDK environments...
    */
   @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // relies on assumptions about OpenJDK
   public void testNewHashMapWithExpectedSize_wontGrow() throws Exception {
     // before jdk7u40: creates one-bucket table
     // after  jdk7u40: creates empty table
     assertTrue(bucketsOf(Maps.newHashMapWithExpectedSize(0)) <= 1);
 
     for (int size = 1; size < 200; size++) {
-      HashMap<Integer, Void> map1 = Maps.newHashMapWithExpectedSize(size);
+      assertWontGrow(size,
+          Maps.newHashMapWithExpectedSize(size),
+          Maps.newHashMapWithExpectedSize(size));
+    }
+  }
 
-      // Only start measuring table size after the first element inserted, to
-      // deal with empty-map optimization.
-      map1.put(0, null);
+  /**
+   * Same test as above but for newLinkedHashMapWithExpectedSize
+   */
+  @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // relies on assumptions about OpenJDK
+  public void testNewLinkedHashMapWithExpectedSize_wontGrow() throws Exception {
+    assertTrue(bucketsOf(Maps.newLinkedHashMapWithExpectedSize(0)) <= 1);
 
-      int initialBuckets = bucketsOf(map1);
+    for (int size = 1; size < 200; size++) {
+      assertWontGrow(size,
+          Maps.newLinkedHashMapWithExpectedSize(size),
+          Maps.newLinkedHashMapWithExpectedSize(size));
+    }
+  }
 
-      for (int i = 1; i < size; i++) {
-        map1.put(i, null);
-      }
-      assertEquals("table size after adding " + size + " elements",
-          initialBuckets, bucketsOf(map1));
+  @GwtIncompatible("reflection")
+  private static void assertWontGrow(
+      int size, HashMap<Object, Object> map1, HashMap<Object, Object> map2) throws Exception {
+    // Only start measuring table size after the first element inserted, to
+    // deal with empty-map optimization.
+    map1.put(0, null);
+
+    int initialBuckets = bucketsOf(map1);
 
-      /*
-       * Something slightly different happens when the entries are added all at
-       * once; make sure that passes too.
-       */
-      HashMap<Integer, Void> map2 = Maps.newHashMapWithExpectedSize(size);
-      map2.putAll(map1);
-      assertEquals("table size after adding " + size + "elements",
-          initialBuckets, bucketsOf(map2));
+    for (int i = 1; i < size; i++) {
+      map1.put(i, null);
     }
+    assertThat(bucketsOf(map1))
+        .named("table size after adding " + size + " elements")
+        .isEqualTo(initialBuckets);
+
+    /*
+     * Something slightly different happens when the entries are added all at
+     * once; make sure that passes too.
+     */
+    map2.putAll(map1);
+    assertThat(bucketsOf(map1))
+        .named("table size after adding " + size + " elements")
+        .isEqualTo(initialBuckets);
   }
 
   @GwtIncompatible("reflection")
@@ -156,7 +179,8 @@ public class MapsTest extends TestCase {
     Field tableField = HashMap.class.getDeclaredField("table");
     tableField.setAccessible(true);
     Object[] table = (Object[]) tableField.get(hashMap);
-    return table.length;
+    // In JDK8, table is set lazily, so it may be null.
+    return table == null ? 0 : table.length;
   }
 
   public void testCapacityForLargeSizes() {
@@ -244,9 +268,9 @@ public class MapsTest extends TestCase {
     assertEquals(Collections.emptyMap(), map);
     map.put(new Derived("foo"), 1);
     map.put(new Derived("bar"), 2);
-    assertThat(map.keySet()).has().exactly(
+    assertThat(map.keySet()).containsExactly(
         new Derived("bar"), new Derived("foo")).inOrder();
-    assertThat(map.values()).has().exactly(2, 1).inOrder();
+    assertThat(map.values()).containsExactly(2, 1).inOrder();
     assertNull(map.comparator());
   }
 
@@ -255,9 +279,9 @@ public class MapsTest extends TestCase {
     assertEquals(Collections.emptyMap(), map);
     map.put(new LegacyComparable("foo"), 1);
     map.put(new LegacyComparable("bar"), 2);
-    assertThat(map.keySet()).has().exactly(
+    assertThat(map.keySet()).containsExactly(
         new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
-    assertThat(map.values()).has().exactly(2, 1).inOrder();
+    assertThat(map.values()).containsExactly(2, 1).inOrder();
     assertNull(map.comparator());
   }
 
@@ -526,13 +550,13 @@ public class MapsTest extends TestCase {
     SortedMapDifference<Integer, String> diff1 =
         Maps.difference(left, right);
     assertFalse(diff1.areEqual());
-    assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
         Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
-    assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
-    assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
         Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
         Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
     assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
@@ -541,11 +565,11 @@ public class MapsTest extends TestCase {
     SortedMapDifference<Integer, String> diff2 =
         Maps.difference(right, left);
     assertFalse(diff2.areEqual());
-    assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item(
+    assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly(
+    assertThat(diff2.entriesOnlyOnRight().entrySet()).containsExactly(
         Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
     assertEquals(ImmutableMap.of(
             3, ValueDifferenceImpl.create("f", "c"),
@@ -565,13 +589,13 @@ public class MapsTest extends TestCase {
         Maps.difference(left, right);
     left.put(6, "z");
     assertFalse(diff1.areEqual());
-    assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
         Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
-    assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
         Maps.immutableEntry(6, "z"));
-    assertThat(diff1.entriesInCommon().entrySet()).has().item(
+    assertThat(diff1.entriesInCommon().entrySet()).contains(
         Maps.immutableEntry(1, "a"));
-    assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
         Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
         Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
     try {
@@ -628,7 +652,7 @@ public class MapsTest extends TestCase {
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(5), map.get("three"));
     assertNull(map.get("five"));
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -651,7 +675,7 @@ public class MapsTest extends TestCase {
     Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(3), map.remove("two"));
-    assertThat(strings).has().exactly("one", "three").inOrder();
+    assertThat(strings).containsExactly("one", "three").inOrder();
   }
 
   public void testAsMapEmpty() {
@@ -684,14 +708,14 @@ public class MapsTest extends TestCase {
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(5), map.get("three"));
     assertNull(map.get("five"));
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.tailMap("onea").entrySet()).has().exactly(
+    assertThat(map.tailMap("onea").entrySet()).containsExactly(
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+    assertThat(map.subMap("one", "two").entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5)).inOrder();
   }
@@ -717,7 +741,7 @@ public class MapsTest extends TestCase {
     assertEquals(
         ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
         headMap);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("five", 4),
         mapEntry("four", 4),
         mapEntry("three", 5),
@@ -730,7 +754,7 @@ public class MapsTest extends TestCase {
     SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(3), map.remove("two"));
-    assertThat(strings).has().exactly("one", "three").inOrder();
+    assertThat(strings).containsExactly("one", "three").inOrder();
   }
 
   public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
@@ -780,14 +804,14 @@ public class MapsTest extends TestCase {
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(5), map.get("three"));
     assertNull(map.get("five"));
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.tailMap("onea").entrySet()).has().exactly(
+    assertThat(map.tailMap("onea").entrySet()).containsExactly(
         mapEntry("three", 5),
         mapEntry("two", 3)).inOrder();
-    assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+    assertThat(map.subMap("one", "two").entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("three", 5)).inOrder();
 
@@ -809,19 +833,19 @@ public class MapsTest extends TestCase {
     assertEquals("one", map.floorKey("r"));
     assertEquals("three", map.floorKey("three"));
 
-    assertThat(map.descendingMap().entrySet()).has().exactly(
+    assertThat(map.descendingMap().entrySet()).containsExactly(
         mapEntry("two", 3),
         mapEntry("three", 5),
         mapEntry("one", 3)).inOrder();
     assertEquals(map.headMap("three", true),
         map.descendingMap().tailMap("three", true));
-    assertThat(map.tailMap("three", false).entrySet()).has().item(
+    assertThat(map.tailMap("three", false).entrySet()).contains(
         mapEntry("two", 3));
     assertNull(map.tailMap("three", true).lowerEntry("three"));
-    assertThat(map.headMap("two", false).values()).has().exactly(3, 5).inOrder();
+    assertThat(map.headMap("two", false).values()).containsExactly(3, 5).inOrder();
     assertThat(map.headMap("two", false).descendingMap().values())
-        .has().exactly(5, 3).inOrder();
-    assertThat(map.descendingKeySet()).has().exactly(
+        .containsExactly(5, 3).inOrder();
+    assertThat(map.descendingKeySet()).containsExactly(
         "two", "three", "one").inOrder();
 
     assertEquals(mapEntry("one", 3), map.pollFirstEntry());
@@ -851,7 +875,7 @@ public class MapsTest extends TestCase {
     assertEquals(
         ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
         headMap);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("five", 4),
         mapEntry("four", 4),
         mapEntry("three", 5),
@@ -862,10 +886,10 @@ public class MapsTest extends TestCase {
 
     strings.add("six");
     strings.remove("two");
-    assertThat(tailMap.entrySet()).has().exactly(
+    assertThat(tailMap.entrySet()).containsExactly(
         mapEntry("six", 3),
         mapEntry("three", 5)).inOrder();
-    assertThat(subMap.entrySet()).has().exactly(
+    assertThat(subMap.entrySet()).containsExactly(
         mapEntry("five", 4),
         mapEntry("four", 4),
         mapEntry("six", 3)).inOrder();
@@ -878,10 +902,10 @@ public class MapsTest extends TestCase {
     NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
     assertEquals(Integer.valueOf(3), map.remove("two"));
-    assertThat(strings).has().exactly("one", "three").inOrder();
+    assertThat(strings).containsExactly("one", "three").inOrder();
     assertEquals(mapEntry("three", 5),
         map.subMap("one", false, "zzz", true).pollLastEntry());
-    assertThat(strings).has().item("one");
+    assertThat(strings).contains("one");
   }
 
   @GwtIncompatible("NavigableMap")
@@ -928,7 +952,7 @@ public class MapsTest extends TestCase {
     Iterable<String> strings = ImmutableList.of("one", "two", "three");
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -938,7 +962,7 @@ public class MapsTest extends TestCase {
     Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -948,7 +972,7 @@ public class MapsTest extends TestCase {
     Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
     ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
     assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
-    assertThat(map.entrySet()).has().exactly(
+    assertThat(map.entrySet()).containsExactly(
         mapEntry("one", 3),
         mapEntry("two", 3),
         mapEntry("three", 5)).inOrder();
@@ -1011,6 +1035,7 @@ public class MapsTest extends TestCase {
       Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
       fail();
     } catch (IllegalArgumentException expected) {
+      assertThat(expected.getMessage()).contains("Multimaps.index");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java b/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
index 803f63f..fa1ea97 100644
--- a/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
+++ b/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
@@ -355,7 +355,7 @@ public class MinMaxPriorityQueueTest extends TestCase {
       }
     }
     assertTrue(q.isIntact());
-    assertThat(result).has().exactly(1, 15, 13, 8, 14);
+    assertThat(result).containsExactly(1, 15, 13, 8, 14);
   }
 
   /**
@@ -718,23 +718,23 @@ public class MinMaxPriorityQueueTest extends TestCase {
     List<Integer> contents = Lists.newArrayList(expected);
     List<Integer> elements = Lists.newArrayListWithCapacity(size);
     while (!q.isEmpty()) {
-      assertThat(q).has().exactlyAs(contents);
+      assertThat(q).containsExactlyElementsIn(contents);
       Integer next = q.pollFirst();
       contents.remove(next);
-      assertThat(q).has().exactlyAs(contents);
+      assertThat(q).containsExactlyElementsIn(contents);
       for (int i = 0; i <= size; i++) {
         q.add(i);
         contents.add(i);
-        assertThat(q).has().exactlyAs(contents);
+        assertThat(q).containsExactlyElementsIn(contents);
         q.add(next);
         contents.add(next);
-        assertThat(q).has().exactlyAs(contents);
+        assertThat(q).containsExactlyElementsIn(contents);
         q.remove(i);
         assertTrue(contents.remove(Integer.valueOf(i)));
-        assertThat(q).has().exactlyAs(contents);
+        assertThat(q).containsExactlyElementsIn(contents);
         assertEquals(next, q.poll());
         contents.remove(next);
-        assertThat(q).has().exactlyAs(contents);
+        assertThat(q).containsExactlyElementsIn(contents);
       }
       elements.add(next);
     }
diff --git a/guava-tests/test/com/google/common/collect/MultimapsTest.java b/guava-tests/test/com/google/common/collect/MultimapsTest.java
index 43123ef..d4b5ec1 100644
--- a/guava-tests/test/com/google/common/collect/MultimapsTest.java
+++ b/guava-tests/test/com/google/common/collect/MultimapsTest.java
@@ -70,14 +70,6 @@ public class MultimapsTest extends TestCase {
   private static final Comparator<Integer> INT_COMPARATOR =
       Ordering.<Integer>natural().reverse().nullsFirst();
 
-  private static final EntryTransformer<Object, Object, Object> ALWAYS_NULL =
-      new EntryTransformer<Object, Object, Object>() {
-        @Override
-        public Object transformEntry(Object k, Object v1) {
-          return null;
-        }
-      };
-
   @SuppressWarnings("deprecation")
   public void testUnmodifiableListMultimapShortCircuit() {
     ListMultimap<String, Integer> mod = ArrayListMultimap.create();
@@ -142,10 +134,9 @@ public class MultimapsTest extends TestCase {
     ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
     delegate.put("foo", 1);
     delegate.put("foo", 3);
-    ListMultimap<String, Integer> multimap
-        = Multimaps.unmodifiableListMultimap(delegate);
-    assertFalse(multimap.get("foo") instanceof RandomAccess);
-    assertFalse(multimap.get("bar") instanceof RandomAccess);
+    ListMultimap<String, Integer> multimap = Multimaps.unmodifiableListMultimap(delegate);
+    assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+    assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
   }
 
   @GwtIncompatible("slow (~10s)")
@@ -297,10 +288,10 @@ public class MultimapsTest extends TestCase {
     assertEquals(multimap.hashCode(), unmodifiable.hashCode());
     assertEquals(multimap, unmodifiable);
 
-    assertThat(unmodifiable.asMap().get("bar")).has().exactly(5, -1);
+    assertThat(unmodifiable.asMap().get("bar")).containsExactly(5, -1);
     assertNull(unmodifiable.asMap().get("missing"));
 
-    assertFalse(unmodifiable.entries() instanceof Serializable);
+    assertThat(unmodifiable.entries()).isNotInstanceOf(Serializable.class);
   }
 
   /**
@@ -454,13 +445,11 @@ public class MultimapsTest extends TestCase {
     assertFalse(map.containsKey("bar"));
     assertEquals(map.keySet(), multimapView.keySet());
     assertEquals(map.keySet(), multimapView.keys().elementSet());
-    assertThat(multimapView.keys()).has().item("foo");
-    assertThat(multimapView.values()).has().item(1);
-    assertThat(multimapView.entries()).has().item(
-        Maps.immutableEntry("foo", 1));
-    assertThat(multimapView.asMap().entrySet()).has().item(
-        Maps.immutableEntry(
-            "foo", (Collection<Integer>) Collections.singleton(1)));
+    assertThat(multimapView.keys()).contains("foo");
+    assertThat(multimapView.values()).contains(1);
+    assertThat(multimapView.entries()).contains(Maps.immutableEntry("foo", 1));
+    assertThat(multimapView.asMap().entrySet())
+        .contains(Maps.immutableEntry("foo", (Collection<Integer>) Collections.singleton(1)));
     multimapView.clear();
     assertFalse(multimapView.containsKey("foo"));
     assertFalse(map.containsKey("foo"));
@@ -615,7 +604,7 @@ public class MultimapsTest extends TestCase {
     } catch (IllegalArgumentException expected) {
       // expected
     }
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry(Color.RED, 1),
         Maps.immutableEntry(Color.BLUE, 2));
   }
@@ -640,8 +629,8 @@ public class MultimapsTest extends TestCase {
     Collection<Integer> collection = multimap.get(Color.BLUE);
     assertEquals(collection, collection);
 
-    assertFalse(multimap.keySet() instanceof SortedSet);
-    assertFalse(multimap.asMap() instanceof SortedMap);
+    assertThat(multimap.keySet()).isNotInstanceOf(SortedSet.class);
+    assertThat(multimap.asMap()).isNotInstanceOf(SortedMap.class);
   }
 
   @GwtIncompatible("SerializableTester")
@@ -673,7 +662,7 @@ public class MultimapsTest extends TestCase {
     multimap.putAll(Color.RED, asList(2, 7, 1, 8));
     assertEquals(2, factory.count);
     assertEquals("{BLUE=[3, 1, 4, 1], RED=[2, 7, 1, 8]}", multimap.toString());
-    assertFalse(multimap.get(Color.BLUE) instanceof RandomAccess);
+    assertThat(multimap.get(Color.BLUE)).isNotInstanceOf(RandomAccess.class);
 
     assertTrue(multimap.keySet() instanceof SortedSet);
     assertTrue(multimap.asMap() instanceof SortedMap);
@@ -838,7 +827,7 @@ public class MultimapsTest extends TestCase {
       }
     };
     Multimap<String, Integer> transformed = Multimaps.transformValues(multimap, square);
-    assertThat(transformed.entries()).has().exactly(immutableEntry("a", 4),
+    assertThat(transformed.entries()).containsExactly(immutableEntry("a", 4),
         immutableEntry("a", 16), immutableEntry("b", 9), immutableEntry("b", 9),
         immutableEntry("c", 36)).inOrder();
   }
@@ -856,7 +845,7 @@ public class MultimapsTest extends TestCase {
         });
     Entry<String, String> entry = multimap.entries().iterator().next();
     entry.setValue("bbb");
-    assertThat(transformed.entries()).has().exactly(immutableEntry("a", 3)).inOrder();
+    assertThat(transformed.entries()).containsExactly(immutableEntry("a", 3));
   }
 
   @GwtIncompatible(value = "untested")
@@ -871,7 +860,7 @@ public class MultimapsTest extends TestCase {
     };
     ListMultimap<String, Integer> transformed =
         Multimaps.transformValues(multimap, square);
-    assertThat(transformed.entries()).has().exactly(immutableEntry("a", 4),
+    assertThat(transformed.entries()).containsExactly(immutableEntry("a", 4),
         immutableEntry("a", 16), immutableEntry("b", 9), immutableEntry("b", 9),
         immutableEntry("c", 36)).inOrder();
   }
@@ -889,7 +878,7 @@ public class MultimapsTest extends TestCase {
         };
     Multimap<String, String> transformed =
         Multimaps.transformEntries(multimap, transformer);
-    assertThat(transformed.entries()).has().exactly(immutableEntry("a", "a"),
+    assertThat(transformed.entries()).containsExactly(immutableEntry("a", "a"),
         immutableEntry("a", "a"), immutableEntry("b", "nob")).inOrder();
   }
 
diff --git a/guava-tests/test/com/google/common/collect/MultisetsTest.java b/guava-tests/test/com/google/common/collect/MultisetsTest.java
index 6623e15..1ca6ccc 100644
--- a/guava-tests/test/com/google/common/collect/MultisetsTest.java
+++ b/guava-tests/test/com/google/common/collect/MultisetsTest.java
@@ -46,7 +46,7 @@ public class MultisetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new DerivedComparable("foo"), 2);
     set.add(new DerivedComparable("bar"), 3);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
         new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
   }
@@ -56,7 +56,7 @@ public class MultisetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new LegacyComparable("foo"), 2);
     set.add(new LegacyComparable("bar"), 3);
-    assertThat(set).has().exactly(new LegacyComparable("bar"),
+    assertThat(set).containsExactly(new LegacyComparable("bar"),
         new LegacyComparable("bar"), new LegacyComparable("bar"),
         new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
   }
@@ -66,7 +66,7 @@ public class MultisetsTest extends TestCase {
         = TreeMultiset.create(Collections.reverseOrder());
     multiset.add("bar", 3);
     multiset.add("foo", 2);
-    assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
+    assertThat(multiset).containsExactly("foo", "foo", "bar", "bar", "bar").inOrder();
   }
 
   public void testRetainOccurrencesEmpty() {
@@ -88,7 +88,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> multiset = HashMultiset.create();
     Multiset<String> toRemove =
         HashMultiset.create(Arrays.asList("a", "b", "a"));
-    assertFalse(Multisets.retainOccurrences(multiset, toRemove));
+    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
     assertTrue(multiset.isEmpty());
   }
 
@@ -96,7 +96,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(
         Arrays.asList("a", "b", "b", "c"));
-    assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+    assertThat(Multisets.union(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
   }
 
   public void testUnionEqualMultisets() {
@@ -132,38 +132,38 @@ public class MultisetsTest extends TestCase {
   public void testSum() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
   }
 
   public void testSumEmptyNonempty() {
     Multiset<String> ms1 = HashMultiset.create();
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
   }
 
   public void testSumNonemptyEmpty() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create();
-    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+    assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
   }
 
   public void testDifferenceWithNoRemovedElements() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
-    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
+    assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "b");
   }
 
   public void testDifferenceWithRemovedElement() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
-    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
+    assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "a");
   }
 
   public void testDifferenceWithMoreElementsInSecondMultiset() {
     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
     Multiset<String> diff = Multisets.difference(ms1, ms2);
-    assertThat(diff).has().item("a");
+    assertThat(diff).contains("a");
     assertEquals(0, diff.count("b"));
     assertEquals(1, diff.count("a"));
     assertFalse(diff.contains("b"));
@@ -213,7 +213,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> toRetain =
         HashMultiset.create(Arrays.asList("a", "b", "b"));
     assertTrue(Multisets.retainOccurrences(multiset, toRetain));
-    assertThat(multiset).has().exactly("a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "b").inOrder();
   }
 
   public void testRemoveEmptyOccurrencesMultiset() {
@@ -221,7 +221,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a"));
     Multiset<String> toRemove = HashMultiset.create();
     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testRemoveOccurrencesMultiset() {
@@ -230,7 +230,7 @@ public class MultisetsTest extends TestCase {
     Multiset<String> toRemove =
         HashMultiset.create(Arrays.asList("a", "b", "b"));
     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "c").inOrder();
+    assertThat(multiset).containsExactly("a", "c").inOrder();
   }
 
   public void testRemoveEmptyOccurrencesIterable() {
@@ -238,7 +238,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a"));
     Iterable<String> toRemove = ImmutableList.of();
     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+    assertThat(multiset).containsExactly("a", "a", "b").inOrder();
   }
 
   public void testRemoveOccurrencesMultisetIterable() {
@@ -246,7 +246,7 @@ public class MultisetsTest extends TestCase {
         TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
     List<String> toRemove = Arrays.asList("a", "b", "b");
     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
-    assertThat(multiset).has().exactly("a", "c").inOrder();
+    assertThat(multiset).containsExactly("a", "c").inOrder();
   }
 
   @SuppressWarnings("deprecation")
@@ -266,11 +266,11 @@ public class MultisetsTest extends TestCase {
     ImmutableMultiset<String> sortedMultiset =
         Multisets.copyHighestCountFirst(multiset);
 
-    assertThat(sortedMultiset.entrySet()).has().exactly(
+    assertThat(sortedMultiset.entrySet()).containsExactly(
         Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
         Multisets.immutableEntry("b", 1)).inOrder();
 
-    assertThat(sortedMultiset).has().exactly(
+    assertThat(sortedMultiset).containsExactly(
         "a",
         "a",
         "a",
diff --git a/guava-tests/test/com/google/common/collect/NewCustomTableTest.java b/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
index 9355aad..64522b8 100644
--- a/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
+++ b/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
@@ -51,11 +51,11 @@ public class NewCustomTableTest extends AbstractTableTest {
 
   public void testRowKeySetOrdering() {
     table = create("foo", 3, 'a', "bar", 1, 'b', "foo", 2, 'c');
-    assertThat(table.rowKeySet()).has().exactly("foo", "bar").inOrder();
+    assertThat(table.rowKeySet()).containsExactly("foo", "bar").inOrder();
   }
 
   public void testRowOrdering() {
     table = create("foo", 3, 'a', "bar", 1, 'b', "foo", 2, 'c');
-    assertThat(table.row("foo").keySet()).has().exactly(2, 3).inOrder();
+    assertThat(table.row("foo").keySet()).containsExactly(2, 3).inOrder();
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
index c379857..b8dba1a 100644
--- a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
+++ b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
@@ -46,14 +46,14 @@ public class ObjectArraysTest extends TestCase {
   public void testNewArray_fromClass_Empty() {
     String[] empty = ObjectArrays.newArray(String.class, 0);
     assertEquals(String[].class, empty.getClass());
-    assertEquals(0, empty.length);
+    assertThat(empty).isEmpty();
   }
 
   @GwtIncompatible("ObjectArrays.newArray(Class, int)")
   public void testNewArray_fromClass_Nonempty() {
     String[] array = ObjectArrays.newArray(String.class, 2);
     assertEquals(String[].class, array.getClass());
-    assertEquals(2, array.length);
+    assertThat(array).hasLength(2);
     assertNull(array[0]);
   }
 
@@ -61,27 +61,27 @@ public class ObjectArraysTest extends TestCase {
   public void testNewArray_fromClass_OfArray() {
     String[][] array = ObjectArrays.newArray(String[].class, 1);
     assertEquals(String[][].class, array.getClass());
-    assertEquals(1, array.length);
+    assertThat(array).hasLength(1);
     assertNull(array[0]);
   }
 
   public void testNewArray_fromArray_Empty() {
     String[] in = new String[0];
     String[] empty = ObjectArrays.newArray(in, 0);
-    assertEquals(0, empty.length);
+    assertThat(empty).isEmpty();
   }
 
   public void testNewArray_fromArray_Nonempty() {
     String[] array = ObjectArrays.newArray(new String[0], 2);
     assertEquals(String[].class, array.getClass());
-    assertEquals(2, array.length);
+    assertThat(array).hasLength(2);
     assertNull(array[0]);
   }
 
   public void testNewArray_fromArray_OfArray() {
     String[][] array = ObjectArrays.newArray(new String[0][0], 1);
     assertEquals(String[][].class, array.getClass());
-    assertEquals(1, array.length);
+    assertThat(array).hasLength(1);
     assertNull(array[0]);
   }
 
@@ -90,7 +90,7 @@ public class ObjectArraysTest extends TestCase {
     String[] result
         = ObjectArrays.concat(new String[0], new String[0], String.class);
     assertEquals(String[].class, result.getClass());
-    assertEquals(0, result.length);
+    assertThat(result).isEmpty();
   }
 
   @GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -98,7 +98,7 @@ public class ObjectArraysTest extends TestCase {
     String[] result = ObjectArrays.concat(
         new String[0], new String[] { "a", "b" }, String.class);
     assertEquals(String[].class, result.getClass());
-    assertThat(result).asList().has().exactly("a", "b").inOrder();
+    assertThat(result).asList().containsExactly("a", "b").inOrder();
   }
 
   @GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -106,7 +106,7 @@ public class ObjectArraysTest extends TestCase {
     String[] result = ObjectArrays.concat(
         new String[] { "a", "b" }, new String[0], String.class);
     assertEquals(String[].class, result.getClass());
-    assertThat(result).asList().has().exactly("a", "b").inOrder();
+    assertThat(result).asList().containsExactly("a", "b").inOrder();
   }
 
   @GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -114,7 +114,7 @@ public class ObjectArraysTest extends TestCase {
     String[] result = ObjectArrays.concat(
         new String[] { "a", "b" }, new String[] { "c", "d" }, String.class);
     assertEquals(String[].class, result.getClass());
-    assertThat(result).asList().has().exactly("a", "b", "c", "d").inOrder();
+    assertThat(result).asList().containsExactly("a", "b", "c", "d").inOrder();
   }
 
   @GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -170,32 +170,32 @@ public class ObjectArraysTest extends TestCase {
 
   public void testPrependZeroElements() {
     String[] result = ObjectArrays.concat("foo", new String[] {});
-    assertThat(result).asList().has().item("foo");
+    assertThat(result).asList().contains("foo");
   }
 
   public void testPrependOneElement() {
     String[] result = ObjectArrays.concat("foo", new String[] { "bar" });
-    assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar").inOrder();
   }
 
   public void testPrependTwoElements() {
     String[] result = ObjectArrays.concat("foo", new String[] { "bar", "baz" });
-    assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
   }
 
   public void testAppendZeroElements() {
     String[] result = ObjectArrays.concat(new String[] {}, "foo");
-    assertThat(result).asList().has().item("foo");
+    assertThat(result).asList().contains("foo");
   }
 
   public void testAppendOneElement() {
     String[] result = ObjectArrays.concat(new String[] { "foo" }, "bar");
-    assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar").inOrder();
   }
 
   public void testAppendTwoElements() {
     String[] result = ObjectArrays.concat(new String[] { "foo", "bar" }, "baz");
-    assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+    assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
   }
 
   public void testEmptyArrayToEmpty() {
diff --git a/guava-tests/test/com/google/common/collect/OrderingTest.java b/guava-tests/test/com/google/common/collect/OrderingTest.java
index 8054740..8cc4cb7 100644
--- a/guava-tests/test/com/google/common/collect/OrderingTest.java
+++ b/guava-tests/test/com/google/common/collect/OrderingTest.java
@@ -72,6 +72,38 @@ public class OrderingTest extends TestCase {
     assertEquals(strings, comparator.immutableSortedCopy(strings));
   }
 
+  // From https://github.com/google/guava/issues/1342
+  public void testComplicatedOrderingExample() {
+    Integer nullInt = (Integer) null;
+    Ordering<Iterable<Integer>> example =
+        Ordering.<Integer>natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
+    List<Integer> list1 = Lists.newArrayList();
+    List<Integer> list2 = Lists.newArrayList(1);
+    List<Integer> list3 = Lists.newArrayList(1, 1);
+    List<Integer> list4 = Lists.newArrayList(1, 2);
+    List<Integer> list5 = Lists.newArrayList(1, null, 2);
+    List<Integer> list6 = Lists.newArrayList(2);
+    List<Integer> list7 = Lists.newArrayList(nullInt);
+    List<Integer> list8 = Lists.newArrayList(nullInt, nullInt);
+    List<List<Integer>> list =
+        Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);
+    List<List<Integer>> sorted = example.sortedCopy(list);
+
+    // [[null, null], [null], [1, null, 2], [1, 1], [1, 2], [1], [2], [], null]
+    assertThat(sorted)
+        .containsExactly(
+            Lists.newArrayList(nullInt, nullInt),
+            Lists.newArrayList(nullInt),
+            Lists.newArrayList(1, null, 2),
+            Lists.newArrayList(1, 1),
+            Lists.newArrayList(1, 2),
+            Lists.newArrayList(1),
+            Lists.newArrayList(2),
+            Lists.newArrayList(),
+            null)
+        .inOrder();
+  }
+
   public void testNatural() {
     Ordering<Integer> comparator = Ordering.natural();
     Helpers.testComparator(comparator,
@@ -157,7 +189,7 @@ public class OrderingTest extends TestCase {
         = Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
     List<Integer> list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
     Collections.sort(list, c);
-    assertThat(list).has().exactly(8, 6, 7, 5, 3, 0, 9).inOrder();
+    assertThat(list).containsExactly(8, 6, 7, 5, 3, 0, 9).inOrder();
     reserializeAndAssert(c);
   }
 
diff --git a/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java b/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
index d1f97f5..c501baf 100644
--- a/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
@@ -63,7 +63,7 @@ public class RegularImmutableTableTest extends AbstractImmutableTableTest {
     for (ImmutableTable<Character, Integer, String> testInstance :
         getTestInstances()) {
       assertThat(testInstance.values())
-          .has().exactly("foo", "bar", "baz")
+          .containsExactly("foo", "bar", "baz")
           .inOrder();
     }
   }
diff --git a/guava-tests/test/com/google/common/collect/SetsTest.java b/guava-tests/test/com/google/common/collect/SetsTest.java
index 68a76c6..4b33d42 100644
--- a/guava-tests/test/com/google/common/collect/SetsTest.java
+++ b/guava-tests/test/com/google/common/collect/SetsTest.java
@@ -148,9 +148,9 @@ public class SetsTest extends TestCase {
     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
           @Override protected Set<String> create(String[] elements) {
             Set<String> set1 = Sets.newHashSet(elements);
-            set1.add(samples().e3);
+            set1.add(samples().e3());
             Set<String> set2 = Sets.newHashSet(elements);
-            set2.add(samples().e4);
+            set2.add(samples().e4());
             return Sets.intersection(set1, set2);
           }
         })
@@ -161,8 +161,8 @@ public class SetsTest extends TestCase {
     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
           @Override protected Set<String> create(String[] elements) {
             Set<String> set1 = Sets.newHashSet(elements);
-            set1.add(samples().e3);
-            Set<String> set2 = Sets.newHashSet(samples().e3);
+            set1.add(samples().e3());
+            Set<String> set2 = Sets.newHashSet(samples().e3());
             return Sets.difference(set1, set2);
           }
         })
@@ -301,7 +301,7 @@ public class SetsTest extends TestCase {
   public void testImmutableEnumSet() {
     Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
 
-    assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+    assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
     try {
       units.remove(SomeEnum.B);
       fail("ImmutableEnumSet should throw an exception on remove()");
@@ -316,7 +316,7 @@ public class SetsTest extends TestCase {
   public void testImmutableEnumSet_serialized() {
     Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
 
-    assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+    assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
 
     Set<SomeEnum> copy = SerializableTester.reserializeAndAssert(units);
     assertTrue(copy instanceof ImmutableEnumSet);
@@ -329,11 +329,10 @@ public class SetsTest extends TestCase {
 
     ImmutableSet<SomeEnum> one
         = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.B));
-    assertThat(one).has().item(SomeEnum.B);
+    assertThat(one).contains(SomeEnum.B);
 
-    ImmutableSet<SomeEnum> two
-        = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
-    assertThat(two).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+    ImmutableSet<SomeEnum> two = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
+    assertThat(two).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
   }
 
   @GwtIncompatible("java serialization not supported in GWT.")
@@ -488,7 +487,7 @@ public class SetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new Derived("foo"));
     set.add(new Derived("bar"));
-    assertThat(set).has().exactly(new Derived("bar"), new Derived("foo")).inOrder();
+    assertThat(set).containsExactly(new Derived("bar"), new Derived("foo")).inOrder();
   }
 
   public void testNewTreeSetEmptyNonGeneric() {
@@ -496,8 +495,8 @@ public class SetsTest extends TestCase {
     assertTrue(set.isEmpty());
     set.add(new LegacyComparable("foo"));
     set.add(new LegacyComparable("bar"));
-    assertThat(set).has()
-        .exactly(new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
+    assertThat(set).containsExactly(
+        new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
   }
 
   public void testNewTreeSetFromCollection() {
@@ -514,7 +513,7 @@ public class SetsTest extends TestCase {
     Iterable<Derived> iterable =
         Arrays.asList(new Derived("foo"), new Derived("bar"));
     TreeSet<Derived> set = Sets.newTreeSet(iterable);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new Derived("bar"), new Derived("foo")).inOrder();
   }
 
@@ -522,7 +521,7 @@ public class SetsTest extends TestCase {
     Iterable<LegacyComparable> iterable =
         Arrays.asList(new LegacyComparable("foo"), new LegacyComparable("bar"));
     TreeSet<LegacyComparable> set = Sets.newTreeSet(iterable);
-    assertThat(set).has().exactly(
+    assertThat(set).containsExactly(
         new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
   }
 
@@ -624,7 +623,7 @@ public class SetsTest extends TestCase {
         Sets.newSetFromMap(new LinkedHashMap<Integer, Boolean>());
     set.addAll(SOME_COLLECTION);
     Set<Integer> copy = SerializableTester.reserializeAndAssert(set);
-    assertThat(copy).has().exactly(0, 1).inOrder();
+    assertThat(copy).containsExactly(0, 1).inOrder();
   }
 
   public void testNewSetFromMapIllegal() {
@@ -644,7 +643,7 @@ public class SetsTest extends TestCase {
    */
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_zeroary() {
-    assertThat(Sets.cartesianProduct()).has().exactly(list());
+    assertThat(Sets.cartesianProduct()).containsExactly(list());
   }
 
   /**
@@ -653,7 +652,7 @@ public class SetsTest extends TestCase {
    */
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_unary() {
-    assertThat(Sets.cartesianProduct(set(1, 2))).has().exactly(list(1), list(2));
+    assertThat(Sets.cartesianProduct(set(1, 2))).containsExactly(list(1), list(2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
@@ -682,24 +681,24 @@ public class SetsTest extends TestCase {
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x1() {
-    assertThat(Sets.cartesianProduct(set(1), set(2))).has().item(list(1, 2));
+    assertThat(Sets.cartesianProduct(set(1), set(2))).contains(list(1, 2));
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary1x2() {
     assertThat(Sets.cartesianProduct(set(1), set(2, 3)))
-        .has().exactly(list(1, 2), list(1, 3)).inOrder();
+        .containsExactly(list(1, 2), list(1, 3)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_binary2x2() {
     assertThat(Sets.cartesianProduct(set(1, 2), set(3, 4)))
-        .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+        .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
   public void testCartesianProduct_2x2x2() {
-    assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).has().exactly(
+    assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).containsExactly(
         list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
         list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
   }
@@ -725,7 +724,7 @@ public class SetsTest extends TestCase {
     List<Object> exp4 = list((Object) 2, "4");
 
     assertThat(Sets.<Object>cartesianProduct(x, y))
-        .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+        .containsExactly(exp1, exp2, exp3, exp4).inOrder();
   }
 
   @SuppressWarnings("unchecked") // varargs!
diff --git a/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java b/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
index f16498b..27eeb1a 100644
--- a/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
@@ -126,7 +126,7 @@ public class SingletonImmutableTableTest extends AbstractImmutableTableTest {
   }
 
   public void testValues() {
-    assertThat(testTable.values()).has().item("blah");
+    assertThat(testTable.values()).contains("blah");
   }
 
   @Override Iterable<ImmutableTable<Character, Integer, String>> getTestInstances() {
diff --git a/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java
new file mode 100644
index 0000000..907cfd2
--- /dev/null
+++ b/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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 java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java b/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
index e7a6aac..559eaf0 100644
--- a/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
@@ -204,11 +204,11 @@ public class SynchronizedMultimapTest extends TestCase {
             ArrayListMultimap.<String, Integer>create());
     multimap.putAll("foo", Arrays.asList(3, -1, 2, 4, 1));
     multimap.putAll("bar", Arrays.asList(1, 2, 3, 1));
-    assertThat(multimap.removeAll("foo")).has().exactly(3, -1, 2, 4, 1).inOrder();
+    assertThat(multimap.removeAll("foo")).containsExactly(3, -1, 2, 4, 1).inOrder();
     assertFalse(multimap.containsKey("foo"));
     assertThat(multimap.replaceValues("bar", Arrays.asList(6, 5)))
-        .has().exactly(1, 2, 3, 1).inOrder();
-    assertThat(multimap.get("bar")).has().exactly(6, 5).inOrder();
+        .containsExactly(1, 2, 3, 1).inOrder();
+    assertThat(multimap.get("bar")).containsExactly(6, 5).inOrder();
   }
 
   public void testSynchronizedSortedSetMultimap() {
@@ -217,11 +217,11 @@ public class SynchronizedMultimapTest extends TestCase {
             TreeMultimap.<String, Integer>create());
     multimap.putAll("foo", Arrays.asList(3, -1, 2, 4, 1));
     multimap.putAll("bar", Arrays.asList(1, 2, 3, 1));
-    assertThat(multimap.removeAll("foo")).has().exactly(-1, 1, 2, 3, 4).inOrder();
+    assertThat(multimap.removeAll("foo")).containsExactly(-1, 1, 2, 3, 4).inOrder();
     assertFalse(multimap.containsKey("foo"));
     assertThat(multimap.replaceValues("bar", Arrays.asList(6, 5)))
-        .has().exactly(1, 2, 3).inOrder();
-    assertThat(multimap.get("bar")).has().exactly(5, 6).inOrder();
+        .containsExactly(1, 2, 3).inOrder();
+    assertThat(multimap.get("bar")).containsExactly(5, 6).inOrder();
   }
 
   public void testSynchronizedArrayListMultimapRandomAccess() {
@@ -238,9 +238,8 @@ public class SynchronizedMultimapTest extends TestCase {
     ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
     delegate.put("foo", 1);
     delegate.put("foo", 3);
-    ListMultimap<String, Integer> multimap
-        = Multimaps.synchronizedListMultimap(delegate);
-    assertFalse(multimap.get("foo") instanceof RandomAccess);
-    assertFalse(multimap.get("bar") instanceof RandomAccess);
+    ListMultimap<String, Integer> multimap = Multimaps.synchronizedListMultimap(delegate);
+    assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+    assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
   }
 }
diff --git a/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java b/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
index 292a3b7..8a80d5a 100644
--- a/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
@@ -154,8 +154,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
     table.put("foo", 12, 'b');
     table.put("bar", 5, 'c');
     table.put("cat", 8, 'd');
-    assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
-    assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+    assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+    assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
   }
 
   public void testCreateCopy() {
@@ -166,8 +166,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
     original.put("bar", 5, 'c');
     original.put("cat", 8, 'd');
     table = TreeBasedTable.create(original);
-    assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
-    assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+    assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+    assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
     assertEquals(original, table);
   }
 
diff --git a/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java b/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
index c6ec282..c679b6d 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
@@ -99,13 +99,13 @@ public class TreeMultimapExplicitTest extends TestCase {
     tree.put("google", 6);
     tree.put("tree", 0);
     tree.put("tree", 3);
-    assertThat(tree.keySet()).has().exactly("tree", "google").inOrder();
-    assertThat(tree.get("google")).has().exactly(6, 2).inOrder();
+    assertThat(tree.keySet()).containsExactly("tree", "google").inOrder();
+    assertThat(tree.get("google")).containsExactly(6, 2).inOrder();
 
     TreeMultimap<String, Integer> copy = TreeMultimap.create(tree);
     assertEquals(tree, copy);
-    assertThat(copy.keySet()).has().exactly("google", "tree").inOrder();
-    assertThat(copy.get("google")).has().exactly(2, 6).inOrder();
+    assertThat(copy.keySet()).containsExactly("google", "tree").inOrder();
+    assertThat(copy.get("google")).containsExactly(2, 6).inOrder();
     assertEquals(Ordering.natural(), copy.keyComparator());
     assertEquals(Ordering.natural(), copy.valueComparator());
     assertEquals(Ordering.natural(), copy.get("google").comparator());
@@ -130,14 +130,14 @@ public class TreeMultimapExplicitTest extends TestCase {
 
   public void testOrderedGet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.get(null)).has().exactly(7, 3, 1).inOrder();
-    assertThat(multimap.get("google")).has().exactly(6, 2).inOrder();
-    assertThat(multimap.get("tree")).has().exactly(null, 0).inOrder();
+    assertThat(multimap.get(null)).containsExactly(7, 3, 1).inOrder();
+    assertThat(multimap.get("google")).containsExactly(6, 2).inOrder();
+    assertThat(multimap.get("tree")).containsExactly(null, 0).inOrder();
   }
 
   public void testOrderedKeySet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.keySet()).has().exactly(null, "tree", "google").inOrder();
+    assertThat(multimap.keySet()).containsExactly(null, "tree", "google").inOrder();
   }
 
   public void testOrderedAsMapEntries() {
@@ -146,18 +146,18 @@ public class TreeMultimapExplicitTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = iterator.next();
     assertEquals(null, entry.getKey());
-    assertThat(entry.getValue()).has().exactly(7, 3, 1);
+    assertThat(entry.getValue()).containsExactly(7, 3, 1);
     entry = iterator.next();
     assertEquals("tree", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(null, 0);
+    assertThat(entry.getValue()).containsExactly(null, 0);
     entry = iterator.next();
     assertEquals("google", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(6, 2);
+    assertThat(entry.getValue()).containsExactly(6, 2);
   }
 
   public void testOrderedEntries() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry((String) null, 7),
         Maps.immutableEntry((String) null, 3),
         Maps.immutableEntry((String) null, 1),
@@ -169,7 +169,7 @@ public class TreeMultimapExplicitTest extends TestCase {
 
   public void testOrderedValues() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
+    assertThat(multimap.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
   }
 
   public void testComparator() {
@@ -211,8 +211,8 @@ public class TreeMultimapExplicitTest extends TestCase {
     TreeMultimap<String, Integer> multimap = createPopulate();
     TreeMultimap<String, Integer> copy
         = SerializableTester.reserializeAndAssert(multimap);
-    assertThat(copy.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
-    assertThat(copy.keySet()).has().exactly(null, "tree", "google").inOrder();
+    assertThat(copy.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
+    assertThat(copy.keySet()).containsExactly(null, "tree", "google").inOrder();
     assertEquals(multimap.keyComparator(), copy.keyComparator());
     assertEquals(multimap.valueComparator(), copy.valueComparator());
   }
diff --git a/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java b/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
index b0edc71..b96c207 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
@@ -65,7 +65,7 @@ public class TreeMultimapNaturalTest extends TestCase {
   @GwtIncompatible("suite")
   public static Test suite() {
     TestSuite suite = new TestSuite();
-    // TODO(user): should we force TreeMultimap to be more thorough about checking nulls?
+    // TODO(lowasser): should we force TreeMultimap to be more thorough about checking nulls?
     suite.addTest(SortedSetMultimapTestSuiteBuilder.using(new TestStringSetMultimapGenerator() {
         @Override
         protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
@@ -283,14 +283,14 @@ public class TreeMultimapNaturalTest extends TestCase {
 
   public void testOrderedGet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.get("foo")).has().exactly(1, 3, 7).inOrder();
-    assertThat(multimap.get("google")).has().exactly(2, 6).inOrder();
-    assertThat(multimap.get("tree")).has().exactly(0, 4).inOrder();
+    assertThat(multimap.get("foo")).containsExactly(1, 3, 7).inOrder();
+    assertThat(multimap.get("google")).containsExactly(2, 6).inOrder();
+    assertThat(multimap.get("tree")).containsExactly(0, 4).inOrder();
   }
 
   public void testOrderedKeySet() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.keySet()).has().exactly("foo", "google", "tree").inOrder();
+    assertThat(multimap.keySet()).containsExactly("foo", "google", "tree").inOrder();
   }
 
   public void testOrderedAsMapEntries() {
@@ -299,18 +299,18 @@ public class TreeMultimapNaturalTest extends TestCase {
         multimap.asMap().entrySet().iterator();
     Map.Entry<String, Collection<Integer>> entry = iterator.next();
     assertEquals("foo", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(1, 3, 7);
+    assertThat(entry.getValue()).containsExactly(1, 3, 7);
     entry = iterator.next();
     assertEquals("google", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(2, 6);
+    assertThat(entry.getValue()).containsExactly(2, 6);
     entry = iterator.next();
     assertEquals("tree", entry.getKey());
-    assertThat(entry.getValue()).has().exactly(0, 4);
+    assertThat(entry.getValue()).containsExactly(0, 4);
   }
 
   public void testOrderedEntries() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.entries()).has().exactly(
+    assertThat(multimap.entries()).containsExactly(
         Maps.immutableEntry("foo", 1),
         Maps.immutableEntry("foo", 3),
         Maps.immutableEntry("foo", 7),
@@ -322,7 +322,7 @@ public class TreeMultimapNaturalTest extends TestCase {
 
   public void testOrderedValues() {
     TreeMultimap<String, Integer> multimap = createPopulate();
-    assertThat(multimap.values()).has().exactly(
+    assertThat(multimap.values()).containsExactly(
         1, 3, 7, 2, 6, 0, 4).inOrder();
   }
 
@@ -405,8 +405,8 @@ public class TreeMultimapNaturalTest extends TestCase {
     TreeMultimap<String, Integer> multimap = createPopulate();
     TreeMultimap<String, Integer> copy
         = SerializableTester.reserializeAndAssert(multimap);
-    assertThat(copy.values()).has().exactly(1, 3, 7, 2, 6, 0, 4).inOrder();
-    assertThat(copy.keySet()).has().exactly("foo", "google", "tree").inOrder();
+    assertThat(copy.values()).containsExactly(1, 3, 7, 2, 6, 0, 4).inOrder();
+    assertThat(copy.keySet()).containsExactly("foo", "google", "tree").inOrder();
     assertEquals(multimap.keyComparator(), copy.keyComparator());
     assertEquals(multimap.valueComparator(), copy.valueComparator());
   }
@@ -421,9 +421,9 @@ public class TreeMultimapNaturalTest extends TestCase {
     multimap.put(new DerivedComparable("bar"), new DerivedComparable("b"));
     multimap.put(new DerivedComparable("bar"), new DerivedComparable("a"));
     multimap.put(new DerivedComparable("bar"), new DerivedComparable("r"));
-    assertThat(multimap.keySet()).has().exactly(
+    assertThat(multimap.keySet()).containsExactly(
         new DerivedComparable("bar"), new DerivedComparable("foo")).inOrder();
-    assertThat(multimap.values()).has().exactly(
+    assertThat(multimap.values()).containsExactly(
         new DerivedComparable("a"), new DerivedComparable("b"), new DerivedComparable("r"),
         new DerivedComparable("f"), new DerivedComparable("o")).inOrder();
     assertEquals(Ordering.natural(), multimap.keyComparator());
@@ -442,9 +442,9 @@ public class TreeMultimapNaturalTest extends TestCase {
     multimap.put(new LegacyComparable("bar"), new LegacyComparable("b"));
     multimap.put(new LegacyComparable("bar"), new LegacyComparable("a"));
     multimap.put(new LegacyComparable("bar"), new LegacyComparable("r"));
-    assertThat(multimap.keySet()).has().exactly(
+    assertThat(multimap.keySet()).containsExactly(
         new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
-    assertThat(multimap.values()).has().exactly(
+    assertThat(multimap.values()).containsExactly(
         new LegacyComparable("a"),
         new LegacyComparable("b"),
         new LegacyComparable("r"),
diff --git a/guava-tests/test/com/google/common/collect/TreeMultisetTest.java b/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
index 86a2197..52db060 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
@@ -163,9 +163,9 @@ public class TreeMultisetTest extends TestCase {
     assertEquals("c", elementSet.last());
     assertEquals(Ordering.natural(), elementSet.comparator());
 
-    assertThat(elementSet.headSet("b")).has().exactly("a").inOrder();
-    assertThat(elementSet.tailSet("b")).has().exactly("b", "c").inOrder();
-    assertThat(elementSet.subSet("a", "c")).has().exactly("a", "b").inOrder();
+    assertThat(elementSet.headSet("b")).containsExactly("a");
+    assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder();
+    assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder();
   }
 
   public void testElementSetSubsetRemove() {
@@ -178,18 +178,18 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.remove("c"));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
 
     assertFalse(subset.remove("a"));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
   }
 
@@ -203,13 +203,13 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.removeAll(Arrays.asList("a", "c")));
-    assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
-    assertThat(subset).has().exactly("b", "d", "e").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+    assertThat(subset).containsExactly("b", "d", "e").inOrder();
     assertEquals(10, ms.size());
   }
 
@@ -223,13 +223,13 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     assertTrue(subset.retainAll(Arrays.asList("a", "c")));
-    assertThat(elementSet).has().exactly("a", "c", "f").inOrder();
-    assertThat(subset).has().exactly("c").inOrder();
+    assertThat(elementSet).containsExactly("a", "c", "f").inOrder();
+    assertThat(subset).containsExactly("c");
     assertEquals(5, ms.size());
   }
 
@@ -243,12 +243,12 @@ public class TreeMultisetTest extends TestCase {
     ms.add("f", 2);
 
     SortedSet<String> elementSet = ms.elementSet();
-    assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
     SortedSet<String> subset = elementSet.subSet("b", "f");
-    assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+    assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
 
     subset.clear();
-    assertThat(elementSet).has().exactly("a", "f").inOrder();
+    assertThat(elementSet).containsExactly("a", "f").inOrder();
     assertThat(subset).isEmpty();
     assertEquals(3, ms.size());
   }
@@ -268,7 +268,7 @@ public class TreeMultisetTest extends TestCase {
     ms.add("b");
     ms.add("d");
 
-    assertThat(ms).has().exactly("d", "c", "b", "b", "a").inOrder();
+    assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder();
 
     SortedSet<String> elementSet = ms.elementSet();
     assertEquals("d", elementSet.first());
@@ -286,7 +286,7 @@ public class TreeMultisetTest extends TestCase {
     ms.add("b");
     ms.add(null, 2);
 
-    assertThat(ms).has().exactly(null, null, null, "a", "b", "b").inOrder();
+    assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder();
     assertEquals(3, ms.count(null));
 
     SortedSet<String> elementSet = ms.elementSet();
@@ -353,6 +353,7 @@ public class TreeMultisetTest extends TestCase {
   }
 
   @GwtIncompatible("reflection")
+  @SuppressUnderAndroid // Reflection bug, or actual binary compatibility problem?
   public void testElementSetBridgeMethods() {
     for (Method m : TreeMultiset.class.getMethods()) {
       if (m.getName().equals("elementSet") && m.getReturnType().equals(SortedSet.class)) {
diff --git a/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java b/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
index 02dbbc4..d1b77ab 100644
--- a/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
@@ -152,6 +152,115 @@ public class TreeRangeMapTest extends TestCase {
           MapFeature.ALLOWS_ANY_NULL_QUERIES,
           CollectionFeature.KNOWN_ORDER)
       .createTestSuite());
+
+    suite.addTest(MapTestSuiteBuilder.using(new TestMapGenerator<Range<Integer>, String>() {
+        @Override
+        public SampleElements<Entry<Range<Integer>, String>> samples() {
+          return new SampleElements<Entry<Range<Integer>, String>>(
+              mapEntry(Range.singleton(0), "banana"),
+              mapEntry(Range.closedOpen(3, 5), "frisbee"),
+              mapEntry(Range.atMost(-1), "fruitcake"),
+              mapEntry(Range.open(10, 15), "elephant"),
+              mapEntry(Range.closed(20, 22), "umbrella"));
+        }
+
+        @Override
+        public Map<Range<Integer>, String> create(Object... elements) {
+          RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
+          for (Object o : elements) {
+            @SuppressWarnings("unchecked")
+            Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o;
+            rangeMap.put(entry.getKey(), entry.getValue());
+          }
+          return rangeMap.asDescendingMapOfRanges();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Entry<Range<Integer>, String>[] createArray(int length) {
+          return new Entry[length];
+        }
+
+        @Override
+        public Iterable<Entry<Range<Integer>, String>> order(
+            List<Entry<Range<Integer>, String>> insertionOrder) {
+          return Range.RANGE_LEX_ORDERING.reverse().<Range<Integer>>onKeys()
+              .sortedCopy(insertionOrder);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Range<Integer>[] createKeyArray(int length) {
+          return new Range[length];
+        }
+
+        @Override
+        public String[] createValueArray(int length) {
+          return new String[length];
+        }
+      })
+      .named("TreeRangeMap.asDescendingMapOfRanges")
+      .withFeatures(
+          CollectionSize.ANY,
+          MapFeature.SUPPORTS_REMOVE,
+          MapFeature.ALLOWS_ANY_NULL_QUERIES,
+          CollectionFeature.KNOWN_ORDER,
+          CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+      .createTestSuite());
+
+    suite.addTest(MapTestSuiteBuilder.using(new TestMapGenerator<Range<Integer>, String>() {
+        @Override
+        public SampleElements<Entry<Range<Integer>, String>> samples() {
+          return new SampleElements<Entry<Range<Integer>, String>>(
+              mapEntry(Range.singleton(0), "banana"),
+              mapEntry(Range.closedOpen(3, 5), "frisbee"),
+              mapEntry(Range.atMost(-1), "fruitcake"),
+              mapEntry(Range.open(10, 15), "elephant"),
+              mapEntry(Range.closed(20, 22), "umbrella"));
+        }
+
+        @Override
+        public Map<Range<Integer>, String> create(Object... elements) {
+          RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
+          for (Object o : elements) {
+            @SuppressWarnings("unchecked")
+            Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o;
+            rangeMap.put(entry.getKey(), entry.getValue());
+          }
+          return rangeMap.subRangeMap(Range.atMost(22)).asDescendingMapOfRanges();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Entry<Range<Integer>, String>[] createArray(int length) {
+          return new Entry[length];
+        }
+
+        @Override
+        public Iterable<Entry<Range<Integer>, String>> order(
+            List<Entry<Range<Integer>, String>> insertionOrder) {
+          return Range.RANGE_LEX_ORDERING.reverse().<Range<Integer>>onKeys()
+              .sortedCopy(insertionOrder);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Range<Integer>[] createKeyArray(int length) {
+          return new Range[length];
+        }
+
+        @Override
+        public String[] createValueArray(int length) {
+          return new String[length];
+        }
+      })
+      .named("TreeRangeMap.subRangeMap.asDescendingMapOfRanges")
+      .withFeatures(
+          CollectionSize.ANY,
+          MapFeature.SUPPORTS_REMOVE,
+          MapFeature.ALLOWS_ANY_NULL_QUERIES,
+          CollectionFeature.KNOWN_ORDER)
+      .createTestSuite());
     return suite;
   }
 
@@ -345,6 +454,9 @@ public class TreeRangeMapTest extends TestCase {
           RangeMap<Integer, Integer> subRangeMap = rangeMap.subRangeMap(subRange);
           assertEquals(expected, subRangeMap);
           assertEquals(expected.asMapOfRanges(), subRangeMap.asMapOfRanges());
+          assertEquals(expected.asDescendingMapOfRanges(), subRangeMap.asDescendingMapOfRanges());
+          assertEquals(ImmutableList.copyOf(subRangeMap.asMapOfRanges().entrySet()).reverse(),
+              ImmutableList.copyOf(subRangeMap.asDescendingMapOfRanges().entrySet()));
 
           if (!expected.asMapOfRanges().isEmpty()) {
             assertEquals(expected.span(), subRangeMap.span());
diff --git a/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java b/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
index 55a618e..2d45e87 100644
--- a/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
@@ -115,13 +115,17 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
       assertEquals(expected.higherEntry(key), navigableMap.higherEntry(key));
       for (boolean inclusive : new boolean[] {false, true}) {
         assertThat(navigableMap.headMap(key, inclusive).entrySet())
-            .has().exactlyAs(expected.headMap(key, inclusive).entrySet()).inOrder();
+            .containsExactlyElementsIn(expected.headMap(key, inclusive).entrySet())
+            .inOrder();
         assertThat(navigableMap.tailMap(key, inclusive).entrySet())
-            .has().exactlyAs(expected.tailMap(key, inclusive).entrySet()).inOrder();
+            .containsExactlyElementsIn(expected.tailMap(key, inclusive).entrySet())
+            .inOrder();
         assertThat(navigableMap.headMap(key, inclusive).descendingMap().entrySet())
-            .has().exactlyAs(expected.headMap(key, inclusive).descendingMap().entrySet()).inOrder();
+            .containsExactlyElementsIn(expected.headMap(key, inclusive).descendingMap().entrySet())
+            .inOrder();
         assertThat(navigableMap.tailMap(key, inclusive).descendingMap().entrySet())
-            .has().exactlyAs(expected.tailMap(key, inclusive).descendingMap().entrySet()).inOrder();
+            .containsExactlyElementsIn(expected.tailMap(key, inclusive).descendingMap().entrySet())
+            .inOrder();
       }
     }
   }
@@ -152,7 +156,8 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
 
       assertEquals(complement, rangeSet.complement());
       assertThat(rangeSet.complement().asRanges())
-          .has().exactlyAs(complement.asRanges()).inOrder();
+          .containsExactlyElementsIn(complement.asRanges())
+          .inOrder();
     }
   }
 
@@ -289,9 +294,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 4));
     rangeSet.add(Range.open(2, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.atLeast(6))
+        .inOrder();
   }
 
   public void testMergesConnectedDisjoint() {
@@ -299,9 +305,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 4));
     rangeSet.add(Range.open(4, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.atLeast(6))
+        .inOrder();
   }
 
   public void testIgnoresSmallerSharingNoBound() {
@@ -309,9 +316,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 6));
     rangeSet.add(Range.open(2, 4));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testIgnoresSmallerSharingLowerBound() {
@@ -319,9 +327,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 6));
     rangeSet.add(Range.closed(1, 4));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testIgnoresSmallerSharingUpperBound() {
@@ -329,9 +338,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 6));
     rangeSet.add(Range.closed(3, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testIgnoresEqual() {
@@ -339,9 +349,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 6));
     rangeSet.add(Range.closed(1, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testExtendSameLowerBound() {
@@ -349,9 +360,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 4));
     rangeSet.add(Range.closed(1, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testExtendSameUpperBound() {
@@ -359,9 +371,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 6));
     rangeSet.add(Range.closed(1, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testExtendBothDirections() {
@@ -369,9 +382,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 4));
     rangeSet.add(Range.closed(1, 6));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testAddEmpty() {
@@ -379,7 +393,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closedOpen(3, 3));
     testInvariants(rangeSet);
     assertThat(rangeSet.asRanges()).isEmpty();
-    assertThat(rangeSet.complement().asRanges()).has().exactly(Range.<Integer>all()).inOrder();
+    assertThat(rangeSet.complement().asRanges()).containsExactly(Range.<Integer>all());
   }
 
   public void testFillHoleExactly() {
@@ -388,9 +402,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closedOpen(4, 6));
     rangeSet.add(Range.closedOpen(3, 4));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.atLeast(6))
+        .inOrder();
   }
 
   public void testFillHoleWithOverlap() {
@@ -399,9 +414,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closedOpen(4, 6));
     rangeSet.add(Range.closedOpen(2, 5));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.atLeast(6))
+        .inOrder();
   }
 
   public void testAddManyPairs() {
@@ -438,16 +454,16 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     if (a.isEmpty() && b.isEmpty()) {
       assertThat(rangeSet.asRanges()).isEmpty();
     } else if (a.isEmpty()) {
-      assertThat(rangeSet.asRanges()).has().item(b);
+      assertThat(rangeSet.asRanges()).contains(b);
     } else if (b.isEmpty()) {
-      assertThat(rangeSet.asRanges()).has().item(a);
+      assertThat(rangeSet.asRanges()).contains(a);
     } else if (a.isConnected(b)) {
-      assertThat(rangeSet.asRanges()).has().exactly(a.span(b)).inOrder();
+      assertThat(rangeSet.asRanges()).containsExactly(a.span(b));
     } else {
       if (a.lowerEndpoint() < b.lowerEndpoint()) {
-        assertThat(rangeSet.asRanges()).has().exactly(a, b).inOrder();
+        assertThat(rangeSet.asRanges()).containsExactly(a, b).inOrder();
       } else {
-        assertThat(rangeSet.asRanges()).has().exactly(b, a).inOrder();
+        assertThat(rangeSet.asRanges()).containsExactly(b, a).inOrder();
       }
     }
   }
@@ -457,9 +473,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(1, 6));
     rangeSet.remove(Range.closedOpen(3, 3));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+        .inOrder();
   }
 
   public void testRemovePartSharingLowerBound() {
@@ -467,9 +484,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 5));
     rangeSet.remove(Range.closedOpen(3, 5));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.singleton(5));
+    assertThat(rangeSet.asRanges()).contains(Range.singleton(5));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(5), Range.greaterThan(5)).inOrder();
+        .containsExactly(Range.lessThan(5), Range.greaterThan(5))
+        .inOrder();
   }
 
   public void testRemovePartSharingUpperBound() {
@@ -477,9 +495,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 5));
     rangeSet.remove(Range.openClosed(3, 5));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().item(Range.singleton(3));
+    assertThat(rangeSet.asRanges()).contains(Range.singleton(3));
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.lessThan(3), Range.greaterThan(3)).inOrder();
+        .containsExactly(Range.lessThan(3), Range.greaterThan(3))
+        .inOrder();
   }
 
   public void testRemoveMiddle() {
@@ -487,9 +506,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.atMost(6));
     rangeSet.remove(Range.closedOpen(3, 4));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().exactly(Range.lessThan(3), Range.closed(4, 6)).inOrder();
+    assertThat(rangeSet.asRanges())
+        .containsExactly(Range.lessThan(3), Range.closed(4, 6)).inOrder();
     assertThat(rangeSet.complement().asRanges())
-        .has().exactly(Range.closedOpen(3, 4), Range.greaterThan(6)).inOrder();
+        .containsExactly(Range.closedOpen(3, 4), Range.greaterThan(6)).inOrder();
   }
 
   public void testRemoveNoOverlap() {
@@ -497,7 +517,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 6));
     rangeSet.remove(Range.closedOpen(1, 3));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().exactly(Range.closed(3, 6)).inOrder();
+    assertThat(rangeSet.asRanges()).containsExactly(Range.closed(3, 6));
   }
 
   public void testRemovePartFromBelowLowerBound() {
@@ -505,7 +525,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 6));
     rangeSet.remove(Range.closed(1, 3));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().exactly(Range.openClosed(3, 6)).inOrder();
+    assertThat(rangeSet.asRanges()).containsExactly(Range.openClosed(3, 6));
   }
 
   public void testRemovePartFromAboveUpperBound() {
@@ -513,7 +533,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
     rangeSet.add(Range.closed(3, 6));
     rangeSet.remove(Range.closed(6, 9));
     testInvariants(rangeSet);
-    assertThat(rangeSet.asRanges()).has().exactly(Range.closedOpen(3, 6)).inOrder();
+    assertThat(rangeSet.asRanges()).containsExactly(Range.closedOpen(3, 6));
   }
 
   public void testRemoveExact() {
diff --git a/guava-tests/test/com/google/common/escape/EscapersTest.java b/guava-tests/test/com/google/common/escape/EscapersTest.java
index c8df0a2..9f33368 100644
--- a/guava-tests/test/com/google/common/escape/EscapersTest.java
+++ b/guava-tests/test/com/google/common/escape/EscapersTest.java
@@ -115,7 +115,7 @@ public class EscapersTest extends TestCase {
   }
 
   // A trival non-optimized escaper for testing.
-  private CharEscaper createSimpleCharEscaper(
+  static CharEscaper createSimpleCharEscaper(
       final ImmutableMap<Character, char[]> replacementMap) {
     return new CharEscaper() {
       @Override protected char[] escape(char c) {
@@ -125,7 +125,7 @@ public class EscapersTest extends TestCase {
   }
 
   // A trival non-optimized escaper for testing.
-  private UnicodeEscaper createSimpleUnicodeEscaper(
+  static UnicodeEscaper createSimpleUnicodeEscaper(
       final ImmutableMap<Integer, char[]> replacementMap) {
     return new UnicodeEscaper() {
       @Override protected char[] escape(int cp) {
diff --git a/guava-tests/test/com/google/common/eventbus/DispatcherTest.java b/guava-tests/test/com/google/common/eventbus/DispatcherTest.java
new file mode 100644
index 0000000..a55f191
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/DispatcherTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2014 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.eventbus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Queues;
+import com.google.common.util.concurrent.Uninterruptibles;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * Tests for {@link Dispatcher} implementations.
+ *
+ * @author Colin Decker
+ */
+
+public class DispatcherTest extends TestCase {
+
+  private final EventBus bus = new EventBus();
+
+  private final IntegerSubscriber i1 = new IntegerSubscriber("i1");
+  private final IntegerSubscriber i2 = new IntegerSubscriber("i2");
+  private final IntegerSubscriber i3 = new IntegerSubscriber("i3");
+  private final ImmutableList<Subscriber> integerSubscribers = ImmutableList.of(
+      subscriber(bus, i1, "handleInteger", Integer.class),
+      subscriber(bus, i2, "handleInteger", Integer.class),
+      subscriber(bus, i3, "handleInteger", Integer.class));
+
+  private final StringSubscriber s1 = new StringSubscriber("s1");
+  private final StringSubscriber s2 = new StringSubscriber("s2");
+  private final ImmutableList<Subscriber> stringSubscribers = ImmutableList.of(
+      subscriber(bus, s1, "handleString", String.class),
+      subscriber(bus, s2, "handleString", String.class));
+
+  private final ConcurrentLinkedQueue<Object> dispatchedSubscribers
+      = Queues.newConcurrentLinkedQueue();
+
+  private Dispatcher dispatcher;
+
+  public void testPerThreadQueuedDispatcher() {
+    dispatcher = Dispatcher.perThreadDispatchQueue();
+    dispatcher.dispatch(1, integerSubscribers.iterator());
+
+    assertThat(dispatchedSubscribers)
+        .containsExactly(
+            i1, i2, i3, // Integer subscribers are dispatched to first.
+            s1, s2,     // Though each integer subscriber dispatches to all string subscribers,
+            s1, s2,     // those string subscribers aren't actually dispatched to until all integer
+            s1, s2      // subscribers have finished.
+        ).inOrder();
+  }
+
+  public void testLegacyAsyncDispatcher() {
+    dispatcher = Dispatcher.legacyAsync();
+
+    final CyclicBarrier barrier = new CyclicBarrier(2);
+    final CountDownLatch latch = new CountDownLatch(2);
+
+    new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          barrier.await();
+        } catch (Exception e) {
+          throw new AssertionError(e);
+        }
+
+        dispatcher.dispatch(2, integerSubscribers.iterator());
+        latch.countDown();
+      }
+    }).start();
+
+    new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          barrier.await();
+        } catch (Exception e) {
+          throw new AssertionError(e);
+        }
+
+        dispatcher.dispatch("foo", stringSubscribers.iterator());
+        latch.countDown();
+      }
+    }).start();
+
+    Uninterruptibles.awaitUninterruptibly(latch);
+
+    // See Dispatcher.LegacyAsyncDispatcher for an explanation of why there aren't really any
+    // useful testable guarantees about the behavior of that dispatcher in a multithreaded
+    // environment. Here we simply test that all the expected dispatches happened in some order.
+    assertThat(dispatchedSubscribers)
+        .containsExactly(
+            i1, i2, i3,
+            s1, s1, s1, s1,
+            s2, s2, s2, s2);
+  }
+
+  public void testImmediateDispatcher() {
+    dispatcher = Dispatcher.immediate();
+    dispatcher.dispatch(1, integerSubscribers.iterator());
+
+    assertThat(dispatchedSubscribers)
+        .containsExactly(
+            i1, s1, s2,  // Each integer subscriber immediately dispatches to 2 string subscribers.
+            i2, s1, s2,
+            i3, s1, s2
+        ).inOrder();
+  }
+
+  private static Subscriber subscriber(
+      EventBus bus, Object target,
+      String methodName, Class<?> eventType) {
+    try {
+      return Subscriber.create(bus, target, target.getClass().getMethod(methodName, eventType));
+    } catch (NoSuchMethodException e) {
+      throw new AssertionError(e);
+    }
+  }
+
+  public final class IntegerSubscriber {
+    private final String name;
+
+    public IntegerSubscriber(String name) {
+      this.name = name;
+    }
+
+    @Subscribe
+    public void handleInteger(Integer integer) {
+      dispatchedSubscribers.add(this);
+      dispatcher.dispatch("hello", stringSubscribers.iterator());
+    }
+
+    @Override
+    public String toString() {
+      return name;
+    }
+  }
+
+  public final class StringSubscriber {
+    private final String name;
+
+    public StringSubscriber(String name) {
+      this.name = name;
+    }
+
+    @Subscribe
+    public void handleString(String string) {
+      dispatchedSubscribers.add(this);
+    }
+
+    @Override
+    public String toString() {
+      return name;
+    }
+  }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/EventBusTest.java b/guava-tests/test/com/google/common/eventbus/EventBusTest.java
index 35cb2f1..82371f2 100644
--- a/guava-tests/test/com/google/common/eventbus/EventBusTest.java
+++ b/guava-tests/test/com/google/common/eventbus/EventBusTest.java
@@ -21,9 +21,7 @@ import com.google.common.collect.Lists;
 
 import junit.framework.TestCase;
 
-import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -88,12 +86,12 @@ public class EventBusTest extends TestCase {
     bus.register(compCatcher);
 
     // Two additional event types: Object and Comparable<?> (played by Integer)
-    final Object OBJ_EVENT = new Object();
-    final Object COMP_EVENT = new Integer(6);
+    Object objEvent = new Object();
+    Object compEvent = new Integer(6);
 
     bus.post(EVENT);
-    bus.post(OBJ_EVENT);
-    bus.post(COMP_EVENT);
+    bus.post(objEvent);
+    bus.post(compEvent);
 
     // Check the StringCatcher...
     List<String> stringEvents = stringCatcher.getEvents();
@@ -108,9 +106,9 @@ public class EventBusTest extends TestCase {
     assertEquals("String fixture must be first object delivered.",
         EVENT, objectEvents.get(0));
     assertEquals("Object fixture must be second object delivered.",
-        OBJ_EVENT, objectEvents.get(1));
+        objEvent, objectEvents.get(1));
     assertEquals("Comparable fixture must be thirdobject delivered.",
-        COMP_EVENT, objectEvents.get(2));
+        compEvent, objectEvents.get(2));
 
     // Check the Catcher<Comparable<?>>...
     assertEquals("Two Comparable<?>s should be delivered.",
@@ -118,7 +116,7 @@ public class EventBusTest extends TestCase {
     assertEquals("String fixture must be first comparable delivered.",
         EVENT, compEvents.get(0));
     assertEquals("Comparable fixture must be second comparable delivered.",
-        COMP_EVENT, compEvents.get(1));
+        compEvent, compEvents.get(1));
   }
 
   public void testSubscriberThrowsException() throws Exception{
@@ -198,18 +196,6 @@ public class EventBusTest extends TestCase {
         EVENT, events.get(0).getEvent());
   }
 
-  public void testFlattenHierarchy() {
-    HierarchyFixture fixture = new HierarchyFixture();
-    Set<Class<?>> hierarchy = bus.flattenHierarchy(fixture.getClass());
-
-    assertEquals(5, hierarchy.size());
-    assertContains(Object.class, hierarchy);
-    assertContains(HierarchyFixtureInterface.class, hierarchy);
-    assertContains(HierarchyFixtureSubinterface.class, hierarchy);
-    assertContains(HierarchyFixtureParent.class, hierarchy);
-    assertContains(HierarchyFixture.class, hierarchy);
-  }
-
   public void testMissingSubscribe() {
     bus.register(new Object());
   }
@@ -308,11 +294,6 @@ public class EventBusTest extends TestCase {
     assertEquals(1, calls.get());
   }
 
-  private <T> void assertContains(T element, Collection<T> collection) {
-    assertTrue("Collection must contain " + element,
-        collection.contains(element));
-  }
-
   /**
    * Records thrown exception information.
    */
@@ -370,24 +351,6 @@ public class EventBusTest extends TestCase {
     }
   }
 
-  private interface HierarchyFixtureInterface {
-    // Exists only for hierarchy mapping; no members.
-  }
-
-  private interface HierarchyFixtureSubinterface
-      extends HierarchyFixtureInterface {
-    // Exists only for hierarchy mapping; no members.
-  }
-
-  private static class HierarchyFixtureParent
-      implements HierarchyFixtureSubinterface {
-    // Exists only for hierarchy mapping; no members.
-  }
-
-  private static class HierarchyFixture extends HierarchyFixtureParent {
-    // Exists only for hierarchy mapping; no members.
-  }
-
   private interface Callback<T> {
     void call(T t);
   }
diff --git a/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java b/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java
deleted file mode 100644
index b0a332a..0000000
--- a/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.eventbus;
-
-import com.google.common.testing.EqualsTester;
-
-import junit.framework.TestCase;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Test case for {@link EventSubscriber}.
- *
- * @author Cliff Biffle
- */
-public class EventSubscriberTest extends TestCase {
-
-  private static final Object FIXTURE_ARGUMENT = new Object();
-
-  private boolean methodCalled;
-  private Object methodArgument;
-
-  @Override protected void setUp() throws Exception {
-    super.setUp();
-
-    methodCalled = false;
-    methodArgument = null;
-  }
-
-  /**
-   * Checks that a no-frills, no-issues method call is properly executed.
-   *
-   * @throws Exception  if the aforementioned proper execution is not to be had.
-   */
-  public void testBasicMethodCall() throws Exception {
-    Method method = getRecordingMethod();
-
-    EventSubscriber subscriber = new EventSubscriber(this, method);
-
-    subscriber.handleEvent(FIXTURE_ARGUMENT);
-
-    assertTrue("Subscriber must call provided method.", methodCalled);
-    assertTrue("Subscriber argument must be *exactly* the provided object.",
-        methodArgument == FIXTURE_ARGUMENT);
-  }
-
-  public void testExceptionWrapping() {
-    Method method = getExceptionThrowingMethod();
-    EventSubscriber subscriber = new EventSubscriber(this, method);
-
-    try {
-      subscriber.handleEvent(new Object());
-      fail("Subscribers whose methods throw must throw InvocationTargetException");
-    } catch (InvocationTargetException e) {
-      assertTrue("Expected exception must be wrapped.",
-          e.getCause() instanceof IntentionalException);
-    }
-  }
-
-  public void testErrorPassthrough() throws InvocationTargetException {
-    Method method = getErrorThrowingMethod();
-    EventSubscriber subscriber = new EventSubscriber(this, method);
-
-    try {
-      subscriber.handleEvent(new Object());
-      fail("Subscribers whose methods throw Errors must rethrow them");
-    } catch (JudgmentError e) {
-      // Expected.
-    }
-  }
-
-  public void testEquals() throws Exception {
-    Method charAt = String.class.getMethod("charAt", int.class);
-    Method concat = String.class.getMethod("concat", String.class);
-    new EqualsTester()
-        .addEqualityGroup(
-            new EventSubscriber("foo", charAt), new EventSubscriber("foo", charAt))
-        .addEqualityGroup(new EventSubscriber("bar", charAt))
-        .addEqualityGroup(new EventSubscriber("foo", concat))
-        .testEquals();
-  }
-
-  /**
-   * Gets a reference to {@link #recordingMethod(Object)}.
-   *
-   * @return a Method wrapping {@link #recordingMethod(Object)}.
-   * @throws IllegalStateException if executed in a context where reflection is
-   *         unavailable.
-   * @throws AssertionError if something odd has happened to
-   *         {@link #recordingMethod(Object)}.
-   */
-  private Method getRecordingMethod() {
-    Method method;
-    try {
-      method = getClass().getMethod("recordingMethod", Object.class);
-    } catch (SecurityException e) {
-      throw new IllegalStateException("This test needs access to reflection.");
-    } catch (NoSuchMethodException e) {
-      throw new AssertionError(
-          "Someone changed EventSubscriberTest#recordingMethod's visibility, " +
-          "signature, or removed it entirely.  (Must be public.)");
-    }
-    return method;
-  }
-
-  /**
-   * Gets a reference to {@link #exceptionThrowingMethod(Object)}.
-   *
-   * @return a Method wrapping {@link #exceptionThrowingMethod(Object)}.
-   * @throws IllegalStateException if executed in a context where reflection is
-   *         unavailable.
-   * @throws AssertionError if something odd has happened to
-   *         {@link #exceptionThrowingMethod(Object)}.
-   */
-  private Method getExceptionThrowingMethod() {
-    Method method;
-    try {
-      method = getClass().getMethod("exceptionThrowingMethod", Object.class);
-    } catch (SecurityException e) {
-      throw new IllegalStateException("This test needs access to reflection.");
-    } catch (NoSuchMethodException e) {
-      throw new AssertionError(
-          "Someone changed EventSubscriberTest#exceptionThrowingMethod's " +
-          "visibility, signature, or removed it entirely.  (Must be public.)");
-    }
-    return method;
-  }
-
-  /**
-   * Gets a reference to {@link #errorThrowingMethod(Object)}.
-   *
-   * @return a Method wrapping {@link #errorThrowingMethod(Object)}.
-   * @throws IllegalStateException if executed in a context where reflection is
-   *         unavailable.
-   * @throws AssertionError if something odd has happened to
-   *         {@link #errorThrowingMethod(Object)}.
-   */
-  private Method getErrorThrowingMethod() {
-    Method method;
-    try {
-      method = getClass().getMethod("errorThrowingMethod", Object.class);
-    } catch (SecurityException e) {
-      throw new IllegalStateException("This test needs access to reflection.");
-    } catch (NoSuchMethodException e) {
-      throw new AssertionError(
-          "Someone changed EventSubscriberTest#errorThrowingMethod's " +
-          "visibility, signature, or removed it entirely.  (Must be public.)");
-    }
-    return method;
-  }
-
-  /**
-   * Records the provided object in {@link #methodArgument} and sets
-   * {@link #methodCalled}.  This method is called reflectively by EventSubscriber
-   * during tests, and must remain public.
-   *
-   * @param arg  argument to record.
-   */
-  public void recordingMethod(Object arg) {
-    assertFalse(methodCalled);
-    methodCalled = true;
-    methodArgument = arg;
-  }
-
-  public void exceptionThrowingMethod(Object arg) throws Exception {
-    throw new IntentionalException();
-  }
-  /** Local exception subclass to check variety of exception thrown. */
-  class IntentionalException extends Exception {
-    private static final long serialVersionUID = -2500191180248181379L;
-  }
-
-  public void errorThrowingMethod(Object arg) {
-    throw new JudgmentError();
-  }
-  /** Local Error subclass to check variety of error thrown. */
-  class JudgmentError extends Error {
-    private static final long serialVersionUID = 634248373797713373L;
-  }
-}
diff --git a/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java b/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
index 5f984b0..424e594 100644
--- a/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
+++ b/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
@@ -31,21 +31,35 @@ import javax.annotation.Nullable;
 public class PackageSanityTests extends AbstractPackageSanityTests {
 
   public PackageSanityTests() throws Exception {
-    setDefault(EventSubscriber.class, new DummySubscriber().toEventSubscriber());
+    DummySubscriber dummySubscriber = new DummySubscriber();
+    setDefault(Subscriber.class, dummySubscriber.toSubscriber());
     setDefault(Method.class, DummySubscriber.subscriberMethod());
+    setDefault(SubscriberExceptionContext.class, dummySubscriber.toContext());
+    setDefault(Dispatcher.class, Dispatcher.immediate());
   }
 
   private static class DummySubscriber {
 
-    @SuppressWarnings("unused") // Used by reflection
-    public void handle(@Nullable Object anything) {}
+    private final EventBus eventBus = new EventBus();
 
-    EventSubscriber toEventSubscriber() throws Exception {
-      return new EventSubscriber(this, subscriberMethod());
+    @Subscribe
+    public void handle(@Nullable Object anything) {
     }
 
-    private static Method subscriberMethod() throws NoSuchMethodException {
-      return DummySubscriber.class.getMethod("handle", Object.class);
+    Subscriber toSubscriber() throws Exception {
+      return Subscriber.create(eventBus, this, subscriberMethod());
+    }
+
+    SubscriberExceptionContext toContext() {
+      return new SubscriberExceptionContext(eventBus, new Object(), this, subscriberMethod());
+    }
+
+    private static Method subscriberMethod() {
+      try {
+        return DummySubscriber.class.getMethod("handle", Object.class);
+      } catch (NoSuchMethodException e) {
+        throw new AssertionError(e);
+      }
     }
   }
 }
diff --git a/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java b/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java
new file mode 100644
index 0000000..f3dc30b
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2014 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.eventbus;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+
+/**
+ * Tests for {@link SubscriberRegistry}.
+ *
+ * @author Colin Decker
+ */
+public class SubscriberRegistryTest extends TestCase {
+
+  private final SubscriberRegistry registry = new SubscriberRegistry(new EventBus());
+
+  public void testRegister() {
+    assertEquals(0, registry.getSubscribersForTesting(String.class).size());
+
+    registry.register(new StringSubscriber());
+    assertEquals(1, registry.getSubscribersForTesting(String.class).size());
+
+    registry.register(new StringSubscriber());
+    assertEquals(2, registry.getSubscribersForTesting(String.class).size());
+
+    registry.register(new ObjectSubscriber());
+    assertEquals(2, registry.getSubscribersForTesting(String.class).size());
+    assertEquals(1, registry.getSubscribersForTesting(Object.class).size());
+  }
+
+  public void testUnregister() {
+    StringSubscriber s1 = new StringSubscriber();
+    StringSubscriber s2 = new StringSubscriber();
+
+    registry.register(s1);
+    registry.register(s2);
+
+    registry.unregister(s1);
+    assertEquals(1, registry.getSubscribersForTesting(String.class).size());
+
+    registry.unregister(s2);
+    assertTrue(registry.getSubscribersForTesting(String.class).isEmpty());
+  }
+
+  public void testUnregister_notRegistered() {
+    try {
+      registry.unregister(new StringSubscriber());
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+
+    StringSubscriber s1 = new StringSubscriber();
+    registry.register(s1);
+    try {
+      registry.unregister(new StringSubscriber());
+      fail();
+    } catch (IllegalArgumentException expected) {
+      // a StringSubscriber was registered, but not the same one we tried to unregister
+    }
+
+    registry.unregister(s1);
+
+    try {
+      registry.unregister(s1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetSubscribers() {
+    assertEquals(0, Iterators.size(registry.getSubscribers("")));
+
+    registry.register(new StringSubscriber());
+    assertEquals(1, Iterators.size(registry.getSubscribers("")));
+
+    registry.register(new StringSubscriber());
+    assertEquals(2, Iterators.size(registry.getSubscribers("")));
+
+    registry.register(new ObjectSubscriber());
+    assertEquals(3, Iterators.size(registry.getSubscribers("")));
+    assertEquals(1, Iterators.size(registry.getSubscribers(new Object())));
+    assertEquals(1, Iterators.size(registry.getSubscribers(1)));
+
+    registry.register(new IntegerSubscriber());
+    assertEquals(3, Iterators.size(registry.getSubscribers("")));
+    assertEquals(1, Iterators.size(registry.getSubscribers(new Object())));
+    assertEquals(2, Iterators.size(registry.getSubscribers(1)));
+  }
+
+  public void testGetSubscribers_returnsImmutableSnapshot() {
+    StringSubscriber s1 = new StringSubscriber();
+    StringSubscriber s2 = new StringSubscriber();
+    ObjectSubscriber o1 = new ObjectSubscriber();
+
+    Iterator<Subscriber> empty = registry.getSubscribers("");
+    assertFalse(empty.hasNext());
+
+    empty = registry.getSubscribers("");
+
+    registry.register(s1);
+    assertFalse(empty.hasNext());
+
+    Iterator<Subscriber> one = registry.getSubscribers("");
+    assertEquals(s1, one.next().target);
+    assertFalse(one.hasNext());
+
+    one = registry.getSubscribers("");
+
+    registry.register(s2);
+    registry.register(o1);
+
+    Iterator<Subscriber> three = registry.getSubscribers("");
+    assertEquals(s1, one.next().target);
+    assertFalse(one.hasNext());
+
+    assertEquals(s1, three.next().target);
+    assertEquals(s2, three.next().target);
+    assertEquals(o1, three.next().target);
+    assertFalse(three.hasNext());
+
+    three = registry.getSubscribers("");
+
+    registry.unregister(s2);
+
+    assertEquals(s1, three.next().target);
+    assertEquals(s2, three.next().target);
+    assertEquals(o1, three.next().target);
+    assertFalse(three.hasNext());
+
+    Iterator<Subscriber> two = registry.getSubscribers("");
+    assertEquals(s1, two.next().target);
+    assertEquals(o1, two.next().target);
+    assertFalse(two.hasNext());
+  }
+
+  public static class StringSubscriber {
+
+    @Subscribe
+    public void handle(String s) {
+    }
+  }
+
+  public static class IntegerSubscriber {
+
+    @Subscribe
+    public void handle(Integer i) {
+    }
+  }
+
+  public static class ObjectSubscriber {
+
+    @Subscribe
+    public void handle(Object o) {
+    }
+  }
+
+  public void testFlattenHierarchy() {
+    assertEquals(
+        ImmutableSet.of(
+            Object.class,
+            HierarchyFixtureInterface.class,
+            HierarchyFixtureSubinterface.class,
+            HierarchyFixtureParent.class,
+            HierarchyFixture.class),
+        SubscriberRegistry.flattenHierarchy(HierarchyFixture.class));
+  }
+
+  private interface HierarchyFixtureInterface {
+    // Exists only for hierarchy mapping; no members.
+  }
+
+  private interface HierarchyFixtureSubinterface
+      extends HierarchyFixtureInterface {
+    // Exists only for hierarchy mapping; no members.
+  }
+
+  private static class HierarchyFixtureParent
+      implements HierarchyFixtureSubinterface {
+    // Exists only for hierarchy mapping; no members.
+  }
+
+  private static class HierarchyFixture extends HierarchyFixtureParent {
+    // Exists only for hierarchy mapping; no members.
+  }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/SubscriberTest.java b/guava-tests/test/com/google/common/eventbus/SubscriberTest.java
new file mode 100644
index 0000000..3860d56
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/SubscriberTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.eventbus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Tests for {@link Subscriber}.
+ *
+ * @author Cliff Biffle
+ * @author Colin Decker
+ */
+public class SubscriberTest extends TestCase {
+
+  private static final Object FIXTURE_ARGUMENT = new Object();
+
+  private EventBus bus;
+  private boolean methodCalled;
+  private Object methodArgument;
+
+  @Override
+  protected void setUp() throws Exception {
+    bus = new EventBus();
+    methodCalled = false;
+    methodArgument = null;
+  }
+
+  public void testCreate() {
+    Subscriber s1 = Subscriber.create(bus, this, getTestSubscriberMethod("recordingMethod"));
+    assertThat(s1).isInstanceOf(Subscriber.SynchronizedSubscriber.class);
+
+    // a thread-safe method should not create a synchronized subscriber
+    Subscriber s2 = Subscriber.create(bus, this, getTestSubscriberMethod("threadSafeMethod"));
+    assertThat(s2).isNotInstanceOf(Subscriber.SynchronizedSubscriber.class);
+  }
+
+  public void testInvokeSubscriberMethod_basicMethodCall() throws Throwable {
+    Method method = getTestSubscriberMethod("recordingMethod");
+    Subscriber subscriber = Subscriber.create(bus, this, method);
+
+    subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+
+    assertTrue("Subscriber must call provided method", methodCalled);
+    assertTrue("Subscriber argument must be exactly the provided object.",
+        methodArgument == FIXTURE_ARGUMENT);
+  }
+
+  public void testInvokeSubscriberMethod_exceptionWrapping() throws Throwable {
+    Method method = getTestSubscriberMethod("exceptionThrowingMethod");
+    Subscriber subscriber = Subscriber.create(bus, this, method);
+
+    try {
+      subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+      fail("Subscribers whose methods throw must throw InvocationTargetException");
+    } catch (InvocationTargetException expected) {
+      assertThat(expected.getCause()).isInstanceOf(IntentionalException.class);
+    }
+  }
+
+  public void testInvokeSubscriberMethod_errorPassthrough() throws Throwable {
+    Method method = getTestSubscriberMethod("errorThrowingMethod");
+    Subscriber subscriber = Subscriber.create(bus, this, method);
+
+    try {
+      subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+      fail("Subscribers whose methods throw Errors must rethrow them");
+    } catch (JudgmentError expected) {
+    }
+  }
+
+  public void testEquals() throws Exception {
+    Method charAt = String.class.getMethod("charAt", int.class);
+    Method concat = String.class.getMethod("concat", String.class);
+    new EqualsTester()
+        .addEqualityGroup(
+            Subscriber.create(bus, "foo", charAt), Subscriber.create(bus, "foo", charAt))
+        .addEqualityGroup(Subscriber.create(bus, "bar", charAt))
+        .addEqualityGroup(Subscriber.create(bus, "foo", concat))
+        .testEquals();
+  }
+
+  private Method getTestSubscriberMethod(String name) {
+    try {
+      return getClass().getDeclaredMethod(name, Object.class);
+    } catch (NoSuchMethodException e) {
+      throw new AssertionError();
+    }
+  }
+
+  /**
+   * Records the provided object in {@link #methodArgument} and sets {@link #methodCalled}.  This
+   * method is called reflectively by Subscriber during tests, and must remain public.
+   *
+   * @param arg argument to record.
+   */
+  @Subscribe
+  public void recordingMethod(Object arg) {
+    assertFalse(methodCalled);
+    methodCalled = true;
+    methodArgument = arg;
+  }
+
+  @Subscribe
+  public void exceptionThrowingMethod(Object arg) throws Exception {
+    throw new IntentionalException();
+  }
+
+  /**
+   * Local exception subclass to check variety of exception thrown.
+   */
+  class IntentionalException extends Exception {
+
+    private static final long serialVersionUID = -2500191180248181379L;
+  }
+
+  @Subscribe
+  public void errorThrowingMethod(Object arg) {
+    throw new JudgmentError();
+  }
+
+  @Subscribe @AllowConcurrentEvents
+  public void threadSafeMethod(Object arg) {
+  }
+
+  /**
+   * Local Error subclass to check variety of error thrown.
+   */
+  class JudgmentError extends Error {
+
+    private static final long serialVersionUID = 634248373797713373L;
+  }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java b/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
index b22eefd..ab3f401 100644
--- a/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
+++ b/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
@@ -30,6 +30,7 @@ import java.util.List;
  * Test that EventBus finds the correct subscribers.
  *
  * This test must be outside the c.g.c.eventbus package to test correctly.
+ *
  * @author Louis Wasserman
  */
 public class AnnotatedSubscriberFinderTests {
@@ -62,8 +63,8 @@ public class AnnotatedSubscriberFinderTests {
   /*
    * We break the tests up based on whether they are annotated or abstract in the superclass.
    */
-  public static class BaseSubscriberFinderTest extends
-      AbstractEventBusTest<BaseSubscriberFinderTest.Subscriber> {
+  public static class BaseSubscriberFinderTest
+      extends AbstractEventBusTest<BaseSubscriberFinderTest.Subscriber> {
     static class Subscriber {
       final List<Object> nonSubscriberEvents = Lists.newArrayList();
       final List<Object> subscriberEvents = Lists.newArrayList();
@@ -83,7 +84,7 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testSubscriber() {
-      assertThat(getSubscriber().subscriberEvents).has().item(EVENT);
+      assertThat(getSubscriber().subscriberEvents).contains(EVENT);
     }
 
     @Override
@@ -92,8 +93,8 @@ public class AnnotatedSubscriberFinderTests {
     }
   }
 
-  public static class AnnotatedAndAbstractInSuperclassTest extends
-      AbstractEventBusTest<AnnotatedAndAbstractInSuperclassTest.SubClass> {
+  public static class AnnotatedAndAbstractInSuperclassTest
+      extends AbstractEventBusTest<AnnotatedAndAbstractInSuperclassTest.SubClass> {
     abstract static class SuperClass {
       @Subscribe
       public abstract void overriddenAndAnnotatedInSubclass(Object o);
@@ -119,11 +120,11 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testOverriddenAndAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
     }
 
     public void testOverriddenNotAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenInSubclassEvents).contains(EVENT);
     }
 
     @Override
@@ -132,8 +133,8 @@ public class AnnotatedSubscriberFinderTests {
     }
   }
 
-  public static class AnnotatedNotAbstractInSuperclassTest extends
-      AbstractEventBusTest<AnnotatedNotAbstractInSuperclassTest.SubClass> {
+  public static class AnnotatedNotAbstractInSuperclassTest
+      extends AbstractEventBusTest<AnnotatedNotAbstractInSuperclassTest.SubClass> {
     static class SuperClass {
       final List<Object> notOverriddenInSubclassEvents = Lists.newArrayList();
       final List<Object> overriddenNotAnnotatedInSubclassEvents = Lists.newArrayList();
@@ -199,26 +200,26 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testNotOverriddenInSubclass() {
-      assertThat(getSubscriber().notOverriddenInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().notOverriddenInSubclassEvents).contains(EVENT);
     }
 
     public void testOverriddenNotAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenNotAnnotatedInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenNotAnnotatedInSubclassEvents).contains(EVENT);
     }
 
     public void testDifferentlyOverriddenNotAnnotatedInSubclass() {
       assertThat(getSubscriber().differentlyOverriddenNotAnnotatedInSubclassGoodEvents)
-          .has().item(EVENT);
+          .contains(EVENT);
       assertThat(getSubscriber().differentlyOverriddenNotAnnotatedInSubclassBadEvents).isEmpty();
     }
 
     public void testOverriddenAndAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
     }
 
     public void testDifferentlyOverriddenAndAnnotatedInSubclass() {
       assertThat(getSubscriber().differentlyOverriddenAnnotatedInSubclassGoodEvents)
-          .has().item(EVENT);
+          .contains(EVENT);
       assertThat(getSubscriber().differentlyOverriddenAnnotatedInSubclassBadEvents).isEmpty();
     }
 
@@ -228,8 +229,8 @@ public class AnnotatedSubscriberFinderTests {
     }
   }
 
-  public static class AbstractNotAnnotatedInSuperclassTest extends
-      AbstractEventBusTest<AbstractNotAnnotatedInSuperclassTest.SubClass> {
+  public static class AbstractNotAnnotatedInSuperclassTest
+      extends AbstractEventBusTest<AbstractNotAnnotatedInSuperclassTest.SubClass> {
     abstract static class SuperClass {
       public abstract void overriddenInSubclassNowhereAnnotated(Object o);
 
@@ -253,7 +254,7 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testOverriddenAndAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
     }
 
     public void testOverriddenInSubclassNowhereAnnotated() {
@@ -266,8 +267,8 @@ public class AnnotatedSubscriberFinderTests {
     }
   }
 
-  public static class NeitherAbstractNorAnnotatedInSuperclassTest extends
-      AbstractEventBusTest<NeitherAbstractNorAnnotatedInSuperclassTest.SubClass> {
+  public static class NeitherAbstractNorAnnotatedInSuperclassTest
+      extends AbstractEventBusTest<NeitherAbstractNorAnnotatedInSuperclassTest.SubClass> {
     static class SuperClass {
       final List<Object> neitherOverriddenNorAnnotatedEvents = Lists.newArrayList();
       final List<Object> overriddenInSubclassNowhereAnnotatedEvents = Lists.newArrayList();
@@ -308,7 +309,7 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testOverriddenAndAnnotatedInSubclass() {
-      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+      assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
     }
 
     @Override
@@ -317,8 +318,8 @@ public class AnnotatedSubscriberFinderTests {
     }
   }
 
-  public static class DeepInterfaceTest extends
-      AbstractEventBusTest<DeepInterfaceTest.SubscriberClass> {
+  public static class DeepInterfaceTest
+      extends AbstractEventBusTest<DeepInterfaceTest.SubscriberClass> {
     interface Interface1 {
       @Subscribe
       void annotatedIn1(Object o);
@@ -410,31 +411,31 @@ public class AnnotatedSubscriberFinderTests {
     }
 
     public void testAnnotatedIn1() {
-      assertThat(getSubscriber().annotatedIn1Events).has().item(EVENT);
+      assertThat(getSubscriber().annotatedIn1Events).contains(EVENT);
     }
 
     public void testAnnotatedIn2() {
-      assertThat(getSubscriber().annotatedIn2Events).has().item(EVENT);
+      assertThat(getSubscriber().annotatedIn2Events).contains(EVENT);
     }
 
     public void testAnnotatedIn1And2() {
-      assertThat(getSubscriber().annotatedIn1And2Events).has().item(EVENT);
+      assertThat(getSubscriber().annotatedIn1And2Events).contains(EVENT);
     }
 
     public void testAnnotatedIn1And2AndClass() {
-      assertThat(getSubscriber().annotatedIn1And2AndClassEvents).has().item(EVENT);
+      assertThat(getSubscriber().annotatedIn1And2AndClassEvents).contains(EVENT);
     }
 
     public void testDeclaredIn1AnnotatedIn2() {
-      assertThat(getSubscriber().declaredIn1AnnotatedIn2Events).has().item(EVENT);
+      assertThat(getSubscriber().declaredIn1AnnotatedIn2Events).contains(EVENT);
     }
 
     public void testDeclaredIn1AnnotatedInClass() {
-      assertThat(getSubscriber().declaredIn1AnnotatedInClassEvents).has().item(EVENT);
+      assertThat(getSubscriber().declaredIn1AnnotatedInClassEvents).contains(EVENT);
     }
 
     public void testDeclaredIn2AnnotatedInClass() {
-      assertThat(getSubscriber().declaredIn2AnnotatedInClassEvents).has().item(EVENT);
+      assertThat(getSubscriber().declaredIn2AnnotatedInClassEvents).contains(EVENT);
     }
 
     public void testNowhereAnnotated() {
diff --git a/guava-tests/test/com/google/common/hash/BloomFilterTest.java b/guava-tests/test/com/google/common/hash/BloomFilterTest.java
index 4f54d10..594bcf8 100644
--- a/guava-tests/test/com/google/common/hash/BloomFilterTest.java
+++ b/guava-tests/test/com/google/common/hash/BloomFilterTest.java
@@ -18,6 +18,7 @@ package com.google.common.hash;
 
 import static com.google.common.base.Charsets.UTF_8;
 import static com.google.common.hash.BloomFilterStrategies.BitArray;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.math.LongMath;
@@ -41,6 +42,7 @@ import javax.annotation.Nullable;
  * @author Dimitris Andreou
  */
 public class BloomFilterTest extends TestCase {
+  @SuppressUnderAndroid // OutOfMemoryError
   public void testLargeBloomFilterDoesntOverflow() {
     long numBits = Integer.MAX_VALUE;
     numBits++;
@@ -188,6 +190,7 @@ public class BloomFilterTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testPreconditions() {
     try {
       BloomFilter.create(Funnels.unencodedCharsFunnel(), -1);
@@ -207,6 +210,7 @@ public class BloomFilterTest extends TestCase {
     } catch (IllegalArgumentException expected) {}
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFailureWhenMoreThan255HashFunctionsAreNeeded() {
     try {
       int n = 1000;
@@ -241,6 +245,7 @@ public class BloomFilterTest extends TestCase {
   /**
    * Tests that we always get a non-negative optimal size.
    */
+  @SuppressWarnings("CheckReturnValue")
   public void testOptimalSize() {
     for (int n = 1; n < 1000; n++) {
       for (double fpp = Double.MIN_VALUE; fpp < 1.0; fpp += 0.001) {
@@ -261,10 +266,18 @@ public class BloomFilterTest extends TestCase {
       BloomFilter.create(HashTestUtils.BAD_FUNNEL, Integer.MAX_VALUE, Double.MIN_VALUE);
       fail("we can't represent such a large BF!");
     } catch (IllegalArgumentException expected) {
-      assertEquals("Could not create BloomFilter of 3327428144502 bits", expected.getMessage());
+      assertThat(expected).hasMessage("Could not create BloomFilter of 3327428144502 bits");
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
+  @SuppressUnderAndroid // OutOfMemoryError
+  public void testLargeNumberOfInsertions() {
+    // We use horrible FPPs here to keep Java from OOM'ing
+    BloomFilter.create(Funnels.unencodedCharsFunnel(), 42L + Integer.MAX_VALUE, 0.28);
+    BloomFilter.create(Funnels.unencodedCharsFunnel(), 50L * Integer.MAX_VALUE, 0.99);
+  }
+
   private void checkSanity(BloomFilter<Object> bf) {
     assertFalse(bf.mightContain(new Object()));
     assertFalse(bf.apply(new Object()));
@@ -463,7 +476,7 @@ public class BloomFilterTest extends TestCase {
    * Only appending a new constant is allowed.
    */
   public void testBloomFilterStrategies() {
-    assertEquals(2, BloomFilterStrategies.values().length);
+    assertThat(BloomFilterStrategies.values()).hasLength(2);
     assertEquals(BloomFilterStrategies.MURMUR128_MITZ_32, BloomFilterStrategies.values()[0]);
     assertEquals(BloomFilterStrategies.MURMUR128_MITZ_64, BloomFilterStrategies.values()[1]);
   }
diff --git a/guava-tests/test/com/google/common/hash/HashCodeTest.java b/guava-tests/test/com/google/common/hash/HashCodeTest.java
index a15a57b..ae1fed8 100644
--- a/guava-tests/test/com/google/common/hash/HashCodeTest.java
+++ b/guava-tests/test/com/google/common/hash/HashCodeTest.java
@@ -219,6 +219,7 @@ public class HashCodeTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFromStringFailsWithInvalidHexChar() {
     try {
       HashCode.fromString("7f8005ff0z");
@@ -227,6 +228,7 @@ public class HashCodeTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFromStringFailsWithUpperCaseString() {
     String string = Hashing.sha1().hashString("foo", Charsets.US_ASCII).toString().toUpperCase();
     try {
@@ -236,6 +238,7 @@ public class HashCodeTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFromStringFailsWithShortInputs() {
     try {
       HashCode.fromString("");
@@ -250,6 +253,7 @@ public class HashCodeTest extends TestCase {
     HashCode.fromString("7f");
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testFromStringFailsWithOddLengthInput() {
     try {
       HashCode.fromString("7f8");
@@ -343,6 +347,7 @@ public class HashCodeTest extends TestCase {
         .forAllPublicStaticMethods(HashCode.class);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertExpectedHashCode(ExpectedHashCode expectedHashCode, HashCode hash) {
     assertTrue(Arrays.equals(expectedHashCode.bytes, hash.asBytes()));
     byte[] bb = new byte[hash.bits() / 8];
diff --git a/guava-tests/test/com/google/common/hash/HashFunctionEnum.java b/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
index 7a2d390..6927094 100644
--- a/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
+++ b/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
@@ -33,6 +33,7 @@ enum HashFunctionEnum {
   MURMUR3_32(Hashing.murmur3_32()),
   SHA1(Hashing.sha1()),
   SHA256(Hashing.sha256()),
+  SHA384(Hashing.sha384()),
   SHA512(Hashing.sha512()),
   SIP_HASH24(Hashing.sipHash24()),
 
diff --git a/guava-tests/test/com/google/common/hash/HashingTest.java b/guava-tests/test/com/google/common/hash/HashingTest.java
index 74b43c9..09d427c 100644
--- a/guava-tests/test/com/google/common/hash/HashingTest.java
+++ b/guava-tests/test/com/google/common/hash/HashingTest.java
@@ -16,10 +16,9 @@
 
 package com.google.common.hash;
 
-import static com.google.common.hash.Hashing.ConcatenatedHashFunction;
-import static com.google.common.hash.Hashing.goodFastHash;
+import static com.google.common.base.Charsets.UTF_8;
+import static java.util.Arrays.asList;
 
-import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableTable;
 import com.google.common.collect.Lists;
@@ -36,6 +35,7 @@ import java.lang.reflect.Modifier;
 import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Random;
 
 /**
@@ -69,6 +69,14 @@ public class HashingTest extends TestCase {
     assertEquals("Hashing.sha256()", Hashing.sha256().toString());
   }
 
+  public void testSha384() {
+    HashTestUtils.checkAvalanche(Hashing.sha384(), 100, 0.4);
+    HashTestUtils.checkNo2BitCharacteristics(Hashing.sha384());
+    HashTestUtils.checkNoFunnels(Hashing.sha384());
+    HashTestUtils.assertInvariants(Hashing.sha384());
+    assertEquals("Hashing.sha384()", Hashing.sha384().toString());
+  }
+
   public void testSha512() {
     HashTestUtils.checkAvalanche(Hashing.sha512(), 100, 0.4);
     HashTestUtils.checkNo2BitCharacteristics(Hashing.sha512());
@@ -198,6 +206,7 @@ public class HashingTest extends TestCase {
   private static final int ITERS = 10000;
   private static final int MAX_SHARDS = 500;
 
+  @SuppressWarnings("CheckReturnValue")
   public void testConsistentHash_outOfRange() {
     try {
       Hashing.consistentHash(5L, 0);
@@ -238,6 +247,7 @@ public class HashingTest extends TestCase {
   private static final double MAX_PERCENT_SPREAD = 0.5;
   private static final long RANDOM_SEED = 177L;
 
+  @SuppressWarnings("CheckReturnValue")
   public void testCombineOrdered_empty() {
     try {
       Hashing.combineOrdered(Collections.<HashCode>emptySet());
@@ -246,6 +256,7 @@ public class HashingTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testCombineOrdered_differentBitLengths() {
     try {
       Hashing.combineOrdered(ImmutableList.of(HashCode.fromInt(32), HashCode.fromLong(32L)));
@@ -280,6 +291,7 @@ public class HashingTest extends TestCase {
     assertFalse(hashCode1.equals(hashCode2));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testCombineUnordered_empty() {
     try {
       Hashing.combineUnordered(Collections.<HashCode>emptySet());
@@ -288,6 +300,7 @@ public class HashingTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testCombineUnordered_differentBitLengths() {
     try {
       Hashing.combineUnordered(ImmutableList.of(HashCode.fromInt(32), HashCode.fromLong(32L)));
@@ -321,35 +334,61 @@ public class HashingTest extends TestCase {
     assertEquals(hashCode1, hashCode2);
   }
 
-  public void testConcatenatedHashFunction_equals() {
+  // This isn't specified by contract, but it'll still be nice to know if this behavior changes.
+  public void testConcatenating_equals() {
+    new EqualsTester()
+        .addEqualityGroup(Hashing.concatenating(asList(Hashing.md5())))
+        .addEqualityGroup(Hashing.concatenating(asList(Hashing.murmur3_32())))
+        .addEqualityGroup(
+            Hashing.concatenating(Hashing.md5(), Hashing.md5()),
+            Hashing.concatenating(asList(Hashing.md5(), Hashing.md5())))
+        .addEqualityGroup(
+            Hashing.concatenating(Hashing.murmur3_32(), Hashing.md5()),
+            Hashing.concatenating(asList(Hashing.murmur3_32(), Hashing.md5())))
+        .addEqualityGroup(
+            Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()),
+            Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())))
+        .testEquals();
+  }
+
+  public void testConcatenatingIterable_bits() {
+    assertEquals(
+        Hashing.md5().bits() + Hashing.md5().bits(),
+        Hashing.concatenating(asList(Hashing.md5(), Hashing.md5())).bits());
     assertEquals(
-        new ConcatenatedHashFunction(Hashing.md5()),
-        new ConcatenatedHashFunction(Hashing.md5()));
+        Hashing.md5().bits() + Hashing.murmur3_32().bits(),
+        Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())).bits());
     assertEquals(
-        new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()),
-        new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()));
+        Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
+        Hashing.concatenating(
+            asList(Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128())).bits());
   }
 
-  public void testConcatenatedHashFunction_bits() {
-    assertEquals(Hashing.md5().bits(),
-        new ConcatenatedHashFunction(Hashing.md5()).bits());
-    assertEquals(Hashing.md5().bits() + Hashing.murmur3_32().bits(),
-        new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()).bits());
-    assertEquals(Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
-        new ConcatenatedHashFunction(
-            Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128()).bits());
+  public void testConcatenatingVarArgs_bits() {
+    assertEquals(
+        Hashing.md5().bits() + Hashing.md5().bits(),
+        Hashing.concatenating(Hashing.md5(), Hashing.md5()).bits());
+    assertEquals(
+        Hashing.md5().bits() + Hashing.murmur3_32().bits(),
+        Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()).bits());
+    assertEquals(
+        Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
+        Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128()).bits());
   }
 
-  public void testConcatenatedHashFunction_makeHash() {
+  public void testConcatenatingHashFunction_makeHash() {
     byte[] md5Hash = Hashing.md5().hashLong(42L).asBytes();
     byte[] murmur3Hash = Hashing.murmur3_32().hashLong(42L).asBytes();
     byte[] combined = new byte[md5Hash.length + murmur3Hash.length];
     ByteBuffer buffer = ByteBuffer.wrap(combined);
     buffer.put(md5Hash);
     buffer.put(murmur3Hash);
+    HashCode expected = HashCode.fromBytes(combined);
 
-    assertEquals(HashCode.fromBytes(combined),
-        new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()).hashLong(42L));
+    assertEquals(expected,
+        Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()).hashLong(42L));
+    assertEquals(expected,
+        Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())).hashLong(42L));
   }
 
   public void testHashIntReverseBytesVsHashBytesIntsToByteArray() {
@@ -399,15 +438,24 @@ public class HashingTest extends TestCase {
                "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592")
           .put(Hashing.sha256(), TQBFJOTLDP,
                "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")
+          .put(Hashing.sha384(), EMPTY_STRING,
+               "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da2"
+               + "74edebfe76f65fbd51ad2f14898b95b")
+          .put(Hashing.sha384(), TQBFJOTLD,
+               "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509"
+               + "cb1e5dc1e85a941bbee3d7f2afbc9b1")
+          .put(Hashing.sha384(), TQBFJOTLDP,
+               "ed892481d8272ca6df370bf706e4d7bc1b5739fa2177aae6c50e946678718fc67"
+               + "a7af2819a021c2fc34e91bdb63409d7")
           .put(Hashing.sha512(), EMPTY_STRING,
-               "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" +
-               "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
+               "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"
+               + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
           .put(Hashing.sha512(), TQBFJOTLD,
-               "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64" +
-               "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6")
+               "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64"
+               + "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6")
           .put(Hashing.sha512(), TQBFJOTLDP,
-               "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb" +
-               "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed")
+               "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb"
+               + "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed")
           .put(Hashing.crc32(), EMPTY_STRING, "00000000")
           .put(Hashing.crc32(), TQBFJOTLD, "39a34f41")
           .put(Hashing.crc32(), TQBFJOTLDP, "e9259051")
@@ -437,14 +485,15 @@ public class HashingTest extends TestCase {
       String input = cell.getColumnKey();
       String expected = cell.getValue();
       assertEquals(
-          String.format("Known hash for hash(%s, UTF_8) failed", input),
+          String.format(Locale.ROOT, "Known hash for hash(%s, UTF_8) failed", input),
           expected,
-          func.hashString(input, Charsets.UTF_8).toString());
+          func.hashString(input, UTF_8).toString());
     }
   }
 
   public void testNullPointers() {
     NullPointerTester tester = new NullPointerTester()
+        .setDefault(byte[].class, "secret key".getBytes(UTF_8))
         .setDefault(HashCode.class, HashCode.fromLong(0));
     tester.testAllPublicStaticMethods(Hashing.class);
   }
@@ -465,14 +514,14 @@ public class HashingTest extends TestCase {
    * testSeededHashFunctionEquals}.
    */
   public void testGoodFastHashEquals() throws Exception {
-    HashFunction hashFunction1a = goodFastHash(1);
-    HashFunction hashFunction1b = goodFastHash(32);
-    HashFunction hashFunction2a = goodFastHash(33);
-    HashFunction hashFunction2b = goodFastHash(128);
-    HashFunction hashFunction3a = goodFastHash(129);
-    HashFunction hashFunction3b = goodFastHash(256);
-    HashFunction hashFunction4a = goodFastHash(257);
-    HashFunction hashFunction4b = goodFastHash(384);
+    HashFunction hashFunction1a = Hashing.goodFastHash(1);
+    HashFunction hashFunction1b = Hashing.goodFastHash(32);
+    HashFunction hashFunction2a = Hashing.goodFastHash(33);
+    HashFunction hashFunction2b = Hashing.goodFastHash(128);
+    HashFunction hashFunction3a = Hashing.goodFastHash(129);
+    HashFunction hashFunction3b = Hashing.goodFastHash(256);
+    HashFunction hashFunction4a = Hashing.goodFastHash(257);
+    HashFunction hashFunction4b = Hashing.goodFastHash(384);
 
     new EqualsTester()
         .addEqualityGroup(hashFunction1a, hashFunction1b)
@@ -513,7 +562,9 @@ public class HashingTest extends TestCase {
       if (method.getReturnType().equals(HashFunction.class) // must return HashFunction
           && Modifier.isPublic(method.getModifiers()) // only the public methods
           && method.getParameterTypes().length != 0 // only the seeded hash functions
-          && !method.getName().equals("goodFastHash")) { // tested in testGoodFastHashEquals
+          && !method.getName().equals("concatenating") // don't test Hashing.concatenating()
+          && !method.getName().equals("goodFastHash") // tested in testGoodFastHashEquals
+          && !method.getName().startsWith("hmac")) { // skip hmac functions
         Object[] params1 = new Object[method.getParameterTypes().length];
         Object[] params2 = new Object[method.getParameterTypes().length];
         for (int i = 0; i < params1.length; i++) {
diff --git a/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java b/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
index 4ff932a..c86c5b1 100644
--- a/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
+++ b/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
@@ -47,6 +47,7 @@ public class MessageDigestHashFunctionTest extends TestCase {
           .put("sHa-1", Hashing.sha1()) // Not the official name, but still works
           .put("SHA-1", Hashing.sha1())
           .put("SHA-256", Hashing.sha256())
+          .put("SHA-384", Hashing.sha384())
           .put("SHA-512", Hashing.sha512())
           .build();
 
@@ -72,6 +73,7 @@ public class MessageDigestHashFunctionTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testHashTwice() {
     Hasher sha1 = Hashing.sha1().newHasher();
 
diff --git a/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java
new file mode 100644
index 0000000..ae3ac8c
--- /dev/null
+++ b/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.hash;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/io/BaseEncodingTest.java b/guava-tests/test/com/google/common/io/BaseEncodingTest.java
index 9580185..44db12e 100644
--- a/guava-tests/test/com/google/common/io/BaseEncodingTest.java
+++ b/guava-tests/test/com/google/common/io/BaseEncodingTest.java
@@ -18,6 +18,7 @@ import static com.google.common.io.BaseEncoding.base16;
 import static com.google.common.io.BaseEncoding.base32;
 import static com.google.common.io.BaseEncoding.base32Hex;
 import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
@@ -36,6 +37,8 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 
+import javax.annotation.Nullable;
+
 /**
  * Tests for {@code BaseEncoding}.
  *
@@ -111,12 +114,16 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase64InvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base64(), "\u007f");
-    assertFailsToDecode(base64(), "Wf2!");
+    assertFailsToDecode(base64(), "A\u007f", "Unrecognized character: 0x7f");
+    assertFailsToDecode(base64(), "Wf2!", "Unrecognized character: !");
     // This sentence just isn't base64() encoded.
     assertFailsToDecode(base64(), "let's not talk of love or chains!");
     // A 4n+1 length string is never legal base64().
-    assertFailsToDecode(base64(), "12345");
+    assertFailsToDecode(base64(), "12345", "Invalid input length 5");
+    // These have a combination of invalid length, unrecognized characters and wrong padding.
+    assertFailsToDecode(base64(), "AB=C", "Unrecognized character: =");
+    assertFailsToDecode(base64(), "A=BCD", "Invalid input length 5");
+    assertFailsToDecode(base64(), "?", "Invalid input length 1");
   }
 
   @SuppressWarnings("ReturnValueIgnored")
@@ -185,6 +192,14 @@ public class BaseEncodingTest extends TestCase {
     testStreamingEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
   }
 
+  public void testBase64Offset() {
+    testEncodesWithOffset(base64(), "foobar", 0, 6, "Zm9vYmFy");
+    testEncodesWithOffset(base64(), "foobar", 1, 5, "b29iYXI=");
+    testEncodesWithOffset(base64(), "foobar", 2, 3, "b2Jh");
+    testEncodesWithOffset(base64(), "foobar", 3, 1, "Yg==");
+    testEncodesWithOffset(base64(), "foobar", 4, 0, "");
+  }
+
   public void testBase32() {
     // The following test vectors are specified in RFC 4648 itself
     testEncodingWithCasing(base32(), "", "");
@@ -230,20 +245,32 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase32InvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base32(), "\u007f");
-    assertFailsToDecode(base32(), "Wf2!");
+    assertFailsToDecode(base32(), "A ", "Unrecognized character: 0x20");
+    assertFailsToDecode(base32(), "Wf2!", "Unrecognized character: f");
     // This sentence just isn't base32() encoded.
     assertFailsToDecode(base32(), "let's not talk of love or chains!");
     // An 8n+{1,3,6} length string is never legal base32.
-    assertFailsToDecode(base32(), "A");
+    assertFailsToDecode(base32(), "A", "Invalid input length 1");
     assertFailsToDecode(base32(), "ABC");
     assertFailsToDecode(base32(), "ABCDEF");
+    // These have a combination of invalid length, unrecognized characters and wrong padding.
+    assertFailsToDecode(base32(), "AB=C", "Unrecognized character: =");
+    assertFailsToDecode(base32(), "A=BCDE", "Invalid input length 6");
+    assertFailsToDecode(base32(), "?", "Invalid input length 1");
   }
 
   public void testBase32UpperCaseIsNoOp() {
     assertSame(base32(), base32().upperCase());
   }
 
+  public void testBase32Offset() {
+    testEncodesWithOffset(base32(), "foobar", 0, 6, "MZXW6YTBOI======");
+    testEncodesWithOffset(base32(), "foobar", 1, 5, "N5XWEYLS");
+    testEncodesWithOffset(base32(), "foobar", 2, 3, "N5RGC===");
+    testEncodesWithOffset(base32(), "foobar", 3, 1, "MI======");
+    testEncodesWithOffset(base32(), "foobar", 4, 0, "");
+  }
+
   public void testBase32Hex() {
     // The following test vectors are specified in RFC 4648 itself
     testEncodingWithCasing(base32Hex(), "", "");
@@ -278,8 +305,8 @@ public class BaseEncodingTest extends TestCase {
 
   public void testBase32HexInvalidDecodings() {
     // These contain bytes not in the decodabet.
-    assertFailsToDecode(base32Hex(), "\u007f");
-    assertFailsToDecode(base32Hex(), "Wf2!");
+    assertFailsToDecode(base32Hex(), "A\u007f", "Unrecognized character: 0x7f");
+    assertFailsToDecode(base32Hex(), "Wf2!", "Unrecognized character: W");
     // This sentence just isn't base32 encoded.
     assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
     // An 8n+{1,3,6} length string is never legal base32.
@@ -306,6 +333,25 @@ public class BaseEncodingTest extends TestCase {
     assertSame(base16(), base16().upperCase());
   }
 
+  public void testBase16InvalidDecodings() {
+    // These contain bytes not in the decodabet.
+    assertFailsToDecode(base16(), "\n\n", "Unrecognized character: 0xa");
+    assertFailsToDecode(base16(), "EFGH", "Unrecognized character: G");
+    // Valid base16 strings always have an even length.
+    assertFailsToDecode(base16(), "A", "Invalid input length 1");
+    assertFailsToDecode(base16(), "ABC");
+    // These have a combination of invalid length and unrecognized characters.
+    assertFailsToDecode(base16(), "?", "Invalid input length 1");
+  }
+
+  public void testBase16Offset() {
+    testEncodesWithOffset(base16(), "foobar", 0, 6, "666F6F626172");
+    testEncodesWithOffset(base16(), "foobar", 1, 5, "6F6F626172");
+    testEncodesWithOffset(base16(), "foobar", 2, 3, "6F6261");
+    testEncodesWithOffset(base16(), "foobar", 3, 1, "62");
+    testEncodesWithOffset(base16(), "foobar", 4, 0, "");
+  }
+
   private static void testEncodingWithCasing(
       BaseEncoding encoding, String decoded, String encoded) {
     testEncodingWithSeparators(encoding, decoded, encoded);
@@ -332,39 +378,39 @@ public class BaseEncodingTest extends TestCase {
   }
 
   private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
-    assertEquals(encoded, encoding.encode(bytes));
+    assertEquals(encoded, encoding.encode(getBytes(decoded)));
+  }
+
+  private static void testEncodesWithOffset(
+      BaseEncoding encoding, String decoded, int offset, int len, String encoded) {
+    assertEquals(encoded, encoding.encode(getBytes(decoded), offset, len));
   }
 
   private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
-    assertEquals(bytes, encoding.decode(encoded));
+    assertEquals(getBytes(decoded), encoding.decode(encoded));
   }
 
   private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
+    assertFailsToDecode(encoding, cannotDecode, null);
+  }
+
+  private static void assertFailsToDecode(
+      BaseEncoding encoding, String cannotDecode, @Nullable String expectedMessage) {
     try {
       encoding.decode(cannotDecode);
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
-      // success
+      if (expectedMessage != null) {
+        assertThat(expected.getCause()).hasMessage(expectedMessage);
+      }
     }
     try {
       encoding.decodeChecked(cannotDecode);
       fail("Expected DecodingException");
     } catch (DecodingException expected) {
-      // success
+      if (expectedMessage != null) {
+        assertThat(expected).hasMessage(expectedMessage);
+      }
     }
   }
 
@@ -400,16 +446,9 @@ public class BaseEncodingTest extends TestCase {
   @GwtIncompatible("Writer")
   private static void testStreamingEncodes(BaseEncoding encoding, String decoded, String encoded)
       throws IOException {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
     StringWriter writer = new StringWriter();
     OutputStream encodingStream = encoding.encodingStream(writer);
-    encodingStream.write(bytes);
+    encodingStream.write(getBytes(decoded));
     encodingStream.close();
     assertEquals(encoded, writer.toString());
   }
@@ -417,13 +456,7 @@ public class BaseEncodingTest extends TestCase {
   @GwtIncompatible("Reader")
   private static void testStreamingDecodes(BaseEncoding encoding, String encoded, String decoded)
       throws IOException {
-    byte[] bytes;
-    try {
-      // GWT does not support String.getBytes(Charset)
-      bytes = decoded.getBytes("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new AssertionError();
-    }
+    byte[] bytes = getBytes(decoded);
     InputStream decodingStream = encoding.decodingStream(new StringReader(encoded));
     for (int i = 0; i < bytes.length; i++) {
       assertEquals(bytes[i] & 0xFF, decodingStream.read());
@@ -432,6 +465,15 @@ public class BaseEncodingTest extends TestCase {
     decodingStream.close();
   }
 
+  private static byte[] getBytes(String decoded) {
+    try {
+      // GWT does not support String.getBytes(Charset)
+      return decoded.getBytes("UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new AssertionError();
+    }
+  }
+
   public void testToString() {
     assertEquals("BaseEncoding.base64().withPadChar(=)", BaseEncoding.base64().toString());
     assertEquals("BaseEncoding.base32Hex().omitPadding()",
diff --git a/guava-tests/test/com/google/common/io/ByteSinkTester.java b/guava-tests/test/com/google/common/io/ByteSinkTester.java
index a743be5..47b64bc 100644
--- a/guava-tests/test/com/google/common/io/ByteSinkTester.java
+++ b/guava-tests/test/com/google/common/io/ByteSinkTester.java
@@ -38,6 +38,7 @@ import java.util.Map;
  *
  * @author Colin Decker
  */
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
 public class ByteSinkTester extends SourceSinkTester<ByteSink, byte[], ByteSinkFactory> {
 
   private static final ImmutableList<Method> testMethods
diff --git a/guava-tests/test/com/google/common/io/ByteSourceTest.java b/guava-tests/test/com/google/common/io/ByteSourceTest.java
index 24aaeed..2f12ced 100644
--- a/guava-tests/test/com/google/common/io/ByteSourceTest.java
+++ b/guava-tests/test/com/google/common/io/ByteSourceTest.java
@@ -30,15 +30,16 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.hash.Hashing;
+import com.google.common.primitives.UnsignedBytes;
 import com.google.common.testing.TestLogHandler;
 
 import junit.framework.TestSuite;
 
 import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.EnumSet;
 
 /**
@@ -48,6 +49,7 @@ import java.util.EnumSet;
  */
 public class ByteSourceTest extends IoTestCase {
 
+  @SuppressUnderAndroid // Android doesn't understand suites whose tests lack default constructors.
   public static TestSuite suite() {
     TestSuite suite = new TestSuite();
     suite.addTest(ByteSourceTester.tests("ByteSource.wrap[byte[]]",
@@ -209,11 +211,78 @@ public class ByteSourceTest extends IoTestCase {
     assertCorrectSlice(100, 5, 100, 95);
     assertCorrectSlice(100, 100, 0, 0);
     assertCorrectSlice(100, 100, 10, 0);
+    assertCorrectSlice(100, 101, 10, 0);
+  }
 
-    try {
-      assertCorrectSlice(100, 101, 10, 0);
-      fail();
-    } catch (EOFException expected) {
+  /**
+   * Tests that the default slice() behavior is correct when the source is sliced starting at an
+   * offset that is greater than the current length of the source, a stream is then opened to that
+   * source, and finally additional bytes are appended to the source before the stream is read.
+   *
+   * <p>Without special handling, it's possible to have reads of the open stream start <i>before</i>
+   * the offset at which the slice is supposed to start.
+   */
+  // TODO(cgdecker): Maybe add a test for this to ByteSourceTester
+  public void testSlice_appendingAfterSlicing() throws IOException {
+    // Source of length 5
+    AppendableByteSource source = new AppendableByteSource(newPreFilledByteArray(5));
+
+    // Slice it starting at offset 10.
+    ByteSource slice = source.slice(10, 5);
+
+    // Open a stream to the slice.
+    InputStream in = slice.openStream();
+
+    // Append 10 more bytes to the source.
+    source.append(newPreFilledByteArray(5, 10));
+
+    // The stream reports no bytes... importantly, it doesn't read the byte at index 5 when it
+    // should be reading the byte at index 10.
+    // We could use a custom InputStream instead to make the read start at index 10, but since this
+    // is a racy situation anyway, this behavior seems reasonable.
+    assertEquals(-1, in.read());
+  }
+
+  private static class AppendableByteSource extends ByteSource {
+    private byte[] bytes;
+
+    public AppendableByteSource(byte[] initialBytes) {
+      this.bytes = initialBytes.clone();
+    }
+
+    @Override
+    public InputStream openStream() {
+      return new In();
+    }
+
+    public void append(byte[] b) {
+      byte[] newBytes = Arrays.copyOf(bytes, bytes.length + b.length);
+      System.arraycopy(b, 0, newBytes, bytes.length, b.length);
+      bytes = newBytes;
+    }
+
+    private class In extends InputStream {
+      private int pos;
+
+      @Override
+      public int read() throws IOException {
+        byte[] b = new byte[1];
+        return read(b) == -1
+            ? -1
+            : UnsignedBytes.toInt(b[0]);
+      }
+
+      @Override
+      public int read(byte[] b, int off, int len) {
+        if (pos >= bytes.length) {
+          return -1;
+        }
+
+        int lenToRead = Math.min(len, bytes.length - pos);
+        System.arraycopy(bytes, pos, b, off, lenToRead);
+        pos += lenToRead;
+        return lenToRead;
+      }
     }
   }
 
diff --git a/guava-tests/test/com/google/common/io/ByteSourceTester.java b/guava-tests/test/com/google/common/io/ByteSourceTester.java
index f9a735e..6b4833a 100644
--- a/guava-tests/test/com/google/common/io/ByteSourceTester.java
+++ b/guava-tests/test/com/google/common/io/ByteSourceTester.java
@@ -21,6 +21,7 @@ import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
 import static org.junit.Assert.assertArrayEquals;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.hash.HashCode;
 import com.google.common.hash.Hashing;
@@ -44,6 +45,7 @@ import java.util.Random;
  *
  * @author Colin Decker
  */
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
 public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteSourceFactory> {
 
   private static final ImmutableList<Method> testMethods
@@ -85,8 +87,22 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
       // if expected.length == 0, off has to be 0 but length doesn't matter--result will be empty
       int off = expected.length == 0 ? 0 : random.nextInt(expected.length);
       int len = expected.length == 0 ? 4 : random.nextInt(expected.length - off);
+
       ByteSourceFactory sliced = SourceSinkFactories.asSlicedByteSourceFactory(factory, off, len);
-      suite.addTest(suiteForBytes(sliced, bytes, name + ".slice[int, int]",
+      suite.addTest(suiteForBytes(sliced, bytes, name + ".slice[long, long]",
+          desc, false));
+
+      // test a slice() of the ByteSource starting at a random offset with a length of
+      // Long.MAX_VALUE
+      ByteSourceFactory slicedLongMaxValue = SourceSinkFactories.asSlicedByteSourceFactory(
+          factory, off, Long.MAX_VALUE);
+      suite.addTest(suiteForBytes(slicedLongMaxValue, bytes, name + ".slice[long, Long.MAX_VALUE]",
+          desc, false));
+
+      // test a slice() of the ByteSource starting at an offset greater than its size
+      ByteSourceFactory slicedOffsetPastEnd = SourceSinkFactories.asSlicedByteSourceFactory(
+          factory, expected.length + 2, expected.length + 10);
+      suite.addTest(suiteForBytes(slicedOffsetPastEnd, bytes, name + ".slice[size + 2, long]",
           desc, false));
     }
 
@@ -156,6 +172,13 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
     assertEquals(expected.length, source.size());
   }
 
+  public void testSizeIfKnown() throws IOException {
+    Optional<Long> sizeIfKnown = source.sizeIfKnown();
+    if (sizeIfKnown.isPresent()) {
+      assertEquals(expected.length, (long) sizeIfKnown.get());
+    }
+  }
+
   public void testContentEquals() throws IOException {
     assertTrue(source.contentEquals(new ByteSource() {
       @Override
@@ -204,6 +227,17 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
     }
   }
 
+  // Test that you can not expand the readable data in a previously sliced ByteSource.
+  public void testSlice_constrainedRange() throws IOException {
+    long size = source.read().length;
+    if (size >= 2) {
+      ByteSource sliced = source.slice(1, size - 2);
+      assertEquals(size - 2, sliced.read().length);
+      ByteSource resliced = sliced.slice(0, size - 1);
+      assertTrue(sliced.contentEquals(resliced));
+    }
+  }
+
   private void assertExpectedBytes(byte[] readBytes) {
     assertArrayEquals(expected, readBytes);
   }
diff --git a/guava-tests/test/com/google/common/io/ByteStreamsTest.java b/guava-tests/test/com/google/common/io/ByteStreamsTest.java
index 484b48d..40df0ea 100644
--- a/guava-tests/test/com/google/common/io/ByteStreamsTest.java
+++ b/guava-tests/test/com/google/common/io/ByteStreamsTest.java
@@ -16,15 +16,20 @@
 
 package com.google.common.io;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.base.Charsets;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.RandomAccessFile;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
@@ -48,6 +53,33 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals(expected, out.toByteArray());
   }
 
+  public void testCopyFileChannel() throws IOException {
+    final int chunkSize = 14407; // Random prime, unlikely to match any internal chunk size
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    WritableByteChannel outChannel = Channels.newChannel(out);
+
+    File testFile = createTempFile();
+    FileOutputStream fos = new FileOutputStream(testFile);
+    byte[] dummyData = newPreFilledByteArray(chunkSize);
+    try {
+      for (int i = 0; i < 500; i++) {
+        fos.write(dummyData);
+      }
+    } finally {
+      fos.close();
+    }
+    ReadableByteChannel inChannel = new RandomAccessFile(testFile, "r").getChannel();
+    try {
+      ByteStreams.copy(inChannel, outChannel);
+    } finally {
+      inChannel.close();
+    }
+    byte[] actual = out.toByteArray();
+    for (int i = 0; i < 500 * chunkSize; i += chunkSize) {
+      assertEquals(dummyData, Arrays.copyOfRange(actual, i, i + chunkSize));
+    }
+  }
+
   public void testReadFully() throws IOException {
     byte[] b = new byte[10];
 
@@ -157,7 +189,7 @@ public class ByteStreamsTest extends IoTestCase {
     in.readFully(actual);
     assertEquals(bytes, actual);
   }
-  
+
   public void testNewDataInput_readFullyAndThenSome() {
     ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
     byte[] actual = new byte[bytes.length * 2];
@@ -165,10 +197,10 @@ public class ByteStreamsTest extends IoTestCase {
       in.readFully(actual);
       fail("expected exception");
     } catch (IllegalStateException ex) {
-      assertTrue(ex.getCause() instanceof EOFException);
+      assertThat(ex.getCause()).isInstanceOf(EOFException.class);
     }
   }
-  
+
   public void testNewDataInput_readFullyWithOffset() {
     ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
     byte[] actual = new byte[4];
@@ -178,7 +210,7 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals(bytes[0], actual[2]);
     assertEquals(bytes[1], actual[3]);
   }
-  
+
   public void testNewDataInput_readLine() {
     ByteArrayDataInput in = ByteStreams.newDataInput(
         "This is a line\r\nThis too\rand this\nand also this".getBytes(Charsets.UTF_8));
@@ -194,7 +226,7 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals(Float.intBitsToFloat(0x12345678), in.readFloat(), 0.0);
     assertEquals(Float.intBitsToFloat(0x76543210), in.readFloat(), 0.0);
   }
-  
+
   public void testNewDataInput_readDouble() {
     byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10};
     ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -216,7 +248,7 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals('e', in.readChar());
     assertEquals('d', in.readChar());
   }
-  
+
   public void testNewDataInput_readUnsignedShort() {
     byte[] data = {0, 0, 0, 1, (byte) 0xFF, (byte) 0xFF, 0x12, 0x34};
     ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -225,7 +257,7 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals(65535, in.readUnsignedShort());
     assertEquals(0x1234, in.readUnsignedShort());
   }
-  
+
   public void testNewDataInput_readLong() {
     byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10};
     ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -236,7 +268,7 @@ public class ByteStreamsTest extends IoTestCase {
     ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
     assertTrue(in.readBoolean());
   }
-  
+
   public void testNewDataInput_readByte() {
     ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
     for (int i = 0; i < bytes.length; i++) {
@@ -246,7 +278,7 @@ public class ByteStreamsTest extends IoTestCase {
       in.readByte();
       fail("expected exception");
     } catch (IllegalStateException ex) {
-      assertTrue(ex.getCause() instanceof EOFException);
+      assertThat(ex.getCause()).isInstanceOf(EOFException.class);
     }
   }
 
@@ -259,7 +291,7 @@ public class ByteStreamsTest extends IoTestCase {
       in.readUnsignedByte();
       fail("expected exception");
     } catch (IllegalStateException ex) {
-      assertTrue(ex.getCause() instanceof EOFException);
+      assertThat(ex.getCause()).isInstanceOf(EOFException.class);
     }
   }
 
@@ -344,6 +376,7 @@ public class ByteStreamsTest extends IoTestCase {
     assertEquals(new byte[] {0, 97}, out.toByteArray());
   }
 
+  @SuppressUnderAndroid // TODO(cpovirk): Zero is found at beginning instead of end. Why?
   public void testNewDataOutput_writeChars() {
     ByteArrayDataOutput out = ByteStreams.newDataOutput();
     out.writeChars("r\u00C9sum\u00C9");
@@ -455,7 +488,7 @@ public class ByteStreamsTest extends IoTestCase {
   }
 
   public void testByteProcessorStopEarly() throws IOException {
-    byte[] array = newPreFilledByteArray(6000);
+    byte[] array = newPreFilledByteArray(10000);
     assertEquals((Integer) 42,
         ByteStreams.readBytes(new ByteArrayInputStream(array),
             new ByteProcessor<Integer>() {
@@ -463,7 +496,7 @@ public class ByteStreamsTest extends IoTestCase {
               public boolean processBytes(byte[] buf, int off, int len) {
                 assertEquals(
                     copyOfRange(buf, off, off + len),
-                    newPreFilledByteArray(4096));
+                    newPreFilledByteArray(8192));
                 return false;
               }
 
@@ -554,7 +587,7 @@ public class ByteStreamsTest extends IoTestCase {
     lin.skip(3);
     assertEquals(0, lin.available());
   }
-  
+
   public void testLimit_markNotSet() {
     byte[] big = newPreFilledByteArray(5);
     InputStream bin = new ByteArrayInputStream(big);
@@ -564,10 +597,10 @@ public class ByteStreamsTest extends IoTestCase {
       lin.reset();
       fail();
     } catch (IOException expected) {
-      assertEquals("Mark not set", expected.getMessage());
+      assertThat(expected).hasMessage("Mark not set");
     }
   }
-  
+
   public void testLimit_markNotSupported() {
     InputStream lin = ByteStreams.limit(new UnmarkableInputStream(), 2);
 
@@ -575,7 +608,7 @@ public class ByteStreamsTest extends IoTestCase {
       lin.reset();
       fail();
     } catch (IOException expected) {
-      assertEquals("Mark not supported", expected.getMessage());
+      assertThat(expected).hasMessage("Mark not supported");
     }
   }
 
@@ -599,7 +632,8 @@ public class ByteStreamsTest extends IoTestCase {
     return out;
   }
 
+  // TODO(cpovirk): Inline this.
   private static void assertEquals(byte[] expected, byte[] actual) {
-    assertTrue(Arrays.equals(expected, actual));
+    assertThat(actual).isEqualTo(expected);
   }
 }
diff --git a/guava-tests/test/com/google/common/io/CharSinkTester.java b/guava-tests/test/com/google/common/io/CharSinkTester.java
index 9ad4175..754db61 100644
--- a/guava-tests/test/com/google/common/io/CharSinkTester.java
+++ b/guava-tests/test/com/google/common/io/CharSinkTester.java
@@ -34,6 +34,7 @@ import java.util.Map;
  *
  * @author Colin Decker
  */
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
 public class CharSinkTester extends SourceSinkTester<CharSink, String, CharSinkFactory> {
 
   private static final ImmutableList<Method> testMethods
diff --git a/guava-tests/test/com/google/common/io/CharSourceTest.java b/guava-tests/test/com/google/common/io/CharSourceTest.java
index 4fa5b86..804dcdf 100644
--- a/guava-tests/test/com/google/common/io/CharSourceTest.java
+++ b/guava-tests/test/com/google/common/io/CharSourceTest.java
@@ -44,13 +44,14 @@ import java.util.List;
  */
 public class CharSourceTest extends IoTestCase {
 
+  @SuppressUnderAndroid // Android doesn't understand suites whose tests lack default constructors.
   public static TestSuite suite() {
     TestSuite suite = new TestSuite();
     suite.addTest(CharSourceTester.tests("CharSource.wrap[CharSequence]",
         SourceSinkFactories.stringCharSourceFactory()));
     suite.addTest(CharSourceTester.tests("CharSource.empty[]",
         SourceSinkFactories.emptyCharSourceFactory()));
-    suite.addTestSuite(CharStreamsTest.class);
+    suite.addTestSuite(CharSourceTest.class);
     return suite;
   }
 
@@ -229,7 +230,7 @@ public class CharSourceTest extends IoTestCase {
     String expected = "abcdabcd";
 
     // read the first 8 chars manually, since there's no equivalent to ByteSource.slice
-    // TODO(user): Add CharSource.slice?
+    // TODO(cgdecker): Add CharSource.slice?
     StringBuilder builder = new StringBuilder();
     Reader reader = concatenated.openStream(); // no need to worry about closing
     for (int i = 0; i < 8; i++) {
diff --git a/guava-tests/test/com/google/common/io/CharSourceTester.java b/guava-tests/test/com/google/common/io/CharSourceTester.java
index f2882cd..cf83389 100644
--- a/guava-tests/test/com/google/common/io/CharSourceTester.java
+++ b/guava-tests/test/com/google/common/io/CharSourceTester.java
@@ -18,6 +18,7 @@ package com.google.common.io;
 
 import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -38,6 +39,7 @@ import java.util.Map;
  *
  * @author Colin Decker
  */
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
 public class CharSourceTester extends SourceSinkTester<CharSource, String, CharSourceFactory> {
 
   private static final ImmutableList<Method> testMethods
@@ -142,6 +144,17 @@ public class CharSourceTester extends SourceSinkTester<CharSource, String, CharS
     assertEquals(expected.isEmpty(), source.isEmpty());
   }
 
+  public void testLength() throws IOException {
+    assertEquals(expected.length(), source.length());
+  }
+
+  public void testLengthIfKnown() throws IOException {
+    Optional<Long> lengthIfKnown = source.lengthIfKnown();
+    if (lengthIfKnown.isPresent()) {
+      assertEquals(expected.length(), (long) lengthIfKnown.get());
+    }
+  }
+
   public void testReadLines_withProcessor() throws IOException {
     List<String> list = source.readLines(new LineProcessor<List<String>>() {
       List<String> list = Lists.newArrayList();
diff --git a/guava-tests/test/com/google/common/io/CharStreamsTest.java b/guava-tests/test/com/google/common/io/CharStreamsTest.java
index f47ce8a..3dde28a 100644
--- a/guava-tests/test/com/google/common/io/CharStreamsTest.java
+++ b/guava-tests/test/com/google/common/io/CharStreamsTest.java
@@ -42,23 +42,6 @@ public class CharStreamsTest extends IoTestCase {
     assertEquals(TEXT, CharStreams.toString(new StringReader(TEXT)));
   }
 
-  public void testSkipFully_blockingRead() throws IOException {
-    Reader reader = new NonSkippingReader("abcdef");
-    CharStreams.skipFully(reader, 6);
-    assertEquals(-1, reader.read());
-  }
-
-  private static class NonSkippingReader extends StringReader {
-    NonSkippingReader(String s) {
-      super(s);
-    }
-
-    @Override
-    public long skip(long n) {
-      return 0;
-    }
-  }
-
   public void testReadLines() throws IOException {
     List<String> lines = CharStreams.readLines(
         new StringReader("a\nb\nc"));
diff --git a/guava-tests/test/com/google/common/io/CloserTest.java b/guava-tests/test/com/google/common/io/CloserTest.java
index c33a4b8..ee5ef76 100644
--- a/guava-tests/test/com/google/common/io/CloserTest.java
+++ b/guava-tests/test/com/google/common/io/CloserTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.io;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
 import com.google.common.base.Splitter;
@@ -50,15 +52,16 @@ public class CloserTest extends TestCase {
     suppressor = new TestSuppressor();
   }
 
+  @SuppressUnderAndroid // TODO(cpovirk): Look up Build.VERSION.SDK_INT reflectively.
   public void testCreate() {
     Closer closer = Closer.create();
     String javaVersion = System.getProperty("java.version");
     String secondPart = Iterables.get(Splitter.on('.').split(javaVersion), 1);
     int versionNumber = Integer.parseInt(secondPart);
     if (versionNumber < 7) {
-      assertTrue(closer.suppressor instanceof Closer.LoggingSuppressor);
+      assertThat(closer.suppressor).isInstanceOf(Closer.LoggingSuppressor.class);
     } else {
-      assertTrue(closer.suppressor instanceof Closer.SuppressingSuppressor);
+      assertThat(closer.suppressor).isInstanceOf(Closer.SuppressingSuppressor.class);
     }
   }
 
@@ -125,7 +128,7 @@ public class CloserTest extends TestCase {
         closer.close();
       }
     } catch (Throwable expected) {
-      assertTrue(expected instanceof IOException);
+      assertThat(expected).isInstanceOf(IOException.class);
     }
 
     assertTrue(c1.isClosed());
@@ -339,7 +342,7 @@ public class CloserTest extends TestCase {
       } catch (Throwable e) {
         throw closer.rethrow(thrownException, IOException.class);
       } finally {
-        assertEquals(0, getSuppressed(thrownException).length);
+        assertThat(getSuppressed(thrownException)).isEmpty();
         closer.close();
       }
     } catch (IOException expected) {
diff --git a/guava-tests/test/com/google/common/io/CountingInputStreamTest.java b/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
index 9e06fef..e6341a6 100644
--- a/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
+++ b/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.io;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -90,7 +92,7 @@ public class CountingInputStreamTest extends IoTestCase {
       counter.reset();
       fail();
     } catch (IOException expected) {
-      assertEquals("Mark not set", expected.getMessage());
+      assertThat(expected).hasMessage("Mark not set");
     }
   }
   
@@ -101,7 +103,7 @@ public class CountingInputStreamTest extends IoTestCase {
       counter.reset();
       fail();
     } catch (IOException expected) {
-      assertEquals("Mark not supported", expected.getMessage());
+      assertThat(expected).hasMessage("Mark not supported");
     }
   }
   
diff --git a/guava-tests/test/com/google/common/io/FilesTest.java b/guava-tests/test/com/google/common/io/FilesTest.java
index 5a4dd68..c9055e5 100644
--- a/guava-tests/test/com/google/common/io/FilesTest.java
+++ b/guava-tests/test/com/google/common/io/FilesTest.java
@@ -50,6 +50,7 @@ import java.util.Random;
  *
  * @author Chris Nokleberg
  */
+
 public class FilesTest extends IoTestCase {
 
   public static TestSuite suite() {
@@ -142,7 +143,7 @@ public class FilesTest extends IoTestCase {
   }
 
   /**
-   * A {@link File} that provides a specialized value for {link File#length()}.
+   * A {@link File} that provides a specialized value for {@link File#length()}.
    */
   private static class BadLengthFile extends File {
 
@@ -416,7 +417,7 @@ public class FilesTest extends IoTestCase {
     File temp = Files.createTempDir();
     assertTrue(temp.exists());
     assertTrue(temp.isDirectory());
-    assertEquals(0, temp.listFiles().length);
+    assertThat(temp.listFiles()).isEmpty();
     assertTrue(temp.delete());
   }
 
@@ -542,7 +543,7 @@ public class FilesTest extends IoTestCase {
     w.close();
     Files.readLines(temp, Charsets.UTF_8, collect);
     assertThat(collect.getResult())
-        .has().exactly("hello", "", " world  ", "").inOrder();
+        .containsExactly("hello", "", " world  ", "").inOrder();
 
     LineProcessor<List<String>> collectNonEmptyLines =
         new LineProcessor<List<String>>() {
@@ -562,7 +563,7 @@ public class FilesTest extends IoTestCase {
           }
         };
     Files.readLines(temp, Charsets.UTF_8, collectNonEmptyLines);
-    assertThat(collectNonEmptyLines.getResult()).has().exactly(
+    assertThat(collectNonEmptyLines.getResult()).containsExactly(
         "hello", " world  ").inOrder();
 
     assertTrue(temp.delete());
diff --git a/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java b/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
index d794ad6..6dae439 100644
--- a/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
+++ b/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.io;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.primitives.Bytes;
 
 import junit.framework.TestCase;
@@ -97,7 +99,7 @@ public class LittleEndianDataInputStreamTest extends TestCase {
       in.readLine();
       fail();
     } catch (UnsupportedOperationException expected) {
-      assertEquals("readLine is not supported", expected.getMessage()); 
+      assertThat(expected).hasMessage("readLine is not supported");
     }
   }
   
diff --git a/guava-tests/test/com/google/common/io/ResourcesTest.java b/guava-tests/test/com/google/common/io/ResourcesTest.java
index 3bf17ac..80a21cc 100644
--- a/guava-tests/test/com/google/common/io/ResourcesTest.java
+++ b/guava-tests/test/com/google/common/io/ResourcesTest.java
@@ -41,6 +41,7 @@ import java.util.List;
  *
  * @author Chris Nokleberg
  */
+
 public class ResourcesTest extends IoTestCase {
 
   public static TestSuite suite() {
@@ -108,7 +109,7 @@ public class ResourcesTest extends IoTestCase {
       Resources.getResource("no such resource");
       fail();
     } catch (IllegalArgumentException e) {
-      assertEquals("resource no such resource not found.", e.getMessage());
+      assertThat(e).hasMessage("resource no such resource not found.");
     }
   }
 
@@ -123,9 +124,10 @@ public class ResourcesTest extends IoTestCase {
           getClass(), "com/google/common/io/testdata/i18n.txt");
       fail();
     } catch (IllegalArgumentException e) {
-      assertEquals("resource com/google/common/io/testdata/i18n.txt" +
-          " relative to com.google.common.io.ResourcesTest not found.",
-          e.getMessage());
+      assertThat(e)
+          .hasMessage(
+              "resource com/google/common/io/testdata/i18n.txt"
+                  + " relative to com.google.common.io.ResourcesTest not found.");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/io/SourceSinkFactories.java b/guava-tests/test/com/google/common/io/SourceSinkFactories.java
index 0165bf8..fd48fbf 100644
--- a/guava-tests/test/com/google/common/io/SourceSinkFactories.java
+++ b/guava-tests/test/com/google/common/io/SourceSinkFactories.java
@@ -152,7 +152,7 @@ public class SourceSinkFactories {
   }
 
   public static ByteSourceFactory asSlicedByteSourceFactory(final ByteSourceFactory factory,
-      final int off, final int len) {
+      final long off, final long len) {
     checkNotNull(factory);
     return new ByteSourceFactory() {
       @Override
@@ -163,7 +163,9 @@ public class SourceSinkFactories {
       @Override
       public byte[] getExpected(byte[] bytes) {
         byte[] baseExpected = factory.getExpected(bytes);
-        return Arrays.copyOfRange(baseExpected, off, Math.min(baseExpected.length, off + len));
+        int startOffset = (int) Math.min(off, baseExpected.length);
+        int actualLen = (int) Math.min(len, baseExpected.length - startOffset);
+        return Arrays.copyOfRange(baseExpected, startOffset, startOffset + actualLen);
       }
 
       @Override
diff --git a/guava-tests/test/com/google/common/io/SourceSinkTester.java b/guava-tests/test/com/google/common/io/SourceSinkTester.java
index ff3167b..878d74f 100644
--- a/guava-tests/test/com/google/common/io/SourceSinkTester.java
+++ b/guava-tests/test/com/google/common/io/SourceSinkTester.java
@@ -37,6 +37,7 @@ import java.util.List;
  * @param <F> the factory type
  * @author Colin Decker
  */
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
 public class SourceSinkTester<S, T, F extends SourceSinkFactory<S, T>> extends TestCase {
 
   static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing "
diff --git a/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java
new file mode 100644
index 0000000..6613d88
--- /dev/null
+++ b/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.io;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/math/BigIntegerMathTest.java b/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
index 7e1aa77..4eb78f7 100644
--- a/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
+++ b/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
@@ -367,13 +367,18 @@ public class BigIntegerMathTest extends TestCase {
   }
 
   @GwtIncompatible("TODO")
+  @SuppressUnderAndroid // TODO(cpovirk): Problem with BigIntegerMath.divide on Android?
   public void testDivNonZeroExact() {
     for (BigInteger p : NONZERO_BIGINTEGER_CANDIDATES) {
       for (BigInteger q : NONZERO_BIGINTEGER_CANDIDATES) {
         boolean dividesEvenly = p.remainder(q).equals(ZERO);
 
         try {
-          assertEquals(p, BigIntegerMath.divide(p, q, UNNECESSARY).multiply(q));
+          BigInteger quotient = BigIntegerMath.divide(p, q, UNNECESSARY);
+          BigInteger undone = quotient.multiply(q);
+          if (!p.equals(undone)) {
+            failFormat("expected %s.multiply(%s) = %s; got %s", quotient, q, p, undone);
+          }
           assertTrue(dividesEvenly);
         } catch (ArithmeticException e) {
           assertFalse(dividesEvenly);
@@ -465,4 +470,9 @@ public class BigIntegerMathTest extends TestCase {
     tester.setDefault(long.class, 1L);
     tester.testAllPublicStaticMethods(BigIntegerMath.class);
   }
+
+  @GwtIncompatible("String.format")
+  private static void failFormat(String template, Object... args) {
+    fail(String.format(template, args));
+  }
 }
diff --git a/guava-tests/test/com/google/common/math/DoubleUtilsTest.java b/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
index 65952aa..6f241e7 100644
--- a/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
+++ b/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
@@ -32,15 +32,23 @@ import java.math.BigInteger;
  * @author Louis Wasserman
  */
 public class DoubleUtilsTest extends TestCase {
+  @SuppressUnderAndroid // no FpUtils
   public void testNextDown() {
     for (double d : FINITE_DOUBLE_CANDIDATES) {
       assertEquals(FpUtils.nextDown(d), DoubleUtils.nextDown(d));
     }
   }
   
+  @SuppressUnderAndroid // TODO(cpovirk): File bug for BigDecimal.doubleValue().
   public void testBigToDouble() {
     for (BigInteger b : ALL_BIGINTEGER_CANDIDATES) {
-      assertEquals(b.doubleValue(), DoubleUtils.bigToDouble(b));
+      if (b.doubleValue() != DoubleUtils.bigToDouble(b)) {
+        failFormat(
+            "Converting %s to double: expected doubleValue %s but got bigToDouble %s",
+            b,
+            b.doubleValue(),
+            DoubleUtils.bigToDouble(b));
+      }
     }
   }
 
@@ -58,4 +66,8 @@ public class DoubleUtilsTest extends TestCase {
     } catch (IllegalArgumentException expected) {
     }
   }
+
+  private static void failFormat(String template, Object... args) {
+    fail(String.format(template, args));
+  }
 }
diff --git a/guava-tests/test/com/google/common/math/LongMathTest.java b/guava-tests/test/com/google/common/math/LongMathTest.java
index d3ac668..f29d94b 100644
--- a/guava-tests/test/com/google/common/math/LongMathTest.java
+++ b/guava-tests/test/com/google/common/math/LongMathTest.java
@@ -16,7 +16,6 @@
 
 package com.google.common.math;
 
-import static com.google.common.math.MathTesting.ALL_INTEGER_CANDIDATES;
 import static com.google.common.math.MathTesting.ALL_LONG_CANDIDATES;
 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
@@ -252,12 +251,14 @@ public class LongMathTest extends TestCase {
   public void testLog10Exact() {
     for (long x : POSITIVE_LONG_CANDIDATES) {
       int floor = LongMath.log10(x, FLOOR);
-      boolean expectSuccess = LongMath.pow(10, floor) == x;
+      boolean expectedSuccess = LongMath.pow(10, floor) == x;
       try {
         assertEquals(floor, LongMath.log10(x, UNNECESSARY));
-        assertTrue(expectSuccess);
+        assertTrue(expectedSuccess);
       } catch (ArithmeticException e) {
-        assertFalse(expectSuccess);
+        if (expectedSuccess) {
+          failFormat("expected log10(%s, UNNECESSARY) = %s; got ArithmeticException", x, floor);
+        }
       }
     }
   }
@@ -322,29 +323,37 @@ public class LongMathTest extends TestCase {
   }
 
   @GwtIncompatible("TODO")
+  @SuppressUnderAndroid // TODO(cpovirk): File BigDecimal.divide() rounding bug.
   public void testDivNonZero() {
     for (long p : NONZERO_LONG_CANDIDATES) {
       for (long q : NONZERO_LONG_CANDIDATES) {
         for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
           long expected =
               new BigDecimal(valueOf(p)).divide(new BigDecimal(valueOf(q)), 0, mode).longValue();
-          assertEquals(expected, LongMath.divide(p, q, mode));
+          long actual = LongMath.divide(p, q, mode);
+          if (expected != actual) {
+            failFormat("expected divide(%s, %s, %s) = %s; got %s", p, q, mode, expected, actual);
+          }
         }
       }
     }
   }
 
   @GwtIncompatible("TODO")
+  @SuppressUnderAndroid // TODO(cpovirk): Problem with LongMath.divide on Android?
   public void testDivNonZeroExact() {
     for (long p : NONZERO_LONG_CANDIDATES) {
       for (long q : NONZERO_LONG_CANDIDATES) {
-        boolean dividesEvenly = (p % q) == 0L;
+        boolean expectedSuccess = (p % q) == 0L;
 
         try {
           assertEquals(p, LongMath.divide(p, q, UNNECESSARY) * q);
-          assertTrue(dividesEvenly);
+          assertTrue(expectedSuccess);
         } catch (ArithmeticException e) {
-          assertFalse(dividesEvenly);
+          if (expectedSuccess) {
+            failFormat(
+                "expected divide(%s, %s, UNNECESSARY) to succeed; got ArithmeticException", p, q);
+          }
         }
       }
     }
@@ -474,15 +483,18 @@ public class LongMathTest extends TestCase {
 
   @GwtIncompatible("TODO")
   public void testCheckedAdd() {
-    for (long a : ALL_INTEGER_CANDIDATES) {
-      for (long b : ALL_INTEGER_CANDIDATES) {
+    for (long a : ALL_LONG_CANDIDATES) {
+      for (long b : ALL_LONG_CANDIDATES) {
         BigInteger expectedResult = valueOf(a).add(valueOf(b));
         boolean expectedSuccess = fitsInLong(expectedResult);
         try {
           assertEquals(a + b, LongMath.checkedAdd(a, b));
           assertTrue(expectedSuccess);
         } catch (ArithmeticException e) {
-          assertFalse(expectedSuccess);
+          if (expectedSuccess) {
+            failFormat(
+                "expected checkedAdd(%s, %s) = %s; got ArithmeticException", a, b, expectedResult);
+          }
         }
       }
     }
@@ -490,31 +502,44 @@ public class LongMathTest extends TestCase {
 
   @GwtIncompatible("TODO")
   public void testCheckedSubtract() {
-    for (long a : ALL_INTEGER_CANDIDATES) {
-      for (long b : ALL_INTEGER_CANDIDATES) {
+    for (long a : ALL_LONG_CANDIDATES) {
+      for (long b : ALL_LONG_CANDIDATES) {
         BigInteger expectedResult = valueOf(a).subtract(valueOf(b));
         boolean expectedSuccess = fitsInLong(expectedResult);
         try {
           assertEquals(a - b, LongMath.checkedSubtract(a, b));
           assertTrue(expectedSuccess);
         } catch (ArithmeticException e) {
-          assertFalse(expectedSuccess);
+          if (expectedSuccess) {
+            failFormat(
+                "expected checkedSubtract(%s, %s) = %s; got ArithmeticException",
+                a,
+                b,
+                expectedResult);
+          }
         }
       }
     }
   }
 
   @GwtIncompatible("TODO")
+  @SuppressUnderAndroid // TODO(cpovirk): Problem with LongMath.checkedMultiply on Android?
   public void testCheckedMultiply() {
-    for (long a : ALL_INTEGER_CANDIDATES) {
-      for (long b : ALL_INTEGER_CANDIDATES) {
+    for (long a : ALL_LONG_CANDIDATES) {
+      for (long b : ALL_LONG_CANDIDATES) {
         BigInteger expectedResult = valueOf(a).multiply(valueOf(b));
         boolean expectedSuccess = fitsInLong(expectedResult);
         try {
           assertEquals(a * b, LongMath.checkedMultiply(a, b));
           assertTrue(expectedSuccess);
         } catch (ArithmeticException e) {
-          assertFalse(expectedSuccess);
+          if (expectedSuccess) {
+            failFormat(
+                "expected checkedMultiply(%s, %s) = %s; got ArithmeticException",
+                a,
+                b,
+                expectedResult);
+          }
         }
       }
     }
@@ -522,7 +547,7 @@ public class LongMathTest extends TestCase {
 
   @GwtIncompatible("TODO")
   public void testCheckedPow() {
-    for (long b : ALL_INTEGER_CANDIDATES) {
+    for (long b : ALL_LONG_CANDIDATES) {
       for (int exp : EXPONENTS) {
         BigInteger expectedResult = valueOf(b).pow(exp);
         boolean expectedSuccess = fitsInLong(expectedResult);
@@ -530,7 +555,13 @@ public class LongMathTest extends TestCase {
           assertEquals(expectedResult.longValue(), LongMath.checkedPow(b, exp));
           assertTrue(expectedSuccess);
         } catch (ArithmeticException e) {
-          assertFalse(expectedSuccess);
+          if (expectedSuccess) {
+            failFormat(
+                "expected checkedPow(%s, %s) = %s; got ArithmeticException",
+                b,
+                exp,
+                expectedResult);
+          }
         }
       }
     }
@@ -693,4 +724,9 @@ public class LongMathTest extends TestCase {
     tester.setDefault(long.class, 1L);
     tester.testAllPublicStaticMethods(LongMath.class);
   }
+
+  @GwtIncompatible("String.format")
+  private static void failFormat(String template, Object... args) {
+    fail(String.format(template, args));
+  }
 }
diff --git a/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java
new file mode 100644
index 0000000..c6b7af0
--- /dev/null
+++ b/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.math;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/net/HostSpecifierTest.java b/guava-tests/test/com/google/common/net/HostSpecifierTest.java
index 12c7631..439bae6 100644
--- a/guava-tests/test/com/google/common/net/HostSpecifierTest.java
+++ b/guava-tests/test/com/google/common/net/HostSpecifierTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.net;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.collect.ImmutableList;
 import com.google.common.testing.EqualsTester;
 import com.google.common.testing.NullPointerTester;
@@ -112,7 +114,7 @@ public final class HostSpecifierTest extends TestCase {
       HostSpecifier.from(spec);
       fail("Should have thrown ParseException: " + spec);
     } catch (ParseException expected) {
-      assertTrue(expected.getCause() instanceof IllegalArgumentException);
+      assertThat(expected.getCause()).isInstanceOf(IllegalArgumentException.class);
     }
 
     assertFalse(HostSpecifier.isValid(spec));
diff --git a/guava-tests/test/com/google/common/net/InetAddressesTest.java b/guava-tests/test/com/google/common/net/InetAddressesTest.java
index 7978155..f5f2fb5 100644
--- a/guava-tests/test/com/google/common/net/InetAddressesTest.java
+++ b/guava-tests/test/com/google/common/net/InetAddressesTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.net;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.testing.NullPointerTester;
 
 import junit.framework.TestCase;
@@ -387,26 +389,26 @@ public class InetAddressesTest extends TestCase {
     String mappedStr = "::ffff:192.168.0.1";
     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
     InetAddress mapped = InetAddresses.forString(mappedStr);
-    assertFalse(mapped instanceof Inet6Address);
+    assertThat(mapped).isNotInstanceOf(Inet6Address.class);
     assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
 
     // check upper case
     mappedStr = "::FFFF:192.168.0.1";
     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
     mapped = InetAddresses.forString(mappedStr);
-    assertFalse(mapped instanceof Inet6Address);
+    assertThat(mapped).isNotInstanceOf(Inet6Address.class);
     assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
 
     mappedStr = "0:00:000:0000:0:ffff:1.2.3.4";
     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
     mapped = InetAddresses.forString(mappedStr);
-    assertFalse(mapped instanceof Inet6Address);
+    assertThat(mapped).isNotInstanceOf(Inet6Address.class);
     assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
 
     mappedStr = "::ffff:0102:0304";
     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
     mapped = InetAddresses.forString(mappedStr);
-    assertFalse(mapped instanceof Inet6Address);
+    assertThat(mapped).isNotInstanceOf(Inet6Address.class);
     assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
 
     assertFalse(InetAddresses.isMappedIPv4Address("::"));
diff --git a/guava-tests/test/com/google/common/net/InternetDomainNameTest.java b/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
index 91a4347..3df6977 100644
--- a/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
+++ b/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
@@ -111,7 +111,7 @@ public final class InternetDomainNameTest extends TestCase {
   );
 
   private static final ImmutableSet<String> NO_PS = ImmutableSet.of(
-      "www", "foo.google", "x.y.z");
+      "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z");
 
   private static final ImmutableSet<String> NON_PS = ImmutableSet.of(
       "foo.bar.com", "foo.ca", "foo.bar.ca",
diff --git a/guava-tests/test/com/google/common/net/MediaTypeTest.java b/guava-tests/test/com/google/common/net/MediaTypeTest.java
index 12efed6..bfbc1c6 100644
--- a/guava-tests/test/com/google/common/net/MediaTypeTest.java
+++ b/guava-tests/test/com/google/common/net/MediaTypeTest.java
@@ -27,12 +27,12 @@ import static com.google.common.net.MediaType.ANY_VIDEO_TYPE;
 import static com.google.common.net.MediaType.HTML_UTF_8;
 import static com.google.common.net.MediaType.JPEG;
 import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
+import static com.google.common.truth.Truth.assertThat;
 import static java.lang.reflect.Modifier.isFinal;
 import static java.lang.reflect.Modifier.isPublic;
 import static java.lang.reflect.Modifier.isStatic;
 import static java.util.Arrays.asList;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
@@ -57,7 +57,6 @@ import java.nio.charset.UnsupportedCharsetException;
  *
  * @author Gregory Kick
  */
- at Beta
 @GwtCompatible(emulated = true)
 public class MediaTypeTest extends TestCase {
   @GwtIncompatible("reflection") public void testParse_useConstants() throws Exception {
@@ -77,9 +76,9 @@ public class MediaTypeTest extends TestCase {
     for (Field field : getConstantFields()) {
       Optional<Charset> charset = ((MediaType) field.get(null)).charset();
       if (field.getName().endsWith("_UTF_8")) {
-        assertEquals(Optional.of(UTF_8), charset);
+        assertThat(charset).hasValue(UTF_8);
       } else {
-        assertEquals(Optional.absent(), charset);
+        assertThat(charset).isAbsent();
       }
     }
   }
@@ -333,14 +332,13 @@ public class MediaTypeTest extends TestCase {
   }
 
   public void testGetCharset() {
-    assertEquals(Optional.absent(), MediaType.parse("text/plain").charset());
-    assertEquals(Optional.of(UTF_8),
-        MediaType.parse("text/plain; charset=utf-8").charset());
+    assertThat(MediaType.parse("text/plain").charset()).isAbsent();
+    assertThat(MediaType.parse("text/plain; charset=utf-8").charset()).hasValue(UTF_8);
   }
 
-  @GwtIncompatible("Non-UTF-8 Charset") public void testGetCharset_utf16() {
-    assertEquals(Optional.of(UTF_16),
-        MediaType.parse("text/plain; charset=utf-16").charset());
+  @GwtIncompatible("Non-UTF-8 Charset")
+  public void testGetCharset_utf16() {
+    assertThat(MediaType.parse("text/plain; charset=utf-16").charset()).hasValue(UTF_16);
   }
 
   public void testGetCharset_tooMany() {
diff --git a/guava-tests/test/com/google/common/net/PercentEscaperTest.java b/guava-tests/test/com/google/common/net/PercentEscaperTest.java
index 65425d3..7acdd41 100644
--- a/guava-tests/test/com/google/common/net/PercentEscaperTest.java
+++ b/guava-tests/test/com/google/common/net/PercentEscaperTest.java
@@ -19,6 +19,7 @@ package com.google.common.net;
 import static com.google.common.escape.testing.EscaperAsserts.assertEscaping;
 import static com.google.common.escape.testing.EscaperAsserts.assertUnescaped;
 import static com.google.common.escape.testing.EscaperAsserts.assertUnicodeEscaping;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Preconditions;
@@ -124,7 +125,7 @@ public class PercentEscaperTest extends TestCase {
       new PercentEscaper("-+#abc.!", false);
       fail(msg);
     } catch (IllegalArgumentException expected) {
-      assertEquals(msg, expected.getMessage());
+      assertThat(expected).hasMessage(msg);
     }
   }
 
@@ -144,7 +145,7 @@ public class PercentEscaperTest extends TestCase {
       new PercentEscaper(" ", true);
       fail(msg);
     } catch (IllegalArgumentException expected) {
-      assertEquals(msg, expected.getMessage());
+      assertThat(expected).hasMessage(msg);
     }
   }
 
diff --git a/guava-tests/test/com/google/common/primitives/BooleansTest.java b/guava-tests/test/com/google/common/primitives/BooleansTest.java
index e7610ff..d23e979 100644
--- a/guava-tests/test/com/google/common/primitives/BooleansTest.java
+++ b/guava-tests/test/com/google/common/primitives/BooleansTest.java
@@ -123,6 +123,7 @@ public class BooleansTest extends TestCase {
         Booleans.ensureCapacity(new boolean[] {true}, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Booleans.ensureCapacity(ARRAY_FALSE, -1, 1);
@@ -202,6 +203,7 @@ public class BooleansTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Boolean> list = Arrays.asList(false, true, null);
     try {
diff --git a/guava-tests/test/com/google/common/primitives/BytesTest.java b/guava-tests/test/com/google/common/primitives/BytesTest.java
index e268427..ca6b201 100644
--- a/guava-tests/test/com/google/common/primitives/BytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/BytesTest.java
@@ -145,6 +145,7 @@ public class BytesTest extends TestCase {
         Bytes.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Bytes.ensureCapacity(ARRAY1, -1, 1);
@@ -191,6 +192,7 @@ public class BytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Byte> list = Arrays.asList((byte) 0, (byte) 1, null);
     try {
diff --git a/guava-tests/test/com/google/common/primitives/CharsTest.java b/guava-tests/test/com/google/common/primitives/CharsTest.java
index e6d7439..2dab40f 100644
--- a/guava-tests/test/com/google/common/primitives/CharsTest.java
+++ b/guava-tests/test/com/google/common/primitives/CharsTest.java
@@ -29,6 +29,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Unit test for {@link Chars}.
@@ -75,6 +76,7 @@ public class CharsTest extends TestCase {
     assertEquals(LEAST, Chars.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private void assertCastFails(long value) {
     try {
       Chars.checkedCast(value);
@@ -168,6 +170,7 @@ public class CharsTest extends TestCase {
         (char) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Chars.max();
@@ -184,6 +187,7 @@ public class CharsTest extends TestCase {
         (char) 5, (char) 3, (char) 0, (char) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Chars.min();
@@ -221,7 +225,11 @@ public class CharsTest extends TestCase {
         new byte[] {0x23, 0x45, (byte) 0xDC}));
     assertEquals('\uFEDC', Chars.fromByteArray(
         new byte[] {(byte) 0xFE, (byte) 0xDC}));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  @GwtIncompatible("Chars.fromByteArray")
+  public void testFromByteArrayFails() {
     try {
       Chars.fromByteArray(new byte[Chars.BYTES - 1]);
       fail();
@@ -241,7 +249,8 @@ public class CharsTest extends TestCase {
     for (int hi = 0; hi < 256; hi++) {
       for (int lo = 0; lo < 256; lo++) {
         char result = Chars.fromByteArray(new byte[]{(byte) hi, (byte) lo});
-        assertEquals(String.format("hi=%s, lo=%s, expected=%s, result=%s",
+        assertEquals(String.format(Locale.ROOT,
+            "hi=%s, lo=%s, expected=%s, result=%s",
             hi, lo, (int) c, (int) result), c, result);
 
         byte[] bytes = Chars.toByteArray(c);
@@ -252,7 +261,11 @@ public class CharsTest extends TestCase {
       }
     }
     assertEquals((char) 0, c); // sanity check
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  @GwtIncompatible("Chars.fromByteArray, Chars.toByteArray")
+  public void testByteArrayRoundTripsFails() {
     try {
       Chars.fromByteArray(new byte[] {0x11});
       fail();
@@ -269,6 +282,7 @@ public class CharsTest extends TestCase {
         Chars.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Chars.ensureCapacity(ARRAY1, -1, 1);
@@ -344,6 +358,7 @@ public class CharsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Character> list = Arrays.asList((char) 0, (char) 1, null);
     try {
diff --git a/guava-tests/test/com/google/common/primitives/DoublesTest.java b/guava-tests/test/com/google/common/primitives/DoublesTest.java
index 3ee962f..23fa450 100644
--- a/guava-tests/test/com/google/common/primitives/DoublesTest.java
+++ b/guava-tests/test/com/google/common/primitives/DoublesTest.java
@@ -181,6 +181,7 @@ public class DoublesTest extends TestCase {
     assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Doubles.max();
@@ -202,6 +203,7 @@ public class DoublesTest extends TestCase {
     assertTrue(Double.isNaN(Doubles.max(VALUES)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Doubles.min();
@@ -247,6 +249,7 @@ public class DoublesTest extends TestCase {
         Doubles.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Doubles.ensureCapacity(ARRAY1, -1, 1);
@@ -336,6 +339,7 @@ public class DoublesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Double> list = Arrays.asList((double) 0, (double) 1, null);
     try {
@@ -369,7 +373,7 @@ public class DoublesTest extends TestCase {
     list.set(0, (double) 2);
     assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
     array[1] = (double) 3;
-    assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
+    assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
   }
 
   public void testAsList_toArray_roundTrip() {
@@ -418,14 +422,24 @@ public class DoublesTest extends TestCase {
   private static void checkTryParse(String input) {
     Double expected = referenceTryParse(input);
     assertEquals(expected, Doubles.tryParse(input));
-    assertEquals(expected != null,
-        Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
+    if (expected != null && !Doubles.FLOATING_POINT_PATTERN.matcher(input).matches()) {
+      // TODO(cpovirk): Use SourceCodeEscapers if it is added to Guava.
+      StringBuilder escapedInput = new StringBuilder();
+      for (char c : input.toCharArray()) {
+        if (c >= 0x20 && c <= 0x7E) {
+          escapedInput.append(c);
+        } else {
+          escapedInput.append(String.format("\\u%04x", (int) c));
+        }
+      }
+      fail("FLOATING_POINT_PATTERN should have matched valid input <" + escapedInput + ">");
+    }
   }
 
   @GwtIncompatible("Doubles.tryParse")
   private static void checkTryParse(double expected, String input) {
     assertEquals(Double.valueOf(expected), Doubles.tryParse(input));
-    assertTrue(Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
+    assertThat(input).matches(Doubles.FLOATING_POINT_PATTERN);
   }
 
   @GwtIncompatible("Doubles.tryParse")
@@ -493,7 +507,7 @@ public class DoublesTest extends TestCase {
   @GwtIncompatible("Doubles.tryParse")
   public void testTryParseFailures() {
     for (String badInput : BAD_TRY_PARSE_INPUTS) {
-      assertFalse(Doubles.FLOATING_POINT_PATTERN.matcher(badInput).matches());
+      assertThat(badInput).doesNotMatch(Doubles.FLOATING_POINT_PATTERN);
       assertEquals(referenceTryParse(badInput), Doubles.tryParse(badInput));
       assertNull(Doubles.tryParse(badInput));
     }
@@ -516,6 +530,7 @@ public class DoublesTest extends TestCase {
     assertEquals((Double) 1e-6, converter.convert("1e-6"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Doubles.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/FloatsTest.java b/guava-tests/test/com/google/common/primitives/FloatsTest.java
index 2584328..dbbf6fa 100644
--- a/guava-tests/test/com/google/common/primitives/FloatsTest.java
+++ b/guava-tests/test/com/google/common/primitives/FloatsTest.java
@@ -179,6 +179,7 @@ public class FloatsTest extends TestCase {
     assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Floats.max();
@@ -200,6 +201,7 @@ public class FloatsTest extends TestCase {
     assertTrue(Float.isNaN(Floats.max(VALUES)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Floats.min();
@@ -245,6 +247,7 @@ public class FloatsTest extends TestCase {
         Floats.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Floats.ensureCapacity(ARRAY1, -1, 1);
@@ -327,6 +330,7 @@ public class FloatsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Float> list = Arrays.asList((float) 0, (float) 1, null);
     try {
@@ -360,7 +364,7 @@ public class FloatsTest extends TestCase {
     list.set(0, (float) 2);
     assertTrue(Arrays.equals(new float[] {(float) 2, (float) 1}, array));
     array[1] = (float) 3;
-    assertThat(list).has().exactly((float) 2, (float) 3).inOrder();
+    assertThat(list).containsExactly((float) 2, (float) 3).inOrder();
   }
 
   public void testAsList_toArray_roundTrip() {
@@ -503,6 +507,7 @@ public class FloatsTest extends TestCase {
     assertEquals((Float) 1e-6f, converter.convert("1e-6"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Floats.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/IntsTest.java b/guava-tests/test/com/google/common/primitives/IntsTest.java
index 58279e6..73b13ac 100644
--- a/guava-tests/test/com/google/common/primitives/IntsTest.java
+++ b/guava-tests/test/com/google/common/primitives/IntsTest.java
@@ -77,6 +77,7 @@ public class IntsTest extends TestCase {
     assertEquals(LEAST, Ints.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       Ints.checkedCast(value);
@@ -170,6 +171,7 @@ public class IntsTest extends TestCase {
         (int) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Ints.max();
@@ -186,6 +188,7 @@ public class IntsTest extends TestCase {
         (int) 5, (int) 3, (int) 0, (int) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Ints.min();
@@ -232,7 +235,11 @@ public class IntsTest extends TestCase {
         Ints.fromByteArray(new byte[] {0x12, 0x13, 0x14, 0x15, 0x33}));
     assertEquals(0xFFEEDDCC, Ints.fromByteArray(
         new byte[] {(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC}));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  @GwtIncompatible("Ints.fromByteArray")
+  public void testFromByteArrayFails() {
     try {
       Ints.fromByteArray(new byte[Ints.BYTES - 1]);
       fail();
@@ -272,6 +279,7 @@ public class IntsTest extends TestCase {
         Ints.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Ints.ensureCapacity(ARRAY1, -1, 1);
@@ -353,6 +361,7 @@ public class IntsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Integer> list = Arrays.asList((int) 0, (int) 1, null);
     try {
@@ -433,6 +442,7 @@ public class IntsTest extends TestCase {
     assertEquals((Integer) 438, converter.convert("0666"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Ints.stringConverter().convert("notanumber");
@@ -496,4 +506,51 @@ public class IntsTest extends TestCase {
   private static void tryParseAndAssertEquals(Integer expected, String value) {
     assertEquals(expected, Ints.tryParse(value));
   }
+
+  public void testTryParse_radix() {
+    for (int radix = Character.MIN_RADIX;
+        radix <= Character.MAX_RADIX; radix++) {
+      radixEncodeParseAndAssertEquals(0, radix);
+      radixEncodeParseAndAssertEquals(8000, radix);
+      radixEncodeParseAndAssertEquals(-8000, radix);
+      radixEncodeParseAndAssertEquals(GREATEST, radix);
+      radixEncodeParseAndAssertEquals(LEAST, radix);
+      assertNull("Radix: " + radix, Ints.tryParse("9999999999999999", radix));
+      assertNull("Radix: " + radix,
+          Ints.tryParse(Long.toString((long) GREATEST + 1, radix), radix));
+      assertNull("Radix: " + radix,
+          Ints.tryParse(Long.toString((long) LEAST - 1, radix), radix));
+    }
+    assertNull("Hex string and dec parm", Ints.tryParse("FFFF", 10));
+    assertEquals("Mixed hex case", 65535, (int) Ints.tryParse("ffFF", 16));
+  }
+
+  /**
+   * Encodes the an integer as a string with given radix, then uses
+   * {@link Ints#tryParse(String, int)} to parse the result. Asserts the result
+   * is the same as what we started with.
+   */
+  private static void radixEncodeParseAndAssertEquals(Integer value,
+      int radix) {
+    assertEquals("Radix: " + radix, value,
+        Ints.tryParse(Integer.toString(value, radix), radix));
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooBig() {
+    try {
+      Ints.tryParse("0", Character.MAX_RADIX + 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooSmall() {
+    try {
+      Ints.tryParse("0", Character.MIN_RADIX - 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
 }
diff --git a/guava-tests/test/com/google/common/primitives/LongsTest.java b/guava-tests/test/com/google/common/primitives/LongsTest.java
index 7575a14..45d4235 100644
--- a/guava-tests/test/com/google/common/primitives/LongsTest.java
+++ b/guava-tests/test/com/google/common/primitives/LongsTest.java
@@ -143,6 +143,7 @@ public class LongsTest extends TestCase {
         (long) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Longs.max();
@@ -159,6 +160,7 @@ public class LongsTest extends TestCase {
         (long) 5, (long) 3, (long) 0, (long) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Longs.min();
@@ -214,7 +216,10 @@ public class LongsTest extends TestCase {
         new byte[] {
             (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
             (byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88}));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testFromByteArrayFails() {
     try {
       Longs.fromByteArray(new byte[Longs.BYTES - 1]);
       fail();
@@ -255,6 +260,7 @@ public class LongsTest extends TestCase {
         Longs.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Longs.ensureCapacity(ARRAY1, -1, 1);
@@ -336,6 +342,7 @@ public class LongsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Long> list = Arrays.asList((long) 0, (long) 1, null);
     try {
@@ -477,4 +484,50 @@ public class LongsTest extends TestCase {
   private static void tryParseAndAssertEquals(Long expected, String value) {
     assertEquals(expected, Longs.tryParse(value));
   }
+
+  public void testTryParse_radix() {
+    for (int radix = Character.MIN_RADIX;
+        radix <= Character.MAX_RADIX; radix++) {
+      radixEncodeParseAndAssertEquals((long) 0, radix);
+      radixEncodeParseAndAssertEquals((long) 8000, radix);
+      radixEncodeParseAndAssertEquals((long) -8000, radix);
+      radixEncodeParseAndAssertEquals(MAX_VALUE, radix);
+      radixEncodeParseAndAssertEquals(MIN_VALUE, radix);
+      assertNull("Radix: " + radix, Longs.tryParse("999999999999999999999999", radix));
+      assertNull("Radix: " + radix,
+          Longs.tryParse(BigInteger.valueOf(MAX_VALUE).add(BigInteger.ONE).toString(), radix));
+      assertNull("Radix: " + radix,
+          Longs.tryParse(BigInteger.valueOf(MIN_VALUE).subtract(BigInteger.ONE).toString(), radix));
+    }
+    assertNull("Hex string and dec parm", Longs.tryParse("FFFF", 10));
+    assertEquals("Mixed hex case", 65535, Longs.tryParse("ffFF", 16).longValue());
+  }
+
+  /**
+   * Encodes the long as a string with given radix, then uses
+   * {@link Longs#tryParse(String, int)} to parse the result. Asserts the result
+   * is the same as what we started with.
+   */
+  private static void radixEncodeParseAndAssertEquals(Long value, int radix) {
+    assertEquals("Radix: " + radix, value,
+        Longs.tryParse(Long.toString(value, radix), radix));
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooBig() {
+    try {
+      Longs.tryParse("0", Character.MAX_RADIX + 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  public void testTryParse_radixTooSmall() {
+    try {
+      Longs.tryParse("0", Character.MIN_RADIX - 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
 }
diff --git a/guava-tests/test/com/google/common/primitives/ShortsTest.java b/guava-tests/test/com/google/common/primitives/ShortsTest.java
index f9b9412..b981e12 100644
--- a/guava-tests/test/com/google/common/primitives/ShortsTest.java
+++ b/guava-tests/test/com/google/common/primitives/ShortsTest.java
@@ -77,6 +77,7 @@ public class ShortsTest extends TestCase {
     assertEquals(LEAST, Shorts.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       Shorts.checkedCast(value);
@@ -178,6 +179,7 @@ public class ShortsTest extends TestCase {
         (short) 3));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       Shorts.max();
@@ -194,6 +196,7 @@ public class ShortsTest extends TestCase {
         (short) 5, (short) 3, (short) 0, (short) 9));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       Shorts.min();
@@ -240,7 +243,11 @@ public class ShortsTest extends TestCase {
         Shorts.fromByteArray(new byte[] {0x23, 0x45}));
     assertEquals((short) 0xFEDC, Shorts.fromByteArray(
         new byte[] {(byte) 0xFE, (byte) 0xDC}));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  @GwtIncompatible("Shorts.fromByteArray")
+  public void testFromByteArrayFails() {
     try {
       Shorts.fromByteArray(new byte[] {0x01});
       fail();
@@ -279,6 +286,7 @@ public class ShortsTest extends TestCase {
         Shorts.ensureCapacity(ARRAY1, 2, 1)));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testEnsureCapacity_fail() {
     try {
       Shorts.ensureCapacity(ARRAY1, -1, 1);
@@ -360,6 +368,7 @@ public class ShortsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testToArray_withNull() {
     List<Short> list = Arrays.asList((short) 0, (short) 1, null);
     try {
@@ -440,6 +449,7 @@ public class ShortsTest extends TestCase {
     assertEquals((Short) (short) 438, converter.convert("0666"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testStringConverter_convertError() {
     try {
       Shorts.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/SignedBytesTest.java b/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
index 8e205fe..b5e3dd6 100644
--- a/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
@@ -65,6 +65,7 @@ public class SignedBytesTest extends TestCase {
     assertEquals(LEAST, SignedBytes.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       SignedBytes.checkedCast(value);
@@ -94,6 +95,7 @@ public class SignedBytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       SignedBytes.max();
@@ -109,6 +111,7 @@ public class SignedBytesTest extends TestCase {
         (byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       SignedBytes.min();
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
index 575eb7e..d818875 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
@@ -71,6 +71,7 @@ public class UnsignedBytesTest extends TestCase {
     assertEquals(LEAST, UnsignedBytes.saturatedCast(Long.MIN_VALUE));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertCastFails(long value) {
     try {
       UnsignedBytes.checkedCast(value);
@@ -96,6 +97,7 @@ public class UnsignedBytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       UnsignedBytes.max();
@@ -111,6 +113,7 @@ public class UnsignedBytesTest extends TestCase {
         (byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       UnsignedBytes.min();
@@ -128,6 +131,7 @@ public class UnsignedBytesTest extends TestCase {
         (byte) -1, (byte) 127, (byte) 1, (byte) -128, (byte) 0));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertParseFails(String value) {
     try {
       UnsignedBytes.parseUnsignedByte(value);
@@ -152,6 +156,7 @@ public class UnsignedBytesTest extends TestCase {
         .compare(UnsignedBytes.MAX_VALUE, (byte) (UnsignedBytes.MAX_VALUE + 1)) > 0);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   private static void assertParseFails(String value, int radix) {
     try {
       UnsignedBytes.parseUnsignedByte(value, radix);
@@ -173,6 +178,7 @@ public class UnsignedBytesTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testParseUnsignedByteThrowsExceptionForInvalidRadix() {
     // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
     // inclusive.
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java b/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
index d1fd13c..9e2e12b 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
@@ -45,7 +45,7 @@ public class UnsignedIntsTest extends TestCase {
       0xfffffffdL,
       0xfffffffeL,
       0xffffffffL};
-  
+
   private static final int LEAST = (int) 0L;
   private static final int GREATEST = (int) 0xffffffffL;
 
@@ -64,7 +64,8 @@ public class UnsignedIntsTest extends TestCase {
       }
     }
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       UnsignedInts.max();
@@ -72,7 +73,7 @@ public class UnsignedIntsTest extends TestCase {
     } catch (IllegalArgumentException expected) {
     }
   }
-  
+
   public void testMax() {
     assertEquals(LEAST, UnsignedInts.max(LEAST));
     assertEquals(GREATEST, UnsignedInts.max(GREATEST));
@@ -81,7 +82,8 @@ public class UnsignedIntsTest extends TestCase {
         (int) 0x12345678L, (int) 0x5a4316b8L,
         (int) 0xff1a618bL, (int) 0L));
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       UnsignedInts.min();
@@ -157,27 +159,29 @@ public class UnsignedIntsTest extends TestCase {
   }
 
   public void testParseInt() {
-    try {
-      for (long a : UNSIGNED_INTS) {
-        assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
-      }
-    } catch (NumberFormatException e) {
-      fail(e.getMessage());
+    for (long a : UNSIGNED_INTS) {
+      assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
     }
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseIntFail() {
     try {
       UnsignedInts.parseUnsignedInt(Long.toString(1L << 32));
       fail("Expected NumberFormatException");
     } catch (NumberFormatException expected) {}
   }
 
-  public void testParseIntWithRadix() throws NumberFormatException {
+  public void testParseIntWithRadix() {
     for (long a : UNSIGNED_INTS) {
       for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
         assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a, radix), radix));
       }
     }
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseIntWithRadixLimits() {
     // loops through all legal radix values.
     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
       // tests can successfully parse a number string with this radix.
@@ -194,6 +198,7 @@ public class UnsignedIntsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testParseIntThrowsExceptionForInvalidRadix() {
     // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
     // inclusive.
@@ -224,6 +229,7 @@ public class UnsignedIntsTest extends TestCase {
     assertEquals(0, UnsignedInts.decode("0"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testDecodeIntFails() {
     try {
       // One more than maximum value
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java b/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
index 1df86cb..7fe6724 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
@@ -233,7 +233,7 @@ public class UnsignedLongTest extends TestCase {
     }
   }
 
-  @SuppressWarnings("ReturnValueIgnored")
+  @SuppressWarnings("CheckReturnValue")
   public void testModByZero() {
     for (long a : TEST_LONGS) {
       try {
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java b/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
index 7abee87..e12975d 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
@@ -61,6 +61,7 @@ public class UnsignedLongsTest extends TestCase {
     assertTrue(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xff1a618b7f65ea12L) == 0);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testMax_noArgs() {
     try {
       UnsignedLongs.max();
@@ -76,7 +77,8 @@ public class UnsignedLongsTest extends TestCase {
         0x5a4316b8c153ac4dL, 8L, 100L,
         0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L));
   }
-  
+
+  @SuppressWarnings("CheckReturnValue")
   public void testMin_noArgs() {
     try {
       UnsignedLongs.min();
@@ -150,7 +152,10 @@ public class UnsignedLongsTest extends TestCase {
     assertEquals(0xff1a618b7f65ea12L, UnsignedLongs.parseUnsignedLong("18382112080831834642"));
     assertEquals(0x5a4316b8c153ac4dL, UnsignedLongs.parseUnsignedLong("6504067269626408013"));
     assertEquals(0x6cf78a4b139a4e2aL, UnsignedLongs.parseUnsignedLong("7851896530399809066"));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseLongFails() {
     try {
       // One more than maximum value
       UnsignedLongs.parseUnsignedLong("18446744073709551616");
@@ -169,6 +174,7 @@ public class UnsignedLongsTest extends TestCase {
     assertEquals(0L, UnsignedLongs.decode("0"));
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testDecodeLongFails() {
     try {
       // One more than maximum value
@@ -199,7 +205,10 @@ public class UnsignedLongsTest extends TestCase {
   public void testParseLongWithRadix() {
     assertEquals(0xffffffffffffffffL, UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16));
     assertEquals(0x1234567890abcdefL, UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16));
+  }
 
+  @SuppressWarnings("CheckReturnValue")
+  public void testParseLongWithRadixLimits() {
     BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE);
     // loops through all legal radix values.
     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
@@ -224,6 +233,7 @@ public class UnsignedLongsTest extends TestCase {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public void testParseLongThrowsExceptionForInvalidRadix() {
     // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive.
     try {
diff --git a/guava-tests/test/com/google/common/reflect/ClassPathTest.java b/guava-tests/test/com/google/common/reflect/ClassPathTest.java
index f492409..cafcbbf 100644
--- a/guava-tests/test/com/google/common/reflect/ClassPathTest.java
+++ b/guava-tests/test/com/google/common/reflect/ClassPathTest.java
@@ -20,13 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import com.google.common.io.Closer;
+import com.google.common.io.Files;
 import com.google.common.io.Resources;
 import com.google.common.reflect.ClassPath.ClassInfo;
 import com.google.common.reflect.ClassPath.ResourceInfo;
-import com.google.common.reflect.subpackage.ClassInSubPackage;
 import com.google.common.testing.EqualsTester;
 import com.google.common.testing.NullPointerTester;
 
@@ -39,13 +37,16 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.Map;
+import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.Set;
 import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
@@ -56,105 +57,6 @@ import java.util.zip.ZipEntry;
  */
 public class ClassPathTest extends TestCase {
 
-  public void testGetResources() throws Exception {
-    Map<String, ResourceInfo> byName = Maps.newHashMap();
-    Map<String, ResourceInfo> byToString = Maps.newHashMap();
-    ClassPath classpath = ClassPath.from(getClass().getClassLoader());
-    for (ResourceInfo resource : classpath.getResources()) {
-      assertThat(resource.getResourceName()).isNotEqualTo(JarFile.MANIFEST_NAME);
-      assertThat(resource.toString()).isNotEqualTo(JarFile.MANIFEST_NAME);
-      byName.put(resource.getResourceName(), resource);
-      byToString.put(resource.toString(), resource);
-      assertNotNull(resource.url());
-    }
-    String testResourceName = "com/google/common/reflect/test.txt";
-    assertThat(byName.keySet()).has().allOf(
-        "com/google/common/reflect/ClassPath.class",
-        "com/google/common/reflect/ClassPathTest.class",
-        "com/google/common/reflect/ClassPathTest$Nested.class",
-        testResourceName);
-    assertThat(byToString.keySet()).has().allOf(
-        "com.google.common.reflect.ClassPath",
-        "com.google.common.reflect.ClassPathTest",
-        "com.google.common.reflect.ClassPathTest$Nested",
-        testResourceName);
-    assertEquals(getClass().getClassLoader().getResource(testResourceName),
-        byName.get("com/google/common/reflect/test.txt").url());
-  }
-
-  public void testGetAllClasses() throws Exception {
-    Set<String> names = Sets.newHashSet();
-    Set<String> strings = Sets.newHashSet();
-    Set<Class<?>> classes = Sets.newHashSet();
-    Set<String> packageNames = Sets.newHashSet();
-    Set<String> simpleNames = Sets.newHashSet();
-    ClassPath classpath = ClassPath.from(getClass().getClassLoader());
-    for (ClassInfo classInfo : classpath.getAllClasses()) {
-      if (!classInfo.getPackageName().equals(ClassPathTest.class.getPackage().getName())) {
-        continue;
-      }
-      names.add(classInfo.getName());
-      strings.add(classInfo.toString());
-      classes.add(classInfo.load());
-      packageNames.add(classInfo.getPackageName());
-      simpleNames.add(classInfo.getSimpleName());
-    }
-    class LocalClass {}
-    Class<?> anonymousClass = new Object() {}.getClass();
-    assertThat(names).has().allOf(anonymousClass.getName(), LocalClass.class.getName(),
-        ClassPath.class.getName(), ClassPathTest.class.getName());
-    assertThat(strings).has().allOf(anonymousClass.getName(), LocalClass.class.getName(),
-        ClassPath.class.getName(), ClassPathTest.class.getName());
-    assertThat(classes).has().allOf(anonymousClass, LocalClass.class, ClassPath.class,
-        ClassPathTest.class);
-    assertThat(packageNames).has().exactly(ClassPath.class.getPackage().getName());
-    assertThat(simpleNames).has().allOf("", "Local", "ClassPath", "ClassPathTest");
-  }
-
-  public void testGetTopLevelClasses() throws Exception {
-    Set<String> names = Sets.newHashSet();
-    Set<String> strings = Sets.newHashSet();
-    Set<Class<?>> classes = Sets.newHashSet();
-    Set<String> packageNames = Sets.newHashSet();
-    Set<String> simpleNames = Sets.newHashSet();
-    ClassPath classpath = ClassPath.from(getClass().getClassLoader());
-    for (ClassInfo classInfo
-        : classpath.getTopLevelClasses(ClassPathTest.class.getPackage().getName())) {
-      names.add(classInfo.getName());
-      strings.add(classInfo.toString());
-      classes.add(classInfo.load());
-      packageNames.add(classInfo.getPackageName());
-      simpleNames.add(classInfo.getSimpleName());
-    }
-    assertThat(names).has().allOf(ClassPath.class.getName(), ClassPathTest.class.getName());
-    assertThat(strings).has().allOf(ClassPath.class.getName(), ClassPathTest.class.getName());
-    assertThat(classes).has().allOf(ClassPath.class, ClassPathTest.class);
-    assertThat(packageNames).has().item(ClassPath.class.getPackage().getName());
-    assertThat(simpleNames).has().allOf("ClassPath", "ClassPathTest");
-    assertFalse(classes.contains(ClassInSubPackage.class));
-  }
-
-  public void testGetTopLevelClassesRecursive() throws Exception {
-    Set<Class<?>> classes = Sets.newHashSet();
-    ClassPath classpath = ClassPath.from(ClassPathTest.class.getClassLoader());
-    for (ClassInfo classInfo
-        : classpath.getTopLevelClassesRecursive(ClassPathTest.class.getPackage().getName())) {
-      if (classInfo.getName().contains("ClassPathTest")) {
-        System.err.println("");
-      }
-      classes.add(classInfo.load());
-    }
-    assertThat(classes).has().allOf(ClassPathTest.class, ClassInSubPackage.class);
-  }
-
-  public void testGetTopLevelClasses_diamond() throws Exception {
-    ClassLoader parent = ClassPathTest.class.getClassLoader();
-    ClassLoader sub1 = new ClassLoader(parent) {};
-    ClassLoader sub2 = new ClassLoader(parent) {};
-    assertEquals(findClass(ClassPath.from(sub1).getTopLevelClasses(), ClassPathTest.class),
-        findClass(ClassPath.from(sub2).getTopLevelClasses(), ClassPathTest.class));
-  }
-
   public void testEquals() {
     new EqualsTester()
         .addEqualityGroup(classInfo(ClassPathTest.class), classInfo(ClassPathTest.class))
@@ -167,74 +69,83 @@ public class ClassPathTest extends TestCase {
         .testEquals();
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_emptyURLClassLoader_noParent() {
-    assertThat(ClassPath.getClassPathEntries(new URLClassLoader(new URL[0], null)).keySet())
+    assertThat(ClassPath.Scanner.getClassPathEntries(new URLClassLoader(new URL[0], null)).keySet())
         .isEmpty();
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_URLClassLoader_noParent() throws Exception {
     URL url1 = new URL("file:/a");
     URL url2 = new URL("file:/b");
     URLClassLoader classloader = new URLClassLoader(new URL[] {url1, url2}, null);
     assertEquals(
-        ImmutableMap.of(url1.toURI(), classloader, url2.toURI(), classloader),
-        ClassPath.getClassPathEntries(classloader));
+        ImmutableMap.of(new File("/a"), classloader, new File("/b"), classloader),
+        ClassPath.Scanner.getClassPathEntries(classloader));
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_URLClassLoader_withParent() throws Exception {
     URL url1 = new URL("file:/a");
     URL url2 = new URL("file:/b");
     URLClassLoader parent = new URLClassLoader(new URL[] {url1}, null);
     URLClassLoader child = new URLClassLoader(new URL[] {url2}, parent) {};
-    ImmutableMap<URI, ClassLoader> classPathEntries = ClassPath.getClassPathEntries(child);
-    assertEquals(ImmutableMap.of(url1.toURI(), parent, url2.toURI(), child),  classPathEntries);
-    assertThat(classPathEntries.keySet()).has().exactly(url1.toURI(), url2.toURI()).inOrder();
+    ImmutableMap<File, ClassLoader> classPathEntries = ClassPath.Scanner.getClassPathEntries(child);
+    assertEquals(ImmutableMap.of(new File("/a"), parent, new File("/b"), child),  classPathEntries);
+    assertThat(classPathEntries.keySet()).containsExactly(new File("/a"), new File("/b")).inOrder();
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_duplicateUri_parentWins() throws Exception {
     URL url = new URL("file:/a");
     URLClassLoader parent = new URLClassLoader(new URL[] {url}, null);
     URLClassLoader child = new URLClassLoader(new URL[] {url}, parent) {};
-    assertEquals(ImmutableMap.of(url.toURI(), parent), ClassPath.getClassPathEntries(child));
+    assertEquals(ImmutableMap.of(new File("/a"), parent),
+        ClassPath.Scanner.getClassPathEntries(child));
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_notURLClassLoader_noParent() {
-    assertThat(ClassPath.getClassPathEntries(new ClassLoader(null) {}).keySet()).isEmpty();
+    assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(null) {}).keySet()).isEmpty();
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_notURLClassLoader_withParent() throws Exception {
     URL url = new URL("file:/a");
     URLClassLoader parent = new URLClassLoader(new URL[] {url}, null);
     assertEquals(
-        ImmutableMap.of(url.toURI(), parent),
-        ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+        ImmutableMap.of(new File("/a"), parent),
+        ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_notURLClassLoader_withParentAndGrandParent() throws Exception {
     URL url1 = new URL("file:/a");
     URL url2 = new URL("file:/b");
     URLClassLoader grandParent = new URLClassLoader(new URL[] {url1}, null);
     URLClassLoader parent = new URLClassLoader(new URL[] {url2}, grandParent);
     assertEquals(
-        ImmutableMap.of(url1.toURI(), grandParent, url2.toURI(), parent),
-        ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+        ImmutableMap.of(new File("/a"), grandParent, new File("/b"), parent),
+        ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
   }
 
+  @SuppressUnderAndroid // Android forbids null parent ClassLoader
   public void testClassPathEntries_notURLClassLoader_withGrandParent() throws Exception {
     URL url = new URL("file:/a");
     URLClassLoader grandParent = new URLClassLoader(new URL[] {url}, null);
     ClassLoader parent = new ClassLoader(grandParent) {};
     assertEquals(
-        ImmutableMap.of(url.toURI(), grandParent),
-        ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+        ImmutableMap.of(new File("/a"), grandParent),
+        ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
   }
 
   public void testScan_classPathCycle() throws IOException {
     File jarFile = File.createTempFile("with_circular_class_path", ".jar");
     try {
       writeSelfReferencingJarFile(jarFile, "test.txt");
-      ClassPath.Scanner scanner = new ClassPath.Scanner();
-      scanner.scan(jarFile.toURI(), ClassPathTest.class.getClassLoader());
+      ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
+      scanner.scan(jarFile, ClassPathTest.class.getClassLoader());
       assertEquals(1, scanner.getResources().size());
     } finally {
       jarFile.delete();
@@ -243,33 +154,37 @@ public class ClassPathTest extends TestCase {
 
   public void testScanFromFile_fileNotExists() throws IOException {
     ClassLoader classLoader = ClassPathTest.class.getClassLoader();
-    ClassPath.Scanner scanner = new ClassPath.Scanner();
-    scanner.scanFrom(new File("no/such/file/anywhere"), classLoader);
+    ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
+    scanner.scan(new File("no/such/file/anywhere"), classLoader);
     assertThat(scanner.getResources()).isEmpty();
   }
 
   public void testScanFromFile_notJarFile() throws IOException {
     ClassLoader classLoader = ClassPathTest.class.getClassLoader();
     File notJar = File.createTempFile("not_a_jar", "txt");
-    ClassPath.Scanner scanner = new ClassPath.Scanner();
+    ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
     try {
-      scanner.scanFrom(notJar, classLoader);
+      scanner.scan(notJar, classLoader);
     } finally {
       notJar.delete();
     }
     assertThat(scanner.getResources()).isEmpty();
   }
 
-  public void testGetClassPathEntry() throws URISyntaxException {
-    assertEquals(URI.create("file:/usr/test/dep.jar"),
+  public void testGetClassPathEntry() throws MalformedURLException, URISyntaxException {
+    assertEquals(new File("/usr/test/dep.jar").toURI(),
         ClassPath.Scanner.getClassPathEntry(
-            new File("/home/build/outer.jar"), "file:/usr/test/dep.jar"));
-    assertEquals(URI.create("file:/home/build/a.jar"),
-        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "a.jar"));
-    assertEquals(URI.create("file:/home/build/x/y/z"),
-        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z"));
-    assertEquals(URI.create("file:/home/build/x/y/z.jar"),
-        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z.jar"));
+            new File("/home/build/outer.jar"), "file:/usr/test/dep.jar").toURI());
+    assertEquals(new File("/home/build/a.jar").toURI(),
+        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "a.jar").toURI());
+    assertEquals(new File("/home/build/x/y/z").toURI(),
+        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z").toURI());
+    assertEquals(new File("/home/build/x/y/z.jar").toURI(),
+        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z.jar")
+            .toURI());
+    assertEquals("/home/build/x y.jar",
+        ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x y.jar")
+            .getFile());
   }
 
   public void testGetClassPathFromManifest_nullManifest() {
@@ -290,17 +205,24 @@ public class ClassPathTest extends TestCase {
 
   public void testGetClassPathFromManifest_badClassPath() throws IOException {
     File jarFile = new File("base.jar");
-    Manifest manifest = manifestClasspath("an_invalid^path");
+    Manifest manifest = manifestClasspath("nosuchscheme:an_invalid^path");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
         .isEmpty();
   }
 
+  public void testGetClassPathFromManifest_pathWithStrangeCharacter() throws IOException {
+    File jarFile = new File("base/some.jar");
+    Manifest manifest = manifestClasspath("file:the^file.jar");
+    assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
+        .containsExactly(fullpath("base/the^file.jar"));
+  }
+
   public void testGetClassPathFromManifest_relativeDirectory() throws IOException {
     File jarFile = new File("base/some.jar");
     // with/relative/directory is the Class-Path value in the mf file.
     Manifest manifest = manifestClasspath("with/relative/dir");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("base/with/relative/dir").toURI()).inOrder();
+        .containsExactly(fullpath("base/with/relative/dir"));
   }
 
   public void testGetClassPathFromManifest_relativeJar() throws IOException {
@@ -308,7 +230,7 @@ public class ClassPathTest extends TestCase {
     // with/relative/directory is the Class-Path value in the mf file.
     Manifest manifest = manifestClasspath("with/relative.jar");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("base/with/relative.jar").toURI()).inOrder();
+        .containsExactly(fullpath("base/with/relative.jar"));
   }
 
   public void testGetClassPathFromManifest_jarInCurrentDirectory() throws IOException {
@@ -316,31 +238,31 @@ public class ClassPathTest extends TestCase {
     // with/relative/directory is the Class-Path value in the mf file.
     Manifest manifest = manifestClasspath("current.jar");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("base/current.jar").toURI()).inOrder();
+        .containsExactly(fullpath("base/current.jar"));
   }
 
   public void testGetClassPathFromManifest_absoluteDirectory() throws IOException {
     File jarFile = new File("base/some.jar");
     Manifest manifest = manifestClasspath("file:/with/absolute/dir");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("/with/absolute/dir").toURI()).inOrder();
+        .containsExactly(fullpath("/with/absolute/dir"));
   }
 
   public void testGetClassPathFromManifest_absoluteJar() throws IOException {
     File jarFile = new File("base/some.jar");
     Manifest manifest = manifestClasspath("file:/with/absolute.jar");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("/with/absolute.jar").toURI()).inOrder();
+        .containsExactly(fullpath("/with/absolute.jar"));
   }
 
   public void testGetClassPathFromManifest_multiplePaths() throws IOException {
     File jarFile = new File("base/some.jar");
     Manifest manifest = manifestClasspath("file:/with/absolute.jar relative.jar  relative/dir");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(
-            new File("/with/absolute.jar").toURI(),
-            new File("base/relative.jar").toURI(),
-            new File("base/relative/dir").toURI())
+        .containsExactly(
+            fullpath("/with/absolute.jar"),
+            fullpath("base/relative.jar"),
+            fullpath("base/relative/dir"))
         .inOrder();
   }
 
@@ -348,14 +270,14 @@ public class ClassPathTest extends TestCase {
     File jarFile = new File("base/some.jar");
     Manifest manifest = manifestClasspath(" relative.jar");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("base/relative.jar").toURI()).inOrder();
+        .containsExactly(fullpath("base/relative.jar"));
   }
 
   public void testGetClassPathFromManifest_trailingBlanks() throws IOException {
     File jarFile = new File("base/some.jar");
     Manifest manifest = manifestClasspath("relative.jar ");
     assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
-        .has().exactly(new File("base/relative.jar").toURI()).inOrder();
+        .containsExactly(fullpath("base/relative.jar"));
   }
 
   public void testGetClassName() {
@@ -369,21 +291,21 @@ public class ClassPathTest extends TestCase {
   }
 
   public void testGetSimpleName() {
+    ClassLoader classLoader = getClass().getClassLoader();
     assertEquals("Foo",
-        new ClassInfo("Foo.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("Foo.class", classLoader).getSimpleName());
     assertEquals("Foo",
-        new ClassInfo("a/b/Foo.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("a/b/Foo.class", classLoader).getSimpleName());
     assertEquals("Foo",
-        new ClassInfo("a/b/Bar$Foo.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName());
     assertEquals("",
-        new ClassInfo("a/b/Bar$1.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName());
     assertEquals("Foo",
-        new ClassInfo("a/b/Bar$Foo.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName());
     assertEquals("",
-        new ClassInfo("a/b/Bar$1.class", getClass().getClassLoader()).getSimpleName());
+        new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName());
     assertEquals("Local",
-        new ClassInfo("a/b/Bar$1Local.class", getClass().getClassLoader()).getSimpleName());
-
+        new ClassInfo("a/b/Bar$1Local.class", classLoader).getSimpleName());
   }
 
   public void testGetPackageName() {
@@ -393,6 +315,12 @@ public class ClassPathTest extends TestCase {
         new ClassInfo("a/b/Foo.class", getClass().getClassLoader()).getPackageName());
   }
 
+  // Test that ResourceInfo.urls() returns identical content to ClassLoader.getResources()
+
+  private static boolean contentEquals(URL left, URL right) throws IOException {
+    return Resources.asByteSource(left).contentEquals(Resources.asByteSource(right));
+  }
+
   private static class Nested {}
 
   public void testNulls() throws IOException {
@@ -401,6 +329,12 @@ public class ClassPathTest extends TestCase {
         .testAllPublicInstanceMethods(ClassPath.from(getClass().getClassLoader()));
   }
 
+  public void testResourceScanner() throws IOException {
+    ResourceScanner scanner = new ResourceScanner();
+    scanner.scan(ClassLoader.getSystemClassLoader());
+    assertThat(scanner.resources).contains("com/google/common/reflect/ClassPathTest.class");
+  }
+
   private static ClassPath.ClassInfo findClass(
       Iterable<ClassPath.ClassInfo> classes, Class<?> cls) {
     for (ClassPath.ClassInfo classInfo : classes) {
@@ -412,7 +346,9 @@ public class ClassPathTest extends TestCase {
   }
 
   private static ResourceInfo resourceInfo(Class<?> cls) {
-    return ResourceInfo.of(cls.getName().replace('.', '/') + ".class", cls.getClassLoader());
+    String resource = cls.getName().replace('.', '/') + ".class";
+    ClassLoader loader = cls.getClassLoader();
+    return ResourceInfo.of(resource, loader);
   }
 
   private static ClassInfo classInfo(Class<?> cls) {
@@ -420,7 +356,8 @@ public class ClassPathTest extends TestCase {
   }
 
   private static ClassInfo classInfo(Class<?> cls, ClassLoader classLoader) {
-    return new ClassInfo(cls.getName().replace('.', '/') + ".class", classLoader);
+    String resource = cls.getName().replace('.', '/') + ".class";
+    return new ClassInfo(resource, classLoader);
   }
 
   private static Manifest manifestClasspath(String classpath) throws IOException {
@@ -456,4 +393,27 @@ public class ClassPathTest extends TestCase {
     manifest.read(in);
     return manifest;
   }
+
+  private static File fullpath(String path) {
+    return new File(new File(path).toURI());
+  }
+
+  private static class ResourceScanner extends ClassPath.Scanner {
+    final Set<String> resources = new HashSet<String>();
+
+    @Override protected void scanDirectory(ClassLoader loader, File root) throws IOException {
+      URI base = root.toURI();
+      for (File entry : Files.fileTreeTraverser().preOrderTraversal(root)) {
+        String resourceName = new File(base.relativize(entry.toURI()).getPath()).getPath();
+        resources.add(resourceName);
+      }
+    }
+
+    @Override protected void scanJarFile(ClassLoader loader, JarFile file) throws IOException {
+      Enumeration<JarEntry> entries = file.entries();
+      while (entries.hasMoreElements()) {
+        resources.add(entries.nextElement().getName());
+      }
+    }
+  }
 }
diff --git a/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java b/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
index d622b22..9ad3b91 100644
--- a/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
@@ -42,6 +42,7 @@ import java.util.Map.Entry;
  */
 public class ImmutableTypeToInstanceMapTest extends TestCase {
 
+  @SuppressUnderAndroid // problem with suite builders on Android
   public static Test suite() {
     TestSuite suite = new TestSuite();
     suite.addTestSuite(ImmutableTypeToInstanceMapTest.class);
@@ -109,7 +110,7 @@ public class ImmutableTypeToInstanceMapTest extends TestCase {
             .put(type, array)
             .build();
     assertEquals(1, map.size());
-    assertThat(map.getInstance(type)).asList().has().exactly(array[0]).inOrder();
+    assertThat(map.getInstance(type)).asList().containsExactly(array[0]);
   }
 
   public void testWildcardType() {
diff --git a/guava-tests/test/com/google/common/reflect/InvokableTest.java b/guava-tests/test/com/google/common/reflect/InvokableTest.java
index b8875fd..af0f9c0 100644
--- a/guava-tests/test/com/google/common/reflect/InvokableTest.java
+++ b/guava-tests/test/com/google/common/reflect/InvokableTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.reflect;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.testing.EqualsTester;
@@ -38,6 +40,7 @@ import javax.annotation.Nullable;
  *
  * @author Ben Yu
  */
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
 public class InvokableTest extends TestCase {
 
   public void testConstructor_returnType() throws Exception {
@@ -56,7 +59,7 @@ public class InvokableTest extends TestCase {
     @SuppressWarnings("rawtypes") // Foo.class
     Constructor<WithConstructorAndTypeParameter> constructor = type.getDeclaredConstructor();
     Invokable<?, ?> factory = Invokable.from(constructor);
-    assertEquals(2, factory.getTypeParameters().length);
+    assertThat(factory.getTypeParameters()).hasLength(2);
     assertEquals(type.getTypeParameters()[0], factory.getTypeParameters()[0]);
     assertEquals(constructor.getTypeParameters()[0], factory.getTypeParameters()[1]);
     ParameterizedType returnType = (ParameterizedType) factory.getReturnType().getType();
@@ -71,9 +74,8 @@ public class InvokableTest extends TestCase {
   }
 
   public void testConstructor_typeParameters() throws Exception {
-    TypeVariable<?>[] variables =
-        Prepender.constructor().getTypeParameters();
-    assertEquals(1, variables.length);
+    TypeVariable<?>[] variables = Prepender.constructor().getTypeParameters();
+    assertThat(variables).hasLength(1);
     assertEquals("A", variables[0].getName());
   }
 
@@ -127,7 +129,7 @@ public class InvokableTest extends TestCase {
   public void testStaticMethod_typeParameters() throws Exception {
     Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class);
     TypeVariable<?>[] variables = delegate.getTypeParameters();
-    assertEquals(1, variables.length);
+    assertThat(variables).hasLength(1);
     assertEquals("T", variables[0].getName());
   }
 
@@ -197,7 +199,7 @@ public class InvokableTest extends TestCase {
 
   public void testInstanceMethod_typeParameters() throws Exception {
     Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class);
-    assertEquals(0, delegate.getTypeParameters().length);
+    assertThat(delegate.getTypeParameters()).isEmpty();
   }
 
   public void testInstanceMethod_parameters() throws Exception {
@@ -205,10 +207,8 @@ public class InvokableTest extends TestCase {
     ImmutableList<Parameter> parameters = delegate.getParameters();
     assertEquals(1, parameters.size());
     assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(0).getType());
-    assertEquals(0, parameters.get(0).getAnnotations().length);
-    new EqualsTester()
-        .addEqualityGroup(parameters.get(0))
-        .testEquals();
+    assertThat(parameters.get(0).getAnnotations()).isEmpty();
+    new EqualsTester().addEqualityGroup(parameters.get(0)).testEquals();
   }
 
   public void testInstanceMethod_call() throws Exception {
diff --git a/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java b/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
index 26f702e..ad19d36 100644
--- a/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
@@ -42,6 +42,7 @@ import java.util.Map.Entry;
  */
 public class MutableTypeToInstanceMapTest extends TestCase {
 
+  @SuppressUnderAndroid // problem with suite builders on Android
   public static Test suite() {
     TestSuite suite = new TestSuite();
     suite.addTestSuite(MutableTypeToInstanceMapTest.class);
@@ -200,7 +201,7 @@ public class MutableTypeToInstanceMapTest extends TestCase {
     TypeToken<ImmutableList<Integer>[]> type = new TypeToken<ImmutableList<Integer>[]>() {};
     map.putInstance(type, array);
     assertEquals(1, map.size());
-    assertThat(map.getInstance(type)).asList().has().exactly(array[0]).inOrder();
+    assertThat(map.getInstance(type)).asList().containsExactly(array[0]);
   }
 
   public void testWildcardType() {
diff --git a/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java
new file mode 100644
index 0000000..e5b20bf
--- /dev/null
+++ b/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.reflect;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/reflect/TypeResolverTest.java b/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
index 84b1b5e..a14adec 100644
--- a/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
  *
  * @author Ben Yu
  */
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
 public class TypeResolverTest extends TestCase {
 
   public void testWhere_noMapping() {
@@ -111,11 +112,11 @@ public class TypeResolverTest extends TestCase {
         .where(new TypeCapture<List<T>>() {}.capture(),
             new TypeCapture<List<String>>() {}.capture())
         .resolveType(t));
-    assertEquals(Types.subtypeOf(String.class), new TypeResolver()
+    assertEquals(t, new TypeResolver()
         .where(new TypeCapture<List<T>>() {}.capture(),
             new TypeCapture<List<? extends String>>() {}.capture())
         .resolveType(t));
-    assertEquals(Types.supertypeOf(String.class), new TypeResolver()
+    assertEquals(t, new TypeResolver()
         .where(new TypeCapture<List<T>>() {}.capture(),
             new TypeCapture<List<? super String>>() {}.capture())
         .resolveType(t));
@@ -186,24 +187,67 @@ public class TypeResolverTest extends TestCase {
   public <T> void testWhere_wrongOrder() {
     try {
       new TypeResolver().where(String.class, aTypeVariable());
-     fail();
+      fail();
     } catch (IllegalArgumentException expected) {}
   }
 
   public <T> void testWhere_mapFromConcreteParameterizedType() {
     try {
       new TypeResolver().where(new TypeCapture<List<String>>() {}.capture(), aTypeVariable());
-     fail();
+      fail();
     } catch (IllegalArgumentException expected) {}
   }
 
   public <T> void testWhere_mapFromConcreteGenericArrayType() {
     try {
       new TypeResolver().where(new TypeCapture<List<String>>() {}.capture(), aTypeVariable());
-     fail();
+      fail();
     } catch (IllegalArgumentException expected) {}
   }
 
+  public <K, V> void testWhere_actualArgHasWildcard() {
+    TypeResolver resolver = new TypeResolver().where(
+        new TypeCapture<Iterable<Map<?, V>>>() {}.capture(),
+        new TypeCapture<Iterable<Map<String, Integer>>>() {}.capture());
+    assertEquals(
+        new TypeCapture<K>() {}.capture(), resolver.resolveType(new TypeCapture<K>() {}.capture()));
+    assertEquals(
+        Integer.class, resolver.resolveType(new TypeCapture<V>() {}.capture()));
+  }
+
+  public <T> void testWhere_mapFromWildcard() {
+    Type subType = new TypeCapture<TypedKeyMap<T>>() {}.capture();
+    assertEquals(new TypeCapture<TypedKeyMap<String>>() {}.capture(),
+        new TypeResolver()
+            .where(
+                new TypeCapture<Map<Integer, T>>() {}.capture(),
+                new TypeCapture<Map<?, String>>() {}.capture())
+        .resolveType(subType));
+  }
+
+  public <T> void testWhere_mapFromWildcardToParameterized() {
+    Type subType = new TypeCapture<TypedListKeyMap<T>>() {}.capture();
+    assertEquals(new TypeCapture<TypedListKeyMap<String>>() {}.capture(),
+        new TypeResolver()
+            .where(
+                new TypeCapture<Map<List<Integer>, T>>() {}.capture(),
+                new TypeCapture<Map<?, String>>() {}.capture())
+        .resolveType(subType));
+  }
+
+  public <T> void testWhere_mapFromBoundedWildcard() {
+    Type subType = new TypeCapture<TypedKeyMap<T>>() {}.capture();
+    // TODO(benyu): This should check equality to an expected value, see discussion in cl/98674873
+    new TypeResolver()
+        .where(
+            new TypeCapture<Map<Integer, T>>() {}.capture(),
+            new TypeCapture<Map<? extends Number, ? extends Number>>() {}.capture())
+        .resolveType(subType);
+  }
+
+  interface TypedKeyMap<T> extends Map<Integer, T> {}
+  interface TypedListKeyMap<T> extends Map<List<Integer>, T> {}
+
   private static <T> Type aTypeVariable() {
     return new TypeCapture<T>() {}.capture();
   }
diff --git a/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java b/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
index bf9dd11..bf511c6 100644
--- a/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
@@ -37,6 +37,7 @@ import java.util.Map;
  * 
  * @author Ben Yu
  */
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
 public class TypeTokenResolutionTest extends TestCase {
 
   private static class Foo<A, B> {
@@ -124,9 +125,8 @@ public class TypeTokenResolutionTest extends TestCase {
         parameterized.parameterizedType());
     assertEquals(TypeTokenResolutionTest.class, resolved.getOwnerType());
     assertEquals(Bar.class, resolved.getRawType());
-    assertThat(resolved.getActualTypeArguments()).asList().has().item(String.class);
+    assertThat(resolved.getActualTypeArguments()).asList().contains(String.class);
   }
-  
   private interface StringListPredicate extends Predicate<List<String>> {}
 
   private interface IntegerSupplier extends Supplier<Integer> {}
diff --git a/guava-tests/test/com/google/common/reflect/TypeTokenTest.java b/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
index 893a054..4a91392 100644
--- a/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
@@ -27,7 +27,7 @@ import com.google.common.primitives.Primitives;
 import com.google.common.testing.EqualsTester;
 import com.google.common.testing.NullPointerTester;
 import com.google.common.testing.SerializableTester;
-import com.google.common.truth.CollectionSubject;
+import com.google.common.truth.IterableSubject;
 
 import junit.framework.TestCase;
 
@@ -49,6 +49,7 @@ import java.util.Map;
  * @author Sven Mawson
  * @author Ben Yu
  */
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
 public class TypeTokenTest extends TestCase {
 
   private abstract static class StringList implements List<String> {}
@@ -109,19 +110,19 @@ public class TypeTokenTest extends TestCase {
     assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
   }
 
-  public void testGenericArrayType() throws Exception {
+  public void testGenericArrayType() {
     TypeToken<List<String>[]> token = new TypeToken<List<String>[]>() {};
     assertEquals(List[].class, token.getRawType());
-    assertTrue(token.getType() instanceof GenericArrayType);
+    assertThat(token.getType()).isInstanceOf(GenericArrayType.class);
   }
 
-  public void testMultiDimensionalGenericArrayType() throws Exception {
+  public void testMultiDimensionalGenericArrayType() {
     TypeToken<List<Long>[][][]> token = new TypeToken<List<Long>[][][]>() {};
     assertEquals(List[][][].class, token.getRawType());
-    assertTrue(token.getType() instanceof GenericArrayType);
+    assertThat(token.getType()).isInstanceOf(GenericArrayType.class);
   }
 
-  public <T> void testGenericVariableTypeArrays() throws Exception {
+  public <T> void testGenericVariableTypeArrays() {
     assertEquals("T[]", new TypeToken<T[]>() {}.toString());
   }
 
@@ -133,7 +134,7 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <F extends Enum<F> & Function<String, Integer> & Iterable<Long>>
-  void testResolveType_fromTypeVariable() throws Exception {
+  void testResolveType_fromTypeVariable() {
     TypeToken<?> f = TypeToken.of(new TypeCapture<F>() {}.capture());
     assertEquals(String.class,
         f.resolveType(Function.class.getTypeParameters()[0]).getType());
@@ -144,13 +145,13 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <E extends Comparable<Iterable<String>> & Iterable<Integer>>
-  void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() throws Exception {
+  void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() {
     TypeToken<?> e = TypeToken.of(new TypeCapture<E>() {}.capture());
     assertEquals(Integer.class,
         e.resolveType(Iterable.class.getTypeParameters()[0]).getType());
   }
 
-  public void testResolveType_fromWildcard() throws Exception {
+  public void testResolveType_fromWildcard() {
     ParameterizedType withWildcardType = (ParameterizedType)
         new TypeCapture<Comparable<? extends Iterable<String>>>() {}.capture();
     TypeToken<?> wildcardType = TypeToken.of(withWildcardType.getActualTypeArguments()[0]);
@@ -160,39 +161,39 @@ public class TypeTokenTest extends TestCase {
 
   public void testGetTypes_noSuperclass() {
     TypeToken<Object>.TypeSet types = new TypeToken<Object>() {}.getTypes();
-    assertThat(types).has().item(TypeToken.of(Object.class));
-    assertThat(types.rawTypes()).has().item(Object.class);
+    assertThat(types).contains(TypeToken.of(Object.class));
+    assertThat(types.rawTypes()).contains(Object.class);
     assertThat(types.interfaces()).isEmpty();
     assertThat(types.interfaces().rawTypes()).isEmpty();
-    assertThat(types.classes()).has().item(TypeToken.of(Object.class));
-    assertThat(types.classes().rawTypes()).has().item(Object.class);
+    assertThat(types.classes()).contains(TypeToken.of(Object.class));
+    assertThat(types.classes().rawTypes()).contains(Object.class);
   }
 
   public void testGetTypes_fromInterface() {
     TypeToken<Interface1>.TypeSet types = new TypeToken<Interface1>() {}.getTypes();
-    assertThat(types).has().item(TypeToken.of(Interface1.class));
-    assertThat(types.rawTypes()).has().item(Interface1.class);
-    assertThat(types.interfaces()).has().item(TypeToken.of(Interface1.class));
-    assertThat(types.interfaces().rawTypes()).has().item(Interface1.class);
+    assertThat(types).contains(TypeToken.of(Interface1.class));
+    assertThat(types.rawTypes()).contains(Interface1.class);
+    assertThat(types.interfaces()).contains(TypeToken.of(Interface1.class));
+    assertThat(types.interfaces().rawTypes()).contains(Interface1.class);
     assertThat(types.classes()).isEmpty();
     assertThat(types.classes().rawTypes()).isEmpty();
   }
 
   public void testGetTypes_fromPrimitive() {
     TypeToken<Integer>.TypeSet types = TypeToken.of(int.class).getTypes();
-    assertThat(types).has().item(TypeToken.of(int.class));
-    assertThat(types.rawTypes()).has().item(int.class);
+    assertThat(types).contains(TypeToken.of(int.class));
+    assertThat(types.rawTypes()).contains(int.class);
     assertThat(types.interfaces()).isEmpty();
     assertThat(types.interfaces().rawTypes()).isEmpty();
-    assertThat(types.classes()).has().item(TypeToken.of(int.class));
-    assertThat(types.classes().rawTypes()).has().item(int.class);
+    assertThat(types.classes()).contains(TypeToken.of(int.class));
+    assertThat(types.classes().rawTypes()).contains(int.class);
   }
 
   public void testGetTypes_withInterfacesAndSuperclasses() {
     abstract class Class2 extends Class1 implements Interface12 {}
     abstract class Class3<T> extends Class2 implements Interface3<T> {}
     TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
-    makeUnmodifiable(types).has().exactly(
+    makeUnmodifiable(types).containsExactly(
         new TypeToken<Class3<String>>() {},
         new TypeToken<Interface3<String>>() {},
         new TypeToken<Iterable<String>>() {},
@@ -202,13 +203,13 @@ public class TypeTokenTest extends TestCase {
         TypeToken.of(Interface2.class),
         TypeToken.of(Class1.class),
         TypeToken.of(Object.class));
-    makeUnmodifiable(types.interfaces()).has().exactly(
+    makeUnmodifiable(types.interfaces()).containsExactly(
         new TypeToken<Interface3<String>>() {},
         TypeToken.of(Interface12.class),
         TypeToken.of(Interface1.class),
         TypeToken.of(Interface2.class),
         new TypeToken<Iterable<String>>() {});
-    makeUnmodifiable(types.classes()).has().exactly(
+    makeUnmodifiable(types.classes()).containsExactly(
         new TypeToken<Class3<String>>() {},
         TypeToken.of(Class2.class),
         TypeToken.of(Class1.class),
@@ -220,7 +221,7 @@ public class TypeTokenTest extends TestCase {
     abstract class Class2 extends Class1 implements Interface12 {}
     abstract class Class3<T> extends Class2 implements Interface3<T> {}
     TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
-    makeUnmodifiable(types.rawTypes()).has().exactly(
+    makeUnmodifiable(types.rawTypes()).containsExactly(
         Class3.class, Interface3.class,
         Iterable.class,
         Class2.class,
@@ -229,13 +230,13 @@ public class TypeTokenTest extends TestCase {
         Interface2.class,
         Class1.class,
         Object.class);
-    makeUnmodifiable(types.interfaces().rawTypes()).has().exactly(
+    makeUnmodifiable(types.interfaces().rawTypes()).containsExactly(
         Interface3.class,
         Interface12.class,
         Interface1.class,
         Interface2.class,
         Iterable.class);
-    makeUnmodifiable(types.classes().rawTypes()).has().exactly(
+    makeUnmodifiable(types.classes().rawTypes()).containsExactly(
         Class3.class,
         Class2.class,
         Class1.class,
@@ -246,15 +247,13 @@ public class TypeTokenTest extends TestCase {
   public <A extends Class1 & Interface1, B extends A>
   void testGetTypes_ignoresTypeVariablesByDefault() {
     TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
-    makeUnmodifiable(types).has().exactly(
+    makeUnmodifiable(types).containsExactly(
         TypeToken.of(Interface1.class), TypeToken.of(Class1.class),
         TypeToken.of(Object.class));
     assertSubtypeFirst(types);
-    makeUnmodifiable(types.interfaces())
-        .has().exactly(TypeToken.of(Interface1.class))
-        .inOrder();
+    makeUnmodifiable(types.interfaces()).containsExactly(TypeToken.of(Interface1.class));
     makeUnmodifiable(types.classes())
-        .has().exactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
+        .containsExactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
         .inOrder();
   }
 
@@ -262,12 +261,10 @@ public class TypeTokenTest extends TestCase {
   void testGetTypes_rawTypes_ignoresTypeVariablesByDefault() {
     TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
     makeUnmodifiable(types.rawTypes())
-        .has().exactly(Interface1.class, Class1.class, Object.class);
-    makeUnmodifiable(types.interfaces().rawTypes())
-        .has().exactly(Interface1.class)
-        .inOrder();
+        .containsExactly(Interface1.class, Class1.class, Object.class);
+    makeUnmodifiable(types.interfaces().rawTypes()).containsExactly(Interface1.class);
     makeUnmodifiable(types.classes().rawTypes())
-        .has().exactly(Class1.class, Object.class)
+        .containsExactly(Class1.class, Object.class)
         .inOrder();
   }
 
@@ -275,7 +272,7 @@ public class TypeTokenTest extends TestCase {
   void testGetTypes_manyBounds() {
     TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<A>() {}.capture()).getTypes();
     makeUnmodifiable(types.rawTypes())
-        .has().exactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
+        .containsExactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
   }
 
   private static void assertSubtypeFirst(TypeToken<?>.TypeSet types) {
@@ -293,7 +290,7 @@ public class TypeTokenTest extends TestCase {
     for (TypeToken<?> left : types) {
       int j = 0;
       for (TypeToken<?> right : types) {
-        if (left.isAssignableFrom(right)) {
+        if (left.isSupertypeOf(right)) {
           assertTrue(left + " should be after " + right, i >= j);
         }
         j++;
@@ -477,28 +474,28 @@ public class TypeTokenTest extends TestCase {
   public <T extends NoInterface&Iterable<String>>
   void testGetGenericInterfaces_typeVariable_boundsAreClassWithInterface() {
     makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
-        .has().exactly(new TypeToken<Iterable<String>>() {});
+        .containsExactly(new TypeToken<Iterable<String>>() {});
     assertHasArrayInterfaces(new TypeToken<T[]>() {});
   }
 
   public <T extends CharSequence&Iterable<String>>
   void testGetGenericInterfaces_typeVariable_boundsAreInterfaces() {
     makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
-        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
+        .containsExactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
     assertHasArrayInterfaces(new TypeToken<T[]>() {});
   }
 
   public <T extends CharSequence&Iterable<T>>
   void testGetGenericInterfaces_typeVariable_boundsAreFBoundedInterfaces() {
     makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
-        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
+        .containsExactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
     assertHasArrayInterfaces(new TypeToken<T[]>() {});
   }
 
   public <T extends Base&Iterable<T>>
   void testGetGenericInterfaces_typeVariable_boundsAreClassWithFBoundedInterface() {
     makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
-        .has().exactly(new TypeToken<Iterable<T>>() {});
+        .containsExactly(new TypeToken<Iterable<T>>() {});
     assertHasArrayInterfaces(new TypeToken<T[]>() {});
   }
 
@@ -511,7 +508,7 @@ public class TypeTokenTest extends TestCase {
   public <T extends Iterable<T>, T1 extends T, T2 extends T1>
   void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndInterface() {
     makeUnmodifiable(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces())
-        .has().exactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
+        .containsExactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
     assertHasArrayInterfaces(new TypeToken<T2[]>() {});
   }
 
@@ -528,7 +525,7 @@ public class TypeTokenTest extends TestCase {
   public void testGetGenericInterfaces_wildcard_boundIsInterface() {
     TypeToken<Iterable<String>> interfaceType = new TypeToken<Iterable<String>>() {};
     makeUnmodifiable(TypeToken.of(Types.subtypeOf(interfaceType.getType())).getGenericInterfaces())
-        .has().exactly(interfaceType);
+        .containsExactly(interfaceType);
     assertHasArrayInterfaces(new TypeToken<Iterable<String>[]>() {});
   }
 
@@ -539,8 +536,8 @@ public class TypeTokenTest extends TestCase {
 
   public void testGetGenericInterfaces_withInterfaces() {
     Map<Class<?>, Type> interfaceMap = Maps.newHashMap();
-    for (TypeToken<?> interfaceType:
-        new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
+    for (TypeToken<?> interfaceType
+        : new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
       interfaceMap.put(interfaceType.getRawType(), interfaceType.getType());
     }
     assertEquals(ImmutableMap.of(
@@ -575,171 +572,228 @@ public class TypeTokenTest extends TestCase {
   public void testAssignableClassToClass() {
     @SuppressWarnings("rawtypes") // To test TypeToken<List>
     TypeToken<List> tokL = new TypeToken<List>() {};
-    assertTrue(tokL.isAssignableFrom(List.class));
-    assertTrue(tokL.isAssignableFrom(ArrayList.class));
-    assertFalse(tokL.isAssignableFrom(List[].class));
+    assertTrue(tokL.isSupertypeOf(List.class));
+    assertTrue(tokL.isSupertypeOf(ArrayList.class));
+    assertFalse(tokL.isSupertypeOf(List[].class));
 
     TypeToken<Number> tokN = new TypeToken<Number>() {};
-    assertTrue(tokN.isAssignableFrom(Number.class));
-    assertTrue(tokN.isAssignableFrom(Integer.class));
+    assertTrue(tokN.isSupertypeOf(Number.class));
+    assertTrue(tokN.isSupertypeOf(Integer.class));
   }
 
   public <T> void testAssignableParameterizedTypeToObject() {
-    assertTrue(TypeToken.of(Object.class).isAssignableFrom(
+    assertTrue(TypeToken.of(Object.class).isSupertypeOf(
         TypeToken.of(new TypeCapture<T>() {}.capture())));
-    assertFalse(TypeToken.of(int.class).isAssignableFrom(
+    assertFalse(TypeToken.of(int.class).isSupertypeOf(
         TypeToken.of(new TypeCapture<T>() {}.capture())));
   }
 
   public <T, T1 extends T> void testAssignableGenericArrayToGenericArray() {
-    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[]>() {}));
-    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T1[]>() {}));
-    assertFalse(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[][]>() {}));
+    assertTrue(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T[]>() {}));
+    assertTrue(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T1[]>() {}));
+    assertFalse(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T[][]>() {}));
+  }
+
+  public <T, T1 extends T> void testAssignableGenericArrayToClass() {
+    assertTrue(TypeToken.of(Object[].class.getSuperclass())
+        .isSupertypeOf(new TypeToken<T[]>() {}));
+    for (Class<?> interfaceType : Object[].class.getInterfaces()) {
+      assertTrue(TypeToken.of(interfaceType)
+          .isSupertypeOf(new TypeToken<T[]>() {}));
+    }
+    assertTrue(TypeToken.of(Object.class).isSupertypeOf(new TypeToken<T[]>() {}));
+    assertFalse(TypeToken.of(String.class).isSupertypeOf(new TypeToken<T[]>() {}));
   }
 
-  public void testAssignableWildcardBoundedByArrayToArrayClass() throws Exception {
+  public void testAssignableWildcardBoundedByArrayToArrayClass() {
     Type wildcardType = Types.subtypeOf(Object[].class);
-    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
-    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
-    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
-    assertFalse(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
+    assertTrue(TypeToken.of(Object[].class).isSupertypeOf(wildcardType));
+    assertTrue(TypeToken.of(Object.class).isSupertypeOf(wildcardType));
+    assertFalse(TypeToken.of(wildcardType).isSupertypeOf(wildcardType));
+    assertFalse(TypeToken.of(int[].class).isSupertypeOf(wildcardType));
+  }
+
+  public void testAssignableWildcardTypeParameterToClassTypeParameter() {
+    TypeToken<?> wildcardType = new TypeToken<Iterable<? extends Object[]>>() {};
+    assertFalse(new TypeToken<Iterable<Object[]>>() {}.isSupertypeOf(wildcardType));
+    assertFalse(new TypeToken<Iterable<Object>>() {}.isSupertypeOf(wildcardType));
+    assertTrue(wildcardType.isSupertypeOf(wildcardType));
+    assertFalse(new TypeToken<Iterable<int[]>>() {}.isSupertypeOf(wildcardType));
+  }
+
+  public void testAssignableArrayClassToBoundedWildcard() {
+    TypeToken<?> subtypeOfArray = TypeToken.of(Types.subtypeOf(Object[].class));
+    TypeToken<?> supertypeOfArray = TypeToken.of(Types.supertypeOf(Object[].class));
+    assertFalse(subtypeOfArray.isSupertypeOf(Object[].class));
+    assertFalse(subtypeOfArray.isSupertypeOf(Object[][].class));
+    assertFalse(subtypeOfArray.isSupertypeOf(String[].class));
+    assertTrue(supertypeOfArray.isSupertypeOf(Object[].class));
+    assertFalse(supertypeOfArray.isSupertypeOf(Object.class));
+    assertTrue(supertypeOfArray.isSupertypeOf(Object[][].class));
+    assertTrue(supertypeOfArray.isSupertypeOf(String[].class));
+  }
+
+  public void testAssignableClassTypeParameterToWildcardTypeParameter() {
+    TypeToken<?> subtypeOfArray = new TypeToken<Iterable<? extends Object[]>>() {};
+    TypeToken<?> supertypeOfArray = new TypeToken<Iterable<? super Object[]>>() {};
+    assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[]>>() {}));
+    assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[][]>>() {}));
+    assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<String[]>>() {}));
+    assertTrue(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[]>>() {}));
+    assertTrue(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object>>() {}));
+    assertFalse(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[][]>>() {}));
+    assertFalse(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<String[]>>() {}));
+  }
+
+  public void testAssignableNonParameterizedClassToWildcard() {
+    TypeToken<?> supertypeOfString = TypeToken.of(Types.supertypeOf(String.class));
+    assertFalse(supertypeOfString.isSupertypeOf(supertypeOfString));
+    assertFalse(supertypeOfString.isSupertypeOf(Object.class));
+    assertFalse(supertypeOfString.isSupertypeOf(CharSequence.class));
+    assertTrue(supertypeOfString.isSupertypeOf(String.class));
+    assertTrue(supertypeOfString.isSupertypeOf(Types.subtypeOf(String.class)));
+  }
+
+  public void testAssignableWildcardBoundedByIntArrayToArrayClass() {
+    Type wildcardType = Types.subtypeOf(int[].class);
+    assertTrue(TypeToken.of(int[].class).isSupertypeOf(wildcardType));
+    assertTrue(TypeToken.of(Object.class).isSupertypeOf(wildcardType));
+    assertFalse(TypeToken.of(wildcardType).isSupertypeOf(wildcardType));
+    assertFalse(TypeToken.of(Object[].class).isSupertypeOf(wildcardType));
   }
 
-  public void testAssignableArrayClassToBoundedWildcard() throws Exception {
-    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
-    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
-    assertTrue(upperBounded.isAssignableFrom(Object[].class));
-    assertTrue(upperBounded.isAssignableFrom(Object[][].class));
-    assertTrue(upperBounded.isAssignableFrom(String[].class));
-    assertTrue(lowerBounded.isAssignableFrom(Object[].class));
-    assertTrue(lowerBounded.isAssignableFrom(Object.class));
-    assertFalse(lowerBounded.isAssignableFrom(Object[][].class));
-    assertFalse(lowerBounded.isAssignableFrom(String[].class));
+  public void testAssignableWildcardTypeParameterBoundedByIntArrayToArrayClassTypeParameter() {
+    TypeToken<?> wildcardType = new TypeToken<Iterable<? extends int[]>>() {};
+    assertFalse(new TypeToken<Iterable<int[]>>() {}.isSupertypeOf(wildcardType));
+    assertFalse(new TypeToken<Iterable<Object>>() {}.isSupertypeOf(wildcardType));
+    assertTrue(wildcardType.isSupertypeOf(wildcardType));
+    assertFalse(new TypeToken<Iterable<Object[]>>() {}.isSupertypeOf(wildcardType));
   }
 
-  public void testAssignableWildcardBoundedByIntArrayToArrayClass() throws Exception {
-    Type wildcardType = Types.subtypeOf(int[].class);
-    assertTrue(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
-    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
-    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
-    assertFalse(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
+  public void testAssignableWildcardToWildcard() {
+    TypeToken<?> subtypeOfArray = TypeToken.of(Types.subtypeOf(Object[].class));
+    TypeToken<?> supertypeOfArray = TypeToken.of(Types.supertypeOf(Object[].class));
+    assertTrue(supertypeOfArray.isSupertypeOf(subtypeOfArray));
+    assertFalse(supertypeOfArray.isSupertypeOf(supertypeOfArray));
+    assertFalse(subtypeOfArray.isSupertypeOf(subtypeOfArray));
+    assertFalse(subtypeOfArray.isSupertypeOf(supertypeOfArray));
   }
 
-  public void testAssignableWildcardToWildcard() throws Exception {
-    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
-    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
-    assertFalse(lowerBounded.isAssignableFrom(upperBounded));
-    assertTrue(lowerBounded.isAssignableFrom(lowerBounded));
-    assertTrue(upperBounded.isAssignableFrom(upperBounded));
-    assertFalse(upperBounded.isAssignableFrom(lowerBounded));
+  public void testAssignableWildcardTypeParameterToWildcardTypeParameter() {
+    TypeToken<?> subtypeOfArray = new TypeToken<Iterable<? extends Object[]>>() {};
+    TypeToken<?> supertypeOfArray = new TypeToken<Iterable<? super Object[]>>() {};
+    assertFalse(supertypeOfArray.isSupertypeOf(subtypeOfArray));
+    assertTrue(supertypeOfArray.isSupertypeOf(supertypeOfArray));
+    assertTrue(subtypeOfArray.isSupertypeOf(subtypeOfArray));
+    assertFalse(subtypeOfArray.isSupertypeOf(supertypeOfArray));
   }
 
   public <T> void testAssignableGenericArrayToArrayClass() {
-    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[]>() {}));
-    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[][]>() {}));
-    assertTrue(TypeToken.of(Object[][].class).isAssignableFrom(new TypeToken<T[][]>() {}));
+    assertTrue(TypeToken.of(Object[].class).isSupertypeOf(new TypeToken<T[]>() {}));
+    assertTrue(TypeToken.of(Object[].class).isSupertypeOf(new TypeToken<T[][]>() {}));
+    assertTrue(TypeToken.of(Object[][].class).isSupertypeOf(new TypeToken<T[][]>() {}));
   }
 
   public void testAssignableParameterizedTypeToClass() {
     @SuppressWarnings("rawtypes") // Trying to test raw class
     TypeToken<List> tokL = new TypeToken<List>() {};
-    assertTrue(tokL.isAssignableFrom(StringList.class));
-    assertTrue(tokL.isAssignableFrom(
+    assertTrue(tokL.isSupertypeOf(StringList.class));
+    assertTrue(tokL.isSupertypeOf(
         StringList.class.getGenericInterfaces()[0]));
 
     @SuppressWarnings("rawtypes") // Trying to test raw class
     TypeToken<Second> tokS = new TypeToken<Second>() {};
-    assertTrue(tokS.isAssignableFrom(Second.class));
-    assertTrue(tokS.isAssignableFrom(Third.class.getGenericSuperclass()));
+    assertTrue(tokS.isSupertypeOf(Second.class));
+    assertTrue(tokS.isSupertypeOf(Third.class.getGenericSuperclass()));
   }
 
-  public void testAssignableArrayToClass() throws Exception {
+  public void testAssignableArrayToClass() {
     @SuppressWarnings("rawtypes") // Trying to test raw class
     TypeToken<List[]> tokL = new TypeToken<List[]>() {};
-    assertTrue(tokL.isAssignableFrom(List[].class));
-    assertFalse(tokL.isAssignableFrom(List.class));
+    assertTrue(tokL.isSupertypeOf(List[].class));
+    assertFalse(tokL.isSupertypeOf(List.class));
 
     @SuppressWarnings("rawtypes") // Trying to test raw class
     TypeToken<Second[]> tokS = new TypeToken<Second[]>() {};
-    assertTrue(tokS.isAssignableFrom(Second[].class));
-    assertTrue(tokS.isAssignableFrom(Third[].class));
+    assertTrue(tokS.isSupertypeOf(Second[].class));
+    assertTrue(tokS.isSupertypeOf(Third[].class));
   }
 
   @SuppressWarnings("rawtypes") // Trying to test raw class
   public void testAssignableTokenToClass() {
     TypeToken<List> tokL = new TypeToken<List>() {};
-    assertTrue(tokL.isAssignableFrom(new TypeToken<List>() {}));
-    assertTrue(tokL.isAssignableFrom(new TypeToken<List<String>>() {}));
-    assertTrue(tokL.isAssignableFrom(new TypeToken<List<?>>() {}));
+    assertTrue(tokL.isSupertypeOf(new TypeToken<List>() {}));
+    assertTrue(tokL.isSupertypeOf(new TypeToken<List<String>>() {}));
+    assertTrue(tokL.isSupertypeOf(new TypeToken<List<?>>() {}));
 
     TypeToken<Second> tokS = new TypeToken<Second>() {};
-    assertTrue(tokS.isAssignableFrom(new TypeToken<Second>() {}));
-    assertTrue(tokS.isAssignableFrom(new TypeToken<Third>() {}));
-    assertTrue(tokS.isAssignableFrom(
+    assertTrue(tokS.isSupertypeOf(new TypeToken<Second>() {}));
+    assertTrue(tokS.isSupertypeOf(new TypeToken<Third>() {}));
+    assertTrue(tokS.isSupertypeOf(
         new TypeToken<Third<String, Integer>>() {}));
 
     TypeToken<List[]> tokA = new TypeToken<List[]>() {};
-    assertTrue(tokA.isAssignableFrom(new TypeToken<List[]>() {}));
-    assertTrue(tokA.isAssignableFrom(new TypeToken<List<String>[]>() {}));
-    assertTrue(tokA.isAssignableFrom(new TypeToken<List<?>[]>() {}));
+    assertTrue(tokA.isSupertypeOf(new TypeToken<List[]>() {}));
+    assertTrue(tokA.isSupertypeOf(new TypeToken<List<String>[]>() {}));
+    assertTrue(tokA.isSupertypeOf(new TypeToken<List<?>[]>() {}));
   }
 
   public void testAssignableClassToType() {
     TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
-    assertTrue(tokenL.isAssignableFrom(StringList.class));
-    assertFalse(tokenL.isAssignableFrom(List.class));
+    assertTrue(tokenL.isSupertypeOf(StringList.class));
+    assertFalse(tokenL.isSupertypeOf(List.class));
 
     TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
-    assertTrue(tokenF.isAssignableFrom(ConcreteIS.class));
-    assertFalse(tokenF.isAssignableFrom(ConcreteSI.class));
+    assertTrue(tokenF.isSupertypeOf(ConcreteIS.class));
+    assertFalse(tokenF.isSupertypeOf(ConcreteSI.class));
   }
 
   public void testAssignableClassToArrayType() {
     TypeToken<List<String>[]> tokenL = new TypeToken<List<String>[]>() {};
-    assertTrue(tokenL.isAssignableFrom(StringList[].class));
-    assertFalse(tokenL.isAssignableFrom(List[].class));
+    assertTrue(tokenL.isSupertypeOf(StringList[].class));
+    assertFalse(tokenL.isSupertypeOf(List[].class));
   }
 
   public void testAssignableParameterizedTypeToType() {
     TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
-    assertTrue(tokenL.isAssignableFrom(
+    assertTrue(tokenL.isSupertypeOf(
         StringList.class.getGenericInterfaces()[0]));
-    assertFalse(tokenL.isAssignableFrom(
+    assertFalse(tokenL.isSupertypeOf(
         IntegerList.class.getGenericInterfaces()[0]));
 
     TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
-    assertTrue(tokenF.isAssignableFrom(
+    assertTrue(tokenF.isSupertypeOf(
         ConcreteIS.class.getGenericSuperclass()));
-    assertFalse(tokenF.isAssignableFrom(
+    assertFalse(tokenF.isSupertypeOf(
         ConcreteSI.class.getGenericSuperclass()));
   }
 
-  public void testGenericArrayTypeToArrayType() throws Exception {
+  public void testGenericArrayTypeToArrayType() {
     TypeToken<List<String>[]> tokL = new TypeToken<List<String>[]>() {};
     TypeToken<ArrayList<String>[]> token =
         new TypeToken<ArrayList<String>[]>() {};
-    assertTrue(tokL.isAssignableFrom(tokL.getType()));
-    assertTrue(tokL.isAssignableFrom(token.getType()));
+    assertTrue(tokL.isSupertypeOf(tokL.getType()));
+    assertTrue(tokL.isSupertypeOf(token.getType()));
   }
 
   public void testAssignableTokenToType() {
     TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
-    assertTrue(tokenL.isAssignableFrom(new TypeToken<List<String>>() {}));
-    assertTrue(tokenL.isAssignableFrom(new TypeToken<ArrayList<String>>() {}));
-    assertTrue(tokenL.isAssignableFrom(new TypeToken<StringList>() {}));
+    assertTrue(tokenL.isSupertypeOf(new TypeToken<List<String>>() {}));
+    assertTrue(tokenL.isSupertypeOf(new TypeToken<ArrayList<String>>() {}));
+    assertTrue(tokenL.isSupertypeOf(new TypeToken<StringList>() {}));
 
     TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
-    assertTrue(tokenF.isAssignableFrom(new TypeToken<Second<String>>() {}));
-    assertTrue(tokenF.isAssignableFrom(
+    assertTrue(tokenF.isSupertypeOf(new TypeToken<Second<String>>() {}));
+    assertTrue(tokenF.isSupertypeOf(
         new TypeToken<Third<String, Integer>>() {}));
-    assertFalse(tokenF.isAssignableFrom(
+    assertFalse(tokenF.isSupertypeOf(
         new TypeToken<Third<Integer, String>>() {}));
-    assertTrue(tokenF.isAssignableFrom(
+    assertTrue(tokenF.isSupertypeOf(
         new TypeToken<Fourth<Integer, String>>() {}));
-    assertFalse(tokenF.isAssignableFrom(
+    assertFalse(tokenF.isSupertypeOf(
         new TypeToken<Fourth<String, Integer>>() {}));
-    assertTrue(tokenF.isAssignableFrom(new TypeToken<ConcreteIS>() {}));
-    assertFalse(tokenF.isAssignableFrom(new TypeToken<ConcreteSI>() {}));
+    assertTrue(tokenF.isSupertypeOf(new TypeToken<ConcreteIS>() {}));
+    assertFalse(tokenF.isSupertypeOf(new TypeToken<ConcreteSI>() {}));
   }
 
   public void testAssignableWithWildcards() {
@@ -754,41 +808,41 @@ public class TypeTokenTest extends TestCase {
         concreteToken, subtypeToken, supertypeToken);
 
     for (TypeToken<?> typeToken : allTokens) {
-      assertTrue(typeToken.toString(), unboundedToken.isAssignableFrom(typeToken));
+      assertTrue(typeToken.toString(), unboundedToken.isSupertypeOf(typeToken));
     }
 
-    assertFalse(upperBoundToken.isAssignableFrom(unboundedToken));
-    assertTrue(upperBoundToken.isAssignableFrom(upperBoundToken));
-    assertFalse(upperBoundToken.isAssignableFrom(lowerBoundToken));
-    assertTrue(upperBoundToken.isAssignableFrom(concreteToken));
-    assertTrue(upperBoundToken.isAssignableFrom(subtypeToken));
-    assertFalse(upperBoundToken.isAssignableFrom(supertypeToken));
+    assertFalse(upperBoundToken.isSupertypeOf(unboundedToken));
+    assertTrue(upperBoundToken.isSupertypeOf(upperBoundToken));
+    assertFalse(upperBoundToken.isSupertypeOf(lowerBoundToken));
+    assertTrue(upperBoundToken.isSupertypeOf(concreteToken));
+    assertTrue(upperBoundToken.isSupertypeOf(subtypeToken));
+    assertFalse(upperBoundToken.isSupertypeOf(supertypeToken));
 
-    assertFalse(lowerBoundToken.isAssignableFrom(unboundedToken));
-    assertFalse(lowerBoundToken.isAssignableFrom(upperBoundToken));
-    assertTrue(lowerBoundToken.isAssignableFrom(lowerBoundToken));
-    assertTrue(lowerBoundToken.isAssignableFrom(concreteToken));
-    assertFalse(lowerBoundToken.isAssignableFrom(subtypeToken));
-    assertTrue(lowerBoundToken.isAssignableFrom(supertypeToken));
+    assertFalse(lowerBoundToken.isSupertypeOf(unboundedToken));
+    assertFalse(lowerBoundToken.isSupertypeOf(upperBoundToken));
+    assertTrue(lowerBoundToken.isSupertypeOf(lowerBoundToken));
+    assertTrue(lowerBoundToken.isSupertypeOf(concreteToken));
+    assertFalse(lowerBoundToken.isSupertypeOf(subtypeToken));
+    assertTrue(lowerBoundToken.isSupertypeOf(supertypeToken));
 
     for (TypeToken<?> typeToken : allTokens) {
       assertEquals(typeToken.toString(),
-          typeToken == concreteToken, concreteToken.isAssignableFrom(typeToken));
+          typeToken == concreteToken, concreteToken.isSupertypeOf(typeToken));
     }
 
     for (TypeToken<?> typeToken : allTokens) {
       assertEquals(typeToken.toString(),
-          typeToken == subtypeToken, subtypeToken.isAssignableFrom(typeToken));
+          typeToken == subtypeToken, subtypeToken.isSupertypeOf(typeToken));
     }
 
     for (TypeToken<?> typeToken : allTokens) {
       assertEquals(typeToken.toString(),
-          typeToken == supertypeToken, supertypeToken.isAssignableFrom(typeToken));
+          typeToken == supertypeToken, supertypeToken.isSupertypeOf(typeToken));
     }
   }
 
   public <N1 extends Number, N2 extends Number, N11 extends N1>
-      void testIsAssignableFrom_typeVariable() {
+      void testisSupertypeOf_typeVariable() {
     assertAssignable(TypeToken.of(new TypeCapture<N1>() {}.capture()),
         TypeToken.of(new TypeCapture<N1>() {}.capture()));
     assertNotAssignable(new TypeToken<List<N11>>() {},
@@ -802,7 +856,7 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <N1 extends Number, N2 extends Number, N11 extends N1>
-      void testIsAssignableFrom_equalWildcardTypes() {
+      void testisSupertypeOf_equalWildcardTypes() {
     assertAssignable(new TypeToken<List<? extends N1>>() {},
         new TypeToken<List<? extends N1>>() {});
     assertAssignable(new TypeToken<List<? super N1>>() {},
@@ -813,7 +867,7 @@ public class TypeTokenTest extends TestCase {
         new TypeToken<List<? super Number>>() {});
   }
 
-  public <N> void testIsAssignableFrom_wildcard_noBound() {
+  public <N> void testisSupertypeOf_wildcard_noBound() {
     assertAssignable(new TypeToken<List<? super N>>() {},
         new TypeToken<List<?>>() {});
     assertAssignable(new TypeToken<List<N>>() {},
@@ -821,7 +875,7 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <N1 extends Number, N2 extends Number, N11 extends N1>
-      void testIsAssignableFrom_wildcardType_upperBoundMatch() {
+      void testisSupertypeOf_wildcardType_upperBoundMatch() {
     // ? extends T
     assertAssignable(new TypeToken<List<N11>>() {},
         new TypeToken<List<? extends N1>>() {});
@@ -840,7 +894,7 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <N1 extends Number, N2 extends Number, N11 extends N1>
-      void testIsAssignableFrom_wildcardType_lowerBoundMatch() {
+      void testisSupertypeOf_wildcardType_lowerBoundMatch() {
     // ? super T
     assertAssignable(new TypeToken<List<N1>>() {},
         new TypeToken<List<? super N11>>() {});
@@ -863,7 +917,7 @@ public class TypeTokenTest extends TestCase {
   }
 
   public <L extends List<R>, R extends List<L>>
-      void testIsAssignableFrom_recursiveTypeVariableBounds() {
+      void testisSupertypeOf_recursiveTypeVariableBounds() {
     assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
         TypeToken.of(new TypeCapture<L>() {}.capture()));
     assertNotAssignable(TypeToken.of(new TypeCapture<R>() {}.capture()),
@@ -872,7 +926,7 @@ public class TypeTokenTest extends TestCase {
         new TypeToken<List<R>>() {});
   }
 
-  public void testIsAssignableFrom_resolved() {
+  public void testisSupertypeOf_resolved() {
     assertFalse(Assignability.of().isAssignable());
     assertTrue(new Assignability<Integer, Integer>() {}.isAssignable());
     assertTrue(new Assignability<Integer, Object>() {}.isAssignable());
@@ -880,6 +934,14 @@ public class TypeTokenTest extends TestCase {
     TypeTokenTest.<Number, Integer>assignabilityTestWithTypeVariables();
   }
 
+  public <From extends String&List<? extends String>>
+  void testMultipleTypeBoundsAssignability() {
+    assertTrue(new Assignability<From, String>() {}.isAssignable());
+    assertFalse(new Assignability<From, Number>() {}.isAssignable());
+    assertTrue(new Assignability<From, Iterable<? extends CharSequence>>() {}.isAssignable());
+    assertFalse(new Assignability<From, Iterable<Object>>() {}.isAssignable());
+  }
+
   private static <N1 extends Number, N11 extends N1>
       void assignabilityTestWithTypeVariables() {
     assertTrue(new Assignability<N11, N1>() {}.isAssignable());
@@ -908,7 +970,7 @@ public class TypeTokenTest extends TestCase {
     assertTrue(new TypeToken<T[][]>() {}.isArray());
   }
 
-  public void testIsArray_wildcardType() throws Exception {
+  public void testIsArray_wildcardType() {
     assertTrue(TypeToken.of(Types.subtypeOf(Object[].class)).isArray());
     assertTrue(TypeToken.of(Types.subtypeOf(int[].class)).isArray());
     assertFalse(TypeToken.of(Types.subtypeOf(Object.class)).isArray());
@@ -951,7 +1013,7 @@ public class TypeTokenTest extends TestCase {
     assertEquals(new TypeToken<T[]>() {}, new TypeToken<T[][]>() {}.getComponentType());
   }
 
-  public void testGetComponentType_wildcardType() throws Exception {
+  public void testGetComponentType_wildcardType() {
     assertEquals(Types.subtypeOf(Object.class),
         TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType());
     assertEquals(Types.subtypeOf(Object[].class),
@@ -1003,6 +1065,14 @@ public class TypeTokenTest extends TestCase {
         TypeToken.of(ListIterable.class).getSupertype(Iterable.class).getType());
   }
 
+  public <A, T extends Number&Iterable<A>>
+  void testGetSupertype_typeVariableWithMultipleBounds() {
+    assertEquals(Number.class,
+        new TypeToken<T>(getClass()) {}.getSupertype(Number.class).getType());
+    assertEquals(new TypeToken<Iterable<A>>() {},
+        new TypeToken<T>(getClass()) {}.getSupertype(Iterable.class));
+  }
+
   public void testGetSupertype_withoutTypeVariable() {
     ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
         Types.newParameterizedType(List.class, String.class));
@@ -1160,6 +1230,121 @@ public class TypeTokenTest extends TestCase {
         new TypeToken<Iterable<String>[]>() {}.getSubtype(List[].class));
   }
 
+  private static class ForGetSubType {
+  
+    private abstract static class TwoTypeArgs<K, V> {
+      class InnerType<K2, V2> {}
+    }
+
+    private abstract static class StringForFirstTypeArg<V> extends TwoTypeArgs<String, V> {
+      class StringInnerType<V> extends InnerType<String, V> {}
+    }
+
+    private abstract static class OuterTypeVar<V>
+        extends StringForFirstTypeArg<List<V>> {}
+
+    private abstract static class SingleGenericExtendsBase<T> extends Base {}
+    
+    private abstract static class DoubleGenericExtendsSingleGeneric<T1, T2>
+        extends SingleGenericExtendsBase<T1> {}
+  
+    private interface FourTypeArgs<T1, T2, T3, T4> {}
+    private interface ThreeTypeArgs<T1, T2, T3> extends FourTypeArgs<T1, T2, T3, String> {}
+  
+    static class BaseWithTypeVar<T> {}
+    static class Outer<O> {
+      class Sub<X> extends BaseWithTypeVar<List<X>> {}
+      class Sub2<Y extends Sub2<Y>> extends BaseWithTypeVar<List<Y>> {}
+    }
+  }
+
+  public void testGetSubtype_toWildcard() {
+    TypeToken<ForGetSubType.TwoTypeArgs<?, ?>> superType =
+        new TypeToken<ForGetSubType.TwoTypeArgs<?, ?>>() {};
+    TypeToken<ForGetSubType.StringForFirstTypeArg<String>> subType =
+        new TypeToken<ForGetSubType.StringForFirstTypeArg<String>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    assertEquals(new TypeToken<ForGetSubType.StringForFirstTypeArg<?>>() {},
+        superType.getSubtype(subType.getRawType()));
+  }
+
+  public void testGetSubtype_innerTypeOfGenericClassTranslatesOwnerTypeVars() {
+    TypeToken<ForGetSubType.TwoTypeArgs<?, ?>.InnerType<?, ?>> superType =
+        new TypeToken<ForGetSubType.TwoTypeArgs<?, ?>.InnerType<?, ?>>() {};
+    TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>.StringInnerType<Long>> subType =
+        new TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>.StringInnerType<Long>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    TypeToken<ForGetSubType.StringForFirstTypeArg<?>.StringInnerType<?>> expected =
+        new TypeToken<ForGetSubType.StringForFirstTypeArg<?>.StringInnerType<?>>() {};
+    assertEquals(expected, superType.getSubtype(subType.getRawType()));
+  }
+
+  public void testGetSubtype_localTypeTranslatesTypeVar() {
+    class LocalType<T> extends ForGetSubType.TwoTypeArgs<String, String> {}
+
+    TypeToken<ForGetSubType.TwoTypeArgs<String, String>> superType =
+        new TypeToken<ForGetSubType.TwoTypeArgs<String, String>>() {};
+    TypeToken<LocalType<Integer>> subType = new TypeToken<LocalType<Integer>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    assertEquals(new TypeToken<LocalType<?>>() {}, superType.getSubtype(subType.getRawType()));
+  }
+
+  public void testGetSubtype_outerTypeVarTranslatesInnerTypeVar() {
+    TypeToken<ForGetSubType.StringForFirstTypeArg<List<?>>> type =
+        new TypeToken<ForGetSubType.StringForFirstTypeArg<List<?>>>() {};
+    assertEquals(new TypeToken<ForGetSubType.OuterTypeVar<?>>() {},
+        type.getSubtype(ForGetSubType.OuterTypeVar.class));
+  }
+  
+  public void testGetSubtype_toWildcardWithBounds() {
+    TypeToken<ForGetSubType.TwoTypeArgs<?, ? extends Number>> superType =
+        new TypeToken<ForGetSubType.TwoTypeArgs<?, ? extends Number>>() {};
+    TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>> subType =
+        new TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+
+    // TODO(benyu): This should check equality to an expected value, see discussion in cl/98674873
+    superType.getSubtype(subType.getRawType());
+  }
+  
+  public void testGetSubtype_baseClassWithNoTypeArgs() {
+    TypeToken<Base> superType = new TypeToken<Base>() {};
+    TypeToken<ForGetSubType.SingleGenericExtendsBase<String>> subType =
+        new TypeToken<ForGetSubType.SingleGenericExtendsBase<String>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    assertEquals(TypeToken.of(ForGetSubType.SingleGenericExtendsBase.class),
+        superType.getSubtype(subType.getRawType()));
+  }
+
+  public void testGetSubtype_baseClassWithLessTypeArgs() {
+    TypeToken<ForGetSubType.SingleGenericExtendsBase<?>> superType =
+        new TypeToken<ForGetSubType.SingleGenericExtendsBase<?>>() {};
+    TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<String, Integer>> subType =
+        new TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<String, Integer>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    assertEquals(new TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<?, ?>>() {},
+        superType.getSubtype(subType.getRawType()));
+  }
+
+  public <T> void testGetSubtype_manyGenericArgs() {
+    TypeToken<ForGetSubType.FourTypeArgs<T, Integer, ?, ?>> superType =
+        new TypeToken<ForGetSubType.FourTypeArgs<T, Integer, ?, ?>>() {};
+    TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, String>> subType =
+        new TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, String>>() {};
+    assertTrue(subType.isSubtypeOf(superType));
+    assertEquals(new TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, ?>>() {},
+        superType.getSubtype(subType.getRawType()));
+  }
+
+  public void testGetSubtype_recursiveTypeBoundInSubTypeTranslatedAsIs() {
+    assertEquals(new TypeToken<ForGetSubType.Outer<?>.Sub<?>>() {},
+        new TypeToken<ForGetSubType.BaseWithTypeVar<List<?>>>() {}
+            .getSubtype(ForGetSubType.Outer.Sub.class));
+    // This returns a strange ? extends Sub2<Y> type, which isn't ideal.
+    new TypeToken<ForGetSubType.BaseWithTypeVar<List<?>>>() {}
+        .getSubtype(ForGetSubType.Outer.Sub2.class);
+  }
+
   @SuppressWarnings("unchecked") // To construct TypeToken<T> with TypeToken.of()
   public <T> void testWhere_circleRejected() {
     TypeToken<List<T>> type = new TypeToken<List<T>>() {};
@@ -1195,7 +1380,7 @@ public class TypeTokenTest extends TestCase {
         Holder.class.getDeclaredMethod("setList", List.class).getGenericParameterTypes()[0]);
     assertEquals(List.class, parameterType.getRawType());
     assertFalse(parameterType.getType().toString(),
-        parameterType.isAssignableFrom(new TypeToken<List<Integer>>() {}));
+        parameterType.isSupertypeOf(new TypeToken<List<Integer>>() {}));
   }
 
   public void testWildcardCaptured_field_upperBound() throws Exception {
@@ -1277,7 +1462,7 @@ public class TypeTokenTest extends TestCase {
       throws NoSuchMethodException {
     Method failMethod = Loser.class.getMethod("lose");
     Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(failMethod);
-    assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
+    assertThat(invokable.getExceptionTypes()).contains(TypeToken.of(AssertionError.class));
   }
 
   public void testConstructor_getOwnerType() throws NoSuchMethodException {
@@ -1343,7 +1528,7 @@ public class TypeTokenTest extends TestCase {
     @SuppressWarnings("rawtypes") // Reflection API skew
     Constructor<CannotConstruct> constructor = CannotConstruct.class.getConstructor();
     Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
-    assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
+    assertThat(invokable.getExceptionTypes()).contains(TypeToken.of(AssertionError.class));
   }
 
   public void testRejectTypeVariable_class() {
@@ -1429,20 +1614,22 @@ public class TypeTokenTest extends TestCase {
 
     static void verifyConsitentRawType() {
       for (Method method : RawTypeConsistencyTester.class.getDeclaredMethods()) {
-        assertEquals(method.getReturnType(), TypeToken.getRawType(method.getGenericReturnType()));
+        assertEquals(method.getReturnType(),
+            TypeToken.of(method.getGenericReturnType()).getRawType());
         for (int i = 0; i < method.getParameterTypes().length; i++) {
           assertEquals(method.getParameterTypes()[i],
-              TypeToken.getRawType(method.getGenericParameterTypes()[i]));
+              TypeToken.of(method.getGenericParameterTypes()[i]).getRawType());
         }
       }
     }
   }
 
-  public void testRawTypes() throws Exception {
+  public void testRawTypes() {
     RawTypeConsistencyTester.verifyConsitentRawType();
-    assertEquals(Object.class, TypeToken.getRawType(Types.subtypeOf(Object.class)));
-    assertEquals(CharSequence.class, TypeToken.getRawType(Types.subtypeOf(CharSequence.class)));
-    assertEquals(Object.class, TypeToken.getRawType(Types.supertypeOf(CharSequence.class)));
+    assertEquals(Object.class, TypeToken.of(Types.subtypeOf(Object.class)).getRawType());
+    assertEquals(CharSequence.class,
+        TypeToken.of(Types.subtypeOf(CharSequence.class)).getRawType());
+    assertEquals(Object.class, TypeToken.of(Types.supertypeOf(CharSequence.class)).getRawType());
   }
 
   private abstract static class IKnowMyType<T> {
@@ -1597,7 +1784,7 @@ public class TypeTokenTest extends TestCase {
   private static class Assignability<From, To> {
 
     boolean isAssignable() {
-      return new TypeToken<To>(getClass()) {}.isAssignableFrom(new TypeToken<From>(getClass()) {});
+      return new TypeToken<To>(getClass()) {}.isSupertypeOf(new TypeToken<From>(getClass()) {});
     }
 
     static <From, To> Assignability<From, To> of() {
@@ -1609,12 +1796,24 @@ public class TypeTokenTest extends TestCase {
     assertTrue(
         from.getType() + " is expected to be assignable to " + to.getType(),
         to.isAssignableFrom(from));
+    assertTrue(
+        to.getType() + " is expected to be a supertype of " + from.getType(),
+        to.isSupertypeOf(from));
+    assertTrue(
+        from.getType() + " is expected to be a subtype of " + to.getType(),
+        from.isSubtypeOf(to));
   }
 
   private static void assertNotAssignable(TypeToken<?> from, TypeToken<?> to) {
     assertFalse(
         from.getType() + " shouldn't be assignable to " + to.getType(),
         to.isAssignableFrom(from));
+    assertFalse(
+        to.getType() + " shouldn't be a supertype of " + from.getType(),
+        to.isSupertypeOf(from));
+    assertFalse(
+        from.getType() + " shouldn't be a subtype of " + to.getType(),
+        from.isSubtypeOf(to));
   }
 
   private static void assertHasArrayInterfaces(TypeToken<?> arrayType) {
@@ -1658,7 +1857,7 @@ public class TypeTokenTest extends TestCase {
   private static class Base implements BaseInterface {}
   private static class Sub extends Base {}
 
-  private static CollectionSubject<?, Object, ?> makeUnmodifiable(Collection<?> actual) {
+  private static IterableSubject<?, Object, ?> makeUnmodifiable(Collection<?> actual) {
     return assertThat(Collections.<Object>unmodifiableCollection(actual));
   }
 }
diff --git a/guava-tests/test/com/google/common/reflect/TypesTest.java b/guava-tests/test/com/google/common/reflect/TypesTest.java
index 8e223bc..65841b9 100644
--- a/guava-tests/test/com/google/common/reflect/TypesTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypesTest.java
@@ -43,8 +43,8 @@ import java.util.Map;
  *
  * @author Ben Yu
  */
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
 public class TypesTest extends TestCase {
-
   public void testNewParameterizedType_ownerTypeImplied() throws Exception {
     ParameterizedType jvmType = (ParameterizedType)
         new TypeCapture<Map.Entry<String, Integer>>() {}.capture();
@@ -66,12 +66,12 @@ public class TypesTest extends TestCase {
     assertEquals(jvmType.toString(), ourType.toString());
     assertEquals(jvmType.hashCode(), ourType.hashCode());
     assertEquals(HashMap.class, ourType.getRawType());
-    assertThat(ourType.getActualTypeArguments()).asList()
-        .has().exactlyAs(asList(jvmType.getActualTypeArguments())).inOrder();
-    assertEquals(Arrays.asList(
-            String.class,
-            Types.newArrayType(Types.newArrayType(int.class))),
-        Arrays.asList(ourType.getActualTypeArguments()));
+    assertThat(ourType.getActualTypeArguments())
+        .asList()
+        .containsExactlyElementsIn(asList(jvmType.getActualTypeArguments()))
+        .inOrder();
+    assertEquals(Arrays.asList(String.class, Types.newArrayType(Types.newArrayType(int.class))),
+                 Arrays.asList(ourType.getActualTypeArguments()));
     assertEquals(null, ourType.getOwnerType());
   }
 
@@ -107,8 +107,10 @@ public class TypesTest extends TestCase {
     assertEquals(jvmType.toString(), ourType.toString());
     assertEquals(Map.class, ourType.getOwnerType());
     assertEquals(Map.Entry.class, ourType.getRawType());
-    assertThat(ourType.getActualTypeArguments()).asList()
-        .has().exactlyAs(asList(jvmType.getActualTypeArguments())).inOrder();
+    assertThat(ourType.getActualTypeArguments())
+        .asList()
+        .containsExactlyElementsIn(asList(jvmType.getActualTypeArguments()))
+        .inOrder();
   }
 
   public void testNewParameterizedType_serializable() {
@@ -268,10 +270,14 @@ public class TypesTest extends TestCase {
       WildcardType expected, WildcardType actual) {
     assertEquals(expected.toString(), actual.toString());
     assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
-    assertThat(actual.getLowerBounds()).asList()
-        .has().exactlyAs(asList(expected.getLowerBounds())).inOrder();
-    assertThat(actual.getUpperBounds()).asList()
-        .has().exactlyAs(asList(expected.getUpperBounds())).inOrder();
+    assertThat(actual.getLowerBounds())
+        .asList()
+        .containsExactlyElementsIn(asList(expected.getLowerBounds()))
+        .inOrder();
+    assertThat(actual.getUpperBounds())
+        .asList()
+        .containsExactlyElementsIn(asList(expected.getUpperBounds()))
+        .inOrder();
   }
 
   private static class WithTypeVariable {
@@ -366,8 +372,10 @@ public class TypesTest extends TestCase {
     if (!Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
       assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
     }
-    assertThat(actual.getBounds()).asList()
-        .has().exactlyAs(asList(expected.getBounds())).inOrder();
+    assertThat(actual.getBounds())
+        .asList()
+        .containsExactlyElementsIn(asList(expected.getBounds()))
+        .inOrder();
   }
 
   /**
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java
new file mode 100644
index 0000000..2170c85
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Runnables.doNothing;
+import static com.google.common.util.concurrent.TestPlatform.verifyGetOnPendingFuture;
+import static com.google.common.util.concurrent.TestPlatform.verifyTimedGetOnPendingFuture;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a
+ * different "source Future" for {@link AbstractFuture#setFuture} calls.
+ */
+ at GwtCompatible
+abstract class AbstractAbstractFutureTest extends TestCase {
+  private TestedFuture<Integer> future;
+  private AbstractFuture<Integer> delegate;
+
+  abstract AbstractFuture<Integer> newDelegate();
+
+  @Override
+  protected void setUp() {
+    future = TestedFuture.create();
+    delegate = newDelegate();
+  }
+
+  public void testPending() {
+    assertPending(future);
+  }
+
+  public void testSuccessful() throws Exception {
+    assertThat(future.set(1)).isTrue();
+    assertSuccessful(future, 1);
+  }
+
+  public void testFailed() throws Exception {
+    Exception cause = new Exception();
+    assertThat(future.setException(cause)).isTrue();
+    assertFailed(future, cause);
+  }
+
+  public void testCanceled() throws Exception {
+    assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
+    assertCancelled(future, false);
+  }
+
+  public void testInterrupted() throws Exception {
+    assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
+    assertCancelled(future, true);
+  }
+
+  public void testSetFuturePending() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    assertSetAsynchronously(future);
+  }
+
+  public void testSetFutureThenCancel() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
+    assertCancelled(future, false);
+    assertCancelled(delegate, false);
+  }
+
+  public void testSetFutureThenInterrupt() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
+    assertCancelled(future, true);
+    assertCancelled(delegate, true);
+  }
+
+  public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+    delegate.set(5);
+    assertThat(future.setFuture(delegate)).isTrue();
+    assertSuccessful(future, 5);
+  }
+
+  public void testSetFutureDelegateLaterSuccessful() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    delegate.set(6);
+    assertSuccessful(future, 6);
+  }
+
+  public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+    delegate.cancel(false /** mayInterruptIfRunning */);
+    assertThat(future.setFuture(delegate)).isTrue();
+    assertCancelled(future, false);
+  }
+
+  public void testSetFutureDelegateLaterCancelled() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    delegate.cancel(false /** mayInterruptIfRunning */);
+    assertCancelled(future, false);
+  }
+
+  public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+    delegate.cancel(true /** mayInterruptIfRunning */);
+    assertThat(future.setFuture(delegate)).isTrue();
+    /*
+     * Interruption of the delegate propagates to us only if the delegate was a TrustedFuture.
+     * TODO(cpovirk): Consider whether to stop copying this information from TrustedFuture so that
+     * we're consistent.
+     */
+    assertCancelled(future, delegate instanceof TrustedFuture);
+  }
+
+  public void testSetFutureDelegateLaterInterrupted() throws Exception {
+    assertThat(future.setFuture(delegate)).isTrue();
+    delegate.cancel(true /** mayInterruptIfRunning */);
+    // See previous method doc.
+    assertCancelled(future, delegate instanceof TrustedFuture);
+  }
+
+  public void testListenLaterSuccessful() {
+    CountingRunnable listener = new CountingRunnable();
+
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    future.set(1);
+    listener.assertRun();
+  }
+
+  public void testListenLaterFailed() {
+    CountingRunnable listener = new CountingRunnable();
+
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    future.setException(new Exception());
+    listener.assertRun();
+  }
+
+  public void testListenLaterCancelled() {
+    CountingRunnable listener = new CountingRunnable();
+
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    future.cancel(false);
+    listener.assertRun();
+  }
+
+  public void testListenLaterInterrupted() {
+    CountingRunnable listener = new CountingRunnable();
+
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    future.cancel(true);
+    listener.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronously() {
+    CountingRunnable listener = new CountingRunnable();
+
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    future.setFuture(delegate);
+    listener.assertNotRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    delegate.set(1);
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterDelegateFailed() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    delegate.setException(new Exception());
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    delegate.cancel(false);
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    delegate.cancel(true);
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterSelfCancelled() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    future.cancel(false);
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() {
+    CountingRunnable before = new CountingRunnable();
+    CountingRunnable inBetween = new CountingRunnable();
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.setFuture(delegate);
+    future.addListener(inBetween, directExecutor());
+    future.cancel(true);
+    future.addListener(after, directExecutor());
+
+    before.assertRun();
+    inBetween.assertRun();
+    after.assertRun();
+  }
+
+  public void testMisbehavingListenerAlreadyDone() {
+    class BadRunnableException extends RuntimeException {
+    }
+
+    Runnable bad = new Runnable() {
+      @Override
+      public void run() {
+        throw new BadRunnableException();
+      }
+    };
+
+    future.set(1);
+    future.addListener(bad, directExecutor()); // BadRunnableException must not propagate.
+  }
+
+  public void testMisbehavingListenerLaterDone() {
+    class BadRunnableException extends RuntimeException {
+    }
+
+    CountingRunnable before = new CountingRunnable();
+    Runnable bad = new Runnable() {
+      @Override
+      public void run() {
+        throw new BadRunnableException();
+      }
+    };
+    CountingRunnable after = new CountingRunnable();
+
+    future.addListener(before, directExecutor());
+    future.addListener(bad, directExecutor());
+    future.addListener(after, directExecutor());
+
+    future.set(1); // BadRunnableException must not propagate.
+
+    before.assertRun();
+    after.assertRun();
+  }
+
+  public void testNullListener() {
+    try {
+      future.addListener(null, directExecutor());
+      fail();
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  public void testNullExecutor() {
+    try {
+      future.addListener(doNothing(), null);
+      fail();
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  public void testNullTimeUnit() throws Exception {
+    future.set(1);
+    try {
+      future.get(0, null);
+      fail();
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  public void testSetNull() throws Exception {
+    future.set(null);
+    assertSuccessful(future, null);
+  }
+
+  public void testSetExceptionNull() throws Exception {
+    try {
+      future.setException(null);
+      fail();
+    } catch (NullPointerException expected) {
+    }
+
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.set(1)).isTrue();
+    assertSuccessful(future, 1);
+  }
+
+  public void testSetFutureNull() throws Exception {
+    try {
+      future.setFuture(null);
+      fail();
+    } catch (NullPointerException expected) {
+    }
+
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.set(1)).isTrue();
+    assertSuccessful(future, 1);
+  }
+
+  /**
+   * Concrete subclass for testing.
+   */
+  private static class TestedFuture<V> extends AbstractFuture<V> {
+    private static <V> TestedFuture<V> create() {
+      return new TestedFuture<V>();
+    }
+  }
+
+  private static final class CountingRunnable implements Runnable {
+    int count;
+
+    @Override
+    public void run() {
+      count++;
+    }
+
+    void assertNotRun() {
+      assertEquals(0, count);
+    }
+
+    void assertRun() {
+      assertEquals(1, count);
+    }
+  }
+
+  private static void assertSetAsynchronously(AbstractFuture<Integer> future) {
+    assertCannotSet(future);
+    assertPending(future);
+  }
+
+  private static void assertPending(AbstractFuture<Integer> future) {
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.isCancelled()).isFalse();
+
+    CountingRunnable listener = new CountingRunnable();
+    future.addListener(listener, directExecutor());
+    listener.assertNotRun();
+
+    verifyGetOnPendingFuture(future);
+    verifyTimedGetOnPendingFuture(future);
+  }
+
+  private static void assertSuccessful(AbstractFuture<Integer> future, Integer expectedResult)
+      throws InterruptedException, TimeoutException, ExecutionException {
+    assertDone(future);
+    assertThat(future.isCancelled()).isFalse();
+
+    assertThat(future.get()).isEqualTo(expectedResult);
+    assertThat(future.get(0, SECONDS)).isEqualTo(expectedResult);
+    assertThat(future.get(-1, SECONDS)).isEqualTo(expectedResult);
+  }
+
+  private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException)
+      throws InterruptedException, TimeoutException {
+    assertDone(future);
+    assertThat(future.isCancelled()).isFalse();
+
+    try {
+      future.get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isSameAs(expectedException);
+    }
+
+    try {
+      future.get(0, SECONDS);
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isSameAs(expectedException);
+    }
+  }
+
+  private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)
+      throws InterruptedException, TimeoutException, ExecutionException {
+    assertDone(future);
+    assertThat(future.isCancelled()).isTrue();
+    assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted);
+
+    try {
+      future.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
+
+    try {
+      future.get(0, SECONDS);
+      fail();
+    } catch (CancellationException expected) {
+    }
+  }
+
+  private static void assertDone(AbstractFuture<Integer> future) {
+    CountingRunnable listener = new CountingRunnable();
+    future.addListener(listener, directExecutor());
+    listener.assertRun();
+
+    assertThat(future.isDone()).isTrue();
+    assertCannotSet(future);
+    assertCannotCancel(future);
+  }
+
+  private static void assertCannotSet(AbstractFuture<Integer> future) {
+    assertThat(future.set(99)).isFalse();
+    assertThat(future.setException(new IndexOutOfBoundsException())).isFalse();
+    assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse();
+    assertThat(future.setFuture(immediateFuture(99))).isFalse();
+  }
+
+  private static void assertCannotCancel(AbstractFuture<Integer> future) {
+    assertThat(future.cancel(true)).isFalse();
+    assertThat(future.cancel(false)).isFalse();
+  }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
index b30d531..587ff26 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
@@ -16,8 +16,11 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.testing.TearDown;
 import com.google.common.testing.TearDownStack;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import junit.framework.TestCase;
 
@@ -26,6 +29,7 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -58,6 +62,8 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
 
   @Override protected final void tearDown() {
     tearDownStack.runTearDown();
+    assertNull("exceptions should not be propagated to uncaught exception handlers",
+        thrownByExecutionThread);
   }
 
   public void testServiceStartStop() throws Exception {
@@ -74,7 +80,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
     assertTrue(service.shutDownCalled);
     assertEquals(Service.State.TERMINATED, service.state());
     executionThread.join();
-    assertNull(thrownByExecutionThread);
   }
 
   public void testServiceStopIdempotence() throws Exception {
@@ -91,7 +96,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
     assertEquals(Service.State.TERMINATED, service.state());
 
     executionThread.join();
-    assertNull(thrownByExecutionThread);
   }
 
   public void testServiceExitingOnItsOwn() throws Exception {
@@ -107,7 +111,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
 
     assertTrue(service.shutDownCalled);
     assertEquals(Service.State.TERMINATED, service.state());
-    assertNull(thrownByExecutionThread);
 
     service.stopAsync().awaitTerminated(); // no-op
     assertEquals(Service.State.TERMINATED, service.state());
@@ -169,13 +172,13 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
       service.awaitRunning();
       fail();
     } catch (IllegalStateException expected) {
-      assertEquals("kaboom!", expected.getCause().getMessage());
+      assertThat(expected.getCause()).hasMessage("kaboom!");
     }
     executionThread.join();
 
     assertTrue(service.startUpCalled);
     assertEquals(Service.State.FAILED, service.state());
-    assertTrue(thrownByExecutionThread.getMessage().equals("kaboom!"));
+    assertThat(service.failureCause()).hasMessage("kaboom!");
   }
 
   private class ThrowOnStartUpService extends AbstractExecutionThreadService {
@@ -204,11 +207,11 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
       fail();
     } catch (IllegalStateException expected) {
       executionThread.join();
-      assertEquals(thrownByExecutionThread, expected.getCause());
+      assertEquals(service.failureCause(), expected.getCause());
+      assertThat(expected.getCause()).hasMessage("kaboom!");
     }
     assertTrue(service.shutDownCalled);
     assertEquals(Service.State.FAILED, service.state());
-    assertEquals("kaboom!", thrownByExecutionThread.getMessage());
   }
 
   public void testServiceThrowOnRunAndThenAgainOnShutDown() throws Exception {
@@ -221,12 +224,12 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
       fail();
     } catch (IllegalStateException expected) {
       executionThread.join();
-      assertEquals(thrownByExecutionThread, expected.getCause());
+      assertEquals(service.failureCause(), expected.getCause());
+      assertThat(expected.getCause()).hasMessage("kaboom!");
     }
 
     assertTrue(service.shutDownCalled);
     assertEquals(Service.State.FAILED, service.state());
-    assertEquals("kaboom!", thrownByExecutionThread.getMessage());
   }
 
   private class ThrowOnRunService extends AbstractExecutionThreadService {
@@ -260,7 +263,7 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
     executionThread.join();
 
     assertEquals(Service.State.FAILED, service.state());
-    assertEquals("kaboom!", thrownByExecutionThread.getMessage());
+    assertThat(service.failureCause()).hasMessage("kaboom!");
   }
 
   private class ThrowOnShutDown extends AbstractExecutionThreadService {
@@ -288,7 +291,7 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
       service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
       fail();
     } catch (TimeoutException e) {
-      assertTrue(e.getMessage().contains(Service.State.STARTING.toString()));
+      assertThat(e.getMessage()).contains(Service.State.STARTING.toString());
     }
   }
 
@@ -339,6 +342,27 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
     service.stopAsync().awaitTerminated();
   }
 
+  public void testTimeout() {
+    // Create a service whose executor will never run its commands
+    Service service = new AbstractExecutionThreadService() {
+      @Override protected void run() throws Exception {}
+
+      @Override protected ScheduledExecutorService executor() {
+        return TestingExecutors.noOpScheduledExecutor();
+      }
+
+      @Override protected String serviceName() {
+        return "Foo";
+      }
+    };
+    try {
+      service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
+      fail("Expected timeout");
+    } catch (TimeoutException e) {
+      assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
+    }
+  }
+
   private class FakeService extends AbstractExecutionThreadService implements TearDown {
 
     private final ExecutorService executor = Executors.newSingleThreadExecutor();
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java
new file mode 100644
index 0000000..fe48ff4
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utilities for the AbstractFutureBenchmarks
+ */
+final class AbstractFutureBenchmarks {
+  private AbstractFutureBenchmarks() {}
+
+  interface Facade<T> extends ListenableFuture<T> {
+    boolean set(T t);
+    boolean setException(Throwable t);
+  }
+
+  private static class NewAbstractFutureFacade<T> extends AbstractFuture<T> implements Facade<T> {
+    @Override public boolean set(T t) {
+      return super.set(t);
+    }
+    @Override public boolean setException(Throwable t) {
+      return super.setException(t);
+    }
+  }
+
+  private static class OldAbstractFutureFacade<T>
+      extends OldAbstractFuture<T> implements Facade<T> {
+    @Override public boolean set(T t) {
+      return super.set(t);
+    }
+    @Override public boolean setException(Throwable t) {
+      return super.setException(t);
+    }
+  }
+
+  enum Impl {
+    NEW {
+      @Override <T> Facade<T> newFacade() {
+        return new NewAbstractFutureFacade<T>();
+      }
+    },
+    OLD {
+      @Override <T> Facade<T> newFacade() {
+        return new OldAbstractFutureFacade<T>();
+      }
+    };
+
+    abstract <T> Facade<T> newFacade();
+  }
+
+  static void awaitWaiting(Thread t) {
+    while (true) {
+      Thread.State state = t.getState();
+      switch (state) {
+        case RUNNABLE:
+        case BLOCKED:
+          Thread.yield();
+          break;
+        case WAITING:
+          return;
+        default:
+          throw new AssertionError("unexpected state: " + state);
+      }
+    }
+  }
+
+  abstract static class OldAbstractFuture<V> implements ListenableFuture<V> {
+
+    /** Synchronization control for AbstractFutures. */
+    private final Sync<V> sync = new Sync<V>();
+
+    // The execution list to hold our executors.
+    private final ExecutionList executionList = new ExecutionList();
+
+    /**
+     * Constructor for use by subclasses.
+     */
+    protected OldAbstractFuture() {}
+
+    /*
+     * Improve the documentation of when InterruptedException is thrown. Our
+     * behavior matches the JDK's, but the JDK's documentation is misleading.
+     */
+    /**
+     * {@inheritDoc}
+     *
+     * <p>The default {@link AbstractFuture} implementation throws {@code
+     * InterruptedException} if the current thread is interrupted before or during
+     * the call, even if the value is already available.
+     *
+     * @throws InterruptedException if the current thread was interrupted before
+     *     or during the call (optional but recommended).
+     * @throws CancellationException {@inheritDoc}
+     */
+    @Override
+    public V get(long timeout, TimeUnit unit) throws InterruptedException,
+        TimeoutException, ExecutionException {
+      return sync.get(unit.toNanos(timeout));
+    }
+
+    /*
+     * Improve the documentation of when InterruptedException is thrown. Our
+     * behavior matches the JDK's, but the JDK's documentation is misleading.
+     */
+    /**
+     * {@inheritDoc}
+     *
+     * <p>The default {@link AbstractFuture} implementation throws {@code
+     * InterruptedException} if the current thread is interrupted before or during
+     * the call, even if the value is already available.
+     *
+     * @throws InterruptedException if the current thread was interrupted before
+     *     or during the call (optional but recommended).
+     * @throws CancellationException {@inheritDoc}
+     */
+    @Override
+    public V get() throws InterruptedException, ExecutionException {
+      return sync.get();
+    }
+
+    @Override
+    public boolean isDone() {
+      return sync.isDone();
+    }
+
+    @Override
+    public boolean isCancelled() {
+      return sync.isCancelled();
+    }
+
+    @Override
+    public boolean cancel(boolean mayInterruptIfRunning) {
+      if (!sync.cancel(mayInterruptIfRunning)) {
+        return false;
+      }
+      executionList.execute();
+      if (mayInterruptIfRunning) {
+        interruptTask();
+      }
+      return true;
+    }
+
+    /**
+     * Subclasses can override this method to implement interruption of the
+     * future's computation. The method is invoked automatically by a successful
+     * call to {@link #cancel(boolean) cancel(true)}.
+     *
+     * <p>The default implementation does nothing.
+     *
+     * @since 10.0
+     */
+    protected void interruptTask() {
+    }
+
+    /**
+     * Returns true if this future was cancelled with {@code
+     * mayInterruptIfRunning} set to {@code true}.
+     *
+     * @since 14.0
+     */
+    protected final boolean wasInterrupted() {
+      return sync.wasInterrupted();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 10.0
+     */
+    @Override
+    public void addListener(Runnable listener, Executor exec) {
+      executionList.add(listener, exec);
+    }
+
+    /**
+     * Subclasses should invoke this method to set the result of the computation
+     * to {@code value}.  This will set the state of the future to
+     * {@link OldAbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+     * state was successfully changed.
+     *
+     * @param value the value that was the result of the task.
+     * @return true if the state was successfully changed.
+     */
+    protected boolean set(@Nullable V value) {
+      boolean result = sync.set(value);
+      if (result) {
+        executionList.execute();
+      }
+      return result;
+    }
+
+    /**
+     * Subclasses should invoke this method to set the result of the computation
+     * to an error, {@code throwable}.  This will set the state of the future to
+     * {@link OldAbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+     * state was successfully changed.
+     *
+     * @param throwable the exception that the task failed with.
+     * @return true if the state was successfully changed.
+     */
+    protected boolean setException(Throwable throwable) {
+      boolean result = sync.setException(checkNotNull(throwable));
+      if (result) {
+        executionList.execute();
+      }
+      return result;
+    }
+
+    /**
+     * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a
+     * private subclass to hold the synchronizer.  This synchronizer is used to
+     * implement the blocking and waiting calls as well as to handle state changes
+     * in a thread-safe manner.  The current state of the future is held in the
+     * Sync state, and the lock is released whenever the state changes to
+     * {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}
+     *
+     * <p>To avoid races between threads doing release and acquire, we transition
+     * to the final state in two steps.  One thread will successfully CAS from
+     * RUNNING to COMPLETING, that thread will then set the result of the
+     * computation, and only then transition to COMPLETED, CANCELLED, or
+     * INTERRUPTED.
+     *
+     * <p>We don't use the integer argument passed between acquire methods so we
+     * pass around a -1 everywhere.
+     */
+    static final class Sync<V> extends AbstractQueuedSynchronizer {
+
+      private static final long serialVersionUID = 0L;
+
+      /* Valid states. */
+      static final int RUNNING = 0;
+      static final int COMPLETING = 1;
+      static final int COMPLETED = 2;
+      static final int CANCELLED = 4;
+      static final int INTERRUPTED = 8;
+
+      private V value;
+      private Throwable exception;
+
+      /*
+       * Acquisition succeeds if the future is done, otherwise it fails.
+       */
+      @Override
+      protected int tryAcquireShared(int ignored) {
+        if (isDone()) {
+          return 1;
+        }
+        return -1;
+      }
+
+      /*
+       * We always allow a release to go through, this means the state has been
+       * successfully changed and the result is available.
+       */
+      @Override
+      protected boolean tryReleaseShared(int finalState) {
+        setState(finalState);
+        return true;
+      }
+
+      /**
+       * Blocks until the task is complete or the timeout expires.  Throws a
+       * {@link TimeoutException} if the timer expires, otherwise behaves like
+       * {@link #get()}.
+       */
+      V get(long nanos) throws TimeoutException, CancellationException,
+          ExecutionException, InterruptedException {
+
+        // Attempt to acquire the shared lock with a timeout.
+        if (!tryAcquireSharedNanos(-1, nanos)) {
+          throw new TimeoutException("Timeout waiting for task.");
+        }
+
+        return getValue();
+      }
+
+      /**
+       * Blocks until {@link #complete(Object, Throwable, int)} has been
+       * successfully called.  Throws a {@link CancellationException} if the task
+       * was cancelled, or a {@link ExecutionException} if the task completed with
+       * an error.
+       */
+      V get() throws CancellationException, ExecutionException,
+          InterruptedException {
+
+        // Acquire the shared lock allowing interruption.
+        acquireSharedInterruptibly(-1);
+        return getValue();
+      }
+
+      /**
+       * Implementation of the actual value retrieval.  Will return the value
+       * on success, an exception on failure, a cancellation on cancellation, or
+       * an illegal state if the synchronizer is in an invalid state.
+       */
+      private V getValue() throws CancellationException, ExecutionException {
+        int state = getState();
+        switch (state) {
+          case COMPLETED:
+            if (exception != null) {
+              throw new ExecutionException(exception);
+            } else {
+              return value;
+            }
+
+          case CANCELLED:
+          case INTERRUPTED:
+            throw cancellationExceptionWithCause(
+                "Task was cancelled.", exception);
+
+          default:
+            throw new IllegalStateException(
+                "Error, synchronizer in invalid state: " + state);
+        }
+      }
+
+      /**
+       * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}.
+       */
+      boolean isDone() {
+        return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0;
+      }
+
+      /**
+       * Checks if the state is {@link #CANCELLED} or {@link #INTERRUPTED}.
+       */
+      boolean isCancelled() {
+        return (getState() & (CANCELLED | INTERRUPTED)) != 0;
+      }
+
+      /**
+       * Checks if the state is {@link #INTERRUPTED}.
+       */
+      boolean wasInterrupted() {
+        return getState() == INTERRUPTED;
+      }
+
+      /**
+       * Transition to the COMPLETED state and set the value.
+       */
+      boolean set(@Nullable V v) {
+        return complete(v, null, COMPLETED);
+      }
+
+      /**
+       * Transition to the COMPLETED state and set the exception.
+       */
+      boolean setException(Throwable t) {
+        return complete(null, t, COMPLETED);
+      }
+
+      /**
+       * Transition to the CANCELLED or INTERRUPTED state.
+       */
+      boolean cancel(boolean interrupt) {
+        return complete(null, null, interrupt ? INTERRUPTED : CANCELLED);
+      }
+
+      /**
+       * Implementation of completing a task.  Either {@code v} or {@code t} will
+       * be set but not both.  The {@code finalState} is the state to change to
+       * from {@link #RUNNING}.  If the state is not in the RUNNING state we
+       * return {@code false} after waiting for the state to be set to a valid
+       * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link
+       * #INTERRUPTED}).
+       *
+       * @param v the value to set as the result of the computation.
+       * @param t the exception to set as the result of the computation.
+       * @param finalState the state to transition to.
+       */
+      private boolean complete(@Nullable V v, @Nullable Throwable t,
+          int finalState) {
+        boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
+        if (doCompletion) {
+          // If this thread successfully transitioned to COMPLETING, set the value
+          // and exception and then release to the final state.
+          this.value = v;
+          // Don't actually construct a CancellationException until necessary.
+          this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0)
+              ? new CancellationException("Future.cancel() was called.") : t;
+          releaseShared(finalState);
+        } else if (getState() == COMPLETING) {
+          // If some other thread is currently completing the future, block until
+          // they are done so we can guarantee completion.
+          acquireShared(-1);
+        }
+        return doCompletion;
+      }
+    }
+
+    static final CancellationException cancellationExceptionWithCause(
+        @Nullable String message, @Nullable Throwable cause) {
+      CancellationException exception = new CancellationException(message);
+      exception.initCause(cause);
+      return exception;
+    }
+  }
+}
+
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
new file mode 100644
index 0000000..f24f340
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import junit.framework.TestCase;
+
+import java.net.URLClassLoader;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+
+/**
+ * Tests for {@link AbstractFuture} with the cancellation cause system property set
+ */
+
+public class AbstractFutureCancellationCauseTest extends TestCase {
+
+  private ClassLoader oldClassLoader;
+  private URLClassLoader classReloader;
+
+  @Override protected void setUp() throws Exception {
+    SettableFuture.create();
+    // Hack to load AbstractFuture et. al. in a new classloader so that it re-reads the cancellation
+    // cause system property.  This allows us to run with both settings of the property in one jvm
+    // without resorting to even crazier hacks to reset static final boolean fields.
+    System.setProperty("guava.concurrent.generate_cancellation_cause", "true");
+    final String concurrentPackage = SettableFuture.class.getPackage().getName();
+    classReloader =
+        new URLClassLoader(((URLClassLoader) SettableFuture.class.getClassLoader()).getURLs()) {
+          @Override public Class<?> loadClass(String name) throws ClassNotFoundException {
+            if (name.startsWith(concurrentPackage)) {
+              return super.findClass(name);
+            }
+            return super.loadClass(name);
+          }
+        };
+    oldClassLoader = Thread.currentThread().getContextClassLoader();
+    Thread.currentThread().setContextClassLoader(classReloader);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    classReloader.close();
+    Thread.currentThread().setContextClassLoader(oldClassLoader);
+    System.clearProperty("guava.concurrent.generate_cancellation_cause");
+  }
+
+  public void testCancel_notDoneNoInterrupt() throws Exception {
+    Future<?> future = newFutureInstance();
+    assertTrue(future.cancel(false));
+    assertTrue(future.isCancelled());
+    assertTrue(future.isDone());
+    try {
+      future.get();
+      fail("Expected CancellationException");
+    } catch (CancellationException e) {
+      assertNotNull(e.getCause());
+    }
+  }
+
+  public void testCancel_notDoneInterrupt() throws Exception {
+    Future<?> future = newFutureInstance();
+    assertTrue(future.cancel(true));
+    assertTrue(future.isCancelled());
+    assertTrue(future.isDone());
+    try {
+      future.get();
+      fail("Expected CancellationException");
+    } catch (CancellationException e) {
+      assertNotNull(e.getCause());
+    }
+  }
+
+  private Future<?> newFutureInstance() throws Exception {
+    return (Future<?>)
+        classReloader.loadClass(SettableFuture.class.getName()).getMethod("create").invoke(null);
+  }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java
new file mode 100644
index 0000000..fc0bcf2
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import com.google.common.collect.ImmutableSet;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URLClassLoader;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/**
+ * Tests our AtomicHelper fallback strategies in AbstractFuture.
+ *
+ * <p>On different platforms AbstractFuture uses different strategies for its core synchronization
+ * primitives.  The strategies are all implemented as subtypes of AtomicHelper and the strategy is
+ * selected in the static initializer of AbstractFuture.  This is convenient and performant but
+ * introduces some testing difficulties.   This test exercises the two fallback strategies in
+ * abstract future.
+ * <ul>
+ *     <li>SafeAtomicHelper: uses AtomicReferenceFieldsUpdaters to implement synchronization
+ *     <li>SynchronizedHelper: uses {@code synchronized} blocks for synchronization
+ * </ul>
+ *
+ * To force selection of our fallback strategies we load {@link AbstractFuture} (and all of
+ * {@code com.google.common.util.concurrent} in degenerate class loaders which make certain platform
+ * classes unavailable.  Then we construct a test suite so we can run the normal AbstractFutureTest
+ * test methods in these degenerate classloaders.
+ */
+
+public class AbstractFutureFallbackAtomicHelperTest extends TestCase {
+
+  // stash these in static fields to avoid loading them over and over again (speeds up test
+  // execution significantly)
+
+  /**
+   * This classloader blacklists sun.misc.Unsafe which will prevent us from selecting our preferred
+   * strategy {@code UnsafeAtomicHelper}.
+   */
+  private static final ClassLoader NO_UNSAFE =
+      getClassLoader(ImmutableSet.of(sun.misc.Unsafe.class.getName()));
+
+  /**
+   * This classloader blacklists sun.misc.Unsafe and AtomicReferenceFieldUpdater which will prevent
+   * us from selecting our {@code SafeAtomicHelper} strategy.
+   */
+  private static final ClassLoader NO_ATOMIC_REFERENCE_FIELD_UPDATER =
+      getClassLoader(
+          ImmutableSet.of(
+              sun.misc.Unsafe.class.getName(), AtomicReferenceFieldUpdater.class.getName()));
+
+  public static TestSuite suite() {
+    // we create a test suite containing a test for every AbstractFutureTest test method and we
+    // set it as the name of the test.  Then in runTest we can reflectively load and invoke the
+    // corresponding method on AbstractFutureTest in the correct classloader.
+    TestSuite suite = new TestSuite(AbstractFutureFallbackAtomicHelperTest.class.getName());
+    for (Method method : AbstractFutureTest.class.getDeclaredMethods()) {
+      if (Modifier.isPublic(method.getModifiers()) && method.getName().startsWith("test")) {
+        suite.addTest(
+            TestSuite.createTest(AbstractFutureFallbackAtomicHelperTest.class, method.getName()));
+      }
+    }
+    return suite;
+  }
+
+  @Override
+  public void runTest() throws Exception {
+    // First ensure that our classloaders are intializing the correct helper versions
+    checkHelperVersion(getClass().getClassLoader(), "UnsafeAtomicHelper");
+    checkHelperVersion(NO_UNSAFE, "SafeAtomicHelper");
+    checkHelperVersion(NO_ATOMIC_REFERENCE_FIELD_UPDATER, "SynchronizedHelper");
+
+    // Run the corresponding AbstractFutureTest test method in a new classloader that blacklists
+    // certain core jdk classes.
+    ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+    Thread.currentThread().setContextClassLoader(NO_UNSAFE);
+    try {
+      runTestMethod(NO_UNSAFE);
+    } finally {
+      Thread.currentThread().setContextClassLoader(oldClassLoader);
+    }
+
+    Thread.currentThread().setContextClassLoader(NO_ATOMIC_REFERENCE_FIELD_UPDATER);
+    try {
+      runTestMethod(NO_ATOMIC_REFERENCE_FIELD_UPDATER);
+      // TODO(lukes): assert that the logs are full of errors
+    } finally {
+      Thread.currentThread().setContextClassLoader(oldClassLoader);
+    }
+  }
+
+  private void runTestMethod(ClassLoader classLoader) throws Exception {
+    Class<?> test = classLoader.loadClass(AbstractFutureTest.class.getName());
+    test.getMethod(getName()).invoke(test.newInstance());
+  }
+
+  private void checkHelperVersion(ClassLoader classLoader, String expectedHelperClassName)
+      throws Exception {
+    // Make sure we are actually running with the expected helper implementation
+    Class<?> abstractFutureClass = classLoader.loadClass(AbstractFuture.class.getName());
+    Field helperField = abstractFutureClass.getDeclaredField("ATOMIC_HELPER");
+    helperField.setAccessible(true);
+    assertEquals(expectedHelperClassName, helperField.get(null).getClass().getSimpleName());
+  }
+
+  private static ClassLoader getClassLoader(final Set<String> blacklist) {
+    final String concurrentPackage = SettableFuture.class.getPackage().getName();
+    ClassLoader classLoader = AbstractFutureFallbackAtomicHelperTest.class.getClassLoader();
+    return
+    // we delegate to the current classloader so both loaders agree on classes like TestCase
+    new URLClassLoader(((URLClassLoader) classLoader).getURLs(), classLoader) {
+      @Override
+      public Class<?> loadClass(String name) throws ClassNotFoundException {
+        if (blacklist.contains(name)) {
+          throw new ClassNotFoundException("I'm sorry Dave, I'm afraid I can't do that.");
+        }
+        if (name.startsWith(concurrentPackage)) {
+          Class<?> c = findLoadedClass(name);
+          if (c == null) {
+            return super.findClass(name);
+          }
+          return c;
+        }
+        return super.loadClass(name);
+      }
+    };
+  }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
index 166be3d..f5c5ff0 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
@@ -18,14 +18,32 @@ package com.google.common.util.concurrent;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Range;
+import com.google.common.collect.Sets;
+
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.LockSupport;
 
 /**
  * Tests for {@link AbstractFuture}.
@@ -75,7 +93,8 @@ public class AbstractFutureTest extends TestCase {
       future.get();
       fail("Expected CancellationException");
     } catch (CancellationException e) {
-      assertNotNull(e.getCause());
+      // See AbstractFutureCancellationCauseTest for how to set causes
+      assertNull(e.getCause());
     }
   }
 
@@ -90,7 +109,8 @@ public class AbstractFutureTest extends TestCase {
       future.get();
       fail("Expected CancellationException");
     } catch (CancellationException e) {
-      assertNotNull(e.getCause());
+      // See AbstractFutureCancellationCauseTest for how to set causes
+      assertNull(e.getCause());
     }
   }
 
@@ -105,11 +125,86 @@ public class AbstractFutureTest extends TestCase {
     assertTrue(future.isDone());
   }
 
+  public void testGetWithTimeoutDoneFuture() throws Exception {
+    AbstractFuture<String> future = new AbstractFuture<String>() {
+      {
+        set("foo");
+      }
+    };
+    assertEquals("foo", future.get(0, TimeUnit.SECONDS));
+  }
+
+  public void testEvilFuture_setFuture() throws Exception {
+    final RuntimeException exception = new RuntimeException("you didn't say the magic word!");
+    AbstractFuture<String> evilFuture = new AbstractFuture<String>() {
+      @Override public void addListener(Runnable r, Executor e) {
+        throw exception;
+      }
+    };
+    AbstractFuture<String> normalFuture = new AbstractFuture<String>() {};
+    normalFuture.setFuture(evilFuture);
+    assertTrue(normalFuture.isDone());
+    try {
+      normalFuture.get();
+      fail();
+    } catch (ExecutionException e) {
+      assertSame(exception, e.getCause());
+    }
+  }
+
+  public void testRemoveWaiter_interruption() throws Exception {
+    final AbstractFuture<String> future = new AbstractFuture<String>() {};
+    WaiterThread waiter1 = new WaiterThread(future);
+    waiter1.start();
+    waiter1.awaitWaiting();
+
+    WaiterThread waiter2 = new WaiterThread(future);
+    waiter2.start();
+    waiter2.awaitWaiting();
+    // The waiter queue should be waiter2->waiter1
+
+    // This should wake up waiter1 and cause the waiter1 node to be removed.
+    waiter1.interrupt();
+
+    waiter1.join();
+    waiter2.awaitWaiting();  // should still be blocked
+
+    LockSupport.unpark(waiter2);  // spurious wakeup
+    waiter2.awaitWaiting();  // should eventually re-park
+
+    future.set(null);
+    waiter2.join();
+  }
+
+  public void testRemoveWaiter_polling() throws Exception {
+    final AbstractFuture<String> future = new AbstractFuture<String>() {};
+    WaiterThread waiter = new WaiterThread(future);
+    waiter.start();
+    waiter.awaitWaiting();
+    PollingThread poller = new PollingThread(future);
+    poller.start();
+    PollingThread poller2 = new PollingThread(future);
+    poller2.start();
+    PollingThread poller3 = new PollingThread(future);
+    poller3.start();
+    poller.awaitInLoop();
+    poller2.awaitInLoop();
+    poller3.awaitInLoop();
+
+    // The waiter queue should be {poller x 3}->waiter1
+    waiter.interrupt();
+
+    // This should wake up waiter1 and cause the waiter1 node to be removed.
+    waiter.join();
+    future.set(null);
+    poller.join();
+  }
+
   public void testCompletionFinishesWithDone() {
     ExecutorService executor = Executors.newFixedThreadPool(10);
     for (int i = 0; i < 50000; i++) {
       final AbstractFuture<String> future = new AbstractFuture<String>() {};
-      final AtomicReference<String> errorMessage = new AtomicReference<String>();
+      final AtomicReference<String> errorMessage = Atomics.newReference();
       executor.execute(new Runnable() {
         @Override
         public void run() {
@@ -148,6 +243,376 @@ public class AbstractFutureTest extends TestCase {
     executor.shutdown();
   }
 
+  /**
+   * He did the bash, he did the future bash
+   * The future bash, it was a concurrency smash
+   * He did the bash, it caught on in a flash
+   * He did the bash, he did the future bash
+   */
+  public void testFutureBash() {
+    final CyclicBarrier barrier = new CyclicBarrier(
+        6  // for the setter threads
+        + 50 // for the listeners
+        + 50 // for the blocking get threads,
+        + 1); // for the main thread
+    final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+    final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+    final AtomicInteger numSuccessfulSetCalls = new AtomicInteger();
+    Callable<Void> completeSucessFullyRunnable = new Callable<Void>() {
+      @Override public Void call() {
+        if (currentFuture.get().set("set")) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> completeExceptionallyRunnable = new Callable<Void>() {
+      Exception failureCause = new Exception("setException");
+      @Override public Void call() {
+        if (currentFuture.get().setException(failureCause)) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> cancelRunnable = new Callable<Void>() {
+      @Override public Void call() {
+        if (currentFuture.get().cancel(true)) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+      ListenableFuture<String> future = Futures.immediateFuture("setFuture");
+      @Override public Void call() {
+        if (currentFuture.get().setFuture(future)) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> setFutureCompleteExceptionallyRunnable = new Callable<Void>() {
+      ListenableFuture<String> future = Futures.immediateFailedFuture(new Exception("setFuture"));
+      @Override public Void call() {
+        if (currentFuture.get().setFuture(future)) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> setFutureCancelRunnable = new Callable<Void>() {
+      ListenableFuture<String> future = Futures.immediateCancelledFuture();
+      @Override public Void call() {
+        if (currentFuture.get().setFuture(future)) {
+          numSuccessfulSetCalls.incrementAndGet();
+        }
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+    Runnable collectResultsRunnable = new Runnable() {
+      @Override public void run() {
+        try {
+          String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+          finalResults.add(result);
+        } catch (ExecutionException e) {
+          finalResults.add(e.getCause());
+        } catch (CancellationException e) {
+          finalResults.add(e.getCause());
+        } finally {
+          awaitUnchecked(barrier);
+        }
+      }
+    };
+    Runnable collectResultsTimedGetRunnable = new Runnable() {
+      @Override public void run() {
+        Future<String> future = currentFuture.get();
+        while (true) {
+          try {
+            String result = Uninterruptibles.getUninterruptibly(future, 0, TimeUnit.SECONDS);
+            finalResults.add(result);
+            break;
+          } catch (ExecutionException e) {
+            finalResults.add(e.getCause());
+            break;
+          } catch (CancellationException e) {
+            finalResults.add(e.getCause());
+            break;
+          } catch (TimeoutException e) {
+            // loop
+          }
+        }
+        awaitUnchecked(barrier);
+      }
+    };
+    List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+    allTasks.add(completeSucessFullyRunnable);
+    allTasks.add(completeExceptionallyRunnable);
+    allTasks.add(cancelRunnable);
+    allTasks.add(setFutureCompleteSucessFullyRunnable);
+    allTasks.add(setFutureCompleteExceptionallyRunnable);
+    allTasks.add(setFutureCancelRunnable);
+    for (int k = 0; k < 50; k++) {
+      // For each listener we add a task that submits it to the executor directly for the blocking
+      // get usecase and another task that adds it as a listener to the future to exercise both
+      // racing addListener calls and addListener calls completing after the future completes.
+      final Runnable listener = k % 2 == 0
+          ? collectResultsRunnable
+          : collectResultsTimedGetRunnable;
+      allTasks.add(Executors.callable(listener));
+      allTasks.add(new Callable<Void>() {
+        @Override public Void call() throws Exception {
+          currentFuture.get().addListener(listener, executor);
+          return null;
+        }
+      });
+    }
+    assertEquals(allTasks.size() + 1, barrier.getParties());
+    for (int i = 0; i < 1000; i++) {
+      Collections.shuffle(allTasks);
+      final AbstractFuture<String> future = new AbstractFuture<String>() {};
+      currentFuture.set(future);
+      for (Callable<?> task : allTasks) {
+        executor.submit(task);
+      }
+      awaitUnchecked(barrier);
+      assertThat(future.isDone()).isTrue();
+      // inspect state and ensure it is correct!
+      // asserts that all get calling threads received the same value
+      Object result = Iterables.getOnlyElement(finalResults);
+      if (result instanceof CancellationException) {
+        assertTrue(future.isCancelled());
+        if (future.wasInterrupted()) {
+          // We were cancelled, it is possible that setFuture could have succeeded to.
+          assertThat(numSuccessfulSetCalls.get()).isIn(Range.closed(1, 2));
+        } else {
+          assertThat(numSuccessfulSetCalls.get()).isEqualTo(1);
+        }
+      } else {
+        assertThat(numSuccessfulSetCalls.get()).isEqualTo(1);
+      }
+      // reset for next iteration
+      numSuccessfulSetCalls.set(0);
+      finalResults.clear();
+    }
+    executor.shutdown();
+  }
+
+  // setFuture and cancel() interact in more complicated ways than the other setters.
+  public void testSetFutureCancelBash() {
+    final CyclicBarrier barrier = new CyclicBarrier(
+        2  // for the setter threads
+        + 50 // for the listeners
+        + 50 // for the blocking get threads,
+        + 1); // for the main thread
+    final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+    final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+    final AtomicReference<AbstractFuture<String>> setFutureFuture = Atomics.newReference();
+    final AtomicBoolean setFutureSetSucess = new AtomicBoolean();
+    final AtomicBoolean setFutureCompletionSucess = new AtomicBoolean();
+    final AtomicBoolean cancellationSucess = new AtomicBoolean();
+    Callable<Void> cancelRunnable = new Callable<Void>() {
+      @Override public Void call() {
+        cancellationSucess.set(currentFuture.get().cancel(true));
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+      @Override public Void call() {
+        AbstractFuture<String> future = setFutureFuture.get();
+        setFutureSetSucess.set(currentFuture.get().setFuture(future));
+        setFutureCompletionSucess.set(future.set("hello-async-world"));
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+    Runnable collectResultsRunnable = new Runnable() {
+      @Override public void run() {
+        try {
+          String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+          finalResults.add(result);
+        } catch (ExecutionException e) {
+          finalResults.add(e.getCause());
+        } catch (CancellationException e) {
+          finalResults.add(CancellationException.class);
+        } finally {
+          awaitUnchecked(barrier);
+        }
+      }
+    };
+    Runnable collectResultsTimedGetRunnable = new Runnable() {
+      @Override public void run() {
+        Future<String> future = currentFuture.get();
+        while (true) {
+          try {
+            String result = Uninterruptibles.getUninterruptibly(future, 0, TimeUnit.SECONDS);
+            finalResults.add(result);
+            break;
+          } catch (ExecutionException e) {
+            finalResults.add(e.getCause());
+            break;
+          } catch (CancellationException e) {
+            finalResults.add(CancellationException.class);
+            break;
+          } catch (TimeoutException e) {
+            // loop
+          }
+        }
+        awaitUnchecked(barrier);
+      }
+    };
+    List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+    allTasks.add(cancelRunnable);
+    allTasks.add(setFutureCompleteSucessFullyRunnable);
+    for (int k = 0; k < 50; k++) {
+      // For each listener we add a task that submits it to the executor directly for the blocking
+      // get usecase and another task that adds it as a listener to the future to exercise both
+      // racing addListener calls and addListener calls completing after the future completes.
+      final Runnable listener = k % 2 == 0
+          ? collectResultsRunnable
+          : collectResultsTimedGetRunnable;
+      allTasks.add(Executors.callable(listener));
+      allTasks.add(new Callable<Void>() {
+        @Override public Void call() throws Exception {
+          currentFuture.get().addListener(listener, executor);
+          return null;
+        }
+      });
+    }
+    assertEquals(allTasks.size() + 1, barrier.getParties());  // sanity check
+    for (int i = 0; i < 1000; i++) {
+      Collections.shuffle(allTasks);
+      final AbstractFuture<String> future = new AbstractFuture<String>() {};
+      final AbstractFuture<String> setFuture = new AbstractFuture<String>() {};
+      currentFuture.set(future);
+      setFutureFuture.set(setFuture);
+      for (Callable<?> task : allTasks) {
+        executor.submit(task);
+      }
+      awaitUnchecked(barrier);
+      assertThat(future.isDone()).isTrue();
+      // inspect state and ensure it is correct!
+      // asserts that all get calling threads received the same value
+      Object result = Iterables.getOnlyElement(finalResults);
+      if (result == CancellationException.class) {
+        assertTrue(future.isCancelled());
+        assertTrue(cancellationSucess.get());
+        // cancellation can interleave in 3 ways
+        // 1. prior to setFuture
+        // 2. after setFuture before set() on the future assigned
+        // 3. after setFuture and set() are called but before the listener completes.
+        if (!setFutureSetSucess.get() || !setFutureCompletionSucess.get()) {
+          // If setFuture fails or set on the future fails then it must be because that future was
+          // cancelled
+          assertTrue(setFuture.isCancelled());
+          assertTrue(setFuture.wasInterrupted());  // we only call cancel(true)
+        }
+      } else {
+        // set on the future completed
+        assertFalse(cancellationSucess.get());
+        assertTrue(setFutureSetSucess.get());
+        assertTrue(setFutureCompletionSucess.get());
+      }
+      // reset for next iteration
+      setFutureSetSucess.set(false);
+      setFutureCompletionSucess.set(false);
+      cancellationSucess.set(false);
+      finalResults.clear();
+    }
+    executor.shutdown();
+  }
+
+  // Test to ensure that when calling setFuture with a done future only setFuture or cancel can
+  // return true.
+  public void testSetFutureCancelBash_withDoneFuture() {
+    final CyclicBarrier barrier = new CyclicBarrier(
+        2  // for the setter threads
+        + 1 // for the blocking get thread,
+        + 1); // for the main thread
+    final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+    final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+    final AtomicBoolean setFutureSuccess = new AtomicBoolean();
+    final AtomicBoolean cancellationSucess = new AtomicBoolean();
+    Callable<Void> cancelRunnable = new Callable<Void>() {
+      @Override public Void call() {
+        cancellationSucess.set(currentFuture.get().cancel(true));
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+      final ListenableFuture<String> future = Futures.immediateFuture("hello");
+      @Override public Void call() {
+        setFutureSuccess.set(currentFuture.get().setFuture(future));
+        awaitUnchecked(barrier);
+        return null;
+      }
+    };
+    final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+    final Runnable collectResultsRunnable = new Runnable() {
+      @Override public void run() {
+        try {
+          String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+          finalResults.add(result);
+        } catch (ExecutionException e) {
+          finalResults.add(e.getCause());
+        } catch (CancellationException e) {
+          finalResults.add(CancellationException.class);
+        } finally {
+          awaitUnchecked(barrier);
+        }
+      }
+    };
+    List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+    allTasks.add(cancelRunnable);
+    allTasks.add(setFutureCompleteSucessFullyRunnable);
+    allTasks.add(Executors.callable(collectResultsRunnable));
+    assertEquals(allTasks.size() + 1, barrier.getParties());  // sanity check
+    for (int i = 0; i < 1000; i++) {
+      Collections.shuffle(allTasks);
+      final AbstractFuture<String> future = new AbstractFuture<String>() {};
+      currentFuture.set(future);
+      for (Callable<?> task : allTasks) {
+        executor.submit(task);
+      }
+      awaitUnchecked(barrier);
+      assertThat(future.isDone()).isTrue();
+      // inspect state and ensure it is correct!
+      // asserts that all get calling threads received the same value
+      Object result = Iterables.getOnlyElement(finalResults);
+      if (result == CancellationException.class) {
+        assertTrue(future.isCancelled());
+        assertTrue(cancellationSucess.get());
+        assertFalse(setFutureSuccess.get());
+      } else {
+        assertTrue(setFutureSuccess.get());
+        assertFalse(cancellationSucess.get());
+      }
+      // reset for next iteration
+      setFutureSuccess.set(false);
+      cancellationSucess.set(false);
+      finalResults.clear();
+    }
+    executor.shutdown();
+  }
+
+  private int awaitUnchecked(final CyclicBarrier barrier) {
+    try {
+      return barrier.await();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   private void checkStackTrace(ExecutionException e) {
     // Our call site for get() should be in the trace.
     int index = findStackFrame(
@@ -190,6 +655,61 @@ public class AbstractFutureTest extends TestCase {
     return null;
   }
 
+  private final class WaiterThread extends Thread {
+    private final AbstractFuture<String> future;
+
+    private WaiterThread(AbstractFuture<String> future) {
+      this.future = future;
+    }
+
+    @Override public void run() {
+      try {
+        future.get();
+      } catch (Exception e) {
+        // nothing
+      }
+    }
+
+    void awaitWaiting() {
+      while (LockSupport.getBlocker(this) != future) {
+        if (getState() == State.TERMINATED) {
+          throw new RuntimeException("Thread exited");
+        }
+        Thread.yield();
+      }
+    }
+  }
+
+  private final class PollingThread extends Thread {
+    private final AbstractFuture<String> future;
+    private final CountDownLatch completedIteration = new CountDownLatch(10);
+
+    private PollingThread(AbstractFuture<String> future) {
+      this.future = future;
+    }
+
+    @Override public void run() {
+      while (true) {
+        try {
+          future.get(0, TimeUnit.SECONDS);
+          return;
+        } catch (InterruptedException e) {
+          return;
+        } catch (ExecutionException e) {
+          return;
+        } catch (TimeoutException e) {
+          // do nothing
+        } finally {
+          completedIteration.countDown();
+        }
+      }
+    }
+
+    void awaitInLoop() {
+      Uninterruptibles.awaitUninterruptibly(completedIteration);
+    }
+  }
+
   private static final class InterruptibleFuture
       extends AbstractFuture<String> {
     boolean interruptTaskWasCalled;
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
index 2dfad5c..fbfa404 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
@@ -94,7 +94,7 @@ public class AbstractIdleServiceTest extends TestCase {
     service.startAsync().awaitRunning();
     assertEquals(1, service.startUpCalled);
     assertEquals(Service.State.RUNNING, service.state());
-    assertThat(service.transitionStates).has().exactly(Service.State.STARTING).inOrder();
+    assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
   }
 
   public void testStart_failed() {
@@ -114,7 +114,7 @@ public class AbstractIdleServiceTest extends TestCase {
     }
     assertEquals(1, service.startUpCalled);
     assertEquals(Service.State.FAILED, service.state());
-    assertThat(service.transitionStates).has().exactly(Service.State.STARTING).inOrder();
+    assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
   }
 
   public void testStop_withoutStart() {
@@ -136,7 +136,7 @@ public class AbstractIdleServiceTest extends TestCase {
     assertEquals(1, service.shutDownCalled);
     assertEquals(Service.State.TERMINATED, service.state());
     assertThat(service.transitionStates)
-        .has().exactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
+        .containsExactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
   }
 
   public void testStop_failed() {
@@ -160,7 +160,7 @@ public class AbstractIdleServiceTest extends TestCase {
     assertEquals(1, service.shutDownCalled);
     assertEquals(Service.State.FAILED, service.state());
     assertThat(service.transitionStates)
-        .has().exactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
+        .containsExactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
   }
 
   public void testServiceToString() {
@@ -180,12 +180,16 @@ public class AbstractIdleServiceTest extends TestCase {
           @Override public void execute(Runnable command) {}
         };
       }
+
+      @Override protected String serviceName() {
+        return "Foo";
+      }
     };
     try {
       service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
       fail("Expected timeout");
     } catch (TimeoutException e) {
-      assertThat(e.getMessage()).contains(Service.State.STARTING.toString());
+      assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
index df96535..7742dbb 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.common.collect.ImmutableList;
 
 import junit.framework.TestCase;
@@ -33,26 +35,26 @@ public class AbstractListeningExecutorServiceTest extends TestCase {
 
   public void testSubmit() throws Exception {
     /*
-     * Mostly just tests that ListenableFutureTasks are created and run; tests for
-     * ListenableFutureTask should ensure that listeners are called correctly.
+     * Mostly just tests that TrustedListenableFutureTask are created and run; tests for
+     * TrustedListenableFutureTask should ensure that listeners are called correctly.
      */
 
     TestListeningExecutorService e = new TestListeningExecutorService();
 
     TestRunnable runnable = new TestRunnable();
     ListenableFuture<?> runnableFuture = e.submit(runnable);
-    assertTrue(runnableFuture instanceof ListenableFutureTask);
+    assertThat(runnableFuture).isInstanceOf(TrustedListenableFutureTask.class);
     assertTrue(runnableFuture.isDone());
     assertTrue(runnable.run);
 
     ListenableFuture<String> callableFuture = e.submit(new TestCallable());
-    assertTrue(callableFuture instanceof ListenableFutureTask);
+    assertThat(callableFuture).isInstanceOf(TrustedListenableFutureTask.class);
     assertTrue(callableFuture.isDone());
     assertEquals("foo", callableFuture.get());
 
     TestRunnable runnable2 = new TestRunnable();
     ListenableFuture<Integer> runnableFuture2 = e.submit(runnable2, 3);
-    assertTrue(runnableFuture2 instanceof ListenableFutureTask);
+    assertThat(runnableFuture2).isInstanceOf(TrustedListenableFutureTask.class);
     assertTrue(runnableFuture2.isDone());
     assertTrue(runnable2.run);
     assertEquals((Integer) 3, runnableFuture2.get());
@@ -81,7 +83,7 @@ public class AbstractListeningExecutorServiceTest extends TestCase {
 
     @Override
     public void execute(Runnable runnable) {
-      assertTrue(runnable instanceof ListenableFutureTask);
+      assertThat(runnable).isInstanceOf(TrustedListenableFutureTask.class);
       runnable.run();
     }
 
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
index 7c01d41..599c1ab 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
@@ -16,19 +16,28 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.AbstractScheduledService.Scheduler.newFixedDelaySchedule;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import com.google.common.util.concurrent.AbstractScheduledService.Scheduler;
 import com.google.common.util.concurrent.Service.State;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import junit.framework.TestCase;
 
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -41,7 +50,7 @@ import java.util.concurrent.atomic.AtomicReference;
 
 public class AbstractScheduledServiceTest extends TestCase {
 
-  volatile Scheduler configuration = Scheduler.newFixedDelaySchedule(0, 10, TimeUnit.MILLISECONDS);
+  volatile Scheduler configuration = newFixedDelaySchedule(0, 10, TimeUnit.MILLISECONDS);
   volatile ScheduledFuture<?> future = null;
 
   volatile boolean atFixedRateCalled = false;
@@ -79,11 +88,11 @@ public class AbstractScheduledServiceTest extends TestCase {
     try {
       future.get();
       fail();
-    } catch (ExecutionException e) {
-      // An execution exception holds a runtime exception (from throwables.propogate) that holds our
-      // original exception.
-      assertEquals(service.runException, e.getCause().getCause());
+    } catch (CancellationException expected) {
     }
+    // An execution exception holds a runtime exception (from throwables.propogate) that holds our
+    // original exception.
+    assertEquals(service.runException, service.failureCause());
     assertEquals(service.state(), Service.State.FAILED);
   }
 
@@ -100,6 +109,27 @@ public class AbstractScheduledServiceTest extends TestCase {
     assertEquals(Service.State.FAILED, service.state());
   }
 
+  public void testFailOnErrorFromStartUpListener() throws InterruptedException {
+    final Error error = new Error();
+    final CountDownLatch latch = new CountDownLatch(1);
+    TestService service = new TestService();
+    service.addListener(new Service.Listener() {
+      @Override public void running() {
+        throw error;
+      }
+      @Override public void failed(State from, Throwable failure) {
+        assertEquals(State.RUNNING, from);
+        assertEquals(error, failure);
+        latch.countDown();
+      }
+    }, directExecutor());
+    service.startAsync();
+    latch.await();
+
+    assertEquals(0, service.numberOfTimesRunCalled.get());
+    assertEquals(Service.State.FAILED, service.state());
+  }
+
   public void testFailOnExceptionFromShutDown() throws Exception {
     TestService service = new TestService();
     service.shutDownException = new Exception();
@@ -159,7 +189,7 @@ public class AbstractScheduledServiceTest extends TestCase {
       }
 
       @Override protected Scheduler scheduler() {
-        return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
+        return newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
       }
     };
 
@@ -186,7 +216,7 @@ public class AbstractScheduledServiceTest extends TestCase {
       }
 
       @Override protected Scheduler scheduler() {
-        return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
+        return newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
       }
     };
 
@@ -216,6 +246,31 @@ public class AbstractScheduledServiceTest extends TestCase {
     assertEquals(1, service.numberOfTimesSchedulerCalled.get());
   }
 
+  public void testTimeout() {
+    // Create a service whose executor will never run its commands
+    Service service = new AbstractScheduledService() {
+      @Override protected Scheduler scheduler() {
+        return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.NANOSECONDS);
+      }
+
+      @Override protected ScheduledExecutorService executor() {
+        return TestingExecutors.noOpScheduledExecutor();
+      }
+
+      @Override protected void runOneIteration() throws Exception {}
+
+      @Override protected String serviceName() {
+        return "Foo";
+      }
+    };
+    try {
+      service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
+      fail("Expected timeout");
+    } catch (TimeoutException e) {
+      assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
+    }
+  }
+
   private class TestService extends AbstractScheduledService {
     CyclicBarrier runFirstBarrier = new CyclicBarrier(2);
     CyclicBarrier runSecondBarrier = new CyclicBarrier(2);
@@ -311,7 +366,7 @@ public class AbstractScheduledServiceTest extends TestCase {
     }
 
     public void testFixedDelaySchedule() {
-      Scheduler schedule = Scheduler.newFixedDelaySchedule(initialDelay, delay, unit);
+      Scheduler schedule = newFixedDelaySchedule(initialDelay, delay, unit);
       schedule.schedule(null, new ScheduledThreadPoolExecutor(10) {
         @Override
         public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
@@ -323,6 +378,47 @@ public class AbstractScheduledServiceTest extends TestCase {
       assertTrue(called);
     }
 
+    public void testFixedDelayScheduleFarFuturePotentiallyOverflowingScheduleIsNeverReached()
+        throws Exception {
+      TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
+        @Override protected Scheduler scheduler() {
+          return newFixedDelaySchedule(Long.MAX_VALUE, Long.MAX_VALUE, SECONDS);
+        }
+      };
+      service.startAsync().awaitRunning();
+      try {
+        service.firstBarrier.await(5, SECONDS);
+        fail();
+      } catch (TimeoutException expected) {
+      }
+      assertEquals(0, service.numIterations.get());
+      service.stopAsync();
+      service.awaitTerminated();
+    }
+
+    public void testCustomSchedulerFarFuturePotentiallyOverflowingScheduleIsNeverReached()
+        throws Exception {
+      TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
+        @Override protected Scheduler scheduler() {
+          return new AbstractScheduledService.CustomScheduler() {
+            @Override
+            protected Schedule getNextSchedule() throws Exception {
+              return new Schedule(Long.MAX_VALUE, SECONDS);
+            }
+          };
+        }
+      };
+      service.startAsync().awaitRunning();
+      try {
+        service.firstBarrier.await(5, SECONDS);
+        fail();
+      } catch (TimeoutException expected) {
+      }
+      assertEquals(0, service.numIterations.get());
+      service.stopAsync();
+      service.awaitTerminated();
+    }
+
     private class TestCustomScheduler extends AbstractScheduledService.CustomScheduler {
       public AtomicInteger scheduleCounter = new AtomicInteger(0);
       @Override
@@ -373,6 +469,31 @@ public class AbstractScheduledServiceTest extends TestCase {
       assertEquals(1, service.numIterations.get());
     }
 
+    public void testCustomScheduler_deadlock() throws InterruptedException, BrokenBarrierException {
+      final CyclicBarrier inGetNextSchedule = new CyclicBarrier(2);
+      // This will flakily deadlock, so run it multiple times to increase the flake likelihood
+      for (int i = 0; i < 1000; i++) {
+        Service service = new AbstractScheduledService() {
+          @Override protected void runOneIteration() {}
+          @Override protected Scheduler scheduler() {
+            return new CustomScheduler() {
+              @Override protected Schedule getNextSchedule() throws Exception {
+                if (state() != State.STARTING) {
+                  inGetNextSchedule.await();
+                  Thread.yield();
+                  throw new RuntimeException("boom");
+                }
+                return new Schedule(0, TimeUnit.NANOSECONDS);
+              }
+            };
+          }
+        };
+        service.startAsync().awaitRunning();
+        inGetNextSchedule.await();
+        service.stopAsync();
+      }
+    }
+
     public void testBig() throws Exception {
       TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
         @Override protected Scheduler scheduler() {
@@ -417,10 +538,6 @@ public class AbstractScheduledServiceTest extends TestCase {
         return Executors.newScheduledThreadPool(10);
       }
 
-      @Override protected void startUp() throws Exception {}
-
-      @Override protected void shutDown() throws Exception {}
-
       @Override protected Scheduler scheduler() {
         return new CustomScheduler() {
           @Override
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
index 1fdac38..a6eeaa9 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 import static java.lang.Thread.currentThread;
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -380,7 +381,7 @@ public class AbstractServiceTest extends TestCase {
     assertEquals(State.FAILED, service.state());
     waiter.join(LONG_TIMEOUT_MILLIS);
     assertFalse(waiter.isAlive());
-    assertTrue(exception.get() instanceof IllegalStateException);
+    assertThat(exception.get()).isInstanceOf(IllegalStateException.class);
     assertEquals(EXCEPTION, exception.get().getCause());
   }
 
@@ -460,12 +461,12 @@ public class AbstractServiceTest extends TestCase {
     service.startAsync();
     service.notifyFailed(new Exception("1"));
     service.notifyFailed(new Exception("2"));
-    assertEquals("1", service.failureCause().getMessage());
+    assertThat(service.failureCause()).hasMessage("1");
     try {
       service.awaitRunning();
       fail();
     } catch (IllegalStateException e) {
-      assertEquals("1", e.getCause().getMessage());
+      assertThat(e.getCause()).hasMessage("1");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java
deleted file mode 100644
index 1ffd307..0000000
--- a/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.util.concurrent;
-
-import junit.framework.TestCase;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Tests that {@code AsyncSettableFuture} is a valid {@link ListenableFuture}
- * that behaves itself as expected.
- */
-
-public class AsyncSettableFutureTest extends TestCase {
-
-  private static class Foo {}
-  private static class FooChild extends Foo {}
-
-  /** Tests the initial state of the future. */
-  public void testCreate() throws Exception {
-    AsyncSettableFuture<Integer> future = AsyncSettableFuture.create();
-    assertFalse(future.isSet());
-    assertFalse(future.isDone());
-    assertFalse(future.isCancelled());
-  }
-
-  public void testSetValue() throws Exception {
-    AsyncSettableFuture<Integer> future = AsyncSettableFuture.create();
-    assertTrue(future.setValue(42));
-    assertTrue(future.isSet());
-    // Later attempts to set the future should return false.
-    assertFalse(future.setValue(23));
-    assertFalse(future.setException(new Exception("bar")));
-    assertFalse(future.setFuture(SettableFuture.<Integer>create()));
-    // Check that the future has been set properly.
-    assertTrue(future.isDone());
-    assertFalse(future.isCancelled());
-    assertEquals(42, (int) future.get());
-  }
-
-  public void testSetException() throws Exception {
-    AsyncSettableFuture<Object> future = AsyncSettableFuture.create();
-    Exception e = new Exception("foobarbaz");
-    assertTrue(future.setException(e));
-    assertTrue(future.isSet());
-    // Later attempts to set the future should return false.
-    assertFalse(future.setValue(23));
-    assertFalse(future.setException(new Exception("quux")));
-    assertFalse(future.setFuture(SettableFuture.create()));
-    // Check that the future has been set properly.
-    assertTrue(future.isDone());
-    assertFalse(future.isCancelled());
-    try {
-      future.get();
-      fail("Expected ExecutionException");
-    } catch (ExecutionException ee) {
-      assertSame(e, ee.getCause());
-    }
-  }
-
-  public void testSetFuture() throws Exception {
-    AsyncSettableFuture<String> future = AsyncSettableFuture.create();
-    SettableFuture<String> nested = SettableFuture.create();
-    assertTrue(future.setFuture(nested));
-    assertTrue(future.isSet());
-    // Later attempts to set the future should return false.
-    assertFalse(future.setValue("x"));
-    assertFalse(future.setException(new Exception("bar")));
-    assertFalse(future.setFuture(SettableFuture.<String>create()));
-    // Check that the future has been set properly.
-    assertFalse(future.isDone());
-    assertFalse(future.isCancelled());
-    try {
-      future.get(0, TimeUnit.MILLISECONDS);
-      fail("Expected TimeoutException");
-    } catch (TimeoutException expected) { /* expected */ }
-    nested.set("foo");
-    assertTrue(future.isDone());
-    assertFalse(future.isCancelled());
-    assertEquals("foo", future.get());
-  }
-
-  public void testSetFuture_genericsHierarchy() throws Exception {
-    AsyncSettableFuture<Foo> future = AsyncSettableFuture.create();
-    SettableFuture<FooChild> nested = SettableFuture.create();
-    assertTrue(future.setFuture(nested));
-    assertTrue(future.isSet());
-    // Later attempts to set the future should return false.
-    assertFalse(future.setValue(new Foo()));
-    assertFalse(future.setException(new Exception("bar")));
-    assertFalse(future.setFuture(SettableFuture.<Foo>create()));
-    // Check that the future has been set properly.
-    assertFalse(future.isDone());
-    assertFalse(future.isCancelled());
-    try {
-      future.get(0, TimeUnit.MILLISECONDS);
-      fail("Expected TimeoutException");
-    } catch (TimeoutException expected) { /* expected */ }
-    FooChild value = new FooChild();
-    nested.set(value);
-    assertTrue(future.isDone());
-    assertFalse(future.isCancelled());
-    assertSame(value, future.get());
-  }
-
-  public void testCancel_innerCancelsAsync() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    SettableFuture<Object> inner = SettableFuture.create();
-    async.setFuture(inner);
-    inner.cancel(true);
-    assertTrue(async.isCancelled());
-    try {
-      async.get();
-      fail("Expected CancellationException");
-    } catch (CancellationException expected) { /* expected */ }
-  }
-
-  public void testCancel_resultCancelsInner_interrupted() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    MyFuture<Object> inner = new MyFuture<Object>();
-    async.setFuture(inner);
-    async.cancel(true);
-    assertTrue(inner.isCancelled());
-    assertTrue(inner.myWasInterrupted());
-    try {
-      inner.get();
-      fail("Expected CancellationException");
-    } catch (CancellationException expected) { /* expected */ }
-  }
-
-  public void testCancel_resultCancelsInner() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    MyFuture<Object> inner = new MyFuture<Object>();
-    async.setFuture(inner);
-    async.cancel(false);
-    assertTrue(inner.isCancelled());
-    assertFalse(inner.myWasInterrupted());
-    try {
-      inner.get();
-      fail("Expected CancellationException");
-    } catch (CancellationException expected) { /* expected */ }
-  }
-
-  public void testCancel_beforeSet() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    async.cancel(true);
-    assertFalse(async.setValue(42));
-  }
-
-  public void testCancel_multipleBeforeSetFuture_noInterruptFirst() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    async.cancel(false);
-    async.cancel(true);
-    MyFuture<Object> inner = new MyFuture<Object>();
-    assertFalse(async.setFuture(inner));
-    assertTrue(inner.isCancelled());
-    assertFalse(inner.myWasInterrupted());
-  }
-
-  public void testCancel_multipleBeforeSetFuture_interruptFirst() throws Exception {
-    AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
-    async.cancel(true);
-    async.cancel(false);
-    MyFuture<Object> inner = new MyFuture<Object>();
-    assertFalse(async.setFuture(inner));
-    assertTrue(inner.isCancelled());
-    assertTrue(inner.myWasInterrupted());
-  }
-
-  private static class MyFuture<V> extends AbstractFuture<V> {
-    boolean myWasInterrupted() {
-      // we need a new method since wasInterrupted is final, so we can't increase its visibility.
-      return wasInterrupted();
-    }
-  }
-}
diff --git a/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java b/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
index 885b73c..b024206 100644
--- a/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.util.concurrent;
 
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 
@@ -29,6 +31,7 @@ import java.util.concurrent.Callable;
  *
  * @author Isaac Shum
  */
+ at GwtCompatible(emulated = true)
 public class CallablesTest extends TestCase {
 
   public void testReturning() throws Exception {
@@ -41,6 +44,7 @@ public class CallablesTest extends TestCase {
     assertSame(value, callable.call());
   }
 
+  @GwtIncompatible("threads")
   public void testRenaming() throws Exception {
     String oldName = Thread.currentThread().getName();
     final Supplier<String> newName = Suppliers.ofInstance("MyCrazyThreadName");
@@ -54,6 +58,7 @@ public class CallablesTest extends TestCase {
     assertEquals(oldName, Thread.currentThread().getName());
   }
 
+  @GwtIncompatible("threads")
   public void testRenaming_exceptionalReturn() throws Exception {
     String oldName = Thread.currentThread().getName();
     final Supplier<String> newName = Suppliers.ofInstance("MyCrazyThreadName");
@@ -71,6 +76,8 @@ public class CallablesTest extends TestCase {
     assertEquals(oldName, Thread.currentThread().getName());
   }
 
+  @GwtIncompatible("threads")
+
   public void testRenaming_noPermissions() throws Exception {
     System.setSecurityManager(new SecurityManager() {
       @Override public void checkAccess(Thread t) {
diff --git a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
index edc48a9..4cfd36c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
@@ -16,14 +16,16 @@
 
 package com.google.common.util.concurrent;
 
+import static org.mockito.Answers.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 import com.google.common.base.Function;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ForwardingObject;
 import com.google.common.collect.Iterables;
 import com.google.common.testing.ForwardingWrapperTester;
 
-import org.easymock.EasyMock;
-
 import java.lang.reflect.Method;
 import java.util.Arrays;
 
@@ -57,16 +59,13 @@ final class ForwardingObjectTester {
         Iterables.getOnlyElement(Arrays.asList(forwarderClass.getInterfaces()));
     new ForwardingWrapperTester().testForwarding(interfaceType, new Function<Object, T>() {
       @Override public T apply(Object delegate) {
-        T mock = EasyMock.createMockBuilder(forwarderClass)
-            .addMockedMethod(DELEGATE_METHOD)
-            .createMock();
+        T mock = mock(forwarderClass, CALLS_REAL_METHODS.get());
         try {
-          DELEGATE_METHOD.invoke(mock);
+          T stubber = doReturn(delegate).when(mock);
+          DELEGATE_METHOD.invoke(stubber);
         } catch (Exception e) {
           throw Throwables.propagate(e);
         }
-        EasyMock.expectLastCall().andStubReturn(delegate);
-        EasyMock.replay(mock);
         return mock;
       }
     });
diff --git a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
index eae45bc..0b68e9a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
@@ -32,10 +32,13 @@ public class ForwardingObjectTesterTest extends TestCase {
       ForwardingObjectTester.testForwardingObject(FailToForward.class);
     } catch (AssertionError expected) {
       return;
+    } catch (UnsupportedOperationException expectedOnAndroid) {
+      return;
     }
     fail("Should have thrown");
   }
 
+  @SuppressUnderAndroid // TODO(cpovirk): java.lang.IllegalAccessError: superclass not accessible
   public void testSuccessfulForwarding() {
     ForwardingObjectTester.testForwardingObject(ForwardToDelegate.class);
   }
diff --git a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java b/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
index 14e0179..a98f4a6 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
@@ -16,6 +16,10 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Preconditions;
 
 import junit.framework.TestCase;
@@ -34,6 +38,7 @@ import javax.annotation.Nullable;
  *
  * @author Anthony Zana
  */
+ at GwtCompatible(emulated = true)
 public class FutureCallbackTest extends TestCase {
   public void testSameThreadSuccess() {
     SettableFuture<String> f = SettableFuture.create();
@@ -65,6 +70,7 @@ public class FutureCallbackTest extends TestCase {
     FutureCallback<String> callback =
         new FutureCallback<String>() {
           private boolean called = false;
+
           @Override
           public void onSuccess(String result) {
             fail("Was not expecting onSuccess() to be called.");
@@ -73,7 +79,7 @@ public class FutureCallbackTest extends TestCase {
           @Override
           public synchronized void onFailure(Throwable t) {
             assertFalse(called);
-            assertTrue(t instanceof CancellationException);
+            assertThat(t).isInstanceOf(CancellationException.class);
             called = true;
           }
         };
@@ -95,6 +101,7 @@ public class FutureCallbackTest extends TestCase {
     Futures.addCallback(f, callback);
   }
 
+  @GwtIncompatible("Mockito")
   public void testOnSuccessThrowsRuntimeException() throws Exception {
     RuntimeException exception = new RuntimeException();
     String result = "result";
@@ -109,6 +116,7 @@ public class FutureCallbackTest extends TestCase {
     Mockito.verifyNoMoreInteractions(callback);
   }
 
+  @GwtIncompatible("Mockito")
   public void testOnSuccessThrowsError() throws Exception {
     class TestError extends Error {}
     TestError error = new TestError();
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java
new file mode 100644
index 0000000..db192e7
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java
@@ -0,0 +1,142 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+
+import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Classes and futures used in {@link FuturesGetCheckedTest} and {@link FuturesGetUncheckedTest}.
+ */
+final class FuturesGetCheckedInputs {
+  static final Exception CHECKED_EXCEPTION = new Exception("mymessage");
+  static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION =
+      immediateFailedFuture(CHECKED_EXCEPTION);
+  static final RuntimeException UNCHECKED_EXCEPTION = new RuntimeException("mymessage");
+  static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION =
+      immediateFailedFuture(UNCHECKED_EXCEPTION);
+  static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException();
+  static final OtherThrowable OTHER_THROWABLE = new OtherThrowable();
+  static final Future<String> FAILED_FUTURE_OTHER_THROWABLE =
+      immediateFailedFuture(OTHER_THROWABLE);
+  static final Error ERROR = new Error("mymessage");
+  static final Future<String> FAILED_FUTURE_ERROR = immediateFailedFuture(ERROR);
+  static final Future<String> RUNTIME_EXCEPTION_FUTURE =
+      new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) {
+        @Override
+        public String get() {
+          throw RUNTIME_EXCEPTION;
+        }
+
+        @Override
+        public String get(long timeout, TimeUnit unit) {
+          throw RUNTIME_EXCEPTION;
+        }
+      };
+
+  public static final class TwoArgConstructorException extends Exception {
+    public TwoArgConstructorException(String message, Throwable cause) {
+      super(message, cause);
+    }
+  }
+
+  public static final class TwoArgConstructorRuntimeException extends RuntimeException {
+    public TwoArgConstructorRuntimeException(String message, Throwable cause) {
+      super(message, cause);
+    }
+  }
+
+  public static final class ExceptionWithPrivateConstructor extends Exception {
+    private ExceptionWithPrivateConstructor(String message, Throwable cause) {
+      super(message, cause);
+    }
+  }
+
+  @SuppressWarnings("unused") // we're testing that they're not used
+  public static final class ExceptionWithSomePrivateConstructors extends Exception {
+    private ExceptionWithSomePrivateConstructors(String a) {}
+
+    private ExceptionWithSomePrivateConstructors(String a, String b) {}
+
+    public ExceptionWithSomePrivateConstructors(String a, String b, String c) {}
+
+    private ExceptionWithSomePrivateConstructors(String a, String b, String c, String d) {}
+
+    private ExceptionWithSomePrivateConstructors(
+        String a, String b, String c, String d, String e) {}
+  }
+
+  public static final class ExceptionWithManyConstructors extends Exception {
+    boolean usedExpectedConstructor;
+
+    public ExceptionWithManyConstructors() {}
+
+    public ExceptionWithManyConstructors(Integer i) {}
+
+    public ExceptionWithManyConstructors(Throwable a) {}
+
+    public ExceptionWithManyConstructors(Throwable a, Throwable b) {}
+
+    public ExceptionWithManyConstructors(String s, Throwable b) {
+      usedExpectedConstructor = true;
+    }
+
+    public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c) {}
+
+    public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c, Throwable d) {}
+
+    public ExceptionWithManyConstructors(
+        Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) {}
+
+    public ExceptionWithManyConstructors(
+        Throwable a, Throwable b, Throwable c, Throwable d, Throwable e, String s, Integer i) {}
+  }
+
+  public static final class ExceptionWithoutThrowableConstructor extends Exception {
+    public ExceptionWithoutThrowableConstructor(String s) {
+      super(s);
+    }
+  }
+
+  public static final class ExceptionWithWrongTypesConstructor extends Exception {
+    public ExceptionWithWrongTypesConstructor(Integer i, String s) {
+      super(s);
+    }
+  }
+
+  static final class ExceptionWithGoodAndBadConstructor extends Exception {
+    public ExceptionWithGoodAndBadConstructor(String message, Throwable cause) {
+      throw new RuntimeException("bad constructor");
+    }
+
+    public ExceptionWithGoodAndBadConstructor(Throwable cause) {
+      super(cause);
+    }
+  }
+
+  static final class ExceptionWithBadConstructor extends Exception {
+    public ExceptionWithBadConstructor(String message, Throwable cause) {
+      throw new RuntimeException("bad constructor");
+    }
+  }
+
+  static final class OtherThrowable extends Throwable {}
+
+  private FuturesGetCheckedInputs() {}
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java
new file mode 100644
index 0000000..11a9844
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java
@@ -0,0 +1,367 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.getChecked;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_UNCHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION_FUTURE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.UNCHECKED_EXCEPTION;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import com.google.common.testing.GcFinalization;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithBadConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithGoodAndBadConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithManyConstructors;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithPrivateConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithSomePrivateConstructors;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithWrongTypesConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithoutThrowableConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.TwoArgConstructorException;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.TwoArgConstructorRuntimeException;
+
+import junit.framework.TestCase;
+
+import java.lang.ref.WeakReference;
+import java.net.URLClassLoader;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Unit tests for {@link Futures#getChecked(Future, Class)}.
+ */
+public class FuturesGetCheckedTest extends TestCase {
+  // Boring untimed-get tests:
+
+  public void testGetCheckedUntimed_success() throws TwoArgConstructorException {
+    assertEquals("foo", getChecked(immediateFuture("foo"), TwoArgConstructorException.class));
+  }
+
+  public void testGetCheckedUntimed_interrupted() {
+    SettableFuture<String> future = SettableFuture.create();
+    Thread.currentThread().interrupt();
+    try {
+      getChecked(future, TwoArgConstructorException.class);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertThat(expected.getCause()).isInstanceOf(InterruptedException.class);
+      assertTrue(Thread.currentThread().isInterrupted());
+    } finally {
+      Thread.interrupted();
+    }
+  }
+
+  public void testGetCheckedUntimed_cancelled() throws TwoArgConstructorException {
+    SettableFuture<String> future = SettableFuture.create();
+    future.cancel(true);
+    try {
+      getChecked(future, TwoArgConstructorException.class);
+      fail();
+    } catch (CancellationException expected) {
+    }
+  }
+
+  public void testGetCheckedUntimed_ExecutionExceptionChecked() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertEquals(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedUntimed_ExecutionExceptionUnchecked()
+      throws TwoArgConstructorException {
+    try {
+      getChecked(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class);
+      fail();
+    } catch (UncheckedExecutionException expected) {
+      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedUntimed_ExecutionExceptionError() throws TwoArgConstructorException {
+    try {
+      getChecked(FAILED_FUTURE_ERROR, TwoArgConstructorException.class);
+      fail();
+    } catch (ExecutionError expected) {
+      assertEquals(ERROR, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedUntimed_ExecutionExceptionOtherThrowable() {
+    try {
+      getChecked(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertEquals(OTHER_THROWABLE, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedUntimed_RuntimeException() throws TwoArgConstructorException {
+    try {
+      getChecked(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class);
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals(RUNTIME_EXCEPTION, expected);
+    }
+  }
+
+  public void testGetCheckedUntimed_badExceptionConstructor_failsEvenForSuccessfulInput()
+      throws Exception {
+    try {
+      getChecked(immediateFuture("x"), ExceptionWithBadConstructor.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedUntimed_badExceptionConstructor_wrapsOriginalChecked()
+      throws Exception {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedUntimed_withGoodAndBadExceptionConstructor() throws Exception {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithGoodAndBadConstructor.class);
+      fail();
+    } catch (ExceptionWithGoodAndBadConstructor expected) {
+      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  // Boring timed-get tests:
+
+  public void testGetCheckedTimed_success() throws TwoArgConstructorException {
+    assertEquals(
+        "foo", getChecked(immediateFuture("foo"), TwoArgConstructorException.class, 0, SECONDS));
+  }
+
+  public void testGetCheckedTimed_interrupted() {
+    SettableFuture<String> future = SettableFuture.create();
+    Thread.currentThread().interrupt();
+    try {
+      getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertThat(expected.getCause()).isInstanceOf(InterruptedException.class);
+      assertTrue(Thread.currentThread().isInterrupted());
+    } finally {
+      Thread.interrupted();
+    }
+  }
+
+  public void testGetCheckedTimed_cancelled() throws TwoArgConstructorException {
+    SettableFuture<String> future = SettableFuture.create();
+    future.cancel(true);
+    try {
+      getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (CancellationException expected) {
+    }
+  }
+
+  public void testGetCheckedTimed_ExecutionExceptionChecked() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertEquals(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedTimed_ExecutionExceptionUnchecked() throws TwoArgConstructorException {
+    try {
+      getChecked(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (UncheckedExecutionException expected) {
+      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedTimed_ExecutionExceptionError() throws TwoArgConstructorException {
+    try {
+      getChecked(FAILED_FUTURE_ERROR, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (ExecutionError expected) {
+      assertEquals(ERROR, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedTimed_ExecutionExceptionOtherThrowable() {
+    try {
+      getChecked(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertEquals(OTHER_THROWABLE, expected.getCause());
+    }
+  }
+
+  public void testGetCheckedTimed_RuntimeException() throws TwoArgConstructorException {
+    try {
+      getChecked(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals(RUNTIME_EXCEPTION, expected);
+    }
+  }
+
+  public void testGetCheckedTimed_TimeoutException() {
+    SettableFuture<String> future = SettableFuture.create();
+    try {
+      getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+      fail();
+    } catch (TwoArgConstructorException expected) {
+      assertThat(expected.getCause()).isInstanceOf(TimeoutException.class);
+    }
+  }
+
+  public void testGetCheckedTimed_badExceptionConstructor_failsEvenForSuccessfulInput()
+      throws Exception {
+    try {
+      getChecked(immediateFuture("x"), ExceptionWithBadConstructor.class, 1, TimeUnit.SECONDS);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedTimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
+    try {
+      getChecked(
+          FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class, 1, TimeUnit.SECONDS);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedTimed_withGoodAndBadExceptionConstructor() throws Exception {
+    try {
+      getChecked(
+          FAILED_FUTURE_CHECKED_EXCEPTION,
+          ExceptionWithGoodAndBadConstructor.class,
+          1,
+          TimeUnit.SECONDS);
+      fail();
+    } catch (ExceptionWithGoodAndBadConstructor expected) {
+      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  // Edge case tests of the exception-construction code through untimed get():
+
+  @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+  public void testGetCheckedUntimed_exceptionClassIsRuntimeException() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorRuntimeException.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedUntimed_exceptionClassSomePrivateConstructors() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithSomePrivateConstructors.class);
+      fail();
+    } catch (ExceptionWithSomePrivateConstructors expected) {
+    }
+  }
+
+  @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+  public void testGetCheckedUntimed_exceptionClassNoPublicConstructor()
+      throws ExceptionWithPrivateConstructor {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithPrivateConstructor.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+  public void testGetCheckedUntimed_exceptionClassPublicConstructorWrongType()
+      throws ExceptionWithWrongTypesConstructor {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithWrongTypesConstructor.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testGetCheckedUntimed_exceptionClassPrefersStringConstructor() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithManyConstructors.class);
+      fail();
+    } catch (ExceptionWithManyConstructors expected) {
+      assertTrue(expected.usedExpectedConstructor);
+    }
+  }
+
+  public void testGetCheckedUntimed_exceptionClassUsedInitCause() {
+    try {
+      getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithoutThrowableConstructor.class);
+      fail();
+    } catch (ExceptionWithoutThrowableConstructor expected) {
+      assertThat(expected.getMessage()).contains("mymessage");
+      assertEquals(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  // Class unloading test:
+
+  public static final class WillBeUnloadedException extends Exception {}
+
+  public void testGetChecked_classUnloading() throws Exception {
+    WeakReference<?> classUsedByGetChecked = doTestClassUnloading();
+    GcFinalization.awaitClear(classUsedByGetChecked);
+  }
+
+  /**
+   * Loads {@link WillBeUnloadedException} in a separate {@code ClassLoader}, calls {@code
+   * getChecked(future, WillBeUnloadedException.class)}, and returns the loader. The caller can then
+   * test that the {@code ClassLoader} can still be GCed. The test amounts to a test that {@code
+   * getChecked} holds no strong references to the class.
+   */
+  private WeakReference<?> doTestClassUnloading() throws Exception {
+    URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
+    URLClassLoader shadowLoader = new URLClassLoader(myLoader.getURLs(), null);
+    @SuppressWarnings("unchecked")
+    Class<WillBeUnloadedException> shadowClass =
+        (Class<WillBeUnloadedException>)
+            Class.forName(WillBeUnloadedException.class.getName(), false, shadowLoader);
+    assertNotSame(shadowClass, WillBeUnloadedException.class);
+    getChecked(immediateFuture("foo"), shadowClass);
+    return new WeakReference<ClassLoader>(shadowLoader);
+  }
+
+  /*
+   * TODO(cpovirk): It would be great to run all these tests (including class unloading) in an
+   * environment that forces Futures.getChecked to its fallback WeakSetValidator. One awful way of
+   * doing so would be to derive a separate test library by using remove_from_jar to strip out
+   * ClassValueValidator.
+   */
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java
new file mode 100644
index 0000000..b9db395
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Futures.getUnchecked;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_UNCHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION_FUTURE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.UNCHECKED_EXCEPTION;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+
+/**
+ * Unit tests for {@link Futures#getUnchecked(Future)}.
+ */
+public class FuturesGetUncheckedTest extends TestCase {
+  public void testGetUnchecked_success() {
+    assertEquals("foo", getUnchecked(immediateFuture("foo")));
+  }
+
+  public void testGetUnchecked_interrupted() {
+    Thread.currentThread().interrupt();
+    try {
+      assertEquals("foo", getUnchecked(immediateFuture("foo")));
+      assertTrue(Thread.currentThread().isInterrupted());
+    } finally {
+      Thread.interrupted();
+    }
+  }
+
+  public void testGetUnchecked_cancelled() {
+    SettableFuture<String> future = SettableFuture.create();
+    future.cancel(true);
+    try {
+      getUnchecked(future);
+      fail();
+    } catch (CancellationException expected) {
+    }
+  }
+
+  public void testGetUnchecked_ExecutionExceptionChecked() {
+    try {
+      getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION);
+      fail();
+    } catch (UncheckedExecutionException expected) {
+      assertEquals(CHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetUnchecked_ExecutionExceptionUnchecked() {
+    try {
+      getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION);
+      fail();
+    } catch (UncheckedExecutionException expected) {
+      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+    }
+  }
+
+  public void testGetUnchecked_ExecutionExceptionError() {
+    try {
+      getUnchecked(FAILED_FUTURE_ERROR);
+      fail();
+    } catch (ExecutionError expected) {
+      assertEquals(ERROR, expected.getCause());
+    }
+  }
+
+  public void testGetUnchecked_ExecutionExceptionOtherThrowable() {
+    try {
+      getUnchecked(FAILED_FUTURE_OTHER_THROWABLE);
+      fail();
+    } catch (UncheckedExecutionException expected) {
+      assertEquals(OTHER_THROWABLE, expected.getCause());
+    }
+  }
+
+  public void testGetUnchecked_RuntimeException() {
+    try {
+      getUnchecked(RUNTIME_EXCEPTION_FUTURE);
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals(RUNTIME_EXCEPTION, expected);
+    }
+  }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
index b39dac0..7329064 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
@@ -17,23 +17,26 @@
 package com.google.common.util.concurrent;
 
 import static com.google.common.base.Throwables.propagateIfInstanceOf;
+import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.util.concurrent.Futures.allAsList;
-import static com.google.common.util.concurrent.Futures.get;
-import static com.google.common.util.concurrent.Futures.getUnchecked;
 import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
 import static com.google.common.util.concurrent.Futures.immediateFuture;
 import static com.google.common.util.concurrent.Futures.successfulAsList;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
+import static com.google.common.util.concurrent.TestPlatform.clearInterrupt;
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.easymock.EasyMock.expect;
 
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -41,14 +44,11 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.testing.ClassSanityTester;
 import com.google.common.testing.TestLogHandler;
-import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
-import org.easymock.EasyMock;
-import org.easymock.IMocksControl;
-
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
@@ -64,6 +64,7 @@ import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Handler;
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
@@ -73,36 +74,35 @@ import javax.annotation.Nullable;
 /**
  * Unit tests for {@link Futures}.
  *
- * TODO: Add tests for other Futures methods
- *
  * @author Nishant Thakkar
  */
+ at SuppressWarnings("CheckReturnValue")
+ at GwtCompatible(emulated = true)
 public class FuturesTest extends TestCase {
-  private static final Logger combinedFutureLogger = Logger.getLogger(
-      "com.google.common.util.concurrent.Futures$CombinedFuture");
-  private final TestLogHandler combinedFutureLogHandler = new TestLogHandler();
+  private static final Logger aggregateFutureLogger =
+      Logger.getLogger(AggregateFuture.class.getName());
+  private final TestLogHandler aggregateFutureLogHandler = new TestLogHandler();
 
   private static final String DATA1 = "data";
   private static final String DATA2 = "more data";
   private static final String DATA3 = "most data";
 
-  private IMocksControl mocksControl;
-
-  @Override protected void setUp() throws Exception {
+  @Override
+  protected void setUp() throws Exception {
     super.setUp();
-    combinedFutureLogger.addHandler(combinedFutureLogHandler);
-    mocksControl = EasyMock.createControl();
+    aggregateFutureLogger.addHandler(aggregateFutureLogHandler);
   }
 
-  @Override protected void tearDown() throws Exception {
+  @Override
+  protected void tearDown() throws Exception {
     /*
      * Clear interrupt for future tests.
      *
      * (Ideally we would perform interrupts only in threads that we create, but
      * it's hard to imagine that anything will break in practice.)
      */
-    Thread.interrupted();
-    combinedFutureLogger.removeHandler(combinedFutureLogHandler);
+    clearInterrupt();
+    aggregateFutureLogger.removeHandler(aggregateFutureLogHandler);
     super.tearDown();
   }
 
@@ -151,14 +151,60 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("immediateCancelledFuture")
   public void testImmediateCancelledFuture() throws Exception {
-    ListenableFuture<String> future =
-        Futures.immediateCancelledFuture();
+    ListenableFuture<String> future = CallerClass1.immediateCancelledFuture();
     assertTrue(future.isCancelled());
+
+    try {
+      CallerClass2.get(future);
+      fail();
+    } catch (CancellationException e) {
+      // There should be two CancellationException chained together.  The outer one should have the
+      // stack trace of where the get() call was made, and the inner should have the stack trace of
+      // where the immediateCancelledFuture() call was made.
+      List<StackTraceElement> stackTrace = ImmutableList.copyOf(e.getStackTrace());
+      assertFalse(Iterables.any(stackTrace, hasClassName(CallerClass1.class)));
+      assertTrue(Iterables.any(stackTrace, hasClassName(CallerClass2.class)));
+
+      assertThat(e.getCause()).isInstanceOf(CancellationException.class);
+      stackTrace = ImmutableList.copyOf(e.getCause().getStackTrace());
+      assertTrue(Iterables.any(stackTrace, hasClassName(CallerClass1.class)));
+      assertFalse(Iterables.any(stackTrace, hasClassName(CallerClass2.class)));
+    }
+  }
+
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private static Predicate<StackTraceElement> hasClassName(final Class<?> clazz) {
+    return new Predicate<StackTraceElement>() {
+      @Override
+      public boolean apply(StackTraceElement element) {
+        return element.getClassName().equals(clazz.getName());
+      }
+    };
+  }
+
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private static final class CallerClass1 {
+
+    static ListenableFuture<String> immediateCancelledFuture() {
+      return Futures.immediateCancelledFuture();
+    }
+  }
+
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private static final class CallerClass2 {
+
+    static <V> V get(ListenableFuture<V> future) throws ExecutionException, InterruptedException {
+      return future.get();
+    }
   }
 
-  private static class MyException extends Exception {}
+  private static class MyException extends Exception {
+
+  }
 
+  @GwtIncompatible("immediateCheckedFuture")
   public void testImmediateCheckedFuture() throws Exception {
     CheckedFuture<String, MyException> future = Futures.immediateCheckedFuture(
         DATA1);
@@ -168,6 +214,7 @@ public class FuturesTest extends TestCase {
     assertSame(DATA1, future.checkedGet(0L, TimeUnit.MILLISECONDS));
   }
 
+  @GwtIncompatible("immediateCheckedFuture")
   public void testMultipleImmediateCheckedFutures() throws Exception {
     CheckedFuture<String, MyException> future1 = Futures.immediateCheckedFuture(
         DATA1);
@@ -181,6 +228,7 @@ public class FuturesTest extends TestCase {
     assertSame(DATA2, future2.checkedGet(0L, TimeUnit.MILLISECONDS));
   }
 
+  @GwtIncompatible("immediateFailedCheckedFuture")
   public void testImmediateFailedCheckedFuture() throws Exception {
     MyException exception = new MyException();
     CheckedFuture<String, MyException> future =
@@ -204,10 +252,21 @@ public class FuturesTest extends TestCase {
   }
 
   // Class hierarchy for generics sanity checks
-  private static class Foo {}
-  private static class FooChild extends Foo {}
-  private static class Bar {}
-  private static class BarChild extends Bar {}
+  private static class Foo {
+
+  }
+
+  private static class FooChild extends Foo {
+
+  }
+
+  private static class Bar {
+
+  }
+
+  private static class BarChild extends Bar {
+
+  }
 
   public void testTransform_genericsNull() throws Exception {
     ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
@@ -220,7 +279,8 @@ public class FuturesTest extends TestCase {
     ListenableFuture<FooChild> future = Futures.immediateFuture(null);
     final BarChild barChild = new BarChild();
     Function<Foo, BarChild> function = new Function<Foo, BarChild>() {
-      @Override public BarChild apply(Foo unused) {
+      @Override
+      public BarChild apply(Foo unused) {
         return barChild;
       }
     };
@@ -231,7 +291,8 @@ public class FuturesTest extends TestCase {
   public void testTransform_cancelPropagatesToInput() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
-      @Override public ListenableFuture<Bar> apply(Foo unused) {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
         throw new AssertionFailedError("Unexpeted call to apply.");
       }
     };
@@ -243,7 +304,8 @@ public class FuturesTest extends TestCase {
   public void testTransform_interruptPropagatesToInput() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
-      @Override public ListenableFuture<Bar> apply(Foo unused) {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
         throw new AssertionFailedError("Unexpeted call to apply.");
       }
     };
@@ -256,7 +318,8 @@ public class FuturesTest extends TestCase {
     ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
     final SettableFuture<Bar> secondary = SettableFuture.create();
     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
-      @Override public ListenableFuture<Bar> apply(Foo unused) {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
         return secondary;
       }
     };
@@ -270,7 +333,8 @@ public class FuturesTest extends TestCase {
     ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
     final SettableFuture<Bar> secondary = SettableFuture.create();
     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
-      @Override public ListenableFuture<Bar> apply(Foo unused) {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
         return secondary;
       }
     };
@@ -279,6 +343,100 @@ public class FuturesTest extends TestCase {
     assertTrue(secondary.wasInterrupted());
   }
 
+  public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transformAsync(input, function).cancel(false));
+    assertTrue(input.isCancelled());
+    assertFalse(input.wasInterrupted());
+  }
+
+  public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+    SettableFuture<Foo> input = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        throw new AssertionFailedError("Unexpeted call to apply.");
+      }
+    };
+    assertTrue(Futures.transformAsync(input, function).cancel(true));
+    assertTrue(input.isCancelled());
+    assertTrue(input.wasInterrupted());
+  }
+
+  @GwtIncompatible("threads")
+
+  public void testTransformAsync_interruptPropagatesToTransformingThread() throws Exception {
+    SettableFuture<String> input = SettableFuture.create();
+    final CountDownLatch inFunction = new CountDownLatch(1);
+    final CountDownLatch shouldCompleteFunction = new CountDownLatch(1);
+    final CountDownLatch gotException = new CountDownLatch(1);
+    AsyncFunction<String, String> function = new AsyncFunction<String, String>() {
+      @Override
+      public ListenableFuture<String> apply(String s) throws Exception {
+        inFunction.countDown();
+        try {
+          shouldCompleteFunction.await();
+        } catch (InterruptedException expected) {
+          gotException.countDown();
+          throw expected;
+        }
+        return immediateFuture("a");
+      }
+    };
+
+    ListenableFuture<String> futureResult =
+        Futures.transformAsync(input, function, newSingleThreadExecutor());
+
+    input.set("value");
+    inFunction.await();
+    futureResult.cancel(true);
+    shouldCompleteFunction.countDown();
+    try {
+      futureResult.get();
+      fail();
+    } catch (CancellationException expected) {}
+    // TODO(cpovirk): implement interruption, updating this test:
+    // https://github.com/google/guava/issues/1989
+    assertEquals(1, gotException.getCount());
+    // gotException.await();
+  }
+
+  public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transformAsync(immediate, function).cancel(false));
+    assertTrue(secondary.isCancelled());
+    assertFalse(secondary.wasInterrupted());
+  }
+
+  public void testTransformAsync_interruptPropagatesToAsyncOutput()
+      throws Exception {
+    ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+    final SettableFuture<Bar> secondary = SettableFuture.create();
+    AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+      @Override
+      public ListenableFuture<Bar> apply(Foo unused) {
+        return secondary;
+      }
+    };
+    assertTrue(Futures.transformAsync(immediate, function).cancel(true));
+    assertTrue(secondary.isCancelled());
+    assertTrue(secondary.wasInterrupted());
+  }
+
+  @GwtIncompatible("newDirectExecutorService")
   public void testTransform_rejectionPropagatesToOutput()
       throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
@@ -291,23 +449,24 @@ public class FuturesTest extends TestCase {
       transformed.get(5, TimeUnit.SECONDS);
       fail();
     } catch (ExecutionException expected) {
-      assertTrue(expected.getCause() instanceof RejectedExecutionException);
+      assertThat(expected.getCause()).isInstanceOf(RejectedExecutionException.class);
     }
   }
 
   /**
-   * Tests that the function is invoked only once, even if it throws an
-   * exception.
+   * Tests that the function is invoked only once, even if it throws an exception.
    */
   public void testTransformValueRemainsMemoized() throws Exception {
     class Holder {
+
       int value = 2;
     }
     final Holder holder = new Holder();
 
     // This function adds the holder's value to the input value.
     Function<Integer, Integer> adder = new Function<Integer, Integer>() {
-      @Override public Integer apply(Integer from) {
+      @Override
+      public Integer apply(Integer from) {
         return from + holder.value;
       }
     };
@@ -343,14 +502,19 @@ public class FuturesTest extends TestCase {
         1000, TimeUnit.SECONDS).intValue());
   }
 
-  static class MyError extends Error {}
-  static class MyRuntimeException extends RuntimeException {}
+  static class MyError extends Error {
+
+  }
+
+  static class MyRuntimeException extends RuntimeException {
+
+  }
 
   /**
-   * Test that the function is invoked only once, even if it throws an
-   * exception. Also, test that that function's result is wrapped in an
-   * ExecutionException.
+   * Test that the function is invoked only once, even if it throws an exception. Also, test that
+   * that function's result is wrapped in an ExecutionException.
    */
+  @GwtIncompatible("reflection")
   public void testTransformExceptionRemainsMemoized() throws Throwable {
     // We need to test with two input futures since ExecutionList.execute
     // doesn't catch Errors and we cannot depend on the order that our
@@ -381,6 +545,7 @@ public class FuturesTest extends TestCase {
     runGetIdempotencyTest(errorComposedFuture, MyError.class);
   }
 
+  @GwtIncompatible("reflection")
   private static void runGetIdempotencyTest(Future<Integer> transformedFuture,
       Class<? extends Throwable> expectedExceptionClass) throws Throwable {
     for (int i = 0; i < 5; i++) {
@@ -395,11 +560,13 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static Function<Integer, Integer> newOneTimeExceptionThrower() {
     return new Function<Integer, Integer>() {
       int calls = 0;
 
-      @Override public Integer apply(Integer from) {
+      @Override
+      public Integer apply(Integer from) {
         if (++calls > 1) {
           fail();
         }
@@ -408,11 +575,13 @@ public class FuturesTest extends TestCase {
     };
   }
 
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static Function<Integer, Integer> newOneTimeErrorThrower() {
     return new Function<Integer, Integer>() {
       int calls = 0;
 
-      @Override public Integer apply(Integer from) {
+      @Override
+      public Integer apply(Integer from) {
         if (++calls > 1) {
           fail();
         }
@@ -423,6 +592,7 @@ public class FuturesTest extends TestCase {
 
   // TODO(cpovirk): top-level class?
   static class ExecutorSpy implements Executor {
+
     Executor delegate;
     boolean wasExecuted;
 
@@ -430,7 +600,8 @@ public class FuturesTest extends TestCase {
       this.delegate = delegate;
     }
 
-    @Override public void execute(Runnable command) {
+    @Override
+    public void execute(Runnable command) {
       delegate.execute(command);
       wasExecuted = true;
     }
@@ -450,22 +621,25 @@ public class FuturesTest extends TestCase {
     assertTrue(spy.wasExecuted);
   }
 
+  @GwtIncompatible("lazyTransform")
   public void testLazyTransform() throws Exception {
     FunctionSpy<Object, String> spy =
         new FunctionSpy<Object, String>(Functions.constant("bar"));
     Future<String> input = Futures.immediateFuture("foo");
     Future<String> transformed = Futures.lazyTransform(input, spy);
-    assertEquals(0, spy.getApplyCount());
+    spy.verifyCallCount(0);
     assertEquals("bar", transformed.get());
-    assertEquals(1, spy.getApplyCount());
+    spy.verifyCallCount(1);
     assertEquals("bar", transformed.get());
-    assertEquals(2, spy.getApplyCount());
+    spy.verifyCallCount(2);
   }
 
+  @GwtIncompatible("lazyTransform")
   public void testLazyTransform_exception() throws Exception {
     final RuntimeException exception = new RuntimeException("deliberate");
     Function<Integer, String> function = new Function<Integer, String>() {
-      @Override public String apply(Integer input) {
+      @Override
+      public String apply(Integer input) {
         throw exception;
       }
     };
@@ -498,33 +672,116 @@ public class FuturesTest extends TestCase {
       return delegate.apply(input);
     }
 
-    public int getApplyCount() {
-      return applyCount;
+    void verifyCallCount(int expected) {
+      assertThat(applyCount).isEqualTo(expected);
     }
   }
 
-  @SuppressWarnings("unchecked")
+  private static <I, O> FunctionSpy<I, O> spy(Function<I, O> delegate) {
+    return new FunctionSpy<I, O>(delegate);
+  }
+
+  private static <X extends Throwable, V> Function<X, V> unexpectedFunction() {
+    return new Function<X, V>() {
+      @Override
+      public V apply(X t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  private static class FutureFallbackSpy<V> implements FutureFallback<V> {
+
+    private int count;
+    private final FutureFallback<V> delegate;
+
+    public FutureFallbackSpy(FutureFallback<V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public final ListenableFuture<V> create(Throwable t) throws Exception {
+      count++;
+      return delegate.create(t);
+    }
+
+    void verifyCallCount(int expected) {
+      assertThat(count).isEqualTo(expected);
+    }
+  }
+
+  private static <V> FutureFallbackSpy<V> spy(FutureFallback<V> delegate) {
+    return new FutureFallbackSpy<V>(delegate);
+  }
+
+  private static <V> FutureFallback<V> unexpectedFallback() {
+    return new FutureFallback<V>() {
+      @Override
+      public ListenableFuture<V> create(Throwable t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  private static class AsyncFunctionSpy<X extends Throwable, V> implements AsyncFunction<X, V> {
+    private int count;
+    private final AsyncFunction<X, V> delegate;
+
+    public AsyncFunctionSpy(AsyncFunction<X, V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public final ListenableFuture<V> apply(X t) throws Exception {
+      count++;
+      return delegate.apply(t);
+    }
+
+    void verifyCallCount(int expected) {
+      assertThat(count).isEqualTo(expected);
+    }
+  }
+
+  private static <X extends Throwable, V> AsyncFunctionSpy<X, V> spy(AsyncFunction<X, V> delegate) {
+    return new AsyncFunctionSpy<X, V>(delegate);
+  }
+
+  private static <X extends Throwable, V> AsyncFunction<X, V> unexpectedAsyncFunction() {
+    return new AsyncFunction<X, V>() {
+      @Override
+      public ListenableFuture<V> apply(X t) {
+        throw newAssertionError("Unexpected fallback", t);
+      }
+    };
+  }
+
+  /** Alternative to AssertionError(String, Throwable), which doesn't exist in GWT 2.6.1. */
+  private static AssertionError newAssertionError(String message, Throwable cause) {
+    AssertionError e = new AssertionError(message);
+    e.initCause(cause);
+    return e;
+  }
+
   public void testWithFallback_inputDoesNotRaiseException() throws Exception {
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
+    FutureFallback<Integer> fallback = unexpectedFallback();
     ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
-
-    mocksControl.replay();
     ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(originalFuture, fallback);
     assertEquals(7, faultToleranteFuture.get().intValue());
-    mocksControl.verify();
   }
 
-  @SuppressWarnings("unchecked")
   public void testWithFallback_inputRaisesException() throws Exception {
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-    RuntimeException raisedException = new RuntimeException();
-    expect(fallback.create(raisedException)).andReturn(Futures.immediateFuture(20));
+    final RuntimeException raisedException = new RuntimeException();
+    FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return Futures.immediateFuture(20);
+      }
+    });
     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
-
-    mocksControl.replay();
-    ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
-    assertEquals(20, faultToleranteFuture.get().intValue());
-    mocksControl.verify();
+    ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(failingFuture, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
   }
 
   public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
@@ -533,15 +790,16 @@ public class FuturesTest extends TestCase {
   }
 
   public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
-    Exception expectedException = new Exception() {};
+    Exception expectedException = new Exception() {
+    };
     runExpectedExceptionFallbackTest(expectedException, false);
   }
 
-  @SuppressWarnings("unchecked")
   public void testWithFallback_fallbackGeneratesError() throws Exception {
     final Error error = new Error("deliberate");
     FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
-      @Override public ListenableFuture<Integer> create(Throwable t) throws Exception {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
         throw error;
       }
     };
@@ -560,27 +818,26 @@ public class FuturesTest extends TestCase {
   }
 
   public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
-    Exception expectedException = new Exception() {};
+    Exception expectedException = new Exception() {
+    };
     runExpectedExceptionFallbackTest(expectedException, true);
   }
 
-  @SuppressWarnings("unchecked")
   private void runExpectedExceptionFallbackTest(
-      Throwable expectedException, boolean wrapInFuture) throws Exception {
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-    RuntimeException raisedException = new RuntimeException();
-    if (!wrapInFuture) {
-      // Exception is thrown in the body of the "fallback" method.
-      expect(fallback.create(raisedException)).andThrow(expectedException);
-    } else {
-      // Exception is wrapped in a future and returned.
-      expect(fallback.create(raisedException)).andReturn(
-          Futures.<Integer>immediateFailedFuture(expectedException));
-    }
+      final Exception expectedException, final boolean wrapInFuture) throws Exception {
+    FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        if (!wrapInFuture) {
+          throw expectedException;
+        } else {
+          return Futures.immediateFailedFuture(expectedException);
+        }
+      }
+    });
 
-    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
 
-    mocksControl.replay();
     ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
     try {
       faultToleranteFuture.get();
@@ -588,7 +845,7 @@ public class FuturesTest extends TestCase {
     } catch (ExecutionException ee) {
       assertSame(expectedException, ee.getCause());
     }
-    mocksControl.verify();
+    fallback.verifyCallCount(1);
   }
 
   public void testWithFallback_fallbackNotReady() throws Exception {
@@ -605,122 +862,567 @@ public class FuturesTest extends TestCase {
     assertEquals(1, (int) derived.get());
   }
 
-  @SuppressWarnings("unchecked")
   public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
     SettableFuture<Integer> primary = SettableFuture.create();
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-
-    mocksControl.replay();
+    FutureFallback<Integer> fallback = unexpectedFallback();
     ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
     derived.cancel(true);
     assertTrue(primary.isCancelled());
     assertTrue(primary.wasInterrupted());
-    mocksControl.verify();
   }
 
-  @SuppressWarnings("unchecked")
   public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
     SettableFuture<Integer> primary = SettableFuture.create();
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-
-    mocksControl.replay();
+    FutureFallback<Integer> fallback = unexpectedFallback();
     ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
     derived.cancel(false);
     assertTrue(primary.isCancelled());
     assertFalse(primary.wasInterrupted());
-    mocksControl.verify();
   }
 
+  @GwtIncompatible("mocks")
   @SuppressWarnings("unchecked")
   public void testWithFallback_resultCancelledAfterFallback() throws Exception {
-    SettableFuture<Integer> secondary = SettableFuture.create();
-    FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-    RuntimeException raisedException = new RuntimeException();
-    expect(fallback.create(raisedException)).andReturn(secondary);
+    final SettableFuture<Integer> secondary = SettableFuture.create();
+    final RuntimeException raisedException = new RuntimeException();
+    FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+      @Override
+      public ListenableFuture<Integer> create(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return secondary;
+      }
+    });
+
     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
 
-    mocksControl.replay();
     ListenableFuture<Integer> derived = Futures.withFallback(failingFuture, fallback);
     derived.cancel(false);
     assertTrue(secondary.isCancelled());
     assertFalse(secondary.wasInterrupted());
-    mocksControl.verify();
+    fallback.verifyCallCount(1);
   }
 
-  public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
-    ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
+  public void testWithFallback_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
     ListenableFuture<?> chainedFuture =
-        Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
-    assertNull(chainedFuture.get());
+        Futures.withFallback(inputFuture, new FutureFallback<Integer>() {
+          @Override
+          public ListenableFuture<Integer> create(Throwable t) {
+            return null;
+          }
+        });
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("FutureFallback.create returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
   }
 
-  private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
-      final ListenableFuture<O> output) {
-    return new AsyncFunction<I, O>() {
+  // catchingAsync tests cloned from the old withFallback tests:
+
+  public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+    assertEquals(7, faultToleranteFuture.get().intValue());
+  }
+
+  public void testCatchingAsync_inputRaisesException() throws Exception {
+    final RuntimeException raisedException = new RuntimeException();
+    AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
       @Override
-      public ListenableFuture<O> apply(I input) {
-        return output;
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return Futures.immediateFuture(20);
       }
-    };
+    });
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
   }
 
-  public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
-    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
-    final BarChild barChild = new BarChild();
-    AsyncFunction<Foo, BarChild> function =
-        new AsyncFunction<Foo, BarChild>() {
-          @Override public AbstractFuture<BarChild> apply(Foo unused) {
-            AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {};
-            future.set(barChild);
-            return future;
-          }
-        };
-    Bar bar = Futures.transform(future, function).get();
-    assertSame(barChild, bar);
+  public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingAsyncTest(expectedException, false);
   }
 
-  public void testTransform_asyncFunction_timeout()
-      throws InterruptedException, ExecutionException {
-    AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
-    ListenableFuture<Integer> future = Futures.transform(
-        SettableFuture.<String>create(), function);
-    try {
-      future.get(1, TimeUnit.MILLISECONDS);
-      fail();
-    } catch (TimeoutException expected) {}
+  public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionCatchingAsyncTest(expectedException, false);
   }
 
-  public void testTransform_asyncFunction_error() throws InterruptedException {
+  public void testCatchingAsync_fallbackGeneratesError() throws Exception {
     final Error error = new Error("deliberate");
-    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
-      @Override public ListenableFuture<Integer> apply(String input) {
+    AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
         throw error;
       }
     };
-    SettableFuture<String> inputFuture = SettableFuture.create();
-    ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
-    inputFuture.set("value");
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
     try {
-      outputFuture.get();
-      fail("should have thrown error");
-    } catch (ExecutionException e) {
-      assertSame(error, e.getCause());
+      Futures.catchingAsync(failingFuture, Throwable.class, fallback).get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException expected) {
+      assertSame(error, expected.getCause());
     }
   }
 
-  public void testTransform_asyncFunction_cancelledWhileApplyingFunction()
-      throws InterruptedException, ExecutionException {
-    final CountDownLatch inFunction = new CountDownLatch(1);
-    final CountDownLatch functionDone = new CountDownLatch(1);
-    final SettableFuture<Integer> resultFuture = SettableFuture.create();
-    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
-      @Override public ListenableFuture<Integer> apply(String input) throws Exception {
-        inFunction.countDown();
-        functionDone.await();
-        return resultFuture;
-      }
-    };
-    SettableFuture<String> inputFuture = SettableFuture.create();
+  public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingAsyncTest(expectedException, true);
+  }
+
+  public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+    Exception expectedException = new Exception() {
+    };
+    runExpectedExceptionCatchingAsyncTest(expectedException, true);
+  }
+
+  private void runExpectedExceptionCatchingAsyncTest(
+      final Exception expectedException, final boolean wrapInFuture) throws Exception {
+    AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        if (!wrapInFuture) {
+          throw expectedException;
+        } else {
+          return Futures.immediateFailedFuture(expectedException);
+        }
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+    try {
+      faultToleranteFuture.get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException ee) {
+      assertSame(expectedException, ee.getCause());
+    }
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatchingAsync_fallbackNotReady() throws Exception {
+    ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+    final SettableFuture<Integer> secondary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) {
+        return secondary;
+      }
+    };
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    secondary.set(1);
+    assertEquals(1, (int) derived.get());
+  }
+
+  public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    derived.cancel(true);
+    assertTrue(primary.isCancelled());
+    assertTrue(primary.wasInterrupted());
+  }
+
+  public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+    ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+    derived.cancel(false);
+    assertTrue(primary.isCancelled());
+    assertFalse(primary.wasInterrupted());
+  }
+
+  @GwtIncompatible("mocks")
+  @SuppressWarnings("unchecked")
+  public void testCatchingAsync_resultCancelledAfterFallback() throws Exception {
+    final SettableFuture<Integer> secondary = SettableFuture.create();
+    final RuntimeException raisedException = new RuntimeException();
+    AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+        assertThat(t).isSameAs(raisedException);
+        return secondary;
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+
+    ListenableFuture<Integer> derived =
+        Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+    derived.cancel(false);
+    assertTrue(secondary.isCancelled());
+    assertFalse(secondary.wasInterrupted());
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+    ListenableFuture<?> chainedFuture = Futures.catchingAsync(inputFuture, Throwable.class,
+        new AsyncFunction<Throwable, Integer>() {
+          @Override
+          @SuppressWarnings("AsyncFunctionReturnsNull")
+          public ListenableFuture<Integer> apply(Throwable t) {
+            return null;
+          }
+        });
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  @GwtIncompatible("threads")
+
+  public void testCatchingAsync_interruptPropagatesToTransformingThread() throws Exception {
+    SettableFuture<String> input = SettableFuture.create();
+    final CountDownLatch inFunction = new CountDownLatch(1);
+    final CountDownLatch shouldCompleteFunction = new CountDownLatch(1);
+    final CountDownLatch gotException = new CountDownLatch(1);
+    AsyncFunction<Throwable, String> function = new AsyncFunction<Throwable, String>() {
+      @Override
+      public ListenableFuture<String> apply(Throwable t) throws Exception {
+        inFunction.countDown();
+        try {
+          shouldCompleteFunction.await();
+        } catch (InterruptedException expected) {
+          gotException.countDown();
+          throw expected;
+        }
+        return immediateFuture("a");
+      }
+    };
+
+    ListenableFuture<String> futureResult =
+        Futures.catchingAsync(input, Exception.class, function, newSingleThreadExecutor());
+
+    input.setException(new Exception());
+    inFunction.await();
+    futureResult.cancel(true);
+    shouldCompleteFunction.countDown();
+    try {
+      futureResult.get();
+      fail();
+    } catch (CancellationException expected) {}
+    // TODO(cpovirk): implement interruption, updating this test:
+    // https://github.com/google/guava/issues/1989
+    assertEquals(1, gotException.getCount());
+    // gotException.await();
+  }
+
+  // catching tests cloned from the old withFallback tests:
+
+  public void testCatching_inputDoesNotRaiseException() throws Exception {
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catching(originalFuture, Throwable.class, fallback);
+    assertEquals(7, faultToleranteFuture.get().intValue());
+  }
+
+  public void testCatching_inputRaisesException() throws Exception {
+    final RuntimeException raisedException = new RuntimeException();
+    FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        assertThat(t).isSameAs(raisedException);
+        return 20;
+      }
+    });
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(failingFuture, Throwable.class, fallback);
+    assertEquals(20, faultTolerantFuture.get().intValue());
+    fallback.verifyCallCount(1);
+  }
+
+  public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+    RuntimeException expectedException = new RuntimeException();
+    runExpectedExceptionCatchingTest(expectedException);
+  }
+
+  /*
+   * catching() uses a plain Function, so there's no
+   * testCatching_fallbackGeneratesCheckedException().
+   */
+
+  public void testCatching_fallbackGeneratesError() throws Exception {
+    final Error error = new Error("deliberate");
+    Function<Throwable, Integer> fallback = new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        throw error;
+      }
+    };
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+    try {
+      Futures.catching(failingFuture, Throwable.class, fallback).get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException expected) {
+      assertSame(error, expected.getCause());
+    }
+  }
+
+  /*
+   * catching() uses a plain Function, so there's no testCatching_fallbackReturnsRuntimeException()
+   * or testCatching_fallbackReturnsCheckedException().
+   */
+
+  private void runExpectedExceptionCatchingTest(final RuntimeException expectedException)
+      throws Exception {
+    FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+      @Override
+      public Integer apply(Throwable t) {
+        throw expectedException;
+      }
+    });
+
+    ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+    ListenableFuture<Integer> faultToleranteFuture =
+        Futures.catching(failingFuture, Throwable.class, fallback);
+    try {
+      faultToleranteFuture.get();
+      fail("An Exception should have been thrown!");
+    } catch (ExecutionException ee) {
+      assertSame(expectedException, ee.getCause());
+    }
+    fallback.verifyCallCount(1);
+  }
+
+  // catching() uses a plain Function, so there's no testCatching_fallbackNotReady().
+
+  public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+    derived.cancel(true);
+    assertTrue(primary.isCancelled());
+    assertTrue(primary.wasInterrupted());
+  }
+
+  public void testCatching_resultCancelledBeforeFallback() throws Exception {
+    SettableFuture<Integer> primary = SettableFuture.create();
+    Function<Throwable, Integer> fallback = unexpectedFunction();
+    ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+    derived.cancel(false);
+    assertTrue(primary.isCancelled());
+    assertFalse(primary.wasInterrupted());
+  }
+
+  // catching() uses a plain Function, so there's no testCatching_resultCancelledAfterFallback().
+
+  // catching() uses a plain Function, so there's no testCatching_nullInsteadOfFuture().
+
+  // Some tests of the exceptionType parameter:
+
+  public void testCatching_Throwable() throws Exception {
+    Function<Throwable, Integer> fallback = functionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(originalFuture, Throwable.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  @GwtIncompatible("non-Throwable exceptionType")
+  public void testCatching_customTypeMatch() throws Exception {
+    Function<IOException, Integer> fallback = functionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new FileNotFoundException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(originalFuture, IOException.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  @GwtIncompatible("non-Throwable exceptionType")
+  public void testCatching_customTypeNoMatch() throws Exception {
+    Function<IOException, Integer> fallback = functionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new RuntimeException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catching(originalFuture, IOException.class, fallback);
+    try {
+      faultTolerantFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      assertThat(expected.getCause()).isInstanceOf(RuntimeException.class);
+    }
+  }
+
+  public void testCatchingAsync_Throwable() throws Exception {
+    AsyncFunction<Throwable, Integer> fallback = asyncFunctionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  @GwtIncompatible("non-Throwable exceptionType")
+  public void testCatchingAsync_customTypeMatch() throws Exception {
+    AsyncFunction<IOException, Integer> fallback = asyncFunctionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new FileNotFoundException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(originalFuture, IOException.class, fallback);
+    assertEquals(1, (int) faultTolerantFuture.get());
+  }
+
+  @GwtIncompatible("non-Throwable exceptionType")
+  public void testCatchingAsync_customTypeNoMatch() throws Exception {
+    AsyncFunction<IOException, Integer> fallback = asyncFunctionReturningOne();
+    ListenableFuture<Integer> originalFuture = immediateFailedFuture(new RuntimeException());
+    ListenableFuture<Integer> faultTolerantFuture =
+        Futures.catchingAsync(originalFuture, IOException.class, fallback);
+    try {
+      faultTolerantFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      assertThat(expected.getCause()).isInstanceOf(RuntimeException.class);
+    }
+  }
+
+  @GwtIncompatible("newDirectExecutorService")
+  public void testCatchingAsync_rejectionPropagatesToOutput() throws Exception {
+    SettableFuture<String> input = SettableFuture.create();
+    ExecutorService executor = newDirectExecutorService();
+    ListenableFuture<String> transformed =
+        Futures.catching(input, Throwable.class, Functions.toStringFunction(), executor);
+    executor.shutdown();
+    input.setException(new Exception());
+    try {
+      transformed.get(5, TimeUnit.SECONDS);
+      fail();
+    } catch (ExecutionException expected) {
+      assertThat(expected.getCause()).isInstanceOf(RejectedExecutionException.class);
+    }
+  }
+
+  private <X extends Throwable> Function<X, Integer> functionReturningOne() {
+    return new Function<X, Integer>() {
+      @Override
+      public Integer apply(X t) {
+        return 1;
+      }
+    };
+  }
+
+  private <X extends Throwable> AsyncFunction<X, Integer> asyncFunctionReturningOne() {
+    return new AsyncFunction<X, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(X t) {
+        return immediateFuture(1);
+      }
+    };
+  }
+
+  private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
+      final ListenableFuture<O> output) {
+    return new AsyncFunction<I, O>() {
+      @Override
+      public ListenableFuture<O> apply(I input) {
+        return output;
+      }
+    };
+  }
+
+  public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+    ListenableFuture<?> nullFuture = immediateFuture(null);
+    ListenableFuture<?> chainedFuture =
+        Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
+    assertNull(chainedFuture.get());
+  }
+
+  public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+    final BarChild barChild = new BarChild();
+    AsyncFunction<Foo, BarChild> function =
+        new AsyncFunction<Foo, BarChild>() {
+          @Override
+          public AbstractFuture<BarChild> apply(Foo unused) {
+            AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+            };
+            future.set(barChild);
+            return future;
+          }
+        };
+    Bar bar = Futures.transform(future, function).get();
+    assertSame(barChild, bar);
+  }
+
+  @GwtIncompatible("get() timeout")
+  public void testTransform_asyncFunction_timeout()
+      throws InterruptedException, ExecutionException {
+    AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
+    ListenableFuture<Integer> future = Futures.transform(
+        SettableFuture.<String>create(), function);
+    try {
+      future.get(1, TimeUnit.MILLISECONDS);
+      fail();
+    } catch (TimeoutException expected) {
+    }
+  }
+
+  public void testTransform_asyncFunction_error() throws InterruptedException {
+    final Error error = new Error("deliberate");
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) {
+        throw error;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
+    inputFuture.set("value");
+    try {
+      outputFuture.get();
+      fail("should have thrown error");
+    } catch (ExecutionException e) {
+      assertSame(error, e.getCause());
+    }
+  }
+
+  public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<?> inputFuture = immediateFuture("a");
+    ListenableFuture<?> chainedFuture =
+        Futures.transform(inputFuture, constantAsyncFunction(null));
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  @GwtIncompatible("threads")
+
+  public void testTransform_asyncFunction_cancelledWhileApplyingFunction()
+      throws InterruptedException, ExecutionException {
+    final CountDownLatch inFunction = new CountDownLatch(1);
+    final CountDownLatch functionDone = new CountDownLatch(1);
+    final SettableFuture<Integer> resultFuture = SettableFuture.create();
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) throws Exception {
+        inFunction.countDown();
+        functionDone.await();
+        return resultFuture;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
     ListenableFuture<Integer> future = Futures.transform(
         inputFuture, function, Executors.newSingleThreadExecutor());
     inputFuture.set("value");
@@ -730,11 +1432,154 @@ public class FuturesTest extends TestCase {
     try {
       future.get();
       fail();
-    } catch (CancellationException expected) {}
+    } catch (CancellationException expected) {
+    }
     try {
       resultFuture.get();
       fail();
-    } catch (CancellationException expected) {}
+    } catch (CancellationException expected) {
+    }
+  }
+
+  @GwtIncompatible("threads")
+
+  public void testTransform_asyncFunction_cancelledBeforeApplyingFunction()
+      throws InterruptedException {
+    final AtomicBoolean functionCalled = new AtomicBoolean();
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) throws Exception {
+        functionCalled.set(true);
+        return Futures.immediateFuture(1);
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ExecutorService executor = newSingleThreadExecutor();
+    ListenableFuture<Integer> future = Futures.transform(
+        inputFuture, function, executor);
+
+    // Pause the executor.
+    final CountDownLatch beforeFunction = new CountDownLatch(1);
+    executor.submit(new Runnable() {
+      @Override
+      public void run() {
+        awaitUninterruptibly(beforeFunction);
+      }
+    });
+
+    // Cancel the future after making input available.
+    inputFuture.set("value");
+    future.cancel(false);
+
+    // Unpause the executor.
+    beforeFunction.countDown();
+    executor.awaitTermination(5, TimeUnit.SECONDS);
+
+    assertFalse(functionCalled.get());
+  }
+
+  public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+    ListenableFuture<?> nullFuture = immediateFuture(null);
+    ListenableFuture<?> chainedFuture =
+        Futures.transformAsync(nullFuture, constantAsyncFunction(nullFuture));
+    assertNull(chainedFuture.get());
+  }
+
+  public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+    ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+    final BarChild barChild = new BarChild();
+    AsyncFunction<Foo, BarChild> function =
+        new AsyncFunction<Foo, BarChild>() {
+          @Override
+          public AbstractFuture<BarChild> apply(Foo unused) {
+            AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+            };
+            future.set(barChild);
+            return future;
+          }
+        };
+    Bar bar = Futures.transformAsync(future, function).get();
+    assertSame(barChild, bar);
+  }
+
+  @GwtIncompatible("get() timeout")
+  public void testTransformAsync_asyncFunction_timeout()
+      throws InterruptedException, ExecutionException {
+    AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
+    ListenableFuture<Integer> future = Futures.transformAsync(
+        SettableFuture.<String>create(), function);
+    try {
+      future.get(1, TimeUnit.MILLISECONDS);
+      fail();
+    } catch (TimeoutException expected) {
+    }
+  }
+
+  public void testTransformAsync_asyncFunction_error() throws InterruptedException {
+    final Error error = new Error("deliberate");
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) {
+        throw error;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ListenableFuture<Integer> outputFuture = Futures.transformAsync(inputFuture, function);
+    inputFuture.set("value");
+    try {
+      outputFuture.get();
+      fail("should have thrown error");
+    } catch (ExecutionException e) {
+      assertSame(error, e.getCause());
+    }
+  }
+
+  public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+    ListenableFuture<?> inputFuture = immediateFuture("a");
+    ListenableFuture<?> chainedFuture =
+        Futures.transformAsync(inputFuture, constantAsyncFunction(null));
+    try {
+      chainedFuture.get();
+      fail();
+    } catch (ExecutionException expected) {
+      NullPointerException cause = (NullPointerException) expected.getCause();
+      assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+    }
+  }
+
+  @GwtIncompatible("threads")
+
+  public void testTransformAsync_asyncFunction_cancelledWhileApplyingFunction()
+      throws InterruptedException, ExecutionException {
+    final CountDownLatch inFunction = new CountDownLatch(1);
+    final CountDownLatch functionDone = new CountDownLatch(1);
+    final SettableFuture<Integer> resultFuture = SettableFuture.create();
+    AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+      @Override
+      public ListenableFuture<Integer> apply(String input) throws Exception {
+        inFunction.countDown();
+        functionDone.await();
+        return resultFuture;
+      }
+    };
+    SettableFuture<String> inputFuture = SettableFuture.create();
+    ListenableFuture<Integer> future = Futures.transformAsync(
+        inputFuture, function, Executors.newSingleThreadExecutor());
+    inputFuture.set("value");
+    inFunction.await();
+    future.cancel(false);
+    functionDone.countDown();
+    try {
+      future.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
+    try {
+      resultFuture.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
   }
 
   public void testDereference_genericsWildcard() throws Exception {
@@ -784,16 +1629,17 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * Runnable which can be called a single time, and only after
-   * {@link #expectCall} is called.
+   * Runnable which can be called a single time, and only after {@link #expectCall} is called.
    */
   // TODO(cpovirk): top-level class?
   static class SingleCallListener implements Runnable {
+
     private boolean expectCall = false;
     private final CountDownLatch calledCountDown =
         new CountDownLatch(1);
 
-    @Override public void run() {
+    @Override
+    public void run() {
       assertTrue("Listener called before it was expected", expectCall);
       assertFalse("Listener called more than once", wasCalled());
       calledCountDown.countDown();
@@ -820,7 +1666,7 @@ public class FuturesTest extends TestCase {
     SettableFuture<String> future2 = SettableFuture.create();
     SettableFuture<String> future3 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2, future3);
 
     // Attach a listener
@@ -839,9 +1685,10 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+    assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
   }
 
+  @GwtIncompatible("allAsList")
   public void testAllAsList_emptyList() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     listener.expectCall();
@@ -857,7 +1704,7 @@ public class FuturesTest extends TestCase {
     SingleCallListener listener = new SingleCallListener();
     listener.expectCall();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound = Futures.allAsList();
+        ListenableFuture<List<String>> compound = Futures.allAsList();
     compound.addListener(listener, directExecutor());
     assertTrue(compound.isDone());
     assertTrue(compound.get().isEmpty());
@@ -869,7 +1716,7 @@ public class FuturesTest extends TestCase {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2);
     compound.addListener(listener, directExecutor());
 
@@ -888,6 +1735,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("allAsList")
   public void testAllAsList_singleFailure() throws Exception {
     Throwable exception = new Throwable("failed");
     ListenableFuture<String> future = Futures.immediateFailedFuture(exception);
@@ -901,6 +1749,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("allAsList")
   public void testAllAsList_immediateFailure() throws Exception {
     Throwable exception = new Throwable("failed");
     ListenableFuture<String> future1 = Futures.immediateFailedFuture(exception);
@@ -915,6 +1764,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("allAsList")
   public void testAllAsList_error() throws Exception {
     Error error = new Error("deliberate");
     SettableFuture<String> future1 = SettableFuture.create();
@@ -935,7 +1785,7 @@ public class FuturesTest extends TestCase {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2);
     compound.addListener(listener, directExecutor());
 
@@ -957,7 +1807,7 @@ public class FuturesTest extends TestCase {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2);
 
     future2.set(DATA2);
@@ -968,11 +1818,46 @@ public class FuturesTest extends TestCase {
     assertFalse(future1.wasInterrupted());
   }
 
+  public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture()
+      throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    // There was a bug where the event listener for the combined future would
+    // result in the sub-futures being cancelled without being interrupted.
+    ListenableFuture<List<String>> otherCompound =
+        Futures.allAsList(future1, future2);
+
+    assertTrue(compound.cancel(true));
+    assertTrue(future1.isCancelled());
+    assertTrue(future1.wasInterrupted());
+    assertTrue(future2.isCancelled());
+    assertTrue(future2.wasInterrupted());
+    assertTrue(otherCompound.isCancelled());
+  }
+
+  public void testAllAsList_resultCancelled_withSecondaryListFuture()
+      throws Exception {
+    SettableFuture<String> future1 = SettableFuture.create();
+    SettableFuture<String> future2 = SettableFuture.create();
+    ListenableFuture<List<String>> compound =
+        Futures.allAsList(future1, future2);
+    // This next call is "unused," but it is an important part of the test. Don't remove it!
+    Futures.allAsList(future1, future2);
+
+    assertTrue(compound.cancel(false));
+    assertTrue(future1.isCancelled());
+    assertFalse(future1.wasInterrupted());
+    assertTrue(future2.isCancelled());
+    assertFalse(future2.wasInterrupted());
+  }
+
   public void testAllAsList_resultInterrupted() throws Exception {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2);
 
     future2.set(DATA2);
@@ -984,11 +1869,10 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * Test the case where the futures are fulfilled prior to
-   * constructing the ListFuture.  There was a bug where the
-   * loop that connects a Listener to each of the futures would die
-   * on the last loop-check as done() on ListFuture nulled out the
-   * variable being looped over (the list of futures).
+   * Test the case where the futures are fulfilled prior to constructing the ListFuture.  There was
+   * a bug where the loop that connects a Listener to each of the futures would die on the last
+   * loop-check as done() on ListFuture nulled out the variable being looped over (the list of
+   * futures).
    */
   public void testAllAsList_doneFutures() throws Exception {
     // Create input and output
@@ -1002,7 +1886,7 @@ public class FuturesTest extends TestCase {
     future3.set(DATA3);
 
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.allAsList(future1, future2, future3);
 
     // Attach a listener
@@ -1014,7 +1898,7 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+    assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
   }
 
   /**
@@ -1023,45 +1907,166 @@ public class FuturesTest extends TestCase {
   @SuppressWarnings("unchecked")
   public void testAllAsList_logging_exception() throws Exception {
     try {
-      Futures.allAsList(immediateFailedFuture(new MyException())).get();
+      Futures.allAsList(immediateFailedFuture(new MyException())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+    }
+  }
+
+  /**
+   * Ensure that errors are always logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_error() throws Exception {
+    try {
+      Futures.allAsList(immediateFailedFuture(new MyError())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyError.class);
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(1); // errors are always logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+    }
+  }
+
+  /**
+   * All as list will log extra exceptions that have already occurred.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+    try {
+      Futures.allAsList(immediateFailedFuture(new MyException()),
+          immediateFailedFuture(new MyException())).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(1); // the second failure is logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+    }
+  }
+
+  /**
+   * All as list will log extra exceptions that occur later.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+    SettableFuture<Object> future1 = SettableFuture.create();
+    SettableFuture<Object> future2 = SettableFuture.create();
+    SettableFuture<Object> future3 = SettableFuture.create();
+    ListenableFuture<List<Object>> all = Futures.allAsList(future1, future2, future3);
+
+    future1.setException(new MyException());
+    future2.setException(new MyException());
+    future3.setException(new MyException());
+
+    try {
+      all.get();
+    } catch (ExecutionException e) {
+      List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+      assertThat(logged).hasSize(2); // failures after the first are logged
+      assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+      assertThat(logged.get(1).getThrown()).isInstanceOf(MyException.class);
+    }
+  }
+
+  /**
+   * The same exception happening on multiple futures should not be logged.
+   */
+  @SuppressWarnings("unchecked")
+  public void testAllAsList_logging_same_exception() throws Exception {
+    try {
+      MyException sameInstance = new MyException();
+      Futures.allAsList(immediateFailedFuture(sameInstance),
+          immediateFailedFuture(sameInstance)).get();
+      fail();
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+    }
+  }
+
+  public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+    final MyException sameInstance = new MyException();
+    SettableFuture<Object> firstFuture = SettableFuture.create();
+    final SettableFuture<Object> secondFuture = SettableFuture.create();
+    ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+    bulkFuture.addListener(new Runnable() {
+      @Override
+      public void run() {
+        /*
+         * firstFuture just completed, but AggregateFuture hasn't yet had time to record the
+         * exception in seenExceptions. When we complete secondFuture with the same exception,
+         * we want for AggregateFuture to still detect that it's been previously seen.
+         */
+        secondFuture.setException(sameInstance);
+      }
+    }, directExecutor());
+    firstFuture.setException(sameInstance);
+
+    try {
+      bulkFuture.get();
       fail();
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof MyException);
-      assertEquals("Nothing should be logged", 0,
-          combinedFutureLogHandler.getStoredLogRecords().size());
+    } catch (ExecutionException expected) {
+      assertThat(expected.getCause()).isInstanceOf(MyException.class);
+      assertThat(aggregateFutureLogHandler.getStoredLogRecords()).isEmpty();
     }
   }
 
-  /**
-   * Ensure that errors are always logged.
-   */
-  @SuppressWarnings("unchecked")
-  public void testAllAsList_logging_error() throws Exception {
+  public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+    final MyException subsequentFailure = new MyException();
+    SettableFuture<Object> firstFuture = SettableFuture.create();
+    final SettableFuture<Object> secondFuture = SettableFuture.create();
+    ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+    bulkFuture.addListener(new Runnable() {
+      @Override
+      public void run() {
+        /*
+         * This is similar to the above test, but this time we're making sure that we recognize that
+         * the output Future is done early not because of an exception but because of a
+         * cancellation.
+         */
+        secondFuture.setException(subsequentFailure);
+      }
+    }, directExecutor());
+    firstFuture.cancel(false);
+
     try {
-      Futures.allAsList(immediateFailedFuture(new MyError())).get();
+      bulkFuture.get();
       fail();
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof MyError);
-      List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
-      assertEquals(1, logged.size());  // errors are always logged
-      assertTrue(logged.get(0).getThrown() instanceof MyError);
+    } catch (CancellationException expected) {
+      assertThat(getOnlyElement(aggregateFutureLogHandler.getStoredLogRecords()).getThrown())
+          .isSameAs(subsequentFailure);
     }
   }
 
   /**
-   * All as list will log extra exceptions that occur after failure.
+   * Different exceptions happening on multiple futures with the same cause should not be logged.
    */
   @SuppressWarnings("unchecked")
-  public void testAllAsList_logging_multipleExceptions() throws Exception {
-    try {
-      Futures.allAsList(immediateFailedFuture(new MyException()),
-          immediateFailedFuture(new MyException())).get();
+  public void testAllAsList_logging_same_cause() throws Exception {
+    try {
+      MyException exception1 = new MyException();
+      MyException exception2 = new MyException();
+      MyException exception3 = new MyException();
+
+      MyException sameInstance = new MyException();
+      exception1.initCause(sameInstance);
+      exception2.initCause(sameInstance);
+      exception3.initCause(exception2);
+      Futures.allAsList(immediateFailedFuture(exception1),
+          immediateFailedFuture(exception3)).get();
       fail();
     } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof MyException);
-      List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
-      assertEquals(1, logged.size());  // the second failure is logged
-      assertTrue(logged.get(0).getThrown() instanceof MyException);
+      assertThat(e.getCause()).isInstanceOf(MyException.class);
+      assertEquals(
+          "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
     }
   }
 
@@ -1073,13 +2078,15 @@ public class FuturesTest extends TestCase {
    * TODO(cpovirk): maybe pass around TestFuture instances instead of
    * ListenableFuture instances
    */
+
   /**
-   * A future in {@link TestFutureBatch} that also has a name for debugging
-   * purposes and a {@code finisher}, a task that will complete the future in
-   * some fashion when it is called, allowing for testing both before and after
-   * the completion of the future.
+   * A future in {@link TestFutureBatch} that also has a name for debugging purposes and a {@code
+   * finisher}, a task that will complete the future in some fashion when it is called, allowing for
+   * testing both before and after the completion of the future.
    */
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static final class TestFuture {
+
     final ListenableFuture<String> future;
     final String name;
     final Runnable finisher;
@@ -1093,20 +2100,21 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * A collection of several futures, covering cancellation, success, and
-   * failure (both {@link ExecutionException} and {@link RuntimeException}),
-   * both immediate and delayed. We use each possible pair of these futures in
-   * {@link FuturesTest#runExtensiveMergerTest}.
+   * A collection of several futures, covering cancellation, success, and failure (both {@link
+   * ExecutionException} and {@link RuntimeException}), both immediate and delayed. We use each
+   * possible pair of these futures in {@link FuturesTest#runExtensiveMergerTest}.
    *
-   * <p>Each test requires a new {@link TestFutureBatch} because we need new
-   * delayed futures each time, as the old delayed futures were completed as
-   * part of the old test.
+   * <p>Each test requires a new {@link TestFutureBatch} because we need new delayed futures each
+   * time, as the old delayed futures were completed as part of the old test.
    */
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static final class TestFutureBatch {
+
     final ListenableFuture<String> doneSuccess = immediateFuture("a");
     final ListenableFuture<String> doneFailed =
         immediateFailedFuture(new Exception());
     final SettableFuture<String> doneCancelled = SettableFuture.create();
+
     {
       doneCancelled.cancel(true);
     }
@@ -1130,7 +2138,7 @@ public class FuturesTest extends TestCase {
           public String get(long timeout, TimeUnit unit) {
             throw new RuntimeException();
           }
-    };
+        };
 
     final SettableFuture<String> delayedSuccess = SettableFuture.create();
     final SettableFuture<String> delayedFailed = SettableFuture.create();
@@ -1157,7 +2165,7 @@ public class FuturesTest extends TestCase {
             delegateForDelayedRuntimeException.get(timeout, unit);
             throw new RuntimeException();
           }
-    };
+        };
 
     final Runnable doNothing = new Runnable() {
       @Override
@@ -1190,8 +2198,7 @@ public class FuturesTest extends TestCase {
     };
 
     /**
-     * All the futures, together with human-readable names for use by
-     * {@link #smartToString}.
+     * All the futures, together with human-readable names for use by {@link #smartToString}.
      */
     final ImmutableList<TestFuture> allFutures =
         ImmutableList.of(new TestFuture(doneSuccess, "doneSuccess", doNothing),
@@ -1207,26 +2214,25 @@ public class FuturesTest extends TestCase {
                 finishRuntimeException));
 
     final Function<ListenableFuture<String>, String> nameGetter =
-      new Function<ListenableFuture<String>, String>() {
-        @Override
-        public String apply(ListenableFuture<String> input) {
-          for (TestFuture future : allFutures) {
-            if (future.future == input) {
-              return future.name;
+        new Function<ListenableFuture<String>, String>() {
+          @Override
+          public String apply(ListenableFuture<String> input) {
+            for (TestFuture future : allFutures) {
+              if (future.future == input) {
+                return future.name;
+              }
             }
+            throw new IllegalArgumentException(input.toString());
           }
-          throw new IllegalArgumentException(input.toString());
-        }
-      };
+        };
 
     static boolean intersect(Set<?> a, Set<?> b) {
       return !Sets.intersection(a, b).isEmpty();
     }
 
     /**
-     * Like {@code inputs.toString()}, but with the nonsense {@code toString}
-     * representations replaced with the name of each future from
-     * {@link #allFutures}.
+     * Like {@code inputs.toString()}, but with the nonsense {@code toString} representations
+     * replaced with the name of each future from {@link #allFutures}.
      */
     String smartToString(ImmutableSet<ListenableFuture<String>> inputs) {
       Iterable<String> inputNames = Iterables.transform(inputs, nameGetter);
@@ -1236,7 +2242,7 @@ public class FuturesTest extends TestCase {
     void smartAssertTrue(ImmutableSet<ListenableFuture<String>> inputs,
         Exception cause, boolean expression) {
       if (!expression) {
-        failWithCause(cause, smartToString(inputs));
+        throw failureWithCause(cause, smartToString(inputs));
       }
     }
 
@@ -1283,11 +2289,12 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * {@link Futures#allAsList(Iterable)} or
-   * {@link Futures#successfulAsList(Iterable)}, hidden behind a common
-   * interface for testing.
+   * {@link Futures#allAsList(Iterable)} or {@link Futures#successfulAsList(Iterable)}, hidden
+   * behind a common interface for testing.
    */
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private interface Merger {
+
     ListenableFuture<List<String>> merged(
         ListenableFuture<String> a, ListenableFuture<String> b);
 
@@ -1308,15 +2315,16 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * Very rough equivalent of a timed get, produced by calling the no-arg get
-   * method in another thread and waiting a short time for it.
+   * Very rough equivalent of a timed get, produced by calling the no-arg get method in another
+   * thread and waiting a short time for it.
    *
-   * <p>We need this to test the behavior of no-arg get methods without hanging
-   * the main test thread forever in the case of failure.
+   * <p>We need this to test the behavior of no-arg get methods without hanging the main test thread
+   * forever in the case of failure.
    */
-  private static <V> V pseudoTimedGet(
+  @GwtIncompatible("threads")
+  static <V> V pseudoTimedGetUninterruptibly(
       final Future<V> input, long timeout, TimeUnit unit)
-      throws InterruptedException, ExecutionException, TimeoutException {
+      throws ExecutionException, TimeoutException {
     ExecutorService executor = newSingleThreadExecutor();
     Future<V> waiter = executor.submit(new Callable<V>() {
       @Override
@@ -1326,33 +2334,31 @@ public class FuturesTest extends TestCase {
     });
 
     try {
-      return waiter.get(timeout, unit);
+      return getUninterruptibly(waiter, timeout, unit);
     } catch (ExecutionException e) {
       propagateIfInstanceOf(e.getCause(), ExecutionException.class);
       propagateIfInstanceOf(e.getCause(), CancellationException.class);
-      AssertionFailedError error =
-          new AssertionFailedError("Unexpected exception");
-      error.initCause(e);
-      throw error;
+      throw failureWithCause(e, "Unexpected exception");
     } finally {
       executor.shutdownNow();
-      assertTrue(executor.awaitTermination(10, SECONDS));
+      // TODO(cpovirk: assertTrue(awaitTerminationUninterruptibly(executor, 10, SECONDS));
     }
   }
 
   /**
-   * For each possible pair of futures from {@link TestFutureBatch}, for each
-   * possible completion order of those futures, test that various get calls
-   * (timed before future completion, untimed before future completion, and
-   * untimed after future completion) return or throw the proper values.
+   * For each possible pair of futures from {@link TestFutureBatch}, for each possible completion
+   * order of those futures, test that various get calls (timed before future completion, untimed
+   * before future completion, and untimed after future completion) return or throw the proper
+   * values.
    */
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static void runExtensiveMergerTest(Merger merger)
       throws InterruptedException {
     int inputCount = new TestFutureBatch().allFutures.size();
 
     for (int i = 0; i < inputCount; i++) {
       for (int j = 0; j < inputCount; j++) {
-        for (boolean iBeforeJ : new boolean[] { true, false }) {
+        for (boolean iBeforeJ : new boolean[]{true, false}) {
           TestFutureBatch inputs = new TestFutureBatch();
           ListenableFuture<String> iFuture = inputs.allFutures.get(i).future;
           ListenableFuture<String> jFuture = inputs.allFutures.get(j).future;
@@ -1376,7 +2382,7 @@ public class FuturesTest extends TestCase {
 
           // Same tests with pseudoTimedGet.
           try {
-            List<String> result = conditionalPseudoTimedGet(
+            List<String> result = conditionalPseudoTimedGetUninterruptibly(
                 inputs, iFuture, jFuture, future, 20, MILLISECONDS);
             assertTrue("Got " + result,
                 Arrays.asList("a", null).containsAll(result));
@@ -1412,58 +2418,59 @@ public class FuturesTest extends TestCase {
   }
 
   /**
-   * Call the non-timed {@link Future#get()} in a way that allows us to abort if
-   * it's expected to hang forever. More precisely, if it's expected to return,
-   * we simply call it[*], but if it's expected to hang (because one of the
-   * input futures that we know makes it up isn't done yet), then we call it in
-   * a separate thread (using pseudoTimedGet). The result is that we wait as
-   * long as necessary when the method is expected to return (at the cost of
-   * hanging forever if there is a bug in the class under test) but that we time
-   * out fairly promptly when the method is expected to hang (possibly too
-   * quickly, but too-quick failures should be very unlikely, given that we used
-   * to bail after 20ms during the expected-successful tests, and there we saw a
-   * failure rate of ~1/5000, meaning that the other thread's get() call nearly
-   * always completes within 20ms if it's going to complete at all).
+   * Call the non-timed {@link Future#get()} in a way that allows us to abort if it's expected to
+   * hang forever. More precisely, if it's expected to return, we simply call it[*], but if it's
+   * expected to hang (because one of the input futures that we know makes it up isn't done yet),
+   * then we call it in a separate thread (using pseudoTimedGet). The result is that we wait as long
+   * as necessary when the method is expected to return (at the cost of hanging forever if there is
+   * a bug in the class under test) but that we time out fairly promptly when the method is expected
+   * to hang (possibly too quickly, but too-quick failures should be very unlikely, given that we
+   * used to bail after 20ms during the expected-successful tests, and there we saw a failure rate
+   * of ~1/5000, meaning that the other thread's get() call nearly always completes within 20ms if
+   * it's going to complete at all).
    *
-   * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test
-   * take (very roughly) 2.5s longer. (2.5s is also the maximum length of time
-   * we will wait for a timed get that is expected to succeed; the fact that the
-   * numbers match is only a coincidence.) See the comment below for how to
-   * restore the fast but hang-y version.
+   * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test take (very roughly)
+   * 2.5s longer. (2.5s is also the maximum length of time we will wait for a timed get that is
+   * expected to succeed; the fact that the numbers match is only a coincidence.) See the comment
+   * below for how to restore the fast but hang-y version.
    */
-  private static List<String> conditionalPseudoTimedGet(
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private static List<String> conditionalPseudoTimedGetUninterruptibly(
       TestFutureBatch inputs,
       ListenableFuture<String> iFuture,
       ListenableFuture<String> jFuture,
       ListenableFuture<List<String>> future,
       int timeout,
       TimeUnit unit)
-      throws InterruptedException, ExecutionException, TimeoutException {
+      throws ExecutionException, TimeoutException {
     /*
      * For faster tests (that may hang indefinitely if the class under test has
      * a bug!), switch the second branch to call untimed future.get() instead of
      * pseudoTimedGet.
      */
     return (inputs.hasDelayed(iFuture, jFuture))
-        ? pseudoTimedGet(future, timeout, unit)
-        : pseudoTimedGet(future, 2500, MILLISECONDS);
+        ? pseudoTimedGetUninterruptibly(future, timeout, unit)
+        : pseudoTimedGetUninterruptibly(future, 2500, MILLISECONDS);
   }
 
+  @GwtIncompatible("allAsList")
   public void testAllAsList_extensive() throws InterruptedException {
     runExtensiveMergerTest(Merger.allMerger);
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_extensive() throws InterruptedException {
     runExtensiveMergerTest(Merger.successMerger);
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList() throws Exception {
     // Create input and output
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     SettableFuture<String> future3 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2, future3);
 
     // Attach a listener
@@ -1482,9 +2489,10 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+    assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_emptyList() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     listener.expectCall();
@@ -1496,23 +2504,25 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_emptyArray() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     listener.expectCall();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound = Futures.successfulAsList();
+        ListenableFuture<List<String>> compound = Futures.successfulAsList();
     compound.addListener(listener, directExecutor());
     assertTrue(compound.isDone());
     assertTrue(compound.get().isEmpty());
     assertTrue(listener.wasCalled());
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_partialFailure() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
     compound.addListener(listener, directExecutor());
 
@@ -1525,15 +2535,16 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(null, DATA2).inOrder();
+    assertThat(results).containsExactly(null, DATA2).inOrder();
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_totalFailure() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
     compound.addListener(listener, directExecutor());
 
@@ -1546,15 +2557,16 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(null, null).inOrder();
+    assertThat(results).containsExactly(null, null).inOrder();
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_cancelled() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
     compound.addListener(listener, directExecutor());
 
@@ -1567,14 +2579,15 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(null, DATA2).inOrder();
+    assertThat(results).containsExactly(null, DATA2).inOrder();
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_resultCancelled() throws Exception {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
 
     future2.set(DATA2);
@@ -1585,6 +2598,7 @@ public class FuturesTest extends TestCase {
     assertFalse(future1.wasInterrupted());
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_resultCancelledRacingInputDone()
       throws Exception {
     /*
@@ -1592,17 +2606,21 @@ public class FuturesTest extends TestCase {
      * ExecutionList and logged rather than allowed to propagate. We need to
      * turn that back into a failure.
      */
-    Handler throwingHandler = new Handler() {
-      @Override public void publish(@Nullable LogRecord record) {
-        AssertionFailedError error = new AssertionFailedError();
-        error.initCause(record.getThrown());
-        throw error;
-      }
+    Handler throwingHandler =
+        new Handler() {
+          @Override
+          public void publish(LogRecord record) {
+            AssertionFailedError error = new AssertionFailedError();
+            error.initCause(record.getThrown());
+            throw error;
+          }
 
-      @Override public void flush() {}
+          @Override
+          public void flush() {}
 
-      @Override public void close() {}
-    };
+          @Override
+          public void close() {}
+        };
 
     ExecutionList.log.addHandler(throwingHandler);
     try {
@@ -1612,6 +2630,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("successfulAsList")
   private static void doTestSuccessfulAsList_resultCancelledRacingInputDone()
       throws Exception {
     // Simple (combined.cancel -> input.cancel -> setOneValue):
@@ -1626,11 +2645,12 @@ public class FuturesTest extends TestCase {
     final SettableFuture<String> future1 = SettableFuture.create();
     final SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
 
     future1.addListener(new Runnable() {
-      @Override public void run() {
+      @Override
+      public void run() {
         assertTrue(future1.isCancelled());
         /*
          * This test relies on behavior that's unspecified but currently
@@ -1656,11 +2676,12 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_resultInterrupted() throws Exception {
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2);
 
     future2.set(DATA2);
@@ -1671,13 +2692,14 @@ public class FuturesTest extends TestCase {
     assertTrue(future1.wasInterrupted());
   }
 
+  @GwtIncompatible("successfulAsList")
   public void testSuccessfulAsList_mixed() throws Exception {
     SingleCallListener listener = new SingleCallListener();
     SettableFuture<String> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
     SettableFuture<String> future3 = SettableFuture.create();
     @SuppressWarnings("unchecked") // array is never modified
-    ListenableFuture<List<String>> compound =
+        ListenableFuture<List<String>> compound =
         Futures.successfulAsList(future1, future2, future3);
     compound.addListener(listener, directExecutor());
 
@@ -1693,17 +2715,19 @@ public class FuturesTest extends TestCase {
     assertTrue(listener.wasCalled());
 
     List<String> results = compound.get();
-    assertThat(results).has().exactly(null, null, DATA3).inOrder();
+    assertThat(results).containsExactly(null, null, DATA3).inOrder();
   }
 
-  /** Non-Error exceptions are never logged. */
+  /**
+   * Non-Error exceptions are never logged.
+   */
   @SuppressWarnings("unchecked")
   public void testSuccessfulAsList_logging_exception() throws Exception {
     assertEquals(Lists.newArrayList((Object) null),
         Futures.successfulAsList(
             immediateFailedFuture(new MyException())).get());
     assertEquals("Nothing should be logged", 0,
-        combinedFutureLogHandler.getStoredLogRecords().size());
+        aggregateFutureLogHandler.getStoredLogRecords().size());
 
     // Not even if there are a bunch of failures.
     assertEquals(Lists.newArrayList(null, null, null),
@@ -1712,7 +2736,7 @@ public class FuturesTest extends TestCase {
             immediateFailedFuture(new MyException()),
             immediateFailedFuture(new MyException())).get());
     assertEquals("Nothing should be logged", 0,
-        combinedFutureLogHandler.getStoredLogRecords().size());
+        aggregateFutureLogHandler.getStoredLogRecords().size());
   }
 
   /**
@@ -1723,11 +2747,12 @@ public class FuturesTest extends TestCase {
     assertEquals(Lists.newArrayList((Object) null),
         Futures.successfulAsList(
             immediateFailedFuture(new MyError())).get());
-    List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
-    assertEquals(1, logged.size());  // errors are always logged
-    assertTrue(logged.get(0).getThrown() instanceof MyError);
+    List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+    assertThat(logged).hasSize(1); // errors are always logged
+    assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
   }
 
+  @GwtIncompatible("nonCancellationPropagating")
   public void testNonCancellationPropagating_successful() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1739,6 +2764,7 @@ public class FuturesTest extends TestCase {
     assertSame(foo, wrapper.get());
   }
 
+  @GwtIncompatible("nonCancellationPropagating")
   public void testNonCancellationPropagating_failure() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1755,6 +2781,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("nonCancellationPropagating")
   public void testNonCancellationPropagating_delegateCancelled() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1764,6 +2791,7 @@ public class FuturesTest extends TestCase {
     assertTrue(wrapper.isCancelled());
   }
 
+  @GwtIncompatible("nonCancellationPropagating")
   public void testNonCancellationPropagating_doesNotPropagate() throws Exception {
     SettableFuture<Foo> input = SettableFuture.create();
     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1775,591 +2803,244 @@ public class FuturesTest extends TestCase {
     assertFalse(input.isDone());
   }
 
+  @GwtIncompatible("used only in GwtIncompatible tests")
   private static class TestException extends Exception {
-    TestException(@Nullable Throwable cause) {
-      super(cause);
-    }
-  }
-
-  private static final Function<Exception, TestException> mapper =
-      new Function<Exception, TestException>() {
-    @Override public TestException apply(Exception from) {
-      if (from instanceof ExecutionException) {
-        return new TestException(from.getCause());
-      } else {
-        assertTrue("got " + from.getClass(),
-            from instanceof InterruptedException
-                || from instanceof CancellationException);
-        return new TestException(from);
-      }
-    }
-  };
-
-  public void testMakeChecked_mapsExecutionExceptions() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, mapper);
-
-    future.setException(new IOException("checked"));
-
-    assertTrue(checked.isDone());
-    assertFalse(checked.isCancelled());
-
-    try {
-      checked.get();
-      fail();
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof IOException);
-    }
-
-    try {
-      checked.get(5, TimeUnit.SECONDS);
-      fail();
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof IOException);
-    }
-
-    try {
-      checked.checkedGet();
-      fail();
-    } catch (TestException e) {
-      assertTrue(e.getCause() instanceof IOException);
-    }
-
-    try {
-      checked.checkedGet(5, TimeUnit.SECONDS);
-      fail();
-    } catch (TestException e) {
-      assertTrue(e.getCause() instanceof IOException);
-    }
-  }
-
-  public void testMakeChecked_mapsInterruption() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, mapper);
-
-    Thread.currentThread().interrupt();
-
-    try {
-      checked.get();
-      fail();
-    } catch (InterruptedException e) {
-      // Expected.
-    }
-
-    Thread.currentThread().interrupt();
-
-    try {
-      checked.get(5, TimeUnit.SECONDS);
-      fail();
-    } catch (InterruptedException e) {
-      // Expected.
-    }
-
-    Thread.currentThread().interrupt();
-
-    try {
-      checked.checkedGet();
-      fail();
-    } catch (TestException e) {
-      assertTrue(e.getCause() instanceof InterruptedException);
-    }
-
-    Thread.currentThread().interrupt();
-
-    try {
-      checked.checkedGet(5, TimeUnit.SECONDS);
-      fail();
-    } catch (TestException e) {
-      assertTrue(e.getCause() instanceof InterruptedException);
-    }
-  }
-
-  public void testMakeChecked_mapsCancellation() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, mapper);
-
-    assertTrue(future.cancel(true)); // argument is ignored
-
-    try {
-      checked.get();
-      fail();
-    } catch (CancellationException expected) {}
-
-    try {
-      checked.get(5, TimeUnit.SECONDS);
-      fail();
-    } catch (CancellationException expected) {}
-
-    try {
-      checked.checkedGet();
-      fail();
-    } catch (TestException expected) {
-      assertTrue(expected.getCause() instanceof CancellationException);
-    }
-
-    try {
-      checked.checkedGet(5, TimeUnit.SECONDS);
-      fail();
-    } catch (TestException expected) {
-      assertTrue(expected.getCause() instanceof CancellationException);
-    }
-  }
-
-  public void testMakeChecked_propagatesFailedMappers() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, new Function<Exception, TestException>() {
-          @Override public TestException apply(Exception from) {
-            throw new NullPointerException();
-          }
-    });
-
-    future.setException(new Exception("failed"));
-
-    try {
-      checked.checkedGet();
-      fail();
-    } catch (NullPointerException expected) {}
-
-    try {
-      checked.checkedGet(5, TimeUnit.SECONDS);
-      fail();
-    } catch (NullPointerException expected) {}
-  }
-
-  public void testMakeChecked_listenersRunOnceCompleted() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, new Function<Exception, TestException>() {
-          @Override public TestException apply(Exception from) {
-            throw new NullPointerException();
-          }
-    });
-
-    ListenableFutureTester tester = new ListenableFutureTester(checked);
-    tester.setUp();
-    future.set(DATA1);
-    tester.testCompletedFuture(DATA1);
-    tester.tearDown();
-  }
-
-  public void testMakeChecked_listenersRunOnCancel() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, new Function<Exception, TestException>() {
-          @Override public TestException apply(Exception from) {
-            throw new NullPointerException();
-          }
-    });
-
-    ListenableFutureTester tester = new ListenableFutureTester(checked);
-    tester.setUp();
-    future.cancel(true); // argument is ignored
-    tester.testCancelledFuture();
-    tester.tearDown();
-  }
-
-  public void testMakeChecked_listenersRunOnFailure() throws Exception {
-    SettableFuture<String> future = SettableFuture.create();
-
-    CheckedFuture<String, TestException> checked = Futures.makeChecked(
-        future, new Function<Exception, TestException>() {
-          @Override public TestException apply(Exception from) {
-            throw new NullPointerException();
-          }
-    });
-
-    ListenableFutureTester tester = new ListenableFutureTester(checked);
-    tester.setUp();
-    future.setException(new Exception("failed"));
-    tester.testFailedFuture("failed");
-    tester.tearDown();
-  }
-
-  private interface MapperFunction extends Function<Throwable, Exception> {}
-
-  private static final class OtherThrowable extends Throwable {}
-
-  private static final Exception CHECKED_EXCEPTION = new Exception("mymessage");
-  private static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION =
-      immediateFailedFuture(CHECKED_EXCEPTION);
-  private static final RuntimeException UNCHECKED_EXCEPTION =
-      new RuntimeException("mymessage");
-  private static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION =
-      immediateFailedFuture(UNCHECKED_EXCEPTION);
-  private static final RuntimeException RUNTIME_EXCEPTION =
-      new RuntimeException();
-  private static final OtherThrowable OTHER_THROWABLE = new OtherThrowable();
-  private static final Future<String> FAILED_FUTURE_OTHER_THROWABLE =
-      immediateFailedFuture(OTHER_THROWABLE);
-  private static final Error ERROR = new Error("mymessage");
-  private static final Future<String> FAILED_FUTURE_ERROR =
-      immediateFailedFuture(ERROR);
-  private static final Future<String> RUNTIME_EXCEPTION_FUTURE =
-      new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) {
-        @Override public String get() {
-          throw RUNTIME_EXCEPTION;
-        }
-
-        @Override public String get(long timeout, TimeUnit unit) {
-          throw RUNTIME_EXCEPTION;
-        }
-      };
 
-  // Boring untimed-get tests:
-
-  public void testGetUntimed_success()
-      throws TwoArgConstructorException {
-    assertEquals("foo",
-        get(immediateFuture("foo"), TwoArgConstructorException.class));
-  }
-
-  public void testGetUntimed_interrupted() {
-    SettableFuture<String> future = SettableFuture.create();
-    Thread.currentThread().interrupt();
-    try {
-      get(future, TwoArgConstructorException.class);
-      fail();
-    } catch (TwoArgConstructorException expected) {
-      assertTrue(expected.getCause() instanceof InterruptedException);
-      assertTrue(Thread.currentThread().isInterrupted());
-    } finally {
-      Thread.interrupted();
+    TestException(@Nullable Throwable cause) {
+      super(cause);
     }
   }
 
-  public void testGetUntimed_cancelled()
-      throws TwoArgConstructorException {
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private static final Function<Exception, TestException> mapper =
+      new Function<Exception, TestException>() {
+        @Override
+        public TestException apply(Exception from) {
+          if (from instanceof ExecutionException) {
+            return new TestException(from.getCause());
+          } else {
+            assertTrue("got " + from.getClass(),
+                from instanceof InterruptedException
+                    || from instanceof CancellationException);
+            return new TestException(from);
+          }
+        }
+      };
+
+  @GwtIncompatible("makeChecked")
+  public void testMakeChecked_mapsExecutionExceptions() throws Exception {
     SettableFuture<String> future = SettableFuture.create();
-    future.cancel(true);
-    try {
-      get(future, TwoArgConstructorException.class);
-      fail();
-    } catch (CancellationException expected) {
-    }
-  }
 
-  public void testGetUntimed_ExecutionExceptionChecked() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class);
-      fail();
-    } catch (TwoArgConstructorException expected) {
-      assertEquals(CHECKED_EXCEPTION, expected.getCause());
-    }
-  }
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, mapper);
 
-  public void testGetUntimed_ExecutionExceptionUnchecked()
-      throws TwoArgConstructorException {
-    try {
-      get(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class);
-      fail();
-    } catch (UncheckedExecutionException expected) {
-      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
-    }
-  }
+    future.setException(new IOException("checked"));
 
-  public void testGetUntimed_ExecutionExceptionError()
-      throws TwoArgConstructorException {
-    try {
-      get(FAILED_FUTURE_ERROR, TwoArgConstructorException.class);
-      fail();
-    } catch (ExecutionError expected) {
-      assertEquals(ERROR, expected.getCause());
-    }
-  }
+    assertTrue(checked.isDone());
+    assertFalse(checked.isCancelled());
 
-  public void testGetUntimed_ExecutionExceptionOtherThrowable() {
     try {
-      get(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class);
+      checked.get();
       fail();
-    } catch (TwoArgConstructorException expected) {
-      assertEquals(OTHER_THROWABLE, expected.getCause());
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(IOException.class);
     }
-  }
 
-  public void testGetUntimed_RuntimeException()
-      throws TwoArgConstructorException {
     try {
-      get(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class);
+      checked.get(5, TimeUnit.SECONDS);
       fail();
-    } catch (RuntimeException expected) {
-      assertEquals(RUNTIME_EXCEPTION, expected);
+    } catch (ExecutionException e) {
+      assertThat(e.getCause()).isInstanceOf(IOException.class);
     }
-  }
 
-  public void testGetUntimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
     try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class);
+      checked.checkedGet();
       fail();
-    } catch (IllegalArgumentException expected) {
-      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    } catch (TestException e) {
+      assertThat(e.getCause()).isInstanceOf(IOException.class);
     }
-  }
 
-  public void testGetUntimed_withGoodAndBadExceptionConstructor() throws Exception {
     try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithGoodAndBadConstructor.class);
+      checked.checkedGet(5, TimeUnit.SECONDS);
       fail();
-    } catch (ExceptionWithGoodAndBadConstructor expected) {
-      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    } catch (TestException e) {
+      assertThat(e.getCause()).isInstanceOf(IOException.class);
     }
   }
 
-  // Boring timed-get tests:
+  @GwtIncompatible("makeChecked")
+  public void testMakeChecked_mapsInterruption() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
 
-  public void testGetTimed_success()
-      throws TwoArgConstructorException {
-    assertEquals("foo", get(
-        immediateFuture("foo"), 0, SECONDS, TwoArgConstructorException.class));
-  }
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, mapper);
 
-  public void testGetTimed_interrupted() {
-    SettableFuture<String> future = SettableFuture.create();
     Thread.currentThread().interrupt();
-    try {
-      get(future, 0, SECONDS, TwoArgConstructorException.class);
-      fail();
-    } catch (TwoArgConstructorException expected) {
-      assertTrue(expected.getCause() instanceof InterruptedException);
-      assertTrue(Thread.currentThread().isInterrupted());
-    } finally {
-      Thread.interrupted();
-    }
-  }
 
-  public void testGetTimed_cancelled()
-      throws TwoArgConstructorException {
-    SettableFuture<String> future = SettableFuture.create();
-    future.cancel(true);
     try {
-      get(future, 0, SECONDS, TwoArgConstructorException.class);
+      checked.get();
       fail();
-    } catch (CancellationException expected) {
+    } catch (InterruptedException e) {
+      // Expected.
     }
-  }
 
-  public void testGetTimed_ExecutionExceptionChecked() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, 0, SECONDS,
-          TwoArgConstructorException.class);
-      fail();
-    } catch (TwoArgConstructorException expected) {
-      assertEquals(CHECKED_EXCEPTION, expected.getCause());
-    }
-  }
+    Thread.currentThread().interrupt();
 
-  public void testGetTimed_ExecutionExceptionUnchecked()
-      throws TwoArgConstructorException {
     try {
-      get(FAILED_FUTURE_UNCHECKED_EXCEPTION, 0, SECONDS,
-          TwoArgConstructorException.class);
+      checked.get(5, TimeUnit.SECONDS);
       fail();
-    } catch (UncheckedExecutionException expected) {
-      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+    } catch (InterruptedException e) {
+      // Expected.
     }
-  }
 
-  public void testGetTimed_ExecutionExceptionError()
-      throws TwoArgConstructorException {
+    Thread.currentThread().interrupt();
+
     try {
-      get(FAILED_FUTURE_ERROR, 0, SECONDS, TwoArgConstructorException.class);
+      checked.checkedGet();
       fail();
-    } catch (ExecutionError expected) {
-      assertEquals(ERROR, expected.getCause());
+    } catch (TestException e) {
+      assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
     }
-  }
 
-  public void testGetTimed_ExecutionExceptionOtherThrowable() {
+    Thread.currentThread().interrupt();
+
     try {
-      get(FAILED_FUTURE_OTHER_THROWABLE, 0, SECONDS,
-          TwoArgConstructorException.class);
+      checked.checkedGet(5, TimeUnit.SECONDS);
       fail();
-    } catch (TwoArgConstructorException expected) {
-      assertEquals(OTHER_THROWABLE, expected.getCause());
+    } catch (TestException e) {
+      assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
     }
   }
 
-  public void testGetTimed_RuntimeException()
-      throws TwoArgConstructorException {
+  @GwtIncompatible("makeChecked")
+  public void testMakeChecked_mapsCancellation() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
+
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, mapper);
+
+    assertTrue(future.cancel(true)); // argument is ignored
+
     try {
-      get(RUNTIME_EXCEPTION_FUTURE, 0, SECONDS,
-          TwoArgConstructorException.class);
+      checked.get();
       fail();
-    } catch (RuntimeException expected) {
-      assertEquals(RUNTIME_EXCEPTION, expected);
+    } catch (CancellationException expected) {
     }
-  }
 
-  public void testGetTimed_TimeoutException() {
-    SettableFuture<String> future = SettableFuture.create();
     try {
-      get(future, 0, SECONDS, TwoArgConstructorException.class);
+      checked.get(5, TimeUnit.SECONDS);
       fail();
-    } catch (TwoArgConstructorException expected) {
-      assertTrue(expected.getCause() instanceof TimeoutException);
+    } catch (CancellationException expected) {
     }
-  }
 
-  public void testGetTimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
     try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS, ExceptionWithBadConstructor.class);
+      checked.checkedGet();
       fail();
-    } catch (IllegalArgumentException expected) {
-      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    } catch (TestException expected) {
+      assertThat(expected.getCause()).isInstanceOf(CancellationException.class);
     }
-  }
 
-  public void testGetTimed_withGoodAndBadExceptionConstructor() throws Exception {
     try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS,
-          ExceptionWithGoodAndBadConstructor.class);
+      checked.checkedGet(5, TimeUnit.SECONDS);
       fail();
-    } catch (ExceptionWithGoodAndBadConstructor expected) {
-      assertSame(CHECKED_EXCEPTION, expected.getCause());
+    } catch (TestException expected) {
+      assertThat(expected.getCause()).isInstanceOf(CancellationException.class);
     }
   }
 
-  // Boring getUnchecked tests:
+  @GwtIncompatible("makeChecked")
+  public void testMakeChecked_propagatesFailedMappers() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
 
-  public void testGetUnchecked_success() {
-    assertEquals("foo", getUnchecked(immediateFuture("foo")));
-  }
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, new Function<Exception, TestException>() {
+          @Override
+          public TestException apply(Exception from) {
+            throw new NullPointerException();
+          }
+        });
 
-  public void testGetUnchecked_interrupted() {
-    Thread.currentThread().interrupt();
-    try {
-      assertEquals("foo", getUnchecked(immediateFuture("foo")));
-      assertTrue(Thread.currentThread().isInterrupted());
-    } finally {
-      Thread.interrupted();
-    }
-  }
+    future.setException(new Exception("failed"));
 
-  public void testGetUnchecked_cancelled() {
-    SettableFuture<String> future = SettableFuture.create();
-    future.cancel(true);
     try {
-      getUnchecked(future);
+      checked.checkedGet();
       fail();
-    } catch (CancellationException expected) {
+    } catch (NullPointerException expected) {
     }
-  }
 
-  public void testGetUnchecked_ExecutionExceptionChecked() {
     try {
-      getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION);
+      checked.checkedGet(5, TimeUnit.SECONDS);
       fail();
-    } catch (UncheckedExecutionException expected) {
-      assertEquals(CHECKED_EXCEPTION, expected.getCause());
+    } catch (NullPointerException expected) {
     }
   }
 
-  public void testGetUnchecked_ExecutionExceptionUnchecked() {
-    try {
-      getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION);
-      fail();
-    } catch (UncheckedExecutionException expected) {
-      assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
-    }
-  }
+  @GwtIncompatible("makeChecked")
 
-  public void testGetUnchecked_ExecutionExceptionError() {
-    try {
-      getUnchecked(FAILED_FUTURE_ERROR);
-      fail();
-    } catch (ExecutionError expected) {
-      assertEquals(ERROR, expected.getCause());
-    }
-  }
+  public void testMakeChecked_listenersRunOnceCompleted() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
 
-  public void testGetUnchecked_ExecutionExceptionOtherThrowable() {
-    try {
-      getUnchecked(FAILED_FUTURE_OTHER_THROWABLE);
-      fail();
-    } catch (UncheckedExecutionException expected) {
-      assertEquals(OTHER_THROWABLE, expected.getCause());
-    }
-  }
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, new Function<Exception, TestException>() {
+          @Override
+          public TestException apply(Exception from) {
+            throw new NullPointerException();
+          }
+        });
 
-  public void testGetUnchecked_RuntimeException() {
-    try {
-      getUnchecked(RUNTIME_EXCEPTION_FUTURE);
-      fail();
-    } catch (RuntimeException expected) {
-      assertEquals(RUNTIME_EXCEPTION, expected);
-    }
+    ListenableFutureTester tester = new ListenableFutureTester(checked);
+    tester.setUp();
+    future.set(DATA1);
+    tester.testCompletedFuture(DATA1);
+    tester.tearDown();
   }
 
-  // Edge case tests of the exception-construction code through untimed get():
+  @GwtIncompatible("makeChecked")
 
-  public void testGetUntimed_exceptionClassIsRuntimeException() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          TwoArgConstructorRuntimeException.class);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-  }
+  public void testMakeChecked_listenersRunOnCancel() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
 
-  public void testGetUntimed_exceptionClassSomePublicConstructors() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          ExceptionWithSomePrivateConstructors.class);
-      fail();
-    } catch (ExceptionWithSomePrivateConstructors expected) {
-    }
-  }
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, new Function<Exception, TestException>() {
+          @Override
+          public TestException apply(Exception from) {
+            throw new NullPointerException();
+          }
+        });
 
-  public void testGetUntimed_exceptionClassNoPublicConstructor()
-      throws ExceptionWithPrivateConstructor {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          ExceptionWithPrivateConstructor.class);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
+    ListenableFutureTester tester = new ListenableFutureTester(checked);
+    tester.setUp();
+    future.cancel(true); // argument is ignored
+    tester.testCancelledFuture();
+    tester.tearDown();
   }
 
-  public void testGetUntimed_exceptionClassPublicConstructorWrongType()
-      throws ExceptionWithWrongTypesConstructor {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          ExceptionWithWrongTypesConstructor.class);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-  }
+  @GwtIncompatible("makeChecked")
 
-  public void testGetUntimed_exceptionClassPrefersStringConstructor() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          ExceptionWithManyConstructors.class);
-      fail();
-    } catch (ExceptionWithManyConstructors expected) {
-      assertTrue(expected.usedExpectedConstructor);
-    }
+  public void testMakeChecked_listenersRunOnFailure() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
+
+    CheckedFuture<String, TestException> checked = Futures.makeChecked(
+        future, new Function<Exception, TestException>() {
+          @Override
+          public TestException apply(Exception from) {
+            throw new NullPointerException();
+          }
+        });
+
+    ListenableFutureTester tester = new ListenableFutureTester(checked);
+    tester.setUp();
+    future.setException(new Exception("failed"));
+    tester.testFailedFuture("failed");
+    tester.tearDown();
   }
 
-  public void testGetUntimed_exceptionClassUsedInitCause() {
-    try {
-      get(FAILED_FUTURE_CHECKED_EXCEPTION,
-          ExceptionWithoutThrowableConstructor.class);
-      fail();
-    } catch (ExceptionWithoutThrowableConstructor expected) {
-      assertThat(expected.getMessage()).contains("mymessage");
-      assertEquals(CHECKED_EXCEPTION, expected.getCause());
-    }
+  @GwtIncompatible("used only in GwtIncompatible tests")
+  private interface MapperFunction extends Function<Throwable, Exception> {
+
   }
 
+  @GwtIncompatible("inCompletionOrder")
   public void testCompletionOrder() throws Exception {
     SettableFuture<Long> future1 = SettableFuture.create();
     SettableFuture<Long> future2 = SettableFuture.create();
@@ -2382,6 +3063,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("inCompletionOrder")
   public void testCompletionOrderExceptionThrown() throws Exception {
     SettableFuture<Long> future1 = SettableFuture.create();
     SettableFuture<Long> future2 = SettableFuture.create();
@@ -2407,13 +3089,14 @@ public class FuturesTest extends TestCase {
           fail();
         } catch (ExecutionException e) {
           // Expected
-          assertEquals("2L", e.getCause().getMessage());
+          assertThat(e.getCause()).hasMessage("2L");
         }
       }
       expected++;
     }
   }
 
+  @GwtIncompatible("inCompletionOrder")
   public void testCompletionOrderFutureCancelled() throws Exception {
     SettableFuture<Long> future1 = SettableFuture.create();
     SettableFuture<Long> future2 = SettableFuture.create();
@@ -2445,6 +3128,7 @@ public class FuturesTest extends TestCase {
     }
   }
 
+  @GwtIncompatible("inCompletionOrder")
   public void testCancellingADelegateDoesNotPropagate() throws Exception {
     SettableFuture<Long> future1 = SettableFuture.create();
     SettableFuture<Long> future2 = SettableFuture.create();
@@ -2464,6 +3148,7 @@ public class FuturesTest extends TestCase {
   }
 
   // Mostly an example of how it would look like to use a list of mixed types
+  @GwtIncompatible("inCompletionOrder")
   public void testCompletionOrderMixedBagOTypes() throws Exception {
     SettableFuture<Long> future1 = SettableFuture.create();
     SettableFuture<String> future2 = SettableFuture.create();
@@ -2482,122 +3167,40 @@ public class FuturesTest extends TestCase {
     }
   }
 
-  public static final class TwoArgConstructorException extends Exception {
-    public TwoArgConstructorException(String message, Throwable cause) {
-      super(message, cause);
-    }
-  }
-
-  public static final class TwoArgConstructorRuntimeException
-      extends RuntimeException {
-    public TwoArgConstructorRuntimeException(String message, Throwable cause) {
-      super(message, cause);
-    }
-  }
-
-  public static final class ExceptionWithPrivateConstructor extends Exception {
-    private ExceptionWithPrivateConstructor(String message, Throwable cause) {
-      super(message, cause);
-    }
-  }
-
-  @SuppressWarnings("unused") // we're testing that they're not used
-  public static final class ExceptionWithSomePrivateConstructors
-      extends Exception {
-    private ExceptionWithSomePrivateConstructors(String a) {
-    }
-
-    private ExceptionWithSomePrivateConstructors(String a, String b) {
-    }
-
-    public ExceptionWithSomePrivateConstructors(
-        String a, String b, String c) {
-    }
-
-    private ExceptionWithSomePrivateConstructors(
-        String a, String b, String c, String d) {
-    }
-
-    private ExceptionWithSomePrivateConstructors(
-        String a, String b, String c, String d, String e) {
-    }
-  }
-
-  public static final class ExceptionWithManyConstructors extends Exception {
-    boolean usedExpectedConstructor;
-
-    public ExceptionWithManyConstructors() {
-    }
-
-    public ExceptionWithManyConstructors(Integer i) {
-    }
-
-    public ExceptionWithManyConstructors(Throwable a) {
-    }
-
-    public ExceptionWithManyConstructors(Throwable a, Throwable b) {
-    }
-
-    public ExceptionWithManyConstructors(String s, Throwable b) {
-      usedExpectedConstructor = true;
-    }
-
-    public ExceptionWithManyConstructors(
-        Throwable a, Throwable b, Throwable c) {
-    }
-
-    public ExceptionWithManyConstructors(
-        Throwable a, Throwable b, Throwable c, Throwable d) {
-    }
-
-    public ExceptionWithManyConstructors(
-        Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) {
-    }
-
-    public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c,
-        Throwable d, Throwable e, String s, Integer i) {
-    }
+  @GwtIncompatible("ClassSanityTester")
+  public void testFutures_nullChecks() throws Exception {
+    new ClassSanityTester()
+        .forAllPublicStaticMethods(Futures.class)
+        .thatReturn(Future.class)
+        .testNulls();
   }
 
-  public static final class ExceptionWithoutThrowableConstructor
-      extends Exception {
-    public ExceptionWithoutThrowableConstructor(String s) {
-      super(s);
-    }
+  static AssertionFailedError failureWithCause(Throwable cause, String message) {
+    AssertionFailedError failure = new AssertionFailedError(message);
+    failure.initCause(cause);
+    return failure;
   }
 
-  public static final class ExceptionWithWrongTypesConstructor
-      extends Exception {
-    public ExceptionWithWrongTypesConstructor(Integer i, String s) {
-      super(s);
-    }
-  }
+  /**
+   * A future that throws a runtime exception from get.
+   */
+  static class BuggyFuture extends AbstractFuture<String> {
 
-  private static final class ExceptionWithGoodAndBadConstructor extends Exception {
-    public ExceptionWithGoodAndBadConstructor(String message, Throwable cause) {
-      throw new RuntimeException("bad constructor");
-    }
-    public ExceptionWithGoodAndBadConstructor(Throwable cause) {
-      super(cause);
+    @Override
+    public String get() {
+      throw new RuntimeException();
     }
-  }
 
-  private static final class ExceptionWithBadConstructor extends Exception {
-    public ExceptionWithBadConstructor(String message, Throwable cause) {
-      throw new RuntimeException("bad constructor");
+    @Override
+    public boolean set(String v) {
+      return super.set(v);
     }
   }
 
-  public void testFutures_nullChecks() throws Exception {
-    new ClassSanityTester()
-        .forAllPublicStaticMethods(Futures.class)
-        .thatReturn(Future.class)
-        .testNulls();
-  }
+  // This test covers a bug where an Error thrown from a callback could cause the TimeoutFuture to
+  // never complete when timing out.  Notably, nothing would get logged since the Error would get
+  // stuck in the ScheduledFuture inside of TimeoutFuture and nothing ever calls get on it.
 
-  private static void failWithCause(Throwable cause, String message) {
-    AssertionFailedError failure = new AssertionFailedError(message);
-    failure.initCause(cause);
-    throw failure;
-  }
+  // Simulate a timeout that fires before the call the SES.schedule returns but the future is
+  // already completed.
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java
new file mode 100644
index 0000000..89eb61c
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+
+import com.google.common.util.concurrent.ForwardingListenableFuture.SimpleForwardingListenableFuture;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Unit tests for {@link Futures#transformAsync(ListenableFuture, AsyncFunction)}.
+ *
+ * @author Nishant Thakkar
+ */
+public class FuturesTransformAsyncTest
+    extends AbstractChainedListenableFutureTest<String> {
+  protected static final int SLOW_OUTPUT_VALID_INPUT_DATA = 2;
+  protected static final int SLOW_FUNC_VALID_INPUT_DATA = 3;
+  private static final String RESULT_DATA = "SUCCESS";
+
+  private SettableFuture<String> outputFuture;
+  // Signals that the function is waiting to complete
+  private CountDownLatch funcIsWaitingLatch;
+  // Signals the function so it will complete
+  private CountDownLatch funcCompletionLatch;
+
+  @Override protected ListenableFuture<String> buildChainingFuture(
+      ListenableFuture<Integer> inputFuture) {
+    outputFuture = SettableFuture.create();
+    funcIsWaitingLatch = new CountDownLatch(1);
+    funcCompletionLatch = new CountDownLatch(1);
+    return Futures.transformAsync(inputFuture, new ChainingFunction());
+  }
+
+  @Override protected String getSuccessfulResult() {
+    return RESULT_DATA;
+  }
+
+  private class ChainingFunction implements AsyncFunction<Integer, String> {
+    @Override
+    public ListenableFuture<String> apply(Integer input) {
+      switch (input) {
+        case VALID_INPUT_DATA: outputFuture.set(RESULT_DATA); break;
+        case SLOW_OUTPUT_VALID_INPUT_DATA: break;  // do nothing to the result
+        case SLOW_FUNC_VALID_INPUT_DATA:
+          funcIsWaitingLatch.countDown();
+          awaitUninterruptibly(funcCompletionLatch);
+          break;
+        default: throw new UndeclaredThrowableException(EXCEPTION);
+      }
+      return outputFuture;
+    }
+  }
+
+  public void testFutureGetThrowsFunctionException() throws Exception {
+    inputFuture.set(EXCEPTION_DATA);
+    listener.assertException(EXCEPTION);
+  }
+
+  public void testFutureGetThrowsCancellationIfInputCancelled()
+      throws Exception {
+    inputFuture.cancel(true); // argument is ignored
+    try {
+      resultFuture.get();
+      fail("Result future must throw CancellationException"
+          + " if input future is cancelled.");
+    } catch (CancellationException expected) {}
+  }
+
+  public void testFutureGetThrowsCancellationIfOutputCancelled()
+      throws Exception {
+    inputFuture.set(SLOW_OUTPUT_VALID_INPUT_DATA);
+    outputFuture.cancel(true); // argument is ignored
+    try {
+      resultFuture.get();
+      fail("Result future must throw CancellationException"
+          + " if function output future is cancelled.");
+    } catch (CancellationException expected) {}
+  }
+
+  public void testFutureCancelBeforeInputCompletion() throws Exception {
+    assertTrue(resultFuture.cancel(true));
+    assertTrue(resultFuture.isCancelled());
+    assertTrue(inputFuture.isCancelled());
+    assertFalse(outputFuture.isCancelled());
+    try {
+      resultFuture.get();
+      fail("Result future is cancelled and should have thrown a"
+          + " CancellationException");
+    } catch (CancellationException expected) {}
+  }
+
+  public void testFutureCancellableBeforeOutputCompletion() throws Exception {
+    inputFuture.set(SLOW_OUTPUT_VALID_INPUT_DATA);
+    assertTrue(resultFuture.cancel(true));
+    assertTrue(resultFuture.isCancelled());
+    assertFalse(inputFuture.isCancelled());
+    assertTrue(outputFuture.isCancelled());
+    try {
+      resultFuture.get();
+      fail("Result future is cancelled and should have thrown a"
+          + " CancellationException");
+    } catch (CancellationException expected) {}
+  }
+
+  public void testFutureCancellableBeforeFunctionCompletion() throws Exception {
+    // Set the result in a separate thread since this test runs the function
+    // (which will block) in the same thread.
+    new Thread() {
+      @Override
+      public void run() {
+        inputFuture.set(SLOW_FUNC_VALID_INPUT_DATA);
+      }
+    }.start();
+    funcIsWaitingLatch.await();
+
+    assertTrue(resultFuture.cancel(true));
+    assertTrue(resultFuture.isCancelled());
+    assertFalse(inputFuture.isCancelled());
+    assertFalse(outputFuture.isCancelled());
+    try {
+      resultFuture.get();
+      fail("Result future is cancelled and should have thrown a"
+          + " CancellationException");
+    } catch (CancellationException expected) {}
+
+    funcCompletionLatch.countDown();  // allow the function to complete
+    try {
+      outputFuture.get();
+      fail("The function output future is cancelled and should have thrown a"
+          + " CancellationException");
+    } catch (CancellationException expected) {}
+  }
+
+  public void testFutureCancelAfterCompletion() throws Exception {
+    inputFuture.set(VALID_INPUT_DATA);
+    assertFalse(resultFuture.cancel(true));
+    assertFalse(resultFuture.isCancelled());
+    assertFalse(inputFuture.isCancelled());
+    assertFalse(outputFuture.isCancelled());
+    assertEquals(RESULT_DATA, resultFuture.get());
+  }
+
+  public void testFutureGetThrowsRuntimeException() throws Exception {
+    BadFuture badInput = new BadFuture(Futures.immediateFuture(20));
+    ListenableFuture<String> chain = buildChainingFuture(badInput);
+    try {
+      chain.get();
+      fail("Future.get must throw an exception when the input future fails.");
+    } catch (ExecutionException e) {
+      assertSame(RuntimeException.class, e.getCause().getClass());
+    }
+  }
+
+  /**
+   * Proxy to throw a {@link RuntimeException} out of the {@link #get()} method.
+   */
+  public static class BadFuture
+      extends SimpleForwardingListenableFuture<Integer> {
+    protected BadFuture(ListenableFuture<Integer> delegate) {
+      super(delegate);
+    }
+
+    @Override
+    public Integer get() {
+      throw new RuntimeException("Oops");
+    }
+  }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java b/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java
new file mode 100644
index 0000000..25a49f5
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Ints;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Generated tests for {@link Monitor}.
+ *
+ * <p>This test class generates all of its own test cases in the {@link #suite()} method. Every
+ * {@code enterXxx}, {@code tryEnterXxx}, and {@code waitForXxx} method of the {@code Monitor} class
+ * is analyzed reflectively to determine appropriate test cases based on its signature. Additional
+ * ad hoc test cases can be found in {@link SupplementalMonitorTest}.
+ *
+ * @author Justin T. Sampson
+ */
+
+public class GeneratedMonitorTest extends TestCase {
+
+  public static TestSuite suite() {
+    TestSuite suite = new TestSuite();
+
+    Method[] methods = Monitor.class.getMethods();
+    sortMethods(methods);
+    for (Method method : methods) {
+      if (isAnyEnter(method) || isWaitFor(method)) {
+        validateMethod(method);
+        addTests(suite, method);
+      }
+    }
+
+    assertEquals(548, suite.testCount());
+
+    return suite;
+  }
+
+  /**
+   * A typical timeout value we'll use in the tests.
+   */
+  private static final long SMALL_TIMEOUT_MILLIS = 10;
+
+  /**
+   * How long to wait when determining that a thread is blocked if we expect it to be blocked.
+   */
+  private static final long EXPECTED_HANG_DELAY_MILLIS = 75;
+
+  /**
+   * How long to wait when determining that a thread is blocked if we DON'T expect it to be blocked.
+   */
+  private static final long UNEXPECTED_HANG_DELAY_MILLIS = 10000;
+
+  /**
+   * Various scenarios to be generated for each method under test. The actual scenario generation
+   * (determining which scenarios are applicable to which methods and what the outcome should be)
+   * takes place in {@link #addTests(TestSuite, Method)}.
+   */
+  private enum Scenario {
+
+    SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+    UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+    SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+    SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING,
+
+    SATISFIED_BEFORE_WAITING,
+    SATISFIED_WHILE_WAITING,
+    SATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+    UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+    UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING;
+
+    @Override
+    public String toString() {
+      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+    }
+
+  }
+
+  /**
+   * Timeout values to combine with each {@link Scenario}.
+   */
+  private enum Timeout {
+
+    MIN(Long.MIN_VALUE, "-oo"),
+    MINUS_SMALL(-SMALL_TIMEOUT_MILLIS, "-" + SMALL_TIMEOUT_MILLIS + "ms"),
+    ZERO(0L, "0ms"),
+    SMALL(SMALL_TIMEOUT_MILLIS, SMALL_TIMEOUT_MILLIS + "ms"),
+    LARGE(UNEXPECTED_HANG_DELAY_MILLIS * 2, (2 * UNEXPECTED_HANG_DELAY_MILLIS) + "ms"),
+    MAX(Long.MAX_VALUE, "+oo");
+
+    final long millis;
+    final String label;
+
+    private Timeout(long millis, String label) {
+      this.millis = millis;
+      this.label = label;
+    }
+
+    @Override
+    public String toString() {
+      return label;
+    }
+
+  }
+
+  /**
+   * Convenient subsets of the {@link Timeout} enumeration for specifying scenario outcomes.
+   */
+  private enum TimeoutsToUse {
+
+    ANY(Timeout.values()),
+    PAST(Timeout.MIN, Timeout.MINUS_SMALL, Timeout.ZERO),
+    FUTURE(Timeout.SMALL, Timeout.MAX),
+    SMALL(Timeout.SMALL),
+    FINITE(Timeout.MIN, Timeout.MINUS_SMALL, Timeout.ZERO, Timeout.SMALL),
+    INFINITE(Timeout.LARGE, Timeout.MAX);
+
+    final ImmutableList<Timeout> timeouts;
+
+    private TimeoutsToUse(Timeout... timeouts) {
+      this.timeouts = ImmutableList.copyOf(timeouts);
+    }
+
+  }
+
+  /**
+   * Possible outcomes of calling any of the methods under test.
+   */
+  private enum Outcome {
+
+    /**
+     * The method returned normally and is either void or returned true.
+     */
+    SUCCESS,
+
+    /**
+     * The method returned false.
+     */
+    FAILURE,
+
+    /**
+     * The method threw an InterruptedException.
+     */
+    INTERRUPT,
+
+    /**
+     * The method did not return or throw anything.
+     */
+    HANG;
+
+    @Override
+    public String toString() {
+      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+    }
+
+  }
+
+  /**
+   * Identifies all enterXxx and tryEnterXxx methods.
+   */
+  private static boolean isAnyEnter(Method method) {
+    return method.getName().startsWith("enter") || method.getName().startsWith("tryEnter");
+  }
+
+  /**
+   * Identifies just tryEnterXxx methods (a subset of {@link #isAnyEnter}), which never block.
+   */
+  private static boolean isTryEnter(Method method) {
+    return method.getName().startsWith("tryEnter");
+  }
+
+  /**
+   * Identifies just enterIfXxx methods (a subset of {@link #isAnyEnter}), which are mostly like the
+   * enterXxx methods but behave like tryEnterXxx in some scenarios.
+   */
+  private static boolean isEnterIf(Method method) {
+    return method.getName().startsWith("enterIf");
+  }
+
+  /**
+   * Identifies all waitForXxx methods, which must be called while occupying the monitor.
+   */
+  private static boolean isWaitFor(Method method) {
+    return method.getName().startsWith("waitFor");
+  }
+
+  /**
+   * Determines whether the given method takes a Guard as its first parameter.
+   */
+  private static boolean isGuarded(Method method) {
+    Class<?>[] parameterTypes = method.getParameterTypes();
+    return parameterTypes.length >= 1 && parameterTypes[0] == Monitor.Guard.class;
+  }
+
+  /**
+   * Determines whether the given method takes a time and unit as its last two parameters.
+   */
+  private static boolean isTimed(Method method) {
+    Class<?>[] parameterTypes = method.getParameterTypes();
+    return parameterTypes.length >= 2
+        && parameterTypes[parameterTypes.length - 2] == long.class
+        && parameterTypes[parameterTypes.length - 1] == TimeUnit.class;
+  }
+
+  /**
+   * Determines whether the given method returns a boolean value.
+   */
+  private static boolean isBoolean(Method method) {
+    return method.getReturnType() == boolean.class;
+  }
+
+  /**
+   * Determines whether the given method can throw InterruptedException.
+   */
+  private static boolean isInterruptible(Method method) {
+    return Arrays.asList(method.getExceptionTypes()).contains(InterruptedException.class);
+  }
+
+  /**
+   * Sorts the given methods primarily by name and secondarily by number of parameters.
+   */
+  private static void sortMethods(Method[] methods) {
+    Arrays.sort(methods, new Comparator<Method>() {
+      @Override public int compare(Method m1, Method m2) {
+        int nameComparison = m1.getName().compareTo(m2.getName());
+        if (nameComparison != 0) {
+          return nameComparison;
+        } else {
+          return Ints.compare(m1.getParameterTypes().length, m2.getParameterTypes().length);
+        }
+      }
+    });
+  }
+
+  /**
+   * Validates that the given method's signature meets all of our assumptions.
+   */
+  private static void validateMethod(Method method) {
+    String desc = method.toString();
+
+    assertTrue(desc, isAnyEnter(method) || isWaitFor(method));
+
+    switch (method.getParameterTypes().length) {
+      case 0:
+        assertFalse(desc, isGuarded(method));
+        assertFalse(desc, isTimed(method));
+        break;
+      case 1:
+        assertTrue(desc, isGuarded(method));
+        assertFalse(desc, isTimed(method));
+        break;
+      case 2:
+        assertFalse(desc, isGuarded(method));
+        assertTrue(desc, isTimed(method));
+        break;
+      case 3:
+        assertTrue(desc, isGuarded(method));
+        assertTrue(desc, isTimed(method));
+        break;
+      default:
+        fail(desc);
+    }
+
+    if (method.getReturnType() == void.class) {
+      assertFalse(desc, isBoolean(method));
+    } else {
+      assertTrue(desc, isBoolean(method));
+    }
+
+    switch (method.getExceptionTypes().length) {
+      case 0:
+        assertFalse(desc, isInterruptible(method));
+        break;
+      case 1:
+        assertTrue(desc, isInterruptible(method));
+        break;
+      default:
+        fail(desc);
+    }
+
+    if (isEnterIf(method)) {
+      assertTrue(desc, isGuarded(method));
+      assertTrue(desc, isBoolean(method));
+    } else if (isTryEnter(method)) {
+      assertFalse(desc, isTimed(method));
+      assertTrue(desc, isBoolean(method));
+      assertFalse(desc, isInterruptible(method));
+    } else if (isWaitFor(method)) {
+      assertTrue(desc, isGuarded(method));
+      assertEquals(desc, isTimed(method), isBoolean(method));
+    } else { // any other enterXxx method
+      assertEquals(desc, isTimed(method), isBoolean(method));
+    }
+  }
+
+  /**
+   * Generates all test cases appropriate for the given method.
+   */
+  private static void addTests(TestSuite suite, Method method) {
+    if (isGuarded(method)) {
+      for (boolean fair1 : new boolean[] { true, false }) {
+        for (boolean fair2 : new boolean[] { true, false }) {
+          suite.addTest(generateGuardWithWrongMonitorTestCase(method, fair1, fair2));
+        }
+      }
+    }
+    if (isAnyEnter(method)) {
+      addTests(suite, method,
+          Scenario.SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+          TimeoutsToUse.ANY,
+          Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+          TimeoutsToUse.FINITE,
+          isGuarded(method)
+              ? (isBoolean(method) ? Outcome.FAILURE : Outcome.HANG)
+              : Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+          TimeoutsToUse.INFINITE,
+          isGuarded(method)
+              ? (isTryEnter(method) || isEnterIf(method) ? Outcome.FAILURE : Outcome.HANG)
+              : Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+          TimeoutsToUse.FINITE,
+          isBoolean(method) ? Outcome.FAILURE : Outcome.HANG);
+      addTests(suite, method,
+          Scenario.SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+          TimeoutsToUse.INFINITE,
+          isGuarded(method)
+              ? Outcome.HANG
+              : (isTryEnter(method) ? Outcome.FAILURE : Outcome.HANG));
+      addTests(suite, method,
+          Scenario.SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING,
+          TimeoutsToUse.ANY,
+          isInterruptible(method) ? Outcome.INTERRUPT : Outcome.SUCCESS);
+    } else { // any waitForXxx method
+      suite.addTest(generateWaitForWhenNotOccupyingTestCase(method, true));
+      suite.addTest(generateWaitForWhenNotOccupyingTestCase(method, false));
+      addTests(suite, method,
+          Scenario.SATISFIED_BEFORE_WAITING,
+          TimeoutsToUse.ANY,
+          Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.SATISFIED_WHILE_WAITING,
+          TimeoutsToUse.INFINITE,
+          Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.SATISFIED_WHILE_WAITING,
+          TimeoutsToUse.PAST,
+          Outcome.FAILURE);
+      addTests(suite, method,
+          Scenario.SATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+          TimeoutsToUse.ANY,
+          Outcome.SUCCESS);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+          TimeoutsToUse.FINITE,
+          Outcome.FAILURE);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+          TimeoutsToUse.INFINITE,
+          Outcome.HANG);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+          TimeoutsToUse.PAST,
+          // prefer responding to interrupt over timing out
+          isInterruptible(method) ? Outcome.INTERRUPT : Outcome.FAILURE);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+          TimeoutsToUse.SMALL,
+          isInterruptible(method) ? Outcome.INTERRUPT : Outcome.FAILURE);
+      addTests(suite, method,
+          Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+          TimeoutsToUse.INFINITE,
+          isInterruptible(method) ? Outcome.INTERRUPT : Outcome.HANG);
+    }
+  }
+
+  /**
+   * Generates test cases for the given combination of scenario and timeouts. For methods that take
+   * an explicit timeout value, all of the given timeoutsToUse result in individual test cases. For
+   * methods that do not take an explicit timeout value, a single test case is generated only if the
+   * implicit timeout of that method matches the given timeoutsToUse. For example, enter() is
+   * treated like enter(MAX, MILLIS) and tryEnter() is treated like enter(0, MILLIS).
+   */
+  private static void addTests(TestSuite suite, Method method, Scenario scenario,
+      TimeoutsToUse timeoutsToUse, Outcome expectedOutcome) {
+    for (boolean fair : new boolean[] { true, false }) {
+      if (isTimed(method)) {
+        for (Timeout timeout : timeoutsToUse.timeouts) {
+          suite.addTest(new GeneratedMonitorTest(method, scenario, fair, timeout, expectedOutcome));
+        }
+      } else {
+        Timeout implicitTimeout = (isTryEnter(method) ? Timeout.ZERO : Timeout.MAX);
+        if (timeoutsToUse.timeouts.contains(implicitTimeout)) {
+          suite.addTest(new GeneratedMonitorTest(method, scenario, fair, null, expectedOutcome));
+        }
+      }
+    }
+  }
+
+  /**
+   * A guard that encapsulates a simple, mutable boolean flag.
+   */
+  static class FlagGuard extends Monitor.Guard {
+
+    private boolean satisfied;
+
+    protected FlagGuard(Monitor monitor) {
+      super(monitor);
+    }
+
+    @Override
+    public boolean isSatisfied() {
+      return satisfied;
+    }
+
+    public void setSatisfied(boolean satisfied) {
+      this.satisfied = satisfied;
+    }
+
+  }
+
+  private final Method method;
+  private final Scenario scenario;
+  private final Timeout timeout;
+  private final Outcome expectedOutcome;
+  private final Monitor monitor;
+  private final FlagGuard guard;
+  private final CountDownLatch tearDownLatch;
+  private final CountDownLatch doingCallLatch;
+  private final CountDownLatch callCompletedLatch;
+
+  private GeneratedMonitorTest(
+      Method method, Scenario scenario, boolean fair, Timeout timeout, Outcome expectedOutcome) {
+    super(nameFor(method, scenario, fair, timeout, expectedOutcome));
+    this.method = method;
+    this.scenario = scenario;
+    this.timeout = timeout;
+    this.expectedOutcome = expectedOutcome;
+    this.monitor = new Monitor(fair);
+    this.guard = new FlagGuard(monitor);
+    this.tearDownLatch = new CountDownLatch(1);
+    this.doingCallLatch = new CountDownLatch(1);
+    this.callCompletedLatch = new CountDownLatch(1);
+  }
+
+  private static String nameFor(
+      Method method, Scenario scenario, boolean fair, Timeout timeout, Outcome expectedOutcome) {
+    return String.format(Locale.ROOT,
+        "%s%s(%s)/%s->%s",
+        method.getName(),
+        fair ? "(fair)" : "(nonfair)",
+        (timeout == null) ? "untimed" : timeout,
+        scenario,
+        expectedOutcome);
+  }
+
+  @Override
+  protected void runTest() throws Throwable {
+    final Runnable runChosenTest = new Runnable() {
+      @Override public void run() { runChosenTest(); }
+    };
+    final FutureTask<Void> task = new FutureTask<Void>(runChosenTest, null);
+    startThread(new Runnable() {
+        @Override public void run() { task.run(); }
+      });
+    awaitUninterruptibly(doingCallLatch);
+    long hangDelayMillis = (expectedOutcome == Outcome.HANG)
+        ? EXPECTED_HANG_DELAY_MILLIS
+        : UNEXPECTED_HANG_DELAY_MILLIS;
+    boolean hung = !awaitUninterruptibly(
+        callCompletedLatch, hangDelayMillis, TimeUnit.MILLISECONDS);
+    if (hung) {
+      assertEquals(expectedOutcome, Outcome.HANG);
+    } else {
+      assertNull(task.get(UNEXPECTED_HANG_DELAY_MILLIS, TimeUnit.MILLISECONDS));
+    }
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    // We don't want to leave stray threads running after each test. At this point, every thread
+    // launched by this test is either:
+    //
+    // (a) Blocked attempting to enter the monitor.
+    // (b) Waiting for the single guard to become satisfied.
+    // (c) Occupying the monitor and awaiting the tearDownLatch.
+    //
+    // Except for (c), every thread should occupy the monitor very briefly, and every thread leaves
+    // the monitor with the guard satisfied. Therefore as soon as tearDownLatch is triggered, we
+    // should be able to enter the monitor, and then we set the guard to satisfied for the benefit
+    // of any remaining waiting threads.
+
+    tearDownLatch.countDown();
+    assertTrue("Monitor still occupied in tearDown()",
+        monitor.enter(UNEXPECTED_HANG_DELAY_MILLIS, TimeUnit.MILLISECONDS));
+    try {
+      guard.setSatisfied(true);
+    } finally {
+      monitor.leave();
+    }
+  }
+
+  private void runChosenTest() {
+    if (isAnyEnter(method)) {
+      runEnterTest();
+    } else {
+      runWaitTest();
+    }
+  }
+
+  private void runEnterTest() {
+    assertFalse(Thread.currentThread().isInterrupted());
+    assertFalse(monitor.isOccupiedByCurrentThread());
+
+    doEnterScenarioSetUp();
+
+    boolean interruptedBeforeCall = Thread.currentThread().isInterrupted();
+    Outcome actualOutcome = doCall();
+    boolean occupiedAfterCall = monitor.isOccupiedByCurrentThread();
+    boolean interruptedAfterCall = Thread.currentThread().isInterrupted();
+
+    if (occupiedAfterCall) {
+      guard.setSatisfied(true);
+      monitor.leave();
+      assertFalse(monitor.isOccupiedByCurrentThread());
+    }
+
+    assertEquals(expectedOutcome, actualOutcome);
+    assertEquals(expectedOutcome == Outcome.SUCCESS, occupiedAfterCall);
+    assertEquals(interruptedBeforeCall && expectedOutcome != Outcome.INTERRUPT,
+        interruptedAfterCall);
+  }
+
+  private void doEnterScenarioSetUp() {
+    switch (scenario) {
+      case SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING:
+        enterSatisfyGuardAndLeaveInCurrentThread();
+        break;
+      case UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING:
+        break;
+      case SATISFIED_AND_OCCUPIED_BEFORE_ENTERING:
+        enterSatisfyGuardAndLeaveInCurrentThread();
+        enterAndRemainOccupyingInAnotherThread();
+        break;
+      case SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING:
+        enterSatisfyGuardAndLeaveInCurrentThread();
+        Thread.currentThread().interrupt();
+        break;
+      default:
+        throw new AssertionError("unsupported scenario: " + scenario);
+    }
+  }
+
+  private void runWaitTest() {
+    assertFalse(Thread.currentThread().isInterrupted());
+    assertFalse(monitor.isOccupiedByCurrentThread());
+    monitor.enter();
+    try {
+      assertTrue(monitor.isOccupiedByCurrentThread());
+
+      doWaitScenarioSetUp();
+
+      boolean interruptedBeforeCall = Thread.currentThread().isInterrupted();
+      Outcome actualOutcome = doCall();
+      boolean occupiedAfterCall = monitor.isOccupiedByCurrentThread();
+      boolean interruptedAfterCall = Thread.currentThread().isInterrupted();
+
+      assertEquals(expectedOutcome, actualOutcome);
+      assertTrue(occupiedAfterCall);
+      assertEquals(interruptedBeforeCall && expectedOutcome != Outcome.INTERRUPT,
+          interruptedAfterCall);
+    } finally {
+      guard.setSatisfied(true);
+      monitor.leave();
+      assertFalse(monitor.isOccupiedByCurrentThread());
+    }
+  }
+
+  private void doWaitScenarioSetUp() {
+    switch (scenario) {
+      case SATISFIED_BEFORE_WAITING:
+        guard.setSatisfied(true);
+        break;
+      case SATISFIED_WHILE_WAITING:
+        guard.setSatisfied(false);
+        enterSatisfyGuardAndLeaveInAnotherThread(); // enter blocks until we call waitFor
+        break;
+      case UNSATISFIED_BEFORE_AND_WHILE_WAITING:
+        guard.setSatisfied(false);
+        break;
+      case SATISFIED_AND_INTERRUPTED_BEFORE_WAITING:
+        guard.setSatisfied(true);
+        Thread.currentThread().interrupt();
+        break;
+      case UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING:
+        guard.setSatisfied(false);
+        Thread.currentThread().interrupt();
+        break;
+      default:
+        throw new AssertionError("unsupported scenario: " + scenario);
+    }
+  }
+
+  private Outcome doCall() {
+    boolean guarded = isGuarded(method);
+    boolean timed = isTimed(method);
+    Object[] arguments = new Object[(guarded ? 1 : 0) + (timed ? 2 : 0)];
+    if (guarded) {
+      arguments[0] = guard;
+    }
+    if (timed) {
+      arguments[arguments.length - 2] = timeout.millis;
+      arguments[arguments.length - 1] = TimeUnit.MILLISECONDS;
+    }
+    try {
+      Object result;
+      doingCallLatch.countDown();
+      try {
+        result = method.invoke(monitor, arguments);
+      } finally {
+        callCompletedLatch.countDown();
+      }
+      if (result == null) {
+        return Outcome.SUCCESS;
+      } else if ((Boolean) result) {
+        return Outcome.SUCCESS;
+      } else {
+        return Outcome.FAILURE;
+      }
+    } catch (InvocationTargetException targetException) {
+      Throwable actualException = targetException.getTargetException();
+      if (actualException instanceof InterruptedException) {
+        return Outcome.INTERRUPT;
+      } else {
+        throw newAssertionError("unexpected exception", targetException);
+      }
+    } catch (IllegalAccessException e) {
+      throw newAssertionError("unexpected exception", e);
+    }
+  }
+
+  private void enterSatisfyGuardAndLeaveInCurrentThread() {
+    monitor.enter();
+    try {
+      guard.setSatisfied(true);
+    } finally {
+      monitor.leave();
+    }
+  }
+
+  private void enterSatisfyGuardAndLeaveInAnotherThread() {
+    final CountDownLatch startedLatch = new CountDownLatch(1);
+    startThread(new Runnable() {
+      @Override public void run() {
+        startedLatch.countDown();
+        enterSatisfyGuardAndLeaveInCurrentThread();
+      }
+    });
+    awaitUninterruptibly(startedLatch);
+  }
+
+  private void enterAndRemainOccupyingInAnotherThread() {
+    final CountDownLatch enteredLatch = new CountDownLatch(1);
+    startThread(new Runnable() {
+      @Override public void run() {
+        monitor.enter();
+        try {
+          enteredLatch.countDown();
+          awaitUninterruptibly(tearDownLatch);
+          guard.setSatisfied(true);
+        } finally {
+          monitor.leave();
+        }
+      }
+    });
+    awaitUninterruptibly(enteredLatch);
+  }
+
+  static Thread startThread(Runnable runnable) {
+    Thread thread = new Thread(runnable);
+    thread.setDaemon(true);
+    thread.start();
+    return thread;
+  }
+
+  /**
+   * Generates a test case verifying that calling any enterXxx, tryEnterXxx, or waitForXxx method
+   * with a guard that doesn't match the monitor produces an IllegalMonitorStateException.
+   */
+  private static TestCase generateGuardWithWrongMonitorTestCase(final Method method,
+                                                                final boolean fair1,
+                                                                final boolean fair2) {
+    final boolean timed = isTimed(method); // Not going to bother with all timeouts, just 0ms.
+    return new TestCase(method.getName() + (timed ? "(0ms)" : "()") + "/WrongMonitor->IMSE") {
+      @Override protected void runTest() throws Throwable {
+        Monitor monitor1 = new Monitor(fair1);
+        Monitor monitor2 = new Monitor(fair2);
+        FlagGuard guard = new FlagGuard(monitor2);
+        Object[] arguments =
+            (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard});
+        boolean occupyMonitor = isWaitFor(method);
+        if (occupyMonitor) {
+          // If we don't already occupy the monitor, we'll get an IMSE regardless of the guard (see
+          // generateWaitForWhenNotOccupyingTestCase).
+          monitor1.enter();
+        }
+        try {
+          method.invoke(monitor1, arguments);
+          fail("expected IllegalMonitorStateException");
+        } catch (InvocationTargetException e) {
+          assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
+        } finally {
+          if (occupyMonitor) {
+            monitor1.leave();
+          }
+        }
+      }
+    };
+  }
+
+  /**
+   * Generates a test case verifying that calling any waitForXxx method when not occupying the
+   * monitor produces an IllegalMonitorStateException.
+   */
+  private static TestCase generateWaitForWhenNotOccupyingTestCase(final Method method,
+                                                                  final boolean fair) {
+    final boolean timed = isTimed(method); // Not going to bother with all timeouts, just 0ms.
+    String testName = method.getName()
+        + (fair ? "(fair)" : "(nonfair)")
+        + (timed ? "(0ms)" : "()")
+        + "/NotOccupying->IMSE";
+    return new TestCase(testName) {
+      @Override protected void runTest() throws Throwable {
+        Monitor monitor = new Monitor(fair);
+        FlagGuard guard = new FlagGuard(monitor);
+        Object[] arguments =
+            (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard});
+        try {
+          method.invoke(monitor, arguments);
+          fail("expected IllegalMonitorStateException");
+        } catch (InvocationTargetException e) {
+          assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
+        }
+      }
+    };
+  }
+
+  /** Alternative to AssertionError(String, Throwable), which doesn't exist in Java 1.6 */
+  private static AssertionError newAssertionError(String message, Throwable cause) {
+    AssertionError e = new AssertionError(message);
+    e.initCause(cause);
+    return e;
+  }
+
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java b/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
index cb10fc8..d9e100c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
@@ -17,6 +17,7 @@
 package com.google.common.util.concurrent;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.truth.Truth.assertThat;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -104,7 +105,7 @@ public class ListenableFutureTester {
       future.get();
       fail("Future should rethrow the exception.");
     } catch (ExecutionException e) {
-      assertEquals(message, e.getCause().getMessage());
+      assertThat(e.getCause()).hasMessage(message);
     }
   }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java b/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
index cb1898c..994d5d9 100644
--- a/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
@@ -53,6 +53,7 @@ import com.google.common.util.concurrent.MoreExecutors.Application;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 
+import java.lang.Thread.State;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -243,6 +244,51 @@ public class MoreExecutorsTest extends JSR166TestCase {
         throwableFromOtherThread.get());
   }
 
+  /**
+   * Test for a bug where threads weren't getting signaled when shutdown was called, only when
+   * tasks completed.
+   */
+
+  public void testDirectExecutorService_awaitTermination_missedSignal() {
+    final ExecutorService service = MoreExecutors.newDirectExecutorService();
+    Thread waiter = new Thread() {
+      @Override public void run() {
+        try {
+          service.awaitTermination(1, TimeUnit.DAYS);
+        } catch (InterruptedException e) {
+          return;
+        }
+      }
+    };
+    waiter.start();
+    awaitTimedWaiting(waiter);
+    service.shutdown();
+    Uninterruptibles.joinUninterruptibly(waiter, 10, TimeUnit.SECONDS);
+    if (waiter.isAlive()) {
+      waiter.interrupt();
+      fail("awaitTermination failed to trigger after shutdown()");
+    }
+  }
+
+  /** Wait for the given thread to reach the {@link State#TIMED_WAITING} thread state. */
+  void awaitTimedWaiting(Thread thread) {
+    while (true) {
+      switch (thread.getState()) {
+        case BLOCKED:
+        case NEW:
+        case RUNNABLE:
+        case WAITING:
+          Thread.yield();
+          break;
+        case TIMED_WAITING:
+          return;
+        case TERMINATED:
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
   public void testDirectExecutorService_shutdownNow() {
     ExecutorService executor = newDirectExecutorService();
     assertEquals(ImmutableList.of(), executor.shutdownNow());
@@ -263,7 +309,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
     ListeningExecutorService executor = newDirectExecutorService();
     List<Callable<T>> tasks = ImmutableList.of();
     @SuppressWarnings("unchecked") // guaranteed by invokeAll contract
-    List<ListenableFuture<T>> futures = (List) executor.invokeAll(tasks);
+    List<ListenableFuture<T>> unused = (List) executor.invokeAll(tasks);
   }
 
   public void testListeningDecorator() throws Exception {
@@ -275,10 +321,10 @@ public class MoreExecutorsTest extends JSR166TestCase {
     List<Future<String>> results;
 
     results = service.invokeAll(callables);
-    assertThat(getOnlyElement(results)).isA(ListenableFutureTask.class);
+    assertThat(getOnlyElement(results)).isInstanceOf(TrustedListenableFutureTask.class);
 
     results = service.invokeAll(callables, 1, SECONDS);
-    assertThat(getOnlyElement(results)).isA(ListenableFutureTask.class);
+    assertThat(getOnlyElement(results)).isInstanceOf(TrustedListenableFutureTask.class);
 
     /*
      * TODO(cpovirk): move ForwardingTestCase somewhere common, and use it to
@@ -306,8 +352,8 @@ public class MoreExecutorsTest extends JSR166TestCase {
       }
     };
     ListeningScheduledExecutorService service = listeningDecorator(delegate);
-    ListenableFuture<?> future =
-        service.schedule(Callables.returning(null), 1, TimeUnit.MILLISECONDS);
+    ListenableFuture<Integer> future =
+        service.schedule(Callables.returning(42), 1, TimeUnit.MILLISECONDS);
 
     /*
      * Wait not just until the Future's value is set (as in future.get()) but
@@ -316,6 +362,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
      */
     completed.await();
     assertTrue(future.isDone());
+    assertThat(future.get()).isEqualTo(42);
     assertListenerRunImmediately(future);
     assertEquals(0, delegate.getQueue().size());
   }
@@ -472,7 +519,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
       invokeAnyImpl(e, l, false, 0);
       shouldThrow();
     } catch (ExecutionException success) {
-      assertTrue(success.getCause() instanceof NullPointerException);
+      assertThat(success.getCause()).isInstanceOf(NullPointerException.class);
     } finally {
       joinPool(e);
     }
diff --git a/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java b/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
index 669e547..359f71b 100644
--- a/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
+++ b/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
 import com.google.common.testing.AbstractPackageSanityTests;
 import com.google.common.util.concurrent.RateLimiter.SleepingStopwatch;
 
+import java.io.IOException;
+
 /**
  * Basic sanity tests for the entire package.
  *
@@ -40,6 +42,7 @@ public class PackageSanityTests extends AbstractPackageSanityTests {
   public PackageSanityTests() {
     setDefault(RateLimiter.class, RateLimiter.create(1.0));
     setDefault(SleepingStopwatch.class, NO_OP_STOPWATCH);
+    setDefault(Class.class, IOException.class);
     setDefault(long.class, 0L);
   }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java b/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
index 62ced5c..69a7011 100644
--- a/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
@@ -37,6 +37,7 @@ import org.mockito.Mockito;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 
@@ -64,6 +65,14 @@ public class RateLimiterTest extends TestCase {
     assertFalse("Capable of acquiring secondary permit", r.tryAcquire());
   }
 
+  public void testDoubleMinValueCanAcquireExactlyOnce() {
+    RateLimiter r = RateLimiter.create(stopwatch, Double.MIN_VALUE);
+    assertTrue("Unable to acquire initial permit", r.tryAcquire());
+    assertFalse("Capable of acquiring an additional permit", r.tryAcquire());
+    stopwatch.sleepMillis(Integer.MAX_VALUE);
+    assertFalse("Capable of acquiring an additional permit after sleeping", r.tryAcquire());
+  }
+
   public void testSimpleRateUpdate() {
     RateLimiter limiter = RateLimiter.create(5.0, 5, SECONDS);
     assertEquals(5.0, limiter.getRate());
@@ -174,8 +183,9 @@ public class RateLimiterTest extends TestCase {
     }
   }
 
+  @SuppressUnderAndroid // difference in String.format rounding?
   public void testWarmUp() {
-    RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS);
+    RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS, 3.0);
     for (int i = 0; i < 8; i++) {
       limiter.acquire(); // #1
     }
@@ -199,8 +209,49 @@ public class RateLimiterTest extends TestCase {
         "R0.00, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50"); // #7
   }
 
+  public void testWarmUpWithColdFactor() {
+    RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 10.0);
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // #1
+    }
+    stopwatch.sleepMillis(200); // #2: to repay for the last acquire
+    stopwatch.sleepMillis(4000); // #3: becomes cold again
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // // #4
+    }
+    stopwatch.sleepMillis(200); // #5: to repay for the last acquire
+    stopwatch.sleepMillis(1000); // #6: still warm! It would take another 3 seconds to go cold
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // #7
+    }
+    assertEvents(
+        "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
+        "U0.20", // #2
+        "U4.00", // #3
+        "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #4
+        "U0.20", // #5
+        "U1.00", // #6
+        "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #7
+  }
+
+  public void testWarmUpWithColdFactor1() {
+    RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 1.0);
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // #1
+    }
+    stopwatch.sleepMillis(340); // #2
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // #3
+    }
+    assertEvents(
+        "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20", // #1
+        "U0.34", // #2
+        "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #3
+  }
+
+  @SuppressUnderAndroid // difference in String.format rounding?
   public void testWarmUpAndUpdate() {
-    RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS);
+    RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS, 3.0);
     for (int i = 0; i < 8; i++) {
       limiter.acquire(); // // #1
     }
@@ -231,6 +282,38 @@ public class RateLimiterTest extends TestCase {
         "R0.34, R0.28, R0.25, R0.25"); // #7 (cont.), note, this matches #5
   }
 
+  public void testWarmUpAndUpdateWithColdFactor() {
+    RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 10.0);
+    for (int i = 0; i < 8; i++) {
+      limiter.acquire(); // #1
+    }
+    stopwatch.sleepMillis(4200); // #2: back to cold state (warmup period + repay last acquire)
+    for (int i = 0; i < 3; i++) { // only three steps, we're somewhere in the warmup period
+      limiter.acquire(); // #3
+    }
+
+    limiter.setRate(10.0); // double the rate!
+    limiter.acquire(); // #4, we repay the debt of the last acquire (imposed by the old rate)
+    for (int i = 0; i < 4; i++) {
+      limiter.acquire(); // #5
+    }
+    stopwatch.sleepMillis(4100); // #6, back to cold state (warmup period + repay last acquire)
+    for (int i = 0; i < 11; i++) {
+      limiter.acquire(); // #7, showing off the warmup starting from totally cold
+    }
+
+    // make sure the areas (times) remain the same, while permits are different
+    assertEvents(
+        "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
+        "U4.20", // #2
+        "R0.00, R1.75, R1.26", // #3, after that the rate changes
+        "R0.76", // #4, this is what the throttling would be with the old rate
+        "R0.20, R0.10, R0.10, R0.10", // #5
+        "U4.10", // #6
+        "R0.00, R0.94, R0.81, R0.69, R0.57, R0.44, R0.32", // #7
+        "R0.20, R0.10, R0.10, R0.10"); // #7 (cont.), note, this matches #5
+  }
+
   public void testBurstyAndUpdate() {
     RateLimiter rateLimiter = RateLimiter.create(stopwatch, 1.0);
     rateLimiter.acquire(1); // no wait
@@ -335,7 +418,7 @@ public class RateLimiterTest extends TestCase {
 
   public void testInfinity_WarmUp() {
     RateLimiter limiter = RateLimiter.create(
-        stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS);
+        stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS, 3.0);
     limiter.acquire(Integer.MAX_VALUE / 4);
     limiter.acquire(Integer.MAX_VALUE / 2);
     limiter.acquire(Integer.MAX_VALUE);
@@ -355,7 +438,7 @@ public class RateLimiterTest extends TestCase {
   }
 
   public void testInfinity_WarmUpTimeElapsed() {
-    RateLimiter limiter = RateLimiter.create(stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS);
+    RateLimiter limiter = RateLimiter.create(stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS, 3.0);
     stopwatch.instant += 1000000;
     limiter.setRate(1.0);
     for (int i = 0; i < 5; i++) {
@@ -393,17 +476,19 @@ public class RateLimiterTest extends TestCase {
    */
   public void testTimeToWarmUpIsHonouredEvenWithWeights() {
     Random random = new Random();
-    int maxPermits = 10;
+    int warmupPermits = 10;
+    double[] coldFactorsToTest = { 2.0, 3.0, 10.0 };
     double[] qpsToTest = { 4.0, 2.0, 1.0, 0.5, 0.1 };
     for (int trial = 0; trial < 100; trial++) {
-      for (double qps : qpsToTest) {
-        // Since we know that: maxPermits = 0.5 * warmup / stableInterval;
-        // then if maxPermits == 10, we have:
-        // warmupSeconds = 20 / qps
-        long warmupMillis = (long) ((2 * maxPermits / qps) * 1000.0);
-        RateLimiter rateLimiter = RateLimiter.create(
-            stopwatch, qps, warmupMillis, MILLISECONDS);
-        assertEquals(warmupMillis, measureTotalTimeMillis(rateLimiter, maxPermits, random));
+      for (double coldFactor : coldFactorsToTest) {
+        for (double qps : qpsToTest) {
+          // If warmupPermits = maxPermits - thresholdPermits then
+          // warmupPeriod = (1 + coldFactor) * warmupPermits * stableInterval / 2
+          long warmupMillis = (long) ((1 + coldFactor) * warmupPermits / (2.0 * qps) * 1000.0);
+          RateLimiter rateLimiter = RateLimiter.create(
+              stopwatch, qps, warmupMillis, MILLISECONDS, coldFactor);
+          assertEquals(warmupMillis, measureTotalTimeMillis(rateLimiter, warmupPermits, random));
+        }
       }
     }
   }
@@ -411,7 +496,8 @@ public class RateLimiterTest extends TestCase {
   public void testNulls() {
     NullPointerTester tester = new NullPointerTester()
         .setDefault(SleepingStopwatch.class, stopwatch)
-        .setDefault(int.class, 1);
+        .setDefault(int.class, 1)
+        .setDefault(double.class, 1.0d);
     tester.testStaticMethods(RateLimiter.class, Visibility.PACKAGE);
     tester.testInstanceMethods(RateLimiter.create(stopwatch, 5.0), Visibility.PACKAGE);
   }
@@ -451,7 +537,7 @@ public class RateLimiterTest extends TestCase {
 
     void sleepMicros(String caption, long micros) {
       instant += MICROSECONDS.toNanos(micros);
-      events.add(caption + String.format("%3.2f", (micros / 1000000.0)));
+      events.add(caption + String.format(Locale.ROOT, "%3.2f", (micros / 1000000.0)));
     }
 
     @Override
@@ -473,16 +559,29 @@ public class RateLimiterTest extends TestCase {
     }
   }
 
-  public void testMocking() throws Exception {
-    RateLimiter mockito = Mockito.mock(RateLimiter.class);
-    RateLimiter easyMock = EasyMock.createNiceMock(RateLimiter.class);
-    EasyMock.replay(easyMock);
+  /*
+   * Note: Mockito appears to lose its ability to Mock doGetRate as of Android 21. If we start
+   * testing with that version or newer, we'll need to suppress this test (or see if Mockito can be
+   * changed to support this).
+   */
+  public void testMockingMockito() throws Exception {
+    RateLimiter mock = Mockito.mock(RateLimiter.class);
+    doTestMocking(mock);
+  }
+
+  @SuppressUnderAndroid // EasyMock Class Extension doesn't appear to work on Android.
+  public void testMockingEasyMock() throws Exception {
+    RateLimiter mock = EasyMock.createNiceMock(RateLimiter.class);
+    EasyMock.replay(mock);
+    doTestMocking(mock);
+  }
+
+  private static void doTestMocking(RateLimiter mock) throws Exception {
     for (Method method : RateLimiter.class.getMethods()) {
       if (!isStatic(method.getModifiers())
           && !NOT_WORKING_ON_MOCKS.contains(method.getName())
           && !method.getDeclaringClass().equals(Object.class)) {
-        method.invoke(mockito, arbitraryParameters(method));
-        method.invoke(easyMock, arbitraryParameters(method));
+        method.invoke(mock, arbitraryParameters(method));
       }
     }
   }
@@ -497,7 +596,7 @@ public class RateLimiterTest extends TestCase {
   }
 
   private static final ImmutableSet<String> NOT_WORKING_ON_MOCKS =
-      ImmutableSet.of("latestPermitAgeSec", "setRate");
+      ImmutableSet.of("latestPermitAgeSec", "setRate", "getAvailablePermits");
 
   // We would use ArbitraryInstances, but it returns 0, invalid for many RateLimiter methods.
   private static final ImmutableClassToInstanceMap<Object> PARAMETER_VALUES =
diff --git a/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java b/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
index f055fe4..97fe727 100644
--- a/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
@@ -54,6 +54,11 @@ public class SerializingExecutorTest extends TestCase {
       tasks.remove().run();
     }
 
+    void runAll() {
+      while (hasNext()) {
+        runNext();
+      }
+    }
   }
   private FakeExecutor fakePool;
   private SerializingExecutor e;
@@ -78,28 +83,80 @@ public class SerializingExecutorTest extends TestCase {
       @Override
       public void run() {
         totalCalls.incrementAndGet();
+        // Make sure that no other tasks are scheduled to run while this is running.
+        assertFalse(fakePool.hasNext());
       }
     };
 
     assertFalse(fakePool.hasNext());
     e.execute(intCounter);
+    // A task should have been scheduled
     assertTrue(fakePool.hasNext());
     e.execute(intCounter);
+    // Our executor hasn't run any tasks yet.
     assertEquals(0, totalCalls.get());
-    fakePool.runNext(); // run just 1 sub task...
+    fakePool.runAll();
     assertEquals(2, totalCalls.get());
+    // Queue is empty so no runner should be scheduled.
     assertFalse(fakePool.hasNext());
 
     // Check that execute can be safely repeated
     e.execute(intCounter);
     e.execute(intCounter);
     e.execute(intCounter);
+    // No change yet.
     assertEquals(2, totalCalls.get());
-    fakePool.runNext();
+    fakePool.runAll();
     assertEquals(5, totalCalls.get());
     assertFalse(fakePool.hasNext());
   }
 
+  public void testSuspend() {
+    final AtomicInteger totalCalls = new AtomicInteger();
+    Runnable suspender = new Runnable() {
+      @Override
+      public void run() {
+        totalCalls.incrementAndGet();
+        // Suspend the queue so no other calls run.
+        e.suspend();
+      }
+    };
+
+    assertFalse(fakePool.hasNext());
+    e.execute(suspender);
+    // A task should have been scheduled
+    assertTrue(fakePool.hasNext());
+    e.execute(suspender);
+    fakePool.runAll();
+    // Only the first call that was already scheduled before suspension should have run.
+    assertEquals(1, totalCalls.get());
+    // Queue is suspended so no runner should be scheduled.
+    assertFalse(fakePool.hasNext());
+
+    e.execute(suspender);
+    // Queue is suspended so no runner should be scheduled.
+    assertFalse(fakePool.hasNext());
+    e.resume();
+    // A task should have been scheduled
+    assertTrue(fakePool.hasNext());
+    fakePool.runAll();
+    // Another call should have been run, but that suspended the queue again.
+    assertEquals(2, totalCalls.get());
+    assertFalse(fakePool.hasNext());
+
+    // Suspend the queue from here as well, making the count two.
+    e.suspend();
+    e.resume();
+    // Queue is still suspended, with count one, so no runner should be scheduled.
+    assertFalse(fakePool.hasNext());
+    e.resume();
+    // A task should have been scheduled
+    assertTrue(fakePool.hasNext());
+    fakePool.runAll();
+    // Another call should have been run, but that suspended the queue again.
+    assertEquals(3, totalCalls.get());
+  }
+
   public void testOrdering() {
     final List<Integer> callOrder = Lists.newArrayList();
 
@@ -119,12 +176,36 @@ public class SerializingExecutorTest extends TestCase {
     e.execute(new FakeOp(0));
     e.execute(new FakeOp(1));
     e.execute(new FakeOp(2));
-    fakePool.runNext();
+    fakePool.runAll();
+
+    assertEquals(ImmutableList.of(0, 1, 2), callOrder);
+  }
+
+  public void testPrependContinuation() {
+    final List<Integer> callOrder = Lists.newArrayList();
+
+    class FakeOp implements Runnable {
+      final int op;
+
+      FakeOp(int op) {
+        this.op = op;
+      }
+
+      @Override
+      public void run() {
+        callOrder.add(op);
+      }
+    }
+
+    e.execute(new FakeOp(1));
+    e.execute(new FakeOp(2));
+    e.executeFirst(new FakeOp(0));
+    fakePool.runAll();
 
     assertEquals(ImmutableList.of(0, 1, 2), callOrder);
   }
 
-  public void testExceptions() {
+  public void testRuntimeException_doesNotStopExecution() {
 
     final AtomicInteger numCalls = new AtomicInteger();
 
@@ -138,9 +219,30 @@ public class SerializingExecutorTest extends TestCase {
 
     e.execute(runMe);
     e.execute(runMe);
-    fakePool.runNext();
+    fakePool.runAll();
+
+    assertEquals(2, numCalls.get());
+  }
+
+  public void testInterrupt_doesNotStopExecution() {
+
+    final AtomicInteger numCalls = new AtomicInteger();
+
+    Runnable runMe = new Runnable() {
+      @Override
+      public void run() {
+        numCalls.incrementAndGet();
+      }
+    };
+
+    Thread.currentThread().interrupt();
+
+    e.execute(runMe);
+    e.execute(runMe);
+    fakePool.runAll();
 
     assertEquals(2, numCalls.get());
+    assertTrue(Thread.interrupted());
   }
 
   public void testDelegateRejection() {
diff --git a/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java b/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
index 302b7d1..9fecf0a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.testing.NullPointerTester;
 import com.google.common.testing.TestLogHandler;
+import com.google.common.util.concurrent.Service.State;
 import com.google.common.util.concurrent.ServiceManager.Listener;
 
 import junit.framework.TestCase;
@@ -91,20 +92,20 @@ public class ServiceManagerTest extends TestCase {
 
   private static class FailStartService extends NoOpService {
     @Override protected void doStart() {
-      notifyFailed(new IllegalStateException("failed"));
+      notifyFailed(new IllegalStateException("start failure"));
     }
   }
 
   private static class FailRunService extends NoOpService {
     @Override protected void doStart() {
       super.doStart();
-      notifyFailed(new IllegalStateException("failed"));
+      notifyFailed(new IllegalStateException("run failure"));
     }
   }
 
   private static class FailStopService extends NoOpService {
     @Override protected void doStop() {
-      notifyFailed(new IllegalStateException("failed"));
+      notifyFailed(new IllegalStateException("stop failure"));
     }
   }
 
@@ -115,8 +116,10 @@ public class ServiceManagerTest extends TestCase {
     serviceManager.startAsync().awaitHealthy();
     ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
     assertEquals(2, startupTimes.size());
-    assertThat(startupTimes.get(a)).isInclusivelyInRange(150, Long.MAX_VALUE);
-    assertThat(startupTimes.get(b)).isInclusivelyInRange(353, Long.MAX_VALUE);
+    // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
+    assertTrue(startupTimes.get(a) >= 150);
+    // TODO(kak): Use assertThat(startupTimes.get(b)).isAtLeast(353);
+    assertTrue(startupTimes.get(b) >= 353);
   }
 
   public void testServiceStartupTimes_selfStartingServices() {
@@ -141,7 +144,8 @@ public class ServiceManagerTest extends TestCase {
     serviceManager.startAsync().awaitHealthy();
     ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
     assertEquals(2, startupTimes.size());
-    assertThat(startupTimes.get(a)).isInclusivelyInRange(150, Long.MAX_VALUE);
+    // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
+    assertTrue(startupTimes.get(a) >= 150);
     // Service b startup takes at least 353 millis, but starting the timer is delayed by at least
     // 150 milliseconds. so in a perfect world the timing would be 353-150=203ms, but since either
     // of our sleep calls can be arbitrarily delayed we should just assert that there is a time
@@ -243,8 +247,8 @@ public class ServiceManagerTest extends TestCase {
     Service b = new FailStartService();
     ServiceManager manager = new ServiceManager(asList(a, b));
     String toString = manager.toString();
-    assertTrue(toString.contains("NoOpService"));
-    assertTrue(toString.contains("FailStartService"));
+    assertThat(toString).contains("NoOpService");
+    assertThat(toString).contains("FailStartService");
   }
 
   public void testTimeouts() throws Exception {
@@ -363,7 +367,7 @@ public class ServiceManagerTest extends TestCase {
       }
     };
     for (LogRecord record : logHandler.getStoredLogRecords()) {
-      assertFalse(logFormatter.format(record).contains("NoOpService"));
+      assertThat(logFormatter.format(record)).doesNotContain("NoOpService");
     }
   }
 
@@ -498,7 +502,7 @@ public class ServiceManagerTest extends TestCase {
       new ServiceManager(Arrays.asList(service1, service2));
       fail();
     } catch (IllegalArgumentException expected) {
-      assertTrue(expected.getMessage().contains("started transitioning asynchronously"));
+      assertThat(expected.getMessage()).contains("started transitioning asynchronously");
     }
   }
 
diff --git a/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
index e8ff37f..d24fa8a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
@@ -25,6 +25,8 @@ import static com.google.common.util.concurrent.Service.State.TERMINATED;
 
 import junit.framework.TestCase;
 
+import java.util.Locale;
+
 /**
  * Unit tests for {@link Service}
  */
@@ -49,7 +51,7 @@ public class ServiceTest extends TestCase {
   
   private static <T extends Comparable<? super T>> void assertLessThan(T a, T b) {
     if (a.compareTo(b) >= 0) {
-      fail(String.format("Expected %s to be less than %s", a, b));
+      fail(String.format(Locale.ROOT, "Expected %s to be less than %s", a, b));
     }
   }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
index 47f71c0..f3ea784 100644
--- a/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
@@ -18,6 +18,8 @@ package com.google.common.util.concurrent;
 
 import junit.framework.TestCase;
 
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -72,4 +74,153 @@ public class SettableFutureTest extends TestCase {
     assertTrue(future.cancel(true));
     tester.testCancelledFuture();
   }
+
+  /** Tests the initial state of the future. */
+  public void testCreate() throws Exception {
+    SettableFuture<Integer> future = SettableFuture.create();
+    assertFalse(future.isDone());
+    assertFalse(future.isCancelled());
+  }
+
+  public void testSetValue_simpleThreaded() throws Exception {
+    SettableFuture<Integer> future = SettableFuture.create();
+    assertTrue(future.set(42));
+    // Later attempts to set the future should return false.
+    assertFalse(future.set(23));
+    assertFalse(future.setException(new Exception("bar")));
+    assertFalse(future.setFuture(SettableFuture.<Integer>create()));
+    // Check that the future has been set properly.
+    assertTrue(future.isDone());
+    assertFalse(future.isCancelled());
+    assertEquals(42, (int) future.get());
+  }
+
+  public void testSetException() throws Exception {
+    SettableFuture<Object> future = SettableFuture.create();
+    Exception e = new Exception("foobarbaz");
+    assertTrue(future.setException(e));
+    // Later attempts to set the future should return false.
+    assertFalse(future.set(23));
+    assertFalse(future.setException(new Exception("quux")));
+    assertFalse(future.setFuture(SettableFuture.create()));
+    // Check that the future has been set properly.
+    assertTrue(future.isDone());
+    assertFalse(future.isCancelled());
+    try {
+      future.get();
+      fail("Expected ExecutionException");
+    } catch (ExecutionException ee) {
+      assertSame(e, ee.getCause());
+    }
+  }
+
+  public void testSetFuture() throws Exception {
+    SettableFuture<String> future = SettableFuture.create();
+    SettableFuture<String> nested = SettableFuture.create();
+    assertTrue(future.setFuture(nested));
+    // Later attempts to set the future should return false.
+    assertFalse(future.set("x"));
+    assertFalse(future.setException(new Exception("bar")));
+    assertFalse(future.setFuture(SettableFuture.<String>create()));
+    // Check that the future has been set properly.
+    assertFalse(future.isDone());
+    assertFalse(future.isCancelled());
+    try {
+      future.get(0, TimeUnit.MILLISECONDS);
+      fail("Expected TimeoutException");
+    } catch (TimeoutException expected) { /* expected */ }
+    nested.set("foo");
+    assertTrue(future.isDone());
+    assertFalse(future.isCancelled());
+    assertEquals("foo", future.get());
+  }
+
+  private static class Foo {}
+  private static class FooChild extends Foo {}
+
+  public void testSetFuture_genericsHierarchy() throws Exception {
+    SettableFuture<Foo> future = SettableFuture.create();
+    SettableFuture<FooChild> nested = SettableFuture.create();
+    assertTrue(future.setFuture(nested));
+    // Later attempts to set the future should return false.
+    assertFalse(future.set(new Foo()));
+    assertFalse(future.setException(new Exception("bar")));
+    assertFalse(future.setFuture(SettableFuture.<Foo>create()));
+    // Check that the future has been set properly.
+    assertFalse(future.isDone());
+    assertFalse(future.isCancelled());
+    try {
+      future.get(0, TimeUnit.MILLISECONDS);
+      fail("Expected TimeoutException");
+    } catch (TimeoutException expected) { /* expected */ }
+    FooChild value = new FooChild();
+    nested.set(value);
+    assertTrue(future.isDone());
+    assertFalse(future.isCancelled());
+    assertSame(value, future.get());
+  }
+
+  public void testCancel_innerCancelsAsync() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    SettableFuture<Object> inner = SettableFuture.create();
+    async.setFuture(inner);
+    inner.cancel(true);
+    assertTrue(async.isCancelled());
+    try {
+      async.get();
+      fail("Expected CancellationException");
+    } catch (CancellationException expected) { /* expected */ }
+  }
+
+  public void testCancel_resultCancelsInner_interrupted() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    SettableFuture<Object> inner = SettableFuture.create();
+    async.setFuture(inner);
+    async.cancel(true);
+    assertTrue(inner.isCancelled());
+    assertTrue(inner.wasInterrupted());
+    try {
+      inner.get();
+      fail("Expected CancellationException");
+    } catch (CancellationException expected) { /* expected */ }
+  }
+
+  public void testCancel_resultCancelsInner() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    SettableFuture<Object> inner = SettableFuture.create();
+    async.setFuture(inner);
+    async.cancel(false);
+    assertTrue(inner.isCancelled());
+    assertFalse(inner.wasInterrupted());
+    try {
+      inner.get();
+      fail("Expected CancellationException");
+    } catch (CancellationException expected) { /* expected */ }
+  }
+
+  public void testCancel_beforeSet() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    async.cancel(true);
+    assertFalse(async.set(42));
+  }
+
+  public void testCancel_multipleBeforeSetFuture_noInterruptFirst() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    async.cancel(false);
+    async.cancel(true);
+    SettableFuture<Object> inner = SettableFuture.create();
+    assertFalse(async.setFuture(inner));
+    assertTrue(inner.isCancelled());
+    assertFalse(inner.wasInterrupted());
+  }
+
+  public void testCancel_multipleBeforeSetFuture_interruptFirst() throws Exception {
+    SettableFuture<Object> async = SettableFuture.create();
+    async.cancel(true);
+    async.cancel(false);
+    SettableFuture<Object> inner = SettableFuture.create();
+    assertFalse(async.setFuture(inner));
+    assertTrue(inner.isCancelled());
+    assertTrue(inner.wasInterrupted());
+  }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java b/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java
new file mode 100644
index 0000000..252e219
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.util.concurrent.GeneratedMonitorTest.startThread;
+import static com.google.common.util.concurrent.Uninterruptibles.joinUninterruptibly;
+
+import com.google.common.util.concurrent.GeneratedMonitorTest.FlagGuard;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Supplemental tests for {@link Monitor}.
+ *
+ * <p>This test class contains various test cases that don't fit into the test case generation in
+ * {@link GeneratedMonitorTest}.
+ *
+ * @author Justin T. Sampson
+ */
+
+public class SupplementalMonitorTest extends TestCase {
+
+  public void testLeaveWithoutEnterThrowsIMSE() {
+    Monitor monitor = new Monitor();
+    try {
+      monitor.leave();
+      fail("expected IllegalMonitorStateException");
+    } catch (IllegalMonitorStateException e) {
+      // expected
+    }
+  }
+
+  public void testGetWaitQueueLengthWithWrongMonitorThrowsIMSE() {
+    Monitor monitor1 = new Monitor();
+    Monitor monitor2 = new Monitor();
+    FlagGuard guard = new FlagGuard(monitor2);
+    try {
+      monitor1.getWaitQueueLength(guard);
+      fail("expected IllegalMonitorStateException");
+    } catch (IllegalMonitorStateException e) {
+      // expected
+    }
+  }
+
+  public void testHasWaitersWithWrongMonitorThrowsIMSE() {
+    Monitor monitor1 = new Monitor();
+    Monitor monitor2 = new Monitor();
+    FlagGuard guard = new FlagGuard(monitor2);
+    try {
+      monitor1.hasWaiters(guard);
+      fail("expected IllegalMonitorStateException");
+    } catch (IllegalMonitorStateException e) {
+      // expected
+    }
+  }
+
+  public void testNullMonitorInGuardConstructorThrowsNPE() {
+    try {
+      new FlagGuard(null);
+      fail("expected NullPointerException");
+    } catch (NullPointerException e) {
+      // expected
+    }
+  }
+
+  public void testIsFair() {
+    assertTrue(new Monitor(true).isFair());
+    assertFalse(new Monitor(false).isFair());
+  }
+
+  public void testOccupiedMethods() {
+    Monitor monitor = new Monitor();
+    verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0);
+    verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0);
+    monitor.enter();
+    try {
+      verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1);
+      verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+      monitor.enter();
+      try {
+        verifyOccupiedMethodsInCurrentThread(monitor, true, true, 2);
+        verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+      } finally {
+        monitor.leave();
+      }
+      verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1);
+      verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+    } finally {
+      monitor.leave();
+    }
+    verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0);
+    verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0);
+  }
+
+  private static void verifyOccupiedMethodsInCurrentThread(Monitor monitor,
+      boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread,
+      int expectedOccupiedDepth) {
+    assertEquals(expectedIsOccupied, monitor.isOccupied());
+    assertEquals(expectedIsOccupiedByCurrentThread, monitor.isOccupiedByCurrentThread());
+    assertEquals(expectedOccupiedDepth, monitor.getOccupiedDepth());
+  }
+
+  private static void verifyOccupiedMethodsInAnotherThread(final Monitor monitor,
+      boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread,
+      int expectedOccupiedDepth) {
+    final AtomicBoolean actualIsOccupied = new AtomicBoolean();
+    final AtomicBoolean actualIsOccupiedByCurrentThread = new AtomicBoolean();
+    final AtomicInteger actualOccupiedDepth = new AtomicInteger();
+    final AtomicReference<Throwable> thrown = new AtomicReference<Throwable>();
+    joinUninterruptibly(startThread(new Runnable() {
+      @Override public void run() {
+        try {
+          actualIsOccupied.set(monitor.isOccupied());
+          actualIsOccupiedByCurrentThread.set(monitor.isOccupiedByCurrentThread());
+          actualOccupiedDepth.set(monitor.getOccupiedDepth());
+        } catch (Throwable t) {
+          thrown.set(t);
+        }
+      }
+    }));
+    assertNull(thrown.get());
+    assertEquals(expectedIsOccupied, actualIsOccupied.get());
+    assertEquals(expectedIsOccupiedByCurrentThread, actualIsOccupiedByCurrentThread.get());
+    assertEquals(expectedOccupiedDepth, actualOccupiedDepth.get());
+  }
+
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java
new file mode 100644
index 0000000..69dcaf7
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java b/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java
new file mode 100644
index 0000000..0db25b6
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.FuturesTest.failureWithCause;
+import static com.google.common.util.concurrent.FuturesTest.pseudoTimedGetUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.fail;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Methods factored out so that they can be emulated differently in GWT.
+ */
+ at GwtCompatible(emulated = true)
+final class TestPlatform {
+  static void verifyGetOnPendingFuture(Future<?> future) {
+    checkNotNull(future);
+    try {
+      pseudoTimedGetUninterruptibly(future, 10, MILLISECONDS);
+      fail();
+    } catch (TimeoutException expected) {
+    } catch (ExecutionException e) {
+      throw failureWithCause(e, "");
+    }
+  }
+
+  static void verifyTimedGetOnPendingFuture(Future<?> future) {
+    try {
+      getUninterruptibly(future, 0, SECONDS);
+      fail();
+    } catch (TimeoutException expected) {
+    } catch (ExecutionException e) {
+      throw failureWithCause(e, "");
+    }
+  }
+
+  static void verifyThreadWasNotInterrupted() {
+    assertFalse(Thread.currentThread().isInterrupted());
+  }
+
+  static void clearInterrupt() {
+    Thread.interrupted();
+  }
+
+  private TestPlatform() {}
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java b/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
index 3582415..18cb51c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
@@ -23,6 +23,7 @@ import com.google.common.testing.NullPointerTester;
 import junit.framework.TestCase;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 
@@ -90,14 +91,14 @@ public class ThreadFactoryBuilderTest extends TestCase {
   }
 
   private static void checkThreadPoolName(Thread thread, int threadId) {
-    assertTrue(thread.getName().matches("^pool-\\d+-thread-" + threadId + "$"));
+    assertThat(thread.getName()).matches("^pool-\\d+-thread-" + threadId + "$");
   }
 
   public void testNameFormatWithPercentS_custom() {
     String format = "super-duper-thread-%s";
     ThreadFactory factory = builder.setNameFormat(format).build();
     for (int i = 0; i < 11; i++) {
-      assertEquals(String.format(format, i),
+      assertEquals(rootLocaleFormat(format, i),
           factory.newThread(monitoredRunnable).getName());
     }
   }
@@ -106,7 +107,7 @@ public class ThreadFactoryBuilderTest extends TestCase {
     String format = "super-duper-thread-%d";
     ThreadFactory factory = builder.setNameFormat(format).build();
     for (int i = 0; i < 11; i++) {
-      assertEquals(String.format(format, i),
+      assertEquals(rootLocaleFormat(format, i),
           factory.newThread(monitoredRunnable).getName());
     }
   }
@@ -212,4 +213,8 @@ public class ThreadFactoryBuilderTest extends TestCase {
     npTester.testAllPublicStaticMethods(ThreadFactoryBuilder.class);
     npTester.testAllPublicInstanceMethods(builder);
   }
+
+  private static String rootLocaleFormat(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
similarity index 54%
copy from guava/src/com/google/common/collect/FilteredSetMultimap.java
copy to guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
index 6b73281..105a7cf 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,21 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
 
 /**
- * A supertype for filtered {@link SetMultimap} implementations.
- * 
- * @author Louis Wasserman
+ * Tests for {@link AbstractFuture} that use a {@link TrustedFuture} for
+ * {@link AbstractFuture#setFuture} calls.
  */
 @GwtCompatible
-interface FilteredSetMultimap<K, V> extends FilteredMultimap<K, V>, SetMultimap<K, V> {
+public class TrustedInputFutureTest extends AbstractAbstractFutureTest {
   @Override
-  SetMultimap<K, V> unfiltered();
+  AbstractFuture<Integer> newDelegate() {
+    AbstractFuture<Integer> future = new TrustedFuture<Integer>() {};
+    assertTrue(future instanceof TrustedFuture); // sanity check
+    return future;
+  }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java b/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
new file mode 100644
index 0000000..6fdf059
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.util.concurrent.Callables.returning;
+import static com.google.common.util.concurrent.TestPlatform.verifyThreadWasNotInterrupted;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Test case for {@link TrustedListenableFutureTask}.
+ */
+ at GwtCompatible(emulated = true)
+public class TrustedListenableFutureTaskTest extends TestCase {
+
+  public void testSuccessful() throws Exception {
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+    assertFalse(task.isDone());
+    task.run();
+    assertTrue(task.isDone());
+    assertFalse(task.isCancelled());
+    assertEquals(2, task.get().intValue());
+  }
+
+  public void testCancelled() throws Exception {
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+    assertFalse(task.isDone());
+    task.cancel(false);
+    assertTrue(task.isDone());
+    assertTrue(task.isCancelled());
+    assertFalse(task.wasInterrupted());
+    try {
+      task.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
+    verifyThreadWasNotInterrupted();
+  }
+
+  public void testFailed() throws Exception {
+    final Exception e = new Exception();
+    TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+        new Callable<Integer>() {
+          @Override public Integer call() throws Exception {
+            throw e;
+          }
+        });
+    task.run();
+    assertTrue(task.isDone());
+    assertFalse(task.isCancelled());
+    try {
+      task.get();
+      fail();
+    } catch (ExecutionException executionException) {
+      assertEquals(e, executionException.getCause());
+    }
+  }
+
+  @GwtIncompatible("blocking wait")
+
+  public void testCancel_interrupted() throws Exception {
+    final AtomicBoolean interruptedExceptionThrown = new AtomicBoolean();
+    final CountDownLatch enterLatch = new CountDownLatch(1);
+    final CountDownLatch exitLatch = new CountDownLatch(1);
+    final TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+        new Callable<Integer>() {
+          @Override public Integer call() throws Exception {
+            enterLatch.countDown();
+            try {
+              new CountDownLatch(1).await();  // wait forever
+              throw new AssertionError();
+            } catch (InterruptedException e) {
+              interruptedExceptionThrown.set(true);
+              throw e;
+            } finally {
+            }
+          }
+        });
+    assertFalse(task.isDone());
+    Thread thread = new Thread(new Runnable() {
+      @Override public void run() {
+        try {
+          task.run();
+        } finally {
+          exitLatch.countDown();
+        }
+      }
+    });
+    thread.start();
+    enterLatch.await();
+    assertFalse(task.isDone());
+    task.cancel(true);
+    assertTrue(task.isDone());
+    assertTrue(task.isCancelled());
+    assertTrue(task.wasInterrupted());
+    try {
+      task.get();
+      fail();
+    } catch (CancellationException expected) {
+    }
+    exitLatch.await();
+    assertTrue(interruptedExceptionThrown.get());
+  }
+
+  @GwtIncompatible("blocking wait")
+
+  public void testRunIdempotency() throws Exception {
+    final int numThreads = 10;
+    final ExecutorService executor = Executors.newFixedThreadPool(numThreads);
+    for (int i = 0; i < 1000; i++) {
+      final AtomicInteger counter = new AtomicInteger();
+      final TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+          new Callable<Integer>() {
+            @Override public Integer call() {
+              return counter.incrementAndGet();
+            }
+          });
+      final CyclicBarrier barrier = new CyclicBarrier(numThreads + 1);
+      Runnable wrapper = new Runnable() {
+        @Override public void run() {
+          awaitUnchecked(barrier);
+          task.run();
+          awaitUnchecked(barrier);
+        }
+      };
+      for (int j = 0; j < 10; j++) {
+        executor.execute(wrapper);
+      }
+      barrier.await();  // release the threads!
+      barrier.await();  // wait for them all to complete
+      assertEquals(1, task.get().intValue());
+      assertEquals(1, counter.get());
+    }
+    executor.shutdown();
+  }
+
+  @GwtIncompatible("used only in GwtIncomaptible tests")
+  private int awaitUnchecked(CyclicBarrier barrier) {
+    try {
+      return barrier.await();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+}
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
similarity index 54%
copy from guava/src/com/google/common/collect/FilteredSetMultimap.java
copy to guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
index 6b73281..a5505b1 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,17 +14,21 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
 
 /**
- * A supertype for filtered {@link SetMultimap} implementations.
- * 
- * @author Louis Wasserman
+ * Tests for {@link AbstractFuture} that use a non-{@link TrustedFuture} for
+ * {@link AbstractFuture#setFuture} calls.
  */
 @GwtCompatible
-interface FilteredSetMultimap<K, V> extends FilteredMultimap<K, V>, SetMultimap<K, V> {
+public class UntrustedInputFutureTest extends AbstractAbstractFutureTest {
   @Override
-  SetMultimap<K, V> unfiltered();
+  AbstractFuture<Integer> newDelegate() {
+    AbstractFuture<Integer> future = new AbstractFuture<Integer>() {};
+    assertFalse(future instanceof TrustedFuture); // sanity check
+    return future;
+  }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
index 900bd5d..cb6d723 100644
--- a/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
 import static com.google.common.util.concurrent.Runnables.doNothing;
 
@@ -271,28 +272,28 @@ public class WrappingExecutorServiceTest extends TestCase {
     @Override
     public <T> Future<T> submit(Callable<T> task) {
       lastMethodCalled = "submit";
-      assertTrue(task instanceof WrappedCallable);
+      assertThat(task).isInstanceOf(WrappedCallable.class);
       return inline.submit(task);
     }
 
     @Override
     public Future<?> submit(Runnable task) {
       lastMethodCalled = "submit";
-      assertTrue(task instanceof WrappedRunnable);
+      assertThat(task).isInstanceOf(WrappedRunnable.class);
       return inline.submit(task);
     }
 
     @Override
     public <T> Future<T> submit(Runnable task, T result) {
       lastMethodCalled = "submit";
-      assertTrue(task instanceof WrappedRunnable);
+      assertThat(task).isInstanceOf(WrappedRunnable.class);
       return inline.submit(task, result);
     }
 
     @Override
     public void execute(Runnable command) {
       lastMethodCalled = "execute";
-      assertTrue(command instanceof WrappedRunnable);
+      assertThat(command).isInstanceOf(WrappedRunnable.class);
       inline.execute(command);
     }
 
diff --git a/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
index 9beadb4..24c35f0 100644
--- a/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import junit.framework.TestCase;
 
 import java.util.Collection;
@@ -122,26 +124,28 @@ public class WrappingScheduledExecutorServiceTest extends TestCase {
       assertEquals(unit, lastUnit);
     }
 
-    @Override public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
-      assertTrue(command instanceof WrappedRunnable);
+    @Override
+    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+      assertThat(command).isInstanceOf(WrappedRunnable.class);
       lastMethodCalled = "scheduleRunnable";
       lastDelay = delay;
       lastUnit = unit;
       return null;
     }
 
-    @Override public <V> ScheduledFuture<V> schedule(
-        Callable<V> callable, long delay, TimeUnit unit) {
-      assertTrue(callable instanceof WrappedCallable);
+    @Override
+    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+      assertThat(callable).isInstanceOf(WrappedCallable.class);
       lastMethodCalled = "scheduleCallable";
       lastDelay = delay;
       lastUnit = unit;
       return null;
     }
 
-    @Override public ScheduledFuture<?> scheduleAtFixedRate(
+    @Override
+    public ScheduledFuture<?> scheduleAtFixedRate(
         Runnable command, long initialDelay, long period, TimeUnit unit) {
-      assertTrue(command instanceof WrappedRunnable);
+      assertThat(command).isInstanceOf(WrappedRunnable.class);
       lastMethodCalled = "scheduleAtFixedRate";
       lastInitialDelay = initialDelay;
       lastDelay = period;
@@ -149,9 +153,10 @@ public class WrappingScheduledExecutorServiceTest extends TestCase {
       return null;
     }
 
-    @Override public ScheduledFuture<?> scheduleWithFixedDelay(
+    @Override
+    public ScheduledFuture<?> scheduleWithFixedDelay(
         Runnable command, long initialDelay, long delay, TimeUnit unit) {
-      assertTrue(command instanceof WrappedRunnable);
+      assertThat(command).isInstanceOf(WrappedRunnable.class);
       lastMethodCalled = "scheduleWithFixedDelay";
       lastInitialDelay = initialDelay;
       lastDelay = delay;
diff --git a/guava-tests/test/com/google/common/xml/XmlEscapersTest.java b/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
index 5052962..2f21e1c 100644
--- a/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
+++ b/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
@@ -55,7 +55,7 @@ public class XmlEscapersTest extends TestCase {
   }
 
   // Helper to assert common properties of xml escapers.
-  private void assertBasicXmlEscaper(CharEscaper xmlEscaper,
+  static void assertBasicXmlEscaper(CharEscaper xmlEscaper,
       boolean shouldEscapeQuotes, boolean shouldEscapeWhitespaceChars) {
     // Simple examples (smoke tests)
     assertEquals("xxx", xmlEscaper.escape("xxx"));
diff --git a/guava/pom.xml b/guava/pom.xml
index 4cf038a..eef6890 100644
--- a/guava/pom.xml
+++ b/guava/pom.xml
@@ -5,11 +5,11 @@
   <parent>
     <groupId>com.google.guava</groupId>
     <artifactId>guava-parent</artifactId>
-    <version>18.0</version>
+    <version>19.0</version>
   </parent>
   <artifactId>guava</artifactId>
-  <name>Guava: Google Core Libraries for Java</name>
   <packaging>bundle</packaging>
+  <name>Guava: Google Core Libraries for Java</name>
   <description>
     Guava is a suite of core and expanded libraries that include
     utility classes, google's collections, io classes, and much
@@ -24,15 +24,32 @@
       <artifactId>jsr305</artifactId>
       <optional>true</optional><!-- needed only for annotations -->
     </dependency>
+    <dependency>
+      <groupId>com.google.errorprone</groupId>
+      <artifactId>error_prone_annotations</artifactId>
+      <optional>true</optional><!-- needed only for annotations -->
+    </dependency>
+    <dependency>
+      <groupId>com.google.j2objc</groupId>
+      <artifactId>j2objc-annotations</artifactId>
+      <optional>true</optional><!-- needed only for annotations -->
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.mojo</groupId>
+      <artifactId>animal-sniffer-annotations</artifactId>
+      <version>${animal.sniffer.version}</version>
+      <optional>true</optional><!-- needed only for annotations -->
+    </dependency>
+    <!-- TODO(cpovirk): does this comment belong on the <dependency> in <profiles>? -->
     <!-- TODO(cpovirk): want this only for dependency plugin but seems not to work there? Maven runs without failure, but the resulting Javadoc is missing the hoped-for inherited text -->
   </dependencies>
   <build>
     <plugins>
       <plugin>
+        <extensions>true</extensions>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
         <version>2.3.7</version>
-        <extensions>true</extensions>
         <executions>
           <execution>
             <id>bundle-manifest</id>
@@ -69,7 +86,6 @@
             <goals><goal>unpack-dependencies</goal></goals>
             <configuration>
               <includeArtifactIds>srczip</includeArtifactIds>
-              <overWrite>true</overWrite>
               <outputDirectory>${project.build.directory}/jdk-sources</outputDirectory>
               <silent>false</silent>
             </configuration>
@@ -107,21 +123,6 @@
             <phase>site</phase>
             <goals><goal>javadoc</goal></goals>
           </execution>
-          <execution>
-            <id>generate-jdiff-site-report</id>
-            <phase>site</phase>
-            <goals><goal>javadoc</goal></goals>
-            <configuration>
-              <doclet>jdiff.JDiff</doclet>
-              <docletPath>${project.basedir}/lib/jdiff.jar</docletPath>
-              <additionalparam>
-                -XDignore.symbol.file -apiname 'Guava ${project.version}'
-              </additionalparam>
-              <useStandardDocletOptions>false</useStandardDocletOptions>
-              <reportOutputDirectory>${project.reporting.outputDirectory}</reportOutputDirectory>
-              <destDir>jdiff</destDir>
-            </configuration>
-          </execution>
         </executions>
       </plugin>
     </plugins>
@@ -145,5 +146,37 @@
         </dependency>
       </dependencies>
     </profile>
+    <profile>
+      <id>jdk8</id>
+      <activation>
+        <jdk>[1.8,)</jdk>
+      </activation>
+      <!-- Disable doclint under JDK 8 -->
+      <!-- This is defined in guava-parent as well, but we need it here too because the
+           <additionalparam> from the maven-javadoc-plugin configuration above seems to
+           override the one from the parent pom. -->
+      <reporting>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-XDignore.symbol.file -Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </reporting>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-XDignore.symbol.file -Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
 </project>
diff --git a/guava/src/com/google/common/base/Absent.java b/guava/src/com/google/common/base/Absent.java
index 8b298b2..a607621 100644
--- a/guava/src/com/google/common/base/Absent.java
+++ b/guava/src/com/google/common/base/Absent.java
@@ -39,50 +39,62 @@ final class Absent<T> extends Optional<T> {
 
   private Absent() {}
 
-  @Override public boolean isPresent() {
+  @Override
+  public boolean isPresent() {
     return false;
   }
 
-  @Override public T get() {
+  @Override
+  public T get() {
     throw new IllegalStateException("Optional.get() cannot be called on an absent value");
   }
 
-  @Override public T or(T defaultValue) {
+  @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) {
+  @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
+  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() {
+  @Override
+  @Nullable
+  public T orNull() {
     return null;
   }
 
-  @Override public Set<T> asSet() {
+  @Override
+  public Set<T> asSet() {
     return Collections.emptySet();
   }
 
-  @Override public <V> Optional<V> transform(Function<? super T, V> function) {
+  @Override
+  public <V> Optional<V> transform(Function<? super T, V> function) {
     checkNotNull(function);
     return Optional.absent();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this;
   }
 
-  @Override public int hashCode() {
-    return 0x598df91c;
+  @Override
+  public int hashCode() {
+    return 0x79a31aac;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Optional.absent()";
   }
 
diff --git a/guava/src/com/google/common/base/AbstractIterator.java b/guava/src/com/google/common/base/AbstractIterator.java
index d8b7257..7b29fea 100644
--- a/guava/src/com/google/common/base/AbstractIterator.java
+++ b/guava/src/com/google/common/base/AbstractIterator.java
@@ -34,7 +34,10 @@ abstract class AbstractIterator<T> implements Iterator<T> {
   protected AbstractIterator() {}
 
   private enum State {
-    READY, NOT_READY, DONE, FAILED,
+    READY,
+    NOT_READY,
+    DONE,
+    FAILED,
   }
 
   private T next;
@@ -50,10 +53,10 @@ abstract class AbstractIterator<T> implements Iterator<T> {
   public final boolean hasNext() {
     checkState(state != State.FAILED);
     switch (state) {
-      case DONE:
-        return false;
       case READY:
         return true;
+      case DONE:
+        return false;
       default:
     }
     return tryToComputeNext();
@@ -80,7 +83,8 @@ abstract class AbstractIterator<T> implements Iterator<T> {
     return result;
   }
 
-  @Override public final void remove() {
+  @Override
+  public final void remove() {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava/src/com/google/common/base/Ascii.java b/guava/src/com/google/common/base/Ascii.java
index 37f7ed6..9024290 100644
--- a/guava/src/com/google/common/base/Ascii.java
+++ b/guava/src/com/google/common/base/Ascii.java
@@ -41,6 +41,7 @@ import javax.annotation.CheckReturnValue;
  * @author Gregory Kick
  * @since 7.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Ascii {
 
@@ -580,7 +581,6 @@ public final class Ascii {
    * @since 16.0
    */
   @Beta
-  @CheckReturnValue
   public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
     checkNotNull(seq);
 
@@ -589,9 +589,11 @@ public final class Ascii {
 
     // 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,
+    checkArgument(
+        truncationLength >= 0,
         "maxLength (%s) must be >= length of the truncation indicator (%s)",
-        maxLength, truncationIndicator.length());
+        maxLength,
+        truncationIndicator.length());
 
     if (seq.length() <= maxLength) {
       String string = seq.toString();
diff --git a/guava/src/com/google/common/base/CaseFormat.java b/guava/src/com/google/common/base/CaseFormat.java
index 0b4cb5c..c074de2 100644
--- a/guava/src/com/google/common/base/CaseFormat.java
+++ b/guava/src/com/google/common/base/CaseFormat.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
 
 import java.io.Serializable;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -32,16 +33,20 @@ import javax.annotation.Nullable;
  * @author Mike Bostock
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public enum CaseFormat {
   /**
    * Hyphenated variable naming convention, e.g., "lower-hyphen".
    */
   LOWER_HYPHEN(CharMatcher.is('-'), "-") {
-    @Override String normalizeWord(String word) {
+    @Override
+    String normalizeWord(String word) {
       return Ascii.toLowerCase(word);
     }
-    @Override String convert(CaseFormat format, String s) {
+
+    @Override
+    String convert(CaseFormat format, String s) {
       if (format == LOWER_UNDERSCORE) {
         return s.replace('-', '_');
       }
@@ -56,10 +61,13 @@ public enum CaseFormat {
    * C++ variable naming convention, e.g., "lower_underscore".
    */
   LOWER_UNDERSCORE(CharMatcher.is('_'), "_") {
-    @Override String normalizeWord(String word) {
+    @Override
+    String normalizeWord(String word) {
       return Ascii.toLowerCase(word);
     }
-    @Override String convert(CaseFormat format, String s) {
+
+    @Override
+    String convert(CaseFormat format, String s) {
       if (format == LOWER_HYPHEN) {
         return s.replace('_', '-');
       }
@@ -74,7 +82,8 @@ public enum CaseFormat {
    * Java variable naming convention, e.g., "lowerCamel".
    */
   LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
-    @Override String normalizeWord(String word) {
+    @Override
+    String normalizeWord(String word) {
       return firstCharOnlyToUpper(word);
     }
   },
@@ -83,7 +92,8 @@ public enum CaseFormat {
    * Java and C++ class naming convention, e.g., "UpperCamel".
    */
   UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
-    @Override String normalizeWord(String word) {
+    @Override
+    String normalizeWord(String word) {
       return firstCharOnlyToUpper(word);
     }
   },
@@ -92,10 +102,13 @@ public enum CaseFormat {
    * Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
    */
   UPPER_UNDERSCORE(CharMatcher.is('_'), "_") {
-    @Override String normalizeWord(String word) {
+    @Override
+    String normalizeWord(String word) {
       return Ascii.toUpperCase(word);
     }
-    @Override String convert(CaseFormat format, String s) {
+
+    @Override
+    String convert(CaseFormat format, String s) {
       if (format == LOWER_HYPHEN) {
         return Ascii.toLowerCase(s.replace('_', '-'));
       }
@@ -145,8 +158,8 @@ public enum CaseFormat {
       i = j + wordSeparator.length();
     }
     return (i == 0)
-      ? format.normalizeFirstWord(s)
-      : out.append(format.normalizeWord(s.substring(i))).toString();
+        ? format.normalizeFirstWord(s)
+        : out.append(format.normalizeWord(s.substring(i))).toString();
   }
 
   /**
@@ -159,8 +172,8 @@ public enum CaseFormat {
     return new StringConverter(this, targetFormat);
   }
 
-  private static final class StringConverter
-      extends Converter<String, String> implements Serializable {
+  private static final class StringConverter extends Converter<String, String>
+      implements Serializable {
 
     private final CaseFormat sourceFormat;
     private final CaseFormat targetFormat;
@@ -170,30 +183,32 @@ public enum CaseFormat {
       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 doForward(String s) {
+      return 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
+    protected String doBackward(String s) {
+      return targetFormat.to(sourceFormat, s);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @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 sourceFormat.equals(that.sourceFormat) && targetFormat.equals(that.targetFormat);
       }
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return sourceFormat.hashCode() ^ targetFormat.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return sourceFormat + ".converterTo(" + targetFormat + ")";
     }
 
diff --git a/guava/src/com/google/common/base/CharMatcher.java b/guava/src/com/google/common/base/CharMatcher.java
index 8a73530..7e732dd 100644
--- a/guava/src/com/google/common/base/CharMatcher.java
+++ b/guava/src/com/google/common/base/CharMatcher.java
@@ -18,10 +18,12 @@ package com.google.common.base;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndex;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.common.annotations.VisibleForTesting;
 
 import java.util.Arrays;
 import java.util.BitSet;
@@ -42,11 +44,11 @@ import javax.annotation.CheckReturnValue;
  * treats these just as two separate characters.
  *
  * <p>Example usages: <pre>
- *   String trimmed = {@link #WHITESPACE WHITESPACE}.{@link #trimFrom trimFrom}(userInput);
- *   if ({@link #ASCII ASCII}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
+ *   String trimmed = {@link #whitespace() whitespace()}.{@link #trimFrom trimFrom}(userInput);
+ *   if ({@link #ascii() ascii()}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher">
+ * "https://github.com/google/guava/wiki/StringsExplained#charmatcher">
  * {@code CharMatcher}</a>.
  *
  * @author Kevin Bourrillion
@@ -56,184 +58,144 @@ import javax.annotation.CheckReturnValue;
 @GwtCompatible(emulated = true)
 public abstract class CharMatcher implements Predicate<Character> {
 
-  // Constants
+  // Constant matcher factory methods
+
   /**
-   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
-   * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
-   * discussion of that term.
+   * Matches any character.
    *
-   * @since 2.0
+   * @since 19.0 (since 1.0 as constant {@code ANY})
    */
-  public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() {
-    @Override
-    public boolean matches(char c) {
-      switch (c) {
-        case '\t':
-        case '\n':
-        case '\013':
-        case '\f':
-        case '\r':
-        case ' ':
-        case '\u0085':
-        case '\u1680':
-        case '\u2028':
-        case '\u2029':
-        case '\u205f':
-        case '\u3000':
-          return true;
-        case '\u2007':
-          return false;
-        default:
-          return c >= '\u2000' && c <= '\u200a';
-      }
-    }
-
-    @Override
-    public String toString() {
-      return "CharMatcher.BREAKING_WHITESPACE";
-    }
-  };
+  public static CharMatcher any() {
+    return Any.INSTANCE;
+  }
 
   /**
-   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   * Matches no characters.
+   *
+   * @since 19.0 (since 1.0 as constant {@code NONE})
    */
-  public static final CharMatcher ASCII = inRange('\0', '\u007f', "CharMatcher.ASCII");
-
-  private static class RangesMatcher extends CharMatcher {
-    private final char[] rangeStarts;
-    private final char[] rangeEnds;
-
-    RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
-      super(description);
-      this.rangeStarts = rangeStarts;
-      this.rangeEnds = rangeEnds;
-      checkArgument(rangeStarts.length == rangeEnds.length);
-      for (int i = 0; i < rangeStarts.length; i++) {
-        checkArgument(rangeStarts[i] <= rangeEnds[i]);
-        if (i + 1 < rangeStarts.length) {
-          checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
-        }
-      }
-    }
+  public static CharMatcher none() {
+    return None.INSTANCE;
+  }
 
-    @Override
-    public boolean matches(char c) {
-      int index = Arrays.binarySearch(rangeStarts, c);
-      if (index >= 0) {
-        return true;
-      } else {
-        index = ~index - 1;
-        return index >= 0 && c <= rangeEnds[index];
-      }
-    }
+  /**
+   * Determines whether a character is whitespace according to the latest Unicode standard, as
+   * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+   * This is not the same definition used by other Java APIs. (See a <a
+   * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+   * definitions of "whitespace"</a>.)
+   *
+   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this matcher to keep it up
+   * to date.
+   *
+   * @since 19.0 (since 1.0 as constant {@code WHITESPACE})
+   */
+  public static CharMatcher whitespace() {
+    return Whitespace.INSTANCE;
   }
 
-  // Must be in ascending order.
-  private static final String ZEROES = "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6"
-      + "\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1b50\u1bb0"
-      + "\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+  /**
+   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+   * interpreted as a break between words for formatting purposes). See {@link #whitespace()} for a
+   * discussion of that term.
+   *
+   * @since 19.0 (since 2.0 as constant {@code BREAKING_WHITESPACE})
+   */
+  public static CharMatcher breakingWhitespace() {
+    return BreakingWhitespace.INSTANCE;
+  }
 
-  private static final String NINES;
-  static {
-    StringBuilder builder = new StringBuilder(ZEROES.length());
-    for (int i = 0; i < ZEROES.length(); i++) {
-      builder.append((char) (ZEROES.charAt(i) + 9));
-    }
-    NINES = builder.toString();
+  /**
+   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   *
+   * @since 19.0 (since 1.0 as constant {@code ASCII})
+   */
+  public static CharMatcher ascii() {
+    return Ascii.INSTANCE;
   }
 
   /**
    * Determines whether a character is a digit according to
    * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
    * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code DIGIT})
    */
-  public static final CharMatcher DIGIT = new RangesMatcher(
-      "CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray());
+  public static CharMatcher digit() {
+    return Digit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
-   * Java's definition}. If you only care to match ASCII digits, you can use {@code
-   * inRange('0', '9')}.
+   * Java's definition}. If you only care to match ASCII digits, you can use {@code inRange('0',
+   * '9')}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_DIGIT})
    */
-  public static final CharMatcher JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") {
-    @Override public boolean matches(char c) {
-      return Character.isDigit(c);
-    }
-  };
+  public static CharMatcher javaDigit() {
+    return JavaDigit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
    * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
    * inRange('a', 'z').or(inRange('A', 'Z'))}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER})
    */
-  public static final CharMatcher JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") {
-    @Override public boolean matches(char c) {
-      return Character.isLetter(c);
-    }
-  };
+  public static CharMatcher javaLetter() {
+    return JavaLetter.INSTANCE;
+  }
 
   /**
    * Determines whether a character is a letter or digit according to {@linkplain
    * Character#isLetterOrDigit(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER_OR_DIGIT}).
    */
-  public static final CharMatcher JAVA_LETTER_OR_DIGIT =
-      new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") {
-    @Override public boolean matches(char c) {
-      return Character.isLetterOrDigit(c);
-    }
-  };
+  public static CharMatcher javaLetterOrDigit() {
+    return JavaLetterOrDigit.INSTANCE;
+  }
 
   /**
    * Determines whether a character is upper case according to {@linkplain
    * Character#isUpperCase(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_UPPER_CASE})
    */
-  public static final CharMatcher JAVA_UPPER_CASE =
-      new CharMatcher("CharMatcher.JAVA_UPPER_CASE") {
-    @Override public boolean matches(char c) {
-      return Character.isUpperCase(c);
-    }
-  };
+  public static CharMatcher javaUpperCase() {
+    return JavaUpperCase.INSTANCE;
+  }
 
   /**
    * Determines whether a character is lower case according to {@linkplain
    * Character#isLowerCase(char) Java's definition}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_LOWER_CASE})
    */
-  public static final CharMatcher JAVA_LOWER_CASE =
-      new CharMatcher("CharMatcher.JAVA_LOWER_CASE") {
-    @Override public boolean matches(char c) {
-      return Character.isLowerCase(c);
-    }
-  };
+  public static CharMatcher javaLowerCase() {
+    return JavaLowerCase.INSTANCE;
+  }
 
   /**
    * Determines whether a character is an ISO control character as specified by {@link
    * Character#isISOControl(char)}.
+   *
+   * @since 19.0 (since 1.0 as constant {@code JAVA_ISO_CONTROL})
    */
-  public static final CharMatcher JAVA_ISO_CONTROL =
-      inRange('\u0000', '\u001f')
-      .or(inRange('\u007f', '\u009f'))
-      .withToString("CharMatcher.JAVA_ISO_CONTROL");
+  public static CharMatcher javaIsoControl() {
+    return JavaIsoControl.INSTANCE;
+  }
 
   /**
    * Determines whether a character is invisible; that is, if its Unicode category is any of
    * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
    * PRIVATE_USE according to ICU4J.
+   *
+   * @since 19.0 (since 1.0 as constant {@code INVISIBLE})
    */
-  public static final CharMatcher INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", (
-      "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067\u2068"
-      + "\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa").toCharArray(), (
-      "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067\u2068"
-      + "\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb").toCharArray());
-
-  private static String showCharacter(char c) {
-    String hex = "0123456789ABCDEF";
-    char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
-    for (int i = 0; i < 4; i++) {
-      tmp[5 - i] = hex.charAt(c & 0xF);
-      c >>= 4;
-    }
-    return String.copyValueOf(tmp);
-
+  public static CharMatcher invisible() {
+    return Invisible.INSTANCE;
   }
 
   /**
@@ -241,170 +203,111 @@ public abstract class CharMatcher implements Predicate<Character> {
    * errs on the side of returning {@code false} (that is, it tends to assume a character is
    * double-width).
    *
-   * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+   * <p><b>Note:</b> as the reference file evolves, we will modify this matcher to keep it up to
    * date.
+   *
+   * @since 19.0 (since 1.0 as constant {@code SINGLE_WIDTH})
    */
-  public static final CharMatcher SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH",
-      "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
-      "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
-
-  /** Matches any character. */
-  public static final CharMatcher ANY =
-      new FastMatcher("CharMatcher.ANY") {
-        @Override public boolean matches(char c) {
-          return true;
-        }
+  public static CharMatcher singleWidth() {
+    return SingleWidth.INSTANCE;
+  }
 
-        @Override public int indexIn(CharSequence sequence) {
-          return (sequence.length() == 0) ? -1 : 0;
-        }
+  // Legacy constants
+  // TODO(cgdecker): Deprecate these so they can be removed eventually
 
-        @Override public int indexIn(CharSequence sequence, int start) {
-          int length = sequence.length();
-          Preconditions.checkPositionIndex(start, length);
-          return (start == length) ? -1 : start;
-        }
+  /**
+   * Determines whether a character is whitespace according to the latest Unicode standard, as
+   * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+   * This is not the same definition used by other Java APIs. (See a <a
+   * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+   * definitions of "whitespace"</a>.)
+   *
+   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
+   * to date.
+   */
+  public static final CharMatcher WHITESPACE = whitespace();
 
-        @Override public int lastIndexIn(CharSequence sequence) {
-          return sequence.length() - 1;
-        }
+  /**
+   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+   * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
+   * discussion of that term.
+   *
+   * @since 2.0
+   */
+  public static final CharMatcher BREAKING_WHITESPACE = breakingWhitespace();
 
-        @Override public boolean matchesAllOf(CharSequence sequence) {
-          checkNotNull(sequence);
-          return true;
-        }
+  /**
+   * Determines whether a character is ASCII, meaning that its code point is less than 128.
+   */
+  public static final CharMatcher ASCII = ascii();
 
-        @Override public boolean matchesNoneOf(CharSequence sequence) {
-          return sequence.length() == 0;
-        }
+  /**
+   * Determines whether a character is a digit according to
+   * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
+   * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+   */
+  public static final CharMatcher DIGIT = digit();
 
-        @Override public String removeFrom(CharSequence sequence) {
-          checkNotNull(sequence);
-          return "";
-        }
+  /**
+   * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
+   * Java's definition}. If you only care to match ASCII digits, you can use {@code
+   * inRange('0', '9')}.
+   */
+  public static final CharMatcher JAVA_DIGIT = javaDigit();
 
-        @Override public String replaceFrom(CharSequence sequence, char replacement) {
-          char[] array = new char[sequence.length()];
-          Arrays.fill(array, replacement);
-          return new String(array);
-        }
+  /**
+   * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
+   * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
+   * inRange('a', 'z').or(inRange('A', 'Z'))}.
+   */
+  public static final CharMatcher JAVA_LETTER = javaLetter();
 
-        @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
-          StringBuilder retval = new StringBuilder(sequence.length() * replacement.length());
-          for (int i = 0; i < sequence.length(); i++) {
-            retval.append(replacement);
-          }
-          return retval.toString();
-        }
+  /**
+   * Determines whether a character is a letter or digit according to {@linkplain
+   * Character#isLetterOrDigit(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_LETTER_OR_DIGIT = javaLetterOrDigit();
 
-        @Override public String collapseFrom(CharSequence sequence, char replacement) {
-          return (sequence.length() == 0) ? "" : String.valueOf(replacement);
-        }
+  /**
+   * Determines whether a character is upper case according to {@linkplain
+   * Character#isUpperCase(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_UPPER_CASE = javaUpperCase();
 
-        @Override public String trimFrom(CharSequence sequence) {
-          checkNotNull(sequence);
-          return "";
-        }
+  /**
+   * Determines whether a character is lower case according to {@linkplain
+   * Character#isLowerCase(char) Java's definition}.
+   */
+  public static final CharMatcher JAVA_LOWER_CASE = javaLowerCase();
 
-        @Override public int countIn(CharSequence sequence) {
-          return sequence.length();
-        }
+  /**
+   * Determines whether a character is an ISO control character as specified by {@link
+   * Character#isISOControl(char)}.
+   */
+  public static final CharMatcher JAVA_ISO_CONTROL = javaIsoControl();
 
-        @Override public CharMatcher and(CharMatcher other) {
-          return checkNotNull(other);
-        }
+  /**
+   * Determines whether a character is invisible; that is, if its Unicode category is any of
+   * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
+   * PRIVATE_USE according to ICU4J.
+   */
+  public static final CharMatcher INVISIBLE = invisible();
 
-        @Override public CharMatcher or(CharMatcher other) {
-          checkNotNull(other);
-          return this;
-        }
+  /**
+   * Determines whether a character is single-width (not double-width). When in doubt, this matcher
+   * errs on the side of returning {@code false} (that is, it tends to assume a character is
+   * double-width).
+   *
+   * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+   * date.
+   */
+  public static final CharMatcher SINGLE_WIDTH = singleWidth();
 
-        @Override public CharMatcher negate() {
-          return NONE;
-        }
-      };
+  /** Matches any character. */
+  public static final CharMatcher ANY = any();
 
   /** Matches no characters. */
-  public static final CharMatcher NONE =
-      new FastMatcher("CharMatcher.NONE") {
-        @Override public boolean matches(char c) {
-          return false;
-        }
-
-        @Override public int indexIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return -1;
-        }
-
-        @Override public int indexIn(CharSequence sequence, int start) {
-          int length = sequence.length();
-          Preconditions.checkPositionIndex(start, length);
-          return -1;
-        }
-
-        @Override public int lastIndexIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return -1;
-        }
-
-        @Override public boolean matchesAllOf(CharSequence sequence) {
-          return sequence.length() == 0;
-        }
-
-        @Override public boolean matchesNoneOf(CharSequence sequence) {
-          checkNotNull(sequence);
-          return true;
-        }
-
-        @Override public String removeFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override public String replaceFrom(CharSequence sequence, char replacement) {
-          return sequence.toString();
-        }
-
-        @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
-          checkNotNull(replacement);
-          return sequence.toString();
-        }
-
-        @Override public String collapseFrom(CharSequence sequence, char replacement) {
-          return sequence.toString();
-        }
-
-        @Override public String trimFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override
-        public String trimLeadingFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override
-        public String trimTrailingFrom(CharSequence sequence) {
-          return sequence.toString();
-        }
-
-        @Override public int countIn(CharSequence sequence) {
-          checkNotNull(sequence);
-          return 0;
-        }
-
-        @Override public CharMatcher and(CharMatcher other) {
-          checkNotNull(other);
-          return this;
-        }
-
-        @Override public CharMatcher or(CharMatcher other) {
-          return checkNotNull(other);
-        }
-
-        @Override public CharMatcher negate() {
-          return ANY;
-        }
-      };
+  public static final CharMatcher NONE = none();
 
   // Static factories
 
@@ -412,34 +315,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * Returns a {@code char} matcher that matches only one specified character.
    */
   public static CharMatcher is(final char match) {
-    String description = "CharMatcher.is('" + showCharacter(match) + "')";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c == match;
-      }
-
-      @Override public String replaceFrom(CharSequence sequence, char replacement) {
-        return sequence.toString().replace(match, replacement);
-      }
-
-      @Override public CharMatcher and(CharMatcher other) {
-        return other.matches(match) ? this : NONE;
-      }
-
-      @Override public CharMatcher or(CharMatcher other) {
-        return other.matches(match) ? other : super.or(other);
-      }
-
-      @Override public CharMatcher negate() {
-        return isNot(match);
-      }
-
-      @GwtIncompatible("java.util.BitSet")
-      @Override
-      void setBits(BitSet table) {
-        table.set(match);
-      }
-    };
+    return new Is(match);
   }
 
   /**
@@ -448,32 +324,8 @@ public abstract class CharMatcher implements Predicate<Character> {
    * <p>To negate another {@code CharMatcher}, use {@link #negate()}.
    */
   public static CharMatcher isNot(final char match) {
-    String description = "CharMatcher.isNot('" + showCharacter(match) + "')";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c != match;
-      }
-
-      @Override public CharMatcher and(CharMatcher other) {
-        return other.matches(match) ? super.and(other) : other;
-      }
-
-      @Override public CharMatcher or(CharMatcher other) {
-        return other.matches(match) ? ANY : this;
-      }
-
-      @GwtIncompatible("java.util.BitSet")
-      @Override
-      void setBits(BitSet table) {
-        table.set(0, match);
-        table.set(match + 1, Character.MAX_VALUE + 1);
-      }
-
-      @Override public CharMatcher negate() {
-        return is(match);
-      }
-    };
-  }
+    return new IsNot(match);
+  }
 
   /**
    * Returns a {@code char} matcher that matches any character present in the given character
@@ -482,53 +334,16 @@ public abstract class CharMatcher implements Predicate<Character> {
   public static CharMatcher anyOf(final CharSequence sequence) {
     switch (sequence.length()) {
       case 0:
-        return NONE;
+        return none();
       case 1:
         return is(sequence.charAt(0));
       case 2:
         return isEither(sequence.charAt(0), sequence.charAt(1));
       default:
-        // continue below to handle the general case
-    }
-    // TODO(user): is it potentially worth just going ahead and building a precomputed matcher?
-    final char[] chars = sequence.toString().toCharArray();
-    Arrays.sort(chars);
-    StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
-    for (char c : chars) {
-      description.append(showCharacter(c));
-    }
-    description.append("\")");
-    return new CharMatcher(description.toString()) {
-      @Override public boolean matches(char c) {
-        return Arrays.binarySearch(chars, c) >= 0;
-      }
-
-      @Override
-      @GwtIncompatible("java.util.BitSet")
-      void setBits(BitSet table) {
-        for (char c : chars) {
-          table.set(c);
-        }
-      }
-    };
-  }
-
-  private static CharMatcher isEither(
-      final char match1,
-      final char match2) {
-    String description = "CharMatcher.anyOf(\"" +
-        showCharacter(match1) + showCharacter(match2) + "\")";
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return c == match1 || c == match2;
-      }
-
-      @GwtIncompatible("java.util.BitSet")
-      @Override void setBits(BitSet table) {
-        table.set(match1);
-        table.set(match2);
-      }
-    };
+        // TODO(lowasser): is it potentially worth just going ahead and building a precomputed
+        // matcher?
+        return new AnyOf(sequence);
+    }
   }
 
   /**
@@ -547,25 +362,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * @throws IllegalArgumentException if {@code endInclusive < startInclusive}
    */
   public static CharMatcher inRange(final char startInclusive, final char endInclusive) {
-    checkArgument(endInclusive >= startInclusive);
-    String description = "CharMatcher.inRange('" +
-        showCharacter(startInclusive) + "', '" +
-        showCharacter(endInclusive) + "')";
-    return inRange(startInclusive, endInclusive, description);
-  }
-
-  static CharMatcher inRange(final char startInclusive, final char endInclusive,
-      String description) {
-    return new FastMatcher(description) {
-      @Override public boolean matches(char c) {
-        return startInclusive <= c && c <= endInclusive;
-      }
-
-      @GwtIncompatible("java.util.BitSet")
-      @Override void setBits(BitSet table) {
-        table.set(startInclusive, endInclusive + 1);
-      }
-    };
+    return new InRange(startInclusive, endInclusive);
   }
 
   /**
@@ -573,41 +370,16 @@ public abstract class CharMatcher implements Predicate<Character> {
    * which operates on primitive {@code char} instances instead.
    */
   public static CharMatcher forPredicate(final Predicate<? super Character> predicate) {
-    checkNotNull(predicate);
-    if (predicate instanceof CharMatcher) {
-      return (CharMatcher) predicate;
-    }
-    String description = "CharMatcher.forPredicate(" + predicate + ")";
-    return new CharMatcher(description) {
-      @Override public boolean matches(char c) {
-        return predicate.apply(c);
-      }
-
-      @Override public boolean apply(Character character) {
-        return predicate.apply(checkNotNull(character));
-      }
-    };
+    return predicate instanceof CharMatcher ? (CharMatcher) predicate : new ForPredicate(predicate);
   }
 
-  // State
-  final String description;
-
   // Constructors
 
   /**
-   * Sets the {@code toString()} from the given description.
-   */
-  CharMatcher(String description) {
-    this.description = description;
-  }
-
-  /**
    * Constructor for use by subclasses. When subclassing, you may want to override
    * {@code toString()} to provide a useful description.
    */
-  protected CharMatcher() {
-    description = super.toString();
-  }
+  protected CharMatcher() {}
 
   // Abstract methods
 
@@ -620,136 +392,21 @@ public abstract class CharMatcher implements Predicate<Character> {
    * Returns a matcher that matches any character not matched by this matcher.
    */
   public CharMatcher negate() {
-    return new NegatedMatcher(this);
-  }
-
-  private static class NegatedMatcher extends CharMatcher {
-    final CharMatcher original;
-
-    NegatedMatcher(String toString, CharMatcher original) {
-      super(toString);
-      this.original = original;
-    }
-
-    NegatedMatcher(CharMatcher original) {
-      this(original + ".negate()", original);
-    }
-
-    @Override public boolean matches(char c) {
-      return !original.matches(c);
-    }
-
-    @Override public boolean matchesAllOf(CharSequence sequence) {
-      return original.matchesNoneOf(sequence);
-    }
-
-    @Override public boolean matchesNoneOf(CharSequence sequence) {
-      return original.matchesAllOf(sequence);
-    }
-
-    @Override public int countIn(CharSequence sequence) {
-      return sequence.length() - original.countIn(sequence);
-    }
-
-    @GwtIncompatible("java.util.BitSet")
-    @Override
-    void setBits(BitSet table) {
-      BitSet tmp = new BitSet();
-      original.setBits(tmp);
-      tmp.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
-      table.or(tmp);
-    }
-
-    @Override public CharMatcher negate() {
-      return original;
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new NegatedMatcher(description, original);
-    }
+    return new Negated(this);
   }
 
   /**
    * Returns a matcher that matches any character matched by both this matcher and {@code other}.
    */
   public CharMatcher and(CharMatcher other) {
-    return new And(this, checkNotNull(other));
-  }
-
-  private static class And extends CharMatcher {
-    final CharMatcher first;
-    final CharMatcher second;
-
-    And(CharMatcher a, CharMatcher b) {
-      this(a, b, "CharMatcher.and(" + a + ", " + b + ")");
-    }
-
-    And(CharMatcher a, CharMatcher b, String description) {
-      super(description);
-      first = checkNotNull(a);
-      second = checkNotNull(b);
-    }
-
-    @Override
-    public boolean matches(char c) {
-      return first.matches(c) && second.matches(c);
-    }
-
-    @GwtIncompatible("java.util.BitSet")
-    @Override
-    void setBits(BitSet table) {
-      BitSet tmp1 = new BitSet();
-      first.setBits(tmp1);
-      BitSet tmp2 = new BitSet();
-      second.setBits(tmp2);
-      tmp1.and(tmp2);
-      table.or(tmp1);
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new And(first, second, description);
-    }
+    return new And(this, other);
   }
 
   /**
    * Returns a matcher that matches any character matched by either this matcher or {@code other}.
    */
   public CharMatcher or(CharMatcher other) {
-    return new Or(this, checkNotNull(other));
-  }
-
-  private static class Or extends CharMatcher {
-    final CharMatcher first;
-    final CharMatcher second;
-
-    Or(CharMatcher a, CharMatcher b, String description) {
-      super(description);
-      first = checkNotNull(a);
-      second = checkNotNull(b);
-    }
-
-    Or(CharMatcher a, CharMatcher b) {
-      this(a, b, "CharMatcher.or(" + a + ", " + b + ")");
-    }
-
-    @GwtIncompatible("java.util.BitSet")
-    @Override
-    void setBits(BitSet table) {
-      first.setBits(table);
-      second.setBits(table);
-    }
-
-    @Override
-    public boolean matches(char c) {
-      return first.matches(c) || second.matches(c);
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new Or(first, second, description);
-    }
+    return new Or(this, other);
   }
 
   /**
@@ -765,16 +422,6 @@ public abstract class CharMatcher implements Predicate<Character> {
     return Platform.precomputeCharMatcher(this);
   }
 
-  /**
-   * Subclasses should provide a new CharMatcher with the same characteristics as {@code this},
-   * but with their {@code toString} method overridden with the new description.
-   *
-   * <p>This is unsupported by default.
-   */
-  CharMatcher withToString(String description) {
-    throw new UnsupportedOperationException();
-  }
-
   private static final int DISTINCT_CHARS = Character.MAX_VALUE - Character.MIN_VALUE + 1;
 
   /**
@@ -793,60 +440,24 @@ public abstract class CharMatcher implements Predicate<Character> {
     setBits(table);
     int totalCharacters = table.cardinality();
     if (totalCharacters * 2 <= DISTINCT_CHARS) {
-      return precomputedPositive(totalCharacters, table, description);
+      return precomputedPositive(totalCharacters, table, toString());
     } else {
-      // TODO(user): is it worth it to worry about the last character of large matchers?
+      // TODO(lowasser): is it worth it to worry about the last character of large matchers?
       table.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
       int negatedCharacters = DISTINCT_CHARS - totalCharacters;
       String suffix = ".negate()";
-      String negatedDescription = description.endsWith(suffix)
-          ? description.substring(0, description.length() - suffix.length())
-          : description + suffix;
-      return new NegatedFastMatcher(toString(),
-          precomputedPositive(negatedCharacters, table, negatedDescription));
-    }
-  }
-
-  /**
-   * A matcher for which precomputation will not yield any significant benefit.
-   */
-  abstract static class FastMatcher extends CharMatcher {
-    FastMatcher() {
-      super();
-    }
-
-    FastMatcher(String description) {
-      super(description);
-    }
-
-    @Override
-    public final CharMatcher precomputed() {
-      return this;
-    }
-
-    @Override
-    public CharMatcher negate() {
-      return new NegatedFastMatcher(this);
-    }
-  }
-
-  static final class NegatedFastMatcher extends NegatedMatcher {
-    NegatedFastMatcher(CharMatcher original) {
-      super(original);
-    }
-
-    NegatedFastMatcher(String toString, CharMatcher original) {
-      super(toString, original);
-    }
-
-    @Override
-    public final CharMatcher precomputed() {
-      return this;
-    }
-
-    @Override
-    CharMatcher withToString(String description) {
-      return new NegatedFastMatcher(description, original);
+      final String description = toString();
+      String negatedDescription =
+          description.endsWith(suffix)
+              ? description.substring(0, description.length() - suffix.length())
+              : description + suffix;
+      return new NegatedFastMatcher(
+          precomputedPositive(negatedCharacters, table, negatedDescription)) {
+        @Override
+        public String toString() {
+          return description;
+        }
+      };
     }
   }
 
@@ -855,12 +466,10 @@ public abstract class CharMatcher implements Predicate<Character> {
    */
   @GwtIncompatible("java.util.BitSet")
   private static CharMatcher precomputedPositive(
-      int totalCharacters,
-      BitSet table,
-      String description) {
+      int totalCharacters, BitSet table, String description) {
     switch (totalCharacters) {
       case 0:
-        return NONE;
+        return none();
       case 1:
         return is((char) table.nextSetBit(0));
       case 2:
@@ -878,30 +487,7 @@ public abstract class CharMatcher implements Predicate<Character> {
   private static boolean isSmall(int totalCharacters, int tableLength) {
     return totalCharacters <= SmallCharMatcher.MAX_SIZE
         && tableLength > (totalCharacters * 4 * Character.SIZE);
-        // err on the side of BitSetMatcher
-  }
-
-  @GwtIncompatible("java.util.BitSet")
-  private static class BitSetMatcher extends FastMatcher {
-    private final BitSet table;
-
-    private BitSetMatcher(BitSet table, String description) {
-      super(description);
-      if (table.length() + Long.SIZE < table.size()) {
-        table = (BitSet) table.clone();
-        // If only we could actually call BitSet.trimToSize() ourselves...
-      }
-      this.table = table;
-    }
-
-    @Override public boolean matches(char c) {
-      return table.get(c);
-    }
-
-    @Override
-    void setBits(BitSet bitSet) {
-      bitSet.or(table);
-    }
+    // err on the side of BitSetMatcher
   }
 
   /**
@@ -978,13 +564,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    * @return an index, or {@code -1} if no character matches
    */
   public int indexIn(CharSequence sequence) {
-    int length = sequence.length();
-    for (int i = 0; i < length; i++) {
-      if (matches(sequence.charAt(i))) {
-        return i;
-      }
-    }
-    return -1;
+    return indexIn(sequence, 0);
   }
 
   /**
@@ -1004,7 +584,7 @@ public abstract class CharMatcher implements Predicate<Character> {
    */
   public int indexIn(CharSequence sequence, int start) {
     int length = sequence.length();
-    Preconditions.checkPositionIndex(start, length);
+    checkPositionIndex(start, length);
     for (int i = start; i < length; i++) {
       if (matches(sequence.charAt(i))) {
         return i;
@@ -1065,7 +645,8 @@ public abstract class CharMatcher implements Predicate<Character> {
     int spread = 1;
 
     // This unusual loop comes from extensive benchmarking
-    OUT: while (true) {
+    OUT:
+    while (true) {
       pos++;
       while (true) {
         if (pos == chars.length) {
@@ -1273,14 +854,12 @@ public abstract class CharMatcher implements Predicate<Character> {
     for (int i = 0; i < len; i++) {
       char c = sequence.charAt(i);
       if (matches(c)) {
-        if (c == replacement
-            && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
+        if (c == replacement && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
           // a no-op replacement
           i++;
         } else {
-          StringBuilder builder = new StringBuilder(len)
-              .append(sequence.subSequence(0, i))
-              .append(replacement);
+          StringBuilder builder =
+              new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement);
           return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
         }
       }
@@ -1298,23 +877,30 @@ public abstract class CharMatcher implements Predicate<Character> {
   public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
     // This implementation avoids unnecessary allocation.
     int len = sequence.length();
-    int first;
-    int last;
+    int first = 0;
+    int last = len - 1;
+
+    while (first < len && matches(sequence.charAt(first))) {
+      first++;
+    }
 
-    for (first = 0; first < len && matches(sequence.charAt(first)); first++) {}
-    for (last = len - 1; last > first && matches(sequence.charAt(last)); last--) {}
+    while (last > first && matches(sequence.charAt(last))) {
+      last--;
+    }
 
     return (first == 0 && last == len - 1)
         ? collapseFrom(sequence, replacement)
         : finishCollapseFrom(
-              sequence, first, last + 1, replacement,
-              new StringBuilder(last + 1 - first),
-              false);
+            sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
   }
 
   private String finishCollapseFrom(
-      CharSequence sequence, int start, int end, char replacement,
-      StringBuilder builder, boolean inMatchingGroup) {
+      CharSequence sequence,
+      int start,
+      int end,
+      char replacement,
+      StringBuilder builder,
+      boolean inMatchingGroup) {
     for (int i = start; i < end; i++) {
       char c = sequence.charAt(i);
       if (matches(c)) {
@@ -1346,40 +932,895 @@ public abstract class CharMatcher implements Predicate<Character> {
    */
   @Override
   public String toString() {
-    return description;
+    return super.toString();
   }
 
-  static final String WHITESPACE_TABLE = ""
-      + "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
-      + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
-      + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
-      + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
-  static final int WHITESPACE_MULTIPLIER = 1682554634;
-  static final int WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(WHITESPACE_TABLE.length() - 1);
-
   /**
-   * Determines whether a character is whitespace according to the latest Unicode standard, as
-   * illustrated
-   * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
-   * This is not the same definition used by other Java APIs. (See a
-   * <a href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
-   * definitions of "whitespace"</a>.)
-   *
-   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
-   * to date.
+   * Returns the Java Unicode escape sequence for the given character, in the form "\u12AB" where
+   * "12AB" is the four hexadecimal digits representing the 16 bits of the UTF-16 character.
    */
-  public static final CharMatcher WHITESPACE = new FastMatcher("WHITESPACE") {
+  private static String showCharacter(char c) {
+    String hex = "0123456789ABCDEF";
+    char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
+    for (int i = 0; i < 4; i++) {
+      tmp[5 - i] = hex.charAt(c & 0xF);
+      c = (char) (c >> 4);
+    }
+    return String.copyValueOf(tmp);
+  }
+
+  // Fast matchers
+
+  /** A matcher for which precomputation will not yield any significant benefit. */
+  abstract static class FastMatcher extends CharMatcher {
+
     @Override
-    public boolean matches(char c) {
-      return WHITESPACE_TABLE.charAt((WHITESPACE_MULTIPLIER * c) >>> WHITESPACE_SHIFT) == c;
+    public final CharMatcher precomputed() {
+      return this;
     }
 
-    @GwtIncompatible("java.util.BitSet")
     @Override
-    void setBits(BitSet table) {
-      for (int i = 0; i < WHITESPACE_TABLE.length(); i++) {
-        table.set(WHITESPACE_TABLE.charAt(i));
+    public CharMatcher negate() {
+      return new NegatedFastMatcher(this);
+    }
+  }
+
+  /** {@link FastMatcher} which overrides {@code toString()} with a custom name. */
+  abstract static class NamedFastMatcher extends FastMatcher {
+
+    private final String description;
+
+    NamedFastMatcher(String description) {
+      this.description = checkNotNull(description);
+    }
+
+    @Override
+    public final String toString() {
+      return description;
+    }
+  }
+
+  /** Negation of a {@link FastMatcher}. */
+  static class NegatedFastMatcher extends Negated {
+
+    NegatedFastMatcher(CharMatcher original) {
+      super(original);
+    }
+
+    @Override
+    public final CharMatcher precomputed() {
+      return this;
+    }
+  }
+
+  /** Fast matcher using a {@link BitSet} table of matching characters. */
+  @GwtIncompatible("java.util.BitSet")
+  private static final class BitSetMatcher extends NamedFastMatcher {
+
+    private final BitSet table;
+
+    private BitSetMatcher(BitSet table, String description) {
+      super(description);
+      if (table.length() + Long.SIZE < table.size()) {
+        table = (BitSet) table.clone();
+        // If only we could actually call BitSet.trimToSize() ourselves...
       }
+      this.table = table;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return table.get(c);
     }
-  };
+
+    @Override
+    void setBits(BitSet bitSet) {
+      bitSet.or(table);
+    }
+  }
+
+  // Static constant implementation classes
+
+  /** Implementation of {@link #any()}. */
+  private static final class Any extends NamedFastMatcher {
+
+    static final Any INSTANCE = new Any();
+
+    private Any() {
+      super("CharMatcher.any()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return true;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence) {
+      return (sequence.length() == 0) ? -1 : 0;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence, int start) {
+      int length = sequence.length();
+      checkPositionIndex(start, length);
+      return (start == length) ? -1 : start;
+    }
+
+    @Override
+    public int lastIndexIn(CharSequence sequence) {
+      return sequence.length() - 1;
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      checkNotNull(sequence);
+      return true;
+    }
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      return sequence.length() == 0;
+    }
+
+    @Override
+    public String removeFrom(CharSequence sequence) {
+      checkNotNull(sequence);
+      return "";
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      char[] array = new char[sequence.length()];
+      Arrays.fill(array, replacement);
+      return new String(array);
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+      StringBuilder result = new StringBuilder(sequence.length() * replacement.length());
+      for (int i = 0; i < sequence.length(); i++) {
+        result.append(replacement);
+      }
+      return result.toString();
+    }
+
+    @Override
+    public String collapseFrom(CharSequence sequence, char replacement) {
+      return (sequence.length() == 0) ? "" : String.valueOf(replacement);
+    }
+
+    @Override
+    public String trimFrom(CharSequence sequence) {
+      checkNotNull(sequence);
+      return "";
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      return sequence.length();
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return checkNotNull(other);
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      checkNotNull(other);
+      return this;
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return none();
+    }
+  }
+
+  /** Implementation of {@link #none()}. */
+  private static final class None extends NamedFastMatcher {
+
+    static final None INSTANCE = new None();
+
+    private None() {
+      super("CharMatcher.none()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return false;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return -1;
+    }
+
+    @Override
+    public int indexIn(CharSequence sequence, int start) {
+      int length = sequence.length();
+      checkPositionIndex(start, length);
+      return -1;
+    }
+
+    @Override
+    public int lastIndexIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return -1;
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      return sequence.length() == 0;
+    }
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      checkNotNull(sequence);
+      return true;
+    }
+
+    @Override
+    public String removeFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+      checkNotNull(replacement);
+      return sequence.toString();
+    }
+
+    @Override
+    public String collapseFrom(CharSequence sequence, char replacement) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimLeadingFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public String trimTrailingFrom(CharSequence sequence) {
+      return sequence.toString();
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      checkNotNull(sequence);
+      return 0;
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      checkNotNull(other);
+      return this;
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return checkNotNull(other);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return any();
+    }
+  }
+
+  /** Implementation of {@link #whitespace()}. */
+  @VisibleForTesting
+  static final class Whitespace extends NamedFastMatcher {
+
+    static final String TABLE =
+        "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
+            + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
+            + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
+            + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
+    static final int MULTIPLIER = 1682554634;
+    static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1);
+
+    static final Whitespace INSTANCE = new Whitespace();
+
+    Whitespace() {
+      super("CharMatcher.whitespace()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return TABLE.charAt((MULTIPLIER * c) >>> SHIFT) == c;
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      for (int i = 0; i < TABLE.length(); i++) {
+        table.set(TABLE.charAt(i));
+      }
+    }
+  }
+
+  /** Implementation of {@link #breakingWhitespace()}. */
+  private static final class BreakingWhitespace extends CharMatcher {
+
+    static final CharMatcher INSTANCE = new BreakingWhitespace();
+
+    @Override
+    public boolean matches(char c) {
+      switch (c) {
+        case '\t':
+        case '\n':
+        case '\013':
+        case '\f':
+        case '\r':
+        case ' ':
+        case '\u0085':
+        case '\u1680':
+        case '\u2028':
+        case '\u2029':
+        case '\u205f':
+        case '\u3000':
+          return true;
+        case '\u2007':
+          return false;
+        default:
+          return c >= '\u2000' && c <= '\u200a';
+      }
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.breakingWhitespace()";
+    }
+  }
+
+  /** Implementation of {@link #ascii()}. */
+  private static final class Ascii extends NamedFastMatcher {
+
+    static final Ascii INSTANCE = new Ascii();
+
+    Ascii() {
+      super("CharMatcher.ascii()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c <= '\u007f';
+    }
+  }
+
+  /** Implementation that matches characters that fall within multiple ranges. */
+  private static class RangesMatcher extends CharMatcher {
+
+    private final String description;
+    private final char[] rangeStarts;
+    private final char[] rangeEnds;
+
+    RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
+      this.description = description;
+      this.rangeStarts = rangeStarts;
+      this.rangeEnds = rangeEnds;
+      checkArgument(rangeStarts.length == rangeEnds.length);
+      for (int i = 0; i < rangeStarts.length; i++) {
+        checkArgument(rangeStarts[i] <= rangeEnds[i]);
+        if (i + 1 < rangeStarts.length) {
+          checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
+        }
+      }
+    }
+
+    @Override
+    public boolean matches(char c) {
+      int index = Arrays.binarySearch(rangeStarts, c);
+      if (index >= 0) {
+        return true;
+      } else {
+        index = ~index - 1;
+        return index >= 0 && c <= rangeEnds[index];
+      }
+    }
+
+    @Override
+    public String toString() {
+      return description;
+    }
+  }
+
+  /** Implementation of {@link #digit()}. */
+  private static final class Digit extends RangesMatcher {
+
+    // Must be in ascending order.
+    private static final String ZEROES =
+        "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66"
+            + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810"
+            + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+
+    private static char[] zeroes() {
+      return ZEROES.toCharArray();
+    }
+
+    private static char[] nines() {
+      char[] nines = new char[ZEROES.length()];
+      for (int i = 0; i < ZEROES.length(); i++) {
+        nines[i] = (char) (ZEROES.charAt(i) + 9);
+      }
+      return nines;
+    }
+
+    static final Digit INSTANCE = new Digit();
+
+    private Digit() {
+      super("CharMatcher.digit()", zeroes(), nines());
+    }
+  }
+
+  /** Implementation of {@link #javaDigit()}. */
+  private static final class JavaDigit extends CharMatcher {
+
+    static final JavaDigit INSTANCE = new JavaDigit();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isDigit(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaDigit()";
+    }
+  }
+
+  /** Implementation of {@link #javaLetter()}. */
+  private static final class JavaLetter extends CharMatcher {
+
+    static final JavaLetter INSTANCE = new JavaLetter();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLetter(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLetter()";
+    }
+  }
+
+  /** Implementation of {@link #javaLetterOrDigit()}. */
+  private static final class JavaLetterOrDigit extends CharMatcher {
+
+    static final JavaLetterOrDigit INSTANCE = new JavaLetterOrDigit();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLetterOrDigit(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLetterOrDigit()";
+    }
+  }
+
+  /** Implementation of {@link #javaUpperCase()}. */
+  private static final class JavaUpperCase extends CharMatcher {
+
+    static final JavaUpperCase INSTANCE = new JavaUpperCase();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isUpperCase(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaUpperCase()";
+    }
+  }
+
+  /** Implementation of {@link #javaLowerCase()}. */
+  private static final class JavaLowerCase extends CharMatcher {
+
+    static final JavaLowerCase INSTANCE = new JavaLowerCase();
+
+    @Override
+    public boolean matches(char c) {
+      return Character.isLowerCase(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.javaLowerCase()";
+    }
+  }
+
+  /** Implementation of {@link #javaIsoControl()}. */
+  private static final class JavaIsoControl extends NamedFastMatcher {
+
+    static final JavaIsoControl INSTANCE = new JavaIsoControl();
+
+    private JavaIsoControl() {
+      super("CharMatcher.javaIsoControl()");
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c <= '\u001f' || (c >= '\u007f' && c <= '\u009f');
+    }
+  }
+
+  /** Implementation of {@link #invisible()}. */
+  private static final class Invisible extends RangesMatcher {
+
+    private static final String RANGE_STARTS =
+      "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067"
+          + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa";
+    private static final String RANGE_ENDS =
+      "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067"
+          + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb";
+
+    static final Invisible INSTANCE = new Invisible();
+
+    private Invisible() {
+      super(
+          "CharMatcher.invisible()",
+          RANGE_STARTS.toCharArray(),
+          RANGE_ENDS.toCharArray());
+    }
+  }
+
+  /** Implementation of {@link #singleWidth()}. */
+  private static final class SingleWidth extends RangesMatcher {
+
+    static final SingleWidth INSTANCE = new SingleWidth();
+
+    private SingleWidth() {
+      super(
+          "CharMatcher.singleWidth()",
+          "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
+          "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
+    }
+  }
+
+  // Non-static factory implementation classes
+
+  /** Implementation of {@link #negate()}. */
+  private static class Negated extends CharMatcher {
+
+    final CharMatcher original;
+
+    Negated(CharMatcher original) {
+      this.original = checkNotNull(original);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return !original.matches(c);
+    }
+
+    @Override
+    public boolean matchesAllOf(CharSequence sequence) {
+      return original.matchesNoneOf(sequence);
+    }
+
+    @Override
+    public boolean matchesNoneOf(CharSequence sequence) {
+      return original.matchesAllOf(sequence);
+    }
+
+    @Override
+    public int countIn(CharSequence sequence) {
+      return sequence.length() - original.countIn(sequence);
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      BitSet tmp = new BitSet();
+      original.setBits(tmp);
+      tmp.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
+      table.or(tmp);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return original;
+    }
+
+    @Override
+    public String toString() {
+      return original + ".negate()";
+    }
+  }
+
+  /** Implementation of {@link #and(CharMatcher)}. */
+  private static final class And extends CharMatcher {
+
+    final CharMatcher first;
+    final CharMatcher second;
+
+    And(CharMatcher a, CharMatcher b) {
+      first = checkNotNull(a);
+      second = checkNotNull(b);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return first.matches(c) && second.matches(c);
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      BitSet tmp1 = new BitSet();
+      first.setBits(tmp1);
+      BitSet tmp2 = new BitSet();
+      second.setBits(tmp2);
+      tmp1.and(tmp2);
+      table.or(tmp1);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.and(" + first + ", " + second + ")";
+    }
+  }
+
+  /** Implementation of {@link #or(CharMatcher)}. */
+  private static final class Or extends CharMatcher {
+
+    final CharMatcher first;
+    final CharMatcher second;
+
+    Or(CharMatcher a, CharMatcher b) {
+      first = checkNotNull(a);
+      second = checkNotNull(b);
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      first.setBits(table);
+      second.setBits(table);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return first.matches(c) || second.matches(c);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.or(" + first + ", " + second + ")";
+    }
+  }
+
+  // Static factory implementations
+
+  /** Implementation of {@link #is(char)}. */
+  private static final class Is extends FastMatcher {
+
+    private final char match;
+
+    Is(char match) {
+      this.match = match;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c == match;
+    }
+
+    @Override
+    public String replaceFrom(CharSequence sequence, char replacement) {
+      return sequence.toString().replace(match, replacement);
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return other.matches(match) ? this : none();
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return other.matches(match) ? other : super.or(other);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return isNot(match);
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      table.set(match);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.is('" + showCharacter(match) + "')";
+    }
+  }
+
+  /** Implementation of {@link #isNot(char)}. */
+  private static final class IsNot extends FastMatcher {
+
+    private final char match;
+
+    IsNot(char match) {
+      this.match = match;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c != match;
+    }
+
+    @Override
+    public CharMatcher and(CharMatcher other) {
+      return other.matches(match) ? super.and(other) : other;
+    }
+
+    @Override
+    public CharMatcher or(CharMatcher other) {
+      return other.matches(match) ? any() : this;
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      table.set(0, match);
+      table.set(match + 1, Character.MAX_VALUE + 1);
+    }
+
+    @Override
+    public CharMatcher negate() {
+      return is(match);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.isNot('" + showCharacter(match) + "')";
+    }
+  }
+
+  private static CharMatcher.IsEither isEither(char c1, char c2) {
+    return new CharMatcher.IsEither(c1, c2);
+  }
+
+  /** Implementation of {@link #anyOf(CharSequence)} for exactly two characters. */
+  private static final class IsEither extends FastMatcher {
+
+    private final char match1;
+    private final char match2;
+
+    IsEither(char match1, char match2) {
+      this.match1 = match1;
+      this.match2 = match2;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return c == match1 || c == match2;
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      table.set(match1);
+      table.set(match2);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")";
+    }
+  }
+
+  /** Implementation of {@link #anyOf(CharSequence)} for three or more characters. */
+  private static final class AnyOf extends CharMatcher {
+
+    private final char[] chars;
+
+    public AnyOf(CharSequence chars) {
+      this.chars = chars.toString().toCharArray();
+      Arrays.sort(this.chars);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return Arrays.binarySearch(chars, c) >= 0;
+    }
+
+    @Override
+    @GwtIncompatible("java.util.BitSet")
+    void setBits(BitSet table) {
+      for (char c : chars) {
+        table.set(c);
+      }
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
+      for (char c : chars) {
+        description.append(showCharacter(c));
+      }
+      description.append("\")");
+      return description.toString();
+    }
+  }
+
+  /** Implementation of {@link #inRange(char, char)}. */
+  private static final class InRange extends FastMatcher {
+
+    private final char startInclusive;
+    private final char endInclusive;
+
+    InRange(char startInclusive, char endInclusive) {
+      checkArgument(endInclusive >= startInclusive);
+      this.startInclusive = startInclusive;
+      this.endInclusive = endInclusive;
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return startInclusive <= c && c <= endInclusive;
+    }
+
+    @GwtIncompatible("java.util.BitSet")
+    @Override
+    void setBits(BitSet table) {
+      table.set(startInclusive, endInclusive + 1);
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.inRange('"
+          + showCharacter(startInclusive)
+          + "', '"
+          + showCharacter(endInclusive)
+          + "')";
+    }
+  }
+
+  /** Implementation of {@link #forPredicate(Predicate)}. */
+  private static final class ForPredicate extends CharMatcher {
+
+    private final Predicate<? super Character> predicate;
+
+    ForPredicate(Predicate<? super Character> predicate) {
+      this.predicate = checkNotNull(predicate);
+    }
+
+    @Override
+    public boolean matches(char c) {
+      return predicate.apply(c);
+    }
+
+    @SuppressWarnings("deprecation") // intentional; deprecation is for callers primarily
+    @Override
+    public boolean apply(Character character) {
+      return predicate.apply(checkNotNull(character));
+    }
+
+    @Override
+    public String toString() {
+      return "CharMatcher.forPredicate(" + predicate + ")";
+    }
+  }
 }
diff --git a/guava/src/com/google/common/base/Charsets.java b/guava/src/com/google/common/base/Charsets.java
index 37fc686..9aba5c4 100644
--- a/guava/src/com/google/common/base/Charsets.java
+++ b/guava/src/com/google/common/base/Charsets.java
@@ -28,7 +28,7 @@ import java.nio.charset.Charset;
  * <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">
+ * href="https://github.com/google/guava/wiki/StringsExplained#charsets">
  * {@code Charsets}</a>.
  *
  * @author Mike Bostock
diff --git a/guava/src/com/google/common/base/Converter.java b/guava/src/com/google/common/base/Converter.java
index 6c13776..40ca53a 100644
--- a/guava/src/com/google/common/base/Converter.java
+++ b/guava/src/com/google/common/base/Converter.java
@@ -69,8 +69,9 @@ import javax.annotation.Nullable;
  *     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.
+ * <li>Extend this class and implement its {@link #doForward} and {@link #doBackward} methods.
+ * <li>If using Java 8, you may prefer to pass two lambda expressions or method references to {@link
+ *     #from}.
  * </ul>
  *
  * <p>Using a converter:
@@ -85,6 +86,26 @@ import javax.annotation.Nullable;
  *     overridden.
  * </ul>
  *
+ * <h3>Example</h3>
+ *
+ * <pre>   {@code
+ *
+ *   return new Converter<Integer, String>() {
+ *     @Override
+ *     protected String doForward(Integer i) {
+ *       return Integer.toHexString(i);
+ *     }
+ *
+ *     @Override
+ *     protected Integer doBackward(String s) {
+ *       return parseUnsignedInt(s, 16);
+ *     }
+ *   };}</pre>
+ *
+ * <p>An alternative using Java 8: <pre>   {@code
+ *
+ *   return Converter.from(Integer::toHexString, s -> parseUnsignedInt(s, 16));}</pre>
+ *
  * @author Mike Ward
  * @author Kurt Alfred Kluever
  * @author Gregory Kick
@@ -178,7 +199,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
   public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
     checkNotNull(fromIterable, "fromIterable");
     return new Iterable<B>() {
-      @Override public Iterator<B> iterator() {
+      @Override
+      public Iterator<B> iterator() {
         return new Iterator<B>() {
           private final Iterator<? extends A> fromIterator = fromIterable.iterator();
 
@@ -207,14 +229,14 @@ public abstract class Converter<A, B> implements Function<A, B> {
    *
    * <p>The returned converter is serializable if {@code this} converter is.
    */
-  // TODO(user): Make this method final
+  // TODO(kak): 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 {
+  private static final class ReverseConverter<A, B> extends Converter<B, A>
+      implements Serializable {
     final Converter<A, B> original;
 
     ReverseConverter(Converter<A, B> original) {
@@ -295,8 +317,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
     return new ConverterComposition<A, B, C>(this, checkNotNull(secondConverter));
   }
 
-  private static final class ConverterComposition<A, B, C>
-      extends Converter<A, C> implements Serializable {
+  private static final class ConverterComposition<A, B, C> extends Converter<A, C>
+      implements Serializable {
     final Converter<A, B> first;
     final Converter<B, C> second;
 
@@ -338,8 +360,7 @@ public abstract class Converter<A, B> implements Function<A, B> {
     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 this.first.equals(that.first) && this.second.equals(that.second);
       }
       return false;
     }
@@ -405,8 +426,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
     return new FunctionBasedConverter<A, B>(forwardFunction, backwardFunction);
   }
 
-  private static final class FunctionBasedConverter<A, B>
-      extends Converter<A, B> implements Serializable {
+  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;
 
diff --git a/guava/src/com/google/common/base/Defaults.java b/guava/src/com/google/common/base/Defaults.java
index e07c75c..bfc22cf 100644
--- a/guava/src/com/google/common/base/Defaults.java
+++ b/guava/src/com/google/common/base/Defaults.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -30,6 +31,7 @@ import javax.annotation.Nullable;
  * @author Ben Yu
  * @since 1.0
  */
+ at CheckReturnValue
 public final class Defaults {
   private Defaults() {}
 
@@ -56,7 +58,7 @@ public final class Defaults {
   /**
    * 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.
+   * {@code void}, {@code null} is returned.
    */
   @Nullable
   public static <T> T defaultValue(Class<T> type) {
diff --git a/guava/src/com/google/common/base/Enums.java b/guava/src/com/google/common/base/Enums.java
index dbc3754..cbbe08f 100644
--- a/guava/src/com/google/common/base/Enums.java
+++ b/guava/src/com/google/common/base/Enums.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.WeakHashMap;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -39,6 +40,7 @@ import javax.annotation.Nullable;
  *
  * @since 9.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 @Beta
 public final class Enums {
@@ -70,8 +72,7 @@ public final class Enums {
    *
    * @since 12.0
    */
-  public static <T extends Enum<T>> Optional<T> getIfPresent(
-      Class<T> enumClass, String value) {
+  public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
     checkNotNull(enumClass);
     checkNotNull(value);
     return Platform.getEnumIfPresent(enumClass, value);
@@ -79,14 +80,15 @@ public final class Enums {
 
   @GwtIncompatible("java.lang.ref.WeakReference")
   private static final Map<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>
-      enumConstantCache = new WeakHashMap
-              <Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>();
+      enumConstantCache =
+          new WeakHashMap<
+              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<?>>>();
+    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));
     }
@@ -98,8 +100,7 @@ public final class Enums {
   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);
+      Map<String, WeakReference<? extends Enum<?>>> constants = enumConstantCache.get(enumClass);
       if (constants == null) {
         constants = populateCache(enumClass);
       }
@@ -119,8 +120,8 @@ public final class Enums {
     return new StringConverter<T>(enumClass);
   }
 
-  private static final class StringConverter<T extends Enum<T>>
-      extends Converter<String, T> implements Serializable {
+  private static final class StringConverter<T extends Enum<T>> extends Converter<String, T>
+      implements Serializable {
 
     private final Class<T> enumClass;
 
diff --git a/guava/src/com/google/common/base/Equivalence.java b/guava/src/com/google/common/base/Equivalence.java
index be654cf..344454f 100644
--- a/guava/src/com/google/common/base/Equivalence.java
+++ b/guava/src/com/google/common/base/Equivalence.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
 
 import java.io.Serializable;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -33,9 +34,10 @@ import javax.annotation.Nullable;
  * @author Bob Lee
  * @author Ben Yu
  * @author Gregory Kick
- * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * @since 10.0 (<a href="https://github.com/google/guava/wiki/Compatibility"
  *        >mostly source-compatible</a> since 4.0)
  */
+ at CheckReturnValue
 @GwtCompatible
 public abstract class Equivalence<T> {
   /**
@@ -124,27 +126,27 @@ public abstract class Equivalence<T> {
    *
    * <pre>   {@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) {
@@ -179,7 +181,8 @@ public abstract class Equivalence<T> {
     }
 
     /** Returns the (possibly null) reference wrapped by this instance. */
-    @Nullable public T get() {
+    @Nullable
+    public T get() {
       return reference;
     }
 
@@ -188,7 +191,8 @@ public abstract class Equivalence<T> {
      * references is {@code true} and both wrappers use the {@link Object#equals(Object) same}
      * equivalence.
      */
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj == this) {
         return true;
       }
@@ -211,7 +215,8 @@ public abstract class Equivalence<T> {
     /**
      * Returns the result of {@link Equivalence#hash(Object)} applied to the wrapped reference.
      */
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return equivalence.hash(reference);
     }
 
@@ -219,7 +224,8 @@ public abstract class Equivalence<T> {
      * Returns a string representation for this equivalence wrapper. The form of this string
      * representation is not specified.
      */
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return equivalence + ".wrap(" + reference + ")";
     }
 
@@ -231,7 +237,7 @@ public abstract class Equivalence<T> {
    * 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.
    *
@@ -243,11 +249,11 @@ public abstract class Equivalence<T> {
     // 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
@@ -265,27 +271,30 @@ public abstract class Equivalence<T> {
       this.target = target;
     }
 
-    @Override public boolean apply(@Nullable T input) {
+    @Override
+    public boolean apply(@Nullable T input) {
       return equivalence.equivalent(input, target);
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @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 equivalence.equals(that.equivalence) && Objects.equal(target, that.target);
       }
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(equivalence, target);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return equivalence + ".equivalentTo(" + target + ")";
     }
 
@@ -318,40 +327,45 @@ public abstract class Equivalence<T> {
     return Identity.INSTANCE;
   }
 
-  static final class Equals extends Equivalence<Object>
-      implements Serializable {
-    
+  static final class Equals extends Equivalence<Object> implements Serializable {
+
     static final Equals INSTANCE = new Equals();
 
-    @Override protected boolean doEquivalent(Object a, Object b) {
+    @Override
+    protected boolean doEquivalent(Object a, Object b) {
       return a.equals(b);
     }
-    @Override protected int doHash(Object o) {
+
+    @Override
+    protected 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 class Identity extends Equivalence<Object> implements Serializable {
+
     static final Identity INSTANCE = new Identity();
-    
-    @Override protected boolean doEquivalent(Object a, Object b) {
+
+    @Override
+    protected boolean doEquivalent(Object a, Object b) {
       return false;
     }
 
-    @Override protected int doHash(Object o) {
+    @Override
+    protected int doHash(Object o) {
       return System.identityHashCode(o);
     }
- 
+
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 }
diff --git a/guava/src/com/google/common/base/FinalizablePhantomReference.java b/guava/src/com/google/common/base/FinalizablePhantomReference.java
index c694bc9..952143e 100644
--- a/guava/src/com/google/common/base/FinalizablePhantomReference.java
+++ b/guava/src/com/google/common/base/FinalizablePhantomReference.java
@@ -27,7 +27,7 @@ import java.lang.ref.ReferenceQueue;
  * <p>Unlike a normal phantom reference, this reference will be cleared automatically.
  *
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public abstract class FinalizablePhantomReference<T> extends PhantomReference<T>
     implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/FinalizableReference.java b/guava/src/com/google/common/base/FinalizableReference.java
index ab2dec3..acc6efc 100644
--- a/guava/src/com/google/common/base/FinalizableReference.java
+++ b/guava/src/com/google/common/base/FinalizableReference.java
@@ -21,7 +21,7 @@ package com.google.common.base;
  *
  * @see FinalizableReferenceQueue
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public interface FinalizableReference {
   /**
diff --git a/guava/src/com/google/common/base/FinalizableReferenceQueue.java b/guava/src/com/google/common/base/FinalizableReferenceQueue.java
index ddd27fa..7ff90e8 100644
--- a/guava/src/com/google/common/base/FinalizableReferenceQueue.java
+++ b/guava/src/com/google/common/base/FinalizableReferenceQueue.java
@@ -89,7 +89,7 @@ import javax.annotation.Nullable;
  * </pre>
  *
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public class FinalizableReferenceQueue implements Closeable {
   /*
@@ -134,9 +134,10 @@ public class FinalizableReferenceQueue implements Closeable {
 
   /** Reference to Finalizer.startFinalizer(). */
   private static final Method startFinalizer;
+
   static {
-    Class<?> finalizer = loadFinalizer(
-        new SystemLoader(), new DecoupledLoader(), new DirectLoader());
+    Class<?> finalizer =
+        loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader());
     startFinalizer = getStartFinalizer(finalizer);
   }
 
@@ -166,8 +167,11 @@ public class FinalizableReferenceQueue implements Closeable {
     } 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);
+      logger.log(
+          Level.INFO,
+          "Failed to start reference finalizer thread."
+              + " Reference cleanup will only occur when new references are created.",
+          t);
     }
 
     this.threadStarted = threadStarted;
@@ -241,8 +245,7 @@ public class FinalizableReferenceQueue implements Closeable {
   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;
+    @VisibleForTesting static boolean disabled;
 
     @Override
     public Class<?> loadFinalizer() {
@@ -275,10 +278,11 @@ public class FinalizableReferenceQueue implements Closeable {
    * 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.";
+    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 Guava to your system class path.";
 
     @Override
     public Class<?> loadFinalizer() {
@@ -350,10 +354,7 @@ public class FinalizableReferenceQueue implements Closeable {
   static Method getStartFinalizer(Class<?> finalizer) {
     try {
       return finalizer.getMethod(
-          "startFinalizer",
-          Class.class,
-          ReferenceQueue.class,
-          PhantomReference.class);
+          "startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
     } catch (NoSuchMethodException e) {
       throw new AssertionError(e);
     }
diff --git a/guava/src/com/google/common/base/FinalizableSoftReference.java b/guava/src/com/google/common/base/FinalizableSoftReference.java
index 88607f4..74726c1 100644
--- a/guava/src/com/google/common/base/FinalizableSoftReference.java
+++ b/guava/src/com/google/common/base/FinalizableSoftReference.java
@@ -25,7 +25,7 @@ import java.lang.ref.SoftReference;
  * ReferenceQueue}.
  *
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public abstract class FinalizableSoftReference<T> extends SoftReference<T>
     implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/FinalizableWeakReference.java b/guava/src/com/google/common/base/FinalizableWeakReference.java
index b14d023..d128df5 100644
--- a/guava/src/com/google/common/base/FinalizableWeakReference.java
+++ b/guava/src/com/google/common/base/FinalizableWeakReference.java
@@ -25,7 +25,7 @@ import java.lang.ref.WeakReference;
  * ReferenceQueue}.
  *
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public abstract class FinalizableWeakReference<T> extends WeakReference<T>
     implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/Function.java b/guava/src/com/google/common/base/Function.java
index f969b4a..f39e2ea 100644
--- a/guava/src/com/google/common/base/Function.java
+++ b/guava/src/com/google/common/base/Function.java
@@ -26,11 +26,11 @@ import javax.annotation.Nullable;
  * <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
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
  * Function}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface Function<F, T> {
@@ -48,7 +48,8 @@ public interface Function<F, T> {
    * @throws NullPointerException if {@code input} is null and this function does not accept null
    *     arguments
    */
-  @Nullable T apply(@Nullable F input);
+  @Nullable
+  T apply(@Nullable F input);
 
   /**
    * Indicates whether another object is equal to this function.
diff --git a/guava/src/com/google/common/base/FunctionalEquivalence.java b/guava/src/com/google/common/base/FunctionalEquivalence.java
index a5e9c13..c28f6b9 100644
--- a/guava/src/com/google/common/base/FunctionalEquivalence.java
+++ b/guava/src/com/google/common/base/FunctionalEquivalence.java
@@ -33,45 +33,47 @@ import javax.annotation.Nullable;
  */
 @Beta
 @GwtCompatible
-final class FunctionalEquivalence<F, T> extends Equivalence<F>
-    implements Serializable {
+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) {
+  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) {
+  @Override
+  protected boolean doEquivalent(F a, F b) {
     return resultEquivalence.equivalent(function.apply(a), function.apply(b));
   }
 
-  @Override protected int doHash(F a) {
+  @Override
+  protected int doHash(F a) {
     return resultEquivalence.hash(function.apply(a));
   }
 
-  @Override public boolean equals(@Nullable Object obj) {
+  @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 function.equals(that.function) && resultEquivalence.equals(that.resultEquivalence);
     }
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Objects.hashCode(function, resultEquivalence);
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return resultEquivalence + ".onResultOf(" + function + ")";
   }
 }
diff --git a/guava/src/com/google/common/base/Functions.java b/guava/src/com/google/common/base/Functions.java
index 669fd9a..da5626d 100644
--- a/guava/src/com/google/common/base/Functions.java
+++ b/guava/src/com/google/common/base/Functions.java
@@ -25,22 +25,24 @@ import com.google.common.annotations.GwtCompatible;
 import java.io.Serializable;
 import java.util.Map;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
  * 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
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
  * Function}</a>.
  *
  * @author Mike Bostock
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
+ at CheckReturnValue
 public final class Functions {
   private Functions() {}
 
@@ -62,12 +64,13 @@ public final class Functions {
 
     @Override
     public String apply(Object o) {
-      checkNotNull(o);  // eager for GWT.
+      checkNotNull(o); // eager for GWT.
       return o.toString();
     }
 
-    @Override public String toString() {
-      return "toString";
+    @Override
+    public String toString() {
+      return "Functions.toStringFunction()";
     }
   }
 
@@ -90,8 +93,9 @@ public final class Functions {
       return o;
     }
 
-    @Override public String toString() {
-      return "identity";
+    @Override
+    public String toString() {
+      return "Functions.identity()";
     }
   }
 
@@ -122,7 +126,8 @@ public final class Functions {
       return result;
     }
 
-    @Override public boolean equals(@Nullable Object o) {
+    @Override
+    public boolean equals(@Nullable Object o) {
       if (o instanceof FunctionForMapNoDefault) {
         FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
         return map.equals(that.map);
@@ -130,12 +135,14 @@ public final class Functions {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return map.hashCode();
     }
 
-    @Override public String toString() {
-      return "forMap(" + map + ")";
+    @Override
+    public String toString() {
+      return "Functions.forMap(" + map + ")";
     }
 
     private static final long serialVersionUID = 0;
@@ -170,7 +177,8 @@ public final class Functions {
       return (result != null || map.containsKey(key)) ? result : defaultValue;
     }
 
-    @Override public boolean equals(@Nullable Object o) {
+    @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);
@@ -178,12 +186,15 @@ public final class Functions {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(map, defaultValue);
     }
 
-    @Override public String toString() {
-      return "forMap(" + map + ", defaultValue=" + defaultValue + ")";
+    @Override
+    public String toString() {
+      // TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does
+      return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")";
     }
 
     private static final long serialVersionUID = 0;
@@ -216,7 +227,8 @@ public final class Functions {
       return g.apply(f.apply(a));
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof FunctionComposition) {
         FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
         return f.equals(that.f) && g.equals(that.g);
@@ -224,11 +236,14 @@ public final class Functions {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return f.hashCode() ^ g.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
+      // TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)")
       return g + "(" + f + ")";
     }
 
@@ -258,7 +273,8 @@ public final class Functions {
       return predicate.apply(t);
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof PredicateFunction) {
         PredicateFunction<?> that = (PredicateFunction<?>) obj;
         return predicate.equals(that.predicate);
@@ -266,12 +282,14 @@ public final class Functions {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return predicate.hashCode();
     }
 
-    @Override public String toString() {
-      return "forPredicate(" + predicate + ")";
+    @Override
+    public String toString() {
+      return "Functions.forPredicate(" + predicate + ")";
     }
 
     private static final long serialVersionUID = 0;
@@ -299,7 +317,8 @@ public final class Functions {
       return value;
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof ConstantFunction) {
         ConstantFunction<?> that = (ConstantFunction<?>) obj;
         return Objects.equal(value, that.value);
@@ -307,12 +326,14 @@ public final class Functions {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return (value == null) ? 0 : value.hashCode();
     }
 
-    @Override public String toString() {
-      return "constant(" + value + ")";
+    @Override
+    public String toString() {
+      return "Functions.constant(" + value + ")";
     }
 
     private static final long serialVersionUID = 0;
@@ -321,7 +342,7 @@ public final class Functions {
   /**
    * Returns a function that always returns the result of invoking {@link Supplier#get} on {@code
    * supplier}, regardless of its input.
-   * 
+   *
    * @since 10.0
    */
   @Beta
@@ -331,33 +352,37 @@ public final class Functions {
 
   /** @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) {
+    @Override
+    public T apply(@Nullable Object input) {
       return supplier.get();
     }
-    
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @Override
+    public int hashCode() {
       return supplier.hashCode();
     }
-    
-    @Override public String toString() {
-      return "forSupplier(" + supplier + ")";
+
+    @Override
+    public String toString() {
+      return "Functions.forSupplier(" + supplier + ")";
     }
-    
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/base/Joiner.java b/guava/src/com/google/common/base/Joiner.java
index 7f4a80a..df78e3b 100644
--- a/guava/src/com/google/common/base/Joiner.java
+++ b/guava/src/com/google/common/base/Joiner.java
@@ -55,18 +55,19 @@ import javax.annotation.Nullable;
  *   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>. 
+ * "https://github.com/google/guava/wiki/StringsExplained#joiner">{@code Joiner}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public class Joiner {
   /**
    * Returns a joiner which automatically places {@code separator} between consecutive elements.
    */
+  @CheckReturnValue
   public static Joiner on(String separator) {
     return new Joiner(separator);
   }
@@ -74,6 +75,7 @@ public class Joiner {
   /**
    * Returns a joiner which automatically places {@code separator} between consecutive elements.
    */
+  @CheckReturnValue
   public static Joiner on(char separator) {
     return new Joiner(String.valueOf(separator));
   }
@@ -127,7 +129,7 @@ public class Joiner {
    */
   public final <A extends Appendable> A appendTo(
       A appendable, @Nullable Object first, @Nullable Object second, Object... rest)
-          throws IOException {
+      throws IOException {
     return appendTo(appendable, iterable(first, second, rest));
   }
 
@@ -179,6 +181,7 @@ public class Joiner {
    * Returns a string containing the string representation of each of {@code parts}, using the
    * previously configured separator between each.
    */
+  @CheckReturnValue
   public final String join(Iterable<?> parts) {
     return join(parts.iterator());
   }
@@ -189,6 +192,7 @@ public class Joiner {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public final String join(Iterator<?> parts) {
     return appendTo(new StringBuilder(), parts).toString();
   }
@@ -197,6 +201,7 @@ public class Joiner {
    * Returns a string containing the string representation of each of {@code parts}, using the
    * previously configured separator between each.
    */
+  @CheckReturnValue
   public final String join(Object[] parts) {
     return join(Arrays.asList(parts));
   }
@@ -205,6 +210,7 @@ public class Joiner {
    * Returns a string containing the string representation of each argument, using the previously
    * configured separator between each.
    */
+  @CheckReturnValue
   public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
     return join(iterable(first, second, rest));
   }
@@ -217,15 +223,18 @@ public class Joiner {
   public Joiner useForNull(final String nullText) {
     checkNotNull(nullText);
     return new Joiner(this) {
-      @Override CharSequence toString(@Nullable Object part) {
+      @Override
+      CharSequence toString(@Nullable Object part) {
         return (part == null) ? nullText : Joiner.this.toString(part);
       }
 
-      @Override public Joiner useForNull(String nullText) {
+      @Override
+      public Joiner useForNull(String nullText) {
         throw new UnsupportedOperationException("already specified useForNull");
       }
 
-      @Override public Joiner skipNulls() {
+      @Override
+      public Joiner skipNulls() {
         throw new UnsupportedOperationException("already specified useForNull");
       }
     };
@@ -238,8 +247,8 @@ public class Joiner {
   @CheckReturnValue
   public Joiner skipNulls() {
     return new Joiner(this) {
-      @Override public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts)
-          throws IOException {
+      @Override
+      public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
         checkNotNull(appendable, "appendable");
         checkNotNull(parts, "parts");
         while (parts.hasNext()) {
@@ -259,11 +268,13 @@ public class Joiner {
         return appendable;
       }
 
-      @Override public Joiner useForNull(String nullText) {
+      @Override
+      public Joiner useForNull(String nullText) {
         throw new UnsupportedOperationException("already specified skipNulls");
       }
 
-      @Override public MapJoiner withKeyValueSeparator(String kvs) {
+      @Override
+      public MapJoiner withKeyValueSeparator(String kvs) {
         throw new UnsupportedOperationException("can't use .skipNulls() with maps");
       }
     };
@@ -294,7 +305,7 @@ public class Joiner {
    *     key1=[A, B]&key2=C}.
    * </ul>
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static final class MapJoiner {
     private final Joiner joiner;
@@ -326,6 +337,7 @@ public class Joiner {
      * Returns a string containing the string representation of each entry of {@code map}, using the
      * previously configured separator and key-value separator.
      */
+    @CheckReturnValue
     public String join(Map<?, ?> map) {
       return join(map.entrySet());
     }
@@ -404,6 +416,7 @@ public class Joiner {
      * @since 10.0
      */
     @Beta
+    @CheckReturnValue
     public String join(Iterable<? extends Entry<?, ?>> entries) {
       return join(entries.iterator());
     }
@@ -415,6 +428,7 @@ public class Joiner {
      * @since 11.0
      */
     @Beta
+    @CheckReturnValue
     public String join(Iterator<? extends Entry<?, ?>> entries) {
       return appendTo(new StringBuilder(), entries).toString();
     }
@@ -430,7 +444,7 @@ public class Joiner {
   }
 
   CharSequence toString(Object part) {
-    checkNotNull(part);  // checkNotNull for GWT (do not optimize).
+    checkNotNull(part); // checkNotNull for GWT (do not optimize).
     return (part instanceof CharSequence) ? (CharSequence) part : part.toString();
   }
 
@@ -438,11 +452,13 @@ public class Joiner {
       final Object first, final Object second, final Object[] rest) {
     checkNotNull(rest);
     return new AbstractList<Object>() {
-      @Override public int size() {
+      @Override
+      public int size() {
         return rest.length + 2;
       }
 
-      @Override public Object get(int index) {
+      @Override
+      public Object get(int index) {
         switch (index) {
           case 0:
             return first;
diff --git a/guava/src/com/google/common/base/MoreObjects.java b/guava/src/com/google/common/base/MoreObjects.java
index ef4f804..f87a892 100644
--- a/guava/src/com/google/common/base/MoreObjects.java
+++ b/guava/src/com/google/common/base/MoreObjects.java
@@ -20,6 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
 
+import java.util.Arrays;
+
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -27,7 +30,7 @@ import javax.annotation.Nullable;
  * {@link java.util.Objects}.
  *
  * <p>See the Guava User Guide on <a
- * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
+ * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
  * {@code Object} methods with {@code MoreObjects}</a>.
  *
  * @author Laurence Gonsalves
@@ -46,8 +49,9 @@ public final class MoreObjects {
    *
    * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
    * @throws NullPointerException if both {@code first} and {@code second} are null
-   * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}.
+   * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}).
    */
+  @CheckReturnValue
   public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
     return first != null ? first : checkNotNull(second);
   }
@@ -89,10 +93,11 @@ public final class MoreObjects {
    *
    * @param self the object to generate the string for (typically {@code this}), used only for its
    *     class name
-   * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}.
+   * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}).
    */
+  @CheckReturnValue
   public static ToStringHelper toStringHelper(Object self) {
-    return new ToStringHelper(simpleName(self.getClass()));
+    return new ToStringHelper(self.getClass().getSimpleName());
   }
 
   /**
@@ -103,10 +108,11 @@ public final class MoreObjects {
    * <p>Note that in GWT, class names are often obfuscated.
    *
    * @param clazz the {@link Class} of the instance
-   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
+   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
    */
+  @CheckReturnValue
   public static ToStringHelper toStringHelper(Class<?> clazz) {
-    return new ToStringHelper(simpleName(clazz));
+    return new ToStringHelper(clazz.getSimpleName());
   }
 
   /**
@@ -115,40 +121,18 @@ public final class MoreObjects {
    * Object#getClass()}.
    *
    * @param className the name of the instance type
-   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
+   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
    */
+  @CheckReturnValue
   public static ToStringHelper toStringHelper(String className) {
     return new ToStringHelper(className);
   }
 
   /**
-   * {@link Class#getSimpleName()} is not GWT compatible yet, so we
-   * provide our own implementation.
-   */
-  // Package-private so Objects can call it.
-  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);
-  }
-
-  /**
    * Support class for {@link MoreObjects#toStringHelper}.
    *
    * @author Jason Lee
-   * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}.
+   * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}).
    */
   public static final class ToStringHelper {
     private final String className;
@@ -168,7 +152,7 @@ public final class MoreObjects {
      * properties with null value. The order of calling this method, relative
      * to the {@code add()}/{@code addValue()} methods, is not significant.
      *
-     * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}).
      */
     public ToStringHelper omitNullValues() {
       omitNullValues = true;
@@ -189,7 +173,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, boolean value) {
       return addHolder(name, String.valueOf(value));
@@ -199,7 +183,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, char value) {
       return addHolder(name, String.valueOf(value));
@@ -209,7 +193,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, double value) {
       return addHolder(name, String.valueOf(value));
@@ -219,7 +203,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, float value) {
       return addHolder(name, String.valueOf(value));
@@ -229,7 +213,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, int value) {
       return addHolder(name, String.valueOf(value));
@@ -239,7 +223,7 @@ public final class MoreObjects {
      * Adds a name/value pair to the formatted output in {@code name=value}
      * format.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
      */
     public ToStringHelper add(String name, long value) {
       return addHolder(name, String.valueOf(value));
@@ -250,8 +234,6 @@ public final class MoreObjects {
      *
      * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
      * and give value a readable name.
-     *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
      */
     public ToStringHelper addValue(@Nullable Object value) {
       return addHolder(value);
@@ -260,12 +242,10 @@ public final class MoreObjects {
     /**
      * Adds an unnamed value to the formatted output.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
-     *
      * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(boolean value) {
       return addHolder(String.valueOf(value));
@@ -277,7 +257,7 @@ public final class MoreObjects {
      * <p>It is strongly encouraged to use {@link #add(String, char)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(char value) {
       return addHolder(String.valueOf(value));
@@ -289,7 +269,7 @@ public final class MoreObjects {
      * <p>It is strongly encouraged to use {@link #add(String, double)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(double value) {
       return addHolder(String.valueOf(value));
@@ -301,7 +281,7 @@ public final class MoreObjects {
      * <p>It is strongly encouraged to use {@link #add(String, float)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(float value) {
       return addHolder(String.valueOf(value));
@@ -313,7 +293,7 @@ public final class MoreObjects {
      * <p>It is strongly encouraged to use {@link #add(String, int)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(int value) {
       return addHolder(String.valueOf(value));
@@ -325,7 +305,7 @@ public final class MoreObjects {
      * <p>It is strongly encouraged to use {@link #add(String, long)} instead
      * and give value a readable name.
      *
-     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
      */
     public ToStringHelper addValue(long value) {
       return addHolder(String.valueOf(value));
@@ -341,22 +321,31 @@ public final class MoreObjects {
      * 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() {
+    @CheckReturnValue
+    @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;
+      StringBuilder builder = new StringBuilder(32).append(className).append('{');
+      for (ValueHolder valueHolder = holderHead.next;
+          valueHolder != null;
           valueHolder = valueHolder.next) {
-        if (!omitNullValuesSnapshot || valueHolder.value != null) {
+        Object value = valueHolder.value;
+        if (!omitNullValuesSnapshot || value != null) {
           builder.append(nextSeparator);
           nextSeparator = ", ";
 
           if (valueHolder.name != null) {
             builder.append(valueHolder.name).append('=');
           }
-          builder.append(valueHolder.value);
+          if (value != null && value.getClass().isArray()) {
+            Object[] objectArray = {value};
+            String arrayString = Arrays.deepToString(objectArray);
+            builder.append(arrayString.substring(1, arrayString.length() - 1));
+          } else {
+            builder.append(value);
+          }
         }
       }
       return builder.append('}').toString();
diff --git a/guava/src/com/google/common/base/Objects.java b/guava/src/com/google/common/base/Objects.java
index 214ac55..62817da 100644
--- a/guava/src/com/google/common/base/Objects.java
+++ b/guava/src/com/google/common/base/Objects.java
@@ -29,11 +29,11 @@ import javax.annotation.Nullable;
  * 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
+ * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
  * {@code Object} methods with {@code Objects}</a>.
  *
  * @author Laurence Gonsalves
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public final class Objects {
@@ -80,6 +80,7 @@ public final class Objects {
    * <p><b>Note for Java 7 and later:</b> This method should be treated as
    * deprecated; use {@link java.util.Objects#hash} instead.
    */
+  @CheckReturnValue
   public static int hashCode(@Nullable Object... objects) {
     return Arrays.hashCode(objects);
   }
@@ -125,9 +126,10 @@ public final class Objects {
    * @deprecated Use {@link MoreObjects#toStringHelper(Object)} instead. This
    *     method is scheduled for removal in June 2016.
    */
+  @CheckReturnValue
   @Deprecated
   public static ToStringHelper toStringHelper(Object self) {
-    return new ToStringHelper(MoreObjects.simpleName(self.getClass()));
+    return new ToStringHelper(self.getClass().getSimpleName());
   }
 
   /**
@@ -142,9 +144,10 @@ public final class Objects {
    * @deprecated Use {@link MoreObjects#toStringHelper(Class)} instead. This
    *     method is scheduled for removal in June 2016.
    */
+  @CheckReturnValue
   @Deprecated
   public static ToStringHelper toStringHelper(Class<?> clazz) {
-    return new ToStringHelper(MoreObjects.simpleName(clazz));
+    return new ToStringHelper(clazz.getSimpleName());
   }
 
   /**
@@ -157,6 +160,7 @@ public final class Objects {
    * @deprecated Use {@link MoreObjects#toStringHelper(String)} instead. This
    *     method is scheduled for removal in June 2016.
    */
+  @CheckReturnValue
   @Deprecated
   public static ToStringHelper toStringHelper(String className) {
     return new ToStringHelper(className);
@@ -181,6 +185,7 @@ public final class Objects {
    * @deprecated Use {@link MoreObjects#firstNonNull} instead. This method is
    *      scheduled for removal in June 2016.
    */
+  @CheckReturnValue
   @Deprecated
   public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
     return MoreObjects.firstNonNull(first, second);
@@ -382,13 +387,14 @@ public final class Objects {
      * 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() {
+    @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;
+      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);
diff --git a/guava/src/com/google/common/base/Optional.java b/guava/src/com/google/common/base/Optional.java
index a0a0425..6c4724b 100644
--- a/guava/src/com/google/common/base/Optional.java
+++ b/guava/src/com/google/common/base/Optional.java
@@ -25,6 +25,7 @@ import java.io.Serializable;
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -47,7 +48,7 @@ import javax.annotation.Nullable;
  *     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">
+ *     <a href="https://github.com/google/guava/wiki/LivingWithNullHostileCollections">
  *     several other approaches to this</a> that should be considered first)
  * </ul>
  *
@@ -58,8 +59,25 @@ import javax.annotation.Nullable;
  * <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><b>Comparison to {@code java.util.Optional} (JDK 8 and higher):</b> A new {@code Optional}
+ * class was added for Java 8. The two classes are extremely similar, but incompatible (they cannot
+ * share a common supertype). <i>All</i> known differences are listed either here or with the
+ * relevant methods below.
+ *
+ * <ul>
+ * <li>This class is serializable; {@code java.util.Optional} is not.
+ * <li>{@code java.util.Optional} has the additional methods {@code ifPresent}, {@code filter},
+ *     {@code flatMap}, and {@code orElseThrow}.
+ * <li>{@code java.util} offers the primitive-specialized versions {@code OptionalInt}, {@code
+ *     OptionalLong} and {@code OptionalDouble}, the use of which is recommended; Guava does not
+ *     have these.
+ * </ul>
+ *
+ * <p><b>There are no plans to deprecate this class in the foreseeable future.</b> However, we do
+ * gently recommend that you prefer the new, standard Java class whenever possible.
+ *
  * <p>See the Guava User Guide article on <a
- * href="http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional">
+ * href="https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained#optional">
  * using {@code Optional}</a>.
  *
  * @param <T> the type of instance that can be contained. {@code Optional} is naturally
@@ -69,17 +87,26 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  * @since 10.0
  */
+ at CheckReturnValue
 @GwtCompatible(serializable = true)
 public abstract class Optional<T> implements Serializable {
   /**
    * Returns an {@code Optional} instance with no contained reference.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+   * {@code Optional.empty}.
    */
   public static <T> Optional<T> absent() {
     return Absent.withType();
   }
 
   /**
-   * Returns an {@code Optional} instance containing the given non-null reference.
+   * Returns an {@code Optional} instance containing the given non-null reference. To have {@code
+   * null} treated as {@link #absent}, use {@link #fromNullable} instead.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
+   *
+   * @throws NullPointerException if {@code reference} is null
    */
   public static <T> Optional<T> of(T reference) {
     return new Present<T>(checkNotNull(reference));
@@ -88,6 +115,9 @@ public abstract class Optional<T> implements Serializable {
   /**
    * If {@code nullableReference} is non-null, returns an {@code Optional} instance containing that
    * reference; otherwise returns {@link Optional#absent}.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+   * {@code Optional.ofNullable}.
    */
   public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
     return (nullableReference == null)
@@ -99,6 +129,8 @@ public abstract class Optional<T> implements Serializable {
 
   /**
    * Returns {@code true} if this holder contains a (non-null) instance.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
    */
   public abstract boolean isPresent();
 
@@ -106,8 +138,13 @@ public abstract class Optional<T> implements Serializable {
    * Returns the contained instance, which must be present. If the instance might be
    * absent, use {@link #or(Object)} or {@link #orNull} instead.
    *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> when the value is absent, this method
+   * throws {@link IllegalStateException}, whereas the Java 8 counterpart throws {@link
+   * NoSuchElementException}.
+   *
    * @throws IllegalStateException if the instance is absent ({@link #isPresent} returns
-   *     {@code false})
+   *     {@code false}); depending on this <i>specific</i> exception type (over the more general
+   *     {@link RuntimeException}) is discouraged
    */
   public abstract T get();
 
@@ -139,20 +176,34 @@ public abstract class Optional<T> implements Serializable {
    *   FluentIterable<? extends Number> numbers = getSomeNumbers();
    *   Optional<Number> first = (Optional) numbers.first();
    *   Number value = first.or(0.5); // fine}</pre>
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+   * {@code Optional.orElse}, but will not accept {@code null} as a {@code defaultValue} ({@link
+   * #orNull} must be used instead). As a result, the value returned by this method is guaranteed
+   * non-null, which is not the case for the {@code java.util} equivalent.
    */
   public abstract T or(T defaultValue);
 
   /**
    * Returns this {@code Optional} if it has a value present; {@code secondChoice}
    * otherwise.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+   * {@code Optional} class; write {@code thisOptional.isPresent() ? thisOptional : secondChoice}
+   * instead.
    */
   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.
+   * Returns the contained instance if it is present; {@code supplier.get()} otherwise.
    *
-   * @throws NullPointerException if the supplier returns {@code null}
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+   * {@code Optional.orElseGet}, except when {@code supplier} returns {@code null}. In this case
+   * this method throws an exception, whereas the Java 8 method returns the {@code null} to the
+   * caller.
+   *
+   * @throws NullPointerException if this optional's value is absent and the supplier returns
+   *     {@code null}
    */
   @Beta
   public abstract T or(Supplier<? extends T> supplier);
@@ -160,6 +211,9 @@ public abstract class Optional<T> implements Serializable {
   /**
    * Returns the contained instance if it is present; {@code null} otherwise. If the
    * instance is known to be present, use {@link #get()} instead.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+   * {@code Optional.orElse(null)}.
    */
   @Nullable
   public abstract T orNull();
@@ -168,17 +222,30 @@ public abstract class Optional<T> implements Serializable {
    * Returns an immutable singleton {@link Set} whose only element is the contained instance
    * if it is present; an empty immutable {@link Set} otherwise.
    *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+   * {@code Optional} class. However, this common usage: <pre>   {@code
+   *
+   *   for (Foo foo : possibleFoo.asSet()) {
+   *     doSomethingWith(foo);
+   *   }}</pre>
+   *
+   * ... can be replaced with: <pre>   {@code
+   *
+   *   possibleFoo.ifPresent(foo -> doSomethingWith(foo));}</pre>
+   *
    * @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.
+   * {@link Optional#absent} is returned.
    *
-   * @throws NullPointerException if the function returns {@code null}
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+   * {@code Optional.map}, except when {@code function} returns {@code null}. In this case this
+   * method throws an exception, whereas the Java 8 method returns {@code Optional.absent()}.
    *
+   * @throws NullPointerException if the function returns {@code null}
    * @since 12.0
    */
   public abstract <V> Optional<V> transform(Function<? super T, V> function);
@@ -188,19 +255,26 @@ public abstract class Optional<T> implements Serializable {
    * 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.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
    */
   @Override
   public abstract boolean equals(@Nullable Object object);
 
   /**
    * Returns a hash code for this instance.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific choice of
+   * hash code unspecified, unlike the Java 8 equivalent.
    */
   @Override
   public abstract int hashCode();
 
   /**
-   * Returns a string representation for this instance. The form of this string
-   * representation is unspecified.
+   * Returns a string representation for this instance.
+   *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific string
+   * representation unspecified, unlike the Java 8 equivalent.
    */
   @Override
   public abstract String toString();
@@ -210,6 +284,10 @@ public abstract class Optional<T> implements Serializable {
    * skipping over occurrences of {@link Optional#absent}. Iterators are unmodifiable and are
    * evaluated lazily.
    *
+   * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+   * {@code Optional} class; use
+   * {@code optionals.stream().filter(Optional::isPresent).map(Optional::get)} instead.
+   *
    * @since 11.0 (generics widened in 13.0)
    */
   @Beta
diff --git a/guava/src/com/google/common/base/PairwiseEquivalence.java b/guava/src/com/google/common/base/PairwiseEquivalence.java
index 23ab539..d409d24 100644
--- a/guava/src/com/google/common/base/PairwiseEquivalence.java
+++ b/guava/src/com/google/common/base/PairwiseEquivalence.java
@@ -24,8 +24,7 @@ import java.util.Iterator;
 import javax.annotation.Nullable;
 
 @GwtCompatible(serializable = true)
-final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>>
-    implements Serializable {
+final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>> implements Serializable {
 
   final Equivalence<? super T> elementEquivalence;
 
diff --git a/guava/src/com/google/common/base/Preconditions.java b/guava/src/com/google/common/base/Preconditions.java
index bd84f05..a27205f 100644
--- a/guava/src/com/google/common/base/Preconditions.java
+++ b/guava/src/com/google/common/base/Preconditions.java
@@ -69,7 +69,7 @@ import javax.annotation.Nullable;
  * <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
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
  * failures explained</a> in the Guava User Guide for more advice.
  *
  * <h3>{@code java.util.Objects.requireNonNull()}</h3>
@@ -87,11 +87,11 @@ import javax.annotation.Nullable;
  * <h3>More information</h3>
  *
  * <p>See the Guava User Guide on
- * <a href="http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained">using {@code
+ * <a href="https://github.com/google/guava/wiki/PreconditionsExplained">using {@code
  * Preconditions}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public final class Preconditions {
@@ -138,7 +138,8 @@ public final class Preconditions {
    * @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,
+  public static void checkArgument(
+      boolean expression,
       @Nullable String errorMessageTemplate,
       @Nullable Object... errorMessageArgs) {
     if (!expression) {
@@ -190,7 +191,8 @@ public final class Preconditions {
    * @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,
+  public static void checkState(
+      boolean expression,
       @Nullable String errorMessageTemplate,
       @Nullable Object... errorMessageArgs) {
     if (!expression) {
@@ -242,9 +244,8 @@ public final class Preconditions {
    * @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) {
+  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));
@@ -303,8 +304,7 @@ public final class Preconditions {
    * @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) {
+  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));
diff --git a/guava/src/com/google/common/base/Predicate.java b/guava/src/com/google/common/base/Predicate.java
index 7345742..43defb8 100644
--- a/guava/src/com/google/common/base/Predicate.java
+++ b/guava/src/com/google/common/base/Predicate.java
@@ -26,11 +26,11 @@ import javax.annotation.Nullable;
  * <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
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
  * Predicate}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface Predicate<T> {
diff --git a/guava/src/com/google/common/base/Predicates.java b/guava/src/com/google/common/base/Predicates.java
index ba5fe1f..67c04cf 100644
--- a/guava/src/com/google/common/base/Predicates.java
+++ b/guava/src/com/google/common/base/Predicates.java
@@ -29,6 +29,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.regex.Pattern;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -38,12 +39,13 @@ import javax.annotation.Nullable;
  * serializable parameters.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the
  * use of {@code Predicate}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Predicates {
   private Predicates() {}
@@ -102,8 +104,7 @@ public final class Predicates {
    * components} is empty, the returned predicate will always evaluate to {@code
    * true}.
    */
-  public static <T> Predicate<T> and(
-      Iterable<? extends Predicate<? super T>> components) {
+  public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
     return new AndPredicate<T>(defensiveCopy(components));
   }
 
@@ -126,10 +127,8 @@ public final class Predicates {
    * 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)));
+  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)));
   }
 
   /**
@@ -141,8 +140,7 @@ public final class Predicates {
    * components} is empty, the returned predicate will always evaluate to {@code
    * false}.
    */
-  public static <T> Predicate<T> or(
-      Iterable<? extends Predicate<? super T>> components) {
+  public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
     return new OrPredicate<T>(defensiveCopy(components));
   }
 
@@ -165,10 +163,8 @@ public final class Predicates {
    * 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)));
+  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)));
   }
 
   /**
@@ -176,9 +172,7 @@ public final class Predicates {
    * 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);
+    return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
   }
 
   /**
@@ -275,37 +269,49 @@ public final class Predicates {
   enum ObjectPredicate implements Predicate<Object> {
     /** @see Predicates#alwaysTrue() */
     ALWAYS_TRUE {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return true;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.alwaysTrue()";
       }
     },
     /** @see Predicates#alwaysFalse() */
     ALWAYS_FALSE {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return false;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.alwaysFalse()";
       }
     },
     /** @see Predicates#isNull() */
     IS_NULL {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return o == null;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.isNull()";
       }
     },
     /** @see Predicates#notNull() */
     NOT_NULL {
-      @Override public boolean apply(@Nullable Object o) {
+      @Override
+      public boolean apply(@Nullable Object o) {
         return o != null;
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return "Predicates.notNull()";
       }
     };
@@ -323,23 +329,31 @@ public final class Predicates {
     NotPredicate(Predicate<T> predicate) {
       this.predicate = checkNotNull(predicate);
     }
+
     @Override
     public boolean apply(@Nullable T t) {
       return !predicate.apply(t);
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       return ~predicate.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() + ")";
+
+    @Override
+    public String toString() {
+      return "Predicates.not(" + predicate + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -352,6 +366,7 @@ public final class Predicates {
     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).
@@ -362,20 +377,27 @@ public final class Predicates {
       }
       return true;
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       // add a random number to avoid collisions with OrPredicate
       return components.hashCode() + 0x12472c2c;
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @Override
+    public String toString() {
       return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -386,6 +408,7 @@ public final class Predicates {
     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).
@@ -396,106 +419,134 @@ public final class Predicates {
       }
       return false;
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       // add a random number to avoid collisions with AndPredicate
       return components.hashCode() + 0x053c91cf;
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @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 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() {
+
+    @Override
+    public int hashCode() {
       return target.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @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 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() {
+
+    @Override
+    public int hashCode() {
       return clazz.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @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 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() {
+
+    @Override
+    public int hashCode() {
       return clazz.hashCode();
     }
-    @Override public boolean equals(@Nullable Object obj) {
+
+    @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() {
+
+    @Override
+    public String toString() {
       return "Predicates.assignableFrom(" + clazz.getName() + ")";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -518,7 +569,8 @@ public final class Predicates {
       }
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof InPredicate) {
         InPredicate<?> that = (InPredicate<?>) obj;
         return target.equals(that.target);
@@ -526,19 +578,21 @@ public final class Predicates {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return target.hashCode();
     }
 
-    @Override public String toString() {
+    @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 {
+  private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
     final Predicate<B> p;
     final Function<A, ? extends B> f;
 
@@ -552,7 +606,8 @@ public final class Predicates {
       return p.apply(f.apply(a));
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof CompositionPredicate) {
         CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
         return f.equals(that.f) && p.equals(that.p);
@@ -560,12 +615,15 @@ public final class Predicates {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return f.hashCode() ^ p.hashCode();
     }
 
-    @Override public String toString() {
-      return p.toString() + "(" + f.toString() + ")";
+    @Override
+    public String toString() {
+      // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
+      return p + "(" + f + ")";
     }
 
     private static final long serialVersionUID = 0;
@@ -573,8 +631,7 @@ public final class Predicates {
 
   /** @see Predicates#contains(Pattern) */
   @GwtIncompatible("Only used by other GWT-incompatible code.")
-  private static class ContainsPatternPredicate
-      implements Predicate<CharSequence>, Serializable {
+  private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
     final Pattern pattern;
 
     ContainsPatternPredicate(Pattern pattern) {
@@ -586,14 +643,16 @@ public final class Predicates {
       return pattern.matcher(t).find();
     }
 
-    @Override public int hashCode() {
+    @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) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof ContainsPatternPredicate) {
         ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
 
@@ -605,7 +664,8 @@ public final class Predicates {
       return false;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       String patternString = Objects.toStringHelper(pattern)
           .add("pattern", pattern.pattern())
           .add("pattern.flags", pattern.flags())
@@ -618,14 +678,14 @@ public final class Predicates {
 
   /** @see Predicates#containsPattern(String) */
   @GwtIncompatible("Only used by other GWT-incompatible code.")
-  private static class ContainsPatternFromStringPredicate
-      extends ContainsPatternPredicate {
+  private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
 
     ContainsPatternFromStringPredicate(String string) {
       super(Pattern.compile(string));
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Predicates.containsPattern(" + pattern.pattern() + ")";
     }
 
diff --git a/guava/src/com/google/common/base/Present.java b/guava/src/com/google/common/base/Present.java
index bcde922..b5103b7 100644
--- a/guava/src/com/google/common/base/Present.java
+++ b/guava/src/com/google/common/base/Present.java
@@ -36,43 +36,54 @@ final class Present<T> extends Optional<T> {
     this.reference = reference;
   }
 
-  @Override public boolean isPresent() {
+  @Override
+  public boolean isPresent() {
     return true;
   }
 
-  @Override public T get() {
+  @Override
+  public T get() {
     return reference;
   }
 
-  @Override public T or(T defaultValue) {
+  @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) {
+  @Override
+  public Optional<T> or(Optional<? extends T> secondChoice) {
     checkNotNull(secondChoice);
     return this;
   }
 
-  @Override public T or(Supplier<? extends T> supplier) {
+  @Override
+  public T or(Supplier<? extends T> supplier) {
     checkNotNull(supplier);
     return reference;
   }
 
-  @Override public T orNull() {
+  @Override
+  public T orNull() {
     return reference;
   }
 
-  @Override public Set<T> asSet() {
+  @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 <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) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof Present) {
       Present<?> other = (Present<?>) object;
       return reference.equals(other.reference);
@@ -80,11 +91,13 @@ final class Present<T> extends Optional<T> {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return 0x598df91c + reference.hashCode();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Optional.of(" + reference + ")";
   }
 
diff --git a/guava/src/com/google/common/base/SmallCharMatcher.java b/guava/src/com/google/common/base/SmallCharMatcher.java
index efd173d..2bea0eb 100644
--- a/guava/src/com/google/common/base/SmallCharMatcher.java
+++ b/guava/src/com/google/common/base/SmallCharMatcher.java
@@ -18,7 +18,7 @@ package com.google.common.base;
 
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher.FastMatcher;
+import com.google.common.base.CharMatcher.NamedFastMatcher;
 
 import java.util.BitSet;
 
@@ -29,20 +29,19 @@ import java.util.BitSet;
  * @author Christopher Swenson
  */
 @GwtIncompatible("no precomputation is done in GWT")
-final class SmallCharMatcher extends FastMatcher {
+final class SmallCharMatcher extends NamedFastMatcher {
   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) {
+  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;
 
@@ -68,13 +67,14 @@ final class SmallCharMatcher extends FastMatcher {
   // 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) {
+  /**
+   * 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;
     }
diff --git a/guava/src/com/google/common/base/Splitter.java b/guava/src/com/google/common/base/Splitter.java
index ce0fc01..6c45952 100644
--- a/guava/src/com/google/common/base/Splitter.java
+++ b/guava/src/com/google/common/base/Splitter.java
@@ -90,7 +90,7 @@ import javax.annotation.CheckReturnValue;
  * 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">
+ * "https://github.com/google/guava/wiki/StringsExplained#splitter">
  * {@code Splitter}</a>.
  *
  * @author Julien Silland
@@ -110,8 +110,7 @@ public final class Splitter {
     this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
   }
 
-  private Splitter(Strategy strategy, boolean omitEmptyStrings,
-      CharMatcher trimmer, int limit) {
+  private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
     this.strategy = strategy;
     this.omitEmptyStrings = omitEmptyStrings;
     this.trimmer = trimmer;
@@ -126,6 +125,7 @@ public final class Splitter {
    * @param separator the character to recognize as a separator
    * @return a splitter, with default settings, that recognizes that separator
    */
+  @CheckReturnValue
   public static Splitter on(char separator) {
     return on(CharMatcher.is(separator));
   }
@@ -140,23 +140,27 @@ public final class Splitter {
    *     character is a separator
    * @return a splitter, with default settings, that uses this matcher
    */
+  @CheckReturnValue
   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);
-          }
+    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;
+              @Override
+              int separatorEnd(int separatorPosition) {
+                return separatorPosition + 1;
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -167,36 +171,40 @@ public final class Splitter {
    * @param separator the literal, nonempty string to recognize as a separator
    * @return a splitter, with default settings, that recognizes that separator
    */
+  @CheckReturnValue
   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;
+    checkArgument(separator.length() != 0, "The separator may not be the empty string.");
+    if (separator.length() == 1) {
+      return Splitter.on(separator.charAt(0));
+    }
+    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;
               }
-              return p;
-            }
-            return -1;
-          }
 
-          @Override public int separatorEnd(int separatorPosition) {
-            return separatorPosition + separator.length();
+              @Override
+              public int separatorEnd(int separatorPosition) {
+                return separatorPosition + separator.length();
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -211,27 +219,33 @@ public final class Splitter {
    * @throws IllegalArgumentException if {@code separatorPattern} matches the
    *     empty string
    */
+  @CheckReturnValue
   @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;
-          }
+    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();
+              @Override
+              public int separatorEnd(int separatorPosition) {
+                return matcher.end();
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -249,6 +263,7 @@ public final class Splitter {
    * @throws IllegalArgumentException if {@code separatorPattern} matches the
    *     empty string
    */
+  @CheckReturnValue
   @GwtIncompatible("java.util.regex")
   public static Splitter onPattern(String separatorPattern) {
     return on(Pattern.compile(separatorPattern));
@@ -273,24 +288,28 @@ public final class Splitter {
    *     pieces
    * @throws IllegalArgumentException if {@code length} is zero or negative
    */
+  @CheckReturnValue
   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);
-          }
+    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;
+              @Override
+              public int separatorEnd(int separatorPosition) {
+                return separatorPosition;
+              }
+            };
           }
-        };
-      }
-    });
+        });
   }
 
   /**
@@ -319,7 +338,8 @@ public final class Splitter {
   /**
    * 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.
+   * The limit defines the maximum number of items returned by the iterator, or
+   * the maximum size of the list returned by {@link #splitToList}.
    *
    * <p>For example,
    * {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
@@ -329,9 +349,9 @@ public final class Splitter {
    * 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"]}.
+   * results in {@code ["a", "b", "c , d"]}.
    *
-   * @param limit the maximum number of items returns
+   * @param limit the maximum number of items returned
    * @return a splitter with the desired configuration
    * @since 9.0
    */
@@ -382,14 +402,18 @@ public final class Splitter {
    * @param sequence the sequence of characters to split
    * @return an iteration over the segments split from the parameter.
    */
+  @CheckReturnValue
   public Iterable<String> split(final CharSequence sequence) {
     checkNotNull(sequence);
 
     return new Iterable<String>() {
-      @Override public Iterator<String> iterator() {
+      @Override
+      public Iterator<String> iterator() {
         return splittingIterator(sequence);
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return Joiner.on(", ")
             .appendTo(new StringBuilder().append('['), this)
             .append(']')
@@ -411,6 +435,7 @@ public final class Splitter {
    * @return an immutable list of the segments split from the parameter
    * @since 15.0
    */
+  @CheckReturnValue
   @Beta
   public List<String> splitToList(CharSequence sequence) {
     checkNotNull(sequence);
@@ -471,8 +496,7 @@ public final class Splitter {
    */
   @Beta
   public static final class MapSplitter {
-    private static final String INVALID_ENTRY_MESSAGE =
-        "Chunk [%s] is not a valid entry";
+    private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
     private final Splitter outerSplitter;
     private final Splitter entrySplitter;
 
@@ -496,6 +520,7 @@ public final class Splitter {
      * @throws IllegalArgumentException if the specified sequence does not split
      *         into valid map entries, or if there are duplicate keys
      */
+    @CheckReturnValue
     public Map<String, String> split(CharSequence sequence) {
       Map<String, String> map = new LinkedHashMap<String, String>();
       for (String entry : outerSplitter.split(sequence)) {
@@ -547,7 +572,8 @@ public final class Splitter {
       this.toSplit = toSplit;
     }
 
-    @Override protected String computeNext() {
+    @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
diff --git a/guava/src/com/google/common/base/StandardSystemProperty.java b/guava/src/com/google/common/base/StandardSystemProperty.java
index a3c1766..2173458 100644
--- a/guava/src/com/google/common/base/StandardSystemProperty.java
+++ b/guava/src/com/google/common/base/StandardSystemProperty.java
@@ -19,6 +19,7 @@ package com.google.common.base;
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtIncompatible;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -29,6 +30,7 @@ import javax.annotation.Nullable;
  */
 @Beta
 @GwtIncompatible("java.lang.System#getProperty")
+ at CheckReturnValue
 public enum StandardSystemProperty {
 
   /** Java Runtime Environment version. */
@@ -140,7 +142,8 @@ public enum StandardSystemProperty {
   /**
    * Returns a string representation of this system property.
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return key() + "=" + value();
   }
 }
diff --git a/guava/src/com/google/common/base/Stopwatch.java b/guava/src/com/google/common/base/Stopwatch.java
index f11fe62..51be949 100644
--- a/guava/src/com/google/common/base/Stopwatch.java
+++ b/guava/src/com/google/common/base/Stopwatch.java
@@ -26,12 +26,14 @@ import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * An object that measures elapsed time in nanoseconds. It is useful to measure
  * elapsed time using this class instead of direct calls to {@link
@@ -71,7 +73,6 @@ import java.util.concurrent.TimeUnit;
  * @author Kevin Bourrillion
  * @since 10.0
  */
- at Beta
 @GwtCompatible(emulated = true)
 public final class Stopwatch {
   private final Ticker ticker;
@@ -85,6 +86,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createUnstarted() {
     return new Stopwatch();
   }
@@ -95,6 +97,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createUnstarted(Ticker ticker) {
     return new Stopwatch(ticker);
   }
@@ -105,6 +108,7 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createStarted() {
     return new Stopwatch().start();
   }
@@ -115,28 +119,15 @@ public final class Stopwatch {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static Stopwatch createStarted(Ticker ticker) {
     return new Stopwatch(ticker).start();
   }
 
-  /**
-   * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
-   * as its time source.
-   *
-   * @deprecated Use {@link Stopwatch#createUnstarted()} instead.
-   */
-  @Deprecated
   Stopwatch() {
-    this(Ticker.systemTicker());
+    this.ticker = Ticker.systemTicker();
   }
 
-  /**
-   * Creates (but does not start) a new stopwatch, using the specified time
-   * source.
-   *
-   * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead.
-   */
-  @Deprecated
   Stopwatch(Ticker ticker) {
     this.ticker = checkNotNull(ticker, "ticker");
   }
@@ -146,6 +137,7 @@ public final class Stopwatch {
    * and {@link #stop()} has not been called since the last call to {@code
    * start()}.
    */
+  @CheckReturnValue
   public boolean isRunning() {
     return isRunning;
   }
@@ -204,6 +196,7 @@ public final class Stopwatch {
    *
    * @since 14.0 (since 10.0 as {@code elapsedTime()})
    */
+  @CheckReturnValue
   public long elapsed(TimeUnit desiredUnit) {
     return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
   }
@@ -212,14 +205,15 @@ public final class Stopwatch {
    * Returns a string representation of the current elapsed time.
    */
   @GwtIncompatible("String.format()")
-  @Override public String toString() {
+  @Override
+  public String toString() {
     long nanos = elapsedNanos();
 
     TimeUnit unit = chooseUnit(nanos);
     double value = (double) nanos / NANOSECONDS.convert(1, unit);
 
     // Too bad this functionality is not exposed as a regular method call
-    return String.format("%.4g %s", value, abbreviate(unit));
+    return String.format(Locale.ROOT, "%.4g %s", value, abbreviate(unit));
   }
 
   private static TimeUnit chooseUnit(long nanos) {
diff --git a/guava/src/com/google/common/base/Strings.java b/guava/src/com/google/common/base/Strings.java
index fa4d0bd..4e4c2f6 100644
--- a/guava/src/com/google/common/base/Strings.java
+++ b/guava/src/com/google/common/base/Strings.java
@@ -24,6 +24,7 @@ import com.google.common.annotations.VisibleForTesting;
 
 import java.util.Formatter;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -33,6 +34,7 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  * @since 3.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Strings {
   private Strings() {}
@@ -96,7 +98,7 @@ public final class Strings {
    * @return the padded string
    */
   public static String padStart(String string, int minLength, char padChar) {
-    checkNotNull(string);  // eager for GWT.
+    checkNotNull(string); // eager for GWT.
     if (string.length() >= minLength) {
       return string;
     }
@@ -128,7 +130,7 @@ public final class Strings {
    * @return the padded string
    */
   public static String padEnd(String string, int minLength, char padChar) {
-    checkNotNull(string);  // eager for GWT.
+    checkNotNull(string); // eager for GWT.
     if (string.length() >= minLength) {
       return string;
     }
@@ -152,7 +154,7 @@ public final class Strings {
    * @throws IllegalArgumentException if {@code count} is negative
    */
   public static String repeat(String string, int count) {
-    checkNotNull(string);  // eager for GWT.
+    checkNotNull(string); // eager for GWT.
 
     if (count <= 1) {
       checkArgument(count >= 0, "invalid count: %s", count);
@@ -164,8 +166,7 @@ public final class Strings {
     final long longSize = (long) len * (long) count;
     final int size = (int) longSize;
     if (size != longSize) {
-      throw new ArrayIndexOutOfBoundsException(
-          "Required array size too large: " + longSize);
+      throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
     }
 
     final char[] array = new char[size];
@@ -215,8 +216,7 @@ public final class Strings {
 
     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)) {
+    while (s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
       s++;
     }
     if (validSurrogatePairAt(a, a.length() - s - 1)
@@ -232,7 +232,8 @@ public final class Strings {
    */
   @VisibleForTesting
   static boolean validSurrogatePairAt(CharSequence string, int index) {
-    return index >= 0 && index <= (string.length() - 2)
+    return index >= 0
+        && index <= (string.length() - 2)
         && Character.isHighSurrogate(string.charAt(index))
         && Character.isLowSurrogate(string.charAt(index + 1));
   }
diff --git a/guava/src/com/google/common/base/Supplier.java b/guava/src/com/google/common/base/Supplier.java
index ab8b908..aca0b32 100644
--- a/guava/src/com/google/common/base/Supplier.java
+++ b/guava/src/com/google/common/base/Supplier.java
@@ -24,7 +24,7 @@ import com.google.common.annotations.GwtCompatible;
  * guarantees are implied by this interface.
  *
  * @author Harry Heymann
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface Supplier<T> {
diff --git a/guava/src/com/google/common/base/Suppliers.java b/guava/src/com/google/common/base/Suppliers.java
index fab3bec..838e64f 100644
--- a/guava/src/com/google/common/base/Suppliers.java
+++ b/guava/src/com/google/common/base/Suppliers.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting;
 import java.io.Serializable;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -33,8 +34,9 @@ import javax.annotation.Nullable;
  *
  * @author Laurence Gonsalves
  * @author Harry Heymann
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Suppliers {
   private Suppliers() {}
@@ -46,15 +48,13 @@ public final class Suppliers {
    * {@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) {
+  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 {
+  private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
     final Function<? super F, T> function;
     final Supplier<F> supplier;
 
@@ -63,11 +63,13 @@ public final class Suppliers {
       this.supplier = supplier;
     }
 
-    @Override public T get() {
+    @Override
+    public T get() {
       return function.apply(supplier.get());
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof SupplierComposition) {
         SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
         return function.equals(that.function) && supplier.equals(that.supplier);
@@ -75,11 +77,13 @@ public final class Suppliers {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(function, supplier);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Suppliers.compose(" + function + ", " + supplier + ")";
     }
 
@@ -92,9 +96,10 @@ public final class Suppliers {
    * {@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>The returned supplier is thread-safe. The delegate's {@code get()}
+   * method will be invoked at most once. 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.
@@ -117,7 +122,8 @@ public final class Suppliers {
       this.delegate = delegate;
     }
 
-    @Override public T get() {
+    @Override
+    public T get() {
       // A 2-field variant of Double Checked Locking.
       if (!initialized) {
         synchronized (this) {
@@ -132,7 +138,8 @@ public final class Suppliers {
       return value;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Suppliers.memoize(" + delegate + ")";
     }
 
@@ -162,22 +169,22 @@ public final class Suppliers {
     return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
   }
 
-  @VisibleForTesting static class ExpiringMemoizingSupplier<T>
-      implements Supplier<T>, Serializable {
+  @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) {
+    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() {
+    @Override
+    public T get() {
       // Another variant of Double Checked Locking.
       //
       // We use two volatile reads.  We could reduce this to one by
@@ -188,7 +195,7 @@ public final class Suppliers {
       long now = Platform.systemNanoTime();
       if (nanos == 0 || now - nanos >= 0) {
         synchronized (this) {
-          if (nanos == expirationNanos) {  // recheck for lost race
+          if (nanos == expirationNanos) { // recheck for lost race
             T t = delegate.get();
             value = t;
             nanos = now + durationNanos;
@@ -202,11 +209,11 @@ public final class Suppliers {
       return value;
     }
 
-    @Override public String toString() {
+    @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)";
+      return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
     }
 
     private static final long serialVersionUID = 0;
@@ -219,19 +226,20 @@ public final class Suppliers {
     return new SupplierOfInstance<T>(instance);
   }
 
-  private static class SupplierOfInstance<T>
-      implements Supplier<T>, Serializable {
+  private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
     final T instance;
 
     SupplierOfInstance(@Nullable T instance) {
       this.instance = instance;
     }
 
-    @Override public T get() {
+    @Override
+    public T get() {
       return instance;
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof SupplierOfInstance) {
         SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
         return Objects.equal(instance, that.instance);
@@ -239,11 +247,13 @@ public final class Suppliers {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(instance);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Suppliers.ofInstance(" + instance + ")";
     }
 
@@ -258,21 +268,22 @@ public final class Suppliers {
     return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
   }
 
-  private static class ThreadSafeSupplier<T>
-      implements Supplier<T>, Serializable {
+  private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
     final Supplier<T> delegate;
 
     ThreadSafeSupplier(Supplier<T> delegate) {
       this.delegate = delegate;
     }
 
-    @Override public T get() {
+    @Override
+    public T get() {
       synchronized (delegate) {
         return delegate.get();
       }
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Suppliers.synchronizedSupplier(" + delegate + ")";
     }
 
@@ -298,11 +309,13 @@ public final class Suppliers {
     INSTANCE;
 
     // Note: This makes T a "pass-through type"
-    @Override public Object apply(Supplier<Object> input) {
+    @Override
+    public Object apply(Supplier<Object> input) {
       return input.get();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Suppliers.supplierFunction()";
     }
   }
diff --git a/guava/src/com/google/common/base/Throwables.java b/guava/src/com/google/common/base/Throwables.java
index 5e4d6ec..04b64bb 100644
--- a/guava/src/com/google/common/base/Throwables.java
+++ b/guava/src/com/google/common/base/Throwables.java
@@ -17,23 +17,29 @@
 package com.google.common.base;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
  * 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>.
+ * "https://github.com/google/guava/wiki/ThrowablesExplained">Throwables</a>.
  *
  * @author Kevin Bourrillion
  * @author Ben Yu
@@ -43,8 +49,8 @@ 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:
+   * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@code
+   * declaredType}.  Example usage:
    * <pre>
    *   try {
    *     someMethodThatCouldThrowAnything();
@@ -66,8 +72,8 @@ public final class Throwables {
   }
 
   /**
-   * Propagates {@code throwable} exactly as-is, if and only if it is an
-   * instance of {@link RuntimeException} or {@link Error}.  Example usage:
+   * 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();
@@ -85,9 +91,8 @@ public final class Throwables {
   }
 
   /**
-   * Propagates {@code throwable} exactly as-is, if and only if it is an
-   * instance of {@link RuntimeException}, {@link Error}, or
-   * {@code declaredType}. Example usage:
+   * 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();
@@ -100,8 +105,7 @@ public final class Throwables {
    * </pre>
    *
    * @param throwable the Throwable to possibly propagate
-   * @param declaredType the single checked exception type declared by the
-   *     calling method
+   * @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 {
@@ -110,35 +114,31 @@ public final class Throwables {
   }
 
   /**
-   * 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
+   * 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
+   * @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 {
+  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.
+   * 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} and 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:
+   * 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 {
@@ -152,8 +152,8 @@ public final class Throwables {
    * </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
+   * @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));
@@ -165,10 +165,10 @@ public final class Throwables {
    * 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());
+   *   assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
    * </pre>
    */
+  @CheckReturnValue
   public static Throwable getRootCause(Throwable throwable) {
     Throwable cause;
     while ((cause = throwable.getCause()) != null) {
@@ -178,23 +178,22 @@ public final class Throwables {
   }
 
   /**
-   * 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.
+   * 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:
+   * <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}
+   * @return an unmodifiable list containing the cause chain starting with {@code throwable}
    */
   @Beta // TODO(kevinb): decide best return type
+  @CheckReturnValue
   public static List<Throwable> getCausalChain(Throwable throwable) {
     checkNotNull(throwable);
     List<Throwable> causes = new ArrayList<Throwable>(4);
@@ -206,15 +205,176 @@ public final class Throwables {
   }
 
   /**
-   * 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()}.
+   * 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()}.
    */
+  @CheckReturnValue
   public static String getStackTraceAsString(Throwable throwable) {
     StringWriter stringWriter = new StringWriter();
     throwable.printStackTrace(new PrintWriter(stringWriter));
     return stringWriter.toString();
   }
+
+  /**
+   * Returns the stack trace of {@code throwable}, possibly providing slower iteration over the full
+   * trace but faster iteration over parts of the trace. Here, "slower" and "faster" are defined in
+   * comparison to the normal way to access the stack trace, {@link Throwable#getStackTrace()
+   * throwable.getStackTrace()}. Note, however, that this method's special implementation is not
+   * available for all platforms and configurations. If that implementation is unavailable, this
+   * method falls back to {@code getStackTrace}. Callers that require the special implementation can
+   * check its availability with {@link #lazyStackTraceIsLazy()}.
+   *
+   * <p>The expected (but not guaranteed) performance of the special implementation differs from
+   * {@code getStackTrace} in one main way: The {@code lazyStackTrace} call itself returns quickly
+   * by delaying the per-stack-frame work until each element is accessed. Roughly speaking:
+   *
+   * <ul>
+   * <li>{@code getStackTrace} takes {@code stackSize} time to return but then negligible time to
+   * retrieve each element of the returned list.
+   * <li>{@code lazyStackTrace} takes negligible time to return but then {@code 1/stackSize} time to
+   * retrieve each element of the returned list (probably slightly more than {@code 1/stackSize}).
+   * </ul>
+   *
+   * <p>Note: The special implementation does not respect calls to {@link Throwable#setStackTrace
+   * throwable.setStackTrace}. Instead, it always reflects the original stack trace from the
+   * exception's creation.
+   *
+   * @since 19.0
+   */
+  // TODO(cpovirk): Say something about the possibility that List access could fail at runtime?
+  @Beta
+  @CheckReturnValue
+  public static List<StackTraceElement> lazyStackTrace(Throwable throwable) {
+    return lazyStackTraceIsLazy()
+        ? jlaStackTrace(throwable)
+        : unmodifiableList(asList(throwable.getStackTrace()));
+  }
+
+  /**
+   * Returns whether {@link #lazyStackTrace} will use the special implementation described in its
+   * documentation.
+   *
+   * @since 19.0
+   */
+  @Beta
+  @CheckReturnValue
+  public static boolean lazyStackTraceIsLazy() {
+    return getStackTraceElementMethod != null & getStackTraceDepthMethod != null;
+  }
+
+  private static List<StackTraceElement> jlaStackTrace(final Throwable t) {
+    checkNotNull(t);
+    /*
+     * TODO(cpovirk): Consider optimizing iterator() to catch IOOBE instead of doing bounds checks.
+     *
+     * TODO(cpovirk): Consider the UnsignedBytes pattern if it performs faster and doesn't cause
+     * AOSP grief.
+     */
+    return new AbstractList<StackTraceElement>() {
+      @Override
+      public StackTraceElement get(int n) {
+        return (StackTraceElement)
+            invokeAccessibleNonThrowingMethod(getStackTraceElementMethod, jla, t, n);
+      }
+
+      @Override
+      public int size() {
+        return (Integer) invokeAccessibleNonThrowingMethod(getStackTraceDepthMethod, jla, t);
+      }
+    };
+  }
+
+  private static Object invokeAccessibleNonThrowingMethod(
+      Method method, Object receiver, Object... params) {
+    try {
+      return method.invoke(receiver, params);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(e);
+    } catch (InvocationTargetException e) {
+      throw propagate(e.getCause());
+    }
+  }
+
+  /** JavaLangAccess class name to load using reflection */
+  private static final String JAVA_LANG_ACCESS_CLASSNAME = "sun.misc.JavaLangAccess";
+
+  /** SharedSecrets class name to load using reflection */
+  @VisibleForTesting static final String SHARED_SECRETS_CLASSNAME = "sun.misc.SharedSecrets";
+
+  /** Access to some fancy internal JVM internals. */
+  @Nullable private static final Object jla = getJLA();
+
+  /**
+   * The "getStackTraceElementMethod" method, only available on some JDKs so we use reflection to
+   * find it when available. When this is null, use the slow way.
+   */
+  @Nullable
+  private static final Method getStackTraceElementMethod = (jla == null) ? null : getGetMethod();
+
+  /**
+   * The "getStackTraceDepth" method, only available on some JDKs so we use reflection to find it
+   * when available. When this is null, use the slow way.
+   */
+  @Nullable
+  private static final Method getStackTraceDepthMethod = (jla == null) ? null : getSizeMethod();
+
+  /**
+   * Returns the JavaLangAccess class that is present in all Sun JDKs. It is not whitelisted for
+   * AppEngine, and not present in non-Sun JDKs.
+   */
+  @Nullable
+  private static Object getJLA() {
+    try {
+      /*
+       * We load sun.misc.* classes using reflection since Android doesn't support these classes and
+       * would result in compilation failure if we directly refer to these classes.
+       */
+      Class<?> sharedSecrets = Class.forName(SHARED_SECRETS_CLASSNAME, false, null);
+      Method langAccess = sharedSecrets.getMethod("getJavaLangAccess");
+      return langAccess.invoke(null);
+    } catch (ThreadDeath death) {
+      throw death;
+    } catch (Throwable t) {
+      /*
+       * This is not one of AppEngine's whitelisted classes, so even in Sun JDKs, this can fail with
+       * a NoClassDefFoundError. Other apps might deny access to sun.misc packages.
+       */
+      return null;
+    }
+  }
+
+  /**
+   * Returns the Method that can be used to resolve an individual StackTraceElement, or null if that
+   * method cannot be found (it is only to be found in fairly recent JDKs).
+   */
+  @Nullable
+  private static Method getGetMethod() {
+    return getJlaMethod("getStackTraceElement", Throwable.class, int.class);
+  }
+
+  /**
+   * Returns the Method that can be used to return the size of a stack, or null if that method
+   * cannot be found (it is only to be found in fairly recent JDKs).
+   */
+  @Nullable
+  private static Method getSizeMethod() {
+    return getJlaMethod("getStackTraceDepth", Throwable.class);
+  }
+
+  @Nullable
+  private static Method getJlaMethod(String name, Class<?>... parameterTypes) throws ThreadDeath {
+    try {
+      return Class.forName(JAVA_LANG_ACCESS_CLASSNAME, false, null).getMethod(name, parameterTypes);
+    } catch (ThreadDeath death) {
+      throw death;
+    } catch (Throwable t) {
+      /*
+       * Either the JavaLangAccess class itself is not found, or the method is not supported on the
+       * JVM.
+       */
+      return null;
+    }
+  }
 }
diff --git a/guava/src/com/google/common/base/Ticker.java b/guava/src/com/google/common/base/Ticker.java
index 6c34aef..670163b 100644
--- a/guava/src/com/google/common/base/Ticker.java
+++ b/guava/src/com/google/common/base/Ticker.java
@@ -19,6 +19,8 @@ package com.google.common.base;
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * 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
@@ -28,7 +30,7 @@ import com.google.common.annotations.GwtCompatible;
  *
  * @author Kevin Bourrillion
  * @since 10.0
- *     (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ *     (<a href="https://github.com/google/guava/wiki/Compatibility"
  *     >mostly source-compatible</a> since 9.0)
  */
 @Beta
@@ -50,14 +52,16 @@ public abstract class Ticker {
    *
    * @since 10.0
    */
+  @CheckReturnValue
   public static Ticker systemTicker() {
     return SYSTEM_TICKER;
   }
 
-  private static final Ticker SYSTEM_TICKER = new Ticker() {
-    @Override
-    public long read() {
-      return Platform.systemNanoTime();
-    }
-  };
+  private static final Ticker SYSTEM_TICKER =
+      new Ticker() {
+        @Override
+        public long read() {
+          return Platform.systemNanoTime();
+        }
+      };
 }
diff --git a/guava/src/com/google/common/base/Utf8.java b/guava/src/com/google/common/base/Utf8.java
index 5a333e1..106491e 100644
--- a/guava/src/com/google/common/base/Utf8.java
+++ b/guava/src/com/google/common/base/Utf8.java
@@ -15,10 +15,14 @@
 package com.google.common.base;
 
 import static com.google.common.base.Preconditions.checkPositionIndexes;
+import static java.lang.Character.MAX_SURROGATE;
+import static java.lang.Character.MIN_SURROGATE;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * 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
@@ -45,6 +49,7 @@ public final class Utf8 {
    * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
    *     surrogates)
    */
+  @CheckReturnValue
   public static int encodedLength(CharSequence sequence) {
     // Warning to maintainers: this implementation is highly optimized.
     int utf16Length = sequence.length();
@@ -60,7 +65,7 @@ public final class Utf8 {
     for (; i < utf16Length; i++) {
       char c = sequence.charAt(i);
       if (c < 0x800) {
-        utf8Length += ((0x7f - c) >>> 31);  // branch free!
+        utf8Length += ((0x7f - c) >>> 31); // branch free!
       } else {
         utf8Length += encodedLengthGeneral(sequence, i);
         break;
@@ -69,8 +74,8 @@ public final class Utf8 {
 
     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)));
+      throw new IllegalArgumentException(
+          "UTF-8 length does not fit in int: " + (utf8Length + (1L << 32)));
     }
     return utf8Length;
   }
@@ -85,11 +90,10 @@ public final class Utf8 {
       } else {
         utf8Length += 2;
         // jdk7+: if (Character.isSurrogate(c)) {
-        if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+        if (MIN_SURROGATE <= c && c <= 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);
+          if (Character.codePointAt(sequence, i) == c) {
+            throw new IllegalArgumentException(unpairedSurrogateMsg(i));
           }
           i++;
         }
@@ -108,6 +112,7 @@ public final class Utf8 {
    * <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.
    */
+  @CheckReturnValue
   public static boolean isWellFormed(byte[] bytes) {
     return isWellFormed(bytes, 0, bytes.length);
   }
@@ -121,6 +126,7 @@ public final class Utf8 {
    * @param off the offset in the buffer of the first byte to read
    * @param len the number of bytes to read from the buffer
    */
+  @CheckReturnValue
   public static boolean isWellFormed(byte[] bytes, int off, int len) {
     int end = off + len;
     checkPositionIndexes(off, end, bytes.length);
@@ -192,5 +198,9 @@ public final class Utf8 {
     }
   }
 
+  private static String unpairedSurrogateMsg(int i) {
+    return "Unpaired surrogate at index " + i;
+  }
+
   private Utf8() {}
 }
diff --git a/guava/src/com/google/common/base/Verify.java b/guava/src/com/google/common/base/Verify.java
index d2c5615..f6d77b4 100644
--- a/guava/src/com/google/common/base/Verify.java
+++ b/guava/src/com/google/common/base/Verify.java
@@ -81,7 +81,7 @@ import javax.annotation.Nullable;
  * <h3>More information</h3>
  *
  * See
- * <a href="http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">Conditional
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
  * failures explained</a> in the Guava User Guide for advice on when this class should be used.
  *
  * @since 17.0
@@ -92,6 +92,8 @@ public final class Verify {
   /**
    * Ensures that {@code expression} is {@code true}, throwing a {@code VerifyException} with no
    * message otherwise.
+   *
+   * @throws VerifyException if {@code expression} is {@code false}
    */
   public static void verify(boolean expression) {
     if (!expression) {
@@ -129,6 +131,7 @@ public final class Verify {
    * message otherwise.
    *
    * @return {@code reference}, guaranteed to be non-null, for convenience
+   * @throws VerifyException if {@code reference} is {@code null}
    */
   public static <T> T verifyNotNull(@Nullable T reference) {
     return verifyNotNull(reference, "expected a non-null reference");
@@ -148,6 +151,7 @@ public final class Verify {
    *     template. Arguments are converted to strings using
    *     {@link String#valueOf(Object)}.
    * @return {@code reference}, guaranteed to be non-null, for convenience
+   * @throws VerifyException if {@code reference} is {@code null}
    */
   public static <T> T verifyNotNull(
       @Nullable T reference,
diff --git a/guava/src/com/google/common/base/VerifyException.java b/guava/src/com/google/common/base/VerifyException.java
index 2354d8e..bbcacd7 100644
--- a/guava/src/com/google/common/base/VerifyException.java
+++ b/guava/src/com/google/common/base/VerifyException.java
@@ -21,7 +21,7 @@ import javax.annotation.Nullable;
 
 /**
  * Exception thrown upon the failure of a
- * <a href="http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">verification
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">verification
  * check</a>, including those performed by the convenience methods of the {@link Verify} class.
  *
  * @since 17.0
@@ -36,4 +36,24 @@ public class VerifyException extends RuntimeException {
   public VerifyException(@Nullable String message) {
     super(message);
   }
+
+  /**
+   * Constructs a {@code VerifyException} with the cause {@code cause} and a message that is
+   * {@code null} if {@code cause} is null, and {@code cause.toString()} otherwise.
+   *
+   * @since 19.0
+   */
+  public VerifyException(@Nullable Throwable cause) {
+    super(cause);
+  }
+
+  /**
+   * Constructs a {@code VerifyException} with the message {@code message} and the cause
+   * {@code cause}.
+   *
+   * @since 19.0
+   */
+  public VerifyException(@Nullable String message, @Nullable Throwable cause) {
+    super(message, cause);
+  }
 }
diff --git a/guava/src/com/google/common/base/internal/Finalizer.java b/guava/src/com/google/common/base/internal/Finalizer.java
index 3191e0f..9469489 100644
--- a/guava/src/com/google/common/base/internal/Finalizer.java
+++ b/guava/src/com/google/common/base/internal/Finalizer.java
@@ -33,9 +33,9 @@ import java.util.logging.Logger;
  * of our published API. It is public so we can access it reflectively across
  * class loaders in secure environments.
  *
- * <p>This class can't depend on other Google Collections code. If we were
+ * <p>This class can't depend on other Guava code. If we were
  * to load this class in the same class loader as the rest of
- * Google Collections, this thread would keep an indirect strong reference
+ * Guava, this thread would keep an indirect strong reference
  * to the class loader and prevent it from being garbage collected. This
  * poses a problem for environments where you want to throw away the class
  * loader. For example, dynamically reloading a web application or unloading
@@ -48,12 +48,10 @@ import java.util.logging.Logger;
  */
 public class Finalizer implements Runnable {
 
-  private static final Logger logger
-      = Logger.getLogger(Finalizer.class.getName());
+  private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
 
   /** Name of FinalizableReference.class. */
-  private static final String FINALIZABLE_REFERENCE
-      = "com.google.common.base.FinalizableReference";
+  private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference";
 
   /**
    * Starts the Finalizer thread. FinalizableReferenceQueue calls this method
@@ -78,8 +76,7 @@ public class Finalizer implements Runnable {
      * collected, at which point, Finalizer can stop running
      */
     if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) {
-      throw new IllegalArgumentException(
-          "Expected " + FINALIZABLE_REFERENCE + ".");
+      throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + ".");
     }
 
     Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference);
@@ -92,8 +89,10 @@ public class Finalizer implements Runnable {
         inheritableThreadLocals.set(thread, null);
       }
     } catch (Throwable t) {
-      logger.log(Level.INFO, "Failed to clear thread local values inherited"
-          + " by reference finalizer thread.", t);
+      logger.log(
+          Level.INFO,
+          "Failed to clear thread local values inherited by reference finalizer thread.",
+          t);
     }
 
     thread.start();
@@ -103,8 +102,7 @@ public class Finalizer implements Runnable {
   private final PhantomReference<Object> frqReference;
   private final ReferenceQueue<Object> queue;
 
-  private static final Field inheritableThreadLocals
-      = getInheritableThreadLocalsField();
+  private static final Field inheritableThreadLocals = getInheritableThreadLocalsField();
 
   /** Constructs a new finalizer thread. */
   private Finalizer(
@@ -113,8 +111,8 @@ public class Finalizer implements Runnable {
       PhantomReference<Object> frqReference) {
     this.queue = queue;
 
-    this.finalizableReferenceClassReference
-        = new WeakReference<Class<?>>(finalizableReferenceClass);
+    this.finalizableReferenceClassReference =
+        new WeakReference<Class<?>>(finalizableReferenceClass);
 
     // Keep track of the FRQ that started us so we know when to stop.
     this.frqReference = frqReference;
@@ -131,7 +129,9 @@ public class Finalizer implements Runnable {
         if (!cleanUp(queue.remove())) {
           break;
         }
-      } catch (InterruptedException e) { /* ignore */ }
+      } catch (InterruptedException e) {
+        // ignore
+      }
     }
   }
 
@@ -178,8 +178,7 @@ public class Finalizer implements Runnable {
    * Looks up FinalizableReference.finalizeReferent() method.
    */
   private Method getFinalizeReferentMethod() {
-    Class<?> finalizableReferenceClass
-        = finalizableReferenceClassReference.get();
+    Class<?> finalizableReferenceClass = finalizableReferenceClassReference.get();
     if (finalizableReferenceClass == null) {
       /*
        * FinalizableReference's class loader was reclaimed. While there's a
@@ -200,14 +199,14 @@ public class Finalizer implements Runnable {
 
   public static Field getInheritableThreadLocalsField() {
     try {
-      Field inheritableThreadLocals
-          = Thread.class.getDeclaredField("inheritableThreadLocals");
+      Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals");
       inheritableThreadLocals.setAccessible(true);
       return inheritableThreadLocals;
     } catch (Throwable t) {
-      logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals."
-          + " Reference finalizer threads will inherit thread local"
-          + " values.");
+      logger.log(
+          Level.INFO,
+          "Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will "
+              + "inherit thread local values.");
       return null;
     }
   }
diff --git a/guava/src/com/google/common/cache/AbstractCache.java b/guava/src/com/google/common/cache/AbstractCache.java
index 7e54174..7506cdb 100644
--- a/guava/src/com/google/common/cache/AbstractCache.java
+++ b/guava/src/com/google/common/cache/AbstractCache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
@@ -40,7 +39,6 @@ import java.util.concurrent.ExecutionException;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public abstract class AbstractCache<K, V> implements Cache<K, V> {
 
@@ -142,7 +140,6 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
    *
    * @since 10.0
    */
-  @Beta
   public interface StatsCounter {
     /**
      * Records cache hits. This should be called when a cache request returns a cached value.
@@ -204,7 +201,6 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
    *
    * @since 10.0
    */
-  @Beta
   public static final class SimpleStatsCounter implements StatsCounter {
     private final LongAddable hitCount = LongAddables.create();
     private final LongAddable missCount = LongAddables.create();
diff --git a/guava/src/com/google/common/cache/AbstractLoadingCache.java b/guava/src/com/google/common/cache/AbstractLoadingCache.java
index 6a12c40..ded9f7b 100644
--- a/guava/src/com/google/common/cache/AbstractLoadingCache.java
+++ b/guava/src/com/google/common/cache/AbstractLoadingCache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.UncheckedExecutionException;
@@ -40,7 +39,6 @@ import java.util.concurrent.ExecutionException;
  * @author Charles Fry
  * @since 11.0
  */
- at Beta
 public abstract class AbstractLoadingCache<K, V>
     extends AbstractCache<K, V> implements LoadingCache<K, V> {
 
diff --git a/guava/src/com/google/common/cache/Cache.java b/guava/src/com/google/common/cache/Cache.java
index 9313c5f..344821c 100644
--- a/guava/src/com/google/common/cache/Cache.java
+++ b/guava/src/com/google/common/cache/Cache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ExecutionError;
@@ -37,15 +36,9 @@ import javax.annotation.Nullable;
  * <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
  * by multiple concurrent threads.
  *
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
- *
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public interface Cache<K, V> {
 
diff --git a/guava/src/com/google/common/cache/CacheBuilder.java b/guava/src/com/google/common/cache/CacheBuilder.java
index ba8ed11..4ced26f 100644
--- a/guava/src/com/google/common/cache/CacheBuilder.java
+++ b/guava/src/com/google/common/cache/CacheBuilder.java
@@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Ascii;
@@ -58,6 +57,7 @@ import javax.annotation.CheckReturnValue;
  * <li>accumulation of cache access statistics
  * </ul>
  *
+ *
  * <p>These features are all optional; caches can be created using all or none of them. By default
  * cache instances created by {@code CacheBuilder} will not perform any type of eviction.
  *
@@ -139,7 +139,7 @@ import javax.annotation.CheckReturnValue;
  * <i>not</i> include cache contents, but only configuration.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
+ * "https://github.com/google/guava/wiki/CachesExplained">caching</a> for a higher-level
  * explanation.
  *
  * @param <K> the base key type for all caches created by this builder
@@ -253,7 +253,6 @@ public final class CacheBuilder<K, V> {
    *
    * @since 12.0
    */
-  @Beta
   @GwtIncompatible("To be supported")
   public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
     return spec.toCacheBuilder()
@@ -267,7 +266,6 @@ public final class CacheBuilder<K, V> {
    * @param spec a String in the format specified by {@link CacheBuilderSpec}
    * @since 12.0
    */
-  @Beta
   @GwtIncompatible("To be supported")
   public static CacheBuilder<Object, Object> from(String spec) {
     return from(CacheBuilderSpec.parse(spec));
@@ -674,7 +672,6 @@ public final class CacheBuilder<K, V> {
    * @throws IllegalStateException if the refresh interval was already set
    * @since 11.0
    */
-  @Beta
   @GwtIncompatible("To be supported (synchronously).")
   public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
     checkNotNull(unit);
@@ -689,11 +686,11 @@ public final class CacheBuilder<K, V> {
   }
 
   /**
-   * Specifies a nanosecond-precision time source for use in determining when entries should be
-   * expired. By default, {@link System#nanoTime} is used.
+   * Specifies a nanosecond-precision time source for this cache. By default,
+   * {@link System#nanoTime} is used.
    *
-   * <p>The primary intent of this method is to facilitate testing of caches which have been
-   * configured with {@link #expireAfterWrite} or {@link #expireAfterAccess}.
+   * <p>The primary intent of this method is to facilitate testing of caches with a fake or mock
+   * time source.
    *
    * @throws IllegalStateException if a ticker was already set
    */
@@ -762,7 +759,7 @@ public final class CacheBuilder<K, V> {
     statsCounterSupplier = CACHE_STATS_COUNTER;
     return this;
   }
-  
+
   boolean isRecordingStats() {
     return statsCounterSupplier == CACHE_STATS_COUNTER;
   }
@@ -784,7 +781,7 @@ public final class CacheBuilder<K, V> {
    * @return a cache having the requested features
    */
   public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
-      CacheLoader<? super K1, V1> loader) {
+          CacheLoader<? super K1, V1> loader) {
     checkWeightWithWeigher();
     return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
   }
diff --git a/guava/src/com/google/common/cache/CacheBuilderSpec.java b/guava/src/com/google/common/cache/CacheBuilderSpec.java
index 919366e..979b70b 100644
--- a/guava/src/com/google/common/cache/CacheBuilderSpec.java
+++ b/guava/src/com/google/common/cache/CacheBuilderSpec.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
@@ -28,6 +27,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Nullable;
@@ -79,7 +79,6 @@ import javax.annotation.Nullable;
  * @author Adam Winer
  * @since 12.0
  */
- at Beta
 public final class CacheBuilderSpec {
   /** Parses a single value. */
   private interface ValueParser {
@@ -295,7 +294,7 @@ public final class CacheBuilderSpec {
         parseInteger(spec, Integer.parseInt(value));
       } catch (NumberFormatException e) {
         throw new IllegalArgumentException(
-            String.format("key %s value set to %s, must be integer", key, value), e);
+            format("key %s value set to %s, must be integer", key, value), e);
       }
     }
   }
@@ -311,7 +310,7 @@ public final class CacheBuilderSpec {
         parseLong(spec, Long.parseLong(value));
       } catch (NumberFormatException e) {
         throw new IllegalArgumentException(
-            String.format("key %s value set to %s, must be integer", key, value), e);
+            format("key %s value set to %s, must be integer", key, value), e);
       }
     }
   }
@@ -433,7 +432,7 @@ public final class CacheBuilderSpec {
             break;
           default:
             throw new IllegalArgumentException(
-                String.format("key %s invalid format.  was %s, must end with one of [dDhHmMsS]",
+                format("key %s invalid format.  was %s, must end with one of [dDhHmMsS]",
                     key, value));
         }
 
@@ -441,7 +440,7 @@ public final class CacheBuilderSpec {
         parseDuration(spec, duration, timeUnit);
       } catch (NumberFormatException e) {
         throw new IllegalArgumentException(
-            String.format("key %s value set to %s, must be integer", key, value));
+            format("key %s value set to %s, must be integer", key, value));
       }
     }
   }
@@ -472,4 +471,8 @@ public final class CacheBuilderSpec {
       spec.refreshTimeUnit = unit;
     }
   }
+
+  private static String format(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava/src/com/google/common/cache/CacheLoader.java b/guava/src/com/google/common/cache/CacheLoader.java
index e60dd42..bbdb66d 100644
--- a/guava/src/com/google/common/cache/CacheLoader.java
+++ b/guava/src/com/google/common/cache/CacheLoader.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
@@ -133,7 +132,6 @@ public abstract class CacheLoader<K, V> {
    * @param function the function to be used for loading values; must never return {@code null}
    * @return a cache loader that loads values by passing each key to {@code function}
    */
-  @Beta
   public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
     return new FunctionToCacheLoader<K, V>(function);
   }
@@ -163,7 +161,6 @@ public abstract class CacheLoader<K, V> {
    * @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
    *     key
    */
-  @Beta
   public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
     return new SupplierToCacheLoader<V>(supplier);
   }
@@ -177,7 +174,6 @@ public abstract class CacheLoader<K, V> {
    *
    * @since 17.0
    */
-  @Beta
   @GwtIncompatible("Executor + Futures")
   public static <K, V> CacheLoader<K, V> asyncReloading(final CacheLoader<K, V> loader,
       final Executor executor) {
@@ -225,7 +221,17 @@ public abstract class CacheLoader<K, V> {
     private static final long serialVersionUID = 0;
   }
 
-  static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {}
+  /**
+   * Exception thrown by {@code loadAll()} to indicate that it is not supported.
+   *
+   * @since 19.0
+   */
+  public static final class UnsupportedLoadingOperationException
+      extends UnsupportedOperationException {
+    // Package-private because this should only be thrown by loadAll() when it is not overridden.
+    // Cache implementors may want to catch it but should not need to be able to throw it.
+    UnsupportedLoadingOperationException() {}
+  }
 
   /**
    * Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
diff --git a/guava/src/com/google/common/cache/CacheStats.java b/guava/src/com/google/common/cache/CacheStats.java
index c37c769..cfee32e 100644
--- a/guava/src/com/google/common/cache/CacheStats.java
+++ b/guava/src/com/google/common/cache/CacheStats.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
@@ -47,7 +46,6 @@ import javax.annotation.Nullable;
  * </ul>
  * <li>When an entry is evicted from the cache, {@code evictionCount} is incremented.
  * <li>No stats are modified when a cache entry is invalidated or manually removed.
- * <li>No stats are modified on a query to {@link Cache#getIfPresent}.
  * <li>No stats are modified by operations invoked on the {@linkplain Cache#asMap asMap} view of
  *     the cache.
  * </ul>
@@ -59,7 +57,6 @@ import javax.annotation.Nullable;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public final class CacheStats {
   private final long hitCount;
diff --git a/guava/src/com/google/common/cache/ForwardingCache.java b/guava/src/com/google/common/cache/ForwardingCache.java
index 44fe683..8cbe307 100644
--- a/guava/src/com/google/common/cache/ForwardingCache.java
+++ b/guava/src/com/google/common/cache/ForwardingCache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ForwardingObject;
 import com.google.common.collect.ImmutableMap;
@@ -36,7 +35,6 @@ import javax.annotation.Nullable;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 public abstract class ForwardingCache<K, V> extends ForwardingObject implements Cache<K, V> {
 
   /** Constructor for use by subclasses. */
@@ -126,11 +124,10 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
 
   /**
    * A simplified version of {@link ForwardingCache} where subclasses can pass in an already
-   * constructed {@link Cache} as the delegete.
+   * constructed {@link Cache} as the delegate.
    *
    * @since 10.0
    */
-  @Beta
   public abstract static class SimpleForwardingCache<K, V> extends ForwardingCache<K, V> {
     private final Cache<K, V> delegate;
 
diff --git a/guava/src/com/google/common/cache/ForwardingLoadingCache.java b/guava/src/com/google/common/cache/ForwardingLoadingCache.java
index 93732ff..bac6823 100644
--- a/guava/src/com/google/common/cache/ForwardingLoadingCache.java
+++ b/guava/src/com/google/common/cache/ForwardingLoadingCache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 
@@ -33,7 +32,6 @@ import java.util.concurrent.ExecutionException;
  * @author Charles Fry
  * @since 11.0
  */
- at Beta
 public abstract class ForwardingLoadingCache<K, V>
     extends ForwardingCache<K, V> implements LoadingCache<K, V> {
 
@@ -70,11 +68,10 @@ public abstract class ForwardingLoadingCache<K, V>
 
   /**
    * A simplified version of {@link ForwardingLoadingCache} where subclasses can pass in an already
-   * constructed {@link LoadingCache} as the delegete.
+   * constructed {@link LoadingCache} as the delegate.
    *
    * @since 10.0
    */
-  @Beta
   public abstract static class SimpleForwardingLoadingCache<K, V>
       extends ForwardingLoadingCache<K, V> {
     private final LoadingCache<K, V> delegate;
diff --git a/guava/src/com/google/common/cache/LoadingCache.java b/guava/src/com/google/common/cache/LoadingCache.java
index da08448..c0e6db6 100644
--- a/guava/src/com/google/common/cache/LoadingCache.java
+++ b/guava/src/com/google/common/cache/LoadingCache.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableMap;
@@ -36,15 +35,9 @@ import java.util.concurrent.ExecutionException;
  * <p>When evaluated as a {@link Function}, a cache yields the same result as invoking
  * {@link #getUnchecked}.
  *
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
- *
  * @author Charles Fry
  * @since 11.0
  */
- at Beta
 @GwtCompatible
 public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
 
@@ -67,7 +60,7 @@ public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
    *
    * @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
    *     ExecutionException} is thrown <a
-   *     href="http://code.google.com/p/guava-libraries/wiki/CachesExplained#Interruption">even if
+   *     href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
    *     computation was interrupted by an {@code InterruptedException}</a>.)
    * @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
    *     value
@@ -118,7 +111,7 @@ public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
    *
    * @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
    *     ExecutionException} is thrown <a
-   *     href="http://code.google.com/p/guava-libraries/wiki/CachesExplained#Interruption">even if
+   *     href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
    *     computation was interrupted by an {@code InterruptedException}</a>.)
    * @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
    *     values
diff --git a/guava/src/com/google/common/cache/LocalCache.java b/guava/src/com/google/common/cache/LocalCache.java
index 0c51d06..7b044f5 100644
--- a/guava/src/com/google/common/cache/LocalCache.java
+++ b/guava/src/com/google/common/cache/LocalCache.java
@@ -40,6 +40,7 @@ import com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
 import com.google.common.collect.AbstractSequentialIterator;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.common.primitives.Ints;
@@ -49,6 +50,8 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
 import com.google.common.util.concurrent.UncheckedExecutionException;
 import com.google.common.util.concurrent.Uninterruptibles;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -61,6 +64,7 @@ import java.util.AbstractCollection;
 import java.util.AbstractMap;
 import java.util.AbstractQueue;
 import java.util.AbstractSet;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
@@ -923,7 +927,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     public void setPreviousInWriteQueue(ReferenceEntry<Object, Object> previous) {}
   }
 
-  static abstract class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
+  abstract static class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
     @Override
     public ValueReference<K, V> getValueReference() {
       throw new UnsupportedOperationException();
@@ -2007,7 +2011,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
      * comments.
      */
 
-    final LocalCache<K, V> map;
+    @Weak final LocalCache<K, V> map;
 
     /**
      * The number of live elements in this segment's region.
@@ -2648,22 +2652,33 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
       }
       if (map.removalNotificationQueue != DISCARDING_QUEUE) {
         V value = valueReference.get();
-        RemovalNotification<K, V> notification = new RemovalNotification<K, V>(key, value, cause);
+        RemovalNotification<K, V> notification = RemovalNotification.create(key, value, cause);
         map.removalNotificationQueue.offer(notification);
       }
     }
 
     /**
-     * Performs eviction if the segment is full. This should only be called prior to adding a new
-     * entry and increasing {@code count}.
+     * Performs eviction if the segment is over capacity. Avoids flushing the entire cache if the
+     * newest entry exceeds the maximum weight all on its own.
+     *
+     * @param newest the most recently added entry
      */
     @GuardedBy("this")
-    void evictEntries() {
+    void evictEntries(ReferenceEntry<K, V> newest) {
       if (!map.evictsBySize()) {
         return;
       }
 
       drainRecencyQueue();
+
+      // If the newest entry by itself is too heavy for the segment, don't bother evicting
+      // anything else, just that
+      if (newest.getValueReference().getWeight() > maxSegmentWeight) {
+        if (!removeEntry(newest, newest.getHash(), RemovalCause.SIZE)) {
+          throw new AssertionError();
+        }
+      }
+
       while (totalWeight > maxSegmentWeight) {
         ReferenceEntry<K, V> e = getNextEvictable();
         if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) {
@@ -2858,7 +2873,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
                 newCount = this.count + 1;
               }
               this.count = newCount; // write-volatile
-              evictEntries();
+              evictEntries(e);
               return null;
             } else if (onlyIfAbsent) {
               // Mimic
@@ -2871,7 +2886,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
               ++modCount;
               enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
               setValue(e, key, value, now);
-              evictEntries();
+              evictEntries(e);
               return entryValue;
             }
           }
@@ -2884,7 +2899,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
         table.set(index, newEntry);
         newCount = this.count + 1;
         this.count = newCount; // write-volatile
-        evictEntries();
+        evictEntries(newEntry);
         return null;
       } finally {
         unlock();
@@ -2998,7 +3013,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
               ++modCount;
               enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
               setValue(e, key, newValue, now);
-              evictEntries();
+              evictEntries(e);
               return true;
             } else {
               // Mimic
@@ -3050,7 +3065,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
             ++modCount;
             enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
             setValue(e, key, newValue, now);
-            evictEntries();
+            evictEntries(e);
             return entryValue;
           }
         }
@@ -3144,7 +3159,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
               }
               setValue(e, key, newValue, now);
               this.count = newCount; // write-volatile
-              evictEntries();
+              evictEntries(e);
               return true;
             }
 
@@ -3160,7 +3175,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
         setValue(newEntry, key, newValue, now);
         table.set(index, newEntry);
         this.count = newCount; // write-volatile
-        evictEntries();
+        evictEntries(newEntry);
         return true;
       } finally {
         unlock();
@@ -3520,9 +3535,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     }
 
     public ListenableFuture<V> loadFuture(K key, CacheLoader<? super K, V> loader) {
-      stopwatch.start();
-      V previousValue = oldValue.get();
       try {
+        stopwatch.start();
+        V previousValue = oldValue.get();
         if (previousValue == null) {
           V newValue = loader.load(key);
           return set(newValue) ? futureValue : Futures.immediateFuture(newValue);
@@ -3541,10 +3556,11 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
           }
         });
       } catch (Throwable t) {
+        ListenableFuture<V> result = setException(t) ? futureValue : fullyFailedFuture(t);
         if (t instanceof InterruptedException) {
           Thread.currentThread().interrupt();
         }
-        return setException(t) ? futureValue : fullyFailedFuture(t);
+        return result;
       }
     }
 
@@ -3900,7 +3916,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     Segment<K, V>[] segments = this.segments;
     long sum = 0;
     for (int i = 0; i < segments.length; ++i) {
-      sum += segments[i].count;
+      sum += Math.max(0, segments[i].count); // see https://github.com/google/guava/issues/2108
     }
     return sum;
   }
@@ -4113,17 +4129,16 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     // in time it was present somewhere int the map. This becomes increasingly unlikely as
     // CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible.
     long now = ticker.read();
-    final Segment<K,V>[] segments = this.segments;
+    final Segment<K, V>[] segments = this.segments;
     long last = -1L;
     for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) {
       long sum = 0L;
       for (Segment<K, V> segment : segments) {
         // ensure visibility of most recent completed write
-        @SuppressWarnings({"UnusedDeclaration", "unused"})
-        int c = segment.count; // read-volatile
+        int unused = segment.count; // read-volatile
 
         AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
-        for (int j = 0 ; j < table.length(); j++) {
+        for (int j = 0; j < table.length(); j++) {
           for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) {
             V v = segment.getLiveValue(e, now);
             if (v != null && valueEquivalence.equivalent(value, v)) {
@@ -4435,7 +4450,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
   }
 
   abstract class AbstractCacheSet<T> extends AbstractSet<T> {
-    final ConcurrentMap<?, ?> map;
+    @Weak final ConcurrentMap<?, ?> map;
 
     AbstractCacheSet(ConcurrentMap<?, ?> map) {
       this.map = map;
@@ -4455,8 +4470,29 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     public void clear() {
       map.clear();
     }
+
+    // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+    // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+    @Override
+    public Object[] toArray() {
+      return toArrayList(this).toArray();
+    }
+
+    @Override
+    public <E> E[] toArray(E[] a) {
+      return toArrayList(this).toArray(a);
+    }
+  }
+
+  private static <E> ArrayList<E> toArrayList(Collection<E> c) {
+    // Avoid calling ArrayList(Collection), which may call back into toArray.
+    ArrayList<E> result = new ArrayList<E>(c.size());
+    Iterators.addAll(result, c.iterator());
+    return result;
   }
 
+  @WeakOuter
   final class KeySet extends AbstractCacheSet<K> {
 
     KeySet(ConcurrentMap<?, ?> map) {
@@ -4479,6 +4515,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     }
   }
 
+  @WeakOuter
   final class Values extends AbstractCollection<V> {
     private final ConcurrentMap<?, ?> map;
 
@@ -4507,8 +4544,22 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
     public boolean contains(Object o) {
       return map.containsValue(o);
     }
+
+    // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+    // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+    @Override
+    public Object[] toArray() {
+      return toArrayList(this).toArray();
+    }
+
+    @Override
+    public <E> E[] toArray(E[] a) {
+      return toArrayList(this).toArray(a);
+    }
   }
 
+  @WeakOuter
   final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
 
     EntrySet(ConcurrentMap<?, ?> map) {
diff --git a/guava/src/com/google/common/cache/LongAddables.java b/guava/src/com/google/common/cache/LongAddables.java
index a110c6c..4428d30 100644
--- a/guava/src/com/google/common/cache/LongAddables.java
+++ b/guava/src/com/google/common/cache/LongAddables.java
@@ -34,7 +34,7 @@ final class LongAddables {
   static {
     Supplier<LongAddable> supplier;
     try {
-      new LongAdder();
+      new LongAdder(); // trigger static initialization of the LongAdder class, which may fail
       supplier = new Supplier<LongAddable>() {
         @Override
         public LongAddable get() {
diff --git a/guava/src/com/google/common/cache/RemovalCause.java b/guava/src/com/google/common/cache/RemovalCause.java
index 0be9b5b..29082f0 100644
--- a/guava/src/com/google/common/cache/RemovalCause.java
+++ b/guava/src/com/google/common/cache/RemovalCause.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
 import java.util.Iterator;
@@ -29,7 +28,6 @@ import java.util.concurrent.ConcurrentMap;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public enum RemovalCause {
   /**
diff --git a/guava/src/com/google/common/cache/RemovalListener.java b/guava/src/com/google/common/cache/RemovalListener.java
index 270a7c4..09bd3cf 100644
--- a/guava/src/com/google/common/cache/RemovalListener.java
+++ b/guava/src/com/google/common/cache/RemovalListener.java
@@ -16,7 +16,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
 /**
@@ -36,11 +35,13 @@ import com.google.common.annotations.GwtCompatible;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public interface RemovalListener<K, V> {
   /**
    * Notifies the listener that a removal occurred at some point in the past.
+   *
+   * <p>This does not always signify that the key is now absent from the cache,
+   * as it may have already been re-added.
    */
   // Technically should accept RemovalNotification<? extends K, ? extends V>, but because
   // RemovalNotification is guaranteed covariant, let's make users' lives simpler.
diff --git a/guava/src/com/google/common/cache/RemovalListeners.java b/guava/src/com/google/common/cache/RemovalListeners.java
index dbb9efc..974ef04 100644
--- a/guava/src/com/google/common/cache/RemovalListeners.java
+++ b/guava/src/com/google/common/cache/RemovalListeners.java
@@ -18,8 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.annotations.Beta;
-
 import java.util.concurrent.Executor;
 
 /**
@@ -28,7 +26,6 @@ import java.util.concurrent.Executor;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 public final class RemovalListeners {
 
   private RemovalListeners() {}
diff --git a/guava/src/com/google/common/cache/RemovalNotification.java b/guava/src/com/google/common/cache/RemovalNotification.java
index f6df2f3..7dd9ba4 100644
--- a/guava/src/com/google/common/cache/RemovalNotification.java
+++ b/guava/src/com/google/common/cache/RemovalNotification.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Objects;
 
@@ -37,14 +36,25 @@ import javax.annotation.Nullable;
  * @author Charles Fry
  * @since 10.0
  */
- at Beta
 @GwtCompatible
 public final class RemovalNotification<K, V> implements Entry<K, V> {
   @Nullable private final K key;
   @Nullable private final V value;
   private final RemovalCause cause;
 
-  RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
+  /**
+   * Creates a new {@code RemovalNotification} for the given {@code key}/{@code value} pair, with
+   * the given {@code cause} for the removal. The {@code key} and/or {@code value} may be
+   * {@code null} if they were already garbage collected.
+   *
+   * @since 19.0
+   */
+  public static <K, V> RemovalNotification<K, V> create(
+      @Nullable K key, @Nullable V value, RemovalCause cause) {
+    return new RemovalNotification(key, value, cause);
+  }
+
+  private RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
     this.key = key;
     this.value = value;
     this.cause = checkNotNull(cause);
diff --git a/guava/src/com/google/common/cache/Weigher.java b/guava/src/com/google/common/cache/Weigher.java
index 5720cb8..9ed07d1 100644
--- a/guava/src/com/google/common/cache/Weigher.java
+++ b/guava/src/com/google/common/cache/Weigher.java
@@ -14,7 +14,6 @@
 
 package com.google.common.cache;
 
-import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
 /**
@@ -23,7 +22,6 @@ import com.google.common.annotations.GwtCompatible;
  * @author Charles Fry
  * @since 11.0
  */
- at Beta
 @GwtCompatible
 public interface Weigher<K, V> {
 
diff --git a/guava/src/com/google/common/cache/package-info.java b/guava/src/com/google/common/cache/package-info.java
index ea0297b..878f29e 100644
--- a/guava/src/com/google/common/cache/package-info.java
+++ b/guava/src/com/google/common/cache/package-info.java
@@ -24,7 +24,7 @@
  * {@link com.google.common.cache.CacheStats}.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caches</a>.
+ * "https://github.com/google/guava/wiki/CachesExplained">caches</a>.
  *
  * <p>This package is a part of the open-source
  * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
diff --git a/guava/src/com/google/common/collect/AbstractBiMap.java b/guava/src/com/google/common/collect/AbstractBiMap.java
index 9cefd6c..3ede377 100644
--- a/guava/src/com/google/common/collect/AbstractBiMap.java
+++ b/guava/src/com/google/common/collect/AbstractBiMap.java
@@ -23,6 +23,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -63,7 +64,8 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     inverse = forward;
   }
 
-  @Override protected Map<K, V> delegate() {
+  @Override
+  protected Map<K, V> delegate() {
     return delegate;
   }
 
@@ -101,13 +103,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   // Query Operations (optimizations)
 
-  @Override public boolean containsValue(@Nullable Object value) {
+  @Override
+  public boolean containsValue(@Nullable Object value) {
     return inverse.containsKey(value);
   }
 
   // Modification Operations
 
-  @Override public V put(@Nullable K key, @Nullable V value) {
+  @Override
+  public V put(@Nullable K key, @Nullable V value) {
     return putInBothMaps(key, value, false);
   }
 
@@ -133,15 +137,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     return oldValue;
   }
 
-  private void updateInverseMap(
-      K key, boolean containedKey, V oldValue, V newValue) {
+  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) {
+  @Override
+  public V remove(@Nullable Object key) {
     return containsKey(key) ? removeFromBothMaps(key) : null;
   }
 
@@ -157,13 +161,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   // Bulk Operations
 
-  @Override public void putAll(Map<? extends K, ? extends V> map) {
+  @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() {
+  @Override
+  public void clear() {
     delegate.clear();
     inverse.delegate.clear();
   }
@@ -177,21 +183,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
   private transient Set<K> keySet;
 
-  @Override public Set<K> keySet() {
+  @Override
+  public Set<K> keySet() {
     Set<K> result = keySet;
     return (result == null) ? keySet = new KeySet() : result;
   }
 
+  @WeakOuter
   private class KeySet extends ForwardingSet<K> {
-    @Override protected Set<K> delegate() {
+    @Override
+    protected Set<K> delegate() {
       return delegate.keySet();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       AbstractBiMap.this.clear();
     }
 
-    @Override public boolean remove(Object key) {
+    @Override
+    public boolean remove(Object key) {
       if (!contains(key)) {
         return false;
       }
@@ -199,22 +210,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
       return true;
     }
 
-    @Override public boolean removeAll(Collection<?> keysToRemove) {
+    @Override
+    public boolean removeAll(Collection<?> keysToRemove) {
       return standardRemoveAll(keysToRemove);
     }
 
-    @Override public boolean retainAll(Collection<?> keysToRetain) {
+    @Override
+    public boolean retainAll(Collection<?> keysToRetain) {
       return standardRetainAll(keysToRetain);
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return Maps.keyIterator(entrySet().iterator());
     }
   }
 
   private transient Set<V> valueSet;
 
-  @Override public Set<V> values() {
+  @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.
@@ -223,49 +238,60 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
     return (result == null) ? valueSet = new ValueSet() : result;
   }
 
+  @WeakOuter
   private class ValueSet extends ForwardingSet<V> {
     final Set<V> valuesDelegate = inverse.keySet();
 
-    @Override protected Set<V> delegate() {
+    @Override
+    protected Set<V> delegate() {
       return valuesDelegate;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       return Maps.valueIterator(entrySet().iterator());
     }
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return standardToString();
     }
   }
 
   private transient Set<Entry<K, V>> entrySet;
 
-  @Override public 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;
   }
 
+  @WeakOuter
   private class EntrySet extends ForwardingSet<Entry<K, V>> {
     final Set<Entry<K, V>> esDelegate = delegate.entrySet();
 
-    @Override protected Set<Entry<K, V>> delegate() {
+    @Override
+    protected Set<Entry<K, V>> delegate() {
       return esDelegate;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       AbstractBiMap.this.clear();
     }
 
-    @Override public boolean remove(Object object) {
+    @Override
+    public boolean remove(Object object) {
       if (!esDelegate.contains(object)) {
         return false;
       }
@@ -282,43 +308,47 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
       return true;
     }
 
-    @Override public Iterator<Entry<K, V>> iterator() {
+    @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() {
+        @Override
+        public boolean hasNext() {
           return iterator.hasNext();
         }
 
-        @Override public Entry<K, V> next() {
+        @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() {
+            @Override
+            protected Entry<K, V> delegate() {
               return finalEntry;
             }
 
-            @Override public V setValue(V value) {
+            @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);
+              checkArgument(!containsValue(value), "value already present: %s", value);
               V oldValue = finalEntry.setValue(value);
-              checkState(Objects.equal(value, get(getKey())),
-                  "entry no longer in map");
+              checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
               updateInverseMap(getKey(), true, oldValue, value);
               return oldValue;
             }
           };
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(entry != null);
           V value = entry.getValue();
           iterator.remove();
@@ -329,22 +359,33 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
     // See java.util.Collections.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       return Maps.containsEntryImpl(delegate(), o);
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       return standardRemoveAll(c);
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       return standardRetainAll(c);
     }
   }
@@ -385,8 +426,7 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked") // reading data stored by writeObject
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
       stream.defaultReadObject();
       setInverse((AbstractBiMap<V, K>) stream.readObject());
     }
diff --git a/guava/src/com/google/common/collect/AbstractIndexedListIterator.java b/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
index a58a2a0..6072f2e 100644
--- a/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
+++ b/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
@@ -31,8 +31,7 @@ import java.util.NoSuchElementException;
  * @author Jared Levy
  */
 @GwtCompatible
-abstract class AbstractIndexedListIterator<E>
-    extends UnmodifiableListIterator<E> {
+abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
   private final int size;
   private int position;
 
diff --git a/guava/src/com/google/common/collect/AbstractIterator.java b/guava/src/com/google/common/collect/AbstractIterator.java
index 70492e0..23a3421 100644
--- a/guava/src/com/google/common/collect/AbstractIterator.java
+++ b/guava/src/com/google/common/collect/AbstractIterator.java
@@ -56,7 +56,7 @@ import java.util.NoSuchElementException;
  * <p>This class supports iterators that include null elements.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 // When making changes to this class, please also update the copy at
 // com.google.common.base.AbstractIterator
diff --git a/guava/src/com/google/common/collect/AbstractListMultimap.java b/guava/src/com/google/common/collect/AbstractListMultimap.java
index 3759c93..3cedc6c 100644
--- a/guava/src/com/google/common/collect/AbstractListMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractListMultimap.java
@@ -31,11 +31,11 @@ import javax.annotation.Nullable;
  * List}.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-abstract class AbstractListMultimap<K, V>
-    extends AbstractMapBasedMultimap<K, V> implements ListMultimap<K, V> {
+abstract class AbstractListMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
+    implements ListMultimap<K, V> {
   /**
    * Creates a new multimap that uses the provided map.
    *
@@ -46,7 +46,8 @@ abstract class AbstractListMultimap<K, V>
     super(map);
   }
 
-  @Override abstract List<V> createCollection();
+  @Override
+  abstract List<V> createCollection();
 
   @Override
   List<V> createUnmodifiableEmptyCollection() {
@@ -62,7 +63,8 @@ abstract class AbstractListMultimap<K, V>
    * 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) {
+  @Override
+  public List<V> get(@Nullable K key) {
     return (List<V>) super.get(key);
   }
 
@@ -73,7 +75,8 @@ abstract class AbstractListMultimap<K, V>
    * 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) {
+  @Override
+  public List<V> removeAll(@Nullable Object key) {
     return (List<V>) super.removeAll(key);
   }
 
@@ -84,8 +87,8 @@ abstract class AbstractListMultimap<K, V>
    * 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) {
+  @Override
+  public List<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
     return (List<V>) super.replaceValues(key, values);
   }
 
@@ -96,7 +99,8 @@ abstract class AbstractListMultimap<K, V>
    * @param value value to store in the multimap
    * @return {@code true} always
    */
-  @Override public boolean put(@Nullable K key, @Nullable V value) {
+  @Override
+  public boolean put(@Nullable K key, @Nullable V value) {
     return super.put(key, value);
   }
 
@@ -106,7 +110,8 @@ abstract class AbstractListMultimap<K, V>
    * <p>Though the method signature doesn't say so explicitly, the returned map
    * has {@link List} values.
    */
-  @Override public Map<K, Collection<V>> asMap() {
+  @Override
+  public Map<K, Collection<V>> asMap() {
     return super.asMap();
   }
 
@@ -117,7 +122,8 @@ abstract class AbstractListMultimap<K, V>
    * 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) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return super.equals(object);
   }
 
diff --git a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
index c39faab..fa4eae8 100644
--- a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
@@ -22,7 +22,8 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
@@ -230,7 +231,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return removeAll(key);
     }
 
-    // TODO(user): investigate atomic failure?
+    // TODO(lowasser): investigate atomic failure?
     Collection<V> collection = getOrCreateCollection(key);
     Collection<V> oldValues = createCollection();
     oldValues.addAll(collection);
@@ -327,8 +328,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     }
   }
 
-  private List<V> wrapList(
-      @Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
+  private List<V> wrapList(@Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
     return (list instanceof RandomAccess)
         ? new RandomAccessWrappedList(key, list, ancestor)
         : new WrappedList(key, list, ancestor);
@@ -351,19 +351,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * removeIfEmpty}, and {@code addToMap} methods call the corresponding methods
    * of the full wrapped collection.
    */
+  @WeakOuter
   private class WrappedCollection extends AbstractCollection<V> {
     final K key;
     Collection<V> delegate;
     final WrappedCollection ancestor;
     final Collection<V> ancestorDelegate;
 
-    WrappedCollection(@Nullable K key, Collection<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+    WrappedCollection(
+        @Nullable K key, Collection<V> delegate, @Nullable WrappedCollection ancestor) {
       this.key = key;
       this.delegate = delegate;
       this.ancestor = ancestor;
-      this.ancestorDelegate
-          = (ancestor == null) ? null : ancestor.getDelegate();
+      this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate();
     }
 
     /**
@@ -418,12 +418,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       }
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       refreshIfEmpty();
       return delegate.size();
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -431,12 +433,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return delegate.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       refreshIfEmpty();
       return delegate.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       refreshIfEmpty();
       return delegate.toString();
     }
@@ -445,7 +449,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return delegate;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       refreshIfEmpty();
       return new WrappedIterator();
     }
@@ -499,7 +504,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       }
     }
 
-    @Override public boolean add(V value) {
+    @Override
+    public boolean add(V value) {
       refreshIfEmpty();
       boolean wasEmpty = delegate.isEmpty();
       boolean changed = delegate.add(value);
@@ -518,11 +524,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are provided for better performance.
 
-    @Override public boolean addAll(Collection<? extends V> collection) {
+    @Override
+    public boolean addAll(Collection<? extends V> collection) {
       if (collection.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.addAll(collection);
       if (changed) {
         int newSize = delegate.size();
@@ -534,27 +541,31 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       refreshIfEmpty();
       return delegate.contains(o);
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       refreshIfEmpty();
       return delegate.containsAll(c);
     }
 
-    @Override public void clear() {
-      int oldSize = size();  // calls refreshIfEmpty
+    @Override
+    public void clear() {
+      int oldSize = size(); // calls refreshIfEmpty
       if (oldSize == 0) {
         return;
       }
       delegate.clear();
       totalSize -= oldSize;
-      removeIfEmpty();       // maybe shouldn't be removed if this is a sublist
+      removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       refreshIfEmpty();
       boolean changed = delegate.remove(o);
       if (changed) {
@@ -564,11 +575,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.removeAll(c);
       if (changed) {
         int newSize = delegate.size();
@@ -578,9 +590,10 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return changed;
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       checkNotNull(c);
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = delegate.retainAll(c);
       if (changed) {
         int newSize = delegate.size();
@@ -598,6 +611,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /** Set decorator that stays in sync with the multimap values for a key. */
+  @WeakOuter
   private class WrappedSet extends WrappedCollection implements Set<V> {
     WrappedSet(@Nullable K key, Set<V> delegate) {
       super(key, delegate, null);
@@ -608,7 +622,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
 
       // Guava issue 1013: AbstractSet and most JDK set implementations are
       // susceptible to quadratic removeAll performance on lists;
@@ -626,10 +640,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   /**
    * SortedSet decorator that stays in sync with the multimap values for a key.
    */
-  private class WrappedSortedSet extends WrappedCollection
-      implements SortedSet<V> {
-    WrappedSortedSet(@Nullable K key, SortedSet<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+  @WeakOuter
+  private class WrappedSortedSet extends WrappedCollection implements SortedSet<V> {
+    WrappedSortedSet(@Nullable K key, SortedSet<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
 
@@ -658,7 +671,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> headSet(V toElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().headSet(toElement),
+          getKey(),
+          getSortedSetDelegate().headSet(toElement),
           (getAncestor() == null) ? this : getAncestor());
     }
 
@@ -666,7 +680,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> subSet(V fromElement, V toElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().subSet(fromElement, toElement),
+          getKey(),
+          getSortedSetDelegate().subSet(fromElement, toElement),
           (getAncestor() == null) ? this : getAncestor());
     }
 
@@ -674,12 +689,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     public SortedSet<V> tailSet(V fromElement) {
       refreshIfEmpty();
       return new WrappedSortedSet(
-          getKey(), getSortedSetDelegate().tailSet(fromElement),
+          getKey(),
+          getSortedSetDelegate().tailSet(fromElement),
           (getAncestor() == null) ? this : getAncestor());
     }
   }
 
   @GwtIncompatible("NavigableSet")
+  @WeakOuter
   class WrappedNavigableSet extends WrappedSortedSet implements NavigableSet<V> {
     WrappedNavigableSet(
         @Nullable K key, NavigableSet<V> delegate, @Nullable WrappedCollection ancestor) {
@@ -722,8 +739,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     }
 
     private NavigableSet<V> wrap(NavigableSet<V> wrapped) {
-      return new WrappedNavigableSet(key, wrapped,
-          (getAncestor() == null) ? this : getAncestor());
+      return new WrappedNavigableSet(key, wrapped, (getAncestor() == null) ? this : getAncestor());
     }
 
     @Override
@@ -755,9 +771,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /** List decorator that stays in sync with the multimap values for a key. */
+  @WeakOuter
   private class WrappedList extends WrappedCollection implements List<V> {
-    WrappedList(@Nullable K key, List<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+    WrappedList(@Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
 
@@ -770,7 +786,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       if (c.isEmpty()) {
         return false;
       }
-      int oldSize = size();  // calls refreshIfEmpty
+      int oldSize = size(); // calls refreshIfEmpty
       boolean changed = getListDelegate().addAll(index, c);
       if (changed) {
         int newSize = getDelegate().size();
@@ -841,14 +857,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     @Override
     public List<V> subList(int fromIndex, int toIndex) {
       refreshIfEmpty();
-      return wrapList(getKey(),
+      return wrapList(
+          getKey(),
           getListDelegate().subList(fromIndex, toIndex),
           (getAncestor() == null) ? this : getAncestor());
     }
 
     /** ListIterator decorator. */
-    private class WrappedListIterator extends WrappedIterator
-        implements ListIterator<V> {
+    private class WrappedListIterator extends WrappedIterator implements ListIterator<V> {
       WrappedListIterator() {}
 
       public WrappedListIterator(int index) {
@@ -900,10 +916,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * List decorator that stays in sync with the multimap values for a key and
    * supports rapid random access.
    */
-  private class RandomAccessWrappedList extends WrappedList
-      implements RandomAccess {
-    RandomAccessWrappedList(@Nullable K key, List<V> delegate,
-        @Nullable WrappedCollection ancestor) {
+  private class RandomAccessWrappedList extends WrappedList implements RandomAccess {
+    RandomAccessWrappedList(
+        @Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
       super(key, delegate, ancestor);
     }
   }
@@ -913,17 +928,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     // TreeMultimap uses NavigableKeySet explicitly, but we don't handle that here for GWT
     // compatibility reasons
     return (map instanceof SortedMap)
-        ? new SortedKeySet((SortedMap<K, Collection<V>>) map) : new KeySet(map);
+        ? new SortedKeySet((SortedMap<K, Collection<V>>) map)
+        : new KeySet(map);
   }
 
+  @WeakOuter
   private class KeySet extends Maps.KeySet<K, Collection<V>> {
     KeySet(final Map<K, Collection<V>> subMap) {
       super(subMap);
     }
 
-    @Override public Iterator<K> iterator() {
-      final Iterator<Map.Entry<K, Collection<V>>> entryIterator
-          = map().entrySet().iterator();
+    @Override
+    public Iterator<K> iterator() {
+      final Iterator<Map.Entry<K, Collection<V>>> entryIterator = map().entrySet().iterator();
       return new Iterator<K>() {
         Map.Entry<K, Collection<V>> entry;
 
@@ -931,11 +948,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
         public boolean hasNext() {
           return entryIterator.hasNext();
         }
+
         @Override
         public K next() {
           entry = entryIterator.next();
           return entry.getKey();
         }
+
         @Override
         public void remove() {
           checkRemove(entry != null);
@@ -949,7 +968,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are included for better performance.
 
-    @Override public boolean remove(Object key) {
+    @Override
+    public boolean remove(Object key) {
       int count = 0;
       Collection<V> collection = map().remove(key);
       if (collection != null) {
@@ -965,19 +985,23 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       Iterators.clear(iterator());
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return map().keySet().containsAll(c);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return this == object || this.map().keySet().equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return map().keySet().hashCode();
     }
   }
 
+  @WeakOuter
   private class SortedKeySet extends KeySet implements SortedSet<K> {
 
     SortedKeySet(SortedMap<K, Collection<V>> subMap) {
@@ -1020,6 +1044,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   @GwtIncompatible("NavigableSet")
+  @WeakOuter
   class NavigableKeySet extends SortedKeySet implements NavigableSet<K> {
     NavigableKeySet(NavigableMap<K, Collection<V>> subMap) {
       super(subMap);
@@ -1166,7 +1191,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
    * <p>The iterator generated by the returned collection traverses the values
    * for one key, followed by the values of a second key, and so on.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
@@ -1224,10 +1250,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     // TreeMultimap uses NavigableAsMap explicitly, but we don't handle that here for GWT
     // compatibility reasons
     return (map instanceof SortedMap)
-        ? new SortedAsMap((SortedMap<K, Collection<V>>) map) : new AsMap(map);
+        ? new SortedAsMap((SortedMap<K, Collection<V>>) map)
+        : new AsMap(map);
   }
 
-  private class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+  @WeakOuter
+  private class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
     /**
      * Usually the same as map, but smaller for the headMap(), tailMap(), or
      * subMap() of a SortedAsMap.
@@ -1245,11 +1273,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // The following methods are included for performance.
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return Maps.safeContainsKey(submap, key);
     }
 
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       Collection<V> collection = Maps.safeGet(submap, key);
       if (collection == null) {
         return null;
@@ -1259,7 +1289,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return wrapCollection(k, collection);
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return AbstractMapBasedMultimap.this.keySet();
     }
 
@@ -1268,7 +1299,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return submap.size();
     }
 
-    @Override public Collection<V> remove(Object key) {
+    @Override
+    public Collection<V> remove(Object key) {
       Collection<V> collection = submap.remove(key);
       if (collection == null) {
         return null;
@@ -1281,15 +1313,18 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return output;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return this == object || submap.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return submap.hashCode();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return submap.toString();
     }
 
@@ -1307,23 +1342,27 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
       return Maps.immutableEntry(key, wrapCollection(key, entry.getValue()));
     }
 
+    @WeakOuter
     class AsMapEntries extends Maps.EntrySet<K, Collection<V>> {
       @Override
       Map<K, Collection<V>> map() {
         return AsMap.this;
       }
 
-      @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+      @Override
+      public Iterator<Map.Entry<K, Collection<V>>> iterator() {
         return new AsMapIterator();
       }
 
       // The following methods are included for performance.
 
-      @Override public boolean contains(Object o) {
+      @Override
+      public boolean contains(Object o) {
         return Collections2.safeContains(submap.entrySet(), o);
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (!contains(o)) {
           return false;
         }
@@ -1335,8 +1374,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     /** Iterator across all keys and value collections. */
     class AsMapIterator implements Iterator<Map.Entry<K, Collection<V>>> {
-      final Iterator<Map.Entry<K, Collection<V>>> delegateIterator
-          = submap.entrySet().iterator();
+      final Iterator<Map.Entry<K, Collection<V>>> delegateIterator = submap.entrySet().iterator();
       Collection<V> collection;
 
       @Override
@@ -1360,8 +1398,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
     }
   }
 
-  private class SortedAsMap extends AsMap
-      implements SortedMap<K, Collection<V>> {
+  @WeakOuter
+  private class SortedAsMap extends AsMap implements SortedMap<K, Collection<V>> {
     SortedAsMap(SortedMap<K, Collection<V>> submap) {
       super(submap);
     }
@@ -1404,7 +1442,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
 
     // returns a SortedSet, even though returning a Set would be sufficient to
     // satisfy the SortedMap.keySet() interface
-    @Override public SortedSet<K> keySet() {
+    @Override
+    public SortedSet<K> keySet() {
       SortedSet<K> result = sortedKeySet;
       return (result == null) ? sortedKeySet = createKeySet() : result;
     }
diff --git a/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java b/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
index 6041c09..7bfc37f 100644
--- a/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
@@ -45,8 +45,7 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  */
 @GwtCompatible(emulated = true)
-abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
-    implements Serializable {
+abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
 
   private transient Map<E, Count> backingMap;
 
@@ -84,8 +83,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
 
   @Override
   Iterator<Entry<E>> entryIterator() {
-    final Iterator<Map.Entry<E, Count>> backingEntries =
-        backingMap.entrySet().iterator();
+    final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
     return new Iterator<Multiset.Entry<E>>() {
       Map.Entry<E, Count> toRemove;
 
@@ -103,6 +101,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
           public E getElement() {
             return mapEntry.getKey();
           }
+
           @Override
           public int getCount() {
             Count count = mapEntry.getValue();
@@ -143,11 +142,13 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
 
   // Optimizations - Query Operations
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return Ints.saturatedCast(size);
   }
 
-  @Override public Iterator<E> iterator() {
+  @Override
+  public Iterator<E> iterator() {
     return new MapBasedMultisetIterator();
   }
 
@@ -197,7 +198,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
     }
   }
 
-  @Override public int count(@Nullable Object element) {
+  @Override
+  public int count(@Nullable Object element) {
     Count frequency = Maps.safeGet(backingMap, element);
     return (frequency == null) ? 0 : frequency.get();
   }
@@ -211,12 +213,12 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
    *     {@link Integer#MAX_VALUE} occurrences of {@code element} in this
    *     multiset.
    */
-  @Override public int add(@Nullable E element, int occurrences) {
+  @Override
+  public int add(@Nullable E element, int occurrences) {
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(
-        occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+    checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
     Count frequency = backingMap.get(element);
     int oldCount;
     if (frequency == null) {
@@ -225,20 +227,19 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
     } else {
       oldCount = frequency.get();
       long newCount = (long) oldCount + (long) occurrences;
-      checkArgument(newCount <= Integer.MAX_VALUE,
-          "too many occurrences: %s", newCount);
+      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) {
+  @Override
+  public int remove(@Nullable Object element, int occurrences) {
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(
-        occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+    checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
     Count frequency = backingMap.get(element);
     if (frequency == null) {
       return 0;
@@ -260,7 +261,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
   }
 
   // Roughly a 33% performance improvement over AbstractMultiset.setCount().
-  @Override public int setCount(@Nullable E element, int count) {
+  @Override
+  public int setCount(@Nullable E element, int count) {
     checkNonnegative(count, "count");
 
     Count existingCounter;
@@ -291,7 +293,6 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
 
   // 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");
   }
diff --git a/guava/src/com/google/common/collect/AbstractMapEntry.java b/guava/src/com/google/common/collect/AbstractMapEntry.java
index d790748..198212a 100644
--- a/guava/src/com/google/common/collect/AbstractMapEntry.java
+++ b/guava/src/com/google/common/collect/AbstractMapEntry.java
@@ -43,7 +43,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
     throw new UnsupportedOperationException();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof Entry) {
       Entry<?, ?> that = (Entry<?, ?>) object;
       return Objects.equal(this.getKey(), that.getKey())
@@ -52,7 +53,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     K k = getKey();
     V v = getValue();
     return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
@@ -61,7 +63,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
   /**
    * Returns a string representation of the form {@code {key}={value}}.
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return getKey() + "=" + getValue();
   }
 }
diff --git a/guava/src/com/google/common/collect/AbstractMultimap.java b/guava/src/com/google/common/collect/AbstractMultimap.java
index 9351956..6b94c12 100644
--- a/guava/src/com/google/common/collect/AbstractMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractMultimap.java
@@ -19,6 +19,7 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.AbstractCollection;
 import java.util.Collection;
@@ -31,7 +32,7 @@ import javax.annotation.Nullable;
 
 /**
  * A skeleton {@code Multimap} implementation, not necessarily in terms of a {@code Map}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -57,7 +58,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
     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);
@@ -99,7 +100,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
     putAll(key, values);
     return result;
   }
-  
+
   private transient Collection<Entry<K, V>> entries;
 
   @Override
@@ -107,7 +108,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
     Collection<Entry<K, V>> result = entries;
     return (result == null) ? entries = createEntries() : result;
   }
-  
+
   Collection<Entry<K, V>> createEntries() {
     if (this instanceof SetMultimap) {
       return new EntrySet();
@@ -115,7 +116,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
       return new Entries();
     }
   }
-  
+
+  @WeakOuter
   private class Entries extends Multimaps.Entries<K, V> {
     @Override
     Multimap<K, V> multimap() {
@@ -127,7 +129,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
       return entryIterator();
     }
   }
-  
+
+  @WeakOuter
   private class EntrySet extends Entries implements Set<Entry<K, V>> {
     @Override
     public int hashCode() {
@@ -137,9 +140,9 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
     @Override
     public boolean equals(@Nullable Object obj) {
       return Sets.equalsImpl(this, obj);
-    }    
+    }
   }
-  
+
   abstract Iterator<Entry<K, V>> entryIterator();
 
   private transient Set<K> keySet;
@@ -153,66 +156,72 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
   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();
   }
 
+  @WeakOuter
   class Values extends AbstractCollection<V> {
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       return valueIterator();
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return AbstractMultimap.this.size();
     }
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       return AbstractMultimap.this.containsValue(o);
     }
 
-    @Override public void clear() {
+    @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) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return Multimaps.equalsImpl(this, object);
   }
 
@@ -224,7 +233,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
    *
    * @see Map#hashCode
    */
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return asMap().hashCode();
   }
 
diff --git a/guava/src/com/google/common/collect/AbstractMultiset.java b/guava/src/com/google/common/collect/AbstractMultiset.java
index a271e34..c55373f 100644
--- a/guava/src/com/google/common/collect/AbstractMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractMultiset.java
@@ -20,6 +20,7 @@ import static com.google.common.collect.Multisets.setCountImpl;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.AbstractCollection;
 import java.util.Collection;
@@ -44,23 +45,26 @@ import javax.annotation.Nullable;
  * @author Louis Wasserman
  */
 @GwtCompatible
-abstract class AbstractMultiset<E> extends AbstractCollection<E>
-    implements Multiset<E> {
+abstract class AbstractMultiset<E> extends AbstractCollection<E> implements Multiset<E> {
   // Query Operations
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return Multisets.sizeImpl(this);
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return entrySet().isEmpty();
   }
 
-  @Override public boolean contains(@Nullable Object element) {
+  @Override
+  public boolean contains(@Nullable Object element) {
     return count(element) > 0;
   }
 
-  @Override public Iterator<E> iterator() {
+  @Override
+  public Iterator<E> iterator() {
     return Multisets.iteratorImpl(this);
   }
 
@@ -76,7 +80,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
 
   // Modification Operations
 
-  @Override public boolean add(@Nullable E element) {
+  @Override
+  public boolean add(@Nullable E element) {
     add(element, 1);
     return true;
   }
@@ -86,7 +91,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
     throw new UnsupportedOperationException();
   }
 
-  @Override public boolean remove(@Nullable Object element) {
+  @Override
+  public boolean remove(@Nullable Object element) {
     return remove(element, 1) > 0;
   }
 
@@ -113,19 +119,23 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
    * <p>This implementation is highly efficient when {@code elementsToAdd}
    * is itself a {@link Multiset}.
    */
-  @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
+  @Override
+  public boolean addAll(Collection<? extends E> elementsToAdd) {
     return Multisets.addAllImpl(this, elementsToAdd);
   }
 
-  @Override public boolean removeAll(Collection<?> elementsToRemove) {
+  @Override
+  public boolean removeAll(Collection<?> elementsToRemove) {
     return Multisets.removeAllImpl(this, elementsToRemove);
   }
 
-  @Override public boolean retainAll(Collection<?> elementsToRetain) {
+  @Override
+  public boolean retainAll(Collection<?> elementsToRetain) {
     return Multisets.retainAllImpl(this, elementsToRetain);
   }
 
-  @Override public void clear() {
+  @Override
+  public void clear() {
     Iterators.clear(entryIterator());
   }
 
@@ -150,6 +160,7 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
     return new ElementSet();
   }
 
+  @WeakOuter
   class ElementSet extends Multisets.ElementSet<E> {
     @Override
     Multiset<E> multiset() {
@@ -163,7 +174,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
 
   private transient Set<Entry<E>> entrySet;
 
-  @Override public Set<Entry<E>> entrySet() {
+  @Override
+  public Set<Entry<E>> entrySet() {
     Set<Entry<E>> result = entrySet;
     if (result == null) {
       entrySet = result = createEntrySet();
@@ -171,16 +183,20 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
     return result;
   }
 
+  @WeakOuter
   class EntrySet extends Multisets.EntrySet<E> {
-    @Override Multiset<E> multiset() {
+    @Override
+    Multiset<E> multiset() {
       return AbstractMultiset.this;
     }
 
-    @Override public Iterator<Entry<E>> iterator() {
+    @Override
+    public Iterator<Entry<E>> iterator() {
       return entryIterator();
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return distinctElements();
     }
   }
@@ -198,7 +214,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
    * of the same size and if, for each element, the two multisets have the same
    * count.
    */
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return Multisets.equalsImpl(this, object);
   }
 
@@ -208,7 +225,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
    * <p>This implementation returns the hash code of {@link
    * Multiset#entrySet()}.
    */
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return entrySet().hashCode();
   }
 
@@ -218,7 +236,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
    * <p>This implementation returns the result of invoking {@code toString} on
    * {@link Multiset#entrySet()}.
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return entrySet().toString();
   }
 }
diff --git a/guava/src/com/google/common/collect/AbstractNavigableMap.java b/guava/src/com/google/common/collect/AbstractNavigableMap.java
index f6defe6..cef4859 100644
--- a/guava/src/com/google/common/collect/AbstractNavigableMap.java
+++ b/guava/src/com/google/common/collect/AbstractNavigableMap.java
@@ -16,9 +16,9 @@
 
 package com.google.common.collect;
 
-import java.util.AbstractMap;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+
 import java.util.Iterator;
-import java.util.Map;
 import java.util.NavigableMap;
 import java.util.NavigableSet;
 import java.util.NoSuchElementException;
@@ -29,15 +29,16 @@ 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> {
+abstract class AbstractNavigableMap<K, V> extends IteratorBasedAbstractMap<K, V>
+    implements NavigableMap<K, V> {
 
   @Override
   @Nullable
   public abstract V get(@Nullable Object key);
-  
+
   @Override
   @Nullable
   public Entry<K, V> firstEntry() {
@@ -126,8 +127,6 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
     return Maps.keyOrNull(higherEntry(key));
   }
 
-  abstract Iterator<Entry<K, V>> entryIterator();
-
   abstract Iterator<Entry<K, V>> descendingEntryIterator();
 
   @Override
@@ -156,24 +155,6 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
   }
 
   @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();
   }
@@ -182,7 +163,7 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
   public NavigableMap<K, V> descendingMap() {
     return new DescendingMap();
   }
-  
+
   private final class DescendingMap extends Maps.DescendingMap<K, V> {
     @Override
     NavigableMap<K, V> forward() {
@@ -194,5 +175,4 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
       return descendingEntryIterator();
     }
   }
-
 }
diff --git a/guava/src/com/google/common/collect/AbstractRangeSet.java b/guava/src/com/google/common/collect/AbstractRangeSet.java
index dff3547..19af0e7 100644
--- a/guava/src/com/google/common/collect/AbstractRangeSet.java
+++ b/guava/src/com/google/common/collect/AbstractRangeSet.java
@@ -46,7 +46,7 @@ abstract class AbstractRangeSet<C extends Comparable> implements RangeSet<C> {
   public void remove(Range<C> range) {
     throw new UnsupportedOperationException();
   }
-  
+
   @Override
   public void clear() {
     remove(Range.<C>all());
diff --git a/guava/src/com/google/common/collect/AbstractSequentialIterator.java b/guava/src/com/google/common/collect/AbstractSequentialIterator.java
index c6567f5..b933a57 100644
--- a/guava/src/com/google/common/collect/AbstractSequentialIterator.java
+++ b/guava/src/com/google/common/collect/AbstractSequentialIterator.java
@@ -30,7 +30,7 @@ import javax.annotation.Nullable;
  *
  * <p>Example: <pre>   {@code
  *
- *   Iterator<Integer> powersOfTwo = 
+ *   Iterator<Integer> powersOfTwo =
  *       new AbstractSequentialIterator<Integer>(1) {
  *         protected Integer computeNext(Integer previous) {
  *           return (previous == 1 << 30) ? null : previous * 2;
@@ -41,8 +41,7 @@ import javax.annotation.Nullable;
  * @since 12.0 (in Guava as {@code AbstractLinkedIterator} since 8.0)
  */
 @GwtCompatible
-public abstract class AbstractSequentialIterator<T>
-    extends UnmodifiableIterator<T> {
+public abstract class AbstractSequentialIterator<T> extends UnmodifiableIterator<T> {
   private T nextOrNull;
 
   /**
diff --git a/guava/src/com/google/common/collect/AbstractSetMultimap.java b/guava/src/com/google/common/collect/AbstractSetMultimap.java
index e43d8b1..94b7136 100644
--- a/guava/src/com/google/common/collect/AbstractSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSetMultimap.java
@@ -32,8 +32,8 @@ import javax.annotation.Nullable;
  * @author Jared Levy
  */
 @GwtCompatible
-abstract class AbstractSetMultimap<K, V>
-    extends AbstractMapBasedMultimap<K, V> implements SetMultimap<K, V> {
+abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
+    implements SetMultimap<K, V> {
   /**
    * Creates a new multimap that uses the provided map.
    *
@@ -44,9 +44,11 @@ abstract class AbstractSetMultimap<K, V>
     super(map);
   }
 
-  @Override abstract Set<V> createCollection();
+  @Override
+  abstract Set<V> createCollection();
 
-  @Override Set<V> createUnmodifiableEmptyCollection() {
+  @Override
+  Set<V> createUnmodifiableEmptyCollection() {
     return ImmutableSet.of();
   }
 
@@ -59,7 +61,8 @@ abstract class AbstractSetMultimap<K, V>
    * method returns a {@link Set}, instead of the {@link Collection} specified
    * in the {@link Multimap} interface.
    */
-  @Override public Set<V> get(@Nullable K key) {
+  @Override
+  public Set<V> get(@Nullable K key) {
     return (Set<V>) super.get(key);
   }
 
@@ -70,7 +73,8 @@ abstract class AbstractSetMultimap<K, V>
    * method returns a {@link Set}, instead of the {@link Collection} specified
    * in the {@link Multimap} interface.
    */
-  @Override public Set<Map.Entry<K, V>> entries() {
+  @Override
+  public Set<Map.Entry<K, V>> entries() {
     return (Set<Map.Entry<K, V>>) super.entries();
   }
 
@@ -81,7 +85,8 @@ abstract class AbstractSetMultimap<K, V>
    * method returns a {@link Set}, instead of the {@link Collection} specified
    * in the {@link Multimap} interface.
    */
-  @Override public Set<V> removeAll(@Nullable Object key) {
+  @Override
+  public Set<V> removeAll(@Nullable Object key) {
     return (Set<V>) super.removeAll(key);
   }
 
@@ -94,8 +99,8 @@ abstract class AbstractSetMultimap<K, V>
    *
    * <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) {
+  @Override
+  public Set<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
     return (Set<V>) super.replaceValues(key, values);
   }
 
@@ -105,7 +110,8 @@ abstract class AbstractSetMultimap<K, V>
    * <p>Though the method signature doesn't say so explicitly, the returned map
    * has {@link Set} values.
    */
-  @Override public Map<K, Collection<V>> asMap() {
+  @Override
+  public Map<K, Collection<V>> asMap() {
     return super.asMap();
   }
 
@@ -117,7 +123,8 @@ abstract class AbstractSetMultimap<K, V>
    * @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) {
+  @Override
+  public boolean put(@Nullable K key, @Nullable V value) {
     return super.put(key, value);
   }
 
@@ -128,7 +135,8 @@ abstract class AbstractSetMultimap<K, V>
    * contain the same values. Equality does not depend on the ordering of keys
    * or values.
    */
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return super.equals(object);
   }
 
diff --git a/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java b/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
index c561b87..8cf09dd 100644
--- a/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
@@ -24,11 +24,11 @@ import java.util.SortedSet;
 
 /**
  * Basic implementation of a {@link SortedSetMultimap} with a sorted key set.
- * 
- * This superclass allows {@code TreeMultimap} to override methods to return
+ *
+ * <p>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
@@ -52,5 +52,4 @@ abstract class AbstractSortedKeySortedSetMultimap<K, V> extends AbstractSortedSe
   public SortedSet<K> keySet() {
     return (SortedSet<K>) super.keySet();
   }
-
 }
diff --git a/guava/src/com/google/common/collect/AbstractSortedMultiset.java b/guava/src/com/google/common/collect/AbstractSortedMultiset.java
index 7c277f8..7bec2db 100644
--- a/guava/src/com/google/common/collect/AbstractSortedMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractSortedMultiset.java
@@ -17,6 +17,7 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Comparator;
 import java.util.Iterator;
@@ -99,8 +100,11 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
   }
 
   @Override
-  public SortedMultiset<E> subMultiset(@Nullable E fromElement, BoundType fromBoundType,
-      @Nullable E toElement, BoundType toBoundType) {
+  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);
@@ -122,7 +126,8 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
   }
 
   SortedMultiset<E> createDescendingMultiset() {
-    return new DescendingMultiset<E>() {
+    @WeakOuter
+    class DescendingMultisetImpl extends DescendingMultiset<E> {
       @Override
       SortedMultiset<E> forwardMultiset() {
         return AbstractSortedMultiset.this;
@@ -137,6 +142,7 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
       public Iterator<E> iterator() {
         return descendingIterator();
       }
-    };
+    }
+    return new DescendingMultisetImpl();
   }
 }
diff --git a/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java b/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
index ac74155..9826c5f 100644
--- a/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
@@ -35,8 +35,8 @@ import javax.annotation.Nullable;
  * @author Jared Levy
  */
 @GwtCompatible
-abstract class AbstractSortedSetMultimap<K, V>
-    extends AbstractSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+abstract class AbstractSortedSetMultimap<K, V> extends AbstractSetMultimap<K, V>
+    implements SortedSetMultimap<K, V> {
   /**
    * Creates a new multimap that uses the provided map.
    *
@@ -74,7 +74,8 @@ abstract class AbstractSortedSetMultimap<K, V>
    * 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) {
+  @Override
+  public SortedSet<V> get(@Nullable K key) {
     return (SortedSet<V>) super.get(key);
   }
 
@@ -86,7 +87,8 @@ abstract class AbstractSortedSetMultimap<K, V>
    * 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) {
+  @Override
+  public SortedSet<V> removeAll(@Nullable Object key) {
     return (SortedSet<V>) super.removeAll(key);
   }
 
@@ -100,8 +102,8 @@ abstract class AbstractSortedSetMultimap<K, V>
    *
    * <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) {
+  @Override
+  public SortedSet<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
     return (SortedSet<V>) super.replaceValues(key, values);
   }
 
@@ -119,7 +121,8 @@ abstract class AbstractSortedSetMultimap<K, V>
    * <p>Though the method signature doesn't say so explicitly, the returned map
    * has {@link SortedSet} values.
    */
-  @Override public Map<K, Collection<V>> asMap() {
+  @Override
+  public Map<K, Collection<V>> asMap() {
     return super.asMap();
   }
 
@@ -129,7 +132,8 @@ abstract class AbstractSortedSetMultimap<K, V>
    * Consequently, the values do not follow their natural ordering or the
    * ordering of the value comparator.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
diff --git a/guava/src/com/google/common/collect/AbstractTable.java b/guava/src/com/google/common/collect/AbstractTable.java
index fc979e9..6a68f4c 100644
--- a/guava/src/com/google/common/collect/AbstractTable.java
+++ b/guava/src/com/google/common/collect/AbstractTable.java
@@ -15,6 +15,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.AbstractCollection;
 import java.util.AbstractSet;
@@ -27,7 +28,7 @@ import javax.annotation.Nullable;
 
 /**
  * Skeletal, implementation-agnostic implementation of the {@link Table} interface.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -117,14 +118,16 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
 
   abstract Iterator<Table.Cell<R, C, V>> cellIterator();
 
+  @WeakOuter
   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 row != null
+            && Collections2.safeContains(
+                row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
       }
       return false;
     }
@@ -134,8 +137,9 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
       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 row != null
+            && Collections2.safeRemove(
+                row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
       }
       return false;
     }
@@ -163,11 +167,11 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
     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
@@ -177,6 +181,7 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
     };
   }
 
+  @WeakOuter
   class Values extends AbstractCollection<V> {
     @Override
     public Iterator<V> iterator() {
@@ -199,18 +204,21 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
     }
   }
 
-  @Override public boolean equals(@Nullable Object obj) {
+  @Override
+  public boolean equals(@Nullable Object obj) {
     return Tables.equalsImpl(this, obj);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return cellSet().hashCode();
   }
 
   /**
    * Returns the string representation {@code rowMap().toString()}.
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return rowMap().toString();
   }
 }
diff --git a/guava/src/com/google/common/collect/ArrayListMultimap.java b/guava/src/com/google/common/collect/ArrayListMultimap.java
index 1929ea7..33147ab 100644
--- a/guava/src/com/google/common/collect/ArrayListMultimap.java
+++ b/guava/src/com/google/common/collect/ArrayListMultimap.java
@@ -55,13 +55,13 @@ import java.util.Map;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
@@ -87,8 +87,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> ArrayListMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
   }
 
@@ -98,8 +97,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    *
    * @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) {
+  public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
     return new ArrayListMultimap<K, V>(multimap);
   }
 
@@ -115,10 +113,11 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
   }
 
   private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
-    this(multimap.keySet().size(),
-        (multimap instanceof ArrayListMultimap) ?
-            ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey :
-            DEFAULT_VALUES_PER_KEY);
+    this(
+        multimap.keySet().size(),
+        (multimap instanceof ArrayListMultimap)
+            ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
+            : DEFAULT_VALUES_PER_KEY);
     putAll(multimap);
   }
 
@@ -126,7 +125,8 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
    * Creates a new, empty {@code ArrayList} to hold the collection of values for
    * an arbitrary key.
    */
-  @Override List<V> createCollection() {
+  @Override
+  List<V> createCollection() {
     return new ArrayList<V>(expectedValuesPerKey);
   }
 
@@ -148,17 +148,15 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
   @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 {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
-    expectedValuesPerKey = stream.readInt();
+    expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
     int distinctKeys = Serialization.readCount(stream);
-    Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
+    Map<K, Collection<V>> map = Maps.newHashMap();
     setMap(map);
     Serialization.populateMultimap(this, stream, distinctKeys);
   }
diff --git a/guava/src/com/google/common/collect/ArrayTable.java b/guava/src/com/google/common/collect/ArrayTable.java
index 48ff8e9..c1a9348 100644
--- a/guava/src/com/google/common/collect/ArrayTable.java
+++ b/guava/src/com/google/common/collect/ArrayTable.java
@@ -24,14 +24,16 @@ import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 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.Map.Entry;
 import java.util.Set;
 
 import javax.annotation.Nullable;
@@ -75,7 +77,7 @@ import javax.annotation.Nullable;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
  * {@code Table}</a>.
  *
  * @author Jared Levy
@@ -129,8 +131,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    */
   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);
+        ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
+        : new ArrayTable<R, C, V>(table);
   }
 
   private final ImmutableList<R> rowList;
@@ -141,8 +143,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   private final ImmutableMap<C, Integer> columnKeyToIndex;
   private final V[][] array;
 
-  private ArrayTable(Iterable<? extends R> rowKeys,
-      Iterable<? extends C> columnKeys) {
+  private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
     this.rowList = ImmutableList.copyOf(rowKeys);
     this.columnList = ImmutableList.copyOf(columnKeys);
     checkArgument(!rowList.isEmpty());
@@ -153,25 +154,16 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
      * 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);
+    rowKeyToIndex = Maps.indexMap(rowList);
+    columnKeyToIndex = Maps.indexMap(columnList);
 
     @SuppressWarnings("unchecked")
-    V[][] tmpArray
-        = (V[][]) new Object[rowList.size()][columnList.size()];
+    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);
@@ -192,7 +184,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     }
   }
 
-  private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
+  private abstract static class ArrayMap<K, V> extends IteratorBasedAbstractMap<K, V> {
     private final ImmutableMap<K, Integer> keyIndex;
 
     private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
@@ -210,9 +202,11 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
 
     abstract String getKeyRole();
 
-    @Nullable abstract V getValue(int index);
+    @Nullable
+    abstract V getValue(int index);
 
-    @Nullable abstract V setValue(int index, V newValue);
+    @Nullable
+    abstract V setValue(int index, V newValue);
 
     @Override
     public int size() {
@@ -225,41 +219,31 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     }
 
     @Override
-    protected Set<Entry<K, V>> createEntrySet() {
-      return new Maps.EntrySet<K, V>() {
+    Iterator<Entry<K, V>> entryIterator() {
+      return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
         @Override
-        Map<K, V> map() {
-          return ArrayMap.this;
-        }
+        protected Entry<K, V> get(final int index) {
+          return new AbstractMapEntry<K, V>() {
+            @Override
+            public K getKey() {
+              return ArrayMap.this.getKey(index);
+            }
 
-        @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);
-                }
-              };
+            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
+    // TODO(lowasser): consider an optimized values() implementation
 
     @Override
     public boolean containsKey(@Nullable Object key) {
@@ -372,8 +356,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   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() });
+    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);
     }
@@ -387,7 +371,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    * @deprecated Use {@link #eraseAll}
    */
   @Override
-  @Deprecated public void clear() {
+  @Deprecated
+  public void clear() {
     throw new UnsupportedOperationException();
   }
 
@@ -444,8 +429,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   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);
+    return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
   }
 
   /**
@@ -469,8 +453,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     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);
+    checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
     return set(rowIndex, columnIndex, value);
   }
 
@@ -502,7 +485,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
    * @deprecated Use {@link #erase}
    */
   @Override
-  @Deprecated public V remove(Object rowKey, Object columnKey) {
+  @Deprecated
+  public V remove(Object rowKey, Object columnKey) {
     throw new UnsupportedOperationException();
   }
 
@@ -556,18 +540,22 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   @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) {
+      @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);
@@ -593,8 +581,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
   public Map<R, V> column(C columnKey) {
     checkNotNull(columnKey);
     Integer columnIndex = columnKeyToIndex.get(columnKey);
-    return (columnIndex == null)
-        ? ImmutableMap.<R, V>of() : new Column(columnIndex);
+    return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
   }
 
   private class Column extends ArrayMap<R, V> {
@@ -640,6 +627,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     return (map == null) ? columnMap = new ColumnMap() : map;
   }
 
+  @WeakOuter
   private class ColumnMap extends ArrayMap<C, Map<R, V>> {
     private ColumnMap() {
       super(columnKeyToIndex);
@@ -729,6 +717,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
     return (map == null) ? rowMap = new RowMap() : map;
   }
 
+  @WeakOuter
   private class RowMap extends ArrayMap<R, Map<C, V>> {
     private RowMap() {
       super(rowKeyToIndex);
diff --git a/guava/src/com/google/common/collect/BiMap.java b/guava/src/com/google/common/collect/BiMap.java
index a6203e0..e8ddf9d 100644
--- a/guava/src/com/google/common/collect/BiMap.java
+++ b/guava/src/com/google/common/collect/BiMap.java
@@ -28,13 +28,13 @@ import javax.annotation.Nullable;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
  * {@code BiMap}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface BiMap<K, V> extends Map<K, V> {
@@ -48,6 +48,7 @@ public interface BiMap<K, V> extends Map<K, V> {
    *     event. To avoid this exception, call {@link #forcePut} instead.
    */
   @Override
+  @Nullable
   V put(@Nullable K key, @Nullable V value);
 
   /**
@@ -67,6 +68,7 @@ public interface BiMap<K, V> extends Map<K, V> {
    * @return the value which was previously associated with the key, which may
    *     be {@code null}, or {@code null} if there was no previous entry
    */
+  @Nullable
   V forcePut(@Nullable K key, @Nullable V value);
 
   // Bulk Operations
diff --git a/guava/src/com/google/common/collect/BinaryTreeTraverser.java b/guava/src/com/google/common/collect/BinaryTreeTraverser.java
index d86d6a4..9eca1a8 100644
--- a/guava/src/com/google/common/collect/BinaryTreeTraverser.java
+++ b/guava/src/com/google/common/collect/BinaryTreeTraverser.java
@@ -37,7 +37,7 @@ import java.util.Iterator;
 @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
+  // TODO(lowasser): 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
@@ -164,7 +164,7 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
     }
   }
 
-  // TODO(user): see if any significant optimizations are possible for breadthFirstIterator
+  // TODO(lowasser): see if any significant optimizations are possible for breadthFirstIterator
 
   public final FluentIterable<T> inOrderTraversal(final T root) {
     checkNotNull(root);
diff --git a/guava/src/com/google/common/collect/ByFunctionOrdering.java b/guava/src/com/google/common/collect/ByFunctionOrdering.java
index c148ba9..82d84e1 100644
--- a/guava/src/com/google/common/collect/ByFunctionOrdering.java
+++ b/guava/src/com/google/common/collect/ByFunctionOrdering.java
@@ -31,38 +31,39 @@ import javax.annotation.Nullable;
  * function on those elements.
  */
 @GwtCompatible(serializable = true)
-final class ByFunctionOrdering<F, T>
-    extends Ordering<F> implements Serializable {
+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) {
+  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) {
+  @Override
+  public int compare(F left, F right) {
     return ordering.compare(function.apply(left), function.apply(right));
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @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 this.function.equals(that.function) && this.ordering.equals(that.ordering);
     }
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Objects.hashCode(function, ordering);
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return ordering + ".onResultOf(" + function + ")";
   }
 
diff --git a/guava/src/com/google/common/collect/CartesianList.java b/guava/src/com/google/common/collect/CartesianList.java
index 0e50740..e27de14 100644
--- a/guava/src/com/google/common/collect/CartesianList.java
+++ b/guava/src/com/google/common/collect/CartesianList.java
@@ -28,7 +28,7 @@ import javax.annotation.Nullable;
 
 /**
  * Implementation of {@link Lists#cartesianProduct(List)}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -36,10 +36,9 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
 
   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());
+    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()) {
@@ -56,8 +55,7 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
     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());
+        axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[i + 1], axes.get(i).size());
       }
     } catch (ArithmeticException e) {
       throw new IllegalArgumentException(
diff --git a/guava/src/com/google/common/collect/ClassToInstanceMap.java b/guava/src/com/google/common/collect/ClassToInstanceMap.java
index b3f535c..8c39210 100644
--- a/guava/src/com/google/common/collect/ClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/ClassToInstanceMap.java
@@ -31,9 +31,9 @@ import javax.annotation.Nullable;
  * <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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap">
  * {@code ClassToInstanceMap}</a>.
  *
  * <p>To map a generic type to an instance of that type, use {@link
@@ -43,7 +43,7 @@ import javax.annotation.Nullable;
  *     simply {@link Object}
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface ClassToInstanceMap<B> extends Map<Class<? extends B>, B> {
diff --git a/guava/src/com/google/common/collect/CollectPreconditions.java b/guava/src/com/google/common/collect/CollectPreconditions.java
index e3e1cbe..f19f475 100644
--- a/guava/src/com/google/common/collect/CollectPreconditions.java
+++ b/guava/src/com/google/common/collect/CollectPreconditions.java
@@ -41,6 +41,12 @@ final class CollectPreconditions {
     return value;
   }
 
+  static void checkPositive(int value, String name) {
+    if (value <= 0) {
+      throw new IllegalArgumentException(name + " must be positive but was: " + value);
+    }
+  }
+
   /**
    * Precondition tester for {@code Iterator.remove()} that throws an exception with a consistent
    * error message.
diff --git a/guava/src/com/google/common/collect/Collections2.java b/guava/src/com/google/common/collect/Collections2.java
index a0c46b1..ae8ae77 100644
--- a/guava/src/com/google/common/collect/Collections2.java
+++ b/guava/src/com/google/common/collect/Collections2.java
@@ -42,6 +42,7 @@ import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -50,8 +51,9 @@ import javax.annotation.Nullable;
  * @author Chris Povirk
  * @author Mike Bostock
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Collections2 {
   private Collections2() {}
@@ -86,16 +88,15 @@ public final class Collections2 {
    */
   // 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) {
+  @CheckReturnValue
+  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));
+    return new FilteredCollection<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
   /**
@@ -103,8 +104,7 @@ public final class Collections2 {
    * {@code contains} method throws a {@code ClassCastException} or
    * {@code NullPointerException}.
    */
-  static boolean safeContains(
-      Collection<?> collection, @Nullable Object object) {
+  static boolean safeContains(Collection<?> collection, @Nullable Object object) {
     checkNotNull(collection);
     try {
       return collection.contains(object);
@@ -135,15 +135,13 @@ public final class Collections2 {
     final Collection<E> unfiltered;
     final Predicate<? super E> predicate;
 
-    FilteredCollection(Collection<E> unfiltered,
-        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));
+      return new FilteredCollection<E>(unfiltered, Predicates.<E>and(predicate, newPredicate));
       // .<E> above needed to compile in JDK 5
     }
 
@@ -198,12 +196,12 @@ public final class Collections2 {
 
     @Override
     public boolean removeAll(final Collection<?> collection) {
-      return Iterables.removeIf(unfiltered, and(predicate, in(collection)));
+      return Iterables.removeIf(unfiltered, and(predicate, Predicates.<Object>in(collection)));
     }
 
     @Override
     public boolean retainAll(final Collection<?> collection) {
-      return Iterables.removeIf(unfiltered, and(predicate, not(in(collection))));
+      return Iterables.removeIf(unfiltered, and(predicate, not(Predicates.<Object>in(collection))));
     }
 
     @Override
@@ -242,8 +240,8 @@ public final class Collections2 {
    * {@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) {
+  public static <F, T> Collection<T> transform(
+      Collection<F> fromCollection, Function<? super F, T> function) {
     return new TransformedCollection<F, T>(fromCollection, function);
   }
 
@@ -251,25 +249,28 @@ public final class Collections2 {
     final Collection<F> fromCollection;
     final Function<? super F, ? extends T> function;
 
-    TransformedCollection(Collection<F> fromCollection,
-        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() {
+    @Override
+    public void clear() {
       fromCollection.clear();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return fromCollection.isEmpty();
     }
 
-    @Override public Iterator<T> iterator() {
+    @Override
+    public Iterator<T> iterator() {
       return Iterators.transform(fromCollection.iterator(), function);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromCollection.size();
     }
   }
@@ -294,14 +295,17 @@ public final class Collections2 {
    * An implementation of {@link Collection#toString()}.
    */
   static String toStringImpl(final Collection<?> collection) {
-    StringBuilder sb
-        = newStringBuilderForCollection(collection.size()).append('[');
+    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;
-          }
-        }));
+        sb,
+        Iterables.transform(
+            collection,
+            new Function<Object, Object>() {
+              @Override
+              public Object apply(Object input) {
+                return input == collection ? "(this Collection)" : input;
+              }
+            }));
     return sb.append(']').toString();
   }
 
@@ -349,8 +353,9 @@ public final class Collections2 {
    *     null elements.
    * @since 12.0
    */
-  @Beta public static <E extends Comparable<? super E>>
-      Collection<List<E>> orderedPermutations(Iterable<E> elements) {
+  @Beta
+  public static <E extends Comparable<? super E>> Collection<List<E>> orderedPermutations(
+      Iterable<E> elements) {
     return orderedPermutations(elements, Ordering.natural());
   }
 
@@ -401,19 +406,18 @@ public final class Collections2 {
    *     null elements, or if the specified comparator is null.
    * @since 12.0
    */
-  @Beta public static <E> Collection<List<E>> orderedPermutations(
+  @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>> {
+  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) {
+    OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator) {
       this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
       this.comparator = comparator;
       this.size = calculateSize(inputList, comparator);
@@ -434,8 +438,7 @@ public final class Collections2 {
       int n = 1;
       int r = 1;
       while (n < sortedInputList.size()) {
-        int comparison = comparator.compare(
-            sortedInputList.get(n - 1), sortedInputList.get(n));
+        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);
@@ -454,19 +457,23 @@ public final class Collections2 {
       return (int) permutations;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return size;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Iterator<List<E>> iterator() {
+    @Override
+    public Iterator<List<E>> iterator() {
       return new OrderedPermutationIterator<E>(inputList, comparator);
     }
 
-    @Override public boolean contains(@Nullable Object obj) {
+    @Override
+    public boolean contains(@Nullable Object obj) {
       if (obj instanceof List) {
         List<?> list = (List<?>) obj;
         return isPermutation(inputList, list);
@@ -474,24 +481,24 @@ public final class Collections2 {
       return false;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "orderedPermutationCollection(" + inputList + ")";
     }
   }
 
-  private static final class OrderedPermutationIterator<E>
-      extends AbstractIterator<List<E>> {
+  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) {
+    OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator) {
       this.nextPermutation = Lists.newArrayList(list);
       this.comparator = comparator;
     }
 
-    @Override protected List<E> computeNext() {
+    @Override
+    protected List<E> computeNext() {
       if (nextPermutation == null) {
         return endOfData();
       }
@@ -515,8 +522,7 @@ public final class Collections2 {
 
     int findNextJ() {
       for (int k = nextPermutation.size() - 2; k >= 0; k--) {
-        if (comparator.compare(nextPermutation.get(k),
-            nextPermutation.get(k + 1)) < 0) {
+        if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) {
           return k;
         }
       }
@@ -554,32 +560,35 @@ public final class Collections2 {
    *     null elements.
    * @since 12.0
    */
-  @Beta public static <E> Collection<List<E>> permutations(
-      Collection<E> elements) {
+  @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>> {
+  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() {
+    @Override
+    public int size() {
       return IntMath.factorial(inputList.size());
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Iterator<List<E>> iterator() {
+    @Override
+    public Iterator<List<E>> iterator() {
       return new PermutationIterator<E>(inputList);
     }
 
-    @Override public boolean contains(@Nullable Object obj) {
+    @Override
+    public boolean contains(@Nullable Object obj) {
       if (obj instanceof List) {
         List<?> list = (List<?>) obj;
         return isPermutation(inputList, list);
@@ -587,13 +596,13 @@ public final class Collections2 {
       return false;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "permutations(" + inputList + ")";
     }
   }
 
-  private static class PermutationIterator<E>
-      extends AbstractIterator<List<E>> {
+  private static class PermutationIterator<E> extends AbstractIterator<List<E>> {
     final List<E> list;
     final int[] c;
     final int[] o;
@@ -609,7 +618,8 @@ public final class Collections2 {
       j = Integer.MAX_VALUE;
     }
 
-    @Override protected List<E> computeNext() {
+    @Override
+    protected List<E> computeNext() {
       if (j <= 0) {
         return endOfData();
       }
@@ -658,8 +668,7 @@ public final class Collections2 {
   /**
    * Returns {@code true} if the second list is a permutation of the first.
    */
-  private static boolean isPermutation(List<?> first,
-      List<?> second) {
+  private static boolean isPermutation(List<?> first, List<?> second) {
     if (first.size() != second.size()) {
       return false;
     }
diff --git a/guava/src/com/google/common/collect/ComparatorOrdering.java b/guava/src/com/google/common/collect/ComparatorOrdering.java
index 5b518af..eec5246 100644
--- a/guava/src/com/google/common/collect/ComparatorOrdering.java
+++ b/guava/src/com/google/common/collect/ComparatorOrdering.java
@@ -34,11 +34,13 @@ final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
     this.comparator = checkNotNull(comparator);
   }
 
-  @Override public int compare(T a, T b) {
+  @Override
+  public int compare(T a, T b) {
     return comparator.compare(a, b);
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -49,11 +51,13 @@ final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return comparator.hashCode();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return comparator.toString();
   }
 
diff --git a/guava/src/com/google/common/collect/ComparisonChain.java b/guava/src/com/google/common/collect/ComparisonChain.java
index c228c8a..43bbc9e 100644
--- a/guava/src/com/google/common/collect/ComparisonChain.java
+++ b/guava/src/com/google/common/collect/ComparisonChain.java
@@ -23,6 +23,7 @@ import com.google.common.primitives.Longs;
 
 import java.util.Comparator;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -41,6 +42,9 @@ import javax.annotation.Nullable;
  * nonzero</i> comparison result in the chain, or will be zero if every
  * comparison result was zero.
  *
+ * <p><b>Note:</b> {@code ComparisonChain} instances are <b>immutable</b>. For
+ * this utility to work correctly, calls must be chained as illustrated above.
+ *
  * <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
@@ -50,13 +54,14 @@ import javax.annotation.Nullable;
  * {@code compare} implementations.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo">
+ * "https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained#comparecompareto">
  * {@code ComparisonChain}</a>.
  *
  * @author Mark Davis
  * @author Kevin Bourrillion
  * @since 2.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public abstract class ComparisonChain {
   private ComparisonChain() {}
@@ -69,41 +74,59 @@ public abstract class ComparisonChain {
     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 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);
 
@@ -115,33 +138,50 @@ public abstract class ComparisonChain {
     InactiveComparisonChain(int result) {
       this.result = result;
     }
-    @Override public ComparisonChain compare(
-        @Nullable Comparable left, @Nullable Comparable right) {
+
+    @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) {
+
+    @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) {
+
+    @Override
+    public ComparisonChain compare(int left, int right) {
       return this;
     }
-    @Override public ComparisonChain compare(long left, long right) {
+
+    @Override
+    public ComparisonChain compare(long left, long right) {
       return this;
     }
-    @Override public ComparisonChain compare(float left, float right) {
+
+    @Override
+    public ComparisonChain compare(float left, float right) {
       return this;
     }
-    @Override public ComparisonChain compare(double left, double right) {
+
+    @Override
+    public ComparisonChain compare(double left, double right) {
       return this;
     }
-    @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) {
+
+    @Override
+    public ComparisonChain compareTrueFirst(boolean left, boolean right) {
       return this;
     }
-    @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) {
+
+    @Override
+    public ComparisonChain compareFalseFirst(boolean left, boolean right) {
       return this;
     }
-    @Override public int result() {
+
+    @Override
+    public int result() {
       return result;
     }
   }
@@ -151,8 +191,7 @@ public abstract class ComparisonChain {
    * Comparable#compareTo}, <i>if</i> the result of this comparison chain
    * has not already been determined.
    */
-  public abstract ComparisonChain compare(
-      Comparable<?> left, Comparable<?> right);
+  public abstract ComparisonChain compare(Comparable<?> left, Comparable<?> right);
 
   /**
    * Compares two objects using a comparator, <i>if</i> the result of this
@@ -190,6 +229,19 @@ public abstract class ComparisonChain {
   public abstract ComparisonChain compare(double left, double right);
 
   /**
+   * Discouraged synonym for {@link #compareFalseFirst}.
+   *
+   * @deprecated Use {@link #compareFalseFirst}; or, if the parameters passed
+   *     are being either negated or reversed, undo the negation or reversal and
+   *     use {@link #compareTrueFirst}.
+   * @since 19.0
+   */
+  @Deprecated
+  public final ComparisonChain compare(Boolean left, Boolean right) {
+    return compareFalseFirst(left, 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.
diff --git a/guava/src/com/google/common/collect/CompoundOrdering.java b/guava/src/com/google/common/collect/CompoundOrdering.java
index 26ebf54..385d0a9 100644
--- a/guava/src/com/google/common/collect/CompoundOrdering.java
+++ b/guava/src/com/google/common/collect/CompoundOrdering.java
@@ -26,17 +26,16 @@ import java.util.Comparator;
 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(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) {
+  @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++) {
@@ -48,7 +47,8 @@ final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
     return 0;
   }
 
-  @Override public boolean equals(Object object) {
+  @Override
+  public boolean equals(Object object) {
     if (object == this) {
       return true;
     }
@@ -59,11 +59,13 @@ final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return comparators.hashCode();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Ordering.compound(" + comparators + ")";
   }
 
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava/src/com/google/common/collect/ComputationException.java
index ac80d6a..80b2f5d 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava/src/com/google/common/collect/ComputationException.java
@@ -24,7 +24,7 @@ import javax.annotation.Nullable;
  * Wraps an exception that occurred during a computation.
  *
  * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public class ComputationException extends RuntimeException {
@@ -34,5 +34,6 @@ public class ComputationException extends RuntimeException {
   public ComputationException(@Nullable Throwable cause) {
     super(cause);
   }
+
   private static final long serialVersionUID = 0;
 }
diff --git a/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java b/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
index eb7363a..87d75bb 100644
--- a/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
+++ b/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
@@ -46,8 +46,7 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
    * Creates a new, empty map with the specified strategy, initial capacity, load factor and
    * concurrency level.
    */
-  ComputingConcurrentHashMap(MapMaker builder,
-      Function<? super K, ? extends V> computingFunction) {
+  ComputingConcurrentHashMap(MapMaker builder, Function<? super K, ? extends V> computingFunction) {
     super(builder);
     this.computingFunction = checkNotNull(computingFunction);
   }
@@ -76,7 +75,8 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
     V getOrCompute(K key, int hash, Function<? super K, ? extends V> computingFunction)
         throws ExecutionException {
       try {
-        outer: while (true) {
+        outer:
+        while (true) {
           // don't call getLiveEntry, which would ignore computing values
           ReferenceEntry<K, V> e = getEntry(key, hash);
           if (e != null) {
@@ -103,7 +103,8 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
 
               for (e = first; e != null; e = e.getNext()) {
                 K entryKey = e.getKey();
-                if (e.getHash() == hash && entryKey != null
+                if (e.getHash() == hash
+                    && entryKey != null
                     && map.keyEquivalence.equivalent(key, entryKey)) {
                   ValueReference<K, V> valueReference = e.getValueReference();
                   if (valueReference.isComputingReference()) {
@@ -168,9 +169,11 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
       }
     }
 
-    V compute(K key, int hash, ReferenceEntry<K, V> e,
-        ComputingValueReference<K, V> computingValueReference)
-        throws ExecutionException {
+    V compute(
+        K key,
+        int hash,
+        ReferenceEntry<K, V> e,
+        ComputingValueReference<K, V> computingValueReference) throws ExecutionException {
       V value = null;
       long start = System.nanoTime();
       long end = 0;
@@ -285,7 +288,7 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
   private static final class ComputingValueReference<K, V> implements ValueReference<K, V> {
     final Function<? super K, ? extends V> computingFunction;
 
-    @GuardedBy("ComputingValueReference.this") // writes
+    @GuardedBy("this") // writes
     volatile ValueReference<K, V> computedReference = unset();
 
     public ComputingValueReference(Function<? super K, ? extends V> computingFunction) {
@@ -379,22 +382,47 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
 
   @Override
   Object writeReplace() {
-    return new ComputingSerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
-        valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
-        concurrencyLevel, removalListener, this, computingFunction);
+    return new ComputingSerializationProxy<K, V>(
+        keyStrength,
+        valueStrength,
+        keyEquivalence,
+        valueEquivalence,
+        expireAfterWriteNanos,
+        expireAfterAccessNanos,
+        maximumSize,
+        concurrencyLevel,
+        removalListener,
+        this,
+        computingFunction);
   }
 
   static final class ComputingSerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
 
     final Function<? super K, ? extends V> computingFunction;
 
-    ComputingSerializationProxy(Strength keyStrength, Strength valueStrength,
-        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
-        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
-        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
-        ConcurrentMap<K, V> delegate, Function<? super K, ? extends V> computingFunction) {
-      super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
-          expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
+    ComputingSerializationProxy(
+        Strength keyStrength,
+        Strength valueStrength,
+        Equivalence<Object> keyEquivalence,
+        Equivalence<Object> valueEquivalence,
+        long expireAfterWriteNanos,
+        long expireAfterAccessNanos,
+        int maximumSize,
+        int concurrencyLevel,
+        RemovalListener<? super K, ? super V> removalListener,
+        ConcurrentMap<K, V> delegate,
+        Function<? super K, ? extends V> computingFunction) {
+      super(
+          keyStrength,
+          valueStrength,
+          keyEquivalence,
+          valueEquivalence,
+          expireAfterWriteNanos,
+          expireAfterAccessNanos,
+          maximumSize,
+          concurrencyLevel,
+          removalListener,
+          delegate);
       this.computingFunction = computingFunction;
     }
 
diff --git a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
index 89afa4e..e3cb982 100644
--- a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
+++ b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
@@ -26,6 +26,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Serialization.FieldSetter;
 import com.google.common.math.IntMath;
 import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -47,12 +48,12 @@ import javax.annotation.Nullable;
  * {@code Multiset} operations (exceptions where noted). Null elements are not supported.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Cliff L. Biffle
  * @author mike nonemacher
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> implements Serializable {
 
@@ -137,7 +138,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    *     their counts. It must be empty.
    * @throws IllegalArgumentException if {@code countMap} is not empty
    */
-  @VisibleForTesting ConcurrentHashMultiset(ConcurrentMap<E, AtomicInteger> countMap) {
+  @VisibleForTesting
+  ConcurrentHashMultiset(ConcurrentMap<E, AtomicInteger> countMap) {
     checkArgument(countMap.isEmpty());
     this.countMap = countMap;
   }
@@ -150,7 +152,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * @param element the element to look for
    * @return the nonnegative number of occurrences of the element
    */
-  @Override public int count(@Nullable Object element) {
+  @Override
+  public int count(@Nullable Object element) {
     AtomicInteger existingCounter = Maps.safeGet(countMap, element);
     return (existingCounter == null) ? 0 : existingCounter.get();
   }
@@ -161,7 +164,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * <p>If the data in the multiset is modified by any other threads during this method,
    * it is undefined which (if any) of these modifications will be reflected in the result.
    */
-  @Override public int size() {
+  @Override
+  public int size() {
     long sum = 0L;
     for (AtomicInteger value : countMap.values()) {
       sum += value.get();
@@ -174,11 +178,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * answer, which ours does not.
    */
 
-  @Override public Object[] toArray() {
+  @Override
+  public Object[] toArray() {
     return snapshot().toArray();
   }
 
-  @Override public <T> T[] toArray(T[] array) {
+  @Override
+  public <T> T[] toArray(T[] array) {
     return snapshot().toArray(array);
   }
 
@@ -208,12 +214,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * @throws IllegalArgumentException if {@code occurrences} is negative, or if
    *     the resulting amount would exceed {@link Integer#MAX_VALUE}
    */
-  @Override public int add(E element, int occurrences) {
+  @Override
+  public int add(E element, int occurrences) {
     checkNotNull(element);
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+    CollectPreconditions.checkPositive(occurrences, "occurences");
 
     while (true) {
       AtomicInteger existingCounter = Maps.safeGet(countMap, element);
@@ -235,8 +242,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
               return oldValue;
             }
           } catch (ArithmeticException overflow) {
-            throw new IllegalArgumentException("Overflow adding " + occurrences
-                + " occurrences to a count of " + oldValue);
+            throw new IllegalArgumentException(
+                "Overflow adding " + occurrences + " occurrences to a count of " + oldValue);
           }
         } else {
           // In the case of a concurrent remove, we might observe a zero value, which means another
@@ -273,11 +280,12 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * we'll want to remove @Nullable, add an eager checkNotNull, and loosen up
    * testRemove_nullAllowed.
    */
-  @Override public int remove(@Nullable Object element, int occurrences) {
+  @Override
+  public int remove(@Nullable Object element, int occurrences) {
     if (occurrences == 0) {
       return count(element);
     }
-    checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+    CollectPreconditions.checkPositive(occurrences, "occurences");
 
     AtomicInteger existingCounter = Maps.safeGet(countMap, element);
     if (existingCounter == null) {
@@ -311,12 +319,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * @param element the element to remove
    * @param occurrences the number of occurrences of {@code element} to remove
    * @return {@code true} if the removal was possible (including if {@code occurrences} is zero)
+   * @throws IllegalArgumentException if {@code occurrences} is negative
    */
   public boolean removeExactly(@Nullable Object element, int occurrences) {
     if (occurrences == 0) {
       return true;
     }
-    checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+    CollectPreconditions.checkPositive(occurrences, "occurences");
 
     AtomicInteger existingCounter = Maps.safeGet(countMap, element);
     if (existingCounter == null) {
@@ -346,7 +355,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    * @return the count of {@code element} in the multiset before this call
    * @throws IllegalArgumentException if {@code count} is negative
    */
-  @Override public int setCount(E element, int count) {
+  @Override
+  public int setCount(E element, int count) {
     checkNotNull(element);
     checkNonnegative(count, "count");
     while (true) {
@@ -401,7 +411,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
    *     the condition was met.
    * @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
    */
-  @Override public boolean setCount(E element, int expectedOldCount, int newCount) {
+  @Override
+  public boolean setCount(E element, int expectedOldCount, int newCount) {
     checkNotNull(element);
     checkNonnegative(expectedOldCount, "oldCount");
     checkNonnegative(newCount, "newCount");
@@ -445,10 +456,12 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
 
   // Views
 
-  @Override Set<E> createElementSet() {
+  @Override
+  Set<E> createElementSet() {
     final Set<E> delegate = countMap.keySet();
     return new ForwardingSet<E>() {
-      @Override protected Set<E> delegate() {
+      @Override
+      protected Set<E> delegate() {
         return delegate;
       }
 
@@ -462,36 +475,43 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
         return standardContainsAll(collection);
       }
 
-      @Override public boolean remove(Object object) {
+      @Override
+      public boolean remove(Object object) {
         return object != null && Collections2.safeRemove(delegate, object);
       }
 
-      @Override public boolean removeAll(Collection<?> c) {
+      @Override
+      public boolean removeAll(Collection<?> c) {
         return standardRemoveAll(c);
       }
     };
   }
 
-  @Override public Set<Multiset.Entry<E>> createEntrySet() {
+  @Override
+  public Set<Multiset.Entry<E>> createEntrySet() {
     return new EntrySet();
   }
 
-  @Override int distinctElements() {
+  @Override
+  int distinctElements() {
     return countMap.size();
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return countMap.isEmpty();
   }
 
-  @Override Iterator<Entry<E>> entryIterator() {
+  @Override
+  Iterator<Entry<E>> entryIterator() {
     // AbstractIterator makes this fairly clean, but it doesn't support remove(). To support
     // remove(), we create an AbstractIterator, and then use ForwardingIterator to delegate to it.
     final Iterator<Entry<E>> readOnlyIterator =
         new AbstractIterator<Entry<E>>() {
           private Iterator<Map.Entry<E, AtomicInteger>> mapEntries = countMap.entrySet().iterator();
 
-          @Override protected Entry<E> computeNext() {
+          @Override
+          protected Entry<E> computeNext() {
             while (true) {
               if (!mapEntries.hasNext()) {
                 return endOfData();
@@ -508,16 +528,19 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
     return new ForwardingIterator<Entry<E>>() {
       private Entry<E> last;
 
-      @Override protected Iterator<Entry<E>> delegate() {
+      @Override
+      protected Iterator<Entry<E>> delegate() {
         return readOnlyIterator;
       }
 
-      @Override public Entry<E> next() {
+      @Override
+      public Entry<E> next() {
         last = super.next();
         return last;
       }
 
-      @Override public void remove() {
+      @Override
+      public void remove() {
         checkRemove(last != null);
         ConcurrentHashMultiset.this.setCount(last.getElement(), 0);
         last = null;
@@ -525,12 +548,15 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
     };
   }
 
-  @Override public void clear() {
+  @Override
+  public void clear() {
     countMap.clear();
   }
 
+  @WeakOuter
   private class EntrySet extends AbstractMultiset<E>.EntrySet {
-    @Override ConcurrentHashMultiset<E> multiset() {
+    @Override
+    ConcurrentHashMultiset<E> multiset() {
       return ConcurrentHashMultiset.this;
     }
 
@@ -539,11 +565,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
      * answer, which ours does not.
      */
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return snapshot().toArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return snapshot().toArray(array);
     }
 
diff --git a/guava/src/com/google/common/collect/Constraints.java b/guava/src/com/google/common/collect/Constraints.java
index 2b5da00..505f31e 100644
--- a/guava/src/com/google/common/collect/Constraints.java
+++ b/guava/src/com/google/common/collect/Constraints.java
@@ -59,19 +59,24 @@ final class Constraints {
     private final Collection<E> delegate;
     private final Constraint<? super E> constraint;
 
-    public ConstrainedCollection(
-        Collection<E> delegate, 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() {
+
+    @Override
+    protected Collection<E> delegate() {
       return delegate;
     }
-    @Override public boolean add(E element) {
+
+    @Override
+    public boolean add(E element) {
       constraint.checkElement(element);
       return delegate.add(element);
     }
-    @Override public boolean addAll(Collection<? extends E> elements) {
+
+    @Override
+    public boolean addAll(Collection<? extends E> elements) {
       return delegate.addAll(checkElements(elements, constraint));
     }
   }
@@ -88,8 +93,7 @@ final class Constraints {
    * @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) {
+  public static <E> Set<E> constrainedSet(Set<E> set, Constraint<? super E> constraint) {
     return new ConstrainedSet<E>(set, constraint);
   }
 
@@ -102,14 +106,20 @@ final class Constraints {
       this.delegate = checkNotNull(delegate);
       this.constraint = checkNotNull(constraint);
     }
-    @Override protected Set<E> delegate() {
+
+    @Override
+    protected Set<E> delegate() {
       return delegate;
     }
-    @Override public boolean add(E element) {
+
+    @Override
+    public boolean add(E element) {
       constraint.checkElement(element);
       return delegate.add(element);
     }
-    @Override public boolean addAll(Collection<? extends E> elements) {
+
+    @Override
+    public boolean addAll(Collection<? extends E> elements) {
       return delegate.addAll(checkElements(elements, constraint));
     }
   }
@@ -136,29 +146,39 @@ final class Constraints {
     final SortedSet<E> delegate;
     final Constraint<? super E> constraint;
 
-    ConstrainedSortedSet(
-        SortedSet<E> delegate, 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() {
+
+    @Override
+    protected SortedSet<E> delegate() {
       return delegate;
     }
-    @Override public SortedSet<E> headSet(E toElement) {
+
+    @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> subSet(E fromElement, E toElement) {
+      return constrainedSortedSet(delegate.subSet(fromElement, toElement), constraint);
     }
-    @Override public SortedSet<E> tailSet(E fromElement) {
+
+    @Override
+    public SortedSet<E> tailSet(E fromElement) {
       return constrainedSortedSet(delegate.tailSet(fromElement), constraint);
     }
-    @Override public boolean add(E element) {
+
+    @Override
+    public boolean add(E element) {
       constraint.checkElement(element);
       return delegate.add(element);
     }
-    @Override public boolean addAll(Collection<? extends E> elements) {
+
+    @Override
+    public boolean addAll(Collection<? extends E> elements) {
       return delegate.addAll(checkElements(elements, constraint));
     }
   }
@@ -176,8 +196,7 @@ final class Constraints {
    * @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) {
+  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);
@@ -193,46 +212,59 @@ final class Constraints {
       this.delegate = checkNotNull(delegate);
       this.constraint = checkNotNull(constraint);
     }
-    @Override protected List<E> delegate() {
+
+    @Override
+    protected List<E> delegate() {
       return delegate;
     }
 
-    @Override public boolean add(E element) {
+    @Override
+    public boolean add(E element) {
       constraint.checkElement(element);
       return delegate.add(element);
     }
-    @Override public void add(int index, E element) {
+
+    @Override
+    public void add(int index, E element) {
       constraint.checkElement(element);
       delegate.add(index, element);
     }
-    @Override public boolean addAll(Collection<? extends E> elements) {
+
+    @Override
+    public boolean addAll(Collection<? extends E> elements) {
       return delegate.addAll(checkElements(elements, constraint));
     }
-    @Override public boolean addAll(int index, Collection<? extends E> elements)
-    {
+
+    @Override
+    public boolean addAll(int index, Collection<? extends E> elements) {
       return delegate.addAll(index, checkElements(elements, constraint));
     }
-    @Override public ListIterator<E> listIterator() {
+
+    @Override
+    public ListIterator<E> listIterator() {
       return constrainedListIterator(delegate.listIterator(), constraint);
     }
-    @Override public ListIterator<E> listIterator(int index) {
+
+    @Override
+    public ListIterator<E> listIterator(int index) {
       return constrainedListIterator(delegate.listIterator(index), constraint);
     }
-    @Override public E set(int index, E element) {
+
+    @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);
+
+    @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) {
+  static class ConstrainedRandomAccessList<E> extends ConstrainedList<E> implements RandomAccess {
+    ConstrainedRandomAccessList(List<E> delegate, Constraint<? super E> constraint) {
       super(delegate, constraint);
     }
   }
@@ -256,20 +288,24 @@ final class Constraints {
     private final ListIterator<E> delegate;
     private final Constraint<? super E> constraint;
 
-    public ConstrainedListIterator(
-        ListIterator<E> delegate, Constraint<? super E> constraint) {
+    public ConstrainedListIterator(ListIterator<E> delegate, Constraint<? super E> constraint) {
       this.delegate = delegate;
       this.constraint = constraint;
     }
-    @Override protected ListIterator<E> delegate() {
+
+    @Override
+    protected ListIterator<E> delegate() {
       return delegate;
     }
 
-    @Override public void add(E element) {
+    @Override
+    public void add(E element) {
       constraint.checkElement(element);
       delegate.add(element);
     }
-    @Override public void set(E element) {
+
+    @Override
+    public void set(E element) {
       constraint.checkElement(element);
       delegate.set(element);
     }
diff --git a/guava/src/com/google/common/collect/ConsumingQueueIterator.java b/guava/src/com/google/common/collect/ConsumingQueueIterator.java
new file mode 100644
index 0000000..bf48a7d
--- /dev/null
+++ b/guava/src/com/google/common/collect/ConsumingQueueIterator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 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 com.google.common.annotations.GwtCompatible;
+
+import java.util.Collections;
+import java.util.Queue;
+
+/**
+ * An Iterator implementation which draws elements from a queue, removing them from the queue as it
+ * iterates.
+ */
+ at GwtCompatible
+class ConsumingQueueIterator<T> extends AbstractIterator<T> {
+  private final Queue<T> queue;
+
+  ConsumingQueueIterator(T... elements) {
+    // Uses LinkedList because ArrayDeque isn't GWT-compatible for now =(
+    this.queue = Lists.newLinkedList();
+    Collections.addAll(queue, elements);
+  }
+
+  ConsumingQueueIterator(Queue<T> queue) {
+    this.queue = checkNotNull(queue);
+  }
+
+  @Override
+  public T computeNext() {
+    return queue.isEmpty() ? endOfData() : queue.remove();
+  }
+}
diff --git a/guava/src/com/google/common/collect/ContiguousSet.java b/guava/src/com/google/common/collect/ContiguousSet.java
index 16f19fa..1bd2856 100644
--- a/guava/src/com/google/common/collect/ContiguousSet.java
+++ b/guava/src/com/google/common/collect/ContiguousSet.java
@@ -66,10 +66,12 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
     }
 
     // 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;
+    boolean empty =
+        effectiveRange.isEmpty()
+            || Range.compareOrThrow(
+                    range.lowerBound.leastValueAbove(domain),
+                    range.upperBound.greatestValueBelow(domain))
+                > 0;
 
     return empty
         ? new EmptyContiguousSet<C>(domain)
@@ -83,7 +85,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
     this.domain = domain;
   }
 
-  @Override public ContiguousSet<C> headSet(C toElement) {
+  @Override
+  public ContiguousSet<C> headSet(C toElement) {
     return headSetImpl(checkNotNull(toElement), false);
   }
 
@@ -91,11 +94,13 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
    * @since 12.0
    */
   @GwtIncompatible("NavigableSet")
-  @Override public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
+  @Override
+  public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
     return headSetImpl(checkNotNull(toElement), inclusive);
   }
 
-  @Override public ContiguousSet<C> subSet(C fromElement, C toElement) {
+  @Override
+  public ContiguousSet<C> subSet(C fromElement, C toElement) {
     checkNotNull(fromElement);
     checkNotNull(toElement);
     checkArgument(comparator().compare(fromElement, toElement) <= 0);
@@ -106,15 +111,17 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
    * @since 12.0
    */
   @GwtIncompatible("NavigableSet")
-  @Override public ContiguousSet<C> subSet(C fromElement, boolean fromInclusive, C toElement,
-      boolean toInclusive) {
+  @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) {
+  @Override
+  public ContiguousSet<C> tailSet(C fromElement) {
     return tailSetImpl(checkNotNull(fromElement), true);
   }
 
@@ -122,19 +129,24 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
    * @since 12.0
    */
   @GwtIncompatible("NavigableSet")
-  @Override public ContiguousSet<C> tailSet(C fromElement, boolean inclusive) {
+  @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);
+  // TODO(kevinb): we can probably make these real @Overrides now
+  /*@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> subSetImpl(
+      C fromElement, boolean fromInclusive, C toElement, boolean toInclusive);
 
-  /*@Override*/ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
+  /*@Override*/
+  abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
 
   /**
    * Returns the set of values that are contained in both this set and the other.
@@ -166,7 +178,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
   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() {
+  @Override
+  public String toString() {
     return range().toString();
   }
 
@@ -178,7 +191,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
    * @throws UnsupportedOperationException always
    * @deprecated Use {@link #create}.
    */
-  @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+  @Deprecated
+  public static <E> ImmutableSortedSet.Builder<E> builder() {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava/src/com/google/common/collect/Cut.java b/guava/src/com/google/common/collect/Cut.java
index 44e3450..087b234 100644
--- a/guava/src/com/google/common/collect/Cut.java
+++ b/guava/src/com/google/common/collect/Cut.java
@@ -44,15 +44,19 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
   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);
 
   /*
@@ -77,8 +81,7 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
       return result;
     }
     // same value. below comes before above
-    return Booleans.compare(
-        this instanceof AboveValue, that instanceof AboveValue);
+    return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue);
   }
 
   C endpoint() {
@@ -86,7 +89,8 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
   }
 
   @SuppressWarnings("unchecked") // catching CCE
-  @Override public boolean equals(Object obj) {
+  @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;
@@ -116,57 +120,82 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
     private BelowAll() {
       super(null);
     }
-    @Override Comparable<?> endpoint() {
+
+    @Override
+    Comparable<?> endpoint() {
       throw new IllegalStateException("range unbounded on this side");
     }
-    @Override boolean isLessThan(Comparable<?> value) {
+
+    @Override
+    boolean isLessThan(Comparable<?> value) {
       return true;
     }
-    @Override BoundType typeAsLowerBound() {
+
+    @Override
+    BoundType typeAsLowerBound() {
       throw new IllegalStateException();
     }
-    @Override BoundType typeAsUpperBound() {
+
+    @Override
+    BoundType typeAsUpperBound() {
       throw new AssertionError("this statement should be unreachable");
     }
-    @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Cut<Comparable<?>> withLowerBoundType(
+        BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
       throw new IllegalStateException();
     }
-    @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Cut<Comparable<?>> withUpperBoundType(
+        BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
       throw new AssertionError("this statement should be unreachable");
     }
-    @Override void describeAsLowerBound(StringBuilder sb) {
+
+    @Override
+    void describeAsLowerBound(StringBuilder sb) {
       sb.append("(-\u221e");
     }
-    @Override void describeAsUpperBound(StringBuilder sb) {
+
+    @Override
+    void describeAsUpperBound(StringBuilder sb) {
       throw new AssertionError();
     }
-    @Override Comparable<?> leastValueAbove(
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
       return domain.minValue();
     }
-    @Override Comparable<?> greatestValueBelow(
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
       throw new AssertionError();
     }
-    @Override Cut<Comparable<?>> canonical(
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @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) {
+
+    @Override
+    public int compareTo(Cut<Comparable<?>> o) {
       return (o == this) ? 0 : -1;
     }
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "-\u221e";
     }
+
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -185,49 +214,73 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
     private AboveAll() {
       super(null);
     }
-    @Override Comparable<?> endpoint() {
+
+    @Override
+    Comparable<?> endpoint() {
       throw new IllegalStateException("range unbounded on this side");
     }
-    @Override boolean isLessThan(Comparable<?> value) {
+
+    @Override
+    boolean isLessThan(Comparable<?> value) {
       return false;
     }
-    @Override BoundType typeAsLowerBound() {
+
+    @Override
+    BoundType typeAsLowerBound() {
       throw new AssertionError("this statement should be unreachable");
     }
-    @Override BoundType typeAsUpperBound() {
+
+    @Override
+    BoundType typeAsUpperBound() {
       throw new IllegalStateException();
     }
-    @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @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) {
+
+    @Override
+    Cut<Comparable<?>> withUpperBoundType(
+        BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
       throw new IllegalStateException();
     }
-    @Override void describeAsLowerBound(StringBuilder sb) {
+
+    @Override
+    void describeAsLowerBound(StringBuilder sb) {
       throw new AssertionError();
     }
-    @Override void describeAsUpperBound(StringBuilder sb) {
+
+    @Override
+    void describeAsUpperBound(StringBuilder sb) {
       sb.append("+\u221e)");
     }
-    @Override Comparable<?> leastValueAbove(
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
       throw new AssertionError();
     }
-    @Override Comparable<?> greatestValueBelow(
-        DiscreteDomain<Comparable<?>> domain) {
+
+    @Override
+    Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
       return domain.maxValue();
     }
-    @Override public int compareTo(Cut<Comparable<?>> o) {
+
+    @Override
+    public int compareTo(Cut<Comparable<?>> o) {
       return (o == this) ? 0 : 1;
     }
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "+\u221e";
     }
+
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -240,16 +293,23 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
       super(checkNotNull(endpoint));
     }
 
-    @Override boolean isLessThan(C value) {
+    @Override
+    boolean isLessThan(C value) {
       return Range.compareOrThrow(endpoint, value) <= 0;
     }
-    @Override BoundType typeAsLowerBound() {
+
+    @Override
+    BoundType typeAsLowerBound() {
       return BoundType.CLOSED;
     }
-    @Override BoundType typeAsUpperBound() {
+
+    @Override
+    BoundType typeAsUpperBound() {
       return BoundType.OPEN;
     }
-    @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+    @Override
+    Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
       switch (boundType) {
         case CLOSED:
           return this;
@@ -260,7 +320,9 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
           throw new AssertionError();
       }
     }
-    @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+    @Override
+    Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
       switch (boundType) {
         case CLOSED:
           @Nullable C previous = domain.previous(endpoint);
@@ -271,24 +333,37 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
           throw new AssertionError();
       }
     }
-    @Override void describeAsLowerBound(StringBuilder sb) {
+
+    @Override
+    void describeAsLowerBound(StringBuilder sb) {
       sb.append('[').append(endpoint);
     }
-    @Override void describeAsUpperBound(StringBuilder sb) {
+
+    @Override
+    void describeAsUpperBound(StringBuilder sb) {
       sb.append(endpoint).append(')');
     }
-    @Override C leastValueAbove(DiscreteDomain<C> domain) {
+
+    @Override
+    C leastValueAbove(DiscreteDomain<C> domain) {
       return endpoint;
     }
-    @Override C greatestValueBelow(DiscreteDomain<C> domain) {
+
+    @Override
+    C greatestValueBelow(DiscreteDomain<C> domain) {
       return domain.previous(endpoint);
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       return endpoint.hashCode();
     }
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "\\" + endpoint + "/";
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -301,16 +376,23 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
       super(checkNotNull(endpoint));
     }
 
-    @Override boolean isLessThan(C value) {
+    @Override
+    boolean isLessThan(C value) {
       return Range.compareOrThrow(endpoint, value) < 0;
     }
-    @Override BoundType typeAsLowerBound() {
+
+    @Override
+    BoundType typeAsLowerBound() {
       return BoundType.OPEN;
     }
-    @Override BoundType typeAsUpperBound() {
+
+    @Override
+    BoundType typeAsUpperBound() {
       return BoundType.CLOSED;
     }
-    @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+    @Override
+    Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
       switch (boundType) {
         case OPEN:
           return this;
@@ -321,7 +403,9 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
           throw new AssertionError();
       }
     }
-    @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+    @Override
+    Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
       switch (boundType) {
         case OPEN:
           @Nullable C next = domain.next(endpoint);
@@ -332,28 +416,43 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
           throw new AssertionError();
       }
     }
-    @Override void describeAsLowerBound(StringBuilder sb) {
+
+    @Override
+    void describeAsLowerBound(StringBuilder sb) {
       sb.append('(').append(endpoint);
     }
-    @Override void describeAsUpperBound(StringBuilder sb) {
+
+    @Override
+    void describeAsUpperBound(StringBuilder sb) {
       sb.append(endpoint).append(']');
     }
-    @Override C leastValueAbove(DiscreteDomain<C> domain) {
+
+    @Override
+    C leastValueAbove(DiscreteDomain<C> domain) {
       return domain.next(endpoint);
     }
-    @Override C greatestValueBelow(DiscreteDomain<C> domain) {
+
+    @Override
+    C greatestValueBelow(DiscreteDomain<C> domain) {
       return endpoint;
     }
-    @Override Cut<C> canonical(DiscreteDomain<C> domain) {
+
+    @Override
+    Cut<C> canonical(DiscreteDomain<C> domain) {
       C next = leastValueAbove(domain);
       return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
     }
-    @Override public int hashCode() {
+
+    @Override
+    public int hashCode() {
       return ~endpoint.hashCode();
     }
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "/" + endpoint + "\\";
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/DenseImmutableTable.java b/guava/src/com/google/common/collect/DenseImmutableTable.java
index 60f93a8..81f26ad 100644
--- a/guava/src/com/google/common/collect/DenseImmutableTable.java
+++ b/guava/src/com/google/common/collect/DenseImmutableTable.java
@@ -17,8 +17,11 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkArgument;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.IteratorBasedImmutableMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
@@ -28,8 +31,7 @@ import javax.annotation.concurrent.Immutable;
  */
 @GwtCompatible
 @Immutable
-final class DenseImmutableTable<R, C, V>
-    extends RegularImmutableTable<R, C, V> {
+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;
@@ -40,23 +42,15 @@ final class DenseImmutableTable<R, C, V>
   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) {
+  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);
+    this.rowKeyToIndex = Maps.indexMap(rowSpace);
+    this.columnKeyToIndex = Maps.indexMap(columnSpace);
     rowCounts = new int[rowKeyToIndex.size()];
     columnCounts = new int[columnKeyToIndex.size()];
     int[] iterationOrderRow = new int[cellList.size()];
@@ -84,66 +78,58 @@ final class DenseImmutableTable<R, C, V>
   /**
    * An immutable map implementation backed by an indexed nullable array.
    */
-  private abstract static class ImmutableArrayMap<K, V> extends ImmutableMap<K, V> {
+  private abstract static class ImmutableArrayMap<K, V> extends IteratorBasedImmutableMap<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);
-  
+
+    @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;
-        }
+    UnmodifiableIterator<Entry<K, V>> entryIterator() {
+      return new AbstractIterator<Entry<K, V>>() {
+        private int index = -1;
+        private final int maxIndex = keyToIndex().size();
 
         @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();
+        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();
         }
       };
     }
@@ -197,6 +183,7 @@ final class DenseImmutableTable<R, C, V>
     }
   }
 
+  @WeakOuter
   private final class RowMap extends ImmutableArrayMap<R, Map<C, V>> {
     private RowMap() {
       super(rowCounts.length);
@@ -218,6 +205,7 @@ final class DenseImmutableTable<R, C, V>
     }
   }
 
+  @WeakOuter
   private final class ColumnMap extends ImmutableArrayMap<C, Map<R, V>> {
     private ColumnMap() {
       super(columnCounts.length);
@@ -239,7 +227,8 @@ final class DenseImmutableTable<R, C, V>
     }
   }
 
-  @Override public ImmutableMap<C, Map<R, V>> columnMap() {
+  @Override
+  public ImmutableMap<C, Map<R, V>> columnMap() {
     return columnMap;
   }
 
@@ -248,12 +237,11 @@ final class DenseImmutableTable<R, C, V>
     return rowMap;
   }
 
-  @Override public V get(@Nullable Object rowKey,
-      @Nullable Object columnKey) {
+  @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];
+    return ((rowIndex == null) || (columnIndex == null)) ? null : values[rowIndex][columnIndex];
   }
 
   @Override
diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
index 4408662..0246b40 100644
--- a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
@@ -56,7 +56,11 @@ final class DescendingImmutableSortedMultiset<E> extends ImmutableSortedMultiset
 
   @Override
   Entry<E> getEntry(int index) {
-    return forward.entrySet().asList().reverse().get(index);
+    return forward
+        .entrySet()
+        .asList()
+        .reverse()
+        .get(index);
   }
 
   @Override
diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
index 340d8b9..d30b0fd 100644
--- a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
@@ -34,6 +34,11 @@ class DescendingImmutableSortedSet<E> extends ImmutableSortedSet<E> {
   }
 
   @Override
+  public boolean contains(@Nullable Object object) {
+    return forward.contains(object);
+  }
+
+  @Override
   public int size() {
     return forward.size();
   }
diff --git a/guava/src/com/google/common/collect/DescendingMultiset.java b/guava/src/com/google/common/collect/DescendingMultiset.java
index d83f782..0be951b 100644
--- a/guava/src/com/google/common/collect/DescendingMultiset.java
+++ b/guava/src/com/google/common/collect/DescendingMultiset.java
@@ -17,6 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Comparator;
 import java.util.Iterator;
@@ -26,28 +27,28 @@ import java.util.Set;
 /**
  * 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 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() {
+  @Override
+  public Comparator<? super E> comparator() {
     Comparator<? super E> result = comparator;
     if (result == null) {
-      return comparator =
-          Ordering.from(forwardMultiset().comparator()).<E>reverse();
+      return comparator = Ordering.from(forwardMultiset().comparator()).<E>reverse();
     }
     return result;
   }
 
   private transient NavigableSet<E> elementSet;
 
-  @Override public NavigableSet<E> elementSet() {
+  @Override
+  public NavigableSet<E> elementSet() {
     NavigableSet<E> result = elementSet;
     if (result == null) {
       return elementSet = new SortedMultisets.NavigableElementSet<E>(this);
@@ -55,45 +56,51 @@ abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
     return result;
   }
 
-  @Override public Entry<E> pollFirstEntry() {
+  @Override
+  public Entry<E> pollFirstEntry() {
     return forwardMultiset().pollLastEntry();
   }
 
-  @Override public Entry<E> 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> 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> 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
+  public SortedMultiset<E> tailMultiset(E fromElement, BoundType boundType) {
+    return forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset();
   }
 
-  @Override protected Multiset<E> delegate() {
+  @Override
+  protected Multiset<E> delegate() {
     return forwardMultiset();
   }
 
-  @Override public SortedMultiset<E> descendingMultiset() {
+  @Override
+  public SortedMultiset<E> descendingMultiset() {
     return forwardMultiset();
   }
 
-  @Override public Entry<E> firstEntry() {
+  @Override
+  public Entry<E> firstEntry() {
     return forwardMultiset().lastEntry();
   }
 
-  @Override public Entry<E> lastEntry() {
+  @Override
+  public Entry<E> lastEntry() {
     return forwardMultiset().firstEntry();
   }
 
@@ -101,40 +108,50 @@ abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
 
   private transient Set<Entry<E>> entrySet;
 
-  @Override public 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() {
+    @WeakOuter
+    class EntrySetImpl extends Multisets.EntrySet<E> {
+      @Override
+      Multiset<E> multiset() {
         return DescendingMultiset.this;
       }
 
-      @Override public Iterator<Entry<E>> iterator() {
+      @Override
+      public Iterator<Entry<E>> iterator() {
         return entryIterator();
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         return forwardMultiset().entrySet().size();
       }
-    };
+    }
+    return new EntrySetImpl();
   }
 
-  @Override public Iterator<E> iterator() {
+  @Override
+  public Iterator<E> iterator() {
     return Multisets.iteratorImpl(this);
   }
 
-  @Override public Object[] toArray() {
+  @Override
+  public Object[] toArray() {
     return standardToArray();
   }
 
-  @Override public <T> T[] toArray(T[] array) {
+  @Override
+  public <T> T[] toArray(T[] array) {
     return standardToArray(array);
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return entrySet().toString();
   }
-}
\ No newline at end of file
+}
diff --git a/guava/src/com/google/common/collect/DiscreteDomain.java b/guava/src/com/google/common/collect/DiscreteDomain.java
index 1afdc3a..1f11dcb 100644
--- a/guava/src/com/google/common/collect/DiscreteDomain.java
+++ b/guava/src/com/google/common/collect/DiscreteDomain.java
@@ -35,7 +35,7 @@ import java.util.NoSuchElementException;
  * "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">
+ * "https://github.com/google/guava/wiki/RangesExplained#discrete-domains">
  * {@code DiscreteDomain}</a>.
  *
  * @author Kevin Bourrillion
@@ -47,36 +47,40 @@ 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 class IntegerDomain extends DiscreteDomain<Integer> implements Serializable {
     private static final IntegerDomain INSTANCE = new IntegerDomain();
 
-    @Override public Integer next(Integer value) {
+    @Override
+    public Integer next(Integer value) {
       int i = value;
       return (i == Integer.MAX_VALUE) ? null : i + 1;
     }
 
-    @Override public Integer previous(Integer value) {
+    @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) {
+    @Override
+    public long distance(Integer start, Integer end) {
       return (long) end - start;
     }
 
-    @Override public Integer minValue() {
+    @Override
+    public Integer minValue() {
       return Integer.MIN_VALUE;
     }
 
-    @Override public Integer maxValue() {
+    @Override
+    public Integer maxValue() {
       return Integer.MAX_VALUE;
     }
 
@@ -94,28 +98,30 @@ public abstract class DiscreteDomain<C extends Comparable> {
 
   /**
    * 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 class LongDomain extends DiscreteDomain<Long> implements Serializable {
     private static final LongDomain INSTANCE = new LongDomain();
 
-    @Override public Long next(Long value) {
+    @Override
+    public Long next(Long value) {
       long l = value;
       return (l == Long.MAX_VALUE) ? null : l + 1;
     }
 
-    @Override public Long previous(Long value) {
+    @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) {
+    @Override
+    public long distance(Long start, Long end) {
       long result = end - start;
       if (end > start && result < 0) { // overflow
         return Long.MAX_VALUE;
@@ -126,11 +132,13 @@ public abstract class DiscreteDomain<C extends Comparable> {
       return result;
     }
 
-    @Override public Long minValue() {
+    @Override
+    public Long minValue() {
       return Long.MIN_VALUE;
     }
 
-    @Override public Long maxValue() {
+    @Override
+    public Long maxValue() {
       return Long.MAX_VALUE;
     }
 
@@ -145,7 +153,7 @@ public abstract class DiscreteDomain<C extends Comparable> {
 
     private static final long serialVersionUID = 0;
   }
-  
+
   /**
    * Returns the discrete domain for values of type {@code BigInteger}.
    *
@@ -159,21 +167,26 @@ public abstract class DiscreteDomain<C extends Comparable> {
       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);
+    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) {
+    @Override
+    public BigInteger next(BigInteger value) {
       return value.add(BigInteger.ONE);
     }
 
-    @Override public BigInteger previous(BigInteger value) {
+    @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();
+    @Override
+    public long distance(BigInteger start, BigInteger end) {
+      return end
+          .subtract(start)
+          .max(MIN_LONG)
+          .min(MAX_LONG)
+          .longValue();
     }
 
     private Object readResolve() {
@@ -187,7 +200,7 @@ public abstract class DiscreteDomain<C extends Comparable> {
 
     private static final long serialVersionUID = 0;
   }
-  
+
   /** Constructor for use by subclasses. */
   protected DiscreteDomain() {}
 
@@ -259,5 +272,4 @@ public abstract class DiscreteDomain<C extends Comparable> {
   public C maxValue() {
     throw new NoSuchElementException();
   }
-  
 }
diff --git a/guava/src/com/google/common/collect/EmptyContiguousSet.java b/guava/src/com/google/common/collect/EmptyContiguousSet.java
index 4546349..2c08e69 100644
--- a/guava/src/com/google/common/collect/EmptyContiguousSet.java
+++ b/guava/src/com/google/common/collect/EmptyContiguousSet.java
@@ -10,7 +10,7 @@
  * 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;
@@ -34,74 +34,96 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
     super(domain);
   }
 
-  @Override public C first() {
+  @Override
+  public C first() {
     throw new NoSuchElementException();
   }
 
-  @Override public C last() {
+  @Override
+  public C last() {
     throw new NoSuchElementException();
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return 0;
   }
 
-  @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+  @Override
+  public ContiguousSet<C> intersection(ContiguousSet<C> other) {
     return this;
   }
 
-  @Override public Range<C> range() {
+  @Override
+  public Range<C> range() {
     throw new NoSuchElementException();
   }
 
-  @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+  @Override
+  public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
     throw new NoSuchElementException();
   }
 
-  @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
     return this;
   }
 
-  @Override ContiguousSet<C> subSetImpl(
+  @Override
+  ContiguousSet<C> subSetImpl(
       C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
     return this;
   }
 
-  @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
+  @Override
+  ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
     return this;
   }
 
+  @Override
+  public boolean contains(Object object) {
+    return false;
+  }
+
   @GwtIncompatible("not used by GWT emulation")
-  @Override int indexOf(Object target) {
+  @Override
+  int indexOf(Object target) {
     return -1;
   }
 
-  @Override public UnmodifiableIterator<C> iterator() {
+  @Override
+  public UnmodifiableIterator<C> iterator() {
     return Iterators.emptyIterator();
   }
 
   @GwtIncompatible("NavigableSet")
-  @Override public UnmodifiableIterator<C> descendingIterator() {
+  @Override
+  public UnmodifiableIterator<C> descendingIterator() {
     return Iterators.emptyIterator();
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return true;
   }
 
-  @Override public ImmutableList<C> asList() {
+  @Override
+  public ImmutableList<C> asList() {
     return ImmutableList.of();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "[]";
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof Set) {
       Set<?> that = (Set<?>) object;
       return that.isEmpty();
@@ -109,7 +131,14 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
     return false;
   }
 
-  @Override public int hashCode() {
+  @GwtIncompatible("not used in GWT")
+  @Override
+  boolean isHashCodeFast() {
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
     return 0;
   }
 
@@ -136,6 +165,6 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
 
   @GwtIncompatible("NavigableSet")
   ImmutableSortedSet<C> createDescendingSet() {
-    return new EmptyImmutableSortedSet<C>(Ordering.natural().reverse());
+    return ImmutableSortedSet.emptySet(Ordering.natural().reverse());
   }
 }
diff --git a/guava/src/com/google/common/collect/EmptyImmutableBiMap.java b/guava/src/com/google/common/collect/EmptyImmutableBiMap.java
deleted file mode 100644
index bc08588..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableBiMap.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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;
-
-import javax.annotation.Nullable;
-
-/**
- * Bimap with no mappings.
- *
- * @author Jared Levy
- */
- at GwtCompatible(emulated = true)
- at 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
-  }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java b/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
index 2a6836d..9b167fb 100644
--- a/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
+++ b/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
@@ -25,8 +25,7 @@ import com.google.common.annotations.GwtCompatible;
  */
 @GwtCompatible(serializable = true)
 class EmptyImmutableListMultimap extends ImmutableListMultimap<Object, Object> {
-  static final EmptyImmutableListMultimap INSTANCE
-      = new EmptyImmutableListMultimap();
+  static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap();
 
   private EmptyImmutableListMultimap() {
     super(ImmutableMap.<Object, ImmutableList<Object>>of(), 0);
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSet.java b/guava/src/com/google/common/collect/EmptyImmutableSet.java
deleted file mode 100644
index c808ec5..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSet.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable set.
- *
- * @author Kevin Bourrillion
- */
- at 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;
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java b/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
index 810de3c..ec2ce2e 100644
--- a/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
+++ b/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
@@ -25,8 +25,7 @@ import com.google.common.annotations.GwtCompatible;
  */
 @GwtCompatible(serializable = true)
 class EmptyImmutableSetMultimap extends ImmutableSetMultimap<Object, Object> {
-  static final EmptyImmutableSetMultimap INSTANCE
-      = new EmptyImmutableSetMultimap();
+  static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap();
 
   private EmptyImmutableSetMultimap() {
     super(ImmutableMap.<Object, ImmutableSet<Object>>of(), 0, null);
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java b/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java
deleted file mode 100644
index 3734851..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 com.google.common.annotations.GwtCompatible;
-
-import java.util.Comparator;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable sorted map.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
- at 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);
-  }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java b/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java
deleted file mode 100644
index 6140f5f..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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
- */
- at 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();
-  }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java b/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java
deleted file mode 100644
index c4d5a78..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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;
-import com.google.common.annotations.GwtIncompatible;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable sorted set.
- *
- * @author Jared Levy
- */
- at GwtCompatible(serializable = true, emulated = true)
- at 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());
-  }
-}
diff --git a/guava/src/com/google/common/collect/EnumBiMap.java b/guava/src/com/google/common/collect/EnumBiMap.java
index 05d84ed..7696ffe 100644
--- a/guava/src/com/google/common/collect/EnumBiMap.java
+++ b/guava/src/com/google/common/collect/EnumBiMap.java
@@ -32,17 +32,16 @@ import java.util.Map;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
  * {@code BiMap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
-public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
-    extends AbstractBiMap<K, V> {
+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;
 
@@ -53,8 +52,8 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
    * @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) {
+  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);
   }
 
@@ -68,15 +67,15 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
    * @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) {
+  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)),
+    super(
+        WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
         WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
     this.keyType = keyType;
     this.valueType = valueType;
@@ -90,7 +89,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
       return ((EnumHashBiMap<K, ?>) map).keyType();
     }
     checkArgument(!map.isEmpty());
-    return map.keySet().iterator().next().getDeclaringClass();
+    return map
+        .keySet()
+        .iterator()
+        .next()
+        .getDeclaringClass();
   }
 
   private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
@@ -98,7 +101,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
       return ((EnumBiMap<?, V>) map).valueType;
     }
     checkArgument(!map.isEmpty());
-    return map.values().iterator().next().getDeclaringClass();
+    return map
+        .values()
+        .iterator()
+        .next()
+        .getDeclaringClass();
   }
 
   /** Returns the associated key type. */
@@ -135,8 +142,7 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
 
   @SuppressWarnings("unchecked") // reading fields populated by writeObject
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     keyType = (Class<K>) stream.readObject();
     valueType = (Class<V>) stream.readObject();
diff --git a/guava/src/com/google/common/collect/EnumHashBiMap.java b/guava/src/com/google/common/collect/EnumHashBiMap.java
index c43daf0..566b3fe 100644
--- a/guava/src/com/google/common/collect/EnumHashBiMap.java
+++ b/guava/src/com/google/common/collect/EnumHashBiMap.java
@@ -35,17 +35,16 @@ import javax.annotation.Nullable;
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
  * {@code BiMap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
-public final class EnumHashBiMap<K extends Enum<K>, V>
-    extends AbstractBiMap<K, V> {
+public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
   private transient Class<K> keyType;
 
   /**
@@ -53,8 +52,7 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
    *
    * @param keyType the key type
    */
-  public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
-      create(Class<K> keyType) {
+  public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
     return new EnumHashBiMap<K, V>(keyType);
   }
 
@@ -68,18 +66,16 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
    * @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) {
+  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));
+    super(
+        WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+        Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
     this.keyType = keyType;
   }
 
@@ -90,11 +86,13 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
     return checkNotNull(key);
   }
 
-  @Override public V put(K key, @Nullable V value) {
+  @Override
+  public V put(K key, @Nullable V value) {
     return super.put(key, value);
   }
 
-  @Override public V forcePut(K key, @Nullable V value) {
+  @Override
+  public V forcePut(K key, @Nullable V value) {
     return super.forcePut(key, value);
   }
 
@@ -116,11 +114,11 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
 
   @SuppressWarnings("unchecked") // reading field populated by writeObject
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     keyType = (Class<K>) stream.readObject();
-    setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+    setDelegates(
+        WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
         new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
     Serialization.populateMap(this, stream);
   }
diff --git a/guava/src/com/google/common/collect/EnumMultiset.java b/guava/src/com/google/common/collect/EnumMultiset.java
index 2bb121c..1ed31a0 100644
--- a/guava/src/com/google/common/collect/EnumMultiset.java
+++ b/guava/src/com/google/common/collect/EnumMultiset.java
@@ -27,13 +27,13 @@ import java.util.Iterator;
 
 /**
  * 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">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
@@ -58,12 +58,12 @@ public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMulti
     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) {
diff --git a/guava/src/com/google/common/collect/EvictingQueue.java b/guava/src/com/google/common/collect/EvictingQueue.java
index c124a0c..56eaffc 100644
--- a/guava/src/com/google/common/collect/EvictingQueue.java
+++ b/guava/src/com/google/common/collect/EvictingQueue.java
@@ -20,17 +20,17 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.annotations.GwtIncompatible;
+import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.VisibleForTesting;
 
 import java.io.Serializable;
-import java.util.ArrayDeque;
 import java.util.Collection;
 import java.util.Queue;
 
 /**
  * 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.
+ * attempting to add new elements onto the queue and it is full. This data structure is logically
+ * equivalent to a circular buffer (i.e., cyclic buffer or ring buffer).
  *
  * <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
@@ -42,17 +42,16 @@ import java.util.Queue;
  * @since 15.0
  */
 @Beta
- at GwtIncompatible("java.util.ArrayDeque")
+ at GwtCompatible
 public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serializable {
 
   private final Queue<E> delegate;
 
-  @VisibleForTesting
-  final int maxSize;
+  @VisibleForTesting final int maxSize;
 
   private EvictingQueue(int maxSize) {
     checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", maxSize);
-    this.delegate = new ArrayDeque<E>(maxSize);
+    this.delegate = Platform.newFastestQueue(maxSize);
     this.maxSize = maxSize;
   }
 
@@ -76,7 +75,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
     return maxSize - size();
   }
 
-  @Override protected Queue<E> delegate() {
+  @Override
+  protected Queue<E> delegate() {
     return delegate;
   }
 
@@ -86,7 +86,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
    *
    * @return {@code true} always
    */
-  @Override public boolean offer(E e) {
+  @Override
+  public boolean offer(E e) {
     return add(e);
   }
 
@@ -96,8 +97,9 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
    *
    * @return {@code true} always
    */
-  @Override public boolean add(E e) {
-    checkNotNull(e);  // check before removing
+  @Override
+  public boolean add(E e) {
+    checkNotNull(e); // check before removing
     if (maxSize == 0) {
       return true;
     }
@@ -108,7 +110,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
     return true;
   }
 
-  @Override public boolean addAll(Collection<? extends E> collection) {
+  @Override
+  public boolean addAll(Collection<? extends E> collection) {
     return standardAddAll(collection);
   }
 
@@ -122,7 +125,7 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
     return delegate().remove(checkNotNull(object));
   }
 
-  // TODO(user): Do we want to checkNotNull each element in containsAll, removeAll, and retainAll?
+  // TODO(kak): Do we want to checkNotNull each element in containsAll, removeAll, and retainAll?
 
   private static final long serialVersionUID = 0L;
 }
diff --git a/guava/src/com/google/common/collect/ExplicitOrdering.java b/guava/src/com/google/common/collect/ExplicitOrdering.java
index 0a2e181..d31e4a5 100644
--- a/guava/src/com/google/common/collect/ExplicitOrdering.java
+++ b/guava/src/com/google/common/collect/ExplicitOrdering.java
@@ -29,14 +29,15 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
   final ImmutableMap<T, Integer> rankMap;
 
   ExplicitOrdering(List<T> valuesInOrder) {
-    this(buildRankMap(valuesInOrder));
+    this(Maps.indexMap(valuesInOrder));
   }
 
   ExplicitOrdering(ImmutableMap<T, Integer> rankMap) {
     this.rankMap = rankMap;
   }
 
-  @Override public int compare(T left, T right) {
+  @Override
+  public int compare(T left, T right) {
     return rank(left) - rank(right); // safe because both are nonnegative
   }
 
@@ -48,17 +49,8 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
     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) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof ExplicitOrdering) {
       ExplicitOrdering<?> that = (ExplicitOrdering<?>) object;
       return this.rankMap.equals(that.rankMap);
@@ -66,11 +58,13 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return rankMap.hashCode();
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Ordering.explicit(" + rankMap.keySet() + ")";
   }
 
diff --git a/guava/src/com/google/common/collect/FilteredEntryMultimap.java b/guava/src/com/google/common/collect/FilteredEntryMultimap.java
index ebc3d4b..261c9a5 100644
--- a/guava/src/com/google/common/collect/FilteredEntryMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredEntryMultimap.java
@@ -24,7 +24,8 @@ import static com.google.common.collect.CollectPreconditions.checkNonnegative;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicate;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -38,7 +39,7 @@ import javax.annotation.Nullable;
 
 /**
  * Implementation of {@link Multimaps#filterEntries(Multimap, Predicate)}.
- * 
+ *
  * @author Jared Levy
  * @author Louis Wasserman
  */
@@ -51,7 +52,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
     this.unfiltered = checkNotNull(unfiltered);
     this.predicate = checkNotNull(predicate);
   }
-  
+
   @Override
   public Multimap<K, V> unfiltered() {
     return unfiltered;
@@ -70,7 +71,6 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
   private boolean satisfies(K key, V value) {
     return predicate.apply(Maps.immutableEntry(key, value));
   }
-  
 
   final class ValuePredicate implements Predicate<V> {
     private final K key;
@@ -106,8 +106,8 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
 
   Collection<V> unmodifiableEmptyCollection() {
     // These return false, rather than throwing a UOE, on remove calls.
-    return (unfiltered instanceof SetMultimap) 
-        ? Collections.<V>emptySet() 
+    return (unfiltered instanceof SetMultimap)
+        ? Collections.<V>emptySet()
         : Collections.<V>emptyList();
   }
 
@@ -125,7 +125,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
   Collection<Entry<K, V>> createEntries() {
     return filterCollection(unfiltered.entries(), predicate);
   }
-  
+
   @Override
   Collection<V> createValues() {
     return new FilteredMultimapValues<K, V>(this);
@@ -140,12 +140,12 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
   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;
@@ -164,8 +164,9 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
     }
     return changed;
   }
-  
-  class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+
+  @WeakOuter
+  class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
     @Override
     public boolean containsKey(@Nullable Object key) {
       return get(key) != null;
@@ -187,7 +188,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
       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);
@@ -213,10 +214,15 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         return Collections.unmodifiableList(result);
       }
     }
-    
+
     @Override
     Set<K> createKeySet() {
-      return new Maps.KeySet<K, Collection<V>>(this) {
+      @WeakOuter
+      class KeySetImpl extends Maps.KeySet<K, Collection<V>> {
+        KeySetImpl() {
+          super(AsMap.this);
+        }
+
         @Override
         public boolean removeAll(Collection<?> c) {
           return removeEntriesIf(Maps.<K>keyPredicateOnEntries(in(c)));
@@ -231,12 +237,14 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         public boolean remove(@Nullable Object o) {
           return AsMap.this.remove(o) != null;
         }
-      };
+      }
+      return new KeySetImpl();
     }
 
     @Override
     Set<Entry<K, Collection<V>>> createEntrySet() {
-      return new Maps.EntrySet<K, Collection<V>>() {
+      @WeakOuter
+      class EntrySetImpl extends Maps.EntrySet<K, Collection<V>> {
         @Override
         Map<K, Collection<V>> map() {
           return AsMap.this;
@@ -245,16 +253,16 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         @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();
+            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));
+                Collection<V> collection =
+                    filterCollection(entry.getValue(), new ValuePredicate(key));
                 if (!collection.isEmpty()) {
                   return Maps.immutableEntry(key, collection);
                 }
@@ -273,28 +281,34 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         public boolean retainAll(Collection<?> c) {
           return removeEntriesIf(not(in(c)));
         }
-        
+
         @Override
         public int size() {
           return Iterators.size(iterator());
         }
-      };
+      }
+      return new EntrySetImpl();
     }
-    
+
     @Override
     Collection<Collection<V>> createValues() {
-      return new Maps.Values<K, Collection<V>>(AsMap.this) {
+      @WeakOuter
+      class ValuesImpl extends Maps.Values<K, Collection<V>> {
+        ValuesImpl() {
+          super(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();
+            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));
+              Collection<V> collection =
+                  filterCollection(entry.getValue(), new ValuePredicate(key));
               if (!collection.isEmpty() && c.equals(collection)) {
                 if (collection.size() == entry.getValue().size()) {
                   entryIterator.remove();
@@ -317,15 +331,17 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         public boolean retainAll(Collection<?> c) {
           return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(not(in(c))));
         }
-      };
+      }
+      return new ValuesImpl();
     }
   }
-  
+
   @Override
   Multiset<K> createKeys() {
     return new Keys();
   }
-  
+
+  @WeakOuter
   class Keys extends Multimaps.Keys<K, V> {
     Keys() {
       super(FilteredEntryMultimap.this);
@@ -375,23 +391,24 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
         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()));
-                }
-              });
+          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)));
diff --git a/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java b/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
index 2e12937..674144c 100644
--- a/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
@@ -24,7 +24,7 @@ import java.util.Set;
 
 /**
  * Implementation of {@link Multimaps#filterEntries(SetMultimap, Predicate)}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -34,7 +34,7 @@ final class FilteredEntrySetMultimap<K, V> extends FilteredEntryMultimap<K, V>
   FilteredEntrySetMultimap(SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
     super(unfiltered, predicate);
   }
-  
+
   @Override
   public SetMultimap<K, V> unfiltered() {
     return (SetMultimap<K, V>) unfiltered;
@@ -44,7 +44,7 @@ final class FilteredEntrySetMultimap<K, V> extends FilteredEntryMultimap<K, V>
   public Set<V> get(K key) {
     return (Set<V>) super.get(key);
   }
-  
+
   @Override
   public Set<V> removeAll(Object key) {
     return (Set<V>) super.removeAll(key);
diff --git a/guava/src/com/google/common/collect/FilteredKeyListMultimap.java b/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
index bf4b8da..27041aa 100644
--- a/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
@@ -25,11 +25,11 @@ import javax.annotation.Nullable;
 
 /**
  * Implementation of {@link Multimaps#filterKeys(ListMultimap, Predicate)}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
-final class FilteredKeyListMultimap<K, V> extends FilteredKeyMultimap<K, V> 
+final class FilteredKeyListMultimap<K, V> extends FilteredKeyMultimap<K, V>
     implements ListMultimap<K, V> {
   FilteredKeyListMultimap(ListMultimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
     super(unfiltered, keyPredicate);
diff --git a/guava/src/com/google/common/collect/FilteredKeyMultimap.java b/guava/src/com/google/common/collect/FilteredKeyMultimap.java
index 3788b72..027169f 100644
--- a/guava/src/com/google/common/collect/FilteredKeyMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeyMultimap.java
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkPositionIndex;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Predicate;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -180,6 +181,7 @@ class FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements Filter
     return new Entries();
   }
 
+  @WeakOuter
   class Entries extends ForwardingCollection<Entry<K, V>> {
     @Override
     protected Collection<Entry<K, V>> delegate() {
@@ -200,7 +202,7 @@ class FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements Filter
       return false;
     }
   }
-  
+
   @Override
   Collection<V> createValues() {
     return new FilteredMultimapValues<K, V>(this);
diff --git a/guava/src/com/google/common/collect/FilteredKeySetMultimap.java b/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
index b8a6a57..29dc133 100644
--- a/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
 
 /**
  * Implementation of {@link Multimaps#filterKeys(SetMultimap, Predicate)}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
@@ -66,13 +66,13 @@ final class FilteredKeySetMultimap<K, V> extends FilteredKeyMultimap<K, V>
   Set<Entry<K, V>> createEntries() {
     return new EntrySet();
   }
-  
+
   class EntrySet extends Entries implements Set<Entry<K, V>> {
     @Override
     public int hashCode() {
       return Sets.hashCodeImpl(this);
     }
-    
+
     @Override
     public boolean equals(@Nullable Object o) {
       return Sets.equalsImpl(this, o);
diff --git a/guava/src/com/google/common/collect/FilteredMultimap.java b/guava/src/com/google/common/collect/FilteredMultimap.java
index e97cfdb..22c2b3d 100644
--- a/guava/src/com/google/common/collect/FilteredMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredMultimap.java
@@ -23,11 +23,11 @@ import java.util.Map.Entry;
 
 /**
  * An interface for all filtered multimap types.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
-interface FilteredMultimap<K, V> extends Multimap<K, V> {  
+interface FilteredMultimap<K, V> extends Multimap<K, V> {
   Multimap<K, V> unfiltered();
 
   Predicate<? super Entry<K, V>> entryPredicate();
diff --git a/guava/src/com/google/common/collect/FilteredMultimapValues.java b/guava/src/com/google/common/collect/FilteredMultimapValues.java
index ae6f785..c34e92f 100644
--- a/guava/src/com/google/common/collect/FilteredMultimapValues.java
+++ b/guava/src/com/google/common/collect/FilteredMultimapValues.java
@@ -20,6 +20,7 @@ import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.AbstractCollection;
 import java.util.Collection;
@@ -31,12 +32,12 @@ import javax.annotation.Nullable;
 
 /**
  * Implementation for {@link FilteredMultimap#values()}.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
 final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
-  private final FilteredMultimap<K, V> multimap;
+  @Weak private final FilteredMultimap<K, V> multimap;
 
   FilteredMultimapValues(FilteredMultimap<K, V> multimap) {
     this.multimap = checkNotNull(multimap);
@@ -73,17 +74,20 @@ final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
 
   @Override
   public boolean removeAll(Collection<?> c) {
-    return Iterables.removeIf(multimap.unfiltered().entries(),
+    return Iterables.removeIf(
+        multimap.unfiltered().entries(),
         // explicit <Entry<K, V>> is required to build with JDK6
-        Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
-            Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
+        Predicates.<Entry<K, V>>and(
+            multimap.entryPredicate(), Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
   }
 
   @Override
   public boolean retainAll(Collection<?> c) {
-    return Iterables.removeIf(multimap.unfiltered().entries(),
+    return Iterables.removeIf(
+        multimap.unfiltered().entries(),
         // explicit <Entry<K, V>> is required to build with JDK6
-        Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
+        Predicates.<Entry<K, V>>and(
+            multimap.entryPredicate(),
             Maps.<V>valuePredicateOnEntries(Predicates.not(Predicates.in(c)))));
   }
 
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava/src/com/google/common/collect/FilteredSetMultimap.java
index 6b73281..a0a149f 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredSetMultimap.java
@@ -20,7 +20,7 @@ import com.google.common.annotations.GwtCompatible;
 
 /**
  * A supertype for filtered {@link SetMultimap} implementations.
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible
diff --git a/guava/src/com/google/common/collect/FluentIterable.java b/guava/src/com/google/common/collect/FluentIterable.java
index e007ef7..59c2a64 100644
--- a/guava/src/com/google/common/collect/FluentIterable.java
+++ b/guava/src/com/google/common/collect/FluentIterable.java
@@ -37,34 +37,72 @@ import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
- * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
- * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
- * of elements. The following types of methods are provided on {@code FluentIterable}:
+ * An expanded {@code Iterable} API, providing functionality similar to Java 8's powerful <a href=
+ * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description"
+ * >streams library</a> in a slightly different way.
+ *
+ * <p>The following types of methods are provided:
+ *
  * <ul>
- * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
- * of the current one (for example {@link #transform})
- * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
- * array (for example {@link #toList})
+ * <li>chaining methods which return a new {@code FluentIterable} based in some way on the contents
+ *     of the current one (for example {@link #transform})
  * <li>element extraction methods which facilitate the retrieval of certain elements (for example
- * {@link #last})
+ *     {@link #last})
  * <li>query methods which answer questions about the {@code FluentIterable}'s contents (for example
- * {@link #anyMatch})
+ *     {@link #anyMatch})
+ * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
+ *     array (for example {@link #toList})
  * </ul>
  *
- * <p>Here is an example that merges the lists returned by two separate database calls, transforms
- * it by invoking {@code toString()} on each element, and returns the first 10 elements as an
- * {@code ImmutableList}: <pre>   {@code
+ * <p>Several lesser-used features are currently available only as static methods on the {@link
+ * Iterables} class.
+ *
+ * <a name="streams"></a>
+ * <h3>Comparison to streams</h3>
+ *
+ * <p>Starting with Java 8, the core Java class libraries provide a new "Streams" library (in {@code
+ * java.util.stream}), which is similar to {@code FluentIterable} but generally more powerful. Key
+ * differences include:</b>
+ *
+ * <ul>
+ * <li>A stream is <i>single-use</i>; it becomes invalid as soon as any "terminal operation" such as
+ *     {@code findFirst()} or {@code iterator()} is invoked. (Even though {@code Stream} contains
+ *     all the right method <i>signatures</i> to implement {@link Iterable}, it does not actually
+ *     do so, to avoid implying repeat-iterability.) {@code FluentIterable}, on the other hand, is
+ *     multiple-use, and does implement {@link Iterable}.
+ * <li>Streams offer many features not found here, including {@code min/max}, {@code
+ *     distinct}, {@code reduce}, {@code sorted}, the very powerful {@code collect}, and built-in
+ *     support for parallelizing stream operations.
+ * <li>{@code FluentIterable} contains several features not available on {@code Stream}, which are
+ *     noted in the method descriptions below.
+ * <li>Streams include primitive-specialized variants such as {@code IntStream}, the use of which is
+ *     strongly recommended.
+ * <li>Streams are standard Java, not requiring a third-party dependency (but do render your code
+ *     incompatible with Java 7 and earlier).
+ * </ul>
+ *
+ * <h3>Example</h3>
+ *
+ * <p>Here is an example that accepts a list from a database call, filters it based on a predicate,
+ * transforms it by invoking {@code toString()} on each element, and returns the first 10 elements
+ * as a {@code List}: <pre>   {@code
  *
- *   FluentIterable
- *       .from(database.getClientList())
- *       .filter(activeInLastMonth())
- *       .transform(Functions.toStringFunction())
- *       .limit(10)
- *       .toList();}</pre>
+ *   List<String> results =
+ *       FluentIterable.from(database.getClientList())
+ *           .filter(activeInLastMonthPredicate)
+ *           .transform(Functions.toStringFunction())
+ *           .limit(10)
+ *           .toList();}</pre>
  *
- * <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
- * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
- * operations significantly more concise.
+ * The approximate stream equivalent is: <pre>   {@code
+ *
+ *   List<String> results =
+ *       database.getClientList()
+ *           .stream()
+ *           .filter(activeInLastMonthPredicate)
+ *           .map(Functions.toStringFunction())
+ *           .limit(10)
+ *           .collect(Collectors.toList());}</pre>
  *
  * @author Marcin Mikosik
  * @since 12.0
@@ -87,9 +125,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
    * is already a {@code FluentIterable}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code iterable.stream()} if {@code iterable} is a
+   * {@link Collection}; {@code StreamSupport.stream(iterable.spliterator(), false)} otherwise.
    */
+  @CheckReturnValue
   public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
-    return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
+    return (iterable instanceof FluentIterable)
+        ? (FluentIterable<E>) iterable
         : new FluentIterable<E>(iterable) {
           @Override
           public Iterator<E> iterator() {
@@ -107,6 +150,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *     {@code FluentIterable}
    */
   @Deprecated
+  @CheckReturnValue
   public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
     return checkNotNull(iterable);
   }
@@ -114,9 +158,13 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a fluent iterable containing {@code elements} in the specified order.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.of(elements)} or {@code
+   * Arrays.stream(elements)}.
+   *
    * @since 18.0
    */
   @Beta
+  @CheckReturnValue
   public static <E> FluentIterable<E> of(E[] elements) {
     return from(Lists.newArrayList(elements));
   }
@@ -124,25 +172,35 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns a string representation of this fluent iterable, with the format
    * {@code [e1, e2, ..., en]}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.joining(", ", "[", "]"))}
+   * or (less efficiently) {@code collect(Collectors.toList()).toString()}.
    */
   @Override
+  @CheckReturnValue
   public String toString() {
     return Iterables.toString(iterable);
   }
 
   /**
    * Returns the number of elements in this fluent iterable.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.count()}.
    */
+  @CheckReturnValue
   public final int size() {
     return Iterables.size(iterable);
   }
 
   /**
    * Returns {@code true} if this fluent iterable contains any object for which
-   * {@code equals(element)} is true.
+   * {@code equals(target)} is true.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(Predicate.isEqual(target))}.
    */
-  public final boolean contains(@Nullable Object element) {
-    return Iterables.contains(iterable, element);
+  @CheckReturnValue
+  public final boolean contains(@Nullable Object target) {
+    return Iterables.contains(iterable, target);
   }
 
   /**
@@ -157,6 +215,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p><b>Warning:</b> Typical uses of the resulting iterator may produce an infinite loop. You
    * should use an explicit {@code break} or be certain that you will eventually remove all the
    * elements.
+   *
+   * <p><b>{@code Stream} equivalent:</b> if the source iterable has only a single element {@code
+   * element}, use {@code Stream.generate(() -> element)}. Otherwise, if the source iterable has
+   * a {@code stream} method (for example, if it is a {@link Collection}), use
+   * {@code Stream.generate(iterable::stream).flatMap(s -> s)}.
    */
   @CheckReturnValue
   public final FluentIterable<E> cycle() {
@@ -170,6 +233,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
    * {@code Iterator} supports it.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, otherStream)}.
+   *
    * @since 18.0
    */
   @Beta
@@ -182,6 +247,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
    * followed by {@code elements}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, Stream.of(elements))}.
+   *
    * @since 18.0
    */
   @Beta
@@ -193,6 +260,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns the elements from this fluent iterable that satisfy a predicate. The
    * resulting fluent iterable's iterator does not support {@code remove()}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate)} (same).
    */
   @CheckReturnValue
   public final FluentIterable<E> filter(Predicate<? super E> predicate) {
@@ -203,6 +272,16 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns the elements from this fluent iterable that are instances of class {@code type}.
    *
    * @param type the type of elements desired
+   *
+   * <p><b>{@code Stream} equivalent:</b> <pre>   {@code
+   *
+   *   @SuppressWarnings("unchecked") // safe by runtime check
+   *   Stream<T> result = (Stream) stream.filter(type::isInstance);}</pre>
+   *
+   * ... or if {@code type} is a class literal {@code MyType.class}, <pre>   {@code
+   *
+   *   @SuppressWarnings("unchecked") // safe by runtime check
+   *   Stream<MyType> result = (Stream) stream.filter(e -> e instanceof MyType);}</pre>
    */
   @GwtIncompatible("Class.isInstance")
   @CheckReturnValue
@@ -212,7 +291,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
 
   /**
    * Returns {@code true} if any element in this fluent iterable satisfies the predicate.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(predicate)} (same).
    */
+  @CheckReturnValue
   public final boolean anyMatch(Predicate<? super E> predicate) {
     return Iterables.any(iterable, predicate);
   }
@@ -220,7 +302,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns {@code true} if every element in this fluent iterable satisfies the predicate.
    * If this fluent iterable is empty, {@code true} is returned.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.allMatch(predicate)} (same).
    */
+  @CheckReturnValue
   public final boolean allMatch(Predicate<? super E> predicate) {
     return Iterables.all(iterable, predicate);
   }
@@ -231,7 +316,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *
    * <p><b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If {@code null}
    * is matched in this fluent iterable, a {@link NullPointerException} will be thrown.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate).findFirst()}.
    */
+  @CheckReturnValue
   public final Optional<E> firstMatch(Predicate<? super E> predicate) {
     return Iterables.tryFind(iterable, predicate);
   }
@@ -243,7 +331,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
    * iterator does. After a successful {@code remove()} call, this fluent iterable no longer
    * contains the corresponding element.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.map(function)}.
    */
+  @CheckReturnValue
   public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
     return from(Iterables.transform(iterable, function));
   }
@@ -257,8 +348,12 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * function-returned iterables' iterator does. After a successful {@code remove()} call,
    * the returned fluent iterable no longer contains the corresponding element.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.flatMap(function)} (using a function that
+   * produces streams, not iterables).
+   *
    * @since 13.0 (required {@code Function<E, Iterable<T>>} until 14.0)
    */
+  @CheckReturnValue
   public <T> FluentIterable<T> transformAndConcat(
       Function<? super E, ? extends Iterable<? extends T>> function) {
     return from(Iterables.concat(transform(function)));
@@ -268,23 +363,29 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@link Optional} containing the first element in this fluent iterable.
    * If the iterable is empty, {@code Optional.absent()} is returned.
    *
+   * <p><b>{@code Stream} equivalent:</b> if the goal is to obtain any element, {@code
+   * stream.findAny()}; if it must specifically be the <i>first</i> element, {@code
+   * stream.findFirst()}.
+   *
    * @throws NullPointerException if the first element is null; if this is a possibility, use
    *     {@code iterator().next()} or {@link Iterables#getFirst} instead.
    */
+  @CheckReturnValue
   public final Optional<E> first() {
     Iterator<E> iterator = iterable.iterator();
-    return iterator.hasNext()
-        ? Optional.of(iterator.next())
-        : Optional.<E>absent();
+    return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.<E>absent();
   }
 
   /**
    * Returns an {@link Optional} containing the last element in this fluent iterable.
    * If the iterable is empty, {@code Optional.absent()} is returned.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.reduce((a, b) -> b)}.
+   *
    * @throws NullPointerException if the last element is null; if this is a possibility, use
    *     {@link Iterables#getLast} instead.
    */
+  @CheckReturnValue
   public final Optional<E> last() {
     // Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
 
@@ -335,6 +436,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * returned fluent iterable's iterator, as the {@code Iterator} contract states that a call
    * to {@code * remove()} before a call to {@code next()} will throw an
    * {@link IllegalStateException}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(numberToSkip)} (same).
    */
   @CheckReturnValue
   public final FluentIterable<E> skip(int numberToSkip) {
@@ -348,17 +451,22 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * The returned fluent iterable's iterator supports {@code remove()} if this
    * fluent iterable's iterator does.
    *
-   * @param size the maximum number of elements in the returned fluent iterable
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.limit(maxSize)} (same).
+   *
+   * @param maxSize the maximum number of elements in the returned fluent iterable
    * @throws IllegalArgumentException if {@code size} is negative
    */
   @CheckReturnValue
-  public final FluentIterable<E> limit(int size) {
-    return from(Iterables.limit(iterable, size));
+  public final FluentIterable<E> limit(int maxSize) {
+    return from(Iterables.limit(iterable, maxSize));
   }
 
   /**
    * Determines whether this fluent iterable is empty.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code !stream.findAny().isPresent()}.
    */
+  @CheckReturnValue
   public final boolean isEmpty() {
     return !iterable.iterator().hasNext();
   }
@@ -367,8 +475,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@code ImmutableList} containing all of the elements from this fluent iterable in
    * proper sequence.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableList.copyOf(stream.iterator())}.
+   *
    * @since 14.0 (since 12.0 as {@code toImmutableList()}).
    */
+  @CheckReturnValue
   public final ImmutableList<E> toList() {
     return ImmutableList.copyOf(iterable);
   }
@@ -378,10 +489,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * FluentIterable} in the order specified by {@code comparator}.  To produce an {@code
    * ImmutableList} sorted by its natural ordering, use {@code toSortedList(Ordering.natural())}.
    *
+   * <p><b>{@code Stream} equivalent:</b>
+   * {@code ImmutableList.copyOf(stream.sorted(comparator).iterator())}.
+   *
    * @param comparator the function by which to sort list elements
    * @throws NullPointerException if any element is null
    * @since 14.0 (since 13.0 as {@code toSortedImmutableList()}).
    */
+  @CheckReturnValue
   public final ImmutableList<E> toSortedList(Comparator<? super E> comparator) {
     return Ordering.from(comparator).immutableSortedCopy(iterable);
   }
@@ -390,8 +505,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns an {@code ImmutableSet} containing all of the elements from this fluent iterable with
    * duplicates removed.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableSet.copyOf(stream.iterator())}.
+   *
    * @since 14.0 (since 12.0 as {@code toImmutableSet()}).
    */
+  @CheckReturnValue
   public final ImmutableSet<E> toSet() {
     return ImmutableSet.copyOf(iterable);
   }
@@ -402,24 +520,48 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * {@code comparator.compare(x, y) == 0}) removed. To produce an {@code ImmutableSortedSet} sorted
    * by its natural ordering, use {@code toSortedSet(Ordering.natural())}.
    *
+   * <p><b>{@code Stream} equivalent:</b>
+   * {@code ImmutableSortedSet.copyOf(comparator, stream.iterator())}.
+   *
    * @param comparator the function by which to sort set elements
    * @throws NullPointerException if any element is null
    * @since 14.0 (since 12.0 as {@code toImmutableSortedSet()}).
    */
+  @CheckReturnValue
   public final ImmutableSortedSet<E> toSortedSet(Comparator<? super E> comparator) {
     return ImmutableSortedSet.copyOf(comparator, iterable);
   }
 
   /**
-   * Returns an immutable map for which the elements of this {@code FluentIterable} are the keys in
-   * the same order, mapped to values by the given function. If this iterable contains duplicate
-   * elements, the returned map will contain each distinct element once in the order it first
-   * appears.
+   * Returns an {@code ImmutableMultiset} containing all of the elements from this fluent iterable.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code ImmutableMultiset.copyOf(stream.iterator())}.
+   *
+   * @since 19.0
+   */
+  @CheckReturnValue
+  public final ImmutableMultiset<E> toMultiset() {
+    return ImmutableMultiset.copyOf(iterable);
+  }
+
+  /**
+   * Returns an immutable map whose keys are the distinct elements of this {@code FluentIterable}
+   * and whose value for each key was computed by {@code valueFunction}. The map's iteration order
+   * is the order of the first appearance of each key in this iterable.
+   *
+   * <p>When there are multiple instances of a key in this iterable, it is unspecified whether
+   * {@code valueFunction} will be applied to more than one instance of that key and, if it is,
+   * which result will be mapped to that key in the returned map.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code
+   * ImmutableMap.copyOf(stream.collect(Collectors.toMap(k -> k, valueFunction)))} (but note that
+   * this may not preserve the order of entries).
    *
    * @throws NullPointerException if any element of this iterable is {@code null}, or if {@code
    *     valueFunction} produces {@code null} for any key
    * @since 14.0
    */
+  @CheckReturnValue
   public final <V> ImmutableMap<E, V> toMap(Function<? super E, V> valueFunction) {
     return Maps.toMap(iterable, valueFunction);
   }
@@ -440,24 +582,49 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    *       <li>An element in this fluent iterable is null
    *       <li>{@code keyFunction} returns {@code null} for any element of this iterable
    *     </ul>
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.groupingBy(keyFunction))}
+   * behaves similarly, but returns a mutable {@code Map<K, List<E>>} instead, and may not preserve
+   * the order of entries).
+   *
    * @since 14.0
    */
+  @CheckReturnValue
   public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
     return Multimaps.index(iterable, keyFunction);
   }
 
   /**
-   * Returns an immutable map for which the {@link java.util.Map#values} are the elements of this
-   * {@code FluentIterable} in the given order, and each key is the product of invoking a supplied
-   * function on its corresponding value.
+   * Returns a map with the contents of this {@code FluentIterable} as its {@code values}, indexed
+   * by keys derived from those values. In other words, each input value produces an entry in the
+   * map whose key is the result of applying {@code keyFunction} to that value. These entries appear
+   * in the same order as they appeared in this fluent iterable. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   FluentIterable<Color> allColors = FluentIterable.from(ImmutableSet.of(red, green, blue));
+   *
+   *   Map<String, Color> colorForName = allColors.uniqueIndex(toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link #index(Function)
+   * index}.
+   *
+   * <p><b>{@code Stream} equivalent:</b> {@code
+   * ImmutableMap.copyOf(stream.collect(Collectors.toMap(keyFunction, v -> v)))} (but note that this
+   * may not preserve the order of entries).
    *
    * @param keyFunction the function used to produce the key for each value
-   * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one
-   *     value in this fluent iterable
-   * @throws NullPointerException if any element of this fluent iterable is null, or if
-   *     {@code keyFunction} produces {@code null} for any value
+   * @return a map mapping the result of evaluating the function {@code
+   *     keyFunction} on each value in this fluent iterable to that value
+   * @throws IllegalArgumentException if {@code keyFunction} produces the same
+   *     key for more than one value in this fluent iterable
+   * @throws NullPointerException if any elements of this fluent iterable is null, or
+   *     if {@code keyFunction} produces {@code null} for any value
    * @since 14.0
    */
+  @CheckReturnValue
   public final <K> ImmutableMap<K, E> uniqueIndex(Function<? super E, K> keyFunction) {
     return Maps.uniqueIndex(iterable, keyFunction);
   }
@@ -465,11 +632,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns an array containing all of the elements from this fluent iterable in iteration order.
    *
+   * <p><b>{@code Stream} equivalent:</b> if an object array is acceptable, use
+   * {@code stream.toArray()}; if {@code type} is a class literal such as {@code MyType.class}, use
+   * {@code stream.toArray(MyType[]::new)}. Otherwise use {@code stream.toArray(
+   * len -> (E[]) Array.newInstance(type, len))}.
+   *
    * @param type the type of the elements
    * @return a newly-allocated array into which all the elements of this fluent iterable have
    *     been copied
    */
   @GwtIncompatible("Array.newArray(Class, int)")
+  @CheckReturnValue
   public final E[] toArray(Class<E> type) {
     return Iterables.toArray(iterable, type);
   }
@@ -478,6 +651,9 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to
    * calling {@code Iterables.addAll(collection, this)}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.forEachOrdered(collection::add)} or
+   * {@code stream.forEach(collection::add)}.
+   *
    * @param collection the collection to copy elements to
    * @return {@code collection}, for convenience
    * @since 14.0
@@ -498,9 +674,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
    * Returns a {@link String} containing all of the elements of this fluent iterable joined with
    * {@code joiner}.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code joiner.join(stream.iterator())}, or, if you are not
+   * using any optional {@code Joiner} features,
+   * {@code stream.collect(Collectors.joining(delimiter)}.
+   *
    * @since 18.0
    */
   @Beta
+  @CheckReturnValue
   public final String join(Joiner joiner) {
     return joiner.join(this);
   }
@@ -508,11 +689,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Returns the element at the specified position in this fluent iterable.
    *
+   * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(position).findFirst().get()} (but note
+   * that this throws different exception types, and throws an exception if {@code null} would be
+   * returned).
+   *
    * @param position position of the element to return
    * @return the element at the specified position in this fluent iterable
    * @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
    *     the size of this fluent iterable
    */
+  // TODO(kevinb): add @Nullable?
+  @CheckReturnValue
   public final E get(int position) {
     return Iterables.get(iterable, position);
   }
@@ -520,8 +707,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
   /**
    * Function that transforms {@code Iterable<E>} into a fluent iterable.
    */
-  private static class FromIterableFunction<E>
-      implements Function<Iterable<E>, FluentIterable<E>> {
+  private static class FromIterableFunction<E> implements Function<Iterable<E>, FluentIterable<E>> {
     @Override
     public FluentIterable<E> apply(Iterable<E> fromObject) {
       return FluentIterable.from(fromObject);
diff --git a/guava/src/com/google/common/collect/ForwardingBlockingDeque.java b/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
index a6fb43d..ad3a21e 100644
--- a/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
+++ b/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
@@ -38,13 +38,14 @@ import java.util.concurrent.TimeUnit;
  * @author Emily Soldal
  * @since 14.0
  */
-public abstract class ForwardingBlockingDeque<E>
-    extends ForwardingDeque<E> implements BlockingDeque<E> {
+public abstract class ForwardingBlockingDeque<E> extends ForwardingDeque<E>
+    implements BlockingDeque<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingBlockingDeque() {}
 
-  @Override protected abstract BlockingDeque<E> delegate();
+  @Override
+  protected abstract BlockingDeque<E> delegate();
 
   @Override
   public int remainingCapacity() {
diff --git a/guava/src/com/google/common/collect/ForwardingCollection.java b/guava/src/com/google/common/collect/ForwardingCollection.java
index 8c1b22e..434e471 100644
--- a/guava/src/com/google/common/collect/ForwardingCollection.java
+++ b/guava/src/com/google/common/collect/ForwardingCollection.java
@@ -42,17 +42,17 @@ import javax.annotation.Nullable;
  *
  * @author Kevin Bourrillion
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingCollection<E> extends ForwardingObject
-    implements Collection<E> {
-  // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingCollection<E> extends ForwardingObject implements Collection<E> {
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingCollection() {}
 
-  @Override protected abstract Collection<E> delegate();
+  @Override
+  protected abstract Collection<E> delegate();
 
   @Override
   public Iterator<E> iterator() {
diff --git a/guava/src/com/google/common/collect/ForwardingConcurrentMap.java b/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
index 0336dd1..de42066 100644
--- a/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
+++ b/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
@@ -27,7 +27,7 @@ import java.util.concurrent.ConcurrentMap;
  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
  *
  * @author Charles Fry
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
@@ -36,7 +36,8 @@ public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
   /** Constructor for use by subclasses. */
   protected ForwardingConcurrentMap() {}
 
-  @Override protected abstract ConcurrentMap<K, V> delegate();
+  @Override
+  protected abstract ConcurrentMap<K, V> delegate();
 
   @Override
   public V putIfAbsent(K key, V value) {
@@ -57,5 +58,4 @@ public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
   public boolean replace(K key, V oldValue, V newValue) {
     return delegate().replace(key, oldValue, newValue);
   }
-
 }
diff --git a/guava/src/com/google/common/collect/ForwardingDeque.java b/guava/src/com/google/common/collect/ForwardingDeque.java
index 070f622..a58636a 100644
--- a/guava/src/com/google/common/collect/ForwardingDeque.java
+++ b/guava/src/com/google/common/collect/ForwardingDeque.java
@@ -34,13 +34,13 @@ import java.util.Iterator;
  * @author Kurt Alfred Kluever
  * @since 12.0
  */
-public abstract class ForwardingDeque<E> extends ForwardingQueue<E>
-    implements Deque<E> {
+public abstract class ForwardingDeque<E> extends ForwardingQueue<E> implements Deque<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingDeque() {}
 
-  @Override protected abstract Deque<E> delegate();
+  @Override
+  protected abstract Deque<E> delegate();
 
   @Override
   public void addFirst(E e) {
diff --git a/guava/src/com/google/common/collect/ForwardingIterator.java b/guava/src/com/google/common/collect/ForwardingIterator.java
index b8927d4..03cbc75 100644
--- a/guava/src/com/google/common/collect/ForwardingIterator.java
+++ b/guava/src/com/google/common/collect/ForwardingIterator.java
@@ -27,16 +27,16 @@ import java.util.Iterator;
  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingIterator<T>
-    extends ForwardingObject implements Iterator<T> {
+public abstract class ForwardingIterator<T> extends ForwardingObject implements Iterator<T> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingIterator() {}
 
-  @Override protected abstract Iterator<T> delegate();
+  @Override
+  protected abstract Iterator<T> delegate();
 
   @Override
   public boolean hasNext() {
diff --git a/guava/src/com/google/common/collect/ForwardingList.java b/guava/src/com/google/common/collect/ForwardingList.java
index 71ae993..288340f 100644
--- a/guava/src/com/google/common/collect/ForwardingList.java
+++ b/guava/src/com/google/common/collect/ForwardingList.java
@@ -49,17 +49,17 @@ import javax.annotation.Nullable;
  *
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingList<E> extends ForwardingCollection<E>
-    implements List<E> {
-  // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingList<E> extends ForwardingCollection<E> implements List<E> {
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingList() {}
 
-  @Override protected abstract List<E> delegate();
+  @Override
+  protected abstract List<E> delegate();
 
   @Override
   public void add(int index, E element) {
@@ -111,11 +111,13 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
     return delegate().subList(fromIndex, toIndex);
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this || delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 
@@ -140,8 +142,7 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  protected boolean standardAddAll(
-      int index, Iterable<? extends E> elements) {
+  protected boolean standardAddAll(int index, Iterable<? extends E> elements) {
     return Lists.addAllImpl(this, index, elements);
   }
 
@@ -200,7 +201,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Beta protected ListIterator<E> standardListIterator(int start) {
+  @Beta
+  protected ListIterator<E> standardListIterator(int start) {
     return Lists.listIteratorImpl(this, start);
   }
 
@@ -211,7 +213,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Beta protected List<E> standardSubList(int fromIndex, int toIndex) {
+  @Beta
+  protected List<E> standardSubList(int fromIndex, int toIndex) {
     return Lists.subListImpl(this, fromIndex, toIndex);
   }
 
@@ -222,7 +225,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Beta protected boolean standardEquals(@Nullable Object object) {
+  @Beta
+  protected boolean standardEquals(@Nullable Object object) {
     return Lists.equalsImpl(this, object);
   }
 
@@ -233,7 +237,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Beta protected int standardHashCode() {
+  @Beta
+  protected int standardHashCode() {
     return Lists.hashCodeImpl(this);
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingListIterator.java b/guava/src/com/google/common/collect/ForwardingListIterator.java
index e2ebe55..b7239ba 100644
--- a/guava/src/com/google/common/collect/ForwardingListIterator.java
+++ b/guava/src/com/google/common/collect/ForwardingListIterator.java
@@ -27,7 +27,7 @@ import java.util.ListIterator;
  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class ForwardingListIterator<E> extends ForwardingIterator<E>
@@ -36,7 +36,8 @@ public abstract class ForwardingListIterator<E> extends ForwardingIterator<E>
   /** Constructor for use by subclasses. */
   protected ForwardingListIterator() {}
 
-  @Override protected abstract ListIterator<E> delegate();
+  @Override
+  protected abstract ListIterator<E> delegate();
 
   @Override
   public void add(E element) {
diff --git a/guava/src/com/google/common/collect/ForwardingListMultimap.java b/guava/src/com/google/common/collect/ForwardingListMultimap.java
index 3b1d55e..477af99 100644
--- a/guava/src/com/google/common/collect/ForwardingListMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingListMultimap.java
@@ -32,23 +32,27 @@ import javax.annotation.Nullable;
  * @since 3.0
  */
 @GwtCompatible
-public abstract class ForwardingListMultimap<K, V>
-    extends ForwardingMultimap<K, V> implements ListMultimap<K, V> {
+public abstract class ForwardingListMultimap<K, V> extends ForwardingMultimap<K, V>
+    implements ListMultimap<K, V> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingListMultimap() {}
 
-  @Override protected abstract ListMultimap<K, V> delegate();
+  @Override
+  protected abstract ListMultimap<K, V> delegate();
 
-  @Override public List<V> get(@Nullable K key) {
+  @Override
+  public List<V> get(@Nullable K key) {
     return delegate().get(key);
   }
 
-  @Override public List<V> removeAll(@Nullable Object key) {
+  @Override
+  public List<V> removeAll(@Nullable Object key) {
     return delegate().removeAll(key);
   }
 
-  @Override public List<V> replaceValues(K key, Iterable<? extends V> values) {
+  @Override
+  public List<V> replaceValues(K key, Iterable<? extends V> values) {
     return delegate().replaceValues(key, values);
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingMap.java b/guava/src/com/google/common/collect/ForwardingMap.java
index 6816ba0..c550789 100644
--- a/guava/src/com/google/common/collect/ForwardingMap.java
+++ b/guava/src/com/google/common/collect/ForwardingMap.java
@@ -53,17 +53,17 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingMap<K, V> extends ForwardingObject
-    implements Map<K, V> {
-  // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingMap<K, V> extends ForwardingObject implements Map<K, V> {
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingMap() {}
 
-  @Override protected abstract Map<K, V> delegate();
+  @Override
+  protected abstract Map<K, V> delegate();
 
   @Override
   public int size() {
@@ -125,11 +125,13 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
     return delegate().entrySet();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this || delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 
@@ -157,7 +159,8 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
    *
    * @since 7.0
    */
-  @Beta protected V standardRemove(@Nullable Object key) {
+  @Beta
+  protected V standardRemove(@Nullable Object key) {
     Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
     while (entryIterator.hasNext()) {
       Entry<K, V> entry = entryIterator.next();
@@ -208,7 +211,8 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
    *
    * @since 7.0
    */
-  @Beta protected boolean standardContainsKey(@Nullable Object key) {
+  @Beta
+  protected boolean standardContainsKey(@Nullable Object key) {
     return Maps.containsKeyImpl(this, key);
   }
 
diff --git a/guava/src/com/google/common/collect/ForwardingMapEntry.java b/guava/src/com/google/common/collect/ForwardingMapEntry.java
index 4d63757..559f0bb 100644
--- a/guava/src/com/google/common/collect/ForwardingMapEntry.java
+++ b/guava/src/com/google/common/collect/ForwardingMapEntry.java
@@ -49,17 +49,17 @@ import javax.annotation.Nullable;
  *
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingMapEntry<K, V>
-    extends ForwardingObject implements Map.Entry<K, V> {
-  // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingMapEntry<K, V> extends ForwardingObject implements Map.Entry<K, V> {
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingMapEntry() {}
 
-  @Override protected abstract Map.Entry<K, V> delegate();
+  @Override
+  protected abstract Map.Entry<K, V> delegate();
 
   @Override
   public K getKey() {
@@ -76,11 +76,13 @@ public abstract class ForwardingMapEntry<K, V>
     return delegate().setValue(value);
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 
@@ -122,7 +124,8 @@ public abstract class ForwardingMapEntry<K, V>
    *
    * @since 7.0
    */
-  @Beta protected String standardToString() {
+  @Beta
+  protected String standardToString() {
     return getKey() + "=" + getValue();
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingMultimap.java b/guava/src/com/google/common/collect/ForwardingMultimap.java
index c860820..5410a1b 100644
--- a/guava/src/com/google/common/collect/ForwardingMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingMultimap.java
@@ -32,16 +32,16 @@ import javax.annotation.Nullable;
  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
  *
  * @author Robert Konigsberg
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingMultimap<K, V> extends ForwardingObject
-    implements Multimap<K, V> {
+public abstract class ForwardingMultimap<K, V> extends ForwardingObject implements Multimap<K, V> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingMultimap() {}
 
-  @Override protected abstract Multimap<K, V> delegate();
+  @Override
+  protected abstract Multimap<K, V> delegate();
 
   @Override
   public Map<K, Collection<V>> asMap() {
@@ -133,11 +133,13 @@ public abstract class ForwardingMultimap<K, V> extends ForwardingObject
     return delegate().values();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this || delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingMultiset.java b/guava/src/com/google/common/collect/ForwardingMultiset.java
index 9834751..9d70d84 100644
--- a/guava/src/com/google/common/collect/ForwardingMultiset.java
+++ b/guava/src/com/google/common/collect/ForwardingMultiset.java
@@ -46,16 +46,16 @@ import javax.annotation.Nullable;
  *
  * @author Kevin Bourrillion
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
-    implements Multiset<E> {
+public abstract class ForwardingMultiset<E> extends ForwardingCollection<E> implements Multiset<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingMultiset() {}
 
-  @Override protected abstract Multiset<E> delegate();
+  @Override
+  protected abstract Multiset<E> delegate();
 
   @Override
   public int count(Object element) {
@@ -82,11 +82,13 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
     return delegate().entrySet();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this || delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 
@@ -104,10 +106,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * A sensible definition of {@link #contains} in terms of {@link #count}. If
    * you override {@link #count}, you may wish to override {@link #contains} to
    * forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
-  @Override protected boolean standardContains(@Nullable Object object) {
+  @Override
+  protected boolean standardContains(@Nullable Object object) {
     return count(object) > 0;
   }
 
@@ -118,7 +121,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Override protected void standardClear() {
+  @Override
+  protected void standardClear() {
     Iterators.clear(entrySet().iterator());
   }
 
@@ -126,10 +130,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * A sensible, albeit inefficient, definition of {@link #count} in terms of
    * {@link #entrySet}. If you override {@link #entrySet}, you may wish to
    * override {@link #count} to forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
-  @Beta protected int standardCount(@Nullable Object object) {
+  @Beta
+  protected int standardCount(@Nullable Object object) {
     for (Entry<?> entry : this.entrySet()) {
       if (Objects.equal(entry.getElement(), object)) {
         return entry.getCount();
@@ -142,7 +147,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * A sensible definition of {@link #add(Object)} in terms of {@link
    * #add(Object, int)}. If you override {@link #add(Object, int)}, you may
    * wish to override {@link #add(Object)} to forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected boolean standardAdd(E element) {
@@ -155,11 +160,12 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * #add(Object)} and {@link #add(Object, int)}. If you override either of
    * these methods, you may wish to override {@link #addAll(Collection)} to
    * forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
-  @Beta @Override protected boolean standardAddAll(
-      Collection<? extends E> elementsToAdd) {
+  @Beta
+  @Override
+  protected boolean standardAddAll(Collection<? extends E> elementsToAdd) {
     return Multisets.addAllImpl(this, elementsToAdd);
   }
 
@@ -168,10 +174,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * #remove(Object, int)}. If you override {@link #remove(Object, int)}, you
    * may wish to override {@link #remove(Object)} to forward to this
    * implementation.
-   * 
+   *
    * @since 7.0
    */
-  @Override protected boolean standardRemove(Object element) {
+  @Override
+  protected boolean standardRemove(Object element) {
     return remove(element, 1) > 0;
   }
 
@@ -183,8 +190,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Override protected boolean standardRemoveAll(
-      Collection<?> elementsToRemove) {
+  @Override
+  protected boolean standardRemoveAll(Collection<?> elementsToRemove) {
     return Multisets.removeAllImpl(this, elementsToRemove);
   }
 
@@ -196,8 +203,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Override protected boolean standardRetainAll(
-      Collection<?> elementsToRetain) {
+  @Override
+  protected boolean standardRetainAll(Collection<?> elementsToRetain) {
     return Multisets.retainAllImpl(this, elementsToRetain);
   }
 
@@ -207,7 +214,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * int)}. {@link #entrySet()}. If you override any of these methods, you may
    * wish to override {@link #setCount(Object, int)} to forward to this
    * implementation.
-   * 
+   *
    * @since 7.0
    */
   protected int standardSetCount(E element, int count) {
@@ -249,12 +256,12 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
       return ForwardingMultiset.this;
     }
   }
-  
+
   /**
    * A sensible definition of {@link #iterator} in terms of {@link #entrySet}
    * and {@link #remove(Object)}. If you override either of these methods, you
    * may wish to override {@link #iterator} to forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected Iterator<E> standardIterator() {
@@ -265,7 +272,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    * A sensible, albeit inefficient, definition of {@link #size} in terms of
    * {@link #entrySet}. If you override {@link #entrySet}, you may wish to
    * override {@link #size} to forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected int standardSize() {
@@ -302,7 +309,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
    *
    * @since 7.0
    */
-  @Override protected String standardToString() {
+  @Override
+  protected String standardToString() {
     return entrySet().toString();
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingNavigableMap.java b/guava/src/com/google/common/collect/ForwardingNavigableMap.java
index 3e11239..b022d1a 100644
--- a/guava/src/com/google/common/collect/ForwardingNavigableMap.java
+++ b/guava/src/com/google/common/collect/ForwardingNavigableMap.java
@@ -49,8 +49,8 @@ import java.util.SortedMap;
  * @author Louis Wasserman
  * @since 12.0
  */
-public abstract class ForwardingNavigableMap<K, V>
-    extends ForwardingSortedMap<K, V> implements NavigableMap<K, V> {
+public abstract class ForwardingNavigableMap<K, V> extends ForwardingSortedMap<K, V>
+    implements NavigableMap<K, V> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingNavigableMap() {}
diff --git a/guava/src/com/google/common/collect/ForwardingNavigableSet.java b/guava/src/com/google/common/collect/ForwardingNavigableSet.java
index dff5ea0..447f397 100644
--- a/guava/src/com/google/common/collect/ForwardingNavigableSet.java
+++ b/guava/src/com/google/common/collect/ForwardingNavigableSet.java
@@ -44,8 +44,8 @@ import java.util.SortedSet;
  * @author Louis Wasserman
  * @since 12.0
  */
-public abstract class ForwardingNavigableSet<E>
-    extends ForwardingSortedSet<E> implements NavigableSet<E> {
+public abstract class ForwardingNavigableSet<E> extends ForwardingSortedSet<E>
+    implements NavigableSet<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingNavigableSet() {}
@@ -174,10 +174,7 @@ public abstract class ForwardingNavigableSet<E>
 
   @Override
   public NavigableSet<E> subSet(
-      E fromElement,
-      boolean fromInclusive,
-      E toElement,
-      boolean toInclusive) {
+      E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
     return delegate().subSet(fromElement, fromInclusive, toElement, toInclusive);
   }
 
@@ -188,10 +185,7 @@ public abstract class ForwardingNavigableSet<E>
    */
   @Beta
   protected NavigableSet<E> standardSubSet(
-      E fromElement,
-      boolean fromInclusive,
-      E toElement,
-      boolean toInclusive) {
+      E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
     return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive);
   }
 
diff --git a/guava/src/com/google/common/collect/ForwardingObject.java b/guava/src/com/google/common/collect/ForwardingObject.java
index 7fecdee..b25538c 100644
--- a/guava/src/com/google/common/collect/ForwardingObject.java
+++ b/guava/src/com/google/common/collect/ForwardingObject.java
@@ -47,7 +47,7 @@ import java.io.Serializable;
  * created since this class has a parameter-less constructor.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class ForwardingObject {
@@ -68,7 +68,8 @@ public abstract class ForwardingObject {
    * Returns the string representation generated by the delegate's
    * {@code toString} method.
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return delegate().toString();
   }
 
diff --git a/guava/src/com/google/common/collect/ForwardingQueue.java b/guava/src/com/google/common/collect/ForwardingQueue.java
index 569880a..c150bdb 100644
--- a/guava/src/com/google/common/collect/ForwardingQueue.java
+++ b/guava/src/com/google/common/collect/ForwardingQueue.java
@@ -39,16 +39,16 @@ import java.util.Queue;
  *
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
-    implements Queue<E> {
+public abstract class ForwardingQueue<E> extends ForwardingCollection<E> implements Queue<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingQueue() {}
 
-  @Override protected abstract Queue<E> delegate();
+  @Override
+  protected abstract Queue<E> delegate();
 
   @Override
   public boolean offer(E o) {
@@ -79,7 +79,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
    * A sensible definition of {@link #offer} in terms of {@link #add}. If you
    * override {@link #add}, you may wish to override {@link #offer} to forward
    * to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected boolean standardOffer(E e) {
@@ -94,7 +94,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
    * A sensible definition of {@link #peek} in terms of {@link #element}. If you
    * override {@link #element}, you may wish to override {@link #peek} to
    * forward to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected E standardPeek() {
@@ -109,7 +109,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
    * A sensible definition of {@link #poll} in terms of {@link #remove}. If you
    * override {@link #remove}, you may wish to override {@link #poll} to forward
    * to this implementation.
-   * 
+   *
    * @since 7.0
    */
   protected E standardPoll() {
diff --git a/guava/src/com/google/common/collect/ForwardingSet.java b/guava/src/com/google/common/collect/ForwardingSet.java
index e1a4485..0430af8 100644
--- a/guava/src/com/google/common/collect/ForwardingSet.java
+++ b/guava/src/com/google/common/collect/ForwardingSet.java
@@ -43,23 +43,25 @@ import javax.annotation.Nullable;
  *
  * @author Kevin Bourrillion
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingSet<E> extends ForwardingCollection<E>
-    implements Set<E> {
-  // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingSet<E> extends ForwardingCollection<E> implements Set<E> {
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingSet() {}
 
-  @Override protected abstract Set<E> delegate();
+  @Override
+  protected abstract Set<E> delegate();
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return object == this || delegate().equals(object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 
diff --git a/guava/src/com/google/common/collect/ForwardingSetMultimap.java b/guava/src/com/google/common/collect/ForwardingSetMultimap.java
index a923946..dde1ff6 100644
--- a/guava/src/com/google/common/collect/ForwardingSetMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingSetMultimap.java
@@ -33,24 +33,29 @@ import javax.annotation.Nullable;
  * @since 3.0
  */
 @GwtCompatible
-public abstract class ForwardingSetMultimap<K, V>
-    extends ForwardingMultimap<K, V> implements SetMultimap<K, V> {
+public abstract class ForwardingSetMultimap<K, V> extends ForwardingMultimap<K, V>
+    implements SetMultimap<K, V> {
 
-  @Override protected abstract SetMultimap<K, V> delegate();
+  @Override
+  protected abstract SetMultimap<K, V> delegate();
 
-  @Override public Set<Entry<K, V>> entries() {
+  @Override
+  public Set<Entry<K, V>> entries() {
     return delegate().entries();
   }
 
-  @Override public Set<V> get(@Nullable K key) {
+  @Override
+  public Set<V> get(@Nullable K key) {
     return delegate().get(key);
   }
 
-  @Override public Set<V> removeAll(@Nullable Object key) {
+  @Override
+  public Set<V> removeAll(@Nullable Object key) {
     return delegate().removeAll(key);
   }
 
-  @Override public Set<V> replaceValues(K key, Iterable<? extends V> values) {
+  @Override
+  public Set<V> replaceValues(K key, Iterable<? extends V> values) {
     return delegate().replaceValues(key, values);
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingSortedMap.java b/guava/src/com/google/common/collect/ForwardingSortedMap.java
index 1235e56..5ccd45b 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedMap.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedMap.java
@@ -50,17 +50,18 @@ import javax.annotation.Nullable;
  *
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
     implements SortedMap<K, V> {
-  // TODO(user): identify places where thread safety is actually lost
+  // TODO(lowasser): identify places where thread safety is actually lost
 
   /** Constructor for use by subclasses. */
   protected ForwardingSortedMap() {}
 
-  @Override protected abstract SortedMap<K, V> delegate();
+  @Override
+  protected abstract SortedMap<K, V> delegate();
 
   @Override
   public Comparator<? super K> comparator() {
@@ -126,7 +127,9 @@ public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
    *
    * @since 7.0
    */
-  @Override @Beta protected boolean standardContainsKey(@Nullable Object key) {
+  @Override
+  @Beta
+  protected boolean standardContainsKey(@Nullable Object key) {
     try {
       // any CCE will be caught
       @SuppressWarnings("unchecked")
@@ -150,7 +153,8 @@ public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
    *
    * @since 7.0
    */
-  @Beta protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
+  @Beta
+  protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
     checkArgument(unsafeCompare(fromKey, toKey) <= 0, "fromKey must be <= toKey");
     return tailMap(fromKey).headMap(toKey);
   }
diff --git a/guava/src/com/google/common/collect/ForwardingSortedMultiset.java b/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
index 9ec79b8..2f0cbbe 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
@@ -92,8 +92,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
    * In many cases, you may wish to override {@link #descendingMultiset()} to return an instance of
    * a subclass of {@code StandardDescendingMultiset}.
    */
-  protected abstract class StandardDescendingMultiset
-      extends DescendingMultiset<E> {
+  protected abstract class StandardDescendingMultiset extends DescendingMultiset<E> {
     /** Constructor for use by subclasses. */
     public StandardDescendingMultiset() {}
 
@@ -136,9 +135,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
    * {@link #firstEntry()} to forward to this implementation.
    */
   protected Entry<E> standardLastEntry() {
-    Iterator<Entry<E>> entryIterator = descendingMultiset()
-        .entrySet()
-        .iterator();
+    Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
     if (!entryIterator.hasNext()) {
       return null;
     }
@@ -181,9 +178,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
    * {@link #pollLastEntry()} to forward to this implementation.
    */
   protected Entry<E> standardPollLastEntry() {
-    Iterator<Entry<E>> entryIterator = descendingMultiset()
-        .entrySet()
-        .iterator();
+    Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
     if (!entryIterator.hasNext()) {
       return null;
     }
@@ -221,5 +216,4 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
   public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
     return delegate().tailMultiset(lowerBound, boundType);
   }
-
 }
diff --git a/guava/src/com/google/common/collect/ForwardingSortedSet.java b/guava/src/com/google/common/collect/ForwardingSortedSet.java
index 756d9af..63ebec2 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedSet.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedSet.java
@@ -51,16 +51,16 @@ import javax.annotation.Nullable;
  *
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
-public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
-    implements SortedSet<E> {
+public abstract class ForwardingSortedSet<E> extends ForwardingSet<E> implements SortedSet<E> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingSortedSet() {}
 
-  @Override protected abstract SortedSet<E> delegate();
+  @Override
+  protected abstract SortedSet<E> delegate();
 
   @Override
   public Comparator<? super E> comparator() {
@@ -108,7 +108,9 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
    *
    * @since 7.0
    */
-  @Override @Beta protected boolean standardContains(@Nullable Object object) {
+  @Override
+  @Beta
+  protected boolean standardContains(@Nullable Object object) {
     try {
       // any ClassCastExceptions are caught
       @SuppressWarnings("unchecked")
@@ -131,7 +133,9 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
    *
    * @since 7.0
    */
-  @Override @Beta protected boolean standardRemove(@Nullable Object object) {
+  @Override
+  @Beta
+  protected boolean standardRemove(@Nullable Object object) {
     try {
       // any ClassCastExceptions are caught
       @SuppressWarnings("unchecked")
@@ -160,7 +164,8 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
    *
    * @since 7.0
    */
-  @Beta protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
+  @Beta
+  protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
     return tailSet(fromElement).headSet(toElement);
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java b/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
index d90c305..b800b7b 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
@@ -33,28 +33,32 @@ import javax.annotation.Nullable;
  * @since 3.0
  */
 @GwtCompatible
-public abstract class ForwardingSortedSetMultimap<K, V>
-    extends ForwardingSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+public abstract class ForwardingSortedSetMultimap<K, V> extends ForwardingSetMultimap<K, V>
+    implements SortedSetMultimap<K, V> {
 
   /** Constructor for use by subclasses. */
   protected ForwardingSortedSetMultimap() {}
 
-  @Override protected abstract SortedSetMultimap<K, V> delegate();
+  @Override
+  protected abstract SortedSetMultimap<K, V> delegate();
 
-  @Override public SortedSet<V> get(@Nullable K key) {
+  @Override
+  public SortedSet<V> get(@Nullable K key) {
     return delegate().get(key);
   }
 
-  @Override public SortedSet<V> removeAll(@Nullable Object key) {
+  @Override
+  public SortedSet<V> removeAll(@Nullable Object key) {
     return delegate().removeAll(key);
   }
 
-  @Override public SortedSet<V> replaceValues(
-      K key, Iterable<? extends V> values) {
+  @Override
+  public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
     return delegate().replaceValues(key, values);
   }
 
-  @Override public Comparator<? super V> valueComparator() {
+  @Override
+  public Comparator<? super V> valueComparator() {
     return delegate().valueComparator();
   }
 }
diff --git a/guava/src/com/google/common/collect/ForwardingTable.java b/guava/src/com/google/common/collect/ForwardingTable.java
index 92cc876..a5f1b83 100644
--- a/guava/src/com/google/common/collect/ForwardingTable.java
+++ b/guava/src/com/google/common/collect/ForwardingTable.java
@@ -32,12 +32,12 @@ import java.util.Set;
  * @since 7.0
  */
 @GwtCompatible
-public abstract class ForwardingTable<R, C, V> extends ForwardingObject
-    implements Table<R, C, V> {
+public abstract class ForwardingTable<R, C, V> extends ForwardingObject implements Table<R, C, V> {
   /** Constructor for use by subclasses. */
   protected ForwardingTable() {}
 
-  @Override protected abstract Table<R, C, V> delegate();
+  @Override
+  protected abstract Table<R, C, V> delegate();
 
   @Override
   public Set<Cell<R, C, V>> cellSet() {
@@ -134,11 +134,13 @@ public abstract class ForwardingTable<R, C, V> extends ForwardingObject
     return delegate().values();
   }
 
-  @Override public boolean equals(Object obj) {
+  @Override
+  public boolean equals(Object obj) {
     return (obj == this) || delegate().equals(obj);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return delegate().hashCode();
   }
 }
diff --git a/guava/src/com/google/common/collect/GeneralRange.java b/guava/src/com/google/common/collect/GeneralRange.java
index cb3b2c8..74fe62b 100644
--- a/guava/src/com/google/common/collect/GeneralRange.java
+++ b/guava/src/com/google/common/collect/GeneralRange.java
@@ -42,15 +42,19 @@ final class GeneralRange<T> implements Serializable {
    * Converts a Range to a GeneralRange.
    */
   static <T extends Comparable> GeneralRange<T> from(Range<T> range) {
-    @Nullable
-    T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
+    @Nullable T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
     BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN;
 
-    @Nullable
-    T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
+    @Nullable T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
     BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN;
-    return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint,
-        lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType);
+    return new GeneralRange<T>(
+        Ordering.natural(),
+        range.hasLowerBound(),
+        lowerEndpoint,
+        lowerBoundType,
+        range.hasUpperBound(),
+        upperEndpoint,
+        upperBoundType);
   }
 
   /**
@@ -64,8 +68,8 @@ final class GeneralRange<T> implements Serializable {
    * Returns everything above the endpoint relative to the specified comparator, with the specified
    * endpoint behavior.
    */
-  static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint,
-      BoundType boundType) {
+  static <T> GeneralRange<T> downTo(
+      Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
     return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN);
   }
 
@@ -73,8 +77,8 @@ final class GeneralRange<T> implements Serializable {
    * Returns everything below the endpoint relative to the specified comparator, with the specified
    * endpoint behavior.
    */
-  static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint,
-      BoundType boundType) {
+  static <T> GeneralRange<T> upTo(
+      Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
     return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType);
   }
 
@@ -82,24 +86,31 @@ final class GeneralRange<T> implements Serializable {
    * Returns everything between the endpoints relative to the specified comparator, with the
    * specified endpoint behavior.
    */
-  static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower,
-      BoundType lowerType, @Nullable T upper, BoundType upperType) {
+  static <T> GeneralRange<T> range(
+      Comparator<? super T> comparator,
+      @Nullable T lower,
+      BoundType lowerType,
+      @Nullable T upper,
+      BoundType upperType) {
     return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType);
   }
 
   private final Comparator<? super T> comparator;
   private final boolean hasLowerBound;
-  @Nullable
-  private final T lowerEndpoint;
+  @Nullable private final T lowerEndpoint;
   private final BoundType lowerBoundType;
   private final boolean hasUpperBound;
-  @Nullable
-  private final T upperEndpoint;
+  @Nullable private final T upperEndpoint;
   private final BoundType upperBoundType;
 
-  private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound,
-      @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound,
-      @Nullable T upperEndpoint, BoundType upperBoundType) {
+  private GeneralRange(
+      Comparator<? super T> comparator,
+      boolean hasLowerBound,
+      @Nullable T lowerEndpoint,
+      BoundType lowerBoundType,
+      boolean hasUpperBound,
+      @Nullable T upperEndpoint,
+      BoundType upperBoundType) {
     this.comparator = checkNotNull(comparator);
     this.hasLowerBound = hasLowerBound;
     this.hasUpperBound = hasUpperBound;
@@ -117,8 +128,8 @@ final class GeneralRange<T> implements Serializable {
     if (hasLowerBound && hasUpperBound) {
       int cmp = comparator.compare(lowerEndpoint, upperEndpoint);
       // be consistent with Range
-      checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint,
-          upperEndpoint);
+      checkArgument(
+          cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint, upperEndpoint);
       if (cmp == 0) {
         checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN);
       }
@@ -172,8 +183,7 @@ final class GeneralRange<T> implements Serializable {
     checkArgument(comparator.equals(other.comparator));
 
     boolean hasLowBound = this.hasLowerBound;
-    @Nullable
-    T lowEnd = getLowerEndpoint();
+    @Nullable T lowEnd = getLowerEndpoint();
     BoundType lowType = getLowerBoundType();
     if (!hasLowerBound()) {
       hasLowBound = other.hasLowerBound;
@@ -188,8 +198,7 @@ final class GeneralRange<T> implements Serializable {
     }
 
     boolean hasUpBound = this.hasUpperBound;
-    @Nullable
-    T upEnd = getUpperEndpoint();
+    @Nullable T upEnd = getUpperEndpoint();
     BoundType upType = getUpperBoundType();
     if (!hasUpperBound()) {
       hasUpBound = other.hasUpperBound;
@@ -220,8 +229,10 @@ final class GeneralRange<T> implements Serializable {
   public boolean equals(@Nullable Object obj) {
     if (obj instanceof GeneralRange) {
       GeneralRange<?> r = (GeneralRange<?>) obj;
-      return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound
-          && hasUpperBound == r.hasUpperBound && getLowerBoundType().equals(r.getLowerBoundType())
+      return comparator.equals(r.comparator)
+          && hasLowerBound == r.hasLowerBound
+          && hasUpperBound == r.hasUpperBound
+          && getLowerBoundType().equals(r.getLowerBoundType())
           && getUpperBoundType().equals(r.getUpperBoundType())
           && Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())
           && Objects.equal(getUpperEndpoint(), r.getUpperEndpoint());
@@ -231,7 +242,11 @@ final class GeneralRange<T> implements Serializable {
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(),
+    return Objects.hashCode(
+        comparator,
+        getLowerEndpoint(),
+        getLowerBoundType(),
+        getUpperEndpoint(),
         getUpperBoundType());
   }
 
@@ -244,8 +259,13 @@ final class GeneralRange<T> implements Serializable {
     GeneralRange<T> result = reverse;
     if (result == null) {
       result = new GeneralRange<T>(
-          Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(),
-          getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType());
+          Ordering.from(comparator).reverse(),
+          hasUpperBound,
+          getUpperEndpoint(),
+          getUpperBoundType(),
+          hasLowerBound,
+          getLowerEndpoint(),
+          getLowerBoundType());
       result.reverse = this;
       return this.reverse = result;
     }
diff --git a/guava/src/com/google/common/collect/GenericMapMaker.java b/guava/src/com/google/common/collect/GenericMapMaker.java
index 77ac673..c951c6c 100644
--- a/guava/src/com/google/common/collect/GenericMapMaker.java
+++ b/guava/src/com/google/common/collect/GenericMapMaker.java
@@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit;
  *     com.google.common.cache.CacheBuilder}, which is a properly generified class and thus needs no
  *     "Generic" equivalent; simple use {@code CacheBuilder} naturally. For general migration
  *     instructions, see the <a
- *     href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker Migration
+ *     href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker Migration
  *     Guide</a>.
  */
 @Beta
@@ -102,12 +102,11 @@ abstract class GenericMapMaker<K0, V0> {
    * @deprecated Caching functionality in {@code MapMaker} has been moved to {@link
    *     com.google.common.cache.CacheBuilder}, with {@link #softValues} being replaced by {@link
    *     com.google.common.cache.CacheBuilder#softValues}. Note that {@code CacheBuilder} is simply
-   *     an enhanced API for an implementation which was branched from {@code MapMaker}. <b>This
-   *     method is scheduled for removal in March 2015.</b>
+   *     an enhanced API for an implementation which was branched from {@code MapMaker}.
    */
   @Deprecated
   @GwtIncompatible("java.lang.ref.SoftReference")
-  public abstract GenericMapMaker<K0, V0> softValues();
+  abstract GenericMapMaker<K0, V0> softValues();
 
   /**
    * See {@link MapMaker#expireAfterWrite}.
diff --git a/guava/src/com/google/common/collect/GwtTransient.java b/guava/src/com/google/common/collect/GwtTransient.java
index a9a15e9..1719456 100644
--- a/guava/src/com/google/common/collect/GwtTransient.java
+++ b/guava/src/com/google/common/collect/GwtTransient.java
@@ -34,5 +34,4 @@ import java.lang.annotation.Target;
 @GwtCompatible
 @Retention(RUNTIME)
 @Target(FIELD)
- at interface GwtTransient {
-}
+ at interface GwtTransient {}
diff --git a/guava/src/com/google/common/collect/HashBasedTable.java b/guava/src/com/google/common/collect/HashBasedTable.java
index caf213c..b58d600 100644
--- a/guava/src/com/google/common/collect/HashBasedTable.java
+++ b/guava/src/com/google/common/collect/HashBasedTable.java
@@ -44,9 +44,9 @@ import javax.annotation.Nullable;
  * <p>Note that this implementation is not synchronized. If multiple threads
  * access this table concurrently and one of the threads modifies the table, it
  * must be synchronized externally.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
  * {@code Table}</a>.
  *
  * @author Jared Levy
@@ -54,16 +54,18 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(serializable = true)
 public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
-  private static class Factory<C, V>
-      implements Supplier<Map<C, V>>, Serializable {
+  private static class Factory<C, V> implements Supplier<Map<C, V>>, Serializable {
     final int expectedSize;
+
     Factory(int expectedSize) {
       this.expectedSize = expectedSize;
     }
+
     @Override
     public Map<C, V> get() {
       return Maps.newHashMapWithExpectedSize(expectedSize);
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -71,8 +73,7 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
    * Creates an empty {@code HashBasedTable}.
    */
   public static <R, C, V> HashBasedTable<R, C, V> create() {
-    return new HashBasedTable<R, C, V>(
-        new HashMap<R, Map<C, V>>(), new Factory<C, V>(0));
+    return new HashBasedTable<R, C, V>(new HashMap<R, Map<C, V>>(), new Factory<C, V>(0));
   }
 
   /**
@@ -87,10 +88,8 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
   public static <R, C, V> HashBasedTable<R, C, V> create(
       int expectedRows, int expectedCellsPerRow) {
     checkNonnegative(expectedCellsPerRow, "expectedCellsPerRow");
-    Map<R, Map<C, V>> backingMap =
-        Maps.newHashMapWithExpectedSize(expectedRows);
-    return new HashBasedTable<R, C, V>(
-        backingMap, new Factory<C, V>(expectedCellsPerRow));
+    Map<R, Map<C, V>> backingMap = Maps.newHashMapWithExpectedSize(expectedRows);
+    return new HashBasedTable<R, C, V>(backingMap, new Factory<C, V>(expectedCellsPerRow));
   }
 
   /**
@@ -114,33 +113,38 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
 
   // Overriding so NullPointerTester test passes.
 
-  @Override public boolean contains(
-      @Nullable Object rowKey, @Nullable Object columnKey) {
+  @Override
+  public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
     return super.contains(rowKey, columnKey);
   }
 
-  @Override public boolean containsColumn(@Nullable Object columnKey) {
+  @Override
+  public boolean containsColumn(@Nullable Object columnKey) {
     return super.containsColumn(columnKey);
   }
 
-  @Override public boolean containsRow(@Nullable Object rowKey) {
+  @Override
+  public boolean containsRow(@Nullable Object rowKey) {
     return super.containsRow(rowKey);
   }
 
-  @Override public boolean containsValue(@Nullable Object value) {
+  @Override
+  public boolean containsValue(@Nullable Object value) {
     return super.containsValue(value);
   }
 
-  @Override public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
+  @Override
+  public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
     return super.get(rowKey, columnKey);
   }
 
-  @Override public boolean equals(@Nullable Object obj) {
+  @Override
+  public boolean equals(@Nullable Object obj) {
     return super.equals(obj);
   }
 
-  @Override public V remove(
-      @Nullable Object rowKey, @Nullable Object columnKey) {
+  @Override
+  public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
     return super.remove(rowKey, columnKey);
   }
 
diff --git a/guava/src/com/google/common/collect/HashBiMap.java b/guava/src/com/google/common/collect/HashBiMap.java
index c597de6..e2738fe 100644
--- a/guava/src/com/google/common/collect/HashBiMap.java
+++ b/guava/src/com/google/common/collect/HashBiMap.java
@@ -17,10 +17,13 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
 import static com.google.common.collect.CollectPreconditions.checkRemove;
+import static com.google.common.collect.Hashing.smearedHash;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -41,15 +44,16 @@ import javax.annotation.Nullable;
  * {@code HashBiMap} 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}
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap"> {@code BiMap}
  * </a>.
  *
  * @author Louis Wasserman
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
-public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable {
+public final class HashBiMap<K, V> extends IteratorBasedAbstractMap<K, V>
+    implements BiMap<K, V>, Serializable {
 
   /**
    * Returns a new, empty {@code HashBiMap} with the default initial capacity (16).
@@ -82,11 +86,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
     final int keyHash;
     final int valueHash;
 
-    @Nullable
-    BiEntry<K, V> nextInKToVBucket;
+    @Nullable BiEntry<K, V> nextInKToVBucket;
+    @Nullable BiEntry<K, V> nextInVToKBucket;
 
-    @Nullable
-    BiEntry<K, V> nextInVToKBucket;
+    @Nullable BiEntry<K, V> nextInKeyInsertionOrder;
+    @Nullable BiEntry<K, V> prevInKeyInsertionOrder;
 
     BiEntry(K key, int keyHash, V value, int valueHash) {
       super(key, value);
@@ -96,9 +100,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   }
 
   private static final double LOAD_FACTOR = 1.0;
-  
+
   private transient BiEntry<K, V>[] hashTableKToV;
   private transient BiEntry<K, V>[] hashTableVToK;
+  private transient BiEntry<K, V> firstInKeyInsertionOrder;
+  private transient BiEntry<K, V> lastInKeyInsertionOrder;
   private transient int size;
   private transient int mask;
   private transient int modCount;
@@ -112,9 +118,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
     int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR);
     this.hashTableKToV = createTable(tableSize);
     this.hashTableVToK = createTable(tableSize);
+    this.firstInKeyInsertionOrder = null;
+    this.lastInKeyInsertionOrder = null;
+    this.size = 0;
     this.mask = tableSize - 1;
     this.modCount = 0;
-    this.size = 0;
   }
 
   /**
@@ -124,7 +132,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   private void delete(BiEntry<K, V> entry) {
     int keyBucket = entry.keyHash & mask;
     BiEntry<K, V> prevBucketEntry = null;
-    for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true;
+    for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket];
+        true;
         bucketEntry = bucketEntry.nextInKToVBucket) {
       if (bucketEntry == entry) {
         if (prevBucketEntry == null) {
@@ -139,7 +148,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
     int valueBucket = entry.valueHash & mask;
     prevBucketEntry = null;
-    for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];;
+    for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];
+        true;
         bucketEntry = bucketEntry.nextInVToKBucket) {
       if (bucketEntry == entry) {
         if (prevBucketEntry == null) {
@@ -152,11 +162,23 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       prevBucketEntry = bucketEntry;
     }
 
+    if (entry.prevInKeyInsertionOrder == null) {
+      firstInKeyInsertionOrder = entry.nextInKeyInsertionOrder;
+    } else {
+      entry.prevInKeyInsertionOrder.nextInKeyInsertionOrder = entry.nextInKeyInsertionOrder;
+    }
+
+    if (entry.nextInKeyInsertionOrder == null) {
+      lastInKeyInsertionOrder = entry.prevInKeyInsertionOrder;
+    } else {
+      entry.nextInKeyInsertionOrder.prevInKeyInsertionOrder = entry.prevInKeyInsertionOrder;
+    }
+
     size--;
     modCount++;
   }
 
-  private void insert(BiEntry<K, V> entry) {
+  private void insert(BiEntry<K, V> entry, @Nullable BiEntry<K, V> oldEntryForKey) {
     int keyBucket = entry.keyHash & mask;
     entry.nextInKToVBucket = hashTableKToV[keyBucket];
     hashTableKToV[keyBucket] = entry;
@@ -165,16 +187,37 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
     entry.nextInVToKBucket = hashTableVToK[valueBucket];
     hashTableVToK[valueBucket] = entry;
 
+    if (oldEntryForKey == null) {
+      entry.prevInKeyInsertionOrder = lastInKeyInsertionOrder;
+      entry.nextInKeyInsertionOrder = null;
+      if (lastInKeyInsertionOrder == null) {
+        firstInKeyInsertionOrder = entry;
+      } else {
+        lastInKeyInsertionOrder.nextInKeyInsertionOrder = entry;
+      }
+      lastInKeyInsertionOrder = entry;
+    } else {
+      entry.prevInKeyInsertionOrder = oldEntryForKey.prevInKeyInsertionOrder;
+      if (entry.prevInKeyInsertionOrder == null) {
+        firstInKeyInsertionOrder = entry;
+      } else {
+        entry.prevInKeyInsertionOrder.nextInKeyInsertionOrder = entry;
+      }
+      entry.nextInKeyInsertionOrder = oldEntryForKey.nextInKeyInsertionOrder;
+      if (entry.nextInKeyInsertionOrder == null) {
+        lastInKeyInsertionOrder = entry;
+      } else {
+        entry.nextInKeyInsertionOrder.prevInKeyInsertionOrder = entry;
+      }
+    }
+
     size++;
     modCount++;
   }
 
-  private static int hash(@Nullable Object o) {
-    return Hashing.smear((o == null) ? 0 : o.hashCode());
-  }
-
   private BiEntry<K, V> seekByKey(@Nullable Object key, int keyHash) {
-    for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null;
+    for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask];
+        entry != null;
         entry = entry.nextInKToVBucket) {
       if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) {
         return entry;
@@ -184,7 +227,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   }
 
   private BiEntry<K, V> seekByValue(@Nullable Object value, int valueHash) {
-    for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null;
+    for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask];
+        entry != null;
         entry = entry.nextInVToKBucket) {
       if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) {
         return entry;
@@ -195,19 +239,18 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
   @Override
   public boolean containsKey(@Nullable Object key) {
-    return seekByKey(key, hash(key)) != null;
+    return seekByKey(key, smearedHash(key)) != null;
   }
 
   @Override
   public boolean containsValue(@Nullable Object value) {
-    return seekByValue(value, hash(value)) != null;
+    return seekByValue(value, smearedHash(value)) != null;
   }
 
   @Nullable
   @Override
   public V get(@Nullable Object key) {
-    BiEntry<K, V> entry = seekByKey(key, hash(key));
-    return (entry == null) ? null : entry.value;
+    return Maps.valueOrNull(seekByKey(key, smearedHash(key)));
   }
 
   @Override
@@ -221,11 +264,12 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   }
 
   private V put(@Nullable K key, @Nullable V value, boolean force) {
-    int keyHash = hash(key);
-    int valueHash = hash(value);
+    int keyHash = smearedHash(key);
+    int valueHash = smearedHash(value);
 
     BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
-    if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash
+    if (oldEntryForKey != null
+        && valueHash == oldEntryForKey.valueHash
         && Objects.equal(value, oldEntryForKey.value)) {
       return value;
     }
@@ -239,22 +283,29 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       }
     }
 
+    BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
     if (oldEntryForKey != null) {
       delete(oldEntryForKey);
+      insert(newEntry, oldEntryForKey);
+      oldEntryForKey.prevInKeyInsertionOrder = null;
+      oldEntryForKey.nextInKeyInsertionOrder = null;
+      rehashIfNecessary();
+      return oldEntryForKey.value;
+    } else {
+      insert(newEntry, null);
+      rehashIfNecessary();
+      return null;
     }
-    BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
-    insert(newEntry);
-    rehashIfNecessary();
-    return (oldEntryForKey == null) ? null : oldEntryForKey.value;
   }
 
   @Nullable
   private K putInverse(@Nullable V value, @Nullable K key, boolean force) {
-    int valueHash = hash(value);
-    int keyHash = hash(key);
+    int valueHash = smearedHash(value);
+    int keyHash = smearedHash(key);
 
     BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
-    if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash
+    if (oldEntryForValue != null
+        && keyHash == oldEntryForValue.keyHash
         && Objects.equal(key, oldEntryForValue.key)) {
       return key;
     }
@@ -272,9 +323,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       delete(oldEntryForValue);
     }
     BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
-    insert(newEntry);
+    insert(newEntry, oldEntryForKey);
+    if (oldEntryForKey != null) {
+      oldEntryForKey.prevInKeyInsertionOrder = null;
+      oldEntryForKey.nextInKeyInsertionOrder = null;
+    }
     rehashIfNecessary();
-    return (oldEntryForValue == null) ? null : oldEntryForValue.key;
+    return Maps.keyOrNull(oldEntryForValue);
   }
 
   private void rehashIfNecessary() {
@@ -287,13 +342,10 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       this.mask = newTableSize - 1;
       this.size = 0;
 
-      for (int bucket = 0; bucket < oldKToV.length; bucket++) {
-        BiEntry<K, V> entry = oldKToV[bucket];
-        while (entry != null) {
-          BiEntry<K, V> nextEntry = entry.nextInKToVBucket;
-          insert(entry);
-          entry = nextEntry;
-        }
+      for (BiEntry<K, V> entry = firstInKeyInsertionOrder;
+          entry != null;
+          entry = entry.nextInKeyInsertionOrder) {
+        insert(entry, entry);
       }
       this.modCount++;
     }
@@ -306,11 +358,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
   @Override
   public V remove(@Nullable Object key) {
-    BiEntry<K, V> entry = seekByKey(key, hash(key));
+    BiEntry<K, V> entry = seekByKey(key, smearedHash(key));
     if (entry == null) {
       return null;
     } else {
       delete(entry);
+      entry.prevInKeyInsertionOrder = null;
+      entry.nextInKeyInsertionOrder = null;
       return entry.value;
     }
   }
@@ -320,6 +374,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
     size = 0;
     Arrays.fill(hashTableKToV, null);
     Arrays.fill(hashTableVToK, null);
+    firstInKeyInsertionOrder = null;
+    lastInKeyInsertionOrder = null;
     modCount++;
   }
 
@@ -329,49 +385,35 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   }
 
   abstract class Itr<T> implements Iterator<T> {
-    int nextBucket = 0;
-    BiEntry<K, V> next = null;
+    BiEntry<K, V> next = firstInKeyInsertionOrder;
     BiEntry<K, V> toRemove = null;
     int expectedModCount = modCount;
 
-    private void checkForConcurrentModification() {
-      if (modCount != expectedModCount) {
-        throw new ConcurrentModificationException();
-      }
-    }
-
     @Override
     public boolean hasNext() {
-      checkForConcurrentModification();
-      if (next != null) {
-        return true;
-      }
-      while (nextBucket < hashTableKToV.length) {
-        if (hashTableKToV[nextBucket] != null) {
-          next = hashTableKToV[nextBucket++];
-          return true;
-        }
-        nextBucket++;
+      if (modCount != expectedModCount) {
+        throw new ConcurrentModificationException();
       }
-      return false;
+      return next != null;
     }
 
     @Override
     public T next() {
-      checkForConcurrentModification();
       if (!hasNext()) {
         throw new NoSuchElementException();
       }
 
       BiEntry<K, V> entry = next;
-      next = entry.nextInKToVBucket;
+      next = entry.nextInKeyInsertionOrder;
       toRemove = entry;
       return output(entry);
     }
 
     @Override
     public void remove() {
-      checkForConcurrentModification();
+      if (modCount != expectedModCount) {
+        throw new ConcurrentModificationException();
+      }
       checkRemove(toRemove != null);
       delete(toRemove);
       expectedModCount = modCount;
@@ -386,6 +428,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
     return new KeySet();
   }
 
+  @WeakOuter
   private final class KeySet extends Maps.KeySet<K, V> {
     KeySet() {
       super(HashBiMap.this);
@@ -403,11 +446,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
     @Override
     public boolean remove(@Nullable Object o) {
-      BiEntry<K, V> entry = seekByKey(o, hash(o));
+      BiEntry<K, V> entry = seekByKey(o, smearedHash(o));
       if (entry == null) {
         return false;
       } else {
         delete(entry);
+        entry.prevInKeyInsertionOrder = null;
+        entry.nextInKeyInsertionOrder = null;
         return true;
       }
     }
@@ -419,61 +464,53 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   }
 
   @Override
-  public Set<Entry<K, V>> entrySet() {
-    return new EntrySet();
-  }
+  Iterator<Entry<K, V>> entryIterator() {
+    return new Itr<Entry<K, V>>() {
+      @Override
+      Entry<K, V> output(BiEntry<K, V> entry) {
+        return new MapEntry(entry);
+      }
 
-  private final class EntrySet extends Maps.EntrySet<K, V> {
-    @Override
-    Map<K, V> map() {
-      return HashBiMap.this;
-    }
+      class MapEntry extends AbstractMapEntry<K, V> {
+        BiEntry<K, V> delegate;
 
-    @Override
-    public Iterator<Entry<K, V>> iterator() {
-      return new Itr<Entry<K, V>>() {
-        @Override
-        Entry<K, V> output(BiEntry<K, V> entry) {
-          return new MapEntry(entry);
+        MapEntry(BiEntry<K, V> entry) {
+          this.delegate = entry;
         }
 
-        class MapEntry extends AbstractMapEntry<K, V> {
-          BiEntry<K, V> delegate;
-
-          MapEntry(BiEntry<K, V> entry) {
-            this.delegate = entry;
-          }
+        @Override
+        public K getKey() {
+          return delegate.key;
+        }
 
-          @Override public K getKey() {
-            return delegate.key;
-          }
+        @Override
+        public V getValue() {
+          return delegate.value;
+        }
 
-          @Override public V getValue() {
-            return delegate.value;
+        @Override
+        public V setValue(V value) {
+          V oldValue = delegate.value;
+          int valueHash = smearedHash(value);
+          if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
+            return value;
           }
-
-          @Override public V setValue(V value) {
-            V oldValue = delegate.value;
-            int valueHash = hash(value);
-            if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
-              return value;
-            }
-            checkArgument(
-                seekByValue(value, valueHash) == null, "value already present: %s", value);
-            delete(delegate);
-            BiEntry<K, V> newEntry =
-                new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
-            insert(newEntry);
-            expectedModCount = modCount;
-            if (toRemove == delegate) {
-              toRemove = newEntry;
-            }
-            delegate = newEntry;
-            return oldValue;
+          checkArgument(seekByValue(value, valueHash) == null, "value already present: %s", value);
+          delete(delegate);
+          BiEntry<K, V> newEntry =
+              new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
+          insert(newEntry, delegate);
+          delegate.prevInKeyInsertionOrder = null;
+          delegate.nextInKeyInsertionOrder = null;
+          expectedModCount = modCount;
+          if (toRemove == delegate) {
+            toRemove = newEntry;
           }
+          delegate = newEntry;
+          return oldValue;
         }
-      };
-    }
+      }
+    };
   }
 
   private transient BiMap<V, K> inverse;
@@ -505,8 +542,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
     @Override
     public K get(@Nullable Object value) {
-      BiEntry<K, V> entry = seekByValue(value, hash(value));
-      return (entry == null) ? null : entry.key;
+      return Maps.keyOrNull(seekByValue(value, smearedHash(value)));
     }
 
     @Override
@@ -521,11 +557,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
     @Override
     public K remove(@Nullable Object value) {
-      BiEntry<K, V> entry = seekByValue(value, hash(value));
+      BiEntry<K, V> entry = seekByValue(value, smearedHash(value));
       if (entry == null) {
         return null;
       } else {
         delete(entry);
+        entry.prevInKeyInsertionOrder = null;
+        entry.nextInKeyInsertionOrder = null;
         return entry.key;
       }
     }
@@ -540,6 +578,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       return new InverseKeySet();
     }
 
+    @WeakOuter
     private final class InverseKeySet extends Maps.KeySet<V, K> {
       InverseKeySet() {
         super(Inverse.this);
@@ -547,7 +586,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
 
       @Override
       public boolean remove(@Nullable Object o) {
-        BiEntry<K, V> entry = seekByValue(o, hash(o));
+        BiEntry<K, V> entry = seekByValue(o, smearedHash(o));
         if (entry == null) {
           return false;
         } else {
@@ -559,7 +598,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
       @Override
       public Iterator<V> iterator() {
         return new Itr<V>() {
-          @Override V output(BiEntry<K, V> entry) {
+          @Override
+          V output(BiEntry<K, V> entry) {
             return entry.value;
           }
         };
@@ -608,7 +648,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
               @Override
               public K setValue(K key) {
                 K oldKey = delegate.key;
-                int keyHash = hash(key);
+                int keyHash = smearedHash(key);
                 if (keyHash == delegate.keyHash && Objects.equal(key, oldKey)) {
                   return key;
                 }
@@ -616,7 +656,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
                 delete(delegate);
                 BiEntry<K, V> newEntry =
                     new BiEntry<K, V>(key, keyHash, delegate.value, delegate.valueHash);
-                insert(newEntry);
+                delegate = newEntry;
+                insert(newEntry, null);
                 expectedModCount = modCount;
                 // This is safe because entries can only get bumped up to earlier in the iteration,
                 // so they can't get revisited.
@@ -657,8 +698,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
   @GwtIncompatible("java.io.ObjectInputStream")
   private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
+    init(16);
     int size = Serialization.readCount(stream);
-    init(size);
     Serialization.populateMap(this, stream, size);
   }
 
diff --git a/guava/src/com/google/common/collect/HashMultimap.java b/guava/src/com/google/common/collect/HashMultimap.java
index bab2a05..36dd385 100644
--- a/guava/src/com/google/common/collect/HashMultimap.java
+++ b/guava/src/com/google/common/collect/HashMultimap.java
@@ -44,14 +44,13 @@ import java.util.Set;
  * Multimaps#synchronizedSetMultimap}.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   private static final int DEFAULT_VALUES_PER_KEY = 2;
 
-  @VisibleForTesting
-  transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
+  @VisibleForTesting transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
 
   /**
    * Creates a new, empty {@code HashMultimap} with the default initial
@@ -70,8 +69,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> HashMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new HashMultimap<K, V>(expectedKeys, expectedValuesPerKey);
   }
 
@@ -82,8 +80,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    *
    * @param multimap the multimap whose contents are copied to this multimap
    */
-  public static <K, V> HashMultimap<K, V> create(
-      Multimap<? extends K, ? extends V> multimap) {
+  public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
     return new HashMultimap<K, V>(multimap);
   }
 
@@ -98,8 +95,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   }
 
   private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
-    super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(
-        multimap.keySet().size()));
+    super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(multimap.keySet().size()));
     putAll(multimap);
   }
 
@@ -110,7 +106,8 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    *
    * @return a new {@code HashSet} containing a collection of values for one key
    */
-  @Override Set<V> createCollection() {
+  @Override
+  Set<V> createCollection() {
     return Sets.<V>newHashSetWithExpectedSize(expectedValuesPerKey);
   }
 
@@ -122,17 +119,15 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   @GwtIncompatible("java.io.ObjectOutputStream")
   private void writeObject(ObjectOutputStream stream) throws IOException {
     stream.defaultWriteObject();
-    stream.writeInt(expectedValuesPerKey);
     Serialization.writeMultimap(this, stream);
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
-    expectedValuesPerKey = stream.readInt();
+    expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
     int distinctKeys = Serialization.readCount(stream);
-    Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
+    Map<K, Collection<V>> map = Maps.newHashMap();
     setMap(map);
     Serialization.populateMultimap(this, stream, distinctKeys);
   }
diff --git a/guava/src/com/google/common/collect/HashMultiset.java b/guava/src/com/google/common/collect/HashMultiset.java
index 51cf7fb..c2a79ff 100644
--- a/guava/src/com/google/common/collect/HashMultiset.java
+++ b/guava/src/com/google/common/collect/HashMultiset.java
@@ -29,7 +29,7 @@ import java.util.HashMap;
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
@@ -55,15 +55,14 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
 
   /**
    * Creates a new {@code HashMultiset} 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
    */
   public static <E> HashMultiset<E> create(Iterable<? extends E> elements) {
-    HashMultiset<E> multiset =
-        create(Multisets.inferDistinctElements(elements));
+    HashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
     Iterables.addAll(multiset, elements);
     return multiset;
   }
@@ -87,12 +86,10 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     int distinctElements = Serialization.readCount(stream);
-    setBackingMap(
-        Maps.<E, Count>newHashMapWithExpectedSize(distinctElements));
+    setBackingMap(Maps.<E, Count>newHashMap());
     Serialization.populateMultiset(this, stream, distinctElements);
   }
 
diff --git a/guava/src/com/google/common/collect/Hashing.java b/guava/src/com/google/common/collect/Hashing.java
index e3957dc..2220007 100644
--- a/guava/src/com/google/common/collect/Hashing.java
+++ b/guava/src/com/google/common/collect/Hashing.java
@@ -46,13 +46,13 @@ final class Hashing {
   static int smear(int hashCode) {
     return C2 * Integer.rotateLeft(hashCode * C1, 15);
   }
-  
+
   static int smearedHash(@Nullable Object o) {
     return smear((o == null) ? 0 : o.hashCode());
   }
-  
+
   private static int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO;
-  
+
   static int closedTableSize(int expectedEntries, double loadFactor) {
     // Get the recommended table size.
     // Round down to the nearest power of 2.
@@ -65,7 +65,7 @@ final class Hashing {
     }
     return tableSize;
   }
-  
+
   static boolean needsResizing(int size, int tableSize, double loadFactor) {
     return size > loadFactor * tableSize && tableSize < MAX_TABLE_SIZE;
   }
diff --git a/guava/src/com/google/common/collect/ImmutableAsList.java b/guava/src/com/google/common/collect/ImmutableAsList.java
index 249abee..ff123e5 100644
--- a/guava/src/com/google/common/collect/ImmutableAsList.java
+++ b/guava/src/com/google/common/collect/ImmutableAsList.java
@@ -35,7 +35,8 @@ import java.io.Serializable;
 abstract class ImmutableAsList<E> extends ImmutableList<E> {
   abstract ImmutableCollection<E> delegateCollection();
 
-  @Override public boolean contains(Object target) {
+  @Override
+  public boolean contains(Object target) {
     // The collection's contains() is at least as fast as ImmutableList's
     // and is often faster.
     return delegateCollection().contains(target);
@@ -62,23 +63,26 @@ abstract class ImmutableAsList<E> extends ImmutableList<E> {
   @GwtIncompatible("serialization")
   static class SerializedForm implements Serializable {
     final ImmutableCollection<?> collection;
+
     SerializedForm(ImmutableCollection<?> collection) {
       this.collection = collection;
     }
+
     Object readResolve() {
       return collection.asList();
     }
+
     private static final long serialVersionUID = 0;
   }
 
   @GwtIncompatible("serialization")
-  private void readObject(ObjectInputStream stream)
-      throws InvalidObjectException {
+  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
     throw new InvalidObjectException("Use SerializedForm");
   }
 
   @GwtIncompatible("serialization")
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm(delegateCollection());
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableBiMap.java b/guava/src/com/google/common/collect/ImmutableBiMap.java
index e3a8a9b..2c531b3 100644
--- a/guava/src/com/google/common/collect/ImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/ImmutableBiMap.java
@@ -16,30 +16,22 @@
 
 package com.google.common.collect;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Map;
 
 /**
- * An immutable {@link BiMap} with reliable user-specified iteration order. Does
- * not permit null keys or values. An {@code ImmutableBiMap} and its inverse
- * have the same iteration ordering.
- *
- * <p>An instance of {@code ImmutableBiMap} contains its own data and will
- * <i>never</i> change. {@code ImmutableBiMap} is convenient for
- * {@code public static final} maps ("constant maps") and also lets you easily
- * make a "defensive copy" of a bimap provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * A {@link BiMap} whose contents will never change, with many other important properties detailed
+ * at {@link ImmutableCollection}.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
-public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
-    implements BiMap<K, V> {
+public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {
 
   /**
    * Returns the empty bimap.
@@ -47,7 +39,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
   // Casting to any type is safe because the set will never hold any elements.
   @SuppressWarnings("unchecked")
   public static <K, V> ImmutableBiMap<K, V> of() {
-    return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
+    return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
   }
 
   /**
@@ -63,7 +55,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    * @throws IllegalArgumentException if duplicate keys or values are added
    */
   public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
-    return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
+    return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
   }
 
   /**
@@ -71,9 +63,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    *
    * @throws IllegalArgumentException if duplicate keys or values are added
    */
-  public static <K, V> ImmutableBiMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
-    return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
+  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+    return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
   }
 
   /**
@@ -81,10 +72,9 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    *
    * @throws IllegalArgumentException if duplicate keys or values are added
    */
-  public static <K, V> ImmutableBiMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
-    return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
-        entryOf(k4, v4));
+  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+    return RegularImmutableBiMap.fromEntries(
+        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
   }
 
   /**
@@ -94,8 +84,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    */
   public static <K, V> ImmutableBiMap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
-    return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
-        entryOf(k4, v4), entryOf(k5, v5));
+    return RegularImmutableBiMap.fromEntries(
+        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
   }
 
   // looking for of() with > 5 entries? Use the builder instead.
@@ -126,7 +116,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    * multiple times to build multiple bimaps in series. Each bimap is a superset
    * of the bimaps created before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
 
@@ -136,40 +126,109 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
      */
     public Builder() {}
 
+    Builder(int size) {
+      super(size);
+    }
+
     /**
      * Associates {@code key} with {@code value} in the built bimap. Duplicate
      * keys or values are not allowed, and will cause {@link #build} to fail.
      */
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       super.put(key, value);
       return this;
     }
 
     /**
+     * Adds the given {@code entry} to the bimap.  Duplicate keys or values
+     * are not allowed, and will cause {@link #build} to fail.
+     *
+     * @since 19.0
+     */
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+      super.put(entry);
+      return this;
+    }
+
+    /**
      * Associates all of the given map's keys and values in the built bimap.
      * Duplicate keys or values are not allowed, and will cause {@link #build}
      * to fail.
      *
      * @throws NullPointerException if any key or value in {@code map} is null
      */
-    @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
+    @Override
+    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
       super.putAll(map);
       return this;
     }
 
     /**
+     * Adds all of the given entries to the built bimap.  Duplicate keys or
+     * values are not allowed, and will cause {@link #build} to fail.
+     *
+     * @throws NullPointerException if any key, value, or entry is null
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
+      return this;
+    }
+
+    /**
+     * Configures this {@code Builder} to order entries by value according to the specified
+     * comparator.
+     *
+     * <p>The sort order is stable, that is, if two entries have values that compare
+     * as equivalent, the entry that was inserted first will be first in the built map's
+     * iteration order.
+     *
+     * @throws IllegalStateException if this method was already called
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      super.orderEntriesByValue(valueComparator);
+      return this;
+    }
+
+    /**
      * Returns a newly-created immutable bimap.
      *
      * @throws IllegalArgumentException if duplicate keys or values were added
      */
-    @Override public ImmutableBiMap<K, V> build() {
+    @Override
+    public ImmutableBiMap<K, V> build() {
       switch (size) {
         case 0:
           return of();
         case 1:
           return of(entries[0].getKey(), entries[0].getValue());
         default:
-          return new RegularImmutableBiMap<K, V>(size, entries);
+          /*
+           * If entries is full, then this implementation may end up using the entries array
+           * directly and writing over the entry objects with non-terminal entries, but this is
+           * safe; if this Builder is used further, it will grow the entries array (so it can't
+           * affect the original array), and future build() calls will always copy any entry
+           * objects that cannot be safely reused.
+           */
+          if (valueComparator != null) {
+            if (entriesUsed) {
+              entries = ObjectArrays.arraysCopyOf(entries, size);
+            }
+            Arrays.sort(
+                entries,
+                0,
+                size,
+                Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+          }
+          entriesUsed = size == entries.length;
+          return RegularImmutableBiMap.fromEntryArray(size, entries);
       }
     }
   }
@@ -187,32 +246,47 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    * @throws IllegalArgumentException if two keys have the same value
    * @throws NullPointerException if any key or value in {@code map} is null
    */
-  public static <K, V> ImmutableBiMap<K, V> copyOf(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
     if (map instanceof ImmutableBiMap) {
       @SuppressWarnings("unchecked") // safe since map is not writable
       ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
-      // TODO(user): if we need to make a copy of a BiMap because the
+      // TODO(lowasser): if we need to make a copy of a BiMap because the
       // forward map is a view, don't make a copy of the non-view delegate map
       if (!bimap.isPartialView()) {
         return bimap;
       }
     }
-    Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
-    switch (entries.length) {
+    return copyOf(map.entrySet());
+  }
+
+  /**
+   * Returns an immutable bimap containing the given entries.
+   *
+   * @throws IllegalArgumentException if two keys have the same value or two
+   *         values have the same key
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableBiMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
+    Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+    switch (entryArray.length) {
       case 0:
         return of();
       case 1:
-        @SuppressWarnings("unchecked") // safe covariant cast in this context
-        Entry<K, V> entry = (Entry<K, V>) entries[0];
+        Entry<K, V> entry = entryArray[0];
         return of(entry.getKey(), entry.getValue());
       default:
-        return new RegularImmutableBiMap<K, V>(entries);
+        /*
+         * The current implementation will end up using entryArray directly, though it will write
+         * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
+         */
+        return RegularImmutableBiMap.fromEntries(entryArray);
     }
   }
 
-  private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
-
   ImmutableBiMap() {}
 
   /**
@@ -228,7 +302,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    * Returns an immutable set of the values in this map. The values are in the
    * same order as the parameters used to build this map.
    */
-  @Override public ImmutableSet<V> values() {
+  @Override
+  public ImmutableSet<V> values() {
     return inverse().keySet();
   }
 
@@ -257,14 +332,18 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
     SerializedForm(ImmutableBiMap<?, ?> bimap) {
       super(bimap);
     }
-    @Override Object readResolve() {
+
+    @Override
+    Object readResolve() {
       Builder<Object, Object> builder = new Builder<Object, Object>();
       return createMap(builder);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm(this);
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java b/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
index d99cf87..a74ae5f 100644
--- a/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
@@ -26,16 +26,38 @@ import java.util.Map;
 import javax.annotation.Nullable;
 
 /**
- * A class-to-instance map backed by an {@link ImmutableMap}. See also {@link
- * MutableClassToInstanceMap}.
+ * A {@link ClassToInstanceMap} whose contents will never change, with many
+ * other important properties detailed at {@link ImmutableCollection}.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
-public final class ImmutableClassToInstanceMap<B> 
-    extends ForwardingMap<Class<? extends B>, B> 
+public final class ImmutableClassToInstanceMap<B> extends ForwardingMap<Class<? extends B>, B>
     implements ClassToInstanceMap<B>, Serializable {
-  
+
+  private static final ImmutableClassToInstanceMap<Object> EMPTY =
+      new ImmutableClassToInstanceMap<Object>(ImmutableMap.<Class<?>, Object>of());
+
+  /**
+   * Returns an empty {@code ImmutableClassToInstanceMap}.
+   *
+   * @since 19.0
+   */
+  @SuppressWarnings("unchecked")
+  public static <B> ImmutableClassToInstanceMap<B> of() {
+    return (ImmutableClassToInstanceMap<B>) EMPTY;
+  }
+
+  /**
+   * Returns an {@code ImmutableClassToInstanceMap} containing a single entry.
+   *
+   * @since 19.0
+   */
+  public static <B, T extends B> ImmutableClassToInstanceMap<B> of(Class<T> type, T value) {
+    ImmutableMap<Class<? extends B>, B> map = ImmutableMap.<Class<? extends B>, B>of(type, value);
+    return new ImmutableClassToInstanceMap<B>(map);
+  }
+
   /**
    * Returns a new builder. The generated builder is equivalent to the builder
    * created by the {@link Builder} constructor.
@@ -59,11 +81,10 @@ public final class ImmutableClassToInstanceMap<B>
    * and build again. Thus each map generated by this builder will be a superset
    * of any map generated before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static final class Builder<B> {
-    private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder
-        = ImmutableMap.builder();
+    private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder = ImmutableMap.builder();
 
     /**
      * Associates {@code key} with {@code value} in the built map. Duplicate
@@ -82,10 +103,8 @@ public final class ImmutableClassToInstanceMap<B>
      * @throws ClassCastException if any value is not an instance of the type
      *     specified by its key
      */
-    public <T extends B> Builder<B> putAll(
-        Map<? extends Class<? extends T>, ? extends T> map) {
-      for (Entry<? extends Class<? extends T>, ? extends T> entry
-          : map.entrySet()) {
+    public <T extends B> Builder<B> putAll(Map<? extends Class<? extends T>, ? extends T> map) {
+      for (Entry<? extends Class<? extends T>, ? extends T> entry : map.entrySet()) {
         Class<? extends T> type = entry.getKey();
         T value = entry.getValue();
         mapBuilder.put(type, cast(type, value));
@@ -104,7 +123,12 @@ public final class ImmutableClassToInstanceMap<B>
      * @throws IllegalArgumentException if duplicate keys were added
      */
     public ImmutableClassToInstanceMap<B> build() {
-      return new ImmutableClassToInstanceMap<B>(mapBuilder.build());
+      ImmutableMap<Class<? extends B>, B> map = mapBuilder.build();
+      if (map.isEmpty()) {
+        return of();
+      } else {
+        return new ImmutableClassToInstanceMap<B>(map);
+      }
     }
   }
 
@@ -134,12 +158,12 @@ public final class ImmutableClassToInstanceMap<B>
 
   private final ImmutableMap<Class<? extends B>, B> delegate;
 
-  private ImmutableClassToInstanceMap(
-      ImmutableMap<Class<? extends B>, B> delegate) {
+  private ImmutableClassToInstanceMap(ImmutableMap<Class<? extends B>, B> delegate) {
     this.delegate = delegate;
   }
 
-  @Override protected Map<Class<? extends B>, B> delegate() {
+  @Override
+  protected Map<Class<? extends B>, B> delegate() {
     return delegate;
   }
 
@@ -161,4 +185,8 @@ public final class ImmutableClassToInstanceMap<B>
   public <T extends B> T putInstance(Class<T> type, T value) {
     throw new UnsupportedOperationException();
   }
+
+  Object readResolve() {
+    return isEmpty() ? of() : this;
+  }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableCollection.java b/guava/src/com/google/common/collect/ImmutableCollection.java
index 1e9f629..606629f 100644
--- a/guava/src/com/google/common/collect/ImmutableCollection.java
+++ b/guava/src/com/google/common/collect/ImmutableCollection.java
@@ -24,28 +24,135 @@ import com.google.common.annotations.GwtCompatible;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 import javax.annotation.Nullable;
 
 /**
- * An immutable collection. Does not permit null elements.
+ * A {@link Collection} whose contents will never change, and which offers a few additional
+ * guarantees detailed below.
  *
- * <p>In addition to the {@link Collection} methods, this class has an {@link
- * #asList()} method, which returns a list view of the collection's elements.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableCollection} as a type (just as
+ * with {@link Collection} itself). Prefer subtypes such as {@link ImmutableSet} or {@link
+ * ImmutableList}, which have well-defined {@link #equals} semantics, thus avoiding a common source
+ * of bugs and confusion.
  *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
- * outside of this package as it has no public or protected constructors. Thus,
- * instances of this type are guaranteed to be immutable.
+ * <h3>About <i>all</i> {@code Immutable-} collections</h3>
  *
- * @author Jesse Wilson
- * @since 2.0 (imported from Google Collections Library)
+ * <p>The remainder of this documentation applies to every public {@code Immutable-} type in this
+ * package, whether it is a subtype of {@code ImmutableCollection} or not.
+ *
+ * <h4>Guarantees</h4>
+ *
+ * <p>Each makes the following guarantees:
+ *
+ * <ul>
+ * <li><b>Shallow immutability.</b> Elements can never be added, removed or replaced in this
+ *     collection. This is a stronger guarantee than that of
+ *     {@link Collections#unmodifiableCollection}, whose contents change whenever the wrapped
+ *     collection is modified.
+ * <li><b>Null-hostility.</b> This collection will never contain a null element.
+ * <li><b>Deterministic iteration.</b> The iteration order is always well-defined, depending on how
+ *     the collection was created (see the appropriate factory method for details). View collections
+ *     such as {@link ImmutableMultiset#elementSet} iterate in the same order as the parent, except
+ *     as noted.
+ * <li><b>Thread safety.</b> It is safe to access this collection concurrently from multiple
+ *     threads.
+ * <li><b>Integrity.</b> This type cannot be subclassed outside this package (which would allow
+ *     these guarantees to be violated).
+ * </ul>
+ *
+ * <h4>"Interfaces", not implementations</h4>
+ *
+ * <p>Each public class, such as {@link ImmutableSet}, is a <i>type</i> offering meaningful
+ * behavioral guarantees -- not merely a specific <i>implementation</i> as in the case of, say,
+ * {@link ArrayList}. You should treat them as interfaces in every important sense of the word.
+ *
+ * <p>For field types and method return types, you should generally use the immutable type (such as
+ * {@link ImmutableList}) instead of the general collection interface type (such as {@link List}).
+ * This communicates to your callers all of the semantic guarantees listed above, which is almost
+ * always very useful information.
+ *
+ * <p>On the other hand, a <i>parameter</i> type of {@link ImmutableList} is generally a nuisance to
+ * callers. Instead, accept {@link Iterable} and have your method or constructor body pass it to the
+ * appropriate {@code copyOf} method itself.
+ *
+ * <h4>Creation</h4>
+ *
+ * <p>Except for logically "abstract" types like {@code ImmutableCollection} itself, each {@code
+ * Immutable} type provides the static operations you need to obtain instances of that type. These
+ * usually include:
+ *
+ * <ul>
+ * <li>Static methods named {@code of}, accepting an explicit list of elements or entries.
+ * <li>Static methods named {@code copyOf} (or {@code copyOfSorted}), accepting an existing
+ *     collection whose contents should be copied.
+ * <li>A static nested {@code Builder} class which can be used to populate a new immutable instance.
+ * </ul>
+ *
+ * <h4>Warnings</h4>
+ *
+ * <ul>
+ * <li><b>Warning:</b> as with any collection, it is almost always a bad idea to modify an element
+ *     (in a way that affects its {@link Object#equals} behavior) while it is contained in a
+ *     collection. Undefined behavior and bugs will result. It's generally best to avoid using
+ *     mutable objects as elements at all, as many users may expect your "immutable" object to be
+ *     <i>deeply</i> immutable.
+ * </ul>
+ *
+ * <h4>Performance notes</h4>
+ *
+ * <ul>
+ * <li>Implementations can be generally assumed to prioritize memory efficiency, then speed of
+ *     access, and lastly speed of creation.
+ * <li>The {@code copyOf} methods will sometimes recognize that the actual copy operation is
+ *     unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only once.
+ *     This reduces the expense of habitually making defensive copies at API boundaries. However,
+ *     the precise conditions for skipping the copy operation are undefined.
+ * <li><b>Warning:</b> a view collection such as {@link ImmutableMap#keySet} or {@link
+ *     ImmutableList#subList} may retain a reference to the entire data set, preventing it from
+ *     being garbage collected. If some of the data is no longer reachable through other means, this
+ *     constitutes a memory leak. Pass the view collection to the appropriate {@code copyOf} method
+ *     to obtain a correctly-sized copy.
+ * <li>The performance of using the associated {@code Builder} class can be assumed to be
+ *     no worse, and possibly better, than creating a mutable collection and copying it.
+ * <li>Implementations generally do not cache hash codes. If your element or key type has a slow
+ *     {@code hashCode} implementation, it should cache it itself.
+ * </ul>
+ *
+ * <h4>Example usage</h4>
+ *
+ * <pre>   {@code
+ *
+ *   class Foo {
+ *     private static final ImmutableSet<String> RESERVED_CODES =
+ *         ImmutableSet.of("AZ", "CQ", "ZX");
+ *
+ *     private final ImmutableSet<String> codes;
+ *
+ *     public Foo(Iterable<String> codes) {
+ *       this.codes = ImmutableSet.copyOf(codes);
+ *       checkArgument(Collections.disjoint(this.codes, RESERVED_CODES));
+ *     }
+ *   }}</pre>
+ *
+ * <h3>See also</h3>
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
+ * immutable collections</a>.
+ *
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
-public abstract class ImmutableCollection<E> extends AbstractCollection<E>
-    implements Serializable {
+// TODO(kevinb): I think we should push everything down to "BaseImmutableCollection" or something,
+// just to do everything we can to emphasize the "practically an interface" nature of this class.
+public abstract class ImmutableCollection<E> extends AbstractCollection<E> implements Serializable {
 
   ImmutableCollection() {}
 
@@ -80,9 +187,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
   }
 
   @Override
-  public boolean contains(@Nullable Object object) {
-    return object != null && super.contains(object);
-  }
+  public abstract boolean contains(@Nullable Object object);
 
   /**
    * Guaranteed to throw an exception and leave the collection unmodified.
@@ -163,7 +268,12 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
   private transient ImmutableList<E> asList;
 
   /**
-   * Returns a list view of the collection.
+   * Returns an {@code ImmutableList} containing the same elements, in the same order, as this
+   * collection.
+   *
+   * <p><b>Performance note:</b> in most cases this method can return quickly without actually
+   * copying anything. The exact circumstances under which the copy is performed are undefined and
+   * subject to change.
    *
    * @since 2.0
    */
@@ -190,7 +300,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
    * memory leaks.
    */
   abstract boolean isPartialView();
-  
+
   /**
    * Copies the contents of this immutable collection into the specified array at the specified
    * offset.  Returns {@code offset + size()}.
@@ -231,8 +341,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
       return newCapacity;
     }
 
-    Builder() {
-    }
+    Builder() {}
 
     /**
      * Adds {@code element} to the {@code ImmutableCollection} being built.
@@ -312,25 +421,26 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
      */
     public abstract ImmutableCollection<E> build();
   }
-  
+
   abstract static class ArrayBasedBuilder<E> extends ImmutableCollection.Builder<E> {
     Object[] contents;
     int size;
-    
+
     ArrayBasedBuilder(int initialCapacity) {
       checkNonnegative(initialCapacity, "initialCapacity");
       this.contents = new Object[initialCapacity];
       this.size = 0;
     }
-    
+
     /**
      * Expand the absolute capacity of the builder so it can accept at least
      * the specified number of elements without being resized.
      */
     private void ensureCapacity(int minCapacity) {
       if (contents.length < minCapacity) {
-        this.contents = ObjectArrays.arraysCopyOf(
-            this.contents, expandedCapacity(contents.length, minCapacity));
+        this.contents =
+            ObjectArrays.arraysCopyOf(
+                this.contents, expandedCapacity(contents.length, minCapacity));
       }
     }
 
diff --git a/guava/src/com/google/common/collect/ImmutableEntry.java b/guava/src/com/google/common/collect/ImmutableEntry.java
index 1d04662..b17d5cb 100644
--- a/guava/src/com/google/common/collect/ImmutableEntry.java
+++ b/guava/src/com/google/common/collect/ImmutableEntry.java
@@ -26,8 +26,7 @@ import javax.annotation.Nullable;
  * @see com.google.common.collect.Maps#immutableEntry(Object, Object)
  */
 @GwtCompatible(serializable = true)
-class ImmutableEntry<K, V> extends AbstractMapEntry<K, V>
-    implements Serializable {
+class ImmutableEntry<K, V> extends AbstractMapEntry<K, V> implements Serializable {
   final K key;
   final V value;
 
@@ -36,15 +35,20 @@ class ImmutableEntry<K, V> extends AbstractMapEntry<K, V>
     this.value = value;
   }
 
-  @Nullable @Override public final K getKey() {
+  @Nullable
+  @Override
+  public final K getKey() {
     return key;
   }
 
-  @Nullable @Override public final V getValue() {
+  @Nullable
+  @Override
+  public final V getValue() {
     return value;
   }
 
-  @Override public final V setValue(V value) {
+  @Override
+  public final V setValue(V value) {
     throw new UnsupportedOperationException();
   }
 
diff --git a/guava/src/com/google/common/collect/ImmutableEnumMap.java b/guava/src/com/google/common/collect/ImmutableEnumMap.java
index 6738685..c361fa5 100644
--- a/guava/src/com/google/common/collect/ImmutableEnumMap.java
+++ b/guava/src/com/google/common/collect/ImmutableEnumMap.java
@@ -18,10 +18,10 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkArgument;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.IteratorBasedImmutableMap;
 
 import java.io.Serializable;
 import java.util.EnumMap;
-import java.util.Iterator;
 
 import javax.annotation.Nullable;
 
@@ -33,15 +33,14 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
-final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
+final class ImmutableEnumMap<K extends Enum<K>, V> extends IteratorBasedImmutableMap<K, V> {
   static <K extends Enum<K>, V> ImmutableMap<K, V> asImmutable(EnumMap<K, V> map) {
     switch (map.size()) {
       case 0:
         return ImmutableMap.of();
-      case 1: {
+      case 1:
         Entry<K, V> entry = Iterables.getOnlyElement(map.entrySet());
         return ImmutableMap.of(entry.getKey(), entry.getValue());
-      }
       default:
         return new ImmutableEnumMap<K, V>(map);
     }
@@ -55,29 +54,8 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
   }
 
   @Override
-  ImmutableSet<K> createKeySet() {
-    return new ImmutableSet<K>() {
-
-      @Override
-      public boolean contains(Object object) {
-        return delegate.containsKey(object);
-      }
-
-      @Override
-      public int size() {
-        return ImmutableEnumMap.this.size();
-      }
-
-      @Override
-      public UnmodifiableIterator<K> iterator() {
-        return Iterators.unmodifiableIterator(delegate.keySet().iterator());
-      }
-
-      @Override
-      boolean isPartialView() {
-        return true;
-      }
-    };
+  UnmodifiableIterator<K> keyIterator() {
+    return Iterators.unmodifiableIterator(delegate.keySet().iterator());
   }
 
   @Override
@@ -96,32 +74,19 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
   }
 
   @Override
-  ImmutableSet<Entry<K, V>> createEntrySet() {
-    return new ImmutableMapEntrySet<K, V>() {
-
-      @Override
-      ImmutableMap<K, V> map() {
-        return ImmutableEnumMap.this;
-      }
-
-      @Override
-      public UnmodifiableIterator<Entry<K, V>> iterator() {
-        return new UnmodifiableIterator<Entry<K, V>>() {
-          private final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
-
-          @Override
-          public boolean hasNext() {
-            return backingIterator.hasNext();
-          }
-
-          @Override
-          public Entry<K, V> next() {
-            Entry<K, V> entry = backingIterator.next();
-            return Maps.immutableEntry(entry.getKey(), entry.getValue());
-          }
-        };
-      }
-    };
+  public boolean equals(Object object) {
+    if (object == this) {
+      return true;
+    }
+    if (object instanceof ImmutableEnumMap) {
+      object = ((ImmutableEnumMap<?, ?>) object).delegate;
+    }
+    return delegate.equals(object);
+  }
+
+  @Override
+  UnmodifiableIterator<Entry<K, V>> entryIterator() {
+    return Maps.unmodifiableEntryIterator(delegate.entrySet().iterator());
   }
 
   @Override
@@ -130,22 +95,25 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
   }
 
   // All callers of the constructor are restricted to <K extends Enum<K>>.
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new EnumSerializedForm<K, V>(delegate);
   }
 
   /*
-   * This class is used to serialize ImmutableEnumSet instances.
+   * This class is used to serialize ImmutableEnumMap instances.
    */
-  private static class EnumSerializedForm<K extends Enum<K>, V>
-      implements Serializable {
+  private static class EnumSerializedForm<K extends Enum<K>, V> implements Serializable {
     final EnumMap<K, V> delegate;
+
     EnumSerializedForm(EnumMap<K, V> delegate) {
       this.delegate = delegate;
     }
+
     Object readResolve() {
       return new ImmutableEnumMap<K, V>(delegate);
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableEnumSet.java b/guava/src/com/google/common/collect/ImmutableEnumSet.java
index 62e3e04..67e8245 100644
--- a/guava/src/com/google/common/collect/ImmutableEnumSet.java
+++ b/guava/src/com/google/common/collect/ImmutableEnumSet.java
@@ -31,14 +31,15 @@ import java.util.EnumSet;
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
 final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
-  static <E extends Enum<E>> ImmutableSet<E> asImmutable(EnumSet<E> set) {
+  @SuppressWarnings("rawtypes") // necessary to compile against Java 8
+  static ImmutableSet asImmutable(EnumSet set) {
     switch (set.size()) {
       case 0:
         return ImmutableSet.of();
       case 1:
         return ImmutableSet.of(Iterables.getOnlyElement(set));
       default:
-        return new ImmutableEnumSet<E>(set);
+        return new ImmutableEnumSet(set);
     }
   }
 
@@ -56,11 +57,13 @@ final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
     this.delegate = delegate;
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     return Iterators.unmodifiableIterator(delegate.iterator());
   }
 
@@ -69,51 +72,74 @@ final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
     return delegate.size();
   }
 
-  @Override public boolean contains(Object object) {
+  @Override
+  public boolean contains(Object object) {
     return delegate.contains(object);
   }
 
-  @Override public boolean containsAll(Collection<?> collection) {
+  @Override
+  public boolean containsAll(Collection<?> collection) {
+    if (collection instanceof ImmutableEnumSet<?>) {
+      collection = ((ImmutableEnumSet<?>) collection).delegate;
+    }
     return delegate.containsAll(collection);
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return delegate.isEmpty();
   }
 
-  @Override public boolean equals(Object object) {
-    return object == this || delegate.equals(object);
+  @Override
+  public boolean equals(Object object) {
+    if (object == this) {
+      return true;
+    }
+    if (object instanceof ImmutableEnumSet) {
+      object = ((ImmutableEnumSet<?>) object).delegate;
+    }
+    return delegate.equals(object);
+  }
+
+  @Override
+  boolean isHashCodeFast() {
+    return true;
   }
 
   private transient int hashCode;
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     int result = hashCode;
     return (result == 0) ? hashCode = delegate.hashCode() : result;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return delegate.toString();
   }
 
   // All callers of the constructor are restricted to <E extends Enum<E>>.
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new EnumSerializedForm<E>(delegate);
   }
 
   /*
    * This class is used to serialize ImmutableEnumSet instances.
    */
-  private static class EnumSerializedForm<E extends Enum<E>>
-      implements Serializable {
+  private static class EnumSerializedForm<E extends Enum<E>> implements Serializable {
     final EnumSet<E> delegate;
+
     EnumSerializedForm(EnumSet<E> delegate) {
       this.delegate = delegate;
     }
+
     Object readResolve() {
       // EJ2 #76: Write readObject() methods defensively.
       return new ImmutableEnumSet<E>(delegate.clone());
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableList.java b/guava/src/com/google/common/collect/ImmutableList.java
index 501a41c..273772e 100644
--- a/guava/src/com/google/common/collect/ImmutableList.java
+++ b/guava/src/com/google/common/collect/ImmutableList.java
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkPositionIndexes;
 import static com.google.common.collect.ObjectArrays.arraysCopyOf;
 import static com.google.common.collect.ObjectArrays.checkElementsNotNull;
+import static com.google.common.collect.RegularImmutableList.EMPTY;
 
 import com.google.common.annotations.GwtCompatible;
 
@@ -28,6 +29,7 @@ import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.RandomAccess;
@@ -35,37 +37,22 @@ import java.util.RandomAccess;
 import javax.annotation.Nullable;
 
 /**
- * A high-performance, immutable, random-access {@code List} implementation.
- * Does not permit null elements.
- *
- * <p>Unlike {@link Collections#unmodifiableList}, which is a <i>view</i> of a
- * separate collection that can still change, an instance of {@code
- * ImmutableList} contains its own private data and will <i>never</i> change.
- * {@code ImmutableList} is convenient for {@code public static final} lists
- * ("constant lists") and also lets you easily make a "defensive copy" of a list
- * provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this type are
- * guaranteed to be immutable.
+ * A {@link List} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @see ImmutableMap
  * @see ImmutableSet
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
 public abstract class ImmutableList<E> extends ImmutableCollection<E>
     implements List<E>, RandomAccess {
-
-  private static final ImmutableList<Object> EMPTY =
-      new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
-
   /**
    * Returns the empty immutable list. This set behaves and performs comparably
    * to {@link Collections#emptyList}, and is preferable mainly for consistency
@@ -139,8 +126,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    *
    * @throws NullPointerException if any element is null
    */
-  public static <E> ImmutableList<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
+  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
     return construct(e1, e2, e3, e4, e5, e6, e7);
   }
 
@@ -149,8 +135,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    *
    * @throws NullPointerException if any element is null
    */
-  public static <E> ImmutableList<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
+  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
     return construct(e1, e2, e3, e4, e5, e6, e7, e8);
   }
 
@@ -159,8 +144,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    *
    * @throws NullPointerException if any element is null
    */
-  public static <E> ImmutableList<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
+  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
     return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);
   }
 
@@ -194,8 +178,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    * @since 3.0 (source-compatible since 2.0)
    */
   public static <E> ImmutableList<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12,
-      E... others) {
+      E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {
     Object[] array = new Object[12 + others.length];
     array[0] = e1;
     array[1] = e2;
@@ -224,8 +207,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
   public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {
     checkNotNull(elements); // TODO(kevinb): is this here only for GWT?
     return (elements instanceof Collection)
-      ? copyOf((Collection<? extends E>) elements)
-      : copyOf(elements.iterator());
+        ? copyOf((Collection<? extends E>) elements)
+        : copyOf(elements.iterator());
   }
 
   /**
@@ -251,9 +234,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
     if (elements instanceof ImmutableCollection) {
       @SuppressWarnings("unchecked") // all supported methods are covariant
       ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
-      return list.isPartialView()
-          ? ImmutableList.<E>asImmutableList(list.toArray())
-          : list;
+      return list.isPartialView() ? ImmutableList.<E>asImmutableList(list.toArray()) : list;
     }
     return construct(elements.toArray());
   }
@@ -272,10 +253,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
     if (!elements.hasNext()) {
       return of(first);
     } else {
-      return new ImmutableList.Builder<E>()
-          .add(first)
-          .addAll(elements)
-          .build();
+      return new ImmutableList.Builder<E>().add(first).addAll(elements).build();
     }
   }
 
@@ -336,15 +314,18 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
 
   // This declaration is needed to make List.iterator() and
   // ImmutableCollection.iterator() consistent.
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     return listIterator();
   }
 
-  @Override public UnmodifiableListIterator<E> listIterator() {
+  @Override
+  public UnmodifiableListIterator<E> listIterator() {
     return listIterator(0);
   }
 
-  @Override public UnmodifiableListIterator<E> listIterator(int index) {
+  @Override
+  public UnmodifiableListIterator<E> listIterator(int index) {
     return new AbstractIndexedListIterator<E>(size(), index) {
       @Override
       protected E get(int index) {
@@ -380,6 +361,9 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
   public ImmutableList<E> subList(int fromIndex, int toIndex) {
     checkPositionIndexes(fromIndex, toIndex, size());
     int length = toIndex - fromIndex;
+    if (length == size()) {
+      return this;
+    }
     switch (length) {
       case 0:
         return of();
@@ -400,8 +384,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
   }
 
   class SubList extends ImmutableList<E> {
-    transient final int offset;
-    transient final int length;
+    final transient int offset;
+    final transient int length;
 
     SubList(int offset, int length) {
       this.offset = offset;
@@ -484,7 +468,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    *
    * @since 2.0
    */
-  @Override public final ImmutableList<E> asList() {
+  @Override
+  public final ImmutableList<E> asList() {
     return this;
   }
 
@@ -507,7 +492,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    * @since 7.0
    */
   public ImmutableList<E> reverse() {
-    return new ReverseImmutableList<E>(this);
+    return (size() <= 1) ? this : new ReverseImmutableList<E>(this);
   }
 
   private static class ReverseImmutableList<E> extends ImmutableList<E> {
@@ -525,49 +510,58 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
       return size() - index;
     }
 
-    @Override public ImmutableList<E> reverse() {
+    @Override
+    public ImmutableList<E> reverse() {
       return forwardList;
     }
 
-    @Override public boolean contains(@Nullable Object object) {
+    @Override
+    public boolean contains(@Nullable Object object) {
       return forwardList.contains(object);
     }
 
-    @Override public int indexOf(@Nullable Object object) {
+    @Override
+    public int indexOf(@Nullable Object object) {
       int index = forwardList.lastIndexOf(object);
       return (index >= 0) ? reverseIndex(index) : -1;
     }
 
-    @Override public int lastIndexOf(@Nullable Object object) {
+    @Override
+    public int lastIndexOf(@Nullable Object object) {
       int index = forwardList.indexOf(object);
       return (index >= 0) ? reverseIndex(index) : -1;
     }
 
-    @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
+    @Override
+    public ImmutableList<E> subList(int fromIndex, int toIndex) {
       checkPositionIndexes(fromIndex, toIndex, size());
-      return forwardList.subList(
-          reversePosition(toIndex), reversePosition(fromIndex)).reverse();
+      return forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)).reverse();
     }
 
-    @Override public E get(int index) {
+    @Override
+    public E get(int index) {
       checkElementIndex(index, size());
       return forwardList.get(reverseIndex(index));
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return forwardList.size();
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return forwardList.isPartialView();
     }
   }
 
-  @Override public boolean equals(@Nullable Object obj) {
+  @Override
+  public boolean equals(@Nullable Object obj) {
     return Lists.equalsImpl(this, obj);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     int hashCode = 1;
     int n = size();
     for (int i = 0; i < n; i++) {
@@ -585,21 +579,24 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    */
   static class SerializedForm implements Serializable {
     final Object[] elements;
+
     SerializedForm(Object[] elements) {
       this.elements = elements;
     }
+
     Object readResolve() {
       return copyOf(elements);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  private void readObject(ObjectInputStream stream)
-      throws InvalidObjectException {
+  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
     throw new InvalidObjectException("Use SerializedForm");
   }
 
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm(toArray());
   }
 
@@ -625,7 +622,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
    * times to build multiple lists in series. Each new list contains all the
    * elements of the ones created before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static final class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
     /**
@@ -636,7 +633,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
       this(DEFAULT_INITIAL_CAPACITY);
     }
 
-    // TODO(user): consider exposing this
+    // TODO(lowasser): consider exposing this
     Builder(int capacity) {
       super(capacity);
     }
@@ -648,7 +645,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code element} is null
      */
-    @Override public Builder<E> add(E element) {
+    @Override
+    public Builder<E> add(E element) {
       super.add(element);
       return this;
     }
@@ -661,7 +659,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterable<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -674,7 +673,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> add(E... elements) {
+    @Override
+    public Builder<E> add(E... elements) {
       super.add(elements);
       return this;
     }
@@ -687,7 +687,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterator<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -696,7 +697,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
      * Returns a newly-created {@code ImmutableList} based on the contents of
      * the {@code Builder}.
      */
-    @Override public ImmutableList<E> build() {
+    @Override
+    public ImmutableList<E> build() {
       return asImmutableList(contents, size);
     }
   }
diff --git a/guava/src/com/google/common/collect/ImmutableListMultimap.java b/guava/src/com/google/common/collect/ImmutableListMultimap.java
index 616f4e9..f70cc52 100644
--- a/guava/src/com/google/common/collect/ImmutableListMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableListMultimap.java
@@ -16,6 +16,7 @@
 
 package com.google.common.collect;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 
@@ -30,31 +31,18 @@ import java.util.Map.Entry;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link ListMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableListMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableListMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link ListMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
-public class ImmutableListMultimap<K, V>
-    extends ImmutableMultimap<K, V>
+public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
     implements ListMultimap<K, V> {
 
   /** Returns the empty multimap. */
@@ -68,8 +56,7 @@ public class ImmutableListMultimap<K, V>
    * Returns an immutable multimap containing a single entry.
    */
   public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     return builder.build();
   }
@@ -78,8 +65,7 @@ public class ImmutableListMultimap<K, V>
    * Returns an immutable multimap containing the given entries, in order.
    */
   public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     return builder.build();
@@ -88,10 +74,8 @@ public class ImmutableListMultimap<K, V>
   /**
    * Returns an immutable multimap containing the given entries, in order.
    */
-  public static <K, V> ImmutableListMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+  public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -103,8 +87,7 @@ public class ImmutableListMultimap<K, V>
    */
   public static <K, V> ImmutableListMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -117,8 +100,7 @@ public class ImmutableListMultimap<K, V>
    */
   public static <K, V> ImmutableListMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
     builder.put(k3, v3);
@@ -153,17 +135,17 @@ public class ImmutableListMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
-  public static final class Builder<K, V>
-      extends ImmutableMultimap.Builder<K, V> {
+  public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
     /**
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableListMultimap#builder}.
      */
     public Builder() {}
 
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       super.put(key, value);
       return this;
     }
@@ -173,24 +155,38 @@ public class ImmutableListMultimap<K, V>
      *
      * @since 11.0
      */
-    @Override public Builder<K, V> put(
-        Entry<? extends K, ? extends V> entry) {
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
       super.put(entry);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+    /**
+     * {@inheritDoc}
+     *
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
+      return this;
+    }
+
+    @Override
+    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       super.putAll(key, values);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, V... values) {
+    @Override
+    public Builder<K, V> putAll(K key, V... values) {
       super.putAll(key, values);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(
-        Multimap<? extends K, ? extends V> multimap) {
+    @Override
+    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
       super.putAll(multimap);
       return this;
     }
@@ -220,7 +216,8 @@ public class ImmutableListMultimap<K, V>
     /**
      * Returns a newly-created immutable list multimap.
      */
-    @Override public ImmutableListMultimap<K, V> build() {
+    @Override
+    public ImmutableListMultimap<K, V> build() {
       return (ImmutableListMultimap<K, V>) super.build();
     }
   }
@@ -243,21 +240,21 @@ public class ImmutableListMultimap<K, V>
       return of();
     }
 
-    // TODO(user): copy ImmutableSetMultimap by using asList() on the sets
+    // TODO(lowasser): copy ImmutableSetMultimap by using asList() on the sets
     if (multimap instanceof ImmutableListMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableListMultimap<K, V> kvMultimap
-          = (ImmutableListMultimap<K, V>) multimap;
+      ImmutableListMultimap<K, V> kvMultimap = (ImmutableListMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
     }
 
-    ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder();
+    ImmutableMap.Builder<K, ImmutableList<V>> builder =
+        new ImmutableMap.Builder<K, ImmutableList<V>>(multimap.asMap().size());
     int size = 0;
 
-    for (Entry<? extends K, ? extends Collection<? extends V>> entry
-        : multimap.asMap().entrySet()) {
+    for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+        multimap.asMap().entrySet()) {
       ImmutableList<V> list = ImmutableList.copyOf(entry.getValue());
       if (!list.isEmpty()) {
         builder.put(entry.getKey(), list);
@@ -268,6 +265,21 @@ public class ImmutableListMultimap<K, V>
     return new ImmutableListMultimap<K, V>(builder.build(), size);
   }
 
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableListMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>().putAll(entries).build();
+  }
+
   ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) {
     super(map, size);
   }
@@ -280,7 +292,8 @@ public class ImmutableListMultimap<K, V>
    * returned. The values are in the same order as the parameters used to build
    * this multimap.
    */
-  @Override public ImmutableList<V> get(@Nullable K key) {
+  @Override
+  public ImmutableList<V> get(@Nullable K key) {
     // This cast is safe as its type is known in constructor.
     ImmutableList<V> list = (ImmutableList<V>) map.get(key);
     return (list == null) ? ImmutableList.<V>of() : list;
@@ -320,7 +333,9 @@ public class ImmutableListMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableList<V> removeAll(Object key) {
+  @Deprecated
+  @Override
+  public ImmutableList<V> removeAll(Object key) {
     throw new UnsupportedOperationException();
   }
 
@@ -330,8 +345,9 @@ public class ImmutableListMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableList<V> replaceValues(
-      K key, Iterable<? extends V> values) {
+  @Deprecated
+  @Override
+  public ImmutableList<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 
@@ -346,15 +362,13 @@ public class ImmutableListMultimap<K, V>
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     int keyCount = stream.readInt();
     if (keyCount < 0) {
       throw new InvalidObjectException("Invalid key count " + keyCount);
     }
-    ImmutableMap.Builder<Object, ImmutableList<Object>> builder
-        = ImmutableMap.builder();
+    ImmutableMap.Builder<Object, ImmutableList<Object>> builder = ImmutableMap.builder();
     int tmpSize = 0;
 
     for (int i = 0; i < keyCount; i++) {
@@ -364,11 +378,11 @@ public class ImmutableListMultimap<K, V>
         throw new InvalidObjectException("Invalid value count " + valueCount);
       }
 
-      Object[] array = new Object[valueCount];
+      ImmutableList.Builder<Object> valuesBuilder = ImmutableList.builder();
       for (int j = 0; j < valueCount; j++) {
-        array[j] = stream.readObject();
+        valuesBuilder.add(stream.readObject());
       }
-      builder.put(key, ImmutableList.copyOf(array));
+      builder.put(key, valuesBuilder.build());
       tmpSize += valueCount;
     }
 
@@ -376,8 +390,7 @@ public class ImmutableListMultimap<K, V>
     try {
       tmpMap = builder.build();
     } catch (IllegalArgumentException e) {
-      throw (InvalidObjectException)
-          new InvalidObjectException(e.getMessage()).initCause(e);
+      throw (InvalidObjectException) new InvalidObjectException(e.getMessage()).initCause(e);
     }
 
     FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap);
diff --git a/guava/src/com/google/common/collect/ImmutableMap.java b/guava/src/com/google/common/collect/ImmutableMap.java
index 959858b..3fe475c 100644
--- a/guava/src/com/google/common/collect/ImmutableMap.java
+++ b/guava/src/com/google/common/collect/ImmutableMap.java
@@ -17,45 +17,35 @@
 package com.google.common.collect;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.EnumMap;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
 import javax.annotation.Nullable;
 
 /**
- * An immutable, hash-based {@link Map} with reliable user-specified iteration
- * order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Collections#unmodifiableMap}, which is a <i>view</i> of a
- * separate map which can still change, an instance of {@code ImmutableMap}
- * contains its own data and will <i>never</i> change. {@code ImmutableMap} is
- * convenient for {@code public static final} maps ("constant maps") and also
- * lets you easily make a "defensive copy" of a map provided to your class by a
- * caller.
- *
- * <p><i>Performance notes:</i> unlike {@link HashMap}, {@code ImmutableMap} is
- * not optimized for element types that have slow {@link Object#equals} or
- * {@link Object#hashCode} implementations. You can get better performance by
- * having your element type cache its own hash codes, and by making use of the
- * cached values to short-circuit a slow {@code equals} algorithm.
+ * A {@link Map} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jesse Wilson
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
@@ -86,7 +76,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    * @throws IllegalArgumentException if duplicate keys are provided
    */
   public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
-    return new RegularImmutableMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
+    return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
   }
 
   /**
@@ -94,10 +84,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    *
    * @throws IllegalArgumentException if duplicate keys are provided
    */
-  public static <K, V> ImmutableMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
-    return new RegularImmutableMap<K, V>(
-        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
+  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+    return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
   }
 
   /**
@@ -105,9 +93,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    *
    * @throws IllegalArgumentException if duplicate keys are provided
    */
-  public static <K, V> ImmutableMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
-    return new RegularImmutableMap<K, V>(
+  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+    return RegularImmutableMap.fromEntries(
         entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
   }
 
@@ -118,8 +105,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    */
   public static <K, V> ImmutableMap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
-    return new RegularImmutableMap<K, V>(entryOf(k1, v1),
-        entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
+    return RegularImmutableMap.fromEntries(
+        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
   }
 
   // looking for of() with > 5 entries? Use the builder instead.
@@ -131,9 +118,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    * <p>A call to {@link Map.Entry#setValue} on the returned entry will always
    * throw {@link UnsupportedOperationException}.
    */
-  static <K, V> TerminalEntry<K, V> entryOf(K key, V value) {
-    checkEntryNotNull(key, value);
-    return new TerminalEntry<K, V>(key, value);
+  static <K, V> ImmutableMapEntry<K, V> entryOf(K key, V value) {
+    return new ImmutableMapEntry<K, V>(key, value);
   }
 
   /**
@@ -144,8 +130,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
     return new Builder<K, V>();
   }
 
-  static void checkNoConflict(boolean safe, String conflictDescription,
-      Entry<?, ?> entry1, Entry<?, ?> entry2) {
+  static void checkNoConflict(
+      boolean safe, String conflictDescription, Entry<?, ?> entry1, Entry<?, ?> entry2) {
     if (!safe) {
       throw new IllegalArgumentException(
           "Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2);
@@ -170,11 +156,13 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    * multiple times to build multiple maps in series. Each map is a superset of
    * the maps created before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<K, V> {
-    TerminalEntry<K, V>[] entries;
+    Comparator<? super V> valueComparator;
+    ImmutableMapEntry<K, V>[] entries;
     int size;
+    boolean entriesUsed;
 
     /**
      * Creates a new builder. The returned builder is equivalent to the builder
@@ -186,14 +174,17 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
 
     @SuppressWarnings("unchecked")
     Builder(int initialCapacity) {
-      this.entries = new TerminalEntry[initialCapacity];
+      this.entries = new ImmutableMapEntry[initialCapacity];
       this.size = 0;
+      this.entriesUsed = false;
     }
 
     private void ensureCapacity(int minCapacity) {
       if (minCapacity > entries.length) {
-        entries = ObjectArrays.arraysCopyOf(
-            entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
+        entries =
+            ObjectArrays.arraysCopyOf(
+                entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
+        entriesUsed = false;
       }
     }
 
@@ -203,7 +194,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
      */
     public Builder<K, V> put(K key, V value) {
       ensureCapacity(size + 1);
-      TerminalEntry<K, V> entry = entryOf(key, value);
+      ImmutableMapEntry<K, V> entry = entryOf(key, value);
       // don't inline this: we want to fail atomically if key or value is null
       entries[size++] = entry;
       return this;
@@ -227,13 +218,45 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
      * @throws NullPointerException if any key or value in {@code map} is null
      */
     public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
-      ensureCapacity(size + map.size());
-      for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
+      return putAll(map.entrySet());
+    }
+
+    /**
+     * Adds all of the given entries to the built map.  Duplicate keys are not
+     * allowed, and will cause {@link #build} to fail.
+     *
+     * @throws NullPointerException if any key, value, or entry is null
+     * @since 19.0
+     */
+    @Beta
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      if (entries instanceof Collection) {
+        ensureCapacity(size + ((Collection<?>) entries).size());
+      }
+      for (Entry<? extends K, ? extends V> entry : entries) {
         put(entry);
       }
       return this;
     }
 
+    /**
+     * Configures this {@code Builder} to order entries by value according to the specified
+     * comparator.
+     *
+     * <p>The sort order is stable, that is, if two entries have values that compare
+     * as equivalent, the entry that was inserted first will be first in the built map's
+     * iteration order.
+     *
+     * @throws IllegalStateException if this method was already called
+     * @since 19.0
+     */
+    @Beta
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      checkState(this.valueComparator == null, "valueComparator was already set");
+      this.valueComparator = checkNotNull(valueComparator, "valueComparator");
+      return this;
+    }
+
     /*
      * TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap
      * versions throw an IllegalStateException instead?
@@ -251,7 +274,25 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
         case 1:
           return of(entries[0].getKey(), entries[0].getValue());
         default:
-          return new RegularImmutableMap<K, V>(size, entries);
+          /*
+           * If entries is full, then this implementation may end up using the entries array
+           * directly and writing over the entry objects with non-terminal entries, but this is
+           * safe; if this Builder is used further, it will grow the entries array (so it can't
+           * affect the original array), and future build() calls will always copy any entry
+           * objects that cannot be safely reused.
+           */
+          if (valueComparator != null) {
+            if (entriesUsed) {
+              entries = ObjectArrays.arraysCopyOf(entries, size);
+            }
+            Arrays.sort(
+                entries,
+                0,
+                size,
+                Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+          }
+          entriesUsed = size == entries.length;
+          return RegularImmutableMap.fromEntryArray(size, entries);
       }
     }
   }
@@ -268,10 +309,9 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    *
    * @throws NullPointerException if any key or value in {@code map} is null
    */
-  public static <K, V> ImmutableMap<K, V> copyOf(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
     if ((map instanceof ImmutableMap) && !(map instanceof ImmutableSortedMap)) {
-      // TODO(user): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
+      // TODO(lowasser): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
       // on the ImmutableMap delegate(), rather than the bimap itself
 
       @SuppressWarnings("unchecked") // safe since map is not writable
@@ -280,29 +320,43 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
         return kvMap;
       }
     } else if (map instanceof EnumMap) {
-      return copyOfEnumMapUnsafe(map);
+      @SuppressWarnings("unchecked") // safe since map is not writable
+      ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) copyOfEnumMap((EnumMap<?, ?>) map);
+      return kvMap;
     }
-    Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
-    switch (entries.length) {
+    return copyOf(map.entrySet());
+  }
+
+  /**
+   * Returns an immutable map containing the specified entries.  The returned
+   * map iterates over entries in the same order as the original iterable.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @throws IllegalArgumentException if two entries have the same key
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
+    Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+    switch (entryArray.length) {
       case 0:
         return of();
       case 1:
-        @SuppressWarnings("unchecked") // all entries will be Entry<K, V>'s
-        Entry<K, V> onlyEntry = (Entry<K, V>) entries[0];
+        Entry<K, V> onlyEntry = entryArray[0];
         return of(onlyEntry.getKey(), onlyEntry.getValue());
       default:
-        return new RegularImmutableMap<K, V>(entries);
+        /*
+         * The current implementation will end up using entryArray directly, though it will write
+         * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
+         */
+        return RegularImmutableMap.fromEntries(entryArray);
     }
   }
 
-  // If the map is an EnumMap, it must have key type K for some <K extends Enum<K>>.
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  private static <K, V> ImmutableMap<K, V> copyOfEnumMapUnsafe(Map<? extends K, ? extends V> map) {
-    return copyOfEnumMap((EnumMap) map);
-  }
-
   private static <K extends Enum<K>, V> ImmutableMap<K, V> copyOfEnumMap(
-      Map<K, ? extends V> original) {
+      EnumMap<K, ? extends V> original) {
     EnumMap<K, V> copy = new EnumMap<K, V>(original);
     for (Map.Entry<?, ?> entry : copy.entrySet()) {
       checkEntryNotNull(entry.getKey(), entry.getValue());
@@ -310,7 +364,28 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
     return ImmutableEnumMap.asImmutable(copy);
   }
 
-  private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
+  static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
+
+  abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {
+    abstract UnmodifiableIterator<Entry<K, V>> entryIterator();
+
+    @Override
+    ImmutableSet<Entry<K, V>> createEntrySet() {
+      @WeakOuter
+      class EntrySetImpl extends ImmutableMapEntrySet<K, V> {
+        @Override
+        ImmutableMap<K, V> map() {
+          return IteratorBasedImmutableMap.this;
+        }
+
+        @Override
+        public UnmodifiableIterator<Entry<K, V>> iterator() {
+          return entryIterator();
+        }
+      }
+      return new EntrySetImpl();
+    }
+  }
 
   ImmutableMap() {}
 
@@ -408,7 +483,22 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
   }
 
   ImmutableSet<K> createKeySet() {
-    return new ImmutableMapKeySet<K, V>(this);
+    return isEmpty() ? ImmutableSet.<K>of() : new ImmutableMapKeySet<K, V>(this);
+  }
+
+  UnmodifiableIterator<K> keyIterator() {
+    final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator();
+    return new UnmodifiableIterator<K>() {
+      @Override
+      public boolean hasNext() {
+        return entryIterator.hasNext();
+      }
+
+      @Override
+      public K next() {
+        return entryIterator.next().getKey();
+      }
+    };
   }
 
   private transient ImmutableCollection<V> values;
@@ -433,69 +523,78 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
    */
   @Beta
   public ImmutableSetMultimap<K, V> asMultimap() {
+    if (isEmpty()) {
+      return ImmutableSetMultimap.of();
+    }
     ImmutableSetMultimap<K, V> result = multimapView;
-    return (result == null) ? (multimapView = createMultimapView()) : result;
+    return (result == null)
+        ? (multimapView =
+            new ImmutableSetMultimap<K, V>(new MapViewOfValuesAsSingletonSets(), size(), null))
+        : result;
   }
 
-  private ImmutableSetMultimap<K, V> createMultimapView() {
-    ImmutableMap<K, ImmutableSet<V>> map = viewMapValuesAsSingletonSets();
-    return new ImmutableSetMultimap<K, V>(map, map.size(), null);
-  }
+  @WeakOuter
+  private final class MapViewOfValuesAsSingletonSets
+      extends IteratorBasedImmutableMap<K, ImmutableSet<V>> {
 
-  private ImmutableMap<K, ImmutableSet<V>> viewMapValuesAsSingletonSets() {
-    return new MapViewOfValuesAsSingletonSets<K, V>(this);
-  }
+    @Override
+    public int size() {
+      return ImmutableMap.this.size();
+    }
 
-  private static final class MapViewOfValuesAsSingletonSets<K, V>
-      extends ImmutableMap<K, ImmutableSet<V>> {
-    private final ImmutableMap<K, V> delegate;
+    @Override
+    public ImmutableSet<K> keySet() {
+      return ImmutableMap.this.keySet();
+    }
 
-    MapViewOfValuesAsSingletonSets(ImmutableMap<K, V> delegate) {
-      this.delegate = checkNotNull(delegate);
+    @Override
+    public boolean containsKey(@Nullable Object key) {
+      return ImmutableMap.this.containsKey(key);
     }
 
-    @Override public int size() {
-      return delegate.size();
+    @Override
+    public ImmutableSet<V> get(@Nullable Object key) {
+      V outerValue = ImmutableMap.this.get(key);
+      return (outerValue == null) ? null : ImmutableSet.of(outerValue);
     }
 
-    @Override public boolean containsKey(@Nullable Object key) {
-      return delegate.containsKey(key);
+    @Override
+    boolean isPartialView() {
+      return ImmutableMap.this.isPartialView();
     }
 
-    @Override public ImmutableSet<V> get(@Nullable Object key) {
-      V outerValue = delegate.get(key);
-      return (outerValue == null) ? null : ImmutableSet.of(outerValue);
+    @Override
+    public int hashCode() {
+      // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same
+      return ImmutableMap.this.hashCode();
     }
 
-    @Override boolean isPartialView() {
-      return false;
+    @Override
+    boolean isHashCodeFast() {
+      return ImmutableMap.this.isHashCodeFast();
     }
 
-    @Override ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
-      return new ImmutableMapEntrySet<K, ImmutableSet<V>>() {
-        @Override ImmutableMap<K, ImmutableSet<V>> map() {
-          return MapViewOfValuesAsSingletonSets.this;
+    @Override
+    UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() {
+      final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator();
+      return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
+        @Override
+        public boolean hasNext() {
+          return backingIterator.hasNext();
         }
 
         @Override
-        public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
-          final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
-          return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
-            @Override public boolean hasNext() {
-              return backingIterator.hasNext();
+        public Entry<K, ImmutableSet<V>> next() {
+          final Entry<K, V> backingEntry = backingIterator.next();
+          return new AbstractMapEntry<K, ImmutableSet<V>>() {
+            @Override
+            public K getKey() {
+              return backingEntry.getKey();
             }
 
-            @Override public Entry<K, ImmutableSet<V>> next() {
-              final Entry<K, V> backingEntry = backingIterator.next();
-              return new AbstractMapEntry<K, ImmutableSet<V>>() {
-                @Override public K getKey() {
-                  return backingEntry.getKey();
-                }
-
-                @Override public ImmutableSet<V> getValue() {
-                  return ImmutableSet.of(backingEntry.getValue());
-                }
-              };
+            @Override
+            public ImmutableSet<V> getValue() {
+              return ImmutableSet.of(backingEntry.getValue());
             }
           };
         }
@@ -503,19 +602,24 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
     }
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return Maps.equalsImpl(this, object);
   }
 
   abstract boolean isPartialView();
 
-  @Override public int hashCode() {
-    // not caching hash code since it could change if map values are mutable
-    // in a way that modifies their hash codes
-    return entrySet().hashCode();
+  @Override
+  public int hashCode() {
+    return Sets.hashCodeImpl(entrySet());
   }
 
-  @Override public String toString() {
+  boolean isHashCodeFast() {
+    return false;
+  }
+
+  @Override
+  public String toString() {
     return Maps.toStringImpl(this);
   }
 
@@ -527,6 +631,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
   static class SerializedForm implements Serializable {
     private final Object[] keys;
     private final Object[] values;
+
     SerializedForm(ImmutableMap<?, ?> map) {
       keys = new Object[map.size()];
       values = new Object[map.size()];
@@ -537,16 +642,19 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
         i++;
       }
     }
+
     Object readResolve() {
-      Builder<Object, Object> builder = new Builder<Object, Object>();
+      Builder<Object, Object> builder = new Builder<Object, Object>(keys.length);
       return createMap(builder);
     }
+
     Object createMap(Builder<Object, Object> builder) {
       for (int i = 0; i < keys.length; i++) {
         builder.put(keys[i], values[i]);
       }
       return builder.build();
     }
+
     private static final long serialVersionUID = 0;
   }
 
diff --git a/guava/src/com/google/common/collect/ImmutableMapEntry.java b/guava/src/com/google/common/collect/ImmutableMapEntry.java
index 6d2aa94..6487aee 100644
--- a/guava/src/com/google/common/collect/ImmutableMapEntry.java
+++ b/guava/src/com/google/common/collect/ImmutableMapEntry.java
@@ -28,10 +28,23 @@ import javax.annotation.Nullable;
  * {@link RegularImmutableBiMap}, which don't have to recopy the entries created by their
  * {@code Builder} implementations.
  *
+ * <p>This base implementation has no key or value pointers, so instances of ImmutableMapEntry
+ * (but not its subclasses) can be reused when copied from one ImmutableMap to another.
+ *
  * @author Louis Wasserman
  */
 @GwtIncompatible("unnecessary")
-abstract class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
+class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
+  /**
+   * Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The
+   * result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or
+   * allowed to escape the class.
+   */
+  @SuppressWarnings("unchecked") // Safe as long as the javadocs are followed
+  static <K, V> ImmutableMapEntry<K, V>[] createEntryArray(int size) {
+    return new ImmutableMapEntry[size];
+  }
+
   ImmutableMapEntry(K key, V value) {
     super(key, value);
     checkEntryNotNull(key, value);
@@ -43,30 +56,60 @@ abstract class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
   }
 
   @Nullable
-  abstract ImmutableMapEntry<K, V> getNextInKeyBucket();
+  ImmutableMapEntry<K, V> getNextInKeyBucket() {
+    return null;
+  }
 
   @Nullable
-  abstract ImmutableMapEntry<K, V> getNextInValueBucket();
+  ImmutableMapEntry<K, V> getNextInValueBucket() {
+    return null;
+  }
 
-  static final class TerminalEntry<K, V> extends ImmutableMapEntry<K, V> {
-    TerminalEntry(ImmutableMapEntry<K, V> contents) {
-      super(contents);
-    }
+  /**
+   * Returns true if this entry has no bucket links and can safely be reused as a terminal
+   * entry in a bucket in another map.
+   */
+  boolean isReusable() {
+    return true;
+  }
+
+  static class NonTerminalImmutableMapEntry<K, V> extends ImmutableMapEntry<K, V> {
+    private final transient ImmutableMapEntry<K, V> nextInKeyBucket;
 
-    TerminalEntry(K key, V value) {
+    NonTerminalImmutableMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {
       super(key, value);
+      this.nextInKeyBucket = nextInKeyBucket;
     }
 
     @Override
     @Nullable
-    ImmutableMapEntry<K, V> getNextInKeyBucket() {
-      return null;
+    final ImmutableMapEntry<K, V> getNextInKeyBucket() {
+      return nextInKeyBucket;
+    }
+
+    @Override
+    final boolean isReusable() {
+      return false;
+    }
+  }
+
+  static final class NonTerminalImmutableBiMapEntry<K, V>
+      extends NonTerminalImmutableMapEntry<K, V> {
+    private final transient ImmutableMapEntry<K, V> nextInValueBucket;
+
+    NonTerminalImmutableBiMapEntry(
+        K key,
+        V value,
+        ImmutableMapEntry<K, V> nextInKeyBucket,
+        ImmutableMapEntry<K, V> nextInValueBucket) {
+      super(key, value, nextInKeyBucket);
+      this.nextInValueBucket = nextInValueBucket;
     }
 
     @Override
     @Nullable
     ImmutableMapEntry<K, V> getNextInValueBucket() {
-      return null;
+      return nextInValueBucket;
     }
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
index a6aa6e0..0329c05 100644
--- a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
+++ b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
 
 import java.io.Serializable;
 import java.util.Map.Entry;
@@ -32,6 +33,31 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
+  static final class RegularEntrySet<K, V> extends ImmutableMapEntrySet<K, V> {
+    @Weak private final transient ImmutableMap<K, V> map;
+    private final transient Entry<K, V>[] entries;
+
+    RegularEntrySet(ImmutableMap<K, V> map, Entry<K, V>[] entries) {
+      this.map = map;
+      this.entries = entries;
+    }
+
+    @Override
+    ImmutableMap<K, V> map() {
+      return map;
+    }
+
+    @Override
+    public UnmodifiableIterator<Entry<K, V>> iterator() {
+      return asList().iterator();
+    }
+
+    @Override
+    ImmutableList<Entry<K, V>> createAsList() {
+      return new RegularImmutableAsList<Entry<K, V>>(this, entries);
+    }
+  }
+
   ImmutableMapEntrySet() {}
 
   abstract ImmutableMap<K, V> map();
@@ -56,6 +82,17 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
     return map().isPartialView();
   }
 
+  @Override
+  @GwtIncompatible("not used in GWT")
+  boolean isHashCodeFast() {
+    return map().isHashCodeFast();
+  }
+
+  @Override
+  public int hashCode() {
+    return map().hashCode();
+  }
+
   @GwtIncompatible("serialization")
   @Override
   Object writeReplace() {
@@ -65,12 +102,15 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
   @GwtIncompatible("serialization")
   private static class EntrySetSerializedForm<K, V> implements Serializable {
     final ImmutableMap<K, V> map;
+
     EntrySetSerializedForm(ImmutableMap<K, V> map) {
       this.map = map;
     }
+
     Object readResolve() {
       return map.entrySet();
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableMapKeySet.java b/guava/src/com/google/common/collect/ImmutableMapKeySet.java
index fbb59d8..b97560b 100644
--- a/guava/src/com/google/common/collect/ImmutableMapKeySet.java
+++ b/guava/src/com/google/common/collect/ImmutableMapKeySet.java
@@ -18,9 +18,9 @@ package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
 
 import java.io.Serializable;
-import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 
@@ -31,8 +31,8 @@ import javax.annotation.Nullable;
  * @author Kevin Bourrillion
  */
 @GwtCompatible(emulated = true)
-final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
-  private final ImmutableMap<K, V> map;
+final class ImmutableMapKeySet<K, V> extends ImmutableSet.Indexed<K> {
+  @Weak private final ImmutableMap<K, V> map;
 
   ImmutableMapKeySet(ImmutableMap<K, V> map) {
     this.map = map;
@@ -45,7 +45,7 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
 
   @Override
   public UnmodifiableIterator<K> iterator() {
-    return asList().iterator();
+    return map.keyIterator();
   }
 
   @Override
@@ -54,21 +54,8 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
   }
 
   @Override
-  ImmutableList<K> createAsList() {
-    final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
-    return new ImmutableAsList<K>() {
-
-      @Override
-      public K get(int index) {
-        return entryList.get(index).getKey();
-      }
-
-      @Override
-      ImmutableCollection<K> delegateCollection() {
-        return ImmutableMapKeySet.this;
-      }
-
-    };
+  K get(int index) {
+    return map.entrySet().asList().get(index).getKey();
   }
 
   @Override
@@ -77,19 +64,23 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
   }
 
   @GwtIncompatible("serialization")
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new KeySetSerializedForm<K>(map);
   }
 
   @GwtIncompatible("serialization")
   private static class KeySetSerializedForm<K> implements Serializable {
     final ImmutableMap<K, ?> map;
+
     KeySetSerializedForm(ImmutableMap<K, ?> map) {
       this.map = map;
     }
+
     Object readResolve() {
       return map.keySet();
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableMapValues.java b/guava/src/com/google/common/collect/ImmutableMapValues.java
index 379b14d..be291fb 100644
--- a/guava/src/com/google/common/collect/ImmutableMapValues.java
+++ b/guava/src/com/google/common/collect/ImmutableMapValues.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
 
 import java.io.Serializable;
 import java.util.Map.Entry;
@@ -32,8 +33,8 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
-  private final ImmutableMap<K, V> map;
-  
+  @Weak private final ImmutableMap<K, V> map;
+
   ImmutableMapValues(ImmutableMap<K, V> map) {
     this.map = map;
   }
@@ -45,7 +46,19 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
 
   @Override
   public UnmodifiableIterator<V> iterator() {
-    return Maps.valueIterator(map.entrySet().iterator());
+    return new UnmodifiableIterator<V>() {
+      final UnmodifiableIterator<Entry<K, V>> entryItr = map.entrySet().iterator();
+
+      @Override
+      public boolean hasNext() {
+        return entryItr.hasNext();
+      }
+
+      @Override
+      public V next() {
+        return entryItr.next().getValue();
+      }
+    };
   }
 
   @Override
@@ -75,19 +88,23 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
   }
 
   @GwtIncompatible("serialization")
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm<V>(map);
   }
 
   @GwtIncompatible("serialization")
   private static class SerializedForm<V> implements Serializable {
     final ImmutableMap<?, V> map;
+
     SerializedForm(ImmutableMap<?, V> map) {
       this.map = map;
     }
+
     Object readResolve() {
       return map.values();
     }
+
     private static final long serialVersionUID = 0;
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableMultimap.java b/guava/src/com/google/common/collect/ImmutableMultimap.java
index 32bf988..5790218 100644
--- a/guava/src/com/google/common/collect/ImmutableMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableMultimap.java
@@ -19,8 +19,11 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Arrays;
@@ -28,7 +31,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -37,29 +39,30 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link Multimap}. Does not permit null keys or values.
+ * A {@link Multimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Multimaps#unmodifiableMultimap(Multimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
+ * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
+ * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
+ * source of bugs and confusion.
  *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
+ * need for a distinct {@code ImmutableBiMultimap} type.
  *
- * <p>In addition to methods defined by {@link Multimap}, an {@link #inverse}
- * method is also supported.
+ * <a name="iteration"></a>
+ * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
+ * current implementations, the iteration order always keeps multiple entries with the same key
+ * together. Any creation method that would customarily respect insertion order (such as {@link
+ * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
+ * immediately after the last entry having that key.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
@@ -85,23 +88,27 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
-  public static <K, V> ImmutableMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
+  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
     return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
-  public static <K, V> ImmutableMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
     return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
   }
 
   /**
-   * Returns an immutable multimap containing the given entries, in order.
+   * Returns an immutable multimap containing the given entries, in the
+   * "key-grouped" insertion order described in the
+   * <a href="#iteration">class documentation</a>.
    */
   public static <K, V> ImmutableMultimap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
@@ -119,21 +126,6 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
-   * value orderings, allows duplicate values, and performs better than
-   * {@link LinkedListMultimap}.
-   */
-  private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
-    BuilderMultimap() {
-      super(new LinkedHashMap<K, Collection<V>>());
-    }
-    @Override Collection<V> createCollection() {
-      return Lists.newArrayList();
-    }
-    private static final long serialVersionUID = 0;
-  }
-
-  /**
    * A builder for creating immutable multimap instances, especially
    * {@code public static final} multimaps ("constant multimaps"). Example:
    * <pre>   {@code
@@ -149,10 +141,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<K, V> {
-    Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
+    Multimap<K, V> builderMultimap;
     Comparator<? super K> keyComparator;
     Comparator<? super V> valueComparator;
 
@@ -160,7 +152,13 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableMultimap#builder}.
      */
-    public Builder() {}
+    public Builder() {
+      this(MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build());
+    }
+    
+    Builder(Multimap<K, V> builderMultimap) {
+      this.builderMultimap = builderMultimap;
+    }
 
     /**
      * Adds a key-value mapping to the built multimap.
@@ -181,6 +179,19 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     }
 
     /**
+     * Adds entries to the built multimap.
+     *
+     * @since 19.0
+     */
+    @Beta
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      for (Entry<? extends K, ? extends V> entry : entries) {
+        put(entry);
+      }
+      return this;
+    }
+
+    /**
      * Stores a collection of values with the same key in the built multimap.
      *
      * @throws NullPointerException if {@code key}, {@code values}, or any
@@ -189,8 +200,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      */
     public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       if (key == null) {
-        throw new NullPointerException(
-            "null key in entry: null=" + Iterables.toString(values));
+        throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
       }
       Collection<V> valueList = builderMultimap.get(key);
       for (V value : values) {
@@ -220,8 +230,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
      *     null. The builder is left in an invalid state.
      */
     public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
-      for (Entry<? extends K, ? extends Collection<? extends V>> entry
-          : multimap.asMap().entrySet()) {
+      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+          multimap.asMap().entrySet()) {
         putAll(entry.getKey(), entry.getValue());
       }
       return this;
@@ -253,17 +263,17 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public ImmutableMultimap<K, V> build() {
       if (valueComparator != null) {
         for (Collection<V> values : builderMultimap.asMap().values()) {
-          List<V> list = (List <V>) values;
+          List<V> list = (List<V>) values;
           Collections.sort(list, valueComparator);
         }
       }
       if (keyComparator != null) {
-        Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
-        List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
-            builderMultimap.asMap().entrySet());
-        Collections.sort(
-            entries,
-            Ordering.from(keyComparator).<K>onKeys());
+        Multimap<K, V> sortedCopy =
+            MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build();
+        List<Map.Entry<K, Collection<V>>> entries =
+            Ordering.from(keyComparator)
+                .<K>onKeys()
+                .immutableSortedCopy(builderMultimap.asMap().entrySet());
         for (Map.Entry<K, Collection<V>> entry : entries) {
           sortedCopy.putAll(entry.getKey(), entry.getValue());
         }
@@ -275,8 +285,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
   /**
    * Returns an immutable multimap containing the same mappings as {@code
-   * multimap}. The generated multimap's key and value orderings correspond to
-   * the iteration ordering of the {@code multimap.asMap()} view.
+   * multimap}, in the "key-grouped" iteration order described in the class
+   * documentation.
    *
    * <p>Despite the method name, this method attempts to avoid actually copying
    * the data when it is safe to do so. The exact circumstances under which a
@@ -285,12 +295,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    * @throws NullPointerException if any key or value in {@code multimap} is
    *         null
    */
-  public static <K, V> ImmutableMultimap<K, V> copyOf(
-      Multimap<? extends K, ? extends V> multimap) {
+  public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
     if (multimap instanceof ImmutableMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableMultimap<K, V> kvMultimap
-          = (ImmutableMultimap<K, V>) multimap;
+      ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
@@ -298,6 +306,21 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     return ImmutableListMultimap.copyOf(multimap);
   }
 
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return ImmutableListMultimap.copyOf(entries);
+  }
+
   final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
   final transient int size;
 
@@ -306,19 +329,15 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   // deserialized.
   @GwtIncompatible("java serialization is not supported")
   static class FieldSettersHolder {
-    static final Serialization.FieldSetter<ImmutableMultimap>
-        MAP_FIELD_SETTER = Serialization.getFieldSetter(
-        ImmutableMultimap.class, "map");
-    static final Serialization.FieldSetter<ImmutableMultimap>
-        SIZE_FIELD_SETTER = Serialization.getFieldSetter(
-        ImmutableMultimap.class, "size");
-    static final Serialization.FieldSetter<ImmutableSetMultimap>
-        EMPTY_SET_FIELD_SETTER = Serialization.getFieldSetter(
-        ImmutableSetMultimap.class, "emptySet");
-  }
-
-  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
-      int size) {
+    static final Serialization.FieldSetter<ImmutableMultimap> MAP_FIELD_SETTER =
+        Serialization.getFieldSetter(ImmutableMultimap.class, "map");
+    static final Serialization.FieldSetter<ImmutableMultimap> SIZE_FIELD_SETTER =
+        Serialization.getFieldSetter(ImmutableMultimap.class, "size");
+    static final Serialization.FieldSetter<ImmutableSetMultimap> EMPTY_SET_FIELD_SETTER =
+        Serialization.getFieldSetter(ImmutableSetMultimap.class, "emptySet");
+  }
+
+  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
     this.map = map;
     this.size = size;
   }
@@ -345,8 +364,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
    */
   @Deprecated
   @Override
-  public ImmutableCollection<V> replaceValues(K key,
-      Iterable<? extends V> values) {
+  public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 
@@ -427,7 +445,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public boolean remove(Object key, Object value) {
     throw new UnsupportedOperationException();
   }
-  
+
   /**
    * Returns {@code true} if this immutable multimap's implementation contains references to
    * user-created objects that aren't accessible via this multimap's methods. This is generally
@@ -449,7 +467,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public boolean containsValue(@Nullable Object value) {
     return value != null && super.containsValue(value);
   }
-  
+
   @Override
   public int size() {
     return size;
@@ -458,9 +476,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   // views
 
   /**
-   * Returns an immutable set of the distinct keys in this multimap. These keys
-   * are ordered according to when they first appeared during the construction
-   * of this multimap.
+   * Returns an immutable set of the distinct keys in this multimap, in the same
+   * order as they appear in this multimap.
    */
   @Override
   public ImmutableSet<K> keySet() {
@@ -469,47 +486,47 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
   /**
    * Returns an immutable map that associates each key with its corresponding
-   * values in the multimap.
+   * values in the multimap. Keys and values appear in the same order as in this
+   * multimap.
    */
   @Override
   @SuppressWarnings("unchecked") // a widening cast
   public ImmutableMap<K, Collection<V>> asMap() {
     return (ImmutableMap) map;
   }
-  
+
   @Override
   Map<K, Collection<V>> createAsMap() {
     throw new AssertionError("should never be called");
   }
 
   /**
-   * Returns an immutable collection of all key-value pairs in the multimap. Its
-   * iterator traverses the values for the first key, the values for the second
-   * key, and so on.
+   * Returns an immutable collection of all key-value pairs in the multimap.
    */
   @Override
   public ImmutableCollection<Entry<K, V>> entries() {
     return (ImmutableCollection<Entry<K, V>>) super.entries();
   }
-  
+
   @Override
   ImmutableCollection<Entry<K, V>> createEntries() {
     return new EntryCollection<K, V>(this);
   }
 
-  private static class EntryCollection<K, V>
-      extends ImmutableCollection<Entry<K, V>> {
-    final ImmutableMultimap<K, V> multimap;
+  private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
+    @Weak final ImmutableMultimap<K, V> multimap;
 
     EntryCollection(ImmutableMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
 
-    @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
+    @Override
+    public UnmodifiableIterator<Entry<K, V>> iterator() {
       return multimap.entryIterator();
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return multimap.isPartialView();
     }
 
@@ -518,7 +535,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return multimap.size();
     }
 
-    @Override public boolean contains(Object object) {
+    @Override
+    public boolean contains(Object object) {
       if (object instanceof Entry) {
         Entry<?, ?> entry = (Entry<?, ?>) object;
         return multimap.containsEntry(entry.getKey(), entry.getValue());
@@ -528,12 +546,12 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
 
     private static final long serialVersionUID = 0;
   }
-  
+
   private abstract class Itr<T> extends UnmodifiableIterator<T> {
     final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
     K key = null;
     Iterator<V> valueIterator = Iterators.emptyIterator();
-    
+
     abstract T output(K key, V value);
 
     @Override
@@ -551,7 +569,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return output(key, valueIterator.next());
     }
   }
-  
+
   @Override
   UnmodifiableIterator<Entry<K, V>> entryIterator() {
     return new Itr<Entry<K, V>>() {
@@ -563,10 +581,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   /**
-   * Returns a collection, which may contain duplicates, of all keys. The number
-   * of times a key appears in the returned multiset equals the number of
-   * mappings the key has in the multimap. Duplicate keys appear consecutively
-   * in the multiset's iteration order.
+   * Returns an immutable multiset containing all the keys in this multimap, in
+   * the same order and with the same frequencies as they appear in this
+   * multimap; to get only a single occurrence of each key, use {@link #keySet}.
    */
   @Override
   public ImmutableMultiset<K> keys() {
@@ -579,6 +596,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   @SuppressWarnings("serial") // Uses writeReplace, not default serialization
+  @WeakOuter
   class Keys extends ImmutableMultiset<K> {
     @Override
     public boolean contains(@Nullable Object object) {
@@ -600,7 +618,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public int size() {
       return ImmutableMultimap.this.size();
     }
-    
+
     @Override
     Multiset.Entry<K> getEntry(int index) {
       Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
@@ -622,7 +640,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   public ImmutableCollection<V> values() {
     return (ImmutableCollection<V>) super.values();
   }
-  
+
   @Override
   ImmutableCollection<V> createValues() {
     return new Values<K, V>(this);
@@ -639,8 +657,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   private static final class Values<K, V> extends ImmutableCollection<V> {
-    private transient final ImmutableMultimap<K, V> multimap;
-    
+    @Weak private final transient ImmutableMultimap<K, V> multimap;
+
     Values(ImmutableMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
@@ -649,8 +667,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
     public boolean contains(@Nullable Object object) {
       return multimap.containsValue(object);
     }
-    
-    @Override public UnmodifiableIterator<V> iterator() {
+
+    @Override
+    public UnmodifiableIterator<V> iterator() {
       return multimap.valueIterator();
     }
 
@@ -668,7 +687,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
       return multimap.size();
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return true;
     }
 
diff --git a/guava/src/com/google/common/collect/ImmutableMultiset.java b/guava/src/com/google/common/collect/ImmutableMultiset.java
index 1b060f6..02c51ca 100644
--- a/guava/src/com/google/common/collect/ImmutableMultiset.java
+++ b/guava/src/com/google/common/collect/ImmutableMultiset.java
@@ -21,46 +21,42 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.Multiset.Entry;
-import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 
 import javax.annotation.Nullable;
 
 /**
- * An immutable hash-based multiset. Does not permit null elements.
+ * A {@link Multiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Its iterator orders elements according to the first appearance of the
- * element among the items passed to the factory method or builder. When the
- * multiset contains multiple instances of an element, those instances are
- * consecutive in the iteration order.
+ * <p><b>Grouped iteration.</b> In all current implementations, duplicate elements always appear
+ * consecutively when iterating. Elements iterate in order by the <i>first</i> appearance of
+ * that element when the multiset was created.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
-// TODO(user): write an efficient asList() implementation
-public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
-    implements Multiset<E> {
-
-  private static final ImmutableMultiset<Object> EMPTY =
-      new RegularImmutableMultiset<Object>(ImmutableMap.<Object, Integer>of(), 0);
-
+// TODO(lowasser): write an efficient asList() implementation
+public abstract class ImmutableMultiset<E> extends ImmutableCollection<E> implements Multiset<E> {
   /**
    * Returns the empty immutable multiset.
    */
   @SuppressWarnings("unchecked") // all supported methods are covariant
   public static <E> ImmutableMultiset<E> of() {
-    return (ImmutableMultiset<E>) EMPTY;
+    return (ImmutableMultiset<E>) RegularImmutableMultiset.EMPTY;
   }
 
   /**
@@ -71,7 +67,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    */
   @SuppressWarnings("unchecked") // generic array created but never written
   public static <E> ImmutableMultiset<E> of(E element) {
-    return copyOfInternal(element);
+    return copyFromElements(element);
   }
 
   /**
@@ -82,51 +78,54 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2) {
-    return copyOfInternal(e1, e2);
+    return copyFromElements(e1, e2);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) {
-    return copyOfInternal(e1, e2, e3);
+    return copyFromElements(e1, e2, e3);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) {
-    return copyOfInternal(e1, e2, e3, e4);
+    return copyFromElements(e1, e2, e3, e4);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
   public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
-    return copyOfInternal(e1, e2, e3, e4, e5);
+    return copyFromElements(e1, e2, e3, e4, e5);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements, in order.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any element is null
    * @since 6.0 (source-compatible since 2.0)
    */
   @SuppressWarnings("unchecked") //
-  public static <E> ImmutableMultiset<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
+  public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
     return new Builder<E>()
         .add(e1)
         .add(e2)
@@ -139,38 +138,23 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example, {@code ImmutableMultiset.copyOf([2, 3, 1, 3])} yields a multiset
-   * with elements in the order {@code 2, 3, 3, 1}.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    * @since 6.0
    */
   public static <E> ImmutableMultiset<E> copyOf(E[] elements) {
-    return copyOf(Arrays.asList(elements));
+    return copyFromElements(elements);
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example, {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3))} yields
-   * a multiset with elements in the order {@code 2, 3, 3, 1}.
-   *
-   * <p>Despite the method name, this method attempts to avoid actually copying
-   * the data when it is safe to do so. The exact circumstances under which a
-   * copy will or will not be performed are undocumented and subject to change.
-   *
-   * <p><b>Note:</b> Despite what the method name suggests, if {@code elements}
-   * is an {@code ImmutableMultiset}, no copy will actually be performed, and
-   * the given multiset itself will be returned.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableMultiset<E> copyOf(
-      Iterable<? extends E> elements) {
+  public static <E> ImmutableMultiset<E> copyOf(Iterable<? extends E> elements) {
     if (elements instanceof ImmutableMultiset) {
       @SuppressWarnings("unchecked") // all supported methods are covariant
       ImmutableMultiset<E> result = (ImmutableMultiset<E>) elements;
@@ -179,63 +163,45 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
       }
     }
 
-    Multiset<? extends E> multiset = (elements instanceof Multiset)
-        ? Multisets.cast(elements)
-        : LinkedHashMultiset.create(elements);
+    Multiset<? extends E> multiset =
+        (elements instanceof Multiset)
+            ? Multisets.cast(elements)
+            : LinkedHashMultiset.create(elements);
 
-    return copyOfInternal(multiset);
-  }
-
-  private static <E> ImmutableMultiset<E> copyOfInternal(E... elements) {
-    return copyOf(Arrays.asList(elements));
+    return copyFromEntries(multiset.entrySet());
   }
 
-  private static <E> ImmutableMultiset<E> copyOfInternal(
-      Multiset<? extends E> multiset) {
+  private static <E> ImmutableMultiset<E> copyFromElements(E... elements) {
+    Multiset<E> multiset = LinkedHashMultiset.create();
+    Collections.addAll(multiset, elements);
     return copyFromEntries(multiset.entrySet());
   }
 
   static <E> ImmutableMultiset<E> copyFromEntries(
       Collection<? extends Entry<? extends E>> entries) {
-    long size = 0;
-    ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
-    for (Entry<? extends E> entry : entries) {
-      int count = entry.getCount();
-      if (count > 0) {
-        // Since ImmutableMap.Builder throws an NPE if an element is null, no
-        // other null checks are needed.
-        builder.put(entry.getElement(), count);
-        size += count;
-      }
-    }
-
-    if (size == 0) {
+    if (entries.isEmpty()) {
       return of();
+    } else {
+      return new RegularImmutableMultiset<E>(entries);
     }
-    return new RegularImmutableMultiset<E>(
-        builder.build(), Ints.saturatedCast(size));
   }
 
   /**
-   * Returns an immutable multiset containing the given elements.
-   *
-   * <p>The multiset is ordered by the first occurrence of each element. For
-   * example,
-   * {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3).iterator())}
-   * yields a multiset with elements in the order {@code 2, 3, 3, 1}.
+   * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+   * described in the class documentation.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableMultiset<E> copyOf(
-      Iterator<? extends E> elements) {
+  public static <E> ImmutableMultiset<E> copyOf(Iterator<? extends E> elements) {
     Multiset<E> multiset = LinkedHashMultiset.create();
     Iterators.addAll(multiset, elements);
-    return copyOfInternal(multiset);
+    return copyFromEntries(multiset.entrySet());
   }
 
   ImmutableMultiset() {}
 
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     final Iterator<Entry<E>> entryIterator = entrySet().iterator();
     return new UnmodifiableIterator<E>() {
       int remaining;
@@ -264,11 +230,6 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     return count(object) > 0;
   }
 
-  @Override
-  public boolean containsAll(Collection<?> targets) {
-    return elementSet().containsAll(targets);
-  }
-
   /**
    * Guaranteed to throw an exception and leave the collection unmodified.
    *
@@ -327,15 +288,18 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     return offset;
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     return Multisets.equalsImpl(this, object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Sets.hashCodeImpl(entrySet());
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return entrySet().toString();
   }
 
@@ -353,30 +317,16 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
 
   abstract Entry<E> getEntry(int index);
 
-  private final class EntrySet extends ImmutableSet<Entry<E>> {
+  @WeakOuter
+  private final class EntrySet extends ImmutableSet.Indexed<Entry<E>> {
     @Override
     boolean isPartialView() {
       return ImmutableMultiset.this.isPartialView();
     }
 
     @Override
-    public UnmodifiableIterator<Entry<E>> iterator() {
-      return asList().iterator();
-    }
-
-    @Override
-    ImmutableList<Entry<E>> createAsList() {
-      return new ImmutableAsList<Entry<E>>() {
-        @Override
-        public Entry<E> get(int index) {
-          return getEntry(index);
-        }
-
-        @Override
-        ImmutableCollection<Entry<E>> delegateCollection() {
-          return EntrySet.this;
-        }
-      };
+    Entry<E> get(int index) {
+      return getEntry(index);
     }
 
     @Override
@@ -441,8 +391,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
     }
 
     Object readResolve() {
-      LinkedHashMultiset<Object> multiset =
-          LinkedHashMultiset.create(elements.length);
+      LinkedHashMultiset<Object> multiset = LinkedHashMultiset.create(elements.length);
       for (int i = 0; i < elements.length; i++) {
         multiset.add(elements[i], counts[i]);
       }
@@ -482,7 +431,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
    * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
    * times to build multiple multisets in series.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<E> extends ImmutableCollection.Builder<E> {
     final Multiset<E> contents;
@@ -506,7 +455,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code element} is null
      */
-    @Override public Builder<E> add(E element) {
+    @Override
+    public Builder<E> add(E element) {
       contents.add(checkNotNull(element));
       return this;
     }
@@ -552,7 +502,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> add(E... elements) {
+    @Override
+    public Builder<E> add(E... elements) {
       super.add(elements);
       return this;
     }
@@ -566,7 +517,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterable<? extends E> elements) {
       if (elements instanceof Multiset) {
         Multiset<? extends E> multiset = Multisets.cast(elements);
         for (Entry<? extends E> entry : multiset.entrySet()) {
@@ -586,7 +538,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterator<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -595,7 +548,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
      * Returns a newly-created {@code ImmutableMultiset} based on the contents
      * of the {@code Builder}.
      */
-    @Override public ImmutableMultiset<E> build() {
+    @Override
+    public ImmutableMultiset<E> build() {
       return copyOf(contents);
     }
   }
diff --git a/guava/src/com/google/common/collect/ImmutableRangeMap.java b/guava/src/com/google/common/collect/ImmutableRangeMap.java
index 49b3989..a96b857 100644
--- a/guava/src/com/google/common/collect/ImmutableRangeMap.java
+++ b/guava/src/com/google/common/collect/ImmutableRangeMap.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.SortedLists.KeyAbsentBehavior;
 import com.google.common.collect.SortedLists.KeyPresentBehavior;
 
+import java.io.Serializable;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
@@ -30,16 +31,15 @@ import java.util.NoSuchElementException;
 import javax.annotation.Nullable;
 
 /**
- * An immutable implementation of {@code RangeMap}, supporting all query operations efficiently.
- *
- * <p>Like all {@code RangeMap} implementations, this supports neither null keys nor null values.
+ * A {@link RangeMap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * @author Louis Wasserman
  * @since 14.0
  */
 @Beta
 @GwtIncompatible("NavigableMap")
-public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K, V> {
+public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K, V>, Serializable {
 
   private static final ImmutableRangeMap<Comparable<?>, Object> EMPTY =
       new ImmutableRangeMap<Comparable<?>, Object>(
@@ -56,8 +56,7 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
   /**
    * Returns an immutable range map mapping a single range to a single value.
    */
-  public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of(
-      Range<K> range, V value) {
+  public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of(Range<K> range, V value) {
     return new ImmutableRangeMap<K, V>(ImmutableList.of(range), ImmutableList.of(value));
   }
 
@@ -151,8 +150,8 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
     }
   }
 
-  private final ImmutableList<Range<K>> ranges;
-  private final ImmutableList<V> values;
+  private final transient ImmutableList<Range<K>> ranges;
+  private final transient ImmutableList<V> values;
 
   ImmutableRangeMap(ImmutableList<Range<K>> ranges, ImmutableList<V> values) {
     this.ranges = ranges;
@@ -162,8 +161,13 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
   @Override
   @Nullable
   public V get(K key) {
-    int index = SortedLists.binarySearch(ranges, Range.<K>lowerBoundFn(),
-        Cut.belowValue(key), KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_LOWER);
+    int index =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<K>lowerBoundFn(),
+            Cut.belowValue(key),
+            KeyPresentBehavior.ANY_PRESENT,
+            KeyAbsentBehavior.NEXT_LOWER);
     if (index == -1) {
       return null;
     } else {
@@ -175,8 +179,13 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
   @Override
   @Nullable
   public Map.Entry<Range<K>, V> getEntry(K key) {
-    int index = SortedLists.binarySearch(ranges, Range.<K>lowerBoundFn(),
-        Cut.belowValue(key), KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_LOWER);
+    int index =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<K>lowerBoundFn(),
+            Cut.belowValue(key),
+            KeyPresentBehavior.ANY_PRESENT,
+            KeyAbsentBehavior.NEXT_LOWER);
     if (index == -1) {
       return null;
     } else {
@@ -222,9 +231,20 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
     }
     RegularImmutableSortedSet<Range<K>> rangeSet =
         new RegularImmutableSortedSet<Range<K>>(ranges, Range.RANGE_LEX_ORDERING);
-    return new RegularImmutableSortedMap<Range<K>, V>(rangeSet, values);
+    return new ImmutableSortedMap<Range<K>, V>(rangeSet, values);
+  }
+
+  @Override
+  public ImmutableMap<Range<K>, V> asDescendingMapOfRanges() {
+    if (ranges.isEmpty()) {
+      return ImmutableMap.of();
+    }
+    RegularImmutableSortedSet<Range<K>> rangeSet =
+        new RegularImmutableSortedSet<Range<K>>(
+            ranges.reverse(), Range.RANGE_LEX_ORDERING.reverse());
+    return new ImmutableSortedMap<Range<K>, V>(rangeSet, values.reverse());
   }
-  
+
   @Override
   public ImmutableRangeMap<K, V> subRangeMap(final Range<K> range) {
     if (checkNotNull(range).isEmpty()) {
@@ -232,49 +252,57 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
     } else if (ranges.isEmpty() || range.encloses(span())) {
       return this;
     }
-    int lowerIndex = SortedLists.binarySearch(
-        ranges, Range.<K>upperBoundFn(), range.lowerBound,
-        KeyPresentBehavior.FIRST_AFTER, KeyAbsentBehavior.NEXT_HIGHER);
-    int upperIndex = SortedLists.binarySearch(ranges, 
-        Range.<K>lowerBoundFn(), range.upperBound,
-        KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_HIGHER);
+    int lowerIndex =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<K>upperBoundFn(),
+            range.lowerBound,
+            KeyPresentBehavior.FIRST_AFTER,
+            KeyAbsentBehavior.NEXT_HIGHER);
+    int upperIndex =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<K>lowerBoundFn(),
+            range.upperBound,
+            KeyPresentBehavior.ANY_PRESENT,
+            KeyAbsentBehavior.NEXT_HIGHER);
     if (lowerIndex >= upperIndex) {
       return ImmutableRangeMap.of();
     }
     final int off = lowerIndex;
     final int len = upperIndex - lowerIndex;
-    ImmutableList<Range<K>> subRanges = new ImmutableList<Range<K>>() {
-      @Override
-      public int size() {
-        return len;
-      }
-
-      @Override
-      public Range<K> get(int index) {
-        checkElementIndex(index, len);
-        if (index == 0 || index == len - 1) {
-          return ranges.get(index + off).intersection(range);
-        } else {
-          return ranges.get(index + off);
-        }
-      }
+    ImmutableList<Range<K>> subRanges =
+        new ImmutableList<Range<K>>() {
+          @Override
+          public int size() {
+            return len;
+          }
 
-      @Override
-      boolean isPartialView() {
-        return true;
-      }
-    };
-    final ImmutableRangeMap<K, V> outer = this;
-    return new ImmutableRangeMap<K, V>(
-        subRanges, values.subList(lowerIndex, upperIndex)) {
           @Override
-          public ImmutableRangeMap<K, V> subRangeMap(Range<K> subRange) {
-            if (range.isConnected(subRange)) {
-              return outer.subRangeMap(subRange.intersection(range));
+          public Range<K> get(int index) {
+            checkElementIndex(index, len);
+            if (index == 0 || index == len - 1) {
+              return ranges.get(index + off).intersection(range);
             } else {
-              return ImmutableRangeMap.of();
+              return ranges.get(index + off);
             }
           }
+
+          @Override
+          boolean isPartialView() {
+            return true;
+          }
+        };
+    final ImmutableRangeMap<K, V> outer = this;
+    return new ImmutableRangeMap<K, V>(subRanges, values.subList(lowerIndex, upperIndex)) {
+      @Override
+      public ImmutableRangeMap<K, V> subRangeMap(Range<K> subRange) {
+        if (range.isConnected(subRange)) {
+          return outer.subRangeMap(subRange.intersection(range));
+        } else {
+          return ImmutableRangeMap.of();
+        }
+      }
     };
   }
 
@@ -296,4 +324,41 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
   public String toString() {
     return asMapOfRanges().toString();
   }
+
+  /**
+   * This class is used to serialize ImmutableRangeMap instances.
+   * Serializes the {@link #asMapOfRanges()} form.
+   */
+  private static class SerializedForm<K extends Comparable<?>, V> implements Serializable {
+
+    private final ImmutableMap<Range<K>, V> mapOfRanges;
+
+    SerializedForm(ImmutableMap<Range<K>, V> mapOfRanges) {
+      this.mapOfRanges = mapOfRanges;
+    }
+
+    Object readResolve() {
+      if (mapOfRanges.isEmpty()) {
+        return of();
+      } else {
+        return createRangeMap();
+      }
+    }
+
+    Object createRangeMap() {
+      Builder<K, V> builder = new Builder<K, V>();
+      for (Entry<Range<K>, V> entry : mapOfRanges.entrySet()) {
+        builder.put(entry.getKey(), entry.getValue());
+      }
+      return builder.build();
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  Object writeReplace() {
+    return new SerializedForm<K, V>(asMapOfRanges());
+  }
+
+  private static final long serialVersionUID = 0;
 }
diff --git a/guava/src/com/google/common/collect/ImmutableRangeSet.java b/guava/src/com/google/common/collect/ImmutableRangeSet.java
index 9e72b97..6345e93 100644
--- a/guava/src/com/google/common/collect/ImmutableRangeSet.java
+++ b/guava/src/com/google/common/collect/ImmutableRangeSet.java
@@ -34,7 +34,8 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 /**
- * An efficient immutable implementation of a {@link RangeSet}.
+ * A {@link RangeSet} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * @author Louis Wasserman
  * @since 14.0
@@ -113,23 +114,27 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
 
   @Override
   public boolean encloses(Range<C> otherRange) {
-    int index = SortedLists.binarySearch(ranges,
-        Range.<C>lowerBoundFn(),
-        otherRange.lowerBound,
-        Ordering.natural(),
-        ANY_PRESENT,
-        NEXT_LOWER);
+    int index =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<C>lowerBoundFn(),
+            otherRange.lowerBound,
+            Ordering.natural(),
+            ANY_PRESENT,
+            NEXT_LOWER);
     return index != -1 && ranges.get(index).encloses(otherRange);
   }
 
   @Override
   public Range<C> rangeContaining(C value) {
-    int index = SortedLists.binarySearch(ranges,
-        Range.<C>lowerBoundFn(),
-        Cut.belowValue(value),
-        Ordering.natural(),
-        ANY_PRESENT,
-        NEXT_LOWER);
+    int index =
+        SortedLists.binarySearch(
+            ranges,
+            Range.<C>lowerBoundFn(),
+            Cut.belowValue(value),
+            Ordering.natural(),
+            ANY_PRESENT,
+            NEXT_LOWER);
     if (index != -1) {
       Range<C> range = ranges.get(index);
       return range.contains(value) ? range : null;
@@ -142,9 +147,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
     if (ranges.isEmpty()) {
       throw new NoSuchElementException();
     }
-    return Range.create(
-        ranges.get(0).lowerBound,
-        ranges.get(ranges.size() - 1).upperBound);
+    return Range.create(ranges.get(0).lowerBound, ranges.get(ranges.size() - 1).upperBound);
   }
 
   @Override
@@ -180,6 +183,15 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
     return new RegularImmutableSortedSet<Range<C>>(ranges, Range.RANGE_LEX_ORDERING);
   }
 
+  @Override
+  public ImmutableSet<Range<C>> asDescendingSetOfRanges() {
+    if (ranges.isEmpty()) {
+      return ImmutableSet.of();
+    }
+    return new RegularImmutableSortedSet<Range<C>>(
+        ranges.reverse(), Range.RANGE_LEX_ORDERING.reverse());
+  }
+
   private transient ImmutableRangeSet<C> complement;
 
   private final class ComplementRanges extends ImmutableList<Range<C>> {
@@ -266,18 +278,26 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
 
     final int fromIndex;
     if (range.hasLowerBound()) {
-      fromIndex = SortedLists.binarySearch(
-          ranges, Range.<C>upperBoundFn(), range.lowerBound, KeyPresentBehavior.FIRST_AFTER,
-          KeyAbsentBehavior.NEXT_HIGHER);
+      fromIndex =
+          SortedLists.binarySearch(
+              ranges,
+              Range.<C>upperBoundFn(),
+              range.lowerBound,
+              KeyPresentBehavior.FIRST_AFTER,
+              KeyAbsentBehavior.NEXT_HIGHER);
     } else {
       fromIndex = 0;
     }
 
     int toIndex;
     if (range.hasUpperBound()) {
-      toIndex = SortedLists.binarySearch(
-          ranges, Range.<C>lowerBoundFn(), range.upperBound, KeyPresentBehavior.FIRST_PRESENT,
-          KeyAbsentBehavior.NEXT_HIGHER);
+      toIndex =
+          SortedLists.binarySearch(
+              ranges,
+              Range.<C>lowerBoundFn(),
+              range.upperBound,
+              KeyPresentBehavior.FIRST_PRESENT,
+              KeyAbsentBehavior.NEXT_HIGHER);
     } else {
       toIndex = ranges.size();
     }
@@ -308,7 +328,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
       };
     }
   }
-  
+
   /**
    * Returns a view of the intersection of this range set with the given range.
    */
@@ -450,9 +470,10 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
       if (!fromInclusive && !toInclusive && Range.compareOrThrow(fromElement, toElement) == 0) {
         return ImmutableSortedSet.of();
       }
-      return subSet(Range.range(
-          fromElement, BoundType.forBoolean(fromInclusive),
-          toElement, BoundType.forBoolean(toInclusive)));
+      return subSet(
+          Range.range(
+              fromElement, BoundType.forBoolean(fromInclusive),
+              toElement, BoundType.forBoolean(toInclusive)));
     }
 
     @Override
@@ -563,7 +584,9 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
         for (Range<C> currentRange : rangeSet.asRanges()) {
           checkArgument(
               !currentRange.isConnected(range) || currentRange.intersection(range).isEmpty(),
-              "Ranges may not overlap, but received %s and %s", currentRange, range);
+              "Ranges may not overlap, but received %s and %s",
+              currentRange,
+              range);
         }
         throw new AssertionError("should have thrown an IAE above");
       }
diff --git a/guava/src/com/google/common/collect/ImmutableSet.java b/guava/src/com/google/common/collect/ImmutableSet.java
index c236182..ea5b691 100644
--- a/guava/src/com/google/common/collect/ImmutableSet.java
+++ b/guava/src/com/google/common/collect/ImmutableSet.java
@@ -28,126 +28,82 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
 import javax.annotation.Nullable;
 
 /**
- * A high-performance, immutable {@code Set} with reliable, user-specified
- * iteration order. Does not permit null elements.
+ * A {@link Set} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Collections#unmodifiableSet}, which is a <i>view</i> of a
- * separate collection that can still change, an instance of this class contains
- * its own private data and will <i>never</i> change. This class is convenient
- * for {@code public static final} sets ("constant sets") and also lets you
- * easily make a "defensive copy" of a set provided to your class by a caller.
- *
- * <p><b>Warning:</b> Like most sets, an {@code ImmutableSet} will not function
- * correctly if an element is modified after being placed in the set. For this
- * reason, and to avoid general confusion, it is strongly recommended to place
- * only immutable objects into this collection.
- *
- * <p>This class has been observed to perform significantly better than {@link
- * HashSet} for objects with very fast {@link Object#hashCode} implementations
- * (as a well-behaved immutable object should). While this class's factory
- * methods create hash-based instances, the {@link ImmutableSortedSet} subclass
- * performs binary searches instead.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
- * outside its package as it has no public or protected constructors. Thus,
- * instances of this type are guaranteed to be immutable.
- *
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
- * immutable collections</a>.
- *
- * @see ImmutableList
- * @see ImmutableMap
- * @author Kevin Bourrillion
- * @author Nick Kralevich
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
-public abstract class ImmutableSet<E> extends ImmutableCollection<E>
-    implements Set<E> {
+public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Set<E> {
   /**
-   * Returns the empty immutable set. This set behaves and performs comparably
-   * to {@link Collections#emptySet}, and is preferable mainly for consistency
-   * and maintainability of your code.
+   * Returns the empty immutable set. Preferred over {@link Collections#emptySet} for code
+   * consistency, and because the return type conveys the immutability guarantee.
    */
-  // Casting to any type is safe because the set will never hold any elements.
-  @SuppressWarnings({"unchecked"})
+  @SuppressWarnings({"unchecked"}) // fully variant implementation (never actually produces any Es)
   public static <E> ImmutableSet<E> of() {
-    return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE;
+    return (ImmutableSet<E>) RegularImmutableSet.EMPTY;
   }
 
   /**
-   * Returns an immutable set containing a single element. This set behaves and
-   * performs comparably to {@link Collections#singleton}, but will not accept
-   * a null element. It is preferable mainly for consistency and
-   * maintainability of your code.
+   * Returns an immutable set containing {@code element}. Preferred over {@link
+   * Collections#singleton} for code consistency, {@code null} rejection, and because the return
+   * type conveys the immutability guarantee.
    */
   public static <E> ImmutableSet<E> of(E element) {
     return new SingletonImmutableSet<E>(element);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
-   *
-   * @throws NullPointerException if any element is null
+   * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+   * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+   * the first are ignored.
    */
   public static <E> ImmutableSet<E> of(E e1, E e2) {
     return construct(2, e1, e2);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
-   *
-   * @throws NullPointerException if any element is null
+   * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+   * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+   * the first are ignored.
    */
   public static <E> ImmutableSet<E> of(E e1, E e2, E e3) {
     return construct(3, e1, e2, e3);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
-   *
-   * @throws NullPointerException if any element is null
+   * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+   * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+   * the first are ignored.
    */
   public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) {
     return construct(4, e1, e2, e3, e4);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
-   *
-   * @throws NullPointerException if any element is null
+   * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+   * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+   * the first are ignored.
    */
   public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) {
     return construct(5, e1, e2, e3, e4, e5);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
+   * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+   * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+   * the first are ignored.
    *
-   * @throws NullPointerException if any element is null
    * @since 3.0 (source-compatible since 2.0)
    */
-  public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6,
-      E... others) {
+  public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
     final int paramCount = 6;
     Object[] elements = new Object[paramCount + others.length];
     elements[0] = e1;
@@ -219,9 +175,10 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
       // when this happens, we have already made a copy
       return construct(uniques, elements);
     } else {
-      Object[] uniqueElements = (uniques < elements.length)
-          ? ObjectArrays.arraysCopyOf(elements, uniques)
-          : elements;
+      Object[] uniqueElements =
+          (uniques < elements.length)
+              ? ObjectArrays.arraysCopyOf(elements, uniques)
+              : elements;
       return new RegularImmutableSet<E>(uniqueElements, hashCode, table, mask);
     }
   }
@@ -233,8 +190,7 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
   private static final double DESIRED_LOAD_FACTOR = 0.7;
 
   // If the set has this many elements, it will "max out" the table size
-  private static final int CUTOFF =
-      (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR);
+  private static final int CUTOFF = (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR);
 
   /**
    * Returns an array size suitable for the backing array of a hash table that
@@ -244,7 +200,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
    *
    * <p>Do not call this method with setSize < 2.
    */
-  @VisibleForTesting static int chooseTableSize(int setSize) {
+  @VisibleForTesting
+  static int chooseTableSize(int setSize) {
     // Correct the size for open addressing to match desired load factor.
     if (setSize < CUTOFF) {
       // Round up to the next highest power of 2.
@@ -261,38 +218,44 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
+   * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+   * each appears first in the source collection.
+   *
+   * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation
+   * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} will copy the data only once.
+   * This reduces the expense of habitually making defensive copies at API boundaries. However, the
+   * the precise conditions for skipping the copy operation are undefined.
    *
    * @throws NullPointerException if any of {@code elements} is null
-   * @since 3.0
+   * @since 7.0 (source-compatible since 2.0)
    */
-  public static <E> ImmutableSet<E> copyOf(E[] elements) {
-    switch (elements.length) {
-      case 0:
-        return of();
-      case 1:
-        return of(elements[0]);
-      default:
-        return construct(elements.length, elements.clone());
+  public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
+    /*
+     * TODO(lowasser): consider checking for ImmutableAsList here
+     * TODO(lowasser): consider checking for Multiset here
+     */
+    if (elements instanceof ImmutableSet && !(elements instanceof ImmutableSortedSet)) {
+      @SuppressWarnings("unchecked") // all supported methods are covariant
+      ImmutableSet<E> set = (ImmutableSet<E>) elements;
+      if (!set.isPartialView()) {
+        return set;
+      }
+    } else if (elements instanceof EnumSet) {
+      return copyOfEnumSet((EnumSet) elements);
     }
+    Object[] array = elements.toArray();
+    return construct(array.length, array);
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored. This method iterates over {@code elements} at most once.
-   *
-   * <p>Note that if {@code s} is a {@code Set<String>}, then {@code
-   * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
-   * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
-   * a {@code ImmutableSet<Set<String>>} containing one element (the given set
-   * itself).
+   * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+   * each appears first in the source iterable. This method iterates over {@code elements} only
+   * once.
    *
-   * <p>Despite the method name, this method attempts to avoid actually copying
-   * the data when it is safe to do so. The exact circumstances under which a
-   * copy will or will not be performed are undocumented and subject to change.
+   * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation
+   * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only
+   * once. This reduces the expense of habitually making defensive copies at API boundaries.
+   * However, the precise conditions for skipping the copy operation are undefined.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
@@ -303,9 +266,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored.
+   * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+   * each appears first in the source iterator.
    *
    * @throws NullPointerException if any of {@code elements} is null
    */
@@ -326,57 +288,25 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
   }
 
   /**
-   * Returns an immutable set containing the given elements, in order. Repeated
-   * occurrences of an element (according to {@link Object#equals}) after the
-   * first are ignored. This method iterates over {@code elements} at most
-   * once.
-   *
-   * <p>Note that if {@code s} is a {@code Set<String>}, then {@code
-   * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
-   * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
-   * a {@code ImmutableSet<Set<String>>} containing one element (the given set
-   * itself).
-   *
-   * <p><b>Note:</b> Despite what the method name suggests, {@code copyOf} will
-   * return constant-space views, rather than linear-space copies, of some
-   * inputs known to be immutable. For some other immutable inputs, such as key
-   * sets of an {@code ImmutableMap}, it still performs a copy in order to avoid
-   * holding references to the values of the map. The heuristics used in this
-   * decision are undocumented and subject to change except that:
-   * <ul>
-   * <li>A full copy will be done of any {@code ImmutableSortedSet}.</li>
-   * <li>{@code ImmutableSet.copyOf()} is idempotent with respect to pointer
-   * equality.</li>
-   * </ul>
-   *
-   * <p>This method is safe to use even when {@code elements} is a synchronized
-   * or concurrent collection that is currently being modified by another
-   * thread.
+   * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+   * each appears first in the source array.
    *
    * @throws NullPointerException if any of {@code elements} is null
-   * @since 7.0 (source-compatible since 2.0)
+   * @since 3.0
    */
-  public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
-    /*
-     * TODO(user): consider checking for ImmutableAsList here
-     * TODO(user): consider checking for Multiset here
-     */
-    if (elements instanceof ImmutableSet
-        && !(elements instanceof ImmutableSortedSet)) {
-      @SuppressWarnings("unchecked") // all supported methods are covariant
-      ImmutableSet<E> set = (ImmutableSet<E>) elements;
-      if (!set.isPartialView()) {
-        return set;
-      }
-    } else if (elements instanceof EnumSet) {
-      return copyOfEnumSet((EnumSet) elements);
+  public static <E> ImmutableSet<E> copyOf(E[] elements) {
+    switch (elements.length) {
+      case 0:
+        return of();
+      case 1:
+        return of(elements[0]);
+      default:
+        return construct(elements.length, elements.clone());
     }
-    Object[] array = elements.toArray();
-    return construct(array.length, array);
   }
 
-  private static <E extends Enum<E>> ImmutableSet<E> copyOfEnumSet(
-      EnumSet<E> enumSet) {
+  @SuppressWarnings("rawtypes") // necessary to compile against Java 8
+  private static ImmutableSet copyOfEnumSet(EnumSet enumSet) {
     return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet));
   }
 
@@ -387,7 +317,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
     return false;
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     } else if (object instanceof ImmutableSet
@@ -399,13 +330,39 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
     return Sets.equalsImpl(this, object);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Sets.hashCodeImpl(this);
   }
 
   // This declaration is needed to make Set.iterator() and
   // ImmutableCollection.iterator() consistent.
-  @Override public abstract UnmodifiableIterator<E> iterator();
+  @Override
+  public abstract UnmodifiableIterator<E> iterator();
+
+  abstract static class Indexed<E> extends ImmutableSet<E> {
+    abstract E get(int index);
+
+    @Override
+    public UnmodifiableIterator<E> iterator() {
+      return asList().iterator();
+    }
+
+    @Override
+    ImmutableList<E> createAsList() {
+      return new ImmutableAsList<E>() {
+        @Override
+        public E get(int index) {
+          return Indexed.this.get(index);
+        }
+
+        @Override
+        Indexed<E> delegateCollection() {
+          return Indexed.this;
+        }
+      };
+    }
+  }
 
   /*
    * This class is used to serialize all ImmutableSet instances, except for
@@ -416,16 +373,20 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
    */
   private static class SerializedForm implements Serializable {
     final Object[] elements;
+
     SerializedForm(Object[] elements) {
       this.elements = elements;
     }
+
     Object readResolve() {
       return copyOf(elements);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm(toArray());
   }
 
@@ -438,20 +399,18 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
   }
 
   /**
-   * A builder for creating immutable set instances, especially {@code public
-   * static final} sets ("constant sets"). Example: <pre>   {@code
+   * A builder for creating {@code ImmutableSet} instances. Example: <pre>   {@code
    *
-   *   public static final ImmutableSet<Color> GOOGLE_COLORS =
-   *       new ImmutableSet.Builder<Color>()
+   *   static final ImmutableSet<Color> GOOGLE_COLORS =
+   *       ImmutableSet.<Color>builder()
    *           .addAll(WEBSAFE_COLORS)
    *           .add(new Color(0, 191, 255))
    *           .build();}</pre>
    *
-   * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
-   * times to build multiple sets in series. Each set is a superset of the set
-   * created before it.
+   * <p>Building does not change the state of the builder, so it is still possible to add more
+   * elements and to build again.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
 
@@ -476,7 +435,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code element} is null
      */
-    @Override public Builder<E> add(E element) {
+    @Override
+    public Builder<E> add(E element) {
       super.add(element);
       return this;
     }
@@ -490,7 +450,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> add(E... elements) {
+    @Override
+    public Builder<E> add(E... elements) {
       super.add(elements);
       return this;
     }
@@ -504,7 +465,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterable<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -518,7 +480,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
      * @throws NullPointerException if {@code elements} is null or contains a
      *     null element
      */
-    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterator<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -527,7 +490,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
      * Returns a newly-created {@code ImmutableSet} based on the contents of
      * the {@code Builder}.
      */
-    @Override public ImmutableSet<E> build() {
+    @Override
+    public ImmutableSet<E> build() {
       ImmutableSet<E> result = construct(size, contents);
       // construct has the side effect of deduping contents, so we update size
       // accordingly.
diff --git a/guava/src/com/google/common/collect/ImmutableSetMultimap.java b/guava/src/com/google/common/collect/ImmutableSetMultimap.java
index ce24af2..5cad010 100644
--- a/guava/src/com/google/common/collect/ImmutableSetMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableSetMultimap.java
@@ -17,11 +17,12 @@
 package com.google.common.collect;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.Arrays.asList;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.MoreObjects;
+import com.google.j2objc.annotations.Weak;
 
 import java.io.IOException;
 import java.io.InvalidObjectException;
@@ -29,9 +30,7 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -39,31 +38,18 @@ import java.util.Map.Entry;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link SetMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableSetMultimap(SetMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableSetMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableSetMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link SetMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Mike Ward
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
-public class ImmutableSetMultimap<K, V>
-    extends ImmutableMultimap<K, V>
+public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V>
     implements SetMultimap<K, V> {
 
   /** Returns the empty multimap. */
@@ -99,8 +85,7 @@ public class ImmutableSetMultimap<K, V>
    * Repeated occurrences of an entry (according to {@link Object#equals}) after
    * the first are ignored.
    */
-  public static <K, V> ImmutableSetMultimap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
+  public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
     ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
     builder.put(k1, v1);
     builder.put(k2, v2);
@@ -149,20 +134,6 @@ public class ImmutableSetMultimap<K, V>
   }
 
   /**
-   * Multimap for {@link ImmutableSetMultimap.Builder} that maintains key
-   * and value orderings and performs better than {@link LinkedHashMultimap}.
-   */
-  private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
-    BuilderMultimap() {
-      super(new LinkedHashMap<K, Collection<V>>());
-    }
-    @Override Collection<V> createCollection() {
-      return Sets.newLinkedHashSet();
-    }
-    private static final long serialVersionUID = 0;
-  }
-
-  /**
    * A builder for creating immutable {@code SetMultimap} instances, especially
    * {@code public static final} multimaps ("constant multimaps"). Example:
    * <pre>   {@code
@@ -178,23 +149,23 @@ public class ImmutableSetMultimap<K, V>
    * times to build multiple multimaps in series. Each multimap contains the
    * key-value mappings in the previously created multimaps.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
-  public static final class Builder<K, V>
-      extends ImmutableMultimap.Builder<K, V> {
+  public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
     /**
      * Creates a new builder. The returned builder is equivalent to the builder
      * generated by {@link ImmutableSetMultimap#builder}.
      */
     public Builder() {
-      builderMultimap = new BuilderMultimap<K, V>();
+      super(MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build());
     }
 
     /**
      * Adds a key-value mapping to the built multimap if it is not already
      * present.
      */
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       builderMultimap.put(checkNotNull(key), checkNotNull(value));
       return this;
     }
@@ -204,13 +175,26 @@ public class ImmutableSetMultimap<K, V>
      *
      * @since 11.0
      */
-    @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
-      builderMultimap.put(
-          checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+      builderMultimap.put(checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+      return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+    @Override
+    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
       Collection<V> collection = builderMultimap.get(checkNotNull(key));
       for (V value : values) {
         collection.add(checkNotNull(value));
@@ -218,14 +202,15 @@ public class ImmutableSetMultimap<K, V>
       return this;
     }
 
-    @Override public Builder<K, V> putAll(K key, V... values) {
+    @Override
+    public Builder<K, V> putAll(K key, V... values) {
       return putAll(key, Arrays.asList(values));
     }
 
-    @Override public Builder<K, V> putAll(
-        Multimap<? extends K, ? extends V> multimap) {
-      for (Entry<? extends K, ? extends Collection<? extends V>> entry
-          : multimap.asMap().entrySet()) {
+    @Override
+    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
+      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+          multimap.asMap().entrySet()) {
         putAll(entry.getKey(), entry.getValue());
       }
       return this;
@@ -263,14 +248,15 @@ public class ImmutableSetMultimap<K, V>
     /**
      * Returns a newly-created immutable set multimap.
      */
-    @Override public ImmutableSetMultimap<K, V> build() {
+    @Override
+    public ImmutableSetMultimap<K, V> build() {
       if (keyComparator != null) {
-        Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
-        List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
-            builderMultimap.asMap().entrySet());
-        Collections.sort(
-            entries,
-            Ordering.from(keyComparator).<K>onKeys());
+        Multimap<K, V> sortedCopy =
+            MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build();
+        List<Map.Entry<K, Collection<V>>> entries =
+            Ordering.from(keyComparator)
+                .<K>onKeys()
+                .immutableSortedCopy(builderMultimap.asMap().entrySet());
         for (Map.Entry<K, Collection<V>> entry : entries) {
           sortedCopy.putAll(entry.getKey(), entry.getValue());
         }
@@ -300,8 +286,7 @@ public class ImmutableSetMultimap<K, V>
   }
 
   private static <K, V> ImmutableSetMultimap<K, V> copyOf(
-      Multimap<? extends K, ? extends V> multimap,
-      Comparator<? super V> valueComparator) {
+      Multimap<? extends K, ? extends V> multimap, Comparator<? super V> valueComparator) {
     checkNotNull(multimap); // eager for GWT
     if (multimap.isEmpty() && valueComparator == null) {
       return of();
@@ -309,18 +294,18 @@ public class ImmutableSetMultimap<K, V>
 
     if (multimap instanceof ImmutableSetMultimap) {
       @SuppressWarnings("unchecked") // safe since multimap is not writable
-      ImmutableSetMultimap<K, V> kvMultimap
-          = (ImmutableSetMultimap<K, V>) multimap;
+      ImmutableSetMultimap<K, V> kvMultimap = (ImmutableSetMultimap<K, V>) multimap;
       if (!kvMultimap.isPartialView()) {
         return kvMultimap;
       }
     }
 
-    ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
+    ImmutableMap.Builder<K, ImmutableSet<V>> builder =
+        new ImmutableMap.Builder<K, ImmutableSet<V>>(multimap.asMap().size());
     int size = 0;
 
-    for (Entry<? extends K, ? extends Collection<? extends V>> entry
-        : multimap.asMap().entrySet()) {
+    for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+        multimap.asMap().entrySet()) {
       K key = entry.getKey();
       Collection<? extends V> values = entry.getValue();
       ImmutableSet<V> set = valueSet(valueComparator, values);
@@ -330,8 +315,23 @@ public class ImmutableSetMultimap<K, V>
       }
     }
 
-    return new ImmutableSetMultimap<K, V>(
-        builder.build(), size, valueComparator);
+    return new ImmutableSetMultimap<K, V>(builder.build(), size, valueComparator);
+  }
+
+  /**
+   * Returns an immutable multimap containing the specified entries.  The
+   * returned multimap iterates over keys in the order they were first
+   * encountered in the input, and the values for each key are iterated in the
+   * order they were encountered.  If two values for the same key are
+   * {@linkplain Object#equals equal}, the first value encountered is used.
+   *
+   * @throws NullPointerException if any key, value, or entry is null
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableSetMultimap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    return new Builder<K, V>().putAll(entries).build();
   }
 
   /**
@@ -340,7 +340,9 @@ public class ImmutableSetMultimap<K, V>
    */
   private final transient ImmutableSet<V> emptySet;
 
-  ImmutableSetMultimap(ImmutableMap<K, ImmutableSet<V>> map, int size,
+  ImmutableSetMultimap(
+      ImmutableMap<K, ImmutableSet<V>> map,
+      int size,
       @Nullable Comparator<? super V> valueComparator) {
     super(map, size);
     this.emptySet = emptySet(valueComparator);
@@ -354,7 +356,8 @@ public class ImmutableSetMultimap<K, V>
    * The values are in the same order as the parameters used to build this
    * multimap.
    */
-  @Override public ImmutableSet<V> get(@Nullable K key) {
+  @Override
+  public ImmutableSet<V> get(@Nullable K key) {
     // This cast is safe as its type is known in constructor.
     ImmutableSet<V> set = (ImmutableSet<V>) map.get(key);
     return MoreObjects.firstNonNull(set, emptySet);
@@ -393,7 +396,9 @@ public class ImmutableSetMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableSet<V> removeAll(Object key) {
+  @Deprecated
+  @Override
+  public ImmutableSet<V> removeAll(Object key) {
     throw new UnsupportedOperationException();
   }
 
@@ -403,8 +408,9 @@ public class ImmutableSetMultimap<K, V>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public ImmutableSet<V> replaceValues(
-      K key, Iterable<? extends V> values) {
+  @Deprecated
+  @Override
+  public ImmutableSet<V> replaceValues(K key, Iterable<? extends V> values) {
     throw new UnsupportedOperationException();
   }
 
@@ -415,16 +421,17 @@ public class ImmutableSetMultimap<K, V>
    * Its iterator traverses the values for the first key, the values for the
    * second key, and so on.
    */
-  @Override public ImmutableSet<Entry<K, V>> entries() {
+  @Override
+  public ImmutableSet<Entry<K, V>> entries() {
     ImmutableSet<Entry<K, V>> result = entries;
-    return (result == null)
+    return result == null
         ? (entries = new EntrySet<K, V>(this))
         : result;
   }
-  
+
   private static final class EntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
-    private transient final ImmutableSetMultimap<K, V> multimap;
-    
+    @Weak private final transient ImmutableSetMultimap<K, V> multimap;
+
     EntrySet(ImmutableSetMultimap<K, V> multimap) {
       this.multimap = multimap;
     }
@@ -451,24 +458,29 @@ public class ImmutableSetMultimap<K, V>
     @Override
     boolean isPartialView() {
       return false;
-    }    
+    }
   }
 
   private static <V> ImmutableSet<V> valueSet(
-      @Nullable Comparator<? super V> valueComparator,
-      Collection<? extends V> values) {
+      @Nullable Comparator<? super V> valueComparator, Collection<? extends V> values) {
     return (valueComparator == null)
         ? ImmutableSet.copyOf(values)
         : ImmutableSortedSet.copyOf(valueComparator, values);
   }
 
-  private static <V> ImmutableSet<V> emptySet(
-      @Nullable Comparator<? super V> valueComparator) {
+  private static <V> ImmutableSet<V> emptySet(@Nullable Comparator<? super V> valueComparator) {
     return (valueComparator == null)
         ? ImmutableSet.<V>of()
         : ImmutableSortedSet.<V>emptySet(valueComparator);
   }
 
+  private static <V> ImmutableSet.Builder<V> valuesBuilder(
+      @Nullable Comparator<? super V> valueComparator) {
+    return (valueComparator == null)
+        ? new ImmutableSet.Builder<V>()
+        : new ImmutableSortedSet.Builder<V>(valueComparator);
+  }
+
   /**
    * @serialData number of distinct keys, and then for each distinct key: the
    *     key, the number of values for that key, and the key's values
@@ -480,7 +492,8 @@ public class ImmutableSetMultimap<K, V>
     Serialization.writeMultimap(this, stream);
   }
 
-  @Nullable Comparator<? super V> valueComparator() {
+  @Nullable
+  Comparator<? super V> valueComparator() {
     return emptySet instanceof ImmutableSortedSet
         ? ((ImmutableSortedSet<V>) emptySet).comparator()
         : null;
@@ -489,17 +502,14 @@ public class ImmutableSetMultimap<K, V>
   @GwtIncompatible("java.io.ObjectInputStream")
   // Serialization type safety is at the caller's mercy.
   @SuppressWarnings("unchecked")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
-    Comparator<Object> valueComparator =
-        (Comparator<Object>) stream.readObject();
+    Comparator<Object> valueComparator = (Comparator<Object>) stream.readObject();
     int keyCount = stream.readInt();
     if (keyCount < 0) {
       throw new InvalidObjectException("Invalid key count " + keyCount);
     }
-    ImmutableMap.Builder<Object, ImmutableSet<Object>> builder
-        = ImmutableMap.builder();
+    ImmutableMap.Builder<Object, ImmutableSet<Object>> builder = ImmutableMap.builder();
     int tmpSize = 0;
 
     for (int i = 0; i < keyCount; i++) {
@@ -509,14 +519,13 @@ public class ImmutableSetMultimap<K, V>
         throw new InvalidObjectException("Invalid value count " + valueCount);
       }
 
-      Object[] array = new Object[valueCount];
+      ImmutableSet.Builder<Object> valuesBuilder = valuesBuilder(valueComparator);
       for (int j = 0; j < valueCount; j++) {
-        array[j] = stream.readObject();
+        valuesBuilder.add(stream.readObject());
       }
-      ImmutableSet<Object> valueSet = valueSet(valueComparator, asList(array));
-      if (valueSet.size() != array.length) {
-        throw new InvalidObjectException(
-            "Duplicate key-value pairs exist for key " + key);
+      ImmutableSet<Object> valueSet = valuesBuilder.build();
+      if (valueSet.size() != valueCount) {
+        throw new InvalidObjectException("Duplicate key-value pairs exist for key " + key);
       }
       builder.put(key, valueSet);
       tmpSize += valueCount;
@@ -526,14 +535,12 @@ public class ImmutableSetMultimap<K, V>
     try {
       tmpMap = builder.build();
     } catch (IllegalArgumentException e) {
-      throw (InvalidObjectException)
-          new InvalidObjectException(e.getMessage()).initCause(e);
+      throw (InvalidObjectException) new InvalidObjectException(e.getMessage()).initCause(e);
     }
 
     FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap);
     FieldSettersHolder.SIZE_FIELD_SETTER.set(this, tmpSize);
-    FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(
-        this, emptySet(valueComparator));
+    FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(this, emptySet(valueComparator));
   }
 
   @GwtIncompatible("not needed in emulated source.")
diff --git a/guava/src/com/google/common/collect/ImmutableSortedAsList.java b/guava/src/com/google/common/collect/ImmutableSortedAsList.java
index 98aab41..43aa976 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedAsList.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedAsList.java
@@ -31,8 +31,7 @@ import javax.annotation.Nullable;
 @SuppressWarnings("serial")
 final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
     implements SortedIterable<E> {
-  ImmutableSortedAsList(
-      ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
+  ImmutableSortedAsList(ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
     super(backingSet, backingList);
   }
 
@@ -41,7 +40,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
     return (ImmutableSortedSet<E>) super.delegateCollection();
   }
 
-  @Override public Comparator<? super E> comparator() {
+  @Override
+  public Comparator<? super E> comparator() {
     return delegateCollection().comparator();
   }
 
@@ -49,7 +49,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
 
   @GwtIncompatible("ImmutableSortedSet.indexOf")
   // TODO(cpovirk): consider manual binary search under GWT to preserve O(log N) lookup
-  @Override public int indexOf(@Nullable Object target) {
+  @Override
+  public int indexOf(@Nullable Object target) {
     int index = delegateCollection().indexOf(target);
 
     // TODO(kevinb): reconsider if it's really worth making feeble attempts at
@@ -61,7 +62,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
   }
 
   @GwtIncompatible("ImmutableSortedSet.indexOf")
-  @Override public int lastIndexOf(@Nullable Object target) {
+  @Override
+  public int lastIndexOf(@Nullable Object target) {
     return indexOf(target);
   }
 
@@ -79,8 +81,7 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
    */
   @Override
   ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
-    return new RegularImmutableSortedSet<E>(
-        super.subListUnchecked(fromIndex, toIndex), comparator())
-        .asList();
+    ImmutableList<E> parentSubList = super.subListUnchecked(fromIndex, toIndex);
+    return new RegularImmutableSortedSet<E>(parentSubList, comparator()).asList();
   }
 }
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMap.java b/guava/src/com/google/common/collect/ImmutableSortedMap.java
index e796a5d..ed07437 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMap.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMap.java
@@ -18,12 +18,15 @@ 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.checkEntryNotNull;
 import static com.google.common.collect.Maps.keyOrNull;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Map;
 import java.util.NavigableMap;
@@ -33,31 +36,27 @@ import java.util.TreeMap;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link SortedMap}. Does not permit null keys or values.
+ * A {@link NavigableMap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Collections#unmodifiableSortedMap}, which is a <i>view</i>
- * of a separate map which can still change, an instance of {@code
- * ImmutableSortedMap} contains its own data and will <i>never</i> change.
- * {@code ImmutableSortedMap} is convenient for {@code public static final} maps
- * ("constant maps") and also lets you easily make a "defensive copy" of a map
- * provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting map will
+ * not correctly obey its specification.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library; implements {@code
- *        NavigableMap} since 12.0)
+ * @since 2.0 (implements {@code NavigableMap} since 12.0)
  */
 @GwtCompatible(serializable = true, emulated = true)
-public abstract class ImmutableSortedMap<K, V>
-    extends ImmutableSortedMapFauxverideShim<K, V> implements NavigableMap<K, V> {
+public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxverideShim<K, V>
+    implements NavigableMap<K, V> {
+
   /*
    * TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
    * uses less memory than TreeMap; then say so in the class Javadoc.
@@ -65,45 +64,15 @@ public abstract class ImmutableSortedMap<K, V>
   private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
 
   private static final ImmutableSortedMap<Comparable, Object> NATURAL_EMPTY_MAP =
-      new EmptyImmutableSortedMap<Comparable, Object>(NATURAL_ORDER);
+      new ImmutableSortedMap<Comparable, Object>(
+          ImmutableSortedSet.emptySet(Ordering.natural()), ImmutableList.<Object>of());
 
   static <K, V> ImmutableSortedMap<K, V> emptyMap(Comparator<? super K> comparator) {
     if (Ordering.natural().equals(comparator)) {
       return of();
     } else {
-      return new EmptyImmutableSortedMap<K, V>(comparator);
-    }
-  }
-
-  static <K, V> ImmutableSortedMap<K, V> fromSortedEntries(
-      Comparator<? super K> comparator,
-      int size,
-      Entry<K, V>[] entries) {
-    if (size == 0) {
-      return emptyMap(comparator);
-    }
-
-    ImmutableList.Builder<K> keyBuilder = ImmutableList.builder();
-    ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();
-    for (int i = 0; i < size; i++) {
-      Entry<K, V> entry = entries[i];
-      keyBuilder.add(entry.getKey());
-      valueBuilder.add(entry.getValue());
-    }
-
-    return new RegularImmutableSortedMap<K, V>(
-        new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),
-        valueBuilder.build());
-  }
-
-  static <K, V> ImmutableSortedMap<K, V> from(
-      ImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
-    if (keySet.isEmpty()) {
-      return emptyMap(keySet.comparator());
-    } else {
-      return new RegularImmutableSortedMap<K, V>(
-          (RegularImmutableSortedSet<K>) keySet,
-          valueList);
+      return new ImmutableSortedMap<K, V>(
+          ImmutableSortedSet.emptySet(comparator), ImmutableList.<V>of());
     }
   }
 
@@ -120,9 +89,22 @@ public abstract class ImmutableSortedMap<K, V>
   /**
    * Returns an immutable map containing a single entry.
    */
-  public static <K extends Comparable<? super K>, V>
-      ImmutableSortedMap<K, V> of(K k1, V v1) {
-    return from(ImmutableSortedSet.of(k1), ImmutableList.of(v1));
+  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
+    return of(Ordering.natural(), k1, v1);
+  }
+
+  /**
+   * Returns an immutable map containing a single entry.
+   */
+  private static <K, V> ImmutableSortedMap<K, V> of(Comparator<? super K> comparator, K k1, V v1) {
+    return new ImmutableSortedMap<K, V>(
+        new RegularImmutableSortedSet<K>(ImmutableList.of(k1), checkNotNull(comparator)),
+        ImmutableList.of(v1));
+  }
+
+  private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> ofEntries(
+      ImmutableMapEntry<K, V>... entries) {
+    return fromEntries(Ordering.natural(), false, entries, entries.length);
   }
 
   /**
@@ -133,9 +115,9 @@ public abstract class ImmutableSortedMap<K, V>
    *     their natural ordering
    */
   @SuppressWarnings("unchecked")
-  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
-      of(K k1, V v1, K k2, V v2) {
-    return fromEntries(Ordering.natural(), false, 2, entryOf(k1, v1), entryOf(k2, v2));
+  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+      K k1, V v1, K k2, V v2) {
+    return ofEntries(entryOf(k1, v1), entryOf(k2, v2));
   }
 
   /**
@@ -146,10 +128,9 @@ public abstract class ImmutableSortedMap<K, V>
    *     their natural ordering
    */
   @SuppressWarnings("unchecked")
-  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
-      of(K k1, V v1, K k2, V v2, K k3, V v3) {
-    return fromEntries(Ordering.natural(), false, 3, entryOf(k1, v1), entryOf(k2, v2), 
-        entryOf(k3, v3));
+  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+      K k1, V v1, K k2, V v2, K k3, V v3) {
+    return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
   }
 
   /**
@@ -160,10 +141,9 @@ public abstract class ImmutableSortedMap<K, V>
    *     their natural ordering
    */
   @SuppressWarnings("unchecked")
-  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
-      of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
-    return fromEntries(Ordering.natural(), false, 4, entryOf(k1, v1), entryOf(k2, v2), 
-        entryOf(k3, v3), entryOf(k4, v4));
+  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+    return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
   }
 
   /**
@@ -174,10 +154,10 @@ public abstract class ImmutableSortedMap<K, V>
    *     their natural ordering
    */
   @SuppressWarnings("unchecked")
-  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
-      of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
-    return fromEntries(Ordering.natural(), false, 5, entryOf(k1, v1), entryOf(k2, v2), 
-        entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
+  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
+    return ofEntries(
+        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
   }
 
   /**
@@ -197,12 +177,11 @@ public abstract class ImmutableSortedMap<K, V>
    * @throws IllegalArgumentException if any two keys are equal according to
    *         their natural ordering
    */
-  public static <K, V> ImmutableSortedMap<K, V> copyOf(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
     // Hack around K not being a subtype of Comparable.
     // Unsafe, see ImmutableSortedSetFauxverideShim.
     @SuppressWarnings("unchecked")
-    Ordering<K> naturalOrder = (Ordering<K>) Ordering.<Comparable>natural();
+    Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
     return copyOfInternal(map, naturalOrder);
   }
 
@@ -224,6 +203,44 @@ public abstract class ImmutableSortedMap<K, V>
   }
 
   /**
+   * Returns an immutable map containing the given entries, with keys sorted
+   * by the provided comparator.
+   *
+   * <p>This method is not type-safe, as it may be called on a map with keys
+   * that are not mutually comparable.
+   *
+   * @throws NullPointerException if any key or value in {@code map} is null
+   * @throws IllegalArgumentException if any two keys are equal according to the
+   *         comparator
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableSortedMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+    // Hack around K not being a subtype of Comparable.
+    // Unsafe, see ImmutableSortedSetFauxverideShim.
+    @SuppressWarnings("unchecked")
+    Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
+    return copyOf(entries, naturalOrder);
+  }
+
+  /**
+   * Returns an immutable map containing the given entries, with keys sorted
+   * by the provided comparator.
+   *
+   * @throws NullPointerException if any key or value in {@code map} is null
+   * @throws IllegalArgumentException if any two keys are equal according to the
+   *         comparator
+   * @since 19.0
+   */
+  @Beta
+  public static <K, V> ImmutableSortedMap<K, V> copyOf(
+      Iterable<? extends Entry<? extends K, ? extends V>> entries,
+      Comparator<? super K> comparator) {
+    return fromEntries(checkNotNull(comparator), false, entries);
+  }
+
+  /**
    * Returns an immutable map containing the same entries as the provided sorted
    * map, with the same ordering.
    *
@@ -234,15 +251,23 @@ public abstract class ImmutableSortedMap<K, V>
    * @throws NullPointerException if any key or value in {@code map} is null
    */
   @SuppressWarnings("unchecked")
-  public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
-      SortedMap<K, ? extends V> map) {
+  public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map) {
     Comparator<? super K> comparator = map.comparator();
     if (comparator == null) {
       // If map has a null comparator, the keys should have a natural ordering,
       // even though K doesn't explicitly implement Comparable.
       comparator = (Comparator<? super K>) NATURAL_ORDER;
     }
-    return copyOfInternal(map, comparator);
+    if (map instanceof ImmutableSortedMap) {
+      // TODO(kevinb): Prove that this cast is safe, even though
+      // Collections.unmodifiableSortedMap requires the same key type.
+      @SuppressWarnings("unchecked")
+      ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
+      if (!kvMap.isPartialView()) {
+        return kvMap;
+      }
+    }
+    return fromEntries(comparator, true, map.entrySet());
   }
 
   private static <K, V> ImmutableSortedMap<K, V> copyOfInternal(
@@ -251,9 +276,10 @@ public abstract class ImmutableSortedMap<K, V>
     if (map instanceof SortedMap) {
       SortedMap<?, ?> sortedMap = (SortedMap<?, ?>) map;
       Comparator<?> comparator2 = sortedMap.comparator();
-      sameComparator = (comparator2 == null)
-          ? comparator == NATURAL_ORDER
-          : comparator.equals(comparator2);
+      sameComparator =
+          (comparator2 == null)
+              ? comparator == NATURAL_ORDER
+              : comparator.equals(comparator2);
     }
 
     if (sameComparator && (map instanceof ImmutableSortedMap)) {
@@ -265,40 +291,68 @@ public abstract class ImmutableSortedMap<K, V>
         return kvMap;
       }
     }
+    return fromEntries(comparator, sameComparator, map.entrySet());
+  }
 
+  /**
+   * Accepts a collection of possibly-null entries.  If {@code sameComparator}, then it is assumed
+   * that they do not need to be sorted or checked for dupes.
+   */
+  private static <K, V> ImmutableSortedMap<K, V> fromEntries(
+      Comparator<? super K> comparator,
+      boolean sameComparator,
+      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
     // "adding" type params to an array of a raw type should be safe as
     // long as no one can ever cast that same array instance back to a
     // raw type.
     @SuppressWarnings("unchecked")
-    Entry<K, V>[] entries = map.entrySet().toArray(new Entry[0]);
-
-    return fromEntries(comparator, sameComparator, entries.length, entries);
-  }
-  
-  static <K, V> ImmutableSortedMap<K, V> fromEntries(
-      Comparator<? super K> comparator, boolean sameComparator, int size, Entry<K, V>... entries) {
-    for (int i = 0; i < size; i++) {
-      Entry<K, V> entry = entries[i];
-      entries[i] = entryOf(entry.getKey(), entry.getValue());
-    }
-    if (!sameComparator) {
-      sortEntries(comparator, size, entries);
-      validateEntries(size, entries, comparator);
-    }
-
-    return fromSortedEntries(comparator, size, entries);
+    Entry<K, V>[] entryArray = (Entry[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+    return fromEntries(comparator, sameComparator, entryArray, entryArray.length);
   }
 
-  private static <K, V> void sortEntries(
-      final Comparator<? super K> comparator, int size, Entry<K, V>[] entries) {
-    Arrays.sort(entries, 0, size, Ordering.from(comparator).<K>onKeys());
-  }
-
-  private static <K, V> void validateEntries(int size, Entry<K, V>[] entries,
-      Comparator<? super K> comparator) {
-    for (int i = 1; i < size; i++) {
-      checkNoConflict(comparator.compare(entries[i - 1].getKey(), entries[i].getKey()) != 0, "key",
-          entries[i - 1], entries[i]);
+  private static <K, V> ImmutableSortedMap<K, V> fromEntries(
+      Comparator<? super K> comparator,
+      boolean sameComparator,
+      Entry<K, V>[] entryArray,
+      int size) {
+    switch (size) {
+      case 0:
+        return emptyMap(comparator);
+      case 1:
+        return ImmutableSortedMap.<K, V>of(
+            comparator, entryArray[0].getKey(), entryArray[0].getValue());
+      default:
+        Object[] keys = new Object[size];
+        Object[] values = new Object[size];
+        if (sameComparator) {
+          // Need to check for nulls, but don't need to sort or validate.
+          for (int i = 0; i < size; i++) {
+            Object key = entryArray[i].getKey();
+            Object value = entryArray[i].getValue();
+            checkEntryNotNull(key, value);
+            keys[i] = key;
+            values[i] = value;
+          }
+        } else {
+          // Need to sort and check for nulls and dupes.
+          Arrays.sort(entryArray, 0, size, Ordering.from(comparator).<K>onKeys());
+          K prevKey = entryArray[0].getKey();
+          keys[0] = prevKey;
+          values[0] = entryArray[0].getValue();
+          for (int i = 1; i < size; i++) {
+            K key = entryArray[i].getKey();
+            V value = entryArray[i].getValue();
+            checkEntryNotNull(key, value);
+            keys[i] = key;
+            values[i] = value;
+            checkNoConflict(
+                comparator.compare(prevKey, key) != 0, "key", entryArray[i - 1], entryArray[i]);
+            prevKey = key;
+          }
+        }
+        return new ImmutableSortedMap<K, V>(
+            new RegularImmutableSortedSet<K>(new RegularImmutableList<K>(keys), comparator),
+            new RegularImmutableList<V>(values));
     }
   }
 
@@ -349,7 +403,7 @@ public abstract class ImmutableSortedMap<K, V>
    * multiple times to build multiple maps in series. Each map is a superset of
    * the maps created before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static class Builder<K, V> extends ImmutableMap.Builder<K, V> {
     private final Comparator<? super K> comparator;
@@ -368,7 +422,8 @@ public abstract class ImmutableSortedMap<K, V>
      * keys, according to the comparator (which might be the keys' natural
      * order), are not allowed, and will cause {@link #build} to fail.
      */
-    @Override public Builder<K, V> put(K key, V value) {
+    @Override
+    public Builder<K, V> put(K key, V value) {
       super.put(key, value);
       return this;
     }
@@ -381,7 +436,8 @@ public abstract class ImmutableSortedMap<K, V>
      *
      * @since 11.0
      */
-    @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+    @Override
+    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
       super.put(entry);
       return this;
     }
@@ -393,60 +449,149 @@ public abstract class ImmutableSortedMap<K, V>
      *
      * @throws NullPointerException if any key or value in {@code map} is null
      */
-    @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
+    @Override
+    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
       super.putAll(map);
       return this;
     }
 
     /**
+     * Adds all the given entries to the built map.  Duplicate keys, according
+     * to the comparator (which might be the keys' natural order), are not
+     * allowed, and will cause {@link #build} to fail.
+     *
+     * @throws NullPointerException if any key, value, or entry is null
+     * @since 19.0
+     */
+    @Beta
+    @Override
+    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+      super.putAll(entries);
+      return this;
+    }
+
+    /**
+     * Throws an {@code UnsupportedOperationException}.
+     *
+     * @since 19.0
+     * @deprecated Unsupported by ImmutableSortedMap.Builder.
+     */
+    @Beta
+    @Override
+    @Deprecated
+    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+      throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
+    }
+
+    /**
      * Returns a newly-created immutable sorted map.
      *
      * @throws IllegalArgumentException if any two keys are equal according to
      *     the comparator (which might be the keys' natural order)
      */
-    @Override public ImmutableSortedMap<K, V> build() {
-      return fromEntries(comparator, false, size, entries);
+    @Override
+    public ImmutableSortedMap<K, V> build() {
+      switch (size) {
+        case 0:
+          return emptyMap(comparator);
+        case 1:
+          return of(comparator, entries[0].getKey(), entries[0].getValue());
+        default:
+          return fromEntries(comparator, false, entries, size);
+      }
     }
   }
 
-  ImmutableSortedMap() {
+  private final transient RegularImmutableSortedSet<K> keySet;
+  private final transient ImmutableList<V> valueList;
+  private transient ImmutableSortedMap<K, V> descendingMap;
+
+  ImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
+    this(keySet, valueList, null);
   }
 
-  ImmutableSortedMap(ImmutableSortedMap<K, V> descendingMap) {
+  ImmutableSortedMap(
+      RegularImmutableSortedSet<K> keySet,
+      ImmutableList<V> valueList,
+      ImmutableSortedMap<K, V> descendingMap) {
+    this.keySet = keySet;
+    this.valueList = valueList;
     this.descendingMap = descendingMap;
   }
 
   @Override
   public int size() {
-    return values().size();
+    return valueList.size();
   }
 
-  @Override public boolean containsValue(@Nullable Object value) {
-    return values().contains(value);
+  @Override
+  public V get(@Nullable Object key) {
+    int index = keySet.indexOf(key);
+    return (index == -1) ? null : valueList.get(index);
   }
 
-  @Override boolean isPartialView() {
-    return keySet().isPartialView() || values().isPartialView();
+  @Override
+  boolean isPartialView() {
+    return keySet.isPartialView() || valueList.isPartialView();
   }
 
   /**
    * Returns an immutable set of the mappings in this map, sorted by the key
    * ordering.
    */
-  @Override public ImmutableSet<Entry<K, V>> entrySet() {
+  @Override
+  public ImmutableSet<Entry<K, V>> entrySet() {
     return super.entrySet();
   }
 
+  @Override
+  ImmutableSet<Entry<K, V>> createEntrySet() {
+    @WeakOuter
+    class EntrySet extends ImmutableMapEntrySet<K, V> {
+      @Override
+      public UnmodifiableIterator<Entry<K, V>> iterator() {
+        return asList().iterator();
+      }
+
+      @Override
+      ImmutableList<Entry<K, V>> createAsList() {
+        return new ImmutableAsList<Entry<K, V>>() {
+          @Override
+          public Entry<K, V> get(int index) {
+            return Maps.immutableEntry(keySet.asList().get(index), valueList.get(index));
+          }
+
+          @Override
+          ImmutableCollection<Entry<K, V>> delegateCollection() {
+            return EntrySet.this;
+          }
+        };
+      }
+
+      @Override
+      ImmutableMap<K, V> map() {
+        return ImmutableSortedMap.this;
+      }
+    }
+    return isEmpty() ? ImmutableSet.<Entry<K, V>>of() : new EntrySet();
+  }
+
   /**
    * Returns an immutable sorted set of the keys in this map.
    */
-  @Override public abstract ImmutableSortedSet<K> keySet();
+  @Override
+  public ImmutableSortedSet<K> keySet() {
+    return keySet;
+  }
 
   /**
    * Returns an immutable collection of the values in this map, sorted by the
    * ordering of the corresponding keys.
    */
-  @Override public abstract ImmutableCollection<V> values();
+  @Override
+  public ImmutableCollection<V> values() {
+    return valueList;
+  }
 
   /**
    * Returns the comparator that orders the keys, which is
@@ -469,6 +614,17 @@ public abstract class ImmutableSortedMap<K, V>
     return keySet().last();
   }
 
+  private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
+    if (fromIndex == 0 && toIndex == size()) {
+      return this;
+    } else if (fromIndex == toIndex) {
+      return emptyMap(comparator());
+    } else {
+      return new ImmutableSortedMap<K, V>(
+          keySet.getSubSet(fromIndex, toIndex), valueList.subList(fromIndex, toIndex));
+    }
+  }
+
   /**
    * This method returns a {@code ImmutableSortedMap}, consisting of the entries
    * whose keys are less than {@code toKey}.
@@ -497,7 +653,9 @@ public abstract class ImmutableSortedMap<K, V>
    * @since 12.0
    */
   @Override
-  public abstract ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive);
+  public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
+    return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
+  }
 
   /**
    * This method returns a {@code ImmutableSortedMap}, consisting of the entries
@@ -533,12 +691,15 @@ public abstract class ImmutableSortedMap<K, V>
    * @since 12.0
    */
   @Override
-  public ImmutableSortedMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey,
-      boolean toInclusive) {
+  public ImmutableSortedMap<K, V> subMap(
+      K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
     checkNotNull(fromKey);
     checkNotNull(toKey);
-    checkArgument(comparator().compare(fromKey, toKey) <= 0,
-        "expected fromKey <= toKey but %s > %s", fromKey, toKey);
+    checkArgument(
+        comparator().compare(fromKey, toKey) <= 0,
+        "expected fromKey <= toKey but %s > %s",
+        fromKey,
+        toKey);
     return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive);
   }
 
@@ -571,7 +732,9 @@ public abstract class ImmutableSortedMap<K, V>
    * @since 12.0
    */
   @Override
-  public abstract ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive);
+  public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
+    return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
+  }
 
   @Override
   public Entry<K, V> lowerEntry(K key) {
@@ -647,27 +810,31 @@ public abstract class ImmutableSortedMap<K, V>
     throw new UnsupportedOperationException();
   }
 
-  private transient ImmutableSortedMap<K, V> descendingMap;
-
   @Override
   public ImmutableSortedMap<K, V> descendingMap() {
+    // TODO(kevinb): the descendingMap is never actually cached at all. Either it should be or the
+    // code below simplified.
     ImmutableSortedMap<K, V> result = descendingMap;
     if (result == null) {
-      result = descendingMap = createDescendingMap();
+      if (isEmpty()) {
+        return result = emptyMap(Ordering.from(comparator()).reverse());
+      } else {
+        return result =
+            new ImmutableSortedMap<K, V>(
+                (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this);
+      }
     }
     return result;
   }
 
-  abstract ImmutableSortedMap<K, V> createDescendingMap();
-
   @Override
   public ImmutableSortedSet<K> navigableKeySet() {
-    return keySet();
+    return keySet;
   }
 
   @Override
   public ImmutableSortedSet<K> descendingKeySet() {
-    return keySet().descendingSet();
+    return keySet.descendingSet();
   }
 
   /**
@@ -678,19 +845,24 @@ public abstract class ImmutableSortedMap<K, V>
    */
   private static class SerializedForm extends ImmutableMap.SerializedForm {
     private final Comparator<Object> comparator;
+
     @SuppressWarnings("unchecked")
     SerializedForm(ImmutableSortedMap<?, ?> sortedMap) {
       super(sortedMap);
       comparator = (Comparator<Object>) sortedMap.comparator();
     }
-    @Override Object readResolve() {
+
+    @Override
+    Object readResolve() {
       Builder<Object, Object> builder = new Builder<Object, Object>(comparator);
       return createMap(builder);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm(this);
   }
 
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
index 7c38d00..13ce60d 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
@@ -23,8 +23,7 @@ package com.google.common.collect;
  *
  * @author Chris Povirk
  */
-abstract class ImmutableSortedMapFauxverideShim<K, V>
-    extends ImmutableMap<K, V> {
+abstract class ImmutableSortedMapFauxverideShim<K, V> extends ImmutableMap<K, V> {
   /**
    * Not supported. Use {@link ImmutableSortedMap#naturalOrder}, which offers
    * better type-safety, instead. This method exists only to hide
@@ -34,7 +33,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    * @deprecated Use {@link ImmutableSortedMap#naturalOrder}, which offers
    *     better type-safety.
    */
-  @Deprecated public static <K, V> ImmutableSortedMap.Builder<K, V> builder() {
+  @Deprecated
+  public static <K, V> ImmutableSortedMap.Builder<K, V> builder() {
     throw new UnsupportedOperationException();
   }
 
@@ -47,7 +47,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    * @deprecated <b>Pass a key of type {@code Comparable} to use {@link
    *     ImmutableSortedMap#of(Comparable, Object)}.</b>
    */
-  @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
+  @Deprecated
+  public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
     throw new UnsupportedOperationException();
   }
 
@@ -60,8 +61,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    * @deprecated <b>Pass keys of type {@code Comparable} to use {@link
    *     ImmutableSortedMap#of(Comparable, Object, Comparable, Object)}.</b>
    */
-  @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
-      K k1, V v1, K k2, V v2) {
+  @Deprecated
+  public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2) {
     throw new UnsupportedOperationException();
   }
 
@@ -75,8 +76,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    *     ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
    *     Comparable, Object)}.</b>
    */
-  @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3) {
+  @Deprecated
+  public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
     throw new UnsupportedOperationException();
   }
 
@@ -90,8 +91,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    *     ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
    *     Comparable, Object, Comparable, Object)}.</b>
    */
-  @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
-      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+  @Deprecated
+  public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
     throw new UnsupportedOperationException();
   }
 
@@ -105,7 +106,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
    *     ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
    *     Comparable, Object, Comparable, Object, Comparable, Object)}.</b>
    */
-  @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
+  @Deprecated
+  public static <K, V> ImmutableSortedMap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
     throw new UnsupportedOperationException();
   }
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
index 24970fa..6d6bb5f 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
@@ -29,49 +29,17 @@ import java.util.Iterator;
 import java.util.List;
 
 /**
- * An immutable {@code SortedMultiset} that stores its elements in a sorted array. Some instances
- * are ordered by an explicit comparator, while others follow the natural sort ordering of their
- * elements. Either way, null elements are not supported.
+ * A {@link SortedMultiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Multisets#unmodifiableSortedMultiset}, which is a <i>view</i> of a separate
- * collection that can still change, an instance of {@code ImmutableSortedMultiset} contains its
- * own private data and will <i>never</i> change. This class is convenient for {@code public static
- * final} multisets ("constant multisets") and also lets you easily make a "defensive copy" of a
- * set provided to your class by a caller.
- *
- * <p>The multisets returned by the {@link #headMultiset}, {@link #tailMultiset}, and
- * {@link #subMultiset} methods share the same array as the original multiset, preventing that
- * array from being garbage collected. If this is a concern, the data may be copied into a
- * correctly-sized array by calling {@link #copyOfSorted}.
- *
- * <p><b>Note on element equivalence:</b> The {@link #contains(Object)},
- * {@link #containsAll(Collection)}, and {@link #equals(Object)} implementations must check whether
- * a provided object is equivalent to an element in the collection. Unlike most collections, an
- * {@code ImmutableSortedMultiset} doesn't use {@link Object#equals} to determine if two elements
- * are equivalent. Instead, with an explicit comparator, the following relation determines whether
- * elements {@code x} and {@code y} are equivalent:
- *
- * <pre>   {@code
- *
- *   {(x, y) | comparator.compare(x, y) == 0}}</pre>
- *
- * <p>With natural ordering of elements, the following relation determines whether two elements are
- * equivalent:
- *
- * <pre>   {@code
- *
- *   {(x, y) | x.compareTo(y) == 0}}</pre>
- *
- * <b>Warning:</b> Like most multisets, an {@code ImmutableSortedMultiset} will not function
- * correctly if an element is modified after being placed in the multiset. For this reason, and to
- * avoid general confusion, it is strongly recommended to place only immutable objects into this
- * collection.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as it has no public or
- * protected constructors. Thus, instances of this type are guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting
+ * collection will not correctly obey its specification.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Louis Wasserman
@@ -81,12 +49,12 @@ import java.util.List;
 @GwtIncompatible("hasn't been tested yet")
 public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultisetFauxverideShim<E>
     implements SortedMultiset<E> {
-  // TODO(user): GWT compatibility
+  // TODO(lowasser): GWT compatibility
 
   private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
 
   private static final ImmutableSortedMultiset<Comparable> NATURAL_EMPTY_MULTISET =
-      new EmptyImmutableSortedMultiset<Comparable>(NATURAL_ORDER);
+      new RegularImmutableSortedMultiset<Comparable>(NATURAL_ORDER);
 
   /**
    * Returns the empty immutable sorted multiset.
@@ -102,9 +70,8 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
   public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E element) {
     RegularImmutableSortedSet<E> elementSet =
         (RegularImmutableSortedSet<E>) ImmutableSortedSet.of(element);
-    int[] counts = {1};
     long[] cumulativeCounts = {0, 1};
-    return new RegularImmutableSortedMultiset<E>(elementSet, counts, cumulativeCounts, 0, 1);
+    return new RegularImmutableSortedMultiset<E>(elementSet, cumulativeCounts, 0, 1);
   }
 
   /**
@@ -283,8 +250,8 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
    * @throws NullPointerException if {@code sortedMultiset} or any of its elements is null
    */
   public static <E> ImmutableSortedMultiset<E> copyOfSorted(SortedMultiset<E> sortedMultiset) {
-    return copyOfSortedEntries(sortedMultiset.comparator(),
-        Lists.newArrayList(sortedMultiset.entrySet()));
+    return copyOfSortedEntries(
+        sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet()));
   }
 
   private static <E> ImmutableSortedMultiset<E> copyOfSortedEntries(
@@ -293,26 +260,27 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
       return emptyMultiset(comparator);
     }
     ImmutableList.Builder<E> elementsBuilder = new ImmutableList.Builder<E>(entries.size());
-    int[] counts = new int[entries.size()];
     long[] cumulativeCounts = new long[entries.size() + 1];
     int i = 0;
     for (Entry<E> entry : entries) {
       elementsBuilder.add(entry.getElement());
-      counts[i] = entry.getCount();
-      cumulativeCounts[i + 1] = cumulativeCounts[i] + counts[i];
+      cumulativeCounts[i + 1] = cumulativeCounts[i] + entry.getCount();
       i++;
     }
     return new RegularImmutableSortedMultiset<E>(
         new RegularImmutableSortedSet<E>(elementsBuilder.build(), comparator),
-        counts, cumulativeCounts, 0, entries.size());
+        cumulativeCounts,
+        0,
+        entries.size());
   }
 
   @SuppressWarnings("unchecked")
   static <E> ImmutableSortedMultiset<E> emptyMultiset(Comparator<? super E> comparator) {
     if (NATURAL_ORDER.equals(comparator)) {
-      return (ImmutableSortedMultiset) NATURAL_EMPTY_MULTISET;
+      return (ImmutableSortedMultiset<E>) NATURAL_EMPTY_MULTISET;
+    } else {
+      return new RegularImmutableSortedMultiset<E>(comparator);
     }
-    return new EmptyImmutableSortedMultiset<E>(comparator);
   }
 
   ImmutableSortedMultiset() {}
@@ -331,7 +299,10 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
   public ImmutableSortedMultiset<E> descendingMultiset() {
     ImmutableSortedMultiset<E> result = descendingMultiset;
     if (result == null) {
-      return descendingMultiset = new DescendingImmutableSortedMultiset<E>(this);
+      return descendingMultiset =
+          this.isEmpty()
+              ? emptyMultiset(Ordering.from(comparator()).reverse())
+              : new DescendingImmutableSortedMultiset<E>(this);
     }
     return result;
   }
@@ -370,8 +341,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
   @Override
   public ImmutableSortedMultiset<E> subMultiset(
       E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
-    checkArgument(comparator().compare(lowerBound, upperBound) <= 0,
-        "Expected lowerBound <= upperBound but %s > %s", lowerBound, upperBound);
+    checkArgument(
+        comparator().compare(lowerBound, upperBound) <= 0,
+        "Expected lowerBound <= upperBound but %s > %s",
+        lowerBound,
+        upperBound);
     return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
   }
 
@@ -394,11 +368,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
    * Returns a builder that creates immutable sorted multisets whose elements are ordered by the
    * reverse of their natural ordering.
    *
-   * <p>Note: the type parameter {@code E} extends {@code Comparable<E>} rather than {@code
+   * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
    * Comparable<? super E>} as a workaround for javac <a
    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug 6468354</a>.
    */
-  public static <E extends Comparable<E>> Builder<E> reverseOrder() {
+  public static <E extends Comparable<?>> Builder<E> reverseOrder() {
     return new Builder<E>(Ordering.natural().reverse());
   }
 
@@ -408,11 +382,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
    * method provides more type-safety than {@link #builder}, as it can be called only for classes
    * that implement {@link Comparable}.
    *
-   * <p>Note: the type parameter {@code E} extends {@code Comparable<E>} rather than {@code
+   * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
    * Comparable<? super E>} as a workaround for javac <a
    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug 6468354</a>.
    */
-  public static <E extends Comparable<E>> Builder<E> naturalOrder() {
+  public static <E extends Comparable<?>> Builder<E> naturalOrder() {
     return new Builder<E>(Ordering.natural());
   }
 
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
index 60ff701..8f13341 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
@@ -20,7 +20,7 @@ package com.google.common.collect;
  * prevents accidents like the following:
  *
  * <pre>   {@code
- * 
+ *
  *   List<Object> objects = ...;
  *   // Sort them:
  *   Set<Object> sorted = ImmutableSortedMultiset.copyOf(objects);
@@ -128,13 +128,7 @@ abstract class ImmutableSortedMultisetFauxverideShim<E> extends ImmutableMultise
    */
   @Deprecated
   public static <E> ImmutableSortedMultiset<E> of(
-      E e1,
-      E e2,
-      E e3,
-      E e4,
-      E e5,
-      E e6,
-      E... remaining) {
+      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
     throw new UnsupportedOperationException();
   }
 
diff --git a/guava/src/com/google/common/collect/ImmutableSortedSet.java b/guava/src/com/google/common/collect/ImmutableSortedSet.java
index c134890..4a7a94b 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedSet.java
@@ -28,7 +28,6 @@ import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.NavigableSet;
@@ -37,56 +36,22 @@ import java.util.SortedSet;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@code SortedSet} that stores its elements in a sorted array.
- * Some instances are ordered by an explicit comparator, while others follow the
- * natural sort ordering of their elements. Either way, null elements are not
- * supported.
+ * A {@link NavigableSet} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
  *
- * <p>Unlike {@link Collections#unmodifiableSortedSet}, which is a <i>view</i>
- * of a separate collection that can still change, an instance of {@code
- * ImmutableSortedSet} contains its own private data and will <i>never</i>
- * change. This class is convenient for {@code public static final} sets
- * ("constant sets") and also lets you easily make a "defensive copy" of a set
- * provided to your class by a caller.
- *
- * <p>The sets returned by the {@link #headSet}, {@link #tailSet}, and
- * {@link #subSet} methods share the same array as the original set, preventing
- * that array from being garbage collected. If this is a concern, the data may
- * be copied into a correctly-sized array by calling {@link #copyOfSorted}.
- *
- * <p><b>Note on element equivalence:</b> The {@link #contains(Object)},
- * {@link #containsAll(Collection)}, and {@link #equals(Object)}
- * implementations must check whether a provided object is equivalent to an
- * element in the collection. Unlike most collections, an
- * {@code ImmutableSortedSet} doesn't use {@link Object#equals} to determine if
- * two elements are equivalent. Instead, with an explicit comparator, the
- * following relation determines whether elements {@code x} and {@code y} are
- * equivalent: <pre>   {@code
- *
- *   {(x, y) | comparator.compare(x, y) == 0}}</pre>
- *
- * <p>With natural ordering of elements, the following relation determines whether
- * two elements are equivalent: <pre>   {@code
- *
- *   {(x, y) | x.compareTo(y) == 0}}</pre>
- *
- * <b>Warning:</b> Like most sets, an {@code ImmutableSortedSet} will not
- * function correctly if an element is modified after being placed in the set.
- * For this reason, and to avoid general confusion, it is strongly recommended
- * to place only immutable objects into this collection.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this type are
- * guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting
+ * collection will not correctly obey its specification.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
- * @see ImmutableSet
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library; implements {@code NavigableSet} since 12.0)
+ * @since 2.0 (implements {@code NavigableSet} since 12.0)
  */
 // TODO(benyu): benchmark and optimize all creation paths, which are a mess now
 @GwtCompatible(serializable = true, emulated = true)
@@ -94,23 +59,16 @@ import javax.annotation.Nullable;
 public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxverideShim<E>
     implements NavigableSet<E>, SortedIterable<E> {
 
-  private static final Comparator<Comparable> NATURAL_ORDER =
-      Ordering.natural();
-
-  private static final ImmutableSortedSet<Comparable> NATURAL_EMPTY_SET =
-      new EmptyImmutableSortedSet<Comparable>(NATURAL_ORDER);
+  private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
 
-  @SuppressWarnings("unchecked")
-  private static <E> ImmutableSortedSet<E> emptySet() {
-    return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
-  }
+  private static final RegularImmutableSortedSet<Comparable> NATURAL_EMPTY_SET =
+      new RegularImmutableSortedSet<Comparable>(ImmutableList.<Comparable>of(), NATURAL_ORDER);
 
-  static <E> ImmutableSortedSet<E> emptySet(
-      Comparator<? super E> comparator) {
+  static <E> RegularImmutableSortedSet<E> emptySet(Comparator<? super E> comparator) {
     if (NATURAL_ORDER.equals(comparator)) {
-      return emptySet();
+      return (RegularImmutableSortedSet<E>) NATURAL_EMPTY_SET;
     } else {
-      return new EmptyImmutableSortedSet<E>(comparator);
+      return new RegularImmutableSortedSet<E>(ImmutableList.<E>of(), comparator);
     }
   }
 
@@ -118,16 +76,14 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * Returns the empty immutable sorted set.
    */
   public static <E> ImmutableSortedSet<E> of() {
-    return emptySet();
+    return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
   }
 
   /**
    * Returns an immutable sorted set containing a single element.
    */
-  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
-      E element) {
-    return new RegularImmutableSortedSet<E>(
-        ImmutableList.of(element), Ordering.natural());
+  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E element) {
+    return new RegularImmutableSortedSet<E>(ImmutableList.of(element), Ordering.natural());
   }
 
   /**
@@ -138,8 +94,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws NullPointerException if any element is null
    */
   @SuppressWarnings("unchecked")
-  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
-      E e1, E e2) {
+  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2) {
     return construct(Ordering.natural(), 2, e1, e2);
   }
 
@@ -151,8 +106,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws NullPointerException if any element is null
    */
   @SuppressWarnings("unchecked")
-  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
-      E e1, E e2, E e3) {
+  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
     return construct(Ordering.natural(), 3, e1, e2, e3);
   }
 
@@ -164,8 +118,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws NullPointerException if any element is null
    */
   @SuppressWarnings("unchecked")
-  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
-      E e1, E e2, E e3, E e4) {
+  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) {
     return construct(Ordering.natural(), 4, e1, e2, e3, e4);
   }
 
@@ -214,8 +167,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws NullPointerException if any of {@code elements} is null
    * @since 3.0
    */
-  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(
-      E[] elements) {
+  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(E[] elements) {
     return construct(Ordering.natural(), elements.length, elements.clone());
   }
 
@@ -245,8 +197,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws ClassCastException if the elements are not mutually comparable
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableSortedSet<E> copyOf(
-      Iterable<? extends E> elements) {
+  public static <E> ImmutableSortedSet<E> copyOf(Iterable<? extends E> elements) {
     // Hack around E not being a subtype of Comparable.
     // Unsafe, see ImmutableSortedSetFauxverideShim.
     @SuppressWarnings("unchecked")
@@ -283,8 +234,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws NullPointerException if any of {@code elements} is null
    * @since 7.0 (source-compatible since 2.0)
    */
-  public static <E> ImmutableSortedSet<E> copyOf(
-      Collection<? extends E> elements) {
+  public static <E> ImmutableSortedSet<E> copyOf(Collection<? extends E> elements) {
     // Hack around E not being a subtype of Comparable.
     // Unsafe, see ImmutableSortedSetFauxverideShim.
     @SuppressWarnings("unchecked")
@@ -303,8 +253,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * @throws ClassCastException if the elements are not mutually comparable
    * @throws NullPointerException if any of {@code elements} is null
    */
-  public static <E> ImmutableSortedSet<E> copyOf(
-      Iterator<? extends E> elements) {
+  public static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements) {
     // Hack around E not being a subtype of Comparable.
     // Unsafe, see ImmutableSortedSetFauxverideShim.
     @SuppressWarnings("unchecked")
@@ -342,8 +291,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
   public static <E> ImmutableSortedSet<E> copyOf(
       Comparator<? super E> comparator, Iterable<? extends E> elements) {
     checkNotNull(comparator);
-    boolean hasSameComparator =
-        SortedIterables.hasSameComparator(comparator, elements);
+    boolean hasSameComparator = SortedIterables.hasSameComparator(comparator, elements);
 
     if (hasSameComparator && (elements instanceof ImmutableSortedSet)) {
       @SuppressWarnings("unchecked")
@@ -485,7 +433,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
    * times to build multiple sets in series. Each set is a superset of the set
    * created before it.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public static final class Builder<E> extends ImmutableSet.Builder<E> {
     private final Comparator<? super E> comparator;
@@ -508,7 +456,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code element} is null
      */
-    @Override public Builder<E> add(E element) {
+    @Override
+    public Builder<E> add(E element) {
       super.add(element);
       return this;
     }
@@ -521,7 +470,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code elements} contains a null element
      */
-    @Override public Builder<E> add(E... elements) {
+    @Override
+    public Builder<E> add(E... elements) {
       super.add(elements);
       return this;
     }
@@ -534,7 +484,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code elements} contains a null element
      */
-    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterable<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -547,7 +498,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
      * @return this {@code Builder} object
      * @throws NullPointerException if {@code elements} contains a null element
      */
-    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+    @Override
+    public Builder<E> addAll(Iterator<? extends E> elements) {
       super.addAll(elements);
       return this;
     }
@@ -556,7 +508,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
      * Returns a newly-created {@code ImmutableSortedSet} based on the contents
      * of the {@code Builder} and its comparator.
      */
-    @Override public ImmutableSortedSet<E> build() {
+    @Override
+    public ImmutableSortedSet<E> build() {
       @SuppressWarnings("unchecked") // we're careful to put only E's in here
       E[] contentsArray = (E[]) contents;
       ImmutableSortedSet<E> result = construct(comparator, size, contentsArray);
@@ -569,8 +522,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
     return unsafeCompare(comparator, a, b);
   }
 
-  static int unsafeCompare(
-      Comparator<?> comparator, Object a, Object b) {
+  static int unsafeCompare(Comparator<?> comparator, Object a, Object b) {
     // Pretend the comparator can compare anything. If it turns out it can't
     // compare a and b, we should get a CCE on the subsequent line. Only methods
     // that are spec'd to throw CCE should call this.
@@ -691,7 +643,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
       E fromElement, boolean fromInclusive, E toElement, boolean toInclusive);
 
   abstract ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive);
-  
+
   /**
    * @since 12.0
    */
@@ -824,13 +776,12 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
     private static final long serialVersionUID = 0;
   }
 
-  private void readObject(ObjectInputStream stream)
-      throws InvalidObjectException {
+  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
     throw new InvalidObjectException("Use SerializedForm");
   }
 
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm<E>(comparator, toArray());
   }
 }
-
diff --git a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
index 14c4d96..1ed865c 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
@@ -42,7 +42,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * @deprecated Use {@link ImmutableSortedSet#naturalOrder}, which offers
    *     better type-safety.
    */
-  @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+  @Deprecated
+  public static <E> ImmutableSortedSet.Builder<E> builder() {
     throw new UnsupportedOperationException();
   }
 
@@ -55,7 +56,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link
    *     ImmutableSortedSet#of(Comparable)}.</b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(E element) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E element) {
     throw new UnsupportedOperationException();
   }
 
@@ -68,7 +70,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
    *     ImmutableSortedSet#of(Comparable, Comparable)}.</b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(E e1, E e2) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E e1, E e2) {
     throw new UnsupportedOperationException();
   }
 
@@ -81,7 +84,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
    *     ImmutableSortedSet#of(Comparable, Comparable, Comparable)}.</b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
     throw new UnsupportedOperationException();
   }
 
@@ -95,8 +99,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    *     ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable)}.
    * </b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(
-      E e1, E e2, E e3, E e4) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) {
     throw new UnsupportedOperationException();
   }
 
@@ -110,8 +114,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    *     ImmutableSortedSet#of(
    *     Comparable, Comparable, Comparable, Comparable, Comparable)}. </b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(
-      E e1, E e2, E e3, E e4, E e5) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5) {
     throw new UnsupportedOperationException();
   }
 
@@ -122,11 +126,11 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    *
    * @throws UnsupportedOperationException always
    * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
-   *     ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable, 
+   *     ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable,
    *     Comparable, Comparable, Comparable...)}. </b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> of(
-      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
     throw new UnsupportedOperationException();
   }
 
@@ -139,7 +143,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link
    *     ImmutableSortedSet#copyOf(Comparable[])}.</b>
    */
-  @Deprecated public static <E> ImmutableSortedSet<E> copyOf(E[] elements) {
+  @Deprecated
+  public static <E> ImmutableSortedSet<E> copyOf(E[] elements) {
     throw new UnsupportedOperationException();
   }
 
@@ -154,7 +159,7 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
    * compatibility with that version and with any other compilers that interpret
    * the JLS similarly, there is no definition of copyOf() here, and the
    * definition in ImmutableSortedSet matches that in ImmutableSet.
-   * 
+   *
    * The result is that ImmutableSortedSet.copyOf() may be called on
    * non-Comparable elements. We have not discovered a better solution. In
    * retrospect, the static factory methods should have gone in a separate class
diff --git a/guava/src/com/google/common/collect/ImmutableTable.java b/guava/src/com/google/common/collect/ImmutableTable.java
index 3ed87be..354b299 100644
--- a/guava/src/com/google/common/collect/ImmutableTable.java
+++ b/guava/src/com/google/common/collect/ImmutableTable.java
@@ -29,15 +29,11 @@ import java.util.Map;
 import javax.annotation.Nullable;
 
 /**
- * An immutable {@link Table} with reliable user-specified iteration order.
- * Does not permit null keys or values.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * A {@link Table} whose contents will never change, with many other important
+ * properties detailed at {@link ImmutableCollection}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
  * immutable collections</a>.
  *
  * @author Gregory Kick
@@ -46,11 +42,12 @@ import javax.annotation.Nullable;
 @GwtCompatible
 // TODO(gak): make serializable
 public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
-  private static final ImmutableTable<Object, Object, Object> EMPTY
-    = new SparseImmutableTable<Object, Object, Object>(
-        ImmutableList.<Cell<Object, Object, Object>>of(),
-        ImmutableSet.of(), ImmutableSet.of());
-  
+  private static final ImmutableTable<Object, Object, Object> EMPTY =
+      new SparseImmutableTable<Object, Object, Object>(
+          ImmutableList.<Cell<Object, Object, Object>>of(),
+          ImmutableSet.of(),
+          ImmutableSet.of());
+
   /** Returns an empty immutable table. */
   @SuppressWarnings("unchecked")
   public static <R, C, V> ImmutableTable<R, C, V> of() {
@@ -58,8 +55,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
   }
 
   /** Returns an immutable table containing a single cell. */
-  public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey,
-      C columnKey, V value) {
+  public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey, C columnKey, V value) {
     return new SingletonImmutableTable<R, C, V>(rowKey, columnKey, value);
   }
 
@@ -81,8 +77,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
       Table<? extends R, ? extends C, ? extends V> table) {
     if (table instanceof ImmutableTable) {
       @SuppressWarnings("unchecked")
-      ImmutableTable<R, C, V> parameterizedTable
-          = (ImmutableTable<R, C, V>) table;
+      ImmutableTable<R, C, V> parameterizedTable = (ImmutableTable<R, C, V>) table;
       return parameterizedTable;
     } else {
       int size = table.size();
@@ -90,21 +85,20 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
         case 0:
           return of();
         case 1:
-          Cell<? extends R, ? extends C, ? extends V> onlyCell
-              = Iterables.getOnlyElement(table.cellSet());
-          return ImmutableTable.<R, C, V>of(onlyCell.getRowKey(),
-              onlyCell.getColumnKey(), onlyCell.getValue());
+          Cell<? extends R, ? extends C, ? extends V> onlyCell =
+              Iterables.getOnlyElement(table.cellSet());
+          return ImmutableTable.<R, C, V>of(
+              onlyCell.getRowKey(), onlyCell.getColumnKey(), onlyCell.getValue());
         default:
-          ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder
-              = ImmutableSet.builder();
-          for (Cell<? extends R, ? extends C, ? extends V> cell :
-              table.cellSet()) {
+          ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder =
+              new ImmutableSet.Builder<Cell<R, C, V>>(size);
+          for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
             /*
              * Must cast to be able to create a Cell<R, C, V> rather than a
              * Cell<? extends R, ? extends C, ? extends V>
              */
-            cellSetBuilder.add(cellOf((R) cell.getRowKey(),
-                (C) cell.getColumnKey(), (V) cell.getValue()));
+            cellSetBuilder.add(
+                cellOf((R) cell.getRowKey(), (C) cell.getColumnKey(), (V) cell.getValue()));
           }
           return RegularImmutableTable.forCells(cellSetBuilder.build());
       }
@@ -124,8 +118,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * non-null, and returns a new entry with those values.
    */
   static <R, C, V> Cell<R, C, V> cellOf(R rowKey, C columnKey, V value) {
-    return Tables.immutableCell(checkNotNull(rowKey), checkNotNull(columnKey),
-        checkNotNull(value));
+    return Tables.immutableCell(checkNotNull(rowKey), checkNotNull(columnKey), checkNotNull(value));
   }
 
   /**
@@ -176,8 +169,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
     /**
      * Specifies the ordering of the generated table's columns.
      */
-    public Builder<R, C, V> orderColumnsBy(
-        Comparator<? super C> columnComparator) {
+    public Builder<R, C, V> orderColumnsBy(Comparator<? super C> columnComparator) {
       this.columnComparator = checkNotNull(columnComparator);
       return this;
     }
@@ -197,8 +189,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
      * necessary. Duplicate key pairs are not allowed and will cause {@link
      * #build} to fail.
      */
-    public Builder<R, C, V> put(
-        Cell<? extends R, ? extends C, ? extends V> cell) {
+    public Builder<R, C, V> put(Cell<? extends R, ? extends C, ? extends V> cell) {
       if (cell instanceof Tables.ImmutableCell) {
         checkNotNull(cell.getRowKey());
         checkNotNull(cell.getColumnKey());
@@ -219,8 +210,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
      *
      * @throws NullPointerException if any key or value in {@code table} is null
      */
-    public Builder<R, C, V> putAll(
-        Table<? extends R, ? extends C, ? extends V> table) {
+    public Builder<R, C, V> putAll(Table<? extends R, ? extends C, ? extends V> table) {
       for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
         put(cell);
       }
@@ -238,18 +228,17 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
         case 0:
           return of();
         case 1:
-          return new SingletonImmutableTable<R, C, V>(
-              Iterables.getOnlyElement(cells));
+          return new SingletonImmutableTable<R, C, V>(Iterables.getOnlyElement(cells));
         default:
-         return RegularImmutableTable.forCells(
-             cells, rowComparator, columnComparator);
+          return RegularImmutableTable.forCells(cells, rowComparator, columnComparator);
       }
     }
   }
 
   ImmutableTable() {}
 
-  @Override public ImmutableSet<Cell<R, C, V>> cellSet() {
+  @Override
+  public ImmutableSet<Cell<R, C, V>> cellSet() {
     return (ImmutableSet<Cell<R, C, V>>) super.cellSet();
   }
 
@@ -271,7 +260,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
 
   @Override
   final Iterator<V> valuesIterator() {
-    throw new AssertionError("should never be called"); 
+    throw new AssertionError("should never be called");
   }
 
   /**
@@ -279,14 +268,16 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    *
    * @throws NullPointerException if {@code columnKey} is {@code null}
    */
-  @Override public ImmutableMap<R, V> column(C columnKey) {
+  @Override
+  public ImmutableMap<R, V> column(C columnKey) {
     checkNotNull(columnKey);
     return MoreObjects.firstNonNull(
         (ImmutableMap<R, V>) columnMap().get(columnKey),
         ImmutableMap.<R, V>of());
   }
 
-  @Override public ImmutableSet<C> columnKeySet() {
+  @Override
+  public ImmutableSet<C> columnKeySet() {
     return columnMap().keySet();
   }
 
@@ -296,21 +287,24 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * <p>The value {@code Map<R, V>} instances in the returned map are
    * {@link ImmutableMap} instances as well.
    */
-  @Override public abstract ImmutableMap<C, Map<R, V>> columnMap();
+  @Override
+  public abstract ImmutableMap<C, Map<R, V>> columnMap();
 
   /**
    * {@inheritDoc}
    *
    * @throws NullPointerException if {@code rowKey} is {@code null}
    */
-  @Override public ImmutableMap<C, V> row(R rowKey) {
+  @Override
+  public ImmutableMap<C, V> row(R rowKey) {
     checkNotNull(rowKey);
     return MoreObjects.firstNonNull(
         (ImmutableMap<C, V>) rowMap().get(rowKey),
         ImmutableMap.<C, V>of());
   }
 
-  @Override public ImmutableSet<R> rowKeySet() {
+  @Override
+  public ImmutableSet<R> rowKeySet() {
     return rowMap().keySet();
   }
 
@@ -320,11 +314,12 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * <p>The value {@code Map<C, V>} instances in the returned map are
    * {@link ImmutableMap} instances as well.
    */
-  @Override public abstract ImmutableMap<R, Map<C, V>> rowMap();
+  @Override
+  public abstract ImmutableMap<R, Map<C, V>> rowMap();
 
   @Override
   public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
-    return get(rowKey, columnKey) != null;    
+    return get(rowKey, columnKey) != null;
   }
 
   @Override
@@ -338,7 +333,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final void clear() {
+  @Deprecated
+  @Override
+  public final void clear() {
     throw new UnsupportedOperationException();
   }
 
@@ -348,7 +345,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final V put(R rowKey, C columnKey, V value) {
+  @Deprecated
+  @Override
+  public final V put(R rowKey, C columnKey, V value) {
     throw new UnsupportedOperationException();
   }
 
@@ -358,8 +357,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final void putAll(
-      Table<? extends R, ? extends C, ? extends V> table) {
+  @Deprecated
+  @Override
+  public final void putAll(Table<? extends R, ? extends C, ? extends V> table) {
     throw new UnsupportedOperationException();
   }
 
@@ -369,7 +369,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final V remove(Object rowKey, Object columnKey) {
+  @Deprecated
+  @Override
+  public final V remove(Object rowKey, Object columnKey) {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava/src/com/google/common/collect/Interners.java b/guava/src/com/google/common/collect/Interners.java
index bd592d6..94531df 100644
--- a/guava/src/com/google/common/collect/Interners.java
+++ b/guava/src/com/google/common/collect/Interners.java
@@ -44,7 +44,8 @@ public final class Interners {
   public static <E> Interner<E> newStrongInterner() {
     final ConcurrentMap<E, E> map = new MapMaker().makeMap();
     return new Interner<E>() {
-      @Override public E intern(E sample) {
+      @Override
+      public E intern(E sample) {
         E canonical = map.putIfAbsent(checkNotNull(sample), sample);
         return (canonical == null) ? sample : canonical;
       }
@@ -65,12 +66,14 @@ public final class Interners {
 
   private static class WeakInterner<E> implements Interner<E> {
     // MapMaker is our friend, we know about this type
-    private final MapMakerInternalMap<E, Dummy> map = new MapMaker()
-          .weakKeys()
-          .keyEquivalence(Equivalence.equals())
-          .makeCustomMap();
-
-    @Override public E intern(E sample) {
+    private final MapMakerInternalMap<E, Dummy> map =
+        new MapMaker()
+            .weakKeys()
+            .keyEquivalence(Equivalence.equals())
+            .makeCustomMap();
+
+    @Override
+    public E intern(E sample) {
       while (true) {
         // trying to read the canonical...
         ReferenceEntry<E, Dummy> entry = map.getEntry(sample);
@@ -96,7 +99,9 @@ public final class Interners {
       }
     }
 
-    private enum Dummy { VALUE }
+    private enum Dummy {
+      VALUE
+    }
   }
 
   /**
@@ -116,15 +121,18 @@ public final class Interners {
       this.interner = interner;
     }
 
-    @Override public E apply(E input) {
+    @Override
+    public E apply(E input) {
       return interner.intern(input);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return interner.hashCode();
     }
 
-    @Override public boolean equals(Object other) {
+    @Override
+    public boolean equals(Object other) {
       if (other instanceof InternerFunction) {
         InternerFunction<?> that = (InternerFunction<?>) other;
         return interner.equals(that.interner);
diff --git a/guava/src/com/google/common/collect/Iterables.java b/guava/src/com/google/common/collect/Iterables.java
index cacba1a..a1421a0 100644
--- a/guava/src/com/google/common/collect/Iterables.java
+++ b/guava/src/com/google/common/collect/Iterables.java
@@ -37,6 +37,7 @@ import java.util.Queue;
 import java.util.RandomAccess;
 import java.util.Set;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -49,23 +50,21 @@ import javax.annotation.Nullable;
  * only advance the backing iteration when absolutely necessary.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
  * {@code Iterables}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Iterables {
   private Iterables() {}
 
   /** Returns an unmodifiable view of {@code iterable}. */
-  public static <T> Iterable<T> unmodifiableIterable(
-      final Iterable<T> iterable) {
+  public static <T> Iterable<T> unmodifiableIterable(final Iterable<T> iterable) {
     checkNotNull(iterable);
-    if (iterable instanceof UnmodifiableIterable ||
-        iterable instanceof ImmutableCollection) {
+    if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) {
       return iterable;
     }
     return new UnmodifiableIterable<T>(iterable);
@@ -77,8 +76,8 @@ public final class Iterables {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <E> Iterable<E> unmodifiableIterable(
-      ImmutableCollection<E> iterable) {
+  @Deprecated
+  public static <E> Iterable<E> unmodifiableIterable(ImmutableCollection<E> iterable) {
     return checkNotNull(iterable);
   }
 
@@ -133,8 +132,7 @@ public final class Iterables {
    * @param elementsToRemove the elements to remove
    * @return {@code true} if any element was removed from {@code iterable}
    */
-  public static boolean removeAll(
-      Iterable<?> removeFrom, Collection<?> elementsToRemove) {
+  public static boolean removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) {
     return (removeFrom instanceof Collection)
         ? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
         : Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
@@ -151,8 +149,7 @@ public final class Iterables {
    * @param elementsToRetain the elements to retain
    * @return {@code true} if any element was removed from {@code iterable}
    */
-  public static boolean retainAll(
-      Iterable<?> removeFrom, Collection<?> elementsToRetain) {
+  public static boolean retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) {
     return (removeFrom instanceof Collection)
         ? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
         : Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
@@ -171,11 +168,9 @@ public final class Iterables {
    *     {@code remove()}.
    * @since 2.0
    */
-  public static <T> boolean removeIf(
-      Iterable<T> removeFrom, Predicate<? super T> predicate) {
+  public static <T> boolean removeIf(Iterable<T> removeFrom, Predicate<? super T> predicate) {
     if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
-      return removeIfFromRandomAccessList(
-          (List<T>) removeFrom, checkNotNull(predicate));
+      return removeIfFromRandomAccessList((List<T>) removeFrom, checkNotNull(predicate));
     }
     return Iterators.removeIf(removeFrom.iterator(), predicate);
   }
@@ -207,8 +202,8 @@ public final class Iterables {
     return from != to;
   }
 
-  private static <T> void slowRemoveIfForRemainingElements(List<T> list,
-      Predicate<? super T> predicate, int to, int from) {
+  private static <T> void slowRemoveIfForRemainingElements(
+      List<T> list, Predicate<? super T> predicate, int to, int from) {
     // Here we know that:
     // * (to < from) and that both are valid indices.
     // * Everything with (index < to) should be kept.
@@ -254,8 +249,8 @@ public final class Iterables {
    * of {@code iterable1} is equal to the corresponding element of
    * {@code iterable2}.
    */
-  public static boolean elementsEqual(
-      Iterable<?> iterable1, Iterable<?> iterable2) {
+  @CheckReturnValue
+  public static boolean elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
     if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
       Collection<?> collection1 = (Collection<?>) iterable1;
       Collection<?> collection2 = (Collection<?>) iterable2;
@@ -297,8 +292,7 @@ public final class Iterables {
    *     elements
    */
   @Nullable
-  public static <T> T getOnlyElement(
-      Iterable<? extends T> iterable, @Nullable T defaultValue) {
+  public static <T> T getOnlyElement(Iterable<? extends T> iterable, @Nullable T defaultValue) {
     return Iterators.getOnlyElement(iterable.iterator(), defaultValue);
   }
 
@@ -317,6 +311,11 @@ public final class Iterables {
     return collection.toArray(array);
   }
 
+  static <T> T[] toArray(Iterable<? extends T> iterable, T[] array) {
+    Collection<? extends T> collection = toCollection(iterable);
+    return collection.toArray(array);
+  }
+
   /**
    * Copies an iterable's elements into an array.
    *
@@ -345,8 +344,7 @@ public final class Iterables {
    * @return {@code true} if {@code collection} was modified as a result of this
    *     operation.
    */
-  public static <T> boolean addAll(
-      Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
+  public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
     if (elementsToAdd instanceof Collection) {
       Collection<? extends T> c = Collections2.cast(elementsToAdd);
       return addTo.addAll(c);
@@ -394,7 +392,9 @@ public final class Iterables {
       public Iterator<T> iterator() {
         return Iterators.cycle(iterable);
       }
-      @Override public String toString() {
+
+      @Override
+      public String toString() {
         return iterable.toString() + " (cycled)";
       }
     };
@@ -430,8 +430,7 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(
-      Iterable<? extends T> a, Iterable<? extends T> b) {
+  public static <T> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b) {
     return concat(ImmutableList.of(a, b));
   }
 
@@ -444,8 +443,8 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(Iterable<? extends T> a,
-      Iterable<? extends T> b, Iterable<? extends T> c) {
+  public static <T> Iterable<T> concat(
+      Iterable<? extends T> a, Iterable<? extends T> b, Iterable<? extends T> c) {
     return concat(ImmutableList.of(a, b, c));
   }
 
@@ -459,8 +458,10 @@ public final class Iterables {
    * <p>The returned iterable's iterator supports {@code remove()} when the
    * corresponding input iterator supports it.
    */
-  public static <T> Iterable<T> concat(Iterable<? extends T> a,
-      Iterable<? extends T> b, Iterable<? extends T> c,
+  public static <T> Iterable<T> concat(
+      Iterable<? extends T> a,
+      Iterable<? extends T> b,
+      Iterable<? extends T> c,
       Iterable<? extends T> d) {
     return concat(ImmutableList.of(a, b, c, d));
   }
@@ -489,8 +490,7 @@ public final class Iterables {
    * iterable may throw {@code NullPointerException} if any of the input
    * iterators is null.
    */
-  public static <T> Iterable<T> concat(
-      final Iterable<? extends Iterable<? extends T>> inputs) {
+  public static <T> Iterable<T> concat(final Iterable<? extends Iterable<? extends T>> inputs) {
     checkNotNull(inputs);
     return new FluentIterable<T>() {
       @Override
@@ -534,8 +534,7 @@ public final class Iterables {
    *     iterable} divided into partitions
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> Iterable<List<T>> partition(
-      final Iterable<T> iterable, final int size) {
+  public static <T> Iterable<List<T>> partition(final Iterable<T> iterable, final int size) {
     checkNotNull(iterable);
     checkArgument(size > 0);
     return new FluentIterable<List<T>>() {
@@ -563,8 +562,7 @@ public final class Iterables {
    *     trailing null elements)
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> Iterable<List<T>> paddedPartition(
-      final Iterable<T> iterable, final int size) {
+  public static <T> Iterable<List<T>> paddedPartition(final Iterable<T> iterable, final int size) {
     checkNotNull(iterable);
     checkArgument(size > 0);
     return new FluentIterable<List<T>>() {
@@ -579,6 +577,7 @@ public final class Iterables {
    * Returns the elements of {@code unfiltered} that satisfy a predicate. The
    * resulting iterable's iterator does not support {@code remove()}.
    */
+  @CheckReturnValue
   public static <T> Iterable<T> filter(
       final Iterable<T> unfiltered, final Predicate<? super T> predicate) {
     checkNotNull(unfiltered);
@@ -603,8 +602,8 @@ public final class Iterables {
    *     iterable that were of the requested type
    */
   @GwtIncompatible("Class.isInstance")
-  public static <T> Iterable<T> filter(
-      final Iterable<?> unfiltered, final Class<T> type) {
+  @CheckReturnValue
+  public static <T> Iterable<T> filter(final Iterable<?> unfiltered, final Class<T> type) {
     checkNotNull(unfiltered);
     checkNotNull(type);
     return new FluentIterable<T>() {
@@ -618,8 +617,7 @@ public final class Iterables {
   /**
    * Returns {@code true} if any element in {@code iterable} satisfies the predicate.
    */
-  public static <T> boolean any(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.any(iterable.iterator(), predicate);
   }
 
@@ -627,8 +625,7 @@ public final class Iterables {
    * Returns {@code true} if every element in {@code iterable} satisfies the
    * predicate. If {@code iterable} is empty, {@code true} is returned.
    */
-  public static <T> boolean all(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.all(iterable.iterator(), predicate);
   }
 
@@ -641,8 +638,7 @@ public final class Iterables {
    * @throws NoSuchElementException if no element in {@code iterable} matches
    *     the given predicate
    */
-  public static <T> T find(Iterable<T> iterable,
-      Predicate<? super T> predicate) {
+  public static <T> T find(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.find(iterable.iterator(), predicate);
   }
 
@@ -655,8 +651,8 @@ public final class Iterables {
    * @since 7.0
    */
   @Nullable
-  public static <T> T find(Iterable<? extends T> iterable,
-      Predicate<? super T> predicate, @Nullable T defaultValue) {
+  public static <T> T find(
+      Iterable<? extends T> iterable, Predicate<? super T> predicate, @Nullable T defaultValue) {
     return Iterators.find(iterable.iterator(), predicate, defaultValue);
   }
 
@@ -670,8 +666,7 @@ public final class Iterables {
    *
    * @since 11.0
    */
-  public static <T> Optional<T> tryFind(Iterable<T> iterable,
-      Predicate<? super T> predicate) {
+  public static <T> Optional<T> tryFind(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.tryFind(iterable.iterator(), predicate);
   }
 
@@ -686,8 +681,7 @@ public final class Iterables {
    *
    * @since 2.0
    */
-  public static <T> int indexOf(
-      Iterable<T> iterable, Predicate<? super T> predicate) {
+  public static <T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate) {
     return Iterators.indexOf(iterable.iterator(), predicate);
   }
 
@@ -703,8 +697,9 @@ public final class Iterables {
    * {@code Collection}, consider {@link Lists#transform} and {@link
    * Collections2#transform}.
    */
-  public static <F, T> Iterable<T> transform(final Iterable<F> fromIterable,
-      final Function<? super F, ? extends T> function) {
+  @CheckReturnValue
+  public static <F, T> Iterable<T> transform(
+      final Iterable<F> fromIterable, final Function<? super F, ? extends T> function) {
     checkNotNull(fromIterable);
     checkNotNull(function);
     return new FluentIterable<T>() {
@@ -840,8 +835,7 @@ public final class Iterables {
    *
    * @since 3.0
    */
-  public static <T> Iterable<T> skip(final Iterable<T> iterable,
-      final int numberToSkip) {
+  public static <T> Iterable<T> skip(final Iterable<T> iterable, final int numberToSkip) {
     checkNotNull(iterable);
     checkArgument(numberToSkip >= 0, "number to skip cannot be negative");
 
@@ -906,8 +900,7 @@ public final class Iterables {
    * @throws IllegalArgumentException if {@code limitSize} is negative
    * @since 3.0
    */
-  public static <T> Iterable<T> limit(
-      final Iterable<T> iterable, final int limitSize) {
+  public static <T> Iterable<T> limit(final Iterable<T> iterable, final int limitSize) {
     checkNotNull(iterable);
     checkArgument(limitSize >= 0, "limit is negative");
     return new FluentIterable<T>() {
@@ -967,22 +960,6 @@ public final class Iterables {
     };
   }
 
-  private static class ConsumingQueueIterator<T> extends AbstractIterator<T> {
-    private final Queue<T> queue;
-
-    private ConsumingQueueIterator(Queue<T> queue) {
-      this.queue = queue;
-    }
-
-    @Override public T computeNext() {
-      try {
-        return queue.remove();
-      } catch (NoSuchElementException e) {
-        return endOfData();
-      }
-    }
-  }
-
   // Methods only in Iterables, not in Iterators
 
   /**
@@ -1019,21 +996,21 @@ public final class Iterables {
       final Comparator<? super T> comparator) {
     checkNotNull(iterables, "iterables");
     checkNotNull(comparator, "comparator");
-    Iterable<T> iterable = new FluentIterable<T>() {
-      @Override
-      public Iterator<T> iterator() {
-        return Iterators.mergeSorted(
-            Iterables.transform(iterables, Iterables.<T>toIterator()),
-            comparator);
-      }
-    };
+    Iterable<T> iterable =
+        new FluentIterable<T>() {
+          @Override
+          public Iterator<T> iterator() {
+            return Iterators.mergeSorted(
+                Iterables.transform(iterables, Iterables.<T>toIterator()),
+                comparator);
+          }
+        };
     return new UnmodifiableIterable<T>(iterable);
   }
 
   // TODO(user): Is this the best place for this? Move to fluent functions?
   // Useful as a public method?
-  private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
-      toIterator() {
+  private static <T> Function<Iterable<? extends T>, Iterator<? extends T>> toIterator() {
     return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
       @Override
       public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
diff --git a/guava/src/com/google/common/collect/Iterators.java b/guava/src/com/google/common/collect/Iterators.java
index 229964b..c94b1e8 100644
--- a/guava/src/com/google/common/collect/Iterators.java
+++ b/guava/src/com/google/common/collect/Iterators.java
@@ -46,6 +46,7 @@ import java.util.NoSuchElementException;
 import java.util.PriorityQueue;
 import java.util.Queue;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -58,39 +59,44 @@ import javax.annotation.Nullable;
  * the backing iteration when absolutely necessary.
  *
  * <p>See the Guava User Guide section on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
  * {@code Iterators}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Iterators {
   private Iterators() {}
 
-  static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR
-      = new UnmodifiableListIterator<Object>() {
+  static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
+      new UnmodifiableListIterator<Object>() {
         @Override
         public boolean hasNext() {
           return false;
         }
+
         @Override
         public Object next() {
           throw new NoSuchElementException();
         }
+
         @Override
         public boolean hasPrevious() {
           return false;
         }
+
         @Override
         public Object previous() {
           throw new NoSuchElementException();
         }
+
         @Override
         public int nextIndex() {
           return 0;
         }
+
         @Override
         public int previousIndex() {
           return -1;
@@ -126,15 +132,18 @@ public final class Iterators {
 
   private static final Iterator<Object> EMPTY_MODIFIABLE_ITERATOR =
       new Iterator<Object>() {
-        @Override public boolean hasNext() {
+        @Override
+        public boolean hasNext() {
           return false;
         }
 
-        @Override public Object next() {
+        @Override
+        public Object next() {
           throw new NoSuchElementException();
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(false);
         }
       };
@@ -152,8 +161,7 @@ public final class Iterators {
   }
 
   /** Returns an unmodifiable view of {@code iterator}. */
-  public static <T> UnmodifiableIterator<T> unmodifiableIterator(
-      final Iterator<T> iterator) {
+  public static <T> UnmodifiableIterator<T> unmodifiableIterator(final Iterator<T> iterator) {
     checkNotNull(iterator);
     if (iterator instanceof UnmodifiableIterator) {
       return (UnmodifiableIterator<T>) iterator;
@@ -163,6 +171,7 @@ public final class Iterators {
       public boolean hasNext() {
         return iterator.hasNext();
       }
+
       @Override
       public T next() {
         return iterator.next();
@@ -176,8 +185,8 @@ public final class Iterators {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <T> UnmodifiableIterator<T> unmodifiableIterator(
-      UnmodifiableIterator<T> iterator) {
+  @Deprecated
+  public static <T> UnmodifiableIterator<T> unmodifiableIterator(UnmodifiableIterator<T> iterator) {
     return checkNotNull(iterator);
   }
 
@@ -211,8 +220,7 @@ public final class Iterators {
    * @param elementsToRemove the elements to remove
    * @return {@code true} if any element was removed from {@code iterator}
    */
-  public static boolean removeAll(
-      Iterator<?> removeFrom, Collection<?> elementsToRemove) {
+  public static boolean removeAll(Iterator<?> removeFrom, Collection<?> elementsToRemove) {
     return removeIf(removeFrom, in(elementsToRemove));
   }
 
@@ -227,8 +235,7 @@ public final class Iterators {
    * @return {@code true} if any elements were removed from the iterator
    * @since 2.0
    */
-  public static <T> boolean removeIf(
-      Iterator<T> removeFrom, Predicate<? super T> predicate) {
+  public static <T> boolean removeIf(Iterator<T> removeFrom, Predicate<? super T> predicate) {
     checkNotNull(predicate);
     boolean modified = false;
     while (removeFrom.hasNext()) {
@@ -249,8 +256,7 @@ public final class Iterators {
    * @param elementsToRetain the elements to retain
    * @return {@code true} if any element was removed from {@code iterator}
    */
-  public static boolean retainAll(
-      Iterator<?> removeFrom, Collection<?> elementsToRetain) {
+  public static boolean retainAll(Iterator<?> removeFrom, Collection<?> elementsToRetain) {
     return removeIf(removeFrom, not(in(elementsToRetain)));
   }
 
@@ -264,8 +270,7 @@ public final class Iterators {
    * <p>Note that this will modify the supplied iterators, since they will have
    * been advanced some number of elements forward.
    */
-  public static boolean elementsEqual(
-      Iterator<?> iterator1, Iterator<?> iterator2) {
+  public static boolean elementsEqual(Iterator<?> iterator1, Iterator<?> iterator2) {
     while (iterator1.hasNext()) {
       if (!iterator2.hasNext()) {
         return false;
@@ -339,8 +344,7 @@ public final class Iterators {
    *         have been copied
    */
   @GwtIncompatible("Array.newInstance(Class, int)")
-  public static <T> T[] toArray(
-      Iterator<? extends T> iterator, Class<T> type) {
+  public static <T> T[] toArray(Iterator<? extends T> iterator, Class<T> type) {
     List<T> list = Lists.newArrayList(iterator);
     return Iterables.toArray(list, type);
   }
@@ -353,8 +357,7 @@ public final class Iterators {
    * @return {@code true} if {@code collection} was modified as a result of this
    *         operation
    */
-  public static <T> boolean addAll(
-      Collection<T> addTo, Iterator<? extends T> iterator) {
+  public static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
     checkNotNull(addTo);
     checkNotNull(iterator);
     boolean wasModified = false;
@@ -392,29 +395,36 @@ public final class Iterators {
   public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
     checkNotNull(iterable);
     return new Iterator<T>() {
-      Iterator<T> iterator = emptyIterator();
-      Iterator<T> removeFrom;
+      Iterator<T> iterator = emptyModifiableIterator();
 
       @Override
       public boolean hasNext() {
-        if (!iterator.hasNext()) {
-          iterator = iterable.iterator();
-        }
-        return iterator.hasNext();
+        /*
+         * Don't store a new Iterator until we know the user can't remove() the last returned
+         * element anymore. Otherwise, when we remove from the old iterator, we may be invalidating
+         * the new one. The result is a ConcurrentModificationException or other bad behavior.
+         *
+         * (If we decide that we really, really hate allocating two Iterators per cycle instead of
+         * one, we can optimistically store the new Iterator and then be willing to throw it out if
+         * the user calls remove().)
+         */
+        return iterator.hasNext() || iterable.iterator().hasNext();
       }
+
       @Override
       public T next() {
-        if (!hasNext()) {
-          throw new NoSuchElementException();
+        if (!iterator.hasNext()) {
+          iterator = iterable.iterator();
+          if (!iterator.hasNext()) {
+            throw new NoSuchElementException();
+          }
         }
-        removeFrom = iterator;
         return iterator.next();
       }
+
       @Override
       public void remove() {
-        checkRemove(removeFrom != null);
-        removeFrom.remove();
-        removeFrom = null;
+        iterator.remove();
       }
     };
   }
@@ -449,9 +459,10 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b) {
-    return concat(ImmutableList.of(a, b).iterator());
+  public static <T> Iterator<T> concat(Iterator<? extends T> a, Iterator<? extends T> b) {
+    checkNotNull(a);
+    checkNotNull(b);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b));
   }
 
   /**
@@ -468,9 +479,12 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b, Iterator<? extends T> c) {
-    return concat(ImmutableList.of(a, b, c).iterator());
+  public static <T> Iterator<T> concat(
+      Iterator<? extends T> a, Iterator<? extends T> b, Iterator<? extends T> c) {
+    checkNotNull(a);
+    checkNotNull(b);
+    checkNotNull(c);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c));
   }
 
   /**
@@ -487,10 +501,16 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(Iterator<? extends T> a,
-      Iterator<? extends T> b, Iterator<? extends T> c,
+  public static <T> Iterator<T> concat(
+      Iterator<? extends T> a,
+      Iterator<? extends T> b,
+      Iterator<? extends T> c,
       Iterator<? extends T> d) {
-    return concat(ImmutableList.of(a, b, c, d).iterator());
+    checkNotNull(a);
+    checkNotNull(b);
+    checkNotNull(c);
+    checkNotNull(d);
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c, d));
   }
 
   /**
@@ -509,7 +529,10 @@ public final class Iterators {
    * @throws NullPointerException if any of the provided iterators is null
    */
   public static <T> Iterator<T> concat(Iterator<? extends T>... inputs) {
-    return concat(ImmutableList.copyOf(inputs).iterator());
+    for (Iterator<? extends T> input : checkNotNull(inputs)) {
+      checkNotNull(input);
+    }
+    return concat(new ConsumingQueueIterator<Iterator<? extends T>>(inputs));
   }
 
   /**
@@ -526,8 +549,7 @@ public final class Iterators {
    * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
    * resulting iterator has a cubic complexity to the depth of the nesting.
    */
-  public static <T> Iterator<T> concat(
-      final Iterator<? extends Iterator<? extends T>> inputs) {
+  public static <T> Iterator<T> concat(final Iterator<? extends Iterator<? extends T>> inputs) {
     checkNotNull(inputs);
     return new Iterator<T>() {
       Iterator<? extends T> current = emptyIterator();
@@ -543,12 +565,12 @@ public final class Iterators {
         // because otherwise we'll have called inputs.next() before throwing
         // the first NPE, and the next time around we'll call inputs.next()
         // again, incorrectly moving beyond the error.
-        while (!(currentHasNext = checkNotNull(current).hasNext())
-            && inputs.hasNext()) {
+        while (!(currentHasNext = checkNotNull(current).hasNext()) && inputs.hasNext()) {
           current = inputs.next();
         }
         return currentHasNext;
       }
+
       @Override
       public T next() {
         if (!hasNext()) {
@@ -557,6 +579,7 @@ public final class Iterators {
         removeFrom = current;
         return current.next();
       }
+
       @Override
       public void remove() {
         checkRemove(removeFrom != null);
@@ -581,8 +604,7 @@ public final class Iterators {
    *     iterator} divided into partitions
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> UnmodifiableIterator<List<T>> partition(
-      Iterator<T> iterator, int size) {
+  public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
     return partitionImpl(iterator, size, false);
   }
 
@@ -602,8 +624,7 @@ public final class Iterators {
    *     trailing null elements)
    * @throws IllegalArgumentException if {@code size} is nonpositive
    */
-  public static <T> UnmodifiableIterator<List<T>> paddedPartition(
-      Iterator<T> iterator, int size) {
+  public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
     return partitionImpl(iterator, size, true);
   }
 
@@ -616,6 +637,7 @@ public final class Iterators {
       public boolean hasNext() {
         return iterator.hasNext();
       }
+
       @Override
       public List<T> next() {
         if (!hasNext()) {
@@ -631,8 +653,7 @@ public final class Iterators {
         }
 
         @SuppressWarnings("unchecked") // we only put Ts in it
-        List<T> list = Collections.unmodifiableList(
-            (List<T>) Arrays.asList(array));
+        List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
         return (pad || count == size) ? list : list.subList(0, count);
       }
     };
@@ -641,12 +662,14 @@ public final class Iterators {
   /**
    * Returns the elements of {@code unfiltered} that satisfy a predicate.
    */
+  @CheckReturnValue
   public static <T> UnmodifiableIterator<T> filter(
       final Iterator<T> unfiltered, final Predicate<? super T> predicate) {
     checkNotNull(unfiltered);
     checkNotNull(predicate);
     return new AbstractIterator<T>() {
-      @Override protected T computeNext() {
+      @Override
+      protected T computeNext() {
         while (unfiltered.hasNext()) {
           T element = unfiltered.next();
           if (predicate.apply(element)) {
@@ -670,8 +693,8 @@ public final class Iterators {
    */
   @SuppressWarnings("unchecked") // can cast to <T> because non-Ts are removed
   @GwtIncompatible("Class.isInstance")
-  public static <T> UnmodifiableIterator<T> filter(
-      Iterator<?> unfiltered, Class<T> type) {
+  @CheckReturnValue
+  public static <T> UnmodifiableIterator<T> filter(Iterator<?> unfiltered, Class<T> type) {
     return (UnmodifiableIterator<T>) filter(unfiltered, instanceOf(type));
   }
 
@@ -679,8 +702,7 @@ public final class Iterators {
    * Returns {@code true} if one or more elements returned by {@code iterator}
    * satisfy the given predicate.
    */
-  public static <T> boolean any(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> boolean any(Iterator<T> iterator, Predicate<? super T> predicate) {
     return indexOf(iterator, predicate) != -1;
   }
 
@@ -689,8 +711,7 @@ public final class Iterators {
    * satisfies the given predicate. If {@code iterator} is empty, {@code true}
    * is returned.
    */
-  public static <T> boolean all(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> boolean all(Iterator<T> iterator, Predicate<? super T> predicate) {
     checkNotNull(predicate);
     while (iterator.hasNext()) {
       T element = iterator.next();
@@ -712,8 +733,7 @@ public final class Iterators {
    * @throws NoSuchElementException if no element in {@code iterator} matches
    *     the given predicate
    */
-  public static <T> T find(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> T find(Iterator<T> iterator, Predicate<? super T> predicate) {
     return filter(iterator, predicate).next();
   }
 
@@ -728,8 +748,8 @@ public final class Iterators {
    * @since 7.0
    */
   @Nullable
-  public static <T> T find(Iterator<? extends T> iterator, Predicate<? super T> predicate,
-      @Nullable T defaultValue) {
+  public static <T> T find(
+      Iterator<? extends T> iterator, Predicate<? super T> predicate, @Nullable T defaultValue) {
     return getNext(filter(iterator, predicate), defaultValue);
   }
 
@@ -746,8 +766,7 @@ public final class Iterators {
    *
    * @since 11.0
    */
-  public static <T> Optional<T> tryFind(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> Optional<T> tryFind(Iterator<T> iterator, Predicate<? super T> predicate) {
     UnmodifiableIterator<T> filteredIterator = filter(iterator, predicate);
     return filteredIterator.hasNext()
         ? Optional.of(filteredIterator.next())
@@ -770,8 +789,7 @@ public final class Iterators {
    *
    * @since 2.0
    */
-  public static <T> int indexOf(
-      Iterator<T> iterator, Predicate<? super T> predicate) {
+  public static <T> int indexOf(Iterator<T> iterator, Predicate<? super T> predicate) {
     checkNotNull(predicate, "predicate");
     for (int i = 0; iterator.hasNext(); i++) {
       T current = iterator.next();
@@ -790,8 +808,8 @@ public final class Iterators {
    * does. After a successful {@code remove()} call, {@code fromIterator} no
    * longer contains the corresponding element.
    */
-  public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator,
-      final Function<? super F, ? extends T> function) {
+  public static <F, T> Iterator<T> transform(
+      final Iterator<F> fromIterator, final Function<? super F, ? extends T> function) {
     checkNotNull(function);
     return new TransformedIterator<F, T>(fromIterator) {
       @Override
@@ -815,17 +833,19 @@ public final class Iterators {
     checkNonnegative(position);
     int skipped = advance(iterator, position);
     if (!iterator.hasNext()) {
-      throw new IndexOutOfBoundsException("position (" + position
-          + ") must be less than the number of elements that remained ("
-          + skipped + ")");
+      throw new IndexOutOfBoundsException(
+          "position ("
+              + position
+              + ") must be less than the number of elements that remained ("
+              + skipped
+              + ")");
     }
     return iterator.next();
   }
 
   static void checkNonnegative(int position) {
     if (position < 0) {
-      throw new IndexOutOfBoundsException("position (" + position
-          + ") must not be negative");
+      throw new IndexOutOfBoundsException("position (" + position + ") must not be negative");
     }
   }
 
@@ -923,8 +943,7 @@ public final class Iterators {
    * @throws IllegalArgumentException if {@code limitSize} is negative
    * @since 3.0
    */
-  public static <T> Iterator<T> limit(
-      final Iterator<T> iterator, final int limitSize) {
+  public static <T> Iterator<T> limit(final Iterator<T> iterator, final int limitSize) {
     checkNotNull(iterator);
     checkArgument(limitSize >= 0, "limit is negative");
     return new Iterator<T>() {
@@ -1056,7 +1075,8 @@ public final class Iterators {
      * past the beginning of the iteration.
      */
     return new AbstractIndexedListIterator<T>(length, index) {
-      @Override protected T get(int index) {
+      @Override
+      protected T get(int index) {
         return array[offset + index];
       }
     };
@@ -1068,14 +1088,15 @@ public final class Iterators {
    * <p>The {@link Iterable} equivalent of this method is {@link
    * Collections#singleton}.
    */
-  public static <T> UnmodifiableIterator<T> singletonIterator(
-      @Nullable final T value) {
+  public static <T> UnmodifiableIterator<T> singletonIterator(@Nullable final T value) {
     return new UnmodifiableIterator<T>() {
       boolean done;
+
       @Override
       public boolean hasNext() {
         return !done;
       }
+
       @Override
       public T next() {
         if (done) {
@@ -1095,14 +1116,14 @@ public final class Iterators {
    * contents can be <i>copied</i> into a collection using {@link
    * Collections#list}.
    */
-  public static <T> UnmodifiableIterator<T> forEnumeration(
-      final Enumeration<T> enumeration) {
+  public static <T> UnmodifiableIterator<T> forEnumeration(final Enumeration<T> enumeration) {
     checkNotNull(enumeration);
     return new UnmodifiableIterator<T>() {
       @Override
       public boolean hasNext() {
         return enumeration.hasMoreElements();
       }
+
       @Override
       public T next() {
         return enumeration.nextElement();
@@ -1124,6 +1145,7 @@ public final class Iterators {
       public boolean hasMoreElements() {
         return iterator.hasNext();
       }
+
       @Override
       public T nextElement() {
         return iterator.next();
@@ -1214,8 +1236,7 @@ public final class Iterators {
    *     additional {@link PeekingIterator#peek()} method, this iterator behaves
    *     exactly the same as {@code iterator}.
    */
-  public static <T> PeekingIterator<T> peekingIterator(
-      Iterator<? extends T> iterator) {
+  public static <T> PeekingIterator<T> peekingIterator(Iterator<? extends T> iterator) {
     if (iterator instanceof PeekingImpl) {
       // Safe to cast <? extends T> to <T> because PeekingImpl only uses T
       // covariantly (and cannot be subclassed to add non-covariant uses).
@@ -1232,8 +1253,8 @@ public final class Iterators {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <T> PeekingIterator<T> peekingIterator(
-      PeekingIterator<T> iterator) {
+  @Deprecated
+  public static <T> PeekingIterator<T> peekingIterator(PeekingIterator<T> iterator) {
     return checkNotNull(iterator);
   }
 
@@ -1252,8 +1273,7 @@ public final class Iterators {
    */
   @Beta
   public static <T> UnmodifiableIterator<T> mergeSorted(
-      Iterable<? extends Iterator<? extends T>> iterators,
-      Comparator<? super T> comparator) {
+      Iterable<? extends Iterator<? extends T>> iterators, Comparator<? super T> comparator) {
     checkNotNull(iterators, "iterators");
     checkNotNull(comparator, "comparator");
 
@@ -1272,7 +1292,8 @@ public final class Iterators {
   private static class MergingIterator<T> extends UnmodifiableIterator<T> {
     final Queue<PeekingIterator<T>> queue;
 
-    public MergingIterator(Iterable<? extends Iterator<? extends T>> iterators,
+    public MergingIterator(
+        Iterable<? extends Iterator<? extends T>> iterators,
         final Comparator<? super T> itemComparator) {
       // A comparator that's used by the heap, allowing the heap
       // to be sorted based on the top of each iterator.
diff --git a/guava/src/com/google/common/collect/LexicographicalOrdering.java b/guava/src/com/google/common/collect/LexicographicalOrdering.java
index 0d993e4..801af6d 100644
--- a/guava/src/com/google/common/collect/LexicographicalOrdering.java
+++ b/guava/src/com/google/common/collect/LexicographicalOrdering.java
@@ -19,6 +19,7 @@ package com.google.common.collect;
 import com.google.common.annotations.GwtCompatible;
 
 import java.io.Serializable;
+import java.util.Comparator;
 import java.util.Iterator;
 
 import javax.annotation.Nullable;
@@ -28,16 +29,15 @@ import javax.annotation.Nullable;
  * pairwise.
  */
 @GwtCompatible(serializable = true)
-final class LexicographicalOrdering<T>
-    extends Ordering<Iterable<T>> implements Serializable {
-  final Ordering<? super T> elementOrder;
+final class LexicographicalOrdering<T> extends Ordering<Iterable<T>> implements Serializable {
+  final Comparator<? super T> elementOrder;
 
-  LexicographicalOrdering(Ordering<? super T> elementOrder) {
+  LexicographicalOrdering(Comparator<? super T> elementOrder) {
     this.elementOrder = elementOrder;
   }
 
-  @Override public int compare(
-      Iterable<T> leftIterable, Iterable<T> rightIterable) {
+  @Override
+  public int compare(Iterable<T> leftIterable, Iterable<T> rightIterable) {
     Iterator<T> left = leftIterable.iterator();
     Iterator<T> right = rightIterable.iterator();
     while (left.hasNext()) {
@@ -55,7 +55,8 @@ final class LexicographicalOrdering<T>
     return 0;
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -66,11 +67,13 @@ final class LexicographicalOrdering<T>
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return elementOrder.hashCode() ^ 2075626741; // meaningless
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return elementOrder + ".lexicographical()";
   }
 
diff --git a/guava/src/com/google/common/collect/LinkedHashMultimap.java b/guava/src/com/google/common/collect/LinkedHashMultimap.java
index 19bc620..0893619 100644
--- a/guava/src/com/google/common/collect/LinkedHashMultimap.java
+++ b/guava/src/com/google/common/collect/LinkedHashMultimap.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -71,12 +72,12 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedSetMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@@ -98,11 +99,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * @throws IllegalArgumentException if {@code expectedKeys} or {@code
    *      expectedValuesPerKey} is negative
    */
-  public static <K, V> LinkedHashMultimap<K, V> create(
-      int expectedKeys, int expectedValuesPerKey) {
+  public static <K, V> LinkedHashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
     return new LinkedHashMultimap<K, V>(
-        Maps.capacity(expectedKeys),
-        Maps.capacity(expectedValuesPerKey));
+        Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey));
   }
 
   /**
@@ -123,9 +122,11 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
 
   private interface ValueSetLink<K, V> {
     ValueSetLink<K, V> getPredecessorInValueSet();
+
     ValueSetLink<K, V> getSuccessorInValueSet();
 
     void setPredecessorInValueSet(ValueSetLink<K, V> entry);
+
     void setSuccessorInValueSet(ValueSetLink<K, V> entry);
   }
 
@@ -134,8 +135,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     succ.setPredecessorInValueSet(pred);
   }
 
-  private static <K, V> void succeedsInMultimap(
-      ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
+  private static <K, V> void succeedsInMultimap(ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
     pred.setSuccessorInMultimap(succ);
     succ.setPredecessorInMultimap(pred);
   }
@@ -155,8 +155,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * in the LinkedHashMultimap as a whole.
    */
   @VisibleForTesting
-  static final class ValueEntry<K, V> extends ImmutableEntry<K, V>
-      implements ValueSetLink<K, V> {
+  static final class ValueEntry<K, V> extends ImmutableEntry<K, V> implements ValueSetLink<K, V> {
     final int smearedValueHash;
 
     @Nullable ValueEntry<K, V> nextInValueBucket;
@@ -167,13 +166,16 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     ValueEntry<K, V> predecessorInMultimap;
     ValueEntry<K, V> successorInMultimap;
 
-    ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash,
+    ValueEntry(
+        @Nullable K key,
+        @Nullable V value,
+        int smearedValueHash,
         @Nullable ValueEntry<K, V> nextInValueBucket) {
       super(key, value);
       this.smearedValueHash = smearedValueHash;
       this.nextInValueBucket = nextInValueBucket;
     }
-    
+
     boolean matchesValue(@Nullable Object v, int smearedVHash) {
       return smearedValueHash == smearedVHash && Objects.equal(getValue(), v);
     }
@@ -284,7 +286,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * multimap, taken at the time the entry is returned by a method call to the
    * collection or its iterator.
    */
-  @Override public Set<Map.Entry<K, V>> entries() {
+  @Override
+  public Set<Map.Entry<K, V>> entries() {
     return super.entries();
   }
 
@@ -295,11 +298,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
    * <p>The iterator generated by the returned collection traverses the values
    * in the order they were added to the multimap.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
   @VisibleForTesting
+  @WeakOuter
   final class ValueSet extends Sets.ImprovedAbstractSet<V> implements ValueSetLink<K, V> {
     /*
      * We currently use a fixed load factor of 1.0, a bit higher than normal to reduce memory
@@ -322,12 +327,12 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       this.lastEntry = this;
       // Round expected values up to a power of 2 to get the table size.
       int tableSize = Hashing.closedTableSize(expectedValues, VALUE_SET_LOAD_FACTOR);
-      
+
       @SuppressWarnings("unchecked")
       ValueEntry<K, V>[] hashTable = new ValueEntry[tableSize];
       this.hashTable = hashTable;
     }
-    
+
     private int mask() {
       return hashTable.length - 1;
     }
@@ -402,7 +407,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
     @Override
     public boolean contains(@Nullable Object o) {
       int smearedHash = Hashing.smearedHash(o);
-      for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()]; entry != null;
+      for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()];
+          entry != null;
           entry = entry.nextInValueBucket) {
         if (entry.matchesValue(o, smearedHash)) {
           return true;
@@ -416,8 +422,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       int smearedHash = Hashing.smearedHash(value);
       int bucket = smearedHash & mask();
       ValueEntry<K, V> rowHead = hashTable[bucket];
-      for (ValueEntry<K, V> entry = rowHead; entry != null;
-          entry = entry.nextInValueBucket) {
+      for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
         if (entry.matchesValue(value, smearedHash)) {
           return false;
         }
@@ -442,7 +447,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
         this.hashTable = hashTable;
         int mask = hashTable.length - 1;
         for (ValueSetLink<K, V> entry = firstEntry;
-            entry != this; entry = entry.getSuccessorInValueSet()) {
+            entry != this;
+            entry = entry.getSuccessorInValueSet()) {
           ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
           int bucket = valueEntry.smearedValueHash & mask;
           valueEntry.nextInValueBucket = hashTable[bucket];
@@ -456,8 +462,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       int smearedHash = Hashing.smearedHash(o);
       int bucket = smearedHash & mask();
       ValueEntry<K, V> prev = null;
-      for (ValueEntry<K, V> entry = hashTable[bucket]; entry != null;
-           prev = entry, entry = entry.nextInValueBucket) {
+      for (ValueEntry<K, V> entry = hashTable[bucket];
+          entry != null;
+          prev = entry, entry = entry.nextInValueBucket) {
         if (entry.matchesValue(o, smearedHash)) {
           if (prev == null) {
             // first entry in the bucket
@@ -480,7 +487,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       Arrays.fill(hashTable, null);
       size = 0;
       for (ValueSetLink<K, V> entry = firstEntry;
-           entry != this; entry = entry.getSuccessorInValueSet()) {
+          entry != this;
+          entry = entry.getSuccessorInValueSet()) {
         ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
         deleteFromMultimap(valueEntry);
       }
@@ -519,7 +527,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
       }
     };
   }
-  
+
   @Override
   Iterator<V> valueIterator() {
     return Maps.valueIterator(entryIterator());
@@ -538,7 +546,6 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   @GwtIncompatible("java.io.ObjectOutputStream")
   private void writeObject(ObjectOutputStream stream) throws IOException {
     stream.defaultWriteObject();
-    stream.writeInt(valueSetCapacity);
     stream.writeInt(keySet().size());
     for (K key : keySet()) {
       stream.writeObject(key);
@@ -551,15 +558,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     multimapHeaderEntry = new ValueEntry<K, V>(null, null, 0, null);
     succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry);
-    valueSetCapacity = stream.readInt();
+    valueSetCapacity = DEFAULT_VALUE_SET_CAPACITY;
     int distinctKeys = stream.readInt();
-    Map<K, Collection<V>> map =
-        new LinkedHashMap<K, Collection<V>>(Maps.capacity(distinctKeys));
+    Map<K, Collection<V>> map = new LinkedHashMap<K, Collection<V>>();
     for (int i = 0; i < distinctKeys; i++) {
       @SuppressWarnings("unchecked")
       K key = (K) stream.readObject();
diff --git a/guava/src/com/google/common/collect/LinkedHashMultiset.java b/guava/src/com/google/common/collect/LinkedHashMultiset.java
index 9b8c45b..e597236 100644
--- a/guava/src/com/google/common/collect/LinkedHashMultiset.java
+++ b/guava/src/com/google/common/collect/LinkedHashMultiset.java
@@ -31,14 +31,14 @@ import java.util.LinkedHashMap;
  * element, those instances are consecutive in the iteration order. If all
  * occurrences of an element are removed, after which that element is added to
  * the multiset, the element will appear at the end of the iteration.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // we're overriding default serialization
@@ -71,10 +71,8 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
    *
    * @param elements the elements that the multiset should contain
    */
-  public static <E> LinkedHashMultiset<E> create(
-      Iterable<? extends E> elements) {
-    LinkedHashMultiset<E> multiset =
-        create(Multisets.inferDistinctElements(elements));
+  public static <E> LinkedHashMultiset<E> create(Iterable<? extends E> elements) {
+    LinkedHashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
     Iterables.addAll(multiset, elements);
     return multiset;
   }
@@ -84,8 +82,7 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
   }
 
   private LinkedHashMultiset(int distinctElements) {
-    // Could use newLinkedHashMapWithExpectedSize() if it existed
-    super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
+    super(Maps.<E, Count>newLinkedHashMapWithExpectedSize(distinctElements));
   }
 
   /**
@@ -99,12 +96,10 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     int distinctElements = Serialization.readCount(stream);
-    setBackingMap(new LinkedHashMap<E, Count>(
-        Maps.capacity(distinctElements)));
+    setBackingMap(new LinkedHashMap<E, Count>());
     Serialization.populateMultiset(this, stream, distinctElements);
   }
 
diff --git a/guava/src/com/google/common/collect/LinkedListMultimap.java b/guava/src/com/google/common/collect/LinkedListMultimap.java
index 30969f3..99c8ffa 100644
--- a/guava/src/com/google/common/collect/LinkedListMultimap.java
+++ b/guava/src/com/google/common/collect/LinkedListMultimap.java
@@ -23,6 +23,7 @@ import static java.util.Collections.unmodifiableList;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -92,11 +93,11 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedListMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@@ -138,12 +139,12 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       return result;
     }
   }
-  
+
   private static class KeyList<K, V> {
     Node<K, V> head;
     Node<K, V> tail;
     int count;
-    
+
     KeyList(Node<K, V> firstNode) {
       this.head = firstNode;
       this.tail = firstNode;
@@ -157,7 +158,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
   private transient Node<K, V> tail; // the tail for all keys
   private transient Map<K, KeyList<K, V>> keyToKeyList;
   private transient int size;
-  
+
   /*
    * Tracks modifications to keyToKeyList so that addition or removal of keys invalidates
    * preexisting iterators. This does *not* track simple additions and removals of values
@@ -215,8 +216,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
    * nextSibling} is null. Note: if {@code nextSibling} is specified, it MUST be
    * for an node for the same {@code key}!
    */
-  private Node<K, V> addNode(
-      @Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
+  private Node<K, V> addNode(@Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
     Node<K, V> node = new Node<K, V>(key, value);
     if (head == null) { // empty list
       head = tail = node;
@@ -290,7 +290,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       } else {
         node.previousSibling.nextSibling = node.nextSibling;
       }
-      
+
       if (node.nextSibling == null) {
         keyList.tail = node.previousSibling;
       } else {
@@ -337,16 +337,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       }
       current = null;
     }
+
     private void checkForConcurrentModification() {
       if (modCount != expectedModCount) {
         throw new ConcurrentModificationException();
       }
     }
+
     @Override
     public boolean hasNext() {
       checkForConcurrentModification();
       return next != null;
     }
+
     @Override
     public Node<K, V> next() {
       checkForConcurrentModification();
@@ -356,6 +359,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       nextIndex++;
       return current;
     }
+
     @Override
     public void remove() {
       checkForConcurrentModification();
@@ -370,11 +374,13 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       current = null;
       expectedModCount = modCount;
     }
+
     @Override
     public boolean hasPrevious() {
       checkForConcurrentModification();
       return previous != null;
     }
+
     @Override
     public Node<K, V> previous() {
       checkForConcurrentModification();
@@ -384,22 +390,27 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       nextIndex--;
       return current;
     }
+
     @Override
     public int nextIndex() {
       return nextIndex;
     }
+
     @Override
     public int previousIndex() {
       return nextIndex - 1;
     }
+
     @Override
     public void set(Entry<K, V> e) {
       throw new UnsupportedOperationException();
     }
+
     @Override
     public void add(Entry<K, V> e) {
       throw new UnsupportedOperationException();
     }
+
     void setValue(V value) {
       checkState(current != null);
       current.value = value;
@@ -412,17 +423,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
     Node<K, V> next = head;
     Node<K, V> current;
     int expectedModCount = modCount;
-    
+
     private void checkForConcurrentModification() {
       if (modCount != expectedModCount) {
         throw new ConcurrentModificationException();
       }
     }
+
     @Override
     public boolean hasNext() {
       checkForConcurrentModification();
       return next != null;
     }
+
     @Override
     public K next() {
       checkForConcurrentModification();
@@ -434,6 +447,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
       } while ((next != null) && !seenKeys.add(next.key));
       return current.key;
     }
+
     @Override
     public void remove() {
       checkForConcurrentModification();
@@ -669,11 +683,14 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
   @Override
   public List<V> get(final @Nullable K key) {
     return new AbstractSequentialList<V>() {
-      @Override public int size() {
+      @Override
+      public int size() {
         KeyList<K, V> keyList = keyToKeyList.get(key);
         return (keyList == null) ? 0 : keyList.count;
       }
-      @Override public ListIterator<V> listIterator(int index) {
+
+      @Override
+      public ListIterator<V> listIterator(int index) {
         return new ValueForKeyIterator(key, index);
       }
     };
@@ -681,21 +698,29 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   Set<K> createKeySet() {
-    return new Sets.ImprovedAbstractSet<K>() {
-      @Override public int size() {
+    @WeakOuter
+    class KeySetImpl extends Sets.ImprovedAbstractSet<K> {
+      @Override
+      public int size() {
         return keyToKeyList.size();
       }
-      @Override public Iterator<K> iterator() {
+
+      @Override
+      public Iterator<K> iterator() {
         return new DistinctKeyIterator();
       }
-      @Override public boolean contains(Object key) { // for performance
+
+      @Override
+      public boolean contains(Object key) { // for performance
         return containsKey(key);
       }
+
       @Override
       public boolean remove(Object o) { // for performance
         return !LinkedListMultimap.this.removeAll(o).isEmpty();
       }
-    };
+    }
+    return new KeySetImpl();
   }
 
   /**
@@ -714,12 +739,15 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   List<V> createValues() {
-    return new AbstractSequentialList<V>() {
-      @Override public int size() {
+    @WeakOuter
+    class ValuesImpl extends AbstractSequentialList<V> {
+      @Override
+      public int size() {
         return size;
       }
 
-      @Override public ListIterator<V> listIterator(int index) {
+      @Override
+      public ListIterator<V> listIterator(int index) {
         final NodeIterator nodeItr = new NodeIterator(index);
         return new TransformedListIterator<Entry<K, V>, V>(nodeItr) {
           @Override
@@ -733,7 +761,8 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
           }
         };
       }
-    };
+    }
+    return new ValuesImpl();
   }
 
   /**
@@ -761,15 +790,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
 
   @Override
   List<Entry<K, V>> createEntries() {
-    return new AbstractSequentialList<Entry<K, V>>() {
-      @Override public int size() {
+    @WeakOuter
+    class EntriesImpl extends AbstractSequentialList<Entry<K, V>> {
+      @Override
+      public int size() {
         return size;
       }
 
-      @Override public ListIterator<Entry<K, V>> listIterator(int index) {
+      @Override
+      public ListIterator<Entry<K, V>> listIterator(int index) {
         return new NodeIterator(index);
       }
-    };
+    }
+    return new EntriesImpl();
   }
 
   @Override
@@ -798,8 +831,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
   }
 
   @GwtIncompatible("java.io.ObjectInputStream")
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     keyToKeyList = Maps.newLinkedHashMap();
     int size = stream.readInt();
diff --git a/guava/src/com/google/common/collect/ListMultimap.java b/guava/src/com/google/common/collect/ListMultimap.java
index b76671e..c281c6c 100644
--- a/guava/src/com/google/common/collect/ListMultimap.java
+++ b/guava/src/com/google/common/collect/ListMultimap.java
@@ -32,13 +32,13 @@ import javax.annotation.Nullable;
  * <p>The {@link #get}, {@link #removeAll}, and {@link #replaceValues} methods
  * each return a {@link List} of values. Though the method signature doesn't say
  * so explicitly, the map returned by {@link #asMap} has {@code List} values.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface ListMultimap<K, V> extends Multimap<K, V> {
diff --git a/guava/src/com/google/common/collect/Lists.java b/guava/src/com/google/common/collect/Lists.java
index c77a5fc..edf7651 100644
--- a/guava/src/com/google/common/collect/Lists.java
+++ b/guava/src/com/google/common/collect/Lists.java
@@ -50,6 +50,7 @@ import java.util.NoSuchElementException;
 import java.util.RandomAccess;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -57,13 +58,13 @@ import javax.annotation.Nullable;
  * class's counterparts {@link Sets}, {@link Maps} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Lists">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#lists">
  * {@code Lists}</a>.
  *
  * @author Kevin Bourrillion
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Lists {
@@ -115,7 +116,8 @@ public final class Lists {
     return list;
   }
 
-  @VisibleForTesting static int computeArrayListCapacity(int arraySize) {
+  @VisibleForTesting
+  static int computeArrayListCapacity(int arraySize) {
     checkNonnegative(arraySize, "arraySize");
 
     // TODO(kevinb): Figure out the right behavior, and document it
@@ -180,8 +182,7 @@ public final class Lists {
    * @throws IllegalArgumentException if {@code initialArraySize} is negative
    */
   @GwtCompatible(serializable = true)
-  public static <E> ArrayList<E> newArrayListWithCapacity(
-      int initialArraySize) {
+  public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
     checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
     return new ArrayList<E>(initialArraySize);
   }
@@ -203,8 +204,7 @@ public final class Lists {
    * @throws IllegalArgumentException if {@code estimatedSize} is negative
    */
   @GwtCompatible(serializable = true)
-  public static <E> ArrayList<E> newArrayListWithExpectedSize(
-      int estimatedSize) {
+  public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
     return new ArrayList<E>(computeArrayListCapacity(estimatedSize));
   }
 
@@ -253,8 +253,7 @@ public final class Lists {
    * advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
    */
   @GwtCompatible(serializable = true)
-  public static <E> LinkedList<E> newLinkedList(
-      Iterable<? extends E> elements) {
+  public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
     LinkedList<E> list = newLinkedList();
     Iterables.addAll(list, elements);
     return list;
@@ -286,9 +285,10 @@ public final class Lists {
       Iterable<? extends E> elements) {
     // We copy elements to an ArrayList first, rather than incurring the
     // quadratic cost of adding them to the COWAL directly.
-    Collection<? extends E> elementsCollection = (elements instanceof Collection)
-        ? Collections2.cast(elements)
-        : newArrayList(elements);
+    Collection<? extends E> elementsCollection =
+        (elements instanceof Collection)
+            ? Collections2.cast(elements)
+            : newArrayList(elements);
     return new CopyOnWriteArrayList<E>(elementsCollection);
   }
 
@@ -322,14 +322,19 @@ public final class Lists {
       this.first = first;
       this.rest = checkNotNull(rest);
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return rest.length + 1;
     }
-    @Override public E get(int index) {
+
+    @Override
+    public E get(int index) {
       // check explicitly so the IOOBE will have the right message
       checkElementIndex(index, size());
       return (index == 0) ? first : rest[index - 1];
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -350,8 +355,7 @@ public final class Lists {
    * @param rest an array of additional elements, possibly empty
    * @return an unmodifiable list containing the specified elements
    */
-  public static <E> List<E> asList(
-      @Nullable E first, @Nullable E second, E[] rest) {
+  public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
     return new TwoPlusArrayList<E>(first, second, rest);
   }
 
@@ -367,10 +371,14 @@ public final class Lists {
       this.second = second;
       this.rest = checkNotNull(rest);
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return rest.length + 2;
     }
-    @Override public E get(int index) {
+
+    @Override
+    public E get(int index) {
       switch (index) {
         case 0:
           return first;
@@ -382,6 +390,7 @@ public final class Lists {
           return rest[index - 2];
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -440,8 +449,9 @@ public final class Lists {
    *     be greater than {@link Integer#MAX_VALUE}
    * @throws NullPointerException if {@code lists}, any one of the {@code lists},
    *     or any element of a provided list is null
-   */ static <B> List<List<B>>
-      cartesianProduct(List<? extends List<? extends B>> lists) {
+   * @since 19.0
+   */
+  public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
     return CartesianList.create(lists);
   }
 
@@ -500,8 +510,9 @@ public final class Lists {
    *     be greater than {@link Integer#MAX_VALUE}
    * @throws NullPointerException if {@code lists}, any one of the
    *     {@code lists}, or any element of a provided list is null
-   */ static <B> List<List<B>>
-      cartesianProduct(List<? extends B>... lists) {
+   * @since 19.0
+   */
+  public static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
     return cartesianProduct(Arrays.asList(lists));
   }
 
@@ -538,6 +549,7 @@ public final class Lists {
    * then serialize the copy. Other methods similar to this do not implement
    * serialization at all for this reason.
    */
+  @CheckReturnValue
   public static <F, T> List<T> transform(
       List<F> fromList, Function<? super F, ? extends T> function) {
     return (fromList instanceof RandomAccess)
@@ -550,13 +562,12 @@ public final class Lists {
    *
    * @see Lists#transform
    */
-  private static class TransformingSequentialList<F, T>
-      extends AbstractSequentialList<T> implements Serializable {
+  private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
+      implements Serializable {
     final List<F> fromList;
     final Function<? super F, ? extends T> function;
 
-    TransformingSequentialList(
-        List<F> fromList, Function<? super F, ? extends T> function) {
+    TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
       this.fromList = checkNotNull(fromList);
       this.function = checkNotNull(function);
     }
@@ -565,13 +576,18 @@ public final class Lists {
      * each element which can be overkill. That's why we forward this call
      * directly to the backing list.
      */
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromList.clear();
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return fromList.size();
     }
-    @Override public ListIterator<T> listIterator(final int index) {
+
+    @Override
+    public ListIterator<T> listIterator(final int index) {
       return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
         @Override
         T transform(F from) {
@@ -591,26 +607,33 @@ public final class Lists {
    *
    * @see Lists#transform
    */
-  private static class TransformingRandomAccessList<F, T>
-      extends AbstractList<T> implements RandomAccess, Serializable {
+  private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
+      implements RandomAccess, Serializable {
     final List<F> fromList;
     final Function<? super F, ? extends T> function;
 
-    TransformingRandomAccessList(
-        List<F> fromList, Function<? super F, ? extends T> function) {
+    TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
       this.fromList = checkNotNull(fromList);
       this.function = checkNotNull(function);
     }
-    @Override public void clear() {
+
+    @Override
+    public void clear() {
       fromList.clear();
     }
-    @Override public T get(int index) {
+
+    @Override
+    public T get(int index) {
       return function.apply(fromList.get(index));
     }
-    @Override public Iterator<T> iterator() {
+
+    @Override
+    public Iterator<T> iterator() {
       return listIterator();
     }
-    @Override public ListIterator<T> listIterator(int index) {
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
       return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
         @Override
         T transform(F from) {
@@ -618,15 +641,22 @@ public final class Lists {
         }
       };
     }
-    @Override public boolean isEmpty() {
+
+    @Override
+    public boolean isEmpty() {
       return fromList.isEmpty();
     }
-    @Override public T remove(int index) {
+
+    @Override
+    public T remove(int index) {
       return function.apply(fromList.remove(index));
     }
-    @Override public int size() {
+
+    @Override
+    public int size() {
       return fromList.size();
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -665,24 +695,26 @@ public final class Lists {
       this.size = size;
     }
 
-    @Override public List<T> get(int index) {
+    @Override
+    public List<T> get(int index) {
       checkElementIndex(index, size());
       int start = index * size;
       int end = Math.min(start + size, list.size());
       return list.subList(start, end);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return IntMath.divide(list.size(), size, RoundingMode.CEILING);
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return list.isEmpty();
     }
   }
 
-  private static class RandomAccessPartition<T> extends Partition<T>
-      implements RandomAccess {
+  private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
     RandomAccessPartition(List<T> list, int size) {
       super(list, size);
     }
@@ -694,13 +726,13 @@ public final class Lists {
    *
    * @since 7.0
    */
-  @Beta public static ImmutableList<Character> charactersOf(String string) {
+  @Beta
+  public static ImmutableList<Character> charactersOf(String string) {
     return new StringAsImmutableList(checkNotNull(string));
   }
 
   @SuppressWarnings("serial") // serialized using ImmutableList serialization
-  private static final class StringAsImmutableList
-      extends ImmutableList<Character> {
+  private static final class StringAsImmutableList extends ImmutableList<Character> {
 
     private final String string;
 
@@ -708,32 +740,35 @@ public final class Lists {
       this.string = string;
     }
 
-    @Override public int indexOf(@Nullable Object object) {
-      return (object instanceof Character)
-          ? string.indexOf((Character) object) : -1;
+    @Override
+    public int indexOf(@Nullable Object object) {
+      return (object instanceof Character) ? string.indexOf((Character) object) : -1;
     }
 
-    @Override public int lastIndexOf(@Nullable Object object) {
-      return (object instanceof Character)
-          ? string.lastIndexOf((Character) object) : -1;
+    @Override
+    public int lastIndexOf(@Nullable Object object) {
+      return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
     }
 
-    @Override public ImmutableList<Character> subList(
-        int fromIndex, int toIndex) {
+    @Override
+    public ImmutableList<Character> subList(int fromIndex, int toIndex) {
       checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
       return charactersOf(string.substring(fromIndex, toIndex));
     }
 
-    @Override boolean isPartialView() {
+    @Override
+    boolean isPartialView() {
       return false;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size()); // for GWT
       return string.charAt(index);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return string.length();
     }
   }
@@ -749,24 +784,26 @@ public final class Lists {
    * @return an {@code List<Character>} view of the character sequence
    * @since 7.0
    */
-  @Beta public static List<Character> charactersOf(CharSequence sequence) {
+  @Beta
+  public static List<Character> charactersOf(CharSequence sequence) {
     return new CharSequenceAsList(checkNotNull(sequence));
   }
 
-  private static final class CharSequenceAsList
-      extends AbstractList<Character> {
+  private static final class CharSequenceAsList extends AbstractList<Character> {
     private final CharSequence sequence;
 
     CharSequenceAsList(CharSequence sequence) {
       this.sequence = sequence;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size()); // for GWT
       return sequence.charAt(index);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return sequence.length();
     }
   }
@@ -783,6 +820,7 @@ public final class Lists {
    *
    * @since 7.0
    */
+  @CheckReturnValue
   public static <T> List<T> reverse(List<T> list) {
     if (list instanceof ImmutableList) {
       return ((ImmutableList<T>) list).reverse();
@@ -818,66 +856,79 @@ public final class Lists {
       return size - index;
     }
 
-    @Override public void add(int index, @Nullable T element) {
+    @Override
+    public void add(int index, @Nullable T element) {
       forwardList.add(reversePosition(index), element);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       forwardList.clear();
     }
 
-    @Override public T remove(int index) {
+    @Override
+    public T remove(int index) {
       return forwardList.remove(reverseIndex(index));
     }
 
-    @Override protected void removeRange(int fromIndex, int toIndex) {
+    @Override
+    protected void removeRange(int fromIndex, int toIndex) {
       subList(fromIndex, toIndex).clear();
     }
 
-    @Override public T set(int index, @Nullable T element) {
+    @Override
+    public T set(int index, @Nullable T element) {
       return forwardList.set(reverseIndex(index), element);
     }
 
-    @Override public T get(int index) {
+    @Override
+    public T get(int index) {
       return forwardList.get(reverseIndex(index));
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return forwardList.size();
     }
 
-    @Override public List<T> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<T> subList(int fromIndex, int toIndex) {
       checkPositionIndexes(fromIndex, toIndex, size());
-      return reverse(forwardList.subList(
-          reversePosition(toIndex), reversePosition(fromIndex)));
+      return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
     }
 
-    @Override public Iterator<T> iterator() {
+    @Override
+    public Iterator<T> iterator() {
       return listIterator();
     }
 
-    @Override public ListIterator<T> listIterator(int index) {
+    @Override
+    public ListIterator<T> listIterator(int index) {
       int start = reversePosition(index);
       final ListIterator<T> forwardIterator = forwardList.listIterator(start);
       return new ListIterator<T>() {
 
         boolean canRemoveOrSet;
 
-        @Override public void add(T e) {
+        @Override
+        public void add(T e) {
           forwardIterator.add(e);
           forwardIterator.previous();
           canRemoveOrSet = false;
         }
 
-        @Override public boolean hasNext() {
+        @Override
+        public boolean hasNext() {
           return forwardIterator.hasPrevious();
         }
 
-        @Override public boolean hasPrevious() {
+        @Override
+        public boolean hasPrevious() {
           return forwardIterator.hasNext();
         }
 
-        @Override public T next() {
+        @Override
+        public T next() {
           if (!hasNext()) {
             throw new NoSuchElementException();
           }
@@ -885,11 +936,13 @@ public final class Lists {
           return forwardIterator.previous();
         }
 
-        @Override public int nextIndex() {
+        @Override
+        public int nextIndex() {
           return reversePosition(forwardIterator.nextIndex());
         }
 
-        @Override public T previous() {
+        @Override
+        public T previous() {
           if (!hasPrevious()) {
             throw new NoSuchElementException();
           }
@@ -897,17 +950,20 @@ public final class Lists {
           return forwardIterator.next();
         }
 
-        @Override public int previousIndex() {
+        @Override
+        public int previousIndex() {
           return nextIndex() - 1;
         }
 
-        @Override public void remove() {
+        @Override
+        public void remove() {
           checkRemove(canRemoveOrSet);
           forwardIterator.remove();
           canRemoveOrSet = false;
         }
 
-        @Override public void set(T e) {
+        @Override
+        public void set(T e) {
           checkState(canRemoveOrSet);
           forwardIterator.set(e);
         }
@@ -915,8 +971,7 @@ public final class Lists {
     }
   }
 
-  private static class RandomAccessReverseList<T> extends ReverseList<T>
-      implements RandomAccess {
+  private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
     RandomAccessReverseList(List<T> forwardList) {
       super(forwardList);
     }
@@ -926,7 +981,7 @@ public final class Lists {
    * An implementation of {@link List#hashCode()}.
    */
   static int hashCodeImpl(List<?> list) {
-    // TODO(user): worth optimizing for RandomAccess?
+    // TODO(lowasser): worth optimizing for RandomAccess?
     int hashCode = 1;
     for (Object o : list) {
       hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
@@ -940,25 +995,35 @@ public final class Lists {
   /**
    * An implementation of {@link List#equals(Object)}.
    */
-  static boolean equalsImpl(List<?> list, @Nullable Object object) {
-    if (object == checkNotNull(list)) {
+  static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
+    if (other == checkNotNull(thisList)) {
       return true;
     }
-    if (!(object instanceof List)) {
+    if (!(other instanceof List)) {
       return false;
     }
-
-    List<?> o = (List<?>) object;
-
-    return list.size() == o.size()
-        && Iterators.elementsEqual(list.iterator(), o.iterator());
+    List<?> otherList = (List<?>) other;
+    int size = thisList.size();
+    if (size != otherList.size()) {
+      return false;
+    }
+    if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
+      // avoid allocation and use the faster loop
+      for (int i = 0; i < size; i++) {
+        if (!Objects.equal(thisList.get(i), otherList.get(i))) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
+    }
   }
 
   /**
    * An implementation of {@link List#addAll(int, Collection)}.
    */
-  static <E> boolean addAllImpl(
-      List<E> list, int index, Iterable<? extends E> elements) {
+  static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
     boolean changed = false;
     ListIterator<E> listIterator = list.listIterator(index);
     for (E e : elements) {
@@ -972,10 +1037,32 @@ public final class Lists {
    * An implementation of {@link List#indexOf(Object)}.
    */
   static int indexOfImpl(List<?> list, @Nullable Object element) {
-    ListIterator<?> listIterator = list.listIterator();
-    while (listIterator.hasNext()) {
-      if (Objects.equal(element, listIterator.next())) {
-        return listIterator.previousIndex();
+    if (list instanceof RandomAccess) {
+      return indexOfRandomAccess(list, element);
+    } else {
+      ListIterator<?> listIterator = list.listIterator();
+      while (listIterator.hasNext()) {
+        if (Objects.equal(element, listIterator.next())) {
+          return listIterator.previousIndex();
+        }
+      }
+      return -1;
+    }
+  }
+
+  private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
+    int size = list.size();
+    if (element == null) {
+      for (int i = 0; i < size; i++) {
+        if (list.get(i) == null) {
+          return i;
+        }
+      }
+    } else {
+      for (int i = 0; i < size; i++) {
+        if (element.equals(list.get(i))) {
+          return i;
+        }
       }
     }
     return -1;
@@ -985,10 +1072,31 @@ public final class Lists {
    * An implementation of {@link List#lastIndexOf(Object)}.
    */
   static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
-    ListIterator<?> listIterator = list.listIterator(list.size());
-    while (listIterator.hasPrevious()) {
-      if (Objects.equal(element, listIterator.previous())) {
-        return listIterator.nextIndex();
+    if (list instanceof RandomAccess) {
+      return lastIndexOfRandomAccess(list, element);
+    } else {
+      ListIterator<?> listIterator = list.listIterator(list.size());
+      while (listIterator.hasPrevious()) {
+        if (Objects.equal(element, listIterator.previous())) {
+          return listIterator.nextIndex();
+        }
+      }
+      return -1;
+    }
+  }
+
+  private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
+    if (element == null) {
+      for (int i = list.size() - 1; i >= 0; i--) {
+        if (list.get(i) == null) {
+          return i;
+        }
+      }
+    } else {
+      for (int i = list.size() - 1; i >= 0; i--) {
+        if (element.equals(list.get(i))) {
+          return i;
+        }
       }
     }
     return -1;
@@ -1004,12 +1112,12 @@ public final class Lists {
   /**
    * An implementation of {@link List#subList(int, int)}.
    */
-  static <E> List<E> subListImpl(
-      final List<E> list, int fromIndex, int toIndex) {
+  static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
     List<E> wrapper;
     if (list instanceof RandomAccess) {
       wrapper = new RandomAccessListWrapper<E>(list) {
-        @Override public ListIterator<E> listIterator(int index) {
+        @Override
+        public ListIterator<E> listIterator(int index) {
           return backingList.listIterator(index);
         }
 
@@ -1017,7 +1125,8 @@ public final class Lists {
       };
     } else {
       wrapper = new AbstractListWrapper<E>(list) {
-        @Override public ListIterator<E> listIterator(int index) {
+        @Override
+        public ListIterator<E> listIterator(int index) {
           return backingList.listIterator(index);
         }
 
@@ -1034,37 +1143,44 @@ public final class Lists {
       this.backingList = checkNotNull(backingList);
     }
 
-    @Override public void add(int index, E element) {
+    @Override
+    public void add(int index, E element) {
       backingList.add(index, element);
     }
 
-    @Override public boolean addAll(int index, Collection<? extends E> c) {
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
       return backingList.addAll(index, c);
     }
 
-    @Override public E get(int index) {
+    @Override
+    public E get(int index) {
       return backingList.get(index);
     }
 
-    @Override public E remove(int index) {
+    @Override
+    public E remove(int index) {
       return backingList.remove(index);
     }
 
-    @Override public E set(int index, E element) {
+    @Override
+    public E set(int index, E element) {
       return backingList.set(index, element);
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return backingList.contains(o);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return backingList.size();
     }
   }
 
-  private static class RandomAccessListWrapper<E>
-      extends AbstractListWrapper<E> implements RandomAccess {
+  private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
+      implements RandomAccess {
     RandomAccessListWrapper(List<E> backingList) {
       super(backingList);
     }
diff --git a/guava/src/com/google/common/collect/MapConstraint.java b/guava/src/com/google/common/collect/MapConstraint.java
index 0f55bce..fb8f694 100644
--- a/guava/src/com/google/common/collect/MapConstraint.java
+++ b/guava/src/com/google/common/collect/MapConstraint.java
@@ -44,9 +44,15 @@ import javax.annotation.Nullable;
  * @see MapConstraints
  * @see Constraint
  * @since 3.0
+ * @deprecated Use {@link Preconditions} for basic checks. In place of
+ *     constrained maps, we encourage you to check your preconditions
+ *     explicitly instead of leaving that work to the map implementation.
+ *     For the specific case of rejecting null, consider {@link ImmutableMap}.
+ *     This class is scheduled for removal in Guava 20.0.
  */
 @GwtCompatible
 @Beta
+ at Deprecated
 public interface MapConstraint<K, V> {
   /**
    * Throws a suitable {@code RuntimeException} if the specified key or value is
diff --git a/guava/src/com/google/common/collect/MapConstraints.java b/guava/src/com/google/common/collect/MapConstraints.java
index 090625d..7b2636e 100644
--- a/guava/src/com/google/common/collect/MapConstraints.java
+++ b/guava/src/com/google/common/collect/MapConstraints.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Collection;
@@ -40,9 +41,15 @@ import javax.annotation.Nullable;
  * @see Constraints
  * @author Mike Bostock
  * @since 3.0
+ * @deprecated Use {@link Preconditions} for basic checks. In place of
+ *     constrained maps, we encourage you to check your preconditions
+ *     explicitly instead of leaving that work to the map implementation.
+ *     For the specific case of rejecting null, consider {@link ImmutableMap}.
+ *     This class is scheduled for removal in Guava 20.0.
  */
 @Beta
 @GwtCompatible
+ at Deprecated
 public final class MapConstraints {
   private MapConstraints() {}
 
@@ -64,7 +71,8 @@ public final class MapConstraints {
       checkNotNull(value);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Not null";
     }
   }
@@ -124,8 +132,7 @@ public final class MapConstraints {
    * @return a constrained view of the specified multimap
    */
   public static <K, V> ListMultimap<K, V> constrainedListMultimap(
-      ListMultimap<K, V> multimap,
-      MapConstraint<? super K, ? super V> constraint) {
+      ListMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
     return new ConstrainedListMultimap<K, V>(multimap, constraint);
   }
 
@@ -145,8 +152,7 @@ public final class MapConstraints {
    * @return a constrained view of the specified multimap
    */
   public static <K, V> SetMultimap<K, V> constrainedSetMultimap(
-      SetMultimap<K, V> multimap,
-      MapConstraint<? super K, ? super V> constraint) {
+      SetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
     return new ConstrainedSetMultimap<K, V>(multimap, constraint);
   }
 
@@ -166,8 +172,7 @@ public final class MapConstraints {
    * @return a constrained view of the specified multimap
    */
   public static <K, V> SortedSetMultimap<K, V> constrainedSortedSetMultimap(
-      SortedSetMultimap<K, V> multimap,
-      MapConstraint<? super K, ? super V> constraint) {
+      SortedSetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
     return new ConstrainedSortedSetMultimap<K, V>(multimap, constraint);
   }
 
@@ -181,15 +186,17 @@ public final class MapConstraints {
    * @return a constrained view of the specified entry
    */
   private static <K, V> Entry<K, V> constrainedEntry(
-      final Entry<K, V> entry,
-      final MapConstraint<? super K, ? super V> constraint) {
+      final Entry<K, V> entry, final MapConstraint<? super K, ? super V> constraint) {
     checkNotNull(entry);
     checkNotNull(constraint);
     return new ForwardingMapEntry<K, V>() {
-      @Override protected Entry<K, V> delegate() {
+      @Override
+      protected Entry<K, V> delegate() {
         return entry;
       }
-      @Override public V setValue(V value) {
+
+      @Override
+      public V setValue(V value) {
         constraint.checkKeyValue(getKey(), value);
         return entry.setValue(value);
       }
@@ -207,23 +214,26 @@ public final class MapConstraints {
    * @return a constrained view of the specified entry
    */
   private static <K, V> Entry<K, Collection<V>> constrainedAsMapEntry(
-      final Entry<K, Collection<V>> entry,
-      final MapConstraint<? super K, ? super V> constraint) {
+      final Entry<K, Collection<V>> entry, final MapConstraint<? super K, ? super V> constraint) {
     checkNotNull(entry);
     checkNotNull(constraint);
     return new ForwardingMapEntry<K, Collection<V>>() {
-      @Override protected Entry<K, Collection<V>> delegate() {
+      @Override
+      protected Entry<K, Collection<V>> delegate() {
         return entry;
       }
-      @Override public Collection<V> getValue() {
+
+      @Override
+      public Collection<V> getValue() {
         return Constraints.constrainedTypePreservingCollection(
-            entry.getValue(), new Constraint<V>() {
-          @Override
-          public V checkElement(V value) {
-            constraint.checkKeyValue(getKey(), value);
-            return value;
-          }
-        });
+            entry.getValue(),
+            new Constraint<V>() {
+              @Override
+              public V checkElement(V value) {
+                constraint.checkKeyValue(getKey(), value);
+                return value;
+              }
+            });
       }
     };
   }
@@ -241,8 +251,7 @@ public final class MapConstraints {
    * @return a constrained view of the entries
    */
   private static <K, V> Set<Entry<K, Collection<V>>> constrainedAsMapEntries(
-      Set<Entry<K, Collection<V>>> entries,
-      MapConstraint<? super K, ? super V> constraint) {
+      Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
     return new ConstrainedAsMapEntries<K, V>(entries, constraint);
   }
 
@@ -259,8 +268,7 @@ public final class MapConstraints {
    * @return a constrained view of the specified entries
    */
   private static <K, V> Collection<Entry<K, V>> constrainedEntries(
-      Collection<Entry<K, V>> entries,
-      MapConstraint<? super K, ? super V> constraint) {
+      Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
     if (entries instanceof Set) {
       return constrainedEntrySet((Set<Entry<K, V>>) entries, constraint);
     }
@@ -282,8 +290,7 @@ public final class MapConstraints {
    * @return a constrained view of the specified entries
    */
   private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
-      Set<Entry<K, V>> entries,
-      MapConstraint<? super K, ? super V> constraint) {
+      Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
     return new ConstrainedEntrySet<K, V>(entries, constraint);
   }
 
@@ -293,27 +300,33 @@ public final class MapConstraints {
     final MapConstraint<? super K, ? super V> constraint;
     private transient Set<Entry<K, V>> entrySet;
 
-    ConstrainedMap(
-        Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
+    ConstrainedMap(Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
       this.delegate = checkNotNull(delegate);
       this.constraint = checkNotNull(constraint);
     }
-    @Override protected Map<K, V> delegate() {
+
+    @Override
+    protected Map<K, V> delegate() {
       return delegate;
     }
-    @Override public Set<Entry<K, V>> entrySet() {
+
+    @Override
+    public Set<Entry<K, V>> entrySet() {
       Set<Entry<K, V>> result = entrySet;
       if (result == null) {
-        entrySet = result =
-            constrainedEntrySet(delegate.entrySet(), constraint);
+        entrySet = result = constrainedEntrySet(delegate.entrySet(), constraint);
       }
       return result;
     }
-    @Override public V put(K key, V value) {
+
+    @Override
+    public V put(K key, V value) {
       constraint.checkKeyValue(key, value);
       return delegate.put(key, value);
     }
-    @Override public void putAll(Map<? extends K, ? extends V> map) {
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> map) {
       delegate.putAll(checkMap(map, constraint));
     }
   }
@@ -335,8 +348,7 @@ public final class MapConstraints {
   }
 
   /** @see MapConstraints#constrainedBiMap */
-  private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V>
-      implements BiMap<K, V> {
+  private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V> implements BiMap<K, V> {
     /*
      * We could switch to racy single-check lazy init and remove volatile, but
      * there's a downside. That's because this field is also written in the
@@ -351,13 +363,16 @@ public final class MapConstraints {
      */
     volatile BiMap<V, K> inverse;
 
-    ConstrainedBiMap(BiMap<K, V> delegate, @Nullable BiMap<V, K> inverse,
+    ConstrainedBiMap(
+        BiMap<K, V> delegate,
+        @Nullable BiMap<V, K> inverse,
         MapConstraint<? super K, ? super V> constraint) {
       super(delegate, constraint);
       this.inverse = inverse;
     }
 
-    @Override protected BiMap<K, V> delegate() {
+    @Override
+    protected BiMap<K, V> delegate() {
       return (BiMap<K, V>) super.delegate();
     }
 
@@ -370,13 +385,14 @@ public final class MapConstraints {
     @Override
     public BiMap<V, K> inverse() {
       if (inverse == null) {
-        inverse = new ConstrainedBiMap<V, K>(delegate().inverse(), this,
-            new InverseConstraint<V, K>(constraint));
+        inverse = new ConstrainedBiMap<V, K>(
+            delegate().inverse(), this, new InverseConstraint<V, K>(constraint));
       }
       return inverse;
     }
 
-    @Override public Set<V> values() {
+    @Override
+    public Set<V> values() {
       return delegate().values();
     }
   }
@@ -388,6 +404,7 @@ public final class MapConstraints {
     public InverseConstraint(MapConstraint<? super V, ? super K> constraint) {
       this.constraint = checkNotNull(constraint);
     }
+
     @Override
     public void checkKeyValue(K key, V value) {
       constraint.checkKeyValue(value, key);
@@ -395,47 +412,54 @@ public final class MapConstraints {
   }
 
   /** @see MapConstraints#constrainedMultimap */
-  private static class ConstrainedMultimap<K, V>
-      extends ForwardingMultimap<K, V> implements Serializable {
+  private static class ConstrainedMultimap<K, V> extends ForwardingMultimap<K, V>
+      implements Serializable {
     final MapConstraint<? super K, ? super V> constraint;
     final Multimap<K, V> delegate;
+
     transient Collection<Entry<K, V>> entries;
+
     transient Map<K, Collection<V>> asMap;
 
-    public ConstrainedMultimap(Multimap<K, V> delegate,
-        MapConstraint<? super K, ? super V> constraint) {
+    public ConstrainedMultimap(
+        Multimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
       this.delegate = checkNotNull(delegate);
       this.constraint = checkNotNull(constraint);
     }
 
-    @Override protected Multimap<K, V> delegate() {
+    @Override
+    protected Multimap<K, V> delegate() {
       return delegate;
     }
 
-    @Override public Map<K, Collection<V>> asMap() {
+    @Override
+    public Map<K, Collection<V>> asMap() {
       Map<K, Collection<V>> result = asMap;
       if (result == null) {
         final Map<K, Collection<V>> asMapDelegate = delegate.asMap();
 
-        asMap = result = new ForwardingMap<K, Collection<V>>() {
+        @WeakOuter
+        class AsMap extends ForwardingMap<K, Collection<V>> {
           Set<Entry<K, Collection<V>>> entrySet;
           Collection<Collection<V>> values;
 
-          @Override protected Map<K, Collection<V>> delegate() {
+          @Override
+          protected Map<K, Collection<V>> delegate() {
             return asMapDelegate;
           }
 
-          @Override public Set<Entry<K, Collection<V>>> entrySet() {
+          @Override
+          public Set<Entry<K, Collection<V>>> entrySet() {
             Set<Entry<K, Collection<V>>> result = entrySet;
             if (result == null) {
-              entrySet = result = constrainedAsMapEntries(
-                  asMapDelegate.entrySet(), constraint);
+              entrySet = result = constrainedAsMapEntries(asMapDelegate.entrySet(), constraint);
             }
             return result;
           }
 
           @SuppressWarnings("unchecked")
-          @Override public Collection<V> get(Object key) {
+          @Override
+          public Collection<V> get(Object key) {
             try {
               Collection<V> collection = ConstrainedMultimap.this.get((K) key);
               return collection.isEmpty() ? null : collection;
@@ -444,24 +468,27 @@ public final class MapConstraints {
             }
           }
 
-          @Override public Collection<Collection<V>> values() {
+          @Override
+          public Collection<Collection<V>> values() {
             Collection<Collection<V>> result = values;
             if (result == null) {
-              values = result = new ConstrainedAsMapValues<K, V>(
-                  delegate().values(), entrySet());
+              values = result = new ConstrainedAsMapValues<K, V>(delegate().values(), entrySet());
             }
             return result;
           }
 
-          @Override public boolean containsValue(Object o) {
+          @Override
+          public boolean containsValue(Object o) {
             return values().contains(o);
           }
-        };
+        }
+        asMap = result = new AsMap();
       }
       return result;
     }
 
-    @Override public Collection<Entry<K, V>> entries() {
+    @Override
+    public Collection<Entry<K, V>> entries() {
       Collection<Entry<K, V>> result = entries;
       if (result == null) {
         entries = result = constrainedEntries(delegate.entries(), constraint);
@@ -469,28 +496,32 @@ public final class MapConstraints {
       return result;
     }
 
-    @Override public Collection<V> get(final K key) {
+    @Override
+    public Collection<V> get(final K key) {
       return Constraints.constrainedTypePreservingCollection(
-          delegate.get(key), new Constraint<V>() {
-        @Override
-        public V checkElement(V value) {
-          constraint.checkKeyValue(key, value);
-          return value;
-        }
-      });
+          delegate.get(key),
+          new Constraint<V>() {
+            @Override
+            public V checkElement(V value) {
+              constraint.checkKeyValue(key, value);
+              return value;
+            }
+          });
     }
 
-    @Override public boolean put(K key, V value) {
+    @Override
+    public boolean put(K key, V value) {
       constraint.checkKeyValue(key, value);
       return delegate.put(key, value);
     }
 
-    @Override public boolean putAll(K key, Iterable<? extends V> values) {
+    @Override
+    public boolean putAll(K key, Iterable<? extends V> values) {
       return delegate.putAll(key, checkValues(key, values, constraint));
     }
 
-    @Override public boolean putAll(
-        Multimap<? extends K, ? extends V> multimap) {
+    @Override
+    public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
       boolean changed = false;
       for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
         changed |= put(entry.getKey(), entry.getValue());
@@ -498,15 +529,14 @@ public final class MapConstraints {
       return changed;
     }
 
-    @Override public Collection<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+    @Override
+    public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
       return delegate.replaceValues(key, checkValues(key, values, constraint));
     }
   }
 
   /** @see ConstrainedMultimap#asMap */
-  private static class ConstrainedAsMapValues<K, V>
-      extends ForwardingCollection<Collection<V>> {
+  private static class ConstrainedAsMapValues<K, V> extends ForwardingCollection<Collection<V>> {
     final Collection<Collection<V>> delegate;
     final Set<Entry<K, Collection<V>>> entrySet;
 
@@ -514,26 +544,31 @@ public final class MapConstraints {
      * @param entrySet map entries, linking each key with its corresponding
      *     values, that already enforce the constraint
      */
-    ConstrainedAsMapValues(Collection<Collection<V>> delegate,
-        Set<Entry<K, Collection<V>>> entrySet) {
+    ConstrainedAsMapValues(
+        Collection<Collection<V>> delegate, Set<Entry<K, Collection<V>>> entrySet) {
       this.delegate = delegate;
       this.entrySet = entrySet;
     }
-    @Override protected Collection<Collection<V>> delegate() {
+
+    @Override
+    protected Collection<Collection<V>> delegate() {
       return delegate;
     }
 
-    @Override public Iterator<Collection<V>> iterator() {
+    @Override
+    public Iterator<Collection<V>> iterator() {
       final Iterator<Entry<K, Collection<V>>> iterator = entrySet.iterator();
       return new Iterator<Collection<V>>() {
         @Override
         public boolean hasNext() {
           return iterator.hasNext();
         }
+
         @Override
         public Collection<V> next() {
           return iterator.next().getValue();
         }
+
         @Override
         public void remove() {
           iterator.remove();
@@ -541,231 +576,282 @@ public final class MapConstraints {
       };
     }
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       return standardContains(o);
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
-    @Override public boolean remove(Object o) {
+
+    @Override
+    public boolean remove(Object o) {
       return standardRemove(o);
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       return standardRemoveAll(c);
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       return standardRetainAll(c);
     }
   }
 
   /** @see MapConstraints#constrainedEntries */
-  private static class ConstrainedEntries<K, V>
-      extends ForwardingCollection<Entry<K, V>> {
+  private static class ConstrainedEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
     final MapConstraint<? super K, ? super V> constraint;
     final Collection<Entry<K, V>> entries;
 
-    ConstrainedEntries(Collection<Entry<K, V>> entries,
-        MapConstraint<? super K, ? super V> constraint) {
+    ConstrainedEntries(
+        Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
       this.entries = entries;
       this.constraint = constraint;
     }
-    @Override protected Collection<Entry<K, V>> delegate() {
+
+    @Override
+    protected Collection<Entry<K, V>> delegate() {
       return entries;
     }
 
-    @Override public Iterator<Entry<K, V>> iterator() {
-      final Iterator<Entry<K, V>> iterator = entries.iterator();
-      return new ForwardingIterator<Entry<K, V>>() {
-        @Override public Entry<K, V> next() {
-          return constrainedEntry(iterator.next(), constraint);
-        }
-        @Override protected Iterator<Entry<K, V>> delegate() {
-          return iterator;
+    @Override
+    public Iterator<Entry<K, V>> iterator() {
+      return new TransformedIterator<Entry<K, V>, Entry<K, V>>(entries.iterator()) {
+        @Override
+        Entry<K, V> transform(Entry<K, V> from) {
+          return constrainedEntry(from, constraint);
         }
       };
     }
 
     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       return Maps.containsEntryImpl(delegate(), o);
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
-    @Override public boolean remove(Object o) {
+
+    @Override
+    public boolean remove(Object o) {
       return Maps.removeEntryImpl(delegate(), o);
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       return standardRemoveAll(c);
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       return standardRetainAll(c);
     }
   }
 
   /** @see MapConstraints#constrainedEntrySet */
-  static class ConstrainedEntrySet<K, V>
-      extends ConstrainedEntries<K, V> implements Set<Entry<K, V>> {
-    ConstrainedEntrySet(Set<Entry<K, V>> entries,
-        MapConstraint<? super K, ? super V> constraint) {
+  static class ConstrainedEntrySet<K, V> extends ConstrainedEntries<K, V>
+      implements Set<Entry<K, V>> {
+    ConstrainedEntrySet(Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
       super(entries, constraint);
     }
 
     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return Sets.equalsImpl(this, object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Sets.hashCodeImpl(this);
     }
   }
 
   /** @see MapConstraints#constrainedAsMapEntries */
-  static class ConstrainedAsMapEntries<K, V>
-      extends ForwardingSet<Entry<K, Collection<V>>> {
+  static class ConstrainedAsMapEntries<K, V> extends ForwardingSet<Entry<K, Collection<V>>> {
     private final MapConstraint<? super K, ? super V> constraint;
     private final Set<Entry<K, Collection<V>>> entries;
 
-    ConstrainedAsMapEntries(Set<Entry<K, Collection<V>>> entries,
-        MapConstraint<? super K, ? super V> constraint) {
+    ConstrainedAsMapEntries(
+        Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
       this.entries = entries;
       this.constraint = constraint;
     }
 
-    @Override protected Set<Entry<K, Collection<V>>> delegate() {
+    @Override
+    protected Set<Entry<K, Collection<V>>> delegate() {
       return entries;
     }
 
-    @Override public Iterator<Entry<K, Collection<V>>> iterator() {
-      final Iterator<Entry<K, Collection<V>>> iterator = entries.iterator();
-      return new ForwardingIterator<Entry<K, Collection<V>>>() {
-        @Override public Entry<K, Collection<V>> next() {
-          return constrainedAsMapEntry(iterator.next(), constraint);
-        }
-        @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
-          return iterator;
+    @Override
+    public Iterator<Entry<K, Collection<V>>> iterator() {
+      return new TransformedIterator<Entry<K, Collection<V>>, Entry<K, Collection<V>>>(
+          entries.iterator()) {
+        @Override
+        Entry<K, Collection<V>> transform(Entry<K, Collection<V>> from) {
+          return constrainedAsMapEntry(from, constraint);
         }
       };
     }
 
     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return Maps.containsEntryImpl(delegate(), o);
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return standardEquals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return standardHashCode();
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       return Maps.removeEntryImpl(delegate(), o);
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       return standardRemoveAll(c);
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       return standardRetainAll(c);
     }
   }
 
-  private static class ConstrainedListMultimap<K, V>
-      extends ConstrainedMultimap<K, V> implements ListMultimap<K, V> {
-    ConstrainedListMultimap(ListMultimap<K, V> delegate,
-        MapConstraint<? super K, ? super V> constraint) {
+  private static class ConstrainedListMultimap<K, V> extends ConstrainedMultimap<K, V>
+      implements ListMultimap<K, V> {
+    ConstrainedListMultimap(
+        ListMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
       super(delegate, constraint);
     }
-    @Override public List<V> get(K key) {
+
+    @Override
+    public List<V> get(K key) {
       return (List<V>) super.get(key);
     }
-    @Override public List<V> removeAll(Object key) {
+
+    @Override
+    public List<V> removeAll(Object key) {
       return (List<V>) super.removeAll(key);
     }
-    @Override public List<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public List<V> replaceValues(K key, Iterable<? extends V> values) {
       return (List<V>) super.replaceValues(key, values);
     }
   }
 
-  private static class ConstrainedSetMultimap<K, V>
-      extends ConstrainedMultimap<K, V> implements SetMultimap<K, V> {
-    ConstrainedSetMultimap(SetMultimap<K, V> delegate,
-        MapConstraint<? super K, ? super V> constraint) {
+  private static class ConstrainedSetMultimap<K, V> extends ConstrainedMultimap<K, V>
+      implements SetMultimap<K, V> {
+    ConstrainedSetMultimap(
+        SetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
       super(delegate, constraint);
     }
-    @Override public Set<V> get(K key) {
+
+    @Override
+    public Set<V> get(K key) {
       return (Set<V>) super.get(key);
     }
-    @Override public Set<Map.Entry<K, V>> entries() {
+
+    @Override
+    public Set<Map.Entry<K, V>> entries() {
       return (Set<Map.Entry<K, V>>) super.entries();
     }
-    @Override public Set<V> removeAll(Object key) {
+
+    @Override
+    public Set<V> removeAll(Object key) {
       return (Set<V>) super.removeAll(key);
     }
-    @Override public Set<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
       return (Set<V>) super.replaceValues(key, values);
     }
   }
 
-  private static class ConstrainedSortedSetMultimap<K, V>
-      extends ConstrainedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
-    ConstrainedSortedSetMultimap(SortedSetMultimap<K, V> delegate,
-        MapConstraint<? super K, ? super V> constraint) {
+  private static class ConstrainedSortedSetMultimap<K, V> extends ConstrainedSetMultimap<K, V>
+      implements SortedSetMultimap<K, V> {
+    ConstrainedSortedSetMultimap(
+        SortedSetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
       super(delegate, constraint);
     }
-    @Override public SortedSet<V> get(K key) {
+
+    @Override
+    public SortedSet<V> get(K key) {
       return (SortedSet<V>) super.get(key);
     }
-    @Override public SortedSet<V> removeAll(Object key) {
+
+    @Override
+    public SortedSet<V> removeAll(Object key) {
       return (SortedSet<V>) super.removeAll(key);
     }
-    @Override public SortedSet<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
       return (SortedSet<V>) super.replaceValues(key, values);
     }
+
     @Override
     public Comparator<? super V> valueComparator() {
       return ((SortedSetMultimap<K, V>) delegate()).valueComparator();
     }
   }
 
-  private static <K, V> Collection<V> checkValues(K key,
-      Iterable<? extends V> values,
-      MapConstraint<? super K, ? super V> constraint) {
+  private static <K, V> Collection<V> checkValues(
+      K key, Iterable<? extends V> values, MapConstraint<? super K, ? super V> constraint) {
     Collection<V> copy = Lists.newArrayList(values);
     for (V value : copy) {
       constraint.checkKeyValue(key, value);
@@ -773,8 +859,8 @@ public final class MapConstraints {
     return copy;
   }
 
-  private static <K, V> Map<K, V> checkMap(Map<? extends K, ? extends V> map,
-      MapConstraint<? super K, ? super V> constraint) {
+  private static <K, V> Map<K, V> checkMap(
+      Map<? extends K, ? extends V> map, MapConstraint<? super K, ? super V> constraint) {
     Map<K, V> copy = new LinkedHashMap<K, V>(map);
     for (Entry<K, V> entry : copy.entrySet()) {
       constraint.checkKeyValue(entry.getKey(), entry.getValue());
diff --git a/guava/src/com/google/common/collect/MapDifference.java b/guava/src/com/google/common/collect/MapDifference.java
index 484cf67..c1c279e 100644
--- a/guava/src/com/google/common/collect/MapDifference.java
+++ b/guava/src/com/google/common/collect/MapDifference.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
  * An object representing the differences between two maps.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface MapDifference<K, V> {
@@ -85,7 +85,7 @@ public interface MapDifference<K, V> {
    * {@link #leftValue} and {@link #rightValue} are not equal, and one but not
    * both of them may be null.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   interface ValueDifference<V> {
     /**
@@ -102,13 +102,14 @@ public interface MapDifference<K, V> {
      * Two instances are considered equal if their {@link #leftValue()}
      * values are equal and their {@link #rightValue()} values are also equal.
      */
-    @Override boolean equals(@Nullable Object other);
+    @Override
+    boolean equals(@Nullable Object other);
 
     /**
      * The hash code equals the value
      * {@code Arrays.asList(leftValue(), rightValue()).hashCode()}.
      */
-    @Override int hashCode();
+    @Override
+    int hashCode();
   }
-
 }
diff --git a/guava/src/com/google/common/collect/MapMaker.java b/guava/src/com/google/common/collect/MapMaker.java
index 0a71ad0..169d122 100644
--- a/guava/src/com/google/common/collect/MapMaker.java
+++ b/guava/src/com/google/common/collect/MapMaker.java
@@ -51,7 +51,6 @@ import javax.annotation.Nullable;
  * <li>keys or values automatically wrapped in {@linkplain WeakReference weak} or {@linkplain
  *     SoftReference soft} references
  * <li>notification of evicted (or otherwise removed) entries
- * <li>on-demand computation of values for keys not already present
  * </ul>
  *
  * <p>Usage example: <pre>   {@code
@@ -100,7 +99,7 @@ import javax.annotation.Nullable;
  * @author Bob Lee
  * @author Charles Fry
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class MapMaker extends GenericMapMaker<Object, Object> {
@@ -167,7 +166,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
    */
   @Override
   public MapMaker initialCapacity(int initialCapacity) {
-    checkState(this.initialCapacity == UNSET_INT, "initial capacity was already set to %s",
+    checkState(
+        this.initialCapacity == UNSET_INT,
+        "initial capacity was already set to %s",
         this.initialCapacity);
     checkArgument(initialCapacity >= 0);
     this.initialCapacity = initialCapacity;
@@ -204,7 +205,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
   @Deprecated
   @Override
   MapMaker maximumSize(int size) {
-    checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
+    checkState(
+        this.maximumSize == UNSET_INT,
+        "maximum size was already set to %s",
         this.maximumSize);
     checkArgument(size >= 0, "maximum size must not be negative");
     this.maximumSize = size;
@@ -237,7 +240,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
    */
   @Override
   public MapMaker concurrencyLevel(int concurrencyLevel) {
-    checkState(this.concurrencyLevel == UNSET_INT, "concurrency level was already set to %s",
+    checkState(
+        this.concurrencyLevel == UNSET_INT,
+        "concurrency level was already set to %s",
         this.concurrencyLevel);
     checkArgument(concurrencyLevel > 0);
     this.concurrencyLevel = concurrencyLevel;
@@ -325,13 +330,12 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
    * @deprecated Caching functionality in {@code MapMaker} has been moved to {@link
    *     com.google.common.cache.CacheBuilder}, with {@link #softValues} being replaced by {@link
    *     com.google.common.cache.CacheBuilder#softValues}. Note that {@code CacheBuilder} is simply
-   *     an enhanced API for an implementation which was branched from {@code MapMaker}. <b>This
-   *     method is scheduled for removal in March 2015.</b>
+   *     an enhanced API for an implementation which was branched from {@code MapMaker}.
    */
   @Deprecated
   @GwtIncompatible("java.lang.ref.SoftReference")
   @Override
-  public MapMaker softValues() {
+  MapMaker softValues() {
     return setValueStrength(Strength.SOFT);
   }
 
@@ -388,9 +392,13 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
   }
 
   private void checkExpiration(long duration, TimeUnit unit) {
-    checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns",
+    checkState(
+        expireAfterWriteNanos == UNSET_INT,
+        "expireAfterWrite was already set to %s ns",
         expireAfterWriteNanos);
-    checkState(expireAfterAccessNanos == UNSET_INT, "expireAfterAccess was already set to %s ns",
+    checkState(
+        expireAfterAccessNanos == UNSET_INT,
+        "expireAfterAccess was already set to %s ns",
         expireAfterAccessNanos);
     checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
   }
@@ -440,7 +448,8 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
 
   long getExpireAfterAccessNanos() {
     return (expireAfterAccessNanos == UNSET_INT)
-        ? DEFAULT_EXPIRATION_NANOS : expireAfterAccessNanos;
+        ? DEFAULT_EXPIRATION_NANOS
+        : expireAfterAccessNanos;
   }
 
   Ticker getTicker() {
@@ -490,9 +499,8 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
   }
 
   /**
-   * Builds a thread-safe map, without on-demand computation of values. This method does not alter
-   * the state of this {@code MapMaker} instance, so it can be invoked again to create multiple
-   * independent maps.
+   * Builds a thread-safe map. This method does not alter the state of this {@code MapMaker}
+   * instance, so it can be invoked again to create multiple independent maps.
    *
    * <p>The bulk operations {@code putAll}, {@code equals}, and {@code clear} are not guaranteed to
    * be performed atomically on the returned map. Additionally, {@code size} and {@code
@@ -575,13 +583,12 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
    * @deprecated Caching functionality in {@code MapMaker} has been moved to
    *     {@link com.google.common.cache.CacheBuilder}, with {@link #makeComputingMap} being replaced
    *     by {@link com.google.common.cache.CacheBuilder#build}. See the
-   *     <a href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker
+   *     <a href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker
    *     Migration Guide</a> for more details.
    */
   @Deprecated
   @Override
-  <K, V> ConcurrentMap<K, V> makeComputingMap(
-      Function<? super K, ? extends V> computingFunction) {
+  <K, V> ConcurrentMap<K, V> makeComputingMap(Function<? super K, ? extends V> computingFunction) {
     return (nullRemovalCause == null)
         ? new MapMaker.ComputingMapAdapter<K, V>(this, computingFunction)
         : new NullComputingConcurrentMap<K, V>(this, computingFunction);
@@ -868,12 +875,11 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
    * This might make more sense in ComputingConcurrentHashMap, but it causes a javac crash in some
    * cases there: http://code.google.com/p/guava-libraries/issues/detail?id=950
    */
-  static final class ComputingMapAdapter<K, V>
-      extends ComputingConcurrentHashMap<K, V> implements Serializable {
+  static final class ComputingMapAdapter<K, V> extends ComputingConcurrentHashMap<K, V>
+      implements Serializable {
     private static final long serialVersionUID = 0;
 
-    ComputingMapAdapter(MapMaker mapMaker,
-        Function<? super K, ? extends V> computingFunction) {
+    ComputingMapAdapter(MapMaker mapMaker, Function<? super K, ? extends V> computingFunction) {
       super(mapMaker, computingFunction);
     }
 
diff --git a/guava/src/com/google/common/collect/MapMakerInternalMap.java b/guava/src/com/google/common/collect/MapMakerInternalMap.java
index 4232679..f3e6162 100644
--- a/guava/src/com/google/common/collect/MapMakerInternalMap.java
+++ b/guava/src/com/google/common/collect/MapMakerInternalMap.java
@@ -25,6 +25,8 @@ import com.google.common.collect.MapMaker.RemovalCause;
 import com.google.common.collect.MapMaker.RemovalListener;
 import com.google.common.collect.MapMaker.RemovalNotification;
 import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -38,6 +40,7 @@ import java.util.AbstractCollection;
 import java.util.AbstractMap;
 import java.util.AbstractQueue;
 import java.util.AbstractSet;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
@@ -68,8 +71,8 @@ import javax.annotation.concurrent.GuardedBy;
  * @author Charles Fry
  * @author Doug Lea ({@code ConcurrentHashMap})
  */
-class MapMakerInternalMap<K, V>
-    extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable {
+class MapMakerInternalMap<K, V> extends AbstractMap<K, V>
+    implements ConcurrentMap<K, V>, Serializable {
 
   /*
    * The basic strategy is to subdivide the table among Segments, each of which itself is a
@@ -209,9 +212,10 @@ class MapMakerInternalMap<K, V>
     ticker = builder.getTicker();
 
     removalListener = builder.getRemovalListener();
-    removalNotificationQueue = (removalListener == NullListener.INSTANCE)
-        ? MapMakerInternalMap.<RemovalNotification<K, V>>discardingQueue()
-        : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
+    removalNotificationQueue =
+        (removalListener == NullListener.INSTANCE)
+            ? MapMakerInternalMap.<RemovalNotification<K, V>>discardingQueue()
+            : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
 
     int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY);
     if (evictsBySize()) {
@@ -251,13 +255,11 @@ class MapMakerInternalMap<K, V>
         if (i == remainder) {
           maximumSegmentSize--;
         }
-        this.segments[i] =
-            createSegment(segmentSize, maximumSegmentSize);
+        this.segments[i] = createSegment(segmentSize, maximumSegmentSize);
       }
     } else {
       for (int i = 0; i < this.segments.length; ++i) {
-        this.segments[i] =
-            createSegment(segmentSize, MapMaker.UNSET_INT);
+        this.segments[i] = createSegment(segmentSize, MapMaker.UNSET_INT);
       }
     }
   }
@@ -461,6 +463,7 @@ class MapMakerInternalMap<K, V>
      * Masks used to compute indices in the following table.
      */
     static final int EXPIRABLE_MASK = 1;
+
     static final int EVICTABLE_MASK = 2;
 
     /**
@@ -468,13 +471,13 @@ class MapMakerInternalMap<K, V>
      * the result of OR-ing the feature masks.
      */
     static final EntryFactory[][] factories = {
-      { STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE },
+      {STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE},
       {}, // no support for SOFT keys
-      { WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE }
+      {WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE}
     };
 
-    static EntryFactory getFactory(Strength keyStrength, boolean expireAfterWrite,
-        boolean evictsBySize) {
+    static EntryFactory getFactory(
+        Strength keyStrength, boolean expireAfterWrite, boolean evictsBySize) {
       int flags = (expireAfterWrite ? EXPIRABLE_MASK : 0) | (evictsBySize ? EVICTABLE_MASK : 0);
       return factories[keyStrength.ordinal()][flags];
     }
@@ -575,36 +578,39 @@ class MapMakerInternalMap<K, V>
   /**
    * Placeholder. Indicates that the value hasn't been set yet.
    */
-  static final ValueReference<Object, Object> UNSET = new ValueReference<Object, Object>() {
-    @Override
-    public Object get() {
-      return null;
-    }
+  static final ValueReference<Object, Object> UNSET =
+      new ValueReference<Object, Object>() {
+        @Override
+        public Object get() {
+          return null;
+        }
 
-    @Override
-    public ReferenceEntry<Object, Object> getEntry() {
-      return null;
-    }
+        @Override
+        public ReferenceEntry<Object, Object> getEntry() {
+          return null;
+        }
 
-    @Override
-    public ValueReference<Object, Object> copyFor(ReferenceQueue<Object> queue,
-        @Nullable Object value, ReferenceEntry<Object, Object> entry) {
-      return this;
-    }
+        @Override
+        public ValueReference<Object, Object> copyFor(
+            ReferenceQueue<Object> queue,
+            @Nullable Object value,
+            ReferenceEntry<Object, Object> entry) {
+          return this;
+        }
 
-    @Override
-    public boolean isComputingReference() {
-      return false;
-    }
+        @Override
+        public boolean isComputingReference() {
+          return false;
+        }
 
-    @Override
-    public Object waitForValue() {
-      return null;
-    }
+        @Override
+        public Object waitForValue() {
+          return null;
+        }
 
-    @Override
-    public void clear(ValueReference<Object, Object> newValue) {}
-  };
+        @Override
+        public void clear(ValueReference<Object, Object> newValue) {}
+      };
 
   /**
    * Singleton placeholder that indicates a value is being computed.
@@ -865,32 +871,33 @@ class MapMakerInternalMap<K, V>
     return (ReferenceEntry<K, V>) NullEntry.INSTANCE;
   }
 
-  static final Queue<? extends Object> DISCARDING_QUEUE = new AbstractQueue<Object>() {
-    @Override
-    public boolean offer(Object o) {
-      return true;
-    }
+  static final Queue<? extends Object> DISCARDING_QUEUE =
+      new AbstractQueue<Object>() {
+        @Override
+        public boolean offer(Object o) {
+          return true;
+        }
 
-    @Override
-    public Object peek() {
-      return null;
-    }
+        @Override
+        public Object peek() {
+          return null;
+        }
 
-    @Override
-    public Object poll() {
-      return null;
-    }
+        @Override
+        public Object poll() {
+          return null;
+        }
 
-    @Override
-    public int size() {
-      return 0;
-    }
+        @Override
+        public int size() {
+          return 0;
+        }
 
-    @Override
-    public Iterator<Object> iterator() {
-      return Iterators.emptyIterator();
-    }
-  };
+        @Override
+        public Iterator<Object> iterator() {
+          return Iterators.emptyIterator();
+        }
+      };
 
   /**
    * Queue that discards all elements.
@@ -1055,8 +1062,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class StrongEvictableEntry<K, V>
-      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class StrongEvictableEntry<K, V> extends StrongEntry<K, V>
+      implements ReferenceEntry<K, V> {
     StrongEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(key, hash, next);
     }
@@ -1090,8 +1097,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class StrongExpirableEvictableEntry<K, V>
-      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class StrongExpirableEvictableEntry<K, V> extends StrongEntry<K, V>
+      implements ReferenceEntry<K, V> {
     StrongExpirableEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(key, hash, next);
     }
@@ -1262,8 +1269,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class SoftExpirableEntry<K, V>
-      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class SoftExpirableEntry<K, V> extends SoftEntry<K, V>
+      implements ReferenceEntry<K, V> {
     SoftExpirableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1310,8 +1317,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class SoftEvictableEntry<K, V>
-      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class SoftEvictableEntry<K, V> extends SoftEntry<K, V>
+      implements ReferenceEntry<K, V> {
     SoftEvictableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1346,8 +1353,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class SoftExpirableEvictableEntry<K, V>
-      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class SoftExpirableEvictableEntry<K, V> extends SoftEntry<K, V>
+      implements ReferenceEntry<K, V> {
     SoftExpirableEvictableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1520,8 +1527,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class WeakExpirableEntry<K, V>
-      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class WeakExpirableEntry<K, V> extends WeakEntry<K, V>
+      implements ReferenceEntry<K, V> {
     WeakExpirableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1568,8 +1575,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class WeakEvictableEntry<K, V>
-      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class WeakEvictableEntry<K, V> extends WeakEntry<K, V>
+      implements ReferenceEntry<K, V> {
     WeakEvictableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1604,8 +1611,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  static final class WeakExpirableEvictableEntry<K, V>
-      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+  static final class WeakExpirableEvictableEntry<K, V> extends WeakEntry<K, V>
+      implements ReferenceEntry<K, V> {
     WeakExpirableEvictableEntry(
         ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       super(queue, key, hash, next);
@@ -1683,8 +1690,8 @@ class MapMakerInternalMap<K, V>
   /**
    * References a weak value.
    */
-  static final class WeakValueReference<K, V>
-      extends WeakReference<V> implements ValueReference<K, V> {
+  static final class WeakValueReference<K, V> extends WeakReference<V>
+      implements ValueReference<K, V> {
     final ReferenceEntry<K, V> entry;
 
     WeakValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
@@ -1722,8 +1729,8 @@ class MapMakerInternalMap<K, V>
   /**
    * References a soft value.
    */
-  static final class SoftValueReference<K, V>
-      extends SoftReference<V> implements ValueReference<K, V> {
+  static final class SoftValueReference<K, V> extends SoftReference<V>
+      implements ValueReference<K, V> {
     final ReferenceEntry<K, V> entry;
 
     SoftValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
@@ -2016,7 +2023,7 @@ class MapMakerInternalMap<K, V>
      * comments.
      */
 
-    final MapMakerInternalMap<K, V> map;
+    @Weak final MapMakerInternalMap<K, V> map;
 
     /**
      * The number of live elements in this segment's region. This does not include unset elements
@@ -2077,14 +2084,14 @@ class MapMakerInternalMap<K, V>
      * A queue of elements currently in the map, ordered by access time. Elements are added to the
      * tail of the queue on access/write.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     final Queue<ReferenceEntry<K, V>> evictionQueue;
 
     /**
      * A queue of elements currently in the map, ordered by expiration time (either access or write
      * time). Elements are added to the tail of the queue on access/write.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     final Queue<ReferenceEntry<K, V>> expirationQueue;
 
     Segment(MapMakerInternalMap<K, V> map, int initialCapacity, int maxSegmentSize) {
@@ -2092,23 +2099,24 @@ class MapMakerInternalMap<K, V>
       this.maxSegmentSize = maxSegmentSize;
       initTable(newEntryArray(initialCapacity));
 
-      keyReferenceQueue = map.usesKeyReferences()
-           ? new ReferenceQueue<K>() : null;
+      keyReferenceQueue = map.usesKeyReferences() ? new ReferenceQueue<K>() : null;
 
-      valueReferenceQueue = map.usesValueReferences()
-           ? new ReferenceQueue<V>() : null;
+      valueReferenceQueue = map.usesValueReferences() ? new ReferenceQueue<V>() : null;
 
-      recencyQueue = (map.evictsBySize() || map.expiresAfterAccess())
-          ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
-          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+      recencyQueue =
+          (map.evictsBySize() || map.expiresAfterAccess())
+              ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
+              : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
 
-      evictionQueue = map.evictsBySize()
-          ? new EvictionQueue<K, V>()
-          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+      evictionQueue =
+          map.evictsBySize()
+              ? new EvictionQueue<K, V>()
+              : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
 
-      expirationQueue = map.expires()
-          ? new ExpirationQueue<K, V>()
-          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+      expirationQueue =
+          map.expires()
+              ? new ExpirationQueue<K, V>()
+              : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
     }
 
     AtomicReferenceArray<ReferenceEntry<K, V>> newEntryArray(int size) {
@@ -2124,7 +2132,7 @@ class MapMakerInternalMap<K, V>
       this.table = newTable;
     }
 
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
       return map.entryFactory.newEntry(this, key, hash, next);
     }
@@ -2133,7 +2141,7 @@ class MapMakerInternalMap<K, V>
      * Copies {@code original} into a new entry chained to {@code newNext}. Returns the new entry,
      * or {@code null} if {@code original} was already garbage collected.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
       if (original.getKey() == null) {
         // key collected
@@ -2155,7 +2163,7 @@ class MapMakerInternalMap<K, V>
     /**
      * Sets a new value of an entry. Adds newly created entries at the end of the expiration queue.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void setValue(ReferenceEntry<K, V> entry, V value) {
       ValueReference<K, V> valueReference = map.valueStrength.referenceValue(this, entry, value);
       entry.setValueReference(valueReference);
@@ -2181,7 +2189,7 @@ class MapMakerInternalMap<K, V>
      * Drain the key and value reference queues, cleaning up internal entries containing garbage
      * collected keys or values.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void drainReferenceQueues() {
       if (map.usesKeyReferences()) {
         drainKeyReferenceQueue();
@@ -2191,7 +2199,7 @@ class MapMakerInternalMap<K, V>
       }
     }
 
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void drainKeyReferenceQueue() {
       Reference<? extends K> ref;
       int i = 0;
@@ -2205,7 +2213,7 @@ class MapMakerInternalMap<K, V>
       }
     }
 
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void drainValueReferenceQueue() {
       Reference<? extends V> ref;
       int i = 0;
@@ -2262,7 +2270,7 @@ class MapMakerInternalMap<K, V>
      * <p>Note: this method should only be called under lock, as it directly manipulates the
      * eviction queues. Unlocked reads should use {@link #recordRead}.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void recordLockedRead(ReferenceEntry<K, V> entry) {
       evictionQueue.add(entry);
       if (map.expiresAfterAccess()) {
@@ -2275,7 +2283,7 @@ class MapMakerInternalMap<K, V>
      * Updates eviction metadata that {@code entry} was just written. This currently amounts to
      * adding {@code entry} to relevant eviction lists.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void recordWrite(ReferenceEntry<K, V> entry) {
       // we are already under lock, so drain the recency queue immediately
       drainRecencyQueue();
@@ -2283,9 +2291,8 @@ class MapMakerInternalMap<K, V>
       if (map.expires()) {
         // currently MapMaker ensures that expireAfterWrite and
         // expireAfterAccess are mutually exclusive
-        long expiration = map.expiresAfterAccess()
-            ? map.expireAfterAccessNanos
-            : map.expireAfterWriteNanos;
+        long expiration =
+            map.expiresAfterAccess() ? map.expireAfterAccessNanos : map.expireAfterWriteNanos;
         recordExpirationTime(entry, expiration);
         expirationQueue.add(entry);
       }
@@ -2297,7 +2304,7 @@ class MapMakerInternalMap<K, V>
      * lists (accounting for the fact that they could have been removed from the map since being
      * added to the recency queue).
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void drainRecencyQueue() {
       ReferenceEntry<K, V> e;
       while ((e = recencyQueue.poll()) != null) {
@@ -2335,7 +2342,7 @@ class MapMakerInternalMap<K, V>
       }
     }
 
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void expireEntries() {
       drainRecencyQueue();
 
@@ -2372,7 +2379,7 @@ class MapMakerInternalMap<K, V>
      *
      * @return {@code true} if eviction occurred
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     boolean evictEntries() {
       if (map.evictsBySize() && count >= maxSegmentSize) {
         drainRecencyQueue();
@@ -2512,7 +2519,8 @@ class MapMakerInternalMap<K, V>
         // Look for an existing entry.
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             // We found an existing entry.
 
@@ -2565,7 +2573,7 @@ class MapMakerInternalMap<K, V>
     /**
      * Expands the table if possible.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void expand() {
       AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table;
       int oldCapacity = oldTable.length();
@@ -2645,7 +2653,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             // If the value disappeared, this entry is partially collected,
             // and we should pretend like it doesn't exist.
@@ -2696,7 +2705,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             // If the value disappeared, this entry is partially collected,
             // and we should pretend like it doesn't exist.
@@ -2741,7 +2751,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             ValueReference<K, V> valueReference = e.getValueReference();
             V entryValue = valueReference.get();
@@ -2784,7 +2795,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             ValueReference<K, V> valueReference = e.getValueReference();
             V entryValue = valueReference.get();
@@ -2859,7 +2871,7 @@ class MapMakerInternalMap<K, V>
      * @param entry the entry being removed from the table
      * @return the new first entry for the table
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     ReferenceEntry<K, V> removeFromChain(ReferenceEntry<K, V> first, ReferenceEntry<K, V> entry) {
       evictionQueue.remove(entry);
       expirationQueue.remove(entry);
@@ -2929,7 +2941,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             ValueReference<K, V> v = e.getValueReference();
             if (v == valueReference) {
@@ -2966,7 +2979,8 @@ class MapMakerInternalMap<K, V>
 
         for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
           K entryKey = e.getKey();
-          if (e.getHash() == hash && entryKey != null
+          if (e.getHash() == hash
+              && entryKey != null
               && map.keyEquivalence.equivalent(key, entryKey)) {
             ValueReference<K, V> v = e.getValueReference();
             if (v == valueReference) {
@@ -2985,7 +2999,7 @@ class MapMakerInternalMap<K, V>
       }
     }
 
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     boolean removeEntry(ReferenceEntry<K, V> entry, int hash, RemovalCause cause) {
       int newCount = this.count - 1;
       AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
@@ -3057,7 +3071,7 @@ class MapMakerInternalMap<K, V>
      *
      * <p>Post-condition: expireEntries has been run.
      */
-    @GuardedBy("Segment.this")
+    @GuardedBy("this")
     void preWriteCleanup() {
       runLockedCleanup();
     }
@@ -3092,7 +3106,6 @@ class MapMakerInternalMap<K, V>
         map.processPendingNotifications();
       }
     }
-
   }
 
   // Queues
@@ -3109,32 +3122,33 @@ class MapMakerInternalMap<K, V>
    * for the current model.
    */
   static final class EvictionQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
-    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
+    final ReferenceEntry<K, V> head =
+        new AbstractReferenceEntry<K, V>() {
 
-      ReferenceEntry<K, V> nextEvictable = this;
+          ReferenceEntry<K, V> nextEvictable = this;
 
-      @Override
-      public ReferenceEntry<K, V> getNextEvictable() {
-        return nextEvictable;
-      }
+          @Override
+          public ReferenceEntry<K, V> getNextEvictable() {
+            return nextEvictable;
+          }
 
-      @Override
-      public void setNextEvictable(ReferenceEntry<K, V> next) {
-        this.nextEvictable = next;
-      }
+          @Override
+          public void setNextEvictable(ReferenceEntry<K, V> next) {
+            this.nextEvictable = next;
+          }
 
-      ReferenceEntry<K, V> previousEvictable = this;
+          ReferenceEntry<K, V> previousEvictable = this;
 
-      @Override
-      public ReferenceEntry<K, V> getPreviousEvictable() {
-        return previousEvictable;
-      }
+          @Override
+          public ReferenceEntry<K, V> getPreviousEvictable() {
+            return previousEvictable;
+          }
 
-      @Override
-      public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
-        this.previousEvictable = previous;
-      }
-    };
+          @Override
+          public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
+            this.previousEvictable = previous;
+          }
+        };
 
     // implements Queue
 
@@ -3237,40 +3251,41 @@ class MapMakerInternalMap<K, V>
    * for the current model.
    */
   static final class ExpirationQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
-    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
+    final ReferenceEntry<K, V> head =
+        new AbstractReferenceEntry<K, V>() {
 
-      @Override
-      public long getExpirationTime() {
-        return Long.MAX_VALUE;
-      }
+          @Override
+          public long getExpirationTime() {
+            return Long.MAX_VALUE;
+          }
 
-      @Override
-      public void setExpirationTime(long time) {}
+          @Override
+          public void setExpirationTime(long time) {}
 
-      ReferenceEntry<K, V> nextExpirable = this;
+          ReferenceEntry<K, V> nextExpirable = this;
 
-      @Override
-      public ReferenceEntry<K, V> getNextExpirable() {
-        return nextExpirable;
-      }
+          @Override
+          public ReferenceEntry<K, V> getNextExpirable() {
+            return nextExpirable;
+          }
 
-      @Override
-      public void setNextExpirable(ReferenceEntry<K, V> next) {
-        this.nextExpirable = next;
-      }
+          @Override
+          public void setNextExpirable(ReferenceEntry<K, V> next) {
+            this.nextExpirable = next;
+          }
 
-      ReferenceEntry<K, V> previousExpirable = this;
+          ReferenceEntry<K, V> previousExpirable = this;
 
-      @Override
-      public ReferenceEntry<K, V> getPreviousExpirable() {
-        return previousExpirable;
-      }
+          @Override
+          public ReferenceEntry<K, V> getPreviousExpirable() {
+            return previousExpirable;
+          }
 
-      @Override
-      public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
-        this.previousExpirable = previous;
-      }
-    };
+          @Override
+          public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
+            this.previousExpirable = previous;
+          }
+        };
 
     // implements Queue
 
@@ -3472,8 +3487,7 @@ class MapMakerInternalMap<K, V>
       long sum = 0L;
       for (Segment<K, V> segment : segments) {
         // ensure visibility of most recent completed write
-        @SuppressWarnings({"UnusedDeclaration", "unused"})
-        int c = segment.count; // read-volatile
+        int unused = segment.count; // read-volatile
 
         AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
         for (int j = 0; j < table.length(); j++) {
@@ -3770,7 +3784,8 @@ class MapMakerInternalMap<K, V>
     }
   }
 
-  final class KeySet extends AbstractSet<K> {
+  @WeakOuter
+  final class KeySet extends SafeToArraySet<K> {
 
     @Override
     public Iterator<K> iterator() {
@@ -3803,6 +3818,7 @@ class MapMakerInternalMap<K, V>
     }
   }
 
+  @WeakOuter
   final class Values extends AbstractCollection<V> {
 
     @Override
@@ -3829,9 +3845,23 @@ class MapMakerInternalMap<K, V>
     public void clear() {
       MapMakerInternalMap.this.clear();
     }
+
+    // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+    // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+    @Override
+    public Object[] toArray() {
+      return toArrayList(this).toArray();
+    }
+
+    @Override
+    public <E> E[] toArray(E[] a) {
+      return toArrayList(this).toArray(a);
+    }
   }
 
-  final class EntrySet extends AbstractSet<Entry<K, V>> {
+  @WeakOuter
+  final class EntrySet extends SafeToArraySet<Entry<K, V>> {
 
     @Override
     public Iterator<Entry<K, V>> iterator() {
@@ -3879,22 +3909,52 @@ class MapMakerInternalMap<K, V>
     }
   }
 
+  private abstract static class SafeToArraySet<E> extends AbstractSet<E> {
+    // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+    // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+    @Override
+    public Object[] toArray() {
+      return toArrayList(this).toArray();
+    }
+
+    @Override
+    public <E> E[] toArray(E[] a) {
+      return toArrayList(this).toArray(a);
+    }
+  }
+
+  private static <E> ArrayList<E> toArrayList(Collection<E> c) {
+    // Avoid calling ArrayList(Collection), which may call back into toArray.
+    ArrayList<E> result = new ArrayList<E>(c.size());
+    Iterators.addAll(result, c.iterator());
+    return result;
+  }
+
   // Serialization Support
 
   private static final long serialVersionUID = 5;
 
   Object writeReplace() {
-    return new SerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
-        valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
-        concurrencyLevel, removalListener, this);
+    return new SerializationProxy<K, V>(
+        keyStrength,
+        valueStrength,
+        keyEquivalence,
+        valueEquivalence,
+        expireAfterWriteNanos,
+        expireAfterAccessNanos,
+        maximumSize,
+        concurrencyLevel,
+        removalListener,
+        this);
   }
 
   /**
    * The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a
    * circular dependency is present, so the proxy must be able to behave as the map itself.
    */
-  abstract static class AbstractSerializationProxy<K, V>
-      extends ForwardingConcurrentMap<K, V> implements Serializable {
+  abstract static class AbstractSerializationProxy<K, V> extends ForwardingConcurrentMap<K, V>
+      implements Serializable {
     private static final long serialVersionUID = 3;
 
     final Strength keyStrength;
@@ -3909,10 +3969,16 @@ class MapMakerInternalMap<K, V>
 
     transient ConcurrentMap<K, V> delegate;
 
-    AbstractSerializationProxy(Strength keyStrength, Strength valueStrength,
-        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
-        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
-        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
+    AbstractSerializationProxy(
+        Strength keyStrength,
+        Strength valueStrength,
+        Equivalence<Object> keyEquivalence,
+        Equivalence<Object> valueEquivalence,
+        long expireAfterWriteNanos,
+        long expireAfterAccessNanos,
+        int maximumSize,
+        int concurrencyLevel,
+        RemovalListener<? super K, ? super V> removalListener,
         ConcurrentMap<K, V> delegate) {
       this.keyStrength = keyStrength;
       this.valueStrength = valueStrength;
@@ -3943,12 +4009,13 @@ class MapMakerInternalMap<K, V>
     @SuppressWarnings("deprecation") // serialization of deprecated feature
     MapMaker readMapMaker(ObjectInputStream in) throws IOException {
       int size = in.readInt();
-      MapMaker mapMaker = new MapMaker()
-          .initialCapacity(size)
-          .setKeyStrength(keyStrength)
-          .setValueStrength(valueStrength)
-          .keyEquivalence(keyEquivalence)
-          .concurrencyLevel(concurrencyLevel);
+      MapMaker mapMaker =
+          new MapMaker()
+              .initialCapacity(size)
+              .setKeyStrength(keyStrength)
+              .setValueStrength(valueStrength)
+              .keyEquivalence(keyEquivalence)
+              .concurrencyLevel(concurrencyLevel);
       mapMaker.removalListener(removalListener);
       if (expireAfterWriteNanos > 0) {
         mapMaker.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS);
@@ -3982,13 +4049,28 @@ class MapMakerInternalMap<K, V>
   private static final class SerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
     private static final long serialVersionUID = 3;
 
-    SerializationProxy(Strength keyStrength, Strength valueStrength,
-        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
-        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
-        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
+    SerializationProxy(
+        Strength keyStrength,
+        Strength valueStrength,
+        Equivalence<Object> keyEquivalence,
+        Equivalence<Object> valueEquivalence,
+        long expireAfterWriteNanos,
+        long expireAfterAccessNanos,
+        int maximumSize,
+        int concurrencyLevel,
+        RemovalListener<? super K, ? super V> removalListener,
         ConcurrentMap<K, V> delegate) {
-      super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
-          expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
+      super(
+          keyStrength,
+          valueStrength,
+          keyEquivalence,
+          valueEquivalence,
+          expireAfterWriteNanos,
+          expireAfterAccessNanos,
+          maximumSize,
+          concurrencyLevel,
+          removalListener,
+          delegate);
     }
 
     private void writeObject(ObjectOutputStream out) throws IOException {
diff --git a/guava/src/com/google/common/collect/Maps.java b/guava/src/com/google/common/collect/Maps.java
index e8ab643..3cd4558 100644
--- a/guava/src/com/google/common/collect/Maps.java
+++ b/guava/src/com/google/common/collect/Maps.java
@@ -37,6 +37,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.MapDifference.ValueDifference;
 import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.AbstractCollection;
@@ -61,6 +63,7 @@ import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -69,14 +72,14 @@ import javax.annotation.Nullable;
  * {@link Lists}, {@link Sets} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Maps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#maps">
  * {@code Maps}</a>.
  *
  * @author Kevin Bourrillion
  * @author Mike Bostock
  * @author Isaac Shum
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Maps {
@@ -117,21 +120,6 @@ public final class Maps {
     return Iterators.transform(entryIterator, Maps.<V>valueFunction());
   }
 
-  static <K, V> UnmodifiableIterator<V> valueIterator(
-      final UnmodifiableIterator<Entry<K, V>> entryIterator) {
-    return new UnmodifiableIterator<V>() {
-      @Override
-      public boolean hasNext() {
-        return entryIterator.hasNext();
-      }
-
-      @Override
-      public V next() {
-        return entryIterator.next().getValue();
-      }
-    };
-  }
-
   /**
    * Returns an immutable map instance containing the given entries.
    * Internally, the returned map will be backed by an {@link EnumMap}.
@@ -181,17 +169,16 @@ public final class Maps {
    * Creates a {@code HashMap} instance, with a high enough "initial capacity"
    * that it <i>should</i> hold {@code expectedSize} elements without growth.
    * This behavior cannot be broadly guaranteed, but it is observed to be true
-   * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
+   * for OpenJDK 1.7. It also can't be guaranteed that the method isn't
    * inadvertently <i>oversizing</i> the returned map.
    *
-   * @param expectedSize the number of elements you expect to add to the
+   * @param expectedSize the number of entries you expect to add to the
    *        returned map
    * @return a new, empty {@code HashMap} with enough capacity to hold {@code
-   *         expectedSize} elements without resizing
+   *         expectedSize} entries without resizing
    * @throws IllegalArgumentException if {@code expectedSize} is negative
    */
-  public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(
-      int expectedSize) {
+  public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
     return new HashMap<K, V>(capacity(expectedSize));
   }
 
@@ -206,7 +193,10 @@ public final class Maps {
       return expectedSize + 1;
     }
     if (expectedSize < Ints.MAX_POWER_OF_TWO) {
-      return expectedSize + expectedSize / 3;
+      // This is the calculation used in JDK8 to resize when a putAll
+      // happens; it seems to be the most conservative calculation we
+      // can make.  0.75 is the default load factor.
+      return (int) ((float) expectedSize / 0.75F + 1.0F);
     }
     return Integer.MAX_VALUE; // any large value
   }
@@ -225,8 +215,7 @@ public final class Maps {
    * @return a new {@code HashMap} initialized with the mappings from {@code
    *         map}
    */
-  public static <K, V> HashMap<K, V> newHashMap(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map) {
     return new HashMap<K, V>(map);
   }
 
@@ -244,6 +233,24 @@ public final class Maps {
   }
 
   /**
+   * Creates a {@code LinkedHashMap} instance, with a high enough
+   * "initial capacity" that it <i>should</i> hold {@code expectedSize}
+   * elements without growth. This behavior cannot be broadly guaranteed, but
+   * it is observed to be true for OpenJDK 1.7. It also can't be guaranteed
+   * that the method isn't inadvertently <i>oversizing</i> the returned map.
+   *
+   * @param expectedSize the number of entries you expect to add to the
+   *        returned map
+   * @return a new, empty {@code LinkedHashMap} with enough capacity to hold
+   *         {@code expectedSize} entries without resizing
+   * @throws IllegalArgumentException if {@code expectedSize} is negative
+   * @since 19.0
+   */
+  public static <K, V> LinkedHashMap<K, V> newLinkedHashMapWithExpectedSize(int expectedSize) {
+    return new LinkedHashMap<K, V>(capacity(expectedSize));
+  }
+
+  /**
    * Creates a <i>mutable</i>, insertion-ordered {@code LinkedHashMap} instance
    * with the same mappings as the specified map.
    *
@@ -254,8 +261,7 @@ public final class Maps {
    * @return a new, {@code LinkedHashMap} initialized with the mappings from
    *         {@code map}
    */
-  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(
-      Map<? extends K, ? extends V> map) {
+  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map) {
     return new LinkedHashMap<K, V>(map);
   }
 
@@ -317,8 +323,7 @@ public final class Maps {
    * @param comparator the comparator to sort the keys with
    * @return a new, empty {@code TreeMap}
    */
-  public static <C, K extends C, V> TreeMap<K, V> newTreeMap(
-      @Nullable Comparator<C> comparator) {
+  public static <C, K extends C, V> TreeMap<K, V> newTreeMap(@Nullable Comparator<C> comparator) {
     // Ideally, the extra type parameter "C" shouldn't be necessary. It is a
     // work-around of a compiler type inference quirk that prevents the
     // following code from being compiled:
@@ -346,8 +351,7 @@ public final class Maps {
    * @throws IllegalArgumentException if {@code m} is not an {@code EnumMap}
    *         instance and contains no mappings
    */
-  public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(
-      Map<K, ? extends V> map) {
+  public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Map<K, ? extends V> map) {
     return new EnumMap<K, V>(map);
   }
 
@@ -408,22 +412,26 @@ public final class Maps {
    */
   @Beta
   public static <K, V> MapDifference<K, V> difference(
-      Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+      Map<? extends K, ? extends V> left,
+      Map<? extends K, ? extends V> right,
       Equivalence<? super V> valueEquivalence) {
     Preconditions.checkNotNull(valueEquivalence);
 
-    Map<K, V> onlyOnLeft = newHashMap();
-    Map<K, V> onlyOnRight = new HashMap<K, V>(right); // will whittle it down
-    Map<K, V> onBoth = newHashMap();
-    Map<K, MapDifference.ValueDifference<V>> differences = newHashMap();
+    Map<K, V> onlyOnLeft = newLinkedHashMap();
+    Map<K, V> onlyOnRight = new LinkedHashMap<K, V>(right); // will whittle it down
+    Map<K, V> onBoth = newLinkedHashMap();
+    Map<K, MapDifference.ValueDifference<V>> differences = newLinkedHashMap();
     doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences);
     return new MapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
   }
 
   private static <K, V> void doDifference(
-      Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+      Map<? extends K, ? extends V> left,
+      Map<? extends K, ? extends V> right,
       Equivalence<? super V> valueEquivalence,
-      Map<K, V> onlyOnLeft, Map<K, V> onlyOnRight, Map<K, V> onBoth,
+      Map<K, V> onlyOnLeft,
+      Map<K, V> onlyOnRight,
+      Map<K, V> onBoth,
       Map<K, MapDifference.ValueDifference<V>> differences) {
     for (Entry<? extends K, ? extends V> entry : left.entrySet()) {
       K leftKey = entry.getKey();
@@ -433,8 +441,7 @@ public final class Maps {
         if (valueEquivalence.equivalent(leftValue, rightValue)) {
           onBoth.put(leftKey, leftValue);
         } else {
-          differences.put(
-              leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
+          differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
         }
       } else {
         onlyOnLeft.put(leftKey, leftValue);
@@ -456,8 +463,10 @@ public final class Maps {
     final Map<K, V> onBoth;
     final Map<K, ValueDifference<V>> differences;
 
-    MapDifferenceImpl(Map<K, V> onlyOnLeft,
-        Map<K, V> onlyOnRight, Map<K, V> onBoth,
+    MapDifferenceImpl(
+        Map<K, V> onlyOnLeft,
+        Map<K, V> onlyOnRight,
+        Map<K, V> onBoth,
         Map<K, ValueDifference<V>> differences) {
       this.onlyOnLeft = unmodifiableMap(onlyOnLeft);
       this.onlyOnRight = unmodifiableMap(onlyOnRight);
@@ -490,7 +499,8 @@ public final class Maps {
       return differences;
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(Object object) {
       if (object == this) {
         return true;
       }
@@ -504,12 +514,14 @@ public final class Maps {
       return false;
     }
 
-    @Override public int hashCode() {
-      return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(),
-          entriesInCommon(), entriesDiffering());
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(
+          entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering());
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       if (areEqual()) {
         return "equal";
       }
@@ -528,8 +540,7 @@ public final class Maps {
     }
   }
 
-  static class ValueDifferenceImpl<V>
-      implements MapDifference.ValueDifference<V> {
+  static class ValueDifferenceImpl<V> implements MapDifference.ValueDifference<V> {
     private final V left;
     private final V right;
 
@@ -552,21 +563,23 @@ public final class Maps {
       return right;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object instanceof MapDifference.ValueDifference) {
-        MapDifference.ValueDifference<?> that =
-            (MapDifference.ValueDifference<?>) object;
+        MapDifference.ValueDifference<?> that = (MapDifference.ValueDifference<?>) object;
         return Objects.equal(this.left, that.leftValue())
             && Objects.equal(this.right, that.rightValue());
       }
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(left, right);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "(" + left + ", " + right + ")";
     }
   }
@@ -599,33 +612,38 @@ public final class Maps {
     SortedMap<K, V> onlyOnRight = Maps.newTreeMap(comparator);
     onlyOnRight.putAll(right); // will whittle it down
     SortedMap<K, V> onBoth = Maps.newTreeMap(comparator);
-    SortedMap<K, MapDifference.ValueDifference<V>> differences =
-        Maps.newTreeMap(comparator);
+    SortedMap<K, MapDifference.ValueDifference<V>> differences = Maps.newTreeMap(comparator);
     doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
     return new SortedMapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
   }
 
   static class SortedMapDifferenceImpl<K, V> extends MapDifferenceImpl<K, V>
       implements SortedMapDifference<K, V> {
-    SortedMapDifferenceImpl(SortedMap<K, V> onlyOnLeft,
-        SortedMap<K, V> onlyOnRight, SortedMap<K, V> onBoth,
+    SortedMapDifferenceImpl(
+        SortedMap<K, V> onlyOnLeft,
+        SortedMap<K, V> onlyOnRight,
+        SortedMap<K, V> onBoth,
         SortedMap<K, ValueDifference<V>> differences) {
       super(onlyOnLeft, onlyOnRight, onBoth, differences);
     }
 
-    @Override public SortedMap<K, ValueDifference<V>> entriesDiffering() {
+    @Override
+    public SortedMap<K, ValueDifference<V>> entriesDiffering() {
       return (SortedMap<K, ValueDifference<V>>) super.entriesDiffering();
     }
 
-    @Override public SortedMap<K, V> entriesInCommon() {
+    @Override
+    public SortedMap<K, V> entriesInCommon() {
       return (SortedMap<K, V>) super.entriesInCommon();
     }
 
-    @Override public SortedMap<K, V> entriesOnlyOnLeft() {
+    @Override
+    public SortedMap<K, V> entriesOnlyOnLeft() {
       return (SortedMap<K, V>) super.entriesOnlyOnLeft();
     }
 
-    @Override public SortedMap<K, V> entriesOnlyOnRight() {
+    @Override
+    public SortedMap<K, V> entriesOnlyOnRight() {
       return (SortedMap<K, V>) super.entriesOnlyOnRight();
     }
   }
@@ -636,8 +654,7 @@ public final class Maps {
    * purpose of this method is to contain the ugly type-casting in one place.
    */
   @SuppressWarnings("unchecked")
-  static <E> Comparator<? super E> orNaturalOrder(
-      @Nullable Comparator<? super E> comparator) {
+  static <E> Comparator<? super E> orNaturalOrder(@Nullable Comparator<? super E> comparator) {
     if (comparator != null) { // can't use ? : because of javac bug 5080917
       return comparator;
     }
@@ -671,9 +688,7 @@ public final class Maps {
    *
    * @since 14.0
    */
-  @Beta
-  public static <K, V> Map<K, V> asMap(
-      Set<K> set, Function<? super K, V> function) {
+  public static <K, V> Map<K, V> asMap(Set<K> set, Function<? super K, V> function) {
     if (set instanceof SortedSet) {
       return asMap((SortedSet<K>) set, function);
     } else {
@@ -707,14 +722,12 @@ public final class Maps {
    *
    * @since 14.0
    */
-  @Beta
-  public static <K, V> SortedMap<K, V> asMap(
-      SortedSet<K> set, Function<? super K, V> function) {
+  public static <K, V> SortedMap<K, V> asMap(SortedSet<K> set, Function<? super K, V> function) {
     return Platform.mapsAsMapSortedSet(set, function);
   }
 
-  static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(SortedSet<K> set,
-      Function<? super K, V> function) {
+  static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(
+      SortedSet<K> set, Function<? super K, V> function) {
     return new SortedAsMapView<K, V>(set, function);
   }
 
@@ -744,14 +757,13 @@ public final class Maps {
    *
    * @since 14.0
    */
-  @Beta
   @GwtIncompatible("NavigableMap")
   public static <K, V> NavigableMap<K, V> asMap(
       NavigableSet<K> set, Function<? super K, V> function) {
     return new NavigableAsMapView<K, V>(set, function);
   }
 
-  private static class AsMapView<K, V> extends ImprovedAbstractMap<K, V> {
+  private static class AsMapView<K, V> extends ViewCachingAbstractMap<K, V> {
 
     private final Set<K> set;
     final Function<? super K, V> function;
@@ -814,7 +826,8 @@ public final class Maps {
 
     @Override
     protected Set<Entry<K, V>> createEntrySet() {
-      return new EntrySet<K, V>() {
+      @WeakOuter
+      class EntrySetImpl extends EntrySet<K, V> {
         @Override
         Map<K, V> map() {
           return AsMapView.this;
@@ -824,13 +837,14 @@ public final class Maps {
         public Iterator<Entry<K, V>> iterator() {
           return asMapEntryIterator(backingSet(), function);
         }
-      };
+      }
+      return new EntrySetImpl();
     }
   }
 
   static <K, V> Iterator<Entry<K, V>> asMapEntryIterator(
       Set<K> set, final Function<? super K, V> function) {
-    return new TransformedIterator<K, Entry<K,V>>(set.iterator()) {
+    return new TransformedIterator<K, Entry<K, V>>(set.iterator()) {
       @Override
       Entry<K, V> transform(final K key) {
         return immutableEntry(key, function.apply(key));
@@ -838,8 +852,7 @@ public final class Maps {
     };
   }
 
-  private static class SortedAsMapView<K, V> extends AsMapView<K, V>
-      implements SortedMap<K, V> {
+  private static class SortedAsMapView<K, V> extends AsMapView<K, V> implements SortedMap<K, V> {
 
     SortedAsMapView(SortedSet<K> set, Function<? super K, V> function) {
       super(set, function);
@@ -887,8 +900,7 @@ public final class Maps {
   }
 
   @GwtIncompatible("NavigableMap")
-  private static final class NavigableAsMapView<K, V>
-      extends AbstractNavigableMap<K, V> {
+  private static final class NavigableAsMapView<K, V> extends AbstractNavigableMap<K, V> {
     /*
      * Using AbstractNavigableMap is simpler than extending SortedAsMapView and rewriting all the
      * NavigableMap methods.
@@ -1044,8 +1056,7 @@ public final class Maps {
 
       @Override
       public SortedSet<E> subSet(E fromElement, E toElement) {
-        return removeOnlySortedSet(
-            super.subSet(fromElement, toElement));
+        return removeOnlySortedSet(super.subSet(fromElement, toElement));
       }
 
       @Override
@@ -1064,10 +1075,10 @@ public final class Maps {
       }
 
       @Override
-      public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
-          E toElement, boolean toInclusive) {
-        return removeOnlyNavigableSet(super.subSet(
-            fromElement, fromInclusive, toElement, toInclusive));
+      public NavigableSet<E> subSet(
+          E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+        return removeOnlyNavigableSet(
+            super.subSet(fromElement, fromInclusive, toElement, toInclusive));
       }
 
       @Override
@@ -1083,6 +1094,11 @@ public final class Maps {
    * The map's iteration order is the order of the first appearance of each key
    * in {@code keys}.
    *
+   * <p>When there are multiple instances of a key in {@code keys}, it is
+   * unspecified whether {@code valueFunction} will be applied to more than one
+   * instance of that key and, if it is, which result will be mapped to that
+   * key in the returned map.
+   *
    * <p>If {@code keys} is a {@link Set}, a live view can be obtained instead of
    * a copy using {@link Maps#asMap(Set, Function)}.
    *
@@ -1091,9 +1107,8 @@ public final class Maps {
    *     for any key
    * @since 14.0
    */
-  @Beta
-  public static <K, V> ImmutableMap<K, V> toMap(Iterable<K> keys,
-      Function<? super K, V> valueFunction) {
+  public static <K, V> ImmutableMap<K, V> toMap(
+      Iterable<K> keys, Function<? super K, V> valueFunction) {
     return toMap(keys.iterator(), valueFunction);
   }
 
@@ -1103,14 +1118,18 @@ public final class Maps {
    * The map's iteration order is the order of the first appearance of each key
    * in {@code keys}.
    *
+   * <p>When there are multiple instances of a key in {@code keys}, it is
+   * unspecified whether {@code valueFunction} will be applied to more than one
+   * instance of that key and, if it is, which result will be mapped to that
+   * key in the returned map.
+   *
    * @throws NullPointerException if any element of {@code keys} is
    *     {@code null}, or if {@code valueFunction} produces {@code null}
    *     for any key
    * @since 14.0
    */
-  @Beta
-  public static <K, V> ImmutableMap<K, V> toMap(Iterator<K> keys,
-      Function<? super K, V> valueFunction) {
+  public static <K, V> ImmutableMap<K, V> toMap(
+      Iterator<K> keys, Function<? super K, V> valueFunction) {
     checkNotNull(valueFunction);
     // Using LHM instead of a builder so as not to fail on duplicate keys
     Map<K, V> builder = newLinkedHashMap();
@@ -1122,9 +1141,22 @@ public final class Maps {
   }
 
   /**
-   * Returns an immutable map for which the {@link Map#values} are the given
-   * elements in the given order, and each key is the product of invoking a
-   * supplied function on its corresponding value.
+   * Returns a map with the given {@code values}, indexed by keys derived from
+   * those values. In other words, each input value produces an entry in the map
+   * whose key is the result of applying {@code keyFunction} to that value.
+   * These entries appear in the same order as the input values. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   ImmutableSet<Color> allColors = ImmutableSet.of(red, green, blue);
+   *
+   *   Map<String, Color> colorForName =
+   *       uniqueIndex(allColors, toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link
+   * Multimaps#index(Iterable, Function) Multimaps.index}.
    *
    * @param values the values to use when constructing the {@code Map}
    * @param keyFunction the function used to produce the key for each value
@@ -1137,13 +1169,27 @@ public final class Maps {
    */
   public static <K, V> ImmutableMap<K, V> uniqueIndex(
       Iterable<V> values, Function<? super V, K> keyFunction) {
+    // TODO(lowasser): consider presizing the builder if values is a Collection
     return uniqueIndex(values.iterator(), keyFunction);
   }
 
   /**
-   * Returns an immutable map for which the {@link Map#values} are the given
-   * elements in the given order, and each key is the product of invoking a
-   * supplied function on its corresponding value.
+   * Returns a map with the given {@code values}, indexed by keys derived from
+   * those values. In other words, each input value produces an entry in the map
+   * whose key is the result of applying {@code keyFunction} to that value.
+   * These entries appear in the same order as the input values. Example usage:
+   * <pre>   {@code
+   *
+   *   Color red = new Color("red", 255, 0, 0);
+   *   ...
+   *   Iterator<Color> allColors = ImmutableSet.of(red, green, blue).iterator();
+   *
+   *   Map<String, Color> colorForName =
+   *       uniqueIndex(allColors, toStringFunction());
+   *   assertThat(colorForName).containsEntry("red", red);}</pre>
+   *
+   * <p>If your index may associate multiple values with each key, use {@link
+   * Multimaps#index(Iterator, Function) Multimaps.index}.
    *
    * @param values the values to use when constructing the {@code Map}
    * @param keyFunction the function used to produce the key for each value
@@ -1163,7 +1209,13 @@ public final class Maps {
       V value = values.next();
       builder.put(keyFunction.apply(value), value);
     }
-    return builder.build();
+    try {
+      return builder.build();
+    } catch (IllegalArgumentException duplicateKeys) {
+      throw new IllegalArgumentException(
+          duplicateKeys.getMessage()
+              + ". To index multiple values under a key, use Multimaps.index.");
+    }
   }
 
   /**
@@ -1180,11 +1232,10 @@ public final class Maps {
    *         null
    */
   @GwtIncompatible("java.util.Properties")
-  public static ImmutableMap<String, String> fromProperties(
-      Properties properties) {
+  public static ImmutableMap<String, String> fromProperties(Properties properties) {
     ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
 
-    for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
+    for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
       String key = (String) e.nextElement();
       builder.put(key, properties.getProperty(key));
     }
@@ -1202,8 +1253,7 @@ public final class Maps {
    * @param value the value to be associated with the returned entry
    */
   @GwtCompatible(serializable = true)
-  public static <K, V> Entry<K, V> immutableEntry(
-      @Nullable K key, @Nullable V value) {
+  public static <K, V> Entry<K, V> immutableEntry(@Nullable K key, @Nullable V value) {
     return new ImmutableEntry<K, V>(key, value);
   }
 
@@ -1215,10 +1265,8 @@ public final class Maps {
    * @param entrySet the entries for which to return an unmodifiable view
    * @return an unmodifiable view of the entries
    */
-  static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(
-      Set<Entry<K, V>> entrySet) {
-    return new UnmodifiableEntrySet<K, V>(
-        Collections.unmodifiableSet(entrySet));
+  static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(Set<Entry<K, V>> entrySet) {
+    return new UnmodifiableEntrySet<K, V>(Collections.unmodifiableSet(entrySet));
   }
 
   /**
@@ -1233,68 +1281,80 @@ public final class Maps {
   static <K, V> Entry<K, V> unmodifiableEntry(final Entry<? extends K, ? extends V> entry) {
     checkNotNull(entry);
     return new AbstractMapEntry<K, V>() {
-      @Override public K getKey() {
+      @Override
+      public K getKey() {
         return entry.getKey();
       }
 
-      @Override public V getValue() {
+      @Override
+      public V getValue() {
         return entry.getValue();
       }
     };
   }
 
+  static <K, V> UnmodifiableIterator<Entry<K, V>> unmodifiableEntryIterator(
+      final Iterator<Entry<K, V>> entryIterator) {
+    return new UnmodifiableIterator<Entry<K, V>>() {
+      @Override
+      public boolean hasNext() {
+        return entryIterator.hasNext();
+      }
+
+      @Override
+      public Entry<K, V> next() {
+        return unmodifiableEntry(entryIterator.next());
+      }
+    };
+  }
+
   /** @see Multimaps#unmodifiableEntries */
-  static class UnmodifiableEntries<K, V>
-      extends ForwardingCollection<Entry<K, V>> {
+  static class UnmodifiableEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
     private final Collection<Entry<K, V>> entries;
 
     UnmodifiableEntries(Collection<Entry<K, V>> entries) {
       this.entries = entries;
     }
 
-    @Override protected Collection<Entry<K, V>> delegate() {
+    @Override
+    protected Collection<Entry<K, V>> delegate() {
       return entries;
     }
 
-    @Override public Iterator<Entry<K, V>> iterator() {
-      final Iterator<Entry<K, V>> delegate = super.iterator();
-      return new UnmodifiableIterator<Entry<K, V>>() {
-        @Override
-        public boolean hasNext() {
-          return delegate.hasNext();
-        }
-
-        @Override public Entry<K, V> next() {
-          return unmodifiableEntry(delegate.next());
-        }
-      };
+    @Override
+    public Iterator<Entry<K, V>> iterator() {
+      return unmodifiableEntryIterator(entries.iterator());
     }
 
     // See java.util.Collections.UnmodifiableEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       return standardToArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
   }
 
   /** @see Maps#unmodifiableEntrySet(Set) */
-  static class UnmodifiableEntrySet<K, V>
-      extends UnmodifiableEntries<K, V> implements Set<Entry<K, V>> {
+  static class UnmodifiableEntrySet<K, V> extends UnmodifiableEntries<K, V>
+      implements Set<Entry<K, V>> {
     UnmodifiableEntrySet(Set<Entry<K, V>> entries) {
       super(entries);
     }
 
     // See java.util.Collections.UnmodifiableEntrySet for details on attacks.
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return Sets.equalsImpl(this, object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Sets.hashCodeImpl(this);
     }
   }
@@ -1406,27 +1466,26 @@ public final class Maps {
    * @param bimap the bimap for which an unmodifiable view is to be returned
    * @return an unmodifiable view of the specified bimap
    */
-  public static <K, V> BiMap<K, V> unmodifiableBiMap(
-      BiMap<? extends K, ? extends V> bimap) {
+  public static <K, V> BiMap<K, V> unmodifiableBiMap(BiMap<? extends K, ? extends V> bimap) {
     return new UnmodifiableBiMap<K, V>(bimap, null);
   }
 
   /** @see Maps#unmodifiableBiMap(BiMap) */
-  private static class UnmodifiableBiMap<K, V>
-      extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
+  private static class UnmodifiableBiMap<K, V> extends ForwardingMap<K, V>
+      implements BiMap<K, V>, Serializable {
     final Map<K, V> unmodifiableMap;
     final BiMap<? extends K, ? extends V> delegate;
     BiMap<V, K> inverse;
     transient Set<V> values;
 
-    UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate,
-        @Nullable BiMap<V, K> inverse) {
+    UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @Nullable BiMap<V, K> inverse) {
       unmodifiableMap = Collections.unmodifiableMap(delegate);
       this.delegate = delegate;
       this.inverse = inverse;
     }
 
-    @Override protected Map<K, V> delegate() {
+    @Override
+    protected Map<K, V> delegate() {
       return unmodifiableMap;
     }
 
@@ -1443,7 +1502,8 @@ public final class Maps {
           : result;
     }
 
-    @Override public Set<V> values() {
+    @Override
+    public Set<V> values() {
       Set<V> result = values;
       return (result == null)
           ? values = Collections.unmodifiableSet(delegate.values())
@@ -1637,8 +1697,7 @@ public final class Maps {
    * @since 7.0
    */
   public static <K, V1, V2> Map<K, V2> transformEntries(
-      Map<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     if (fromMap instanceof SortedMap) {
       return transformEntries((SortedMap<K, V1>) fromMap, transformer);
     }
@@ -1698,8 +1757,7 @@ public final class Maps {
    * @since 11.0
    */
   public static <K, V1, V2> SortedMap<K, V2> transformEntries(
-      SortedMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return Platform.mapsTransformEntriesSortedMap(fromMap, transformer);
   }
 
@@ -1758,14 +1816,12 @@ public final class Maps {
    */
   @GwtIncompatible("NavigableMap")
   public static <K, V1, V2> NavigableMap<K, V2> transformEntries(
-      final NavigableMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      NavigableMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesNavigableMap<K, V1, V2>(fromMap, transformer);
   }
 
   static <K, V1, V2> SortedMap<K, V2> transformEntriesIgnoreNavigable(
-      SortedMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesSortedMap<K, V1, V2>(fromMap, transformer);
   }
 
@@ -1803,8 +1859,8 @@ public final class Maps {
   /**
    * Views a function as an entry transformer that ignores the entry key.
    */
-  static <K, V1, V2> EntryTransformer<K, V1, V2>
-      asEntryTransformer(final Function<? super V1, V2> function) {
+  static <K, V1, V2> EntryTransformer<K, V1, V2> asEntryTransformer(
+      final Function<? super V1, V2> function) {
     checkNotNull(function);
     return new EntryTransformer<K, V1, V2>() {
       @Override
@@ -1873,29 +1929,30 @@ public final class Maps {
     };
   }
 
-  static class TransformedEntriesMap<K, V1, V2>
-      extends ImprovedAbstractMap<K, V2> {
+  static class TransformedEntriesMap<K, V1, V2> extends IteratorBasedAbstractMap<K, V2> {
     final Map<K, V1> fromMap;
     final EntryTransformer<? super K, ? super V1, V2> transformer;
 
     TransformedEntriesMap(
-        Map<K, V1> fromMap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+        Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       this.fromMap = checkNotNull(fromMap);
       this.transformer = checkNotNull(transformer);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromMap.size();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return fromMap.containsKey(key);
     }
 
     // safe as long as the user followed the <b>Warning</b> in the javadoc
     @SuppressWarnings("unchecked")
-    @Override public V2 get(Object key) {
+    @Override
+    public V2 get(Object key) {
       V1 value = fromMap.get(key);
       return (value != null || fromMap.containsKey(key))
           ? transformer.transformEntry((K) key, value)
@@ -1904,169 +1961,192 @@ public final class Maps {
 
     // safe as long as the user followed the <b>Warning</b> in the javadoc
     @SuppressWarnings("unchecked")
-    @Override public V2 remove(Object key) {
+    @Override
+    public V2 remove(Object key) {
       return fromMap.containsKey(key)
           ? transformer.transformEntry((K) key, fromMap.remove(key))
           : null;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromMap.clear();
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return fromMap.keySet();
     }
 
     @Override
-    protected Set<Entry<K, V2>> createEntrySet() {
-      return new EntrySet<K, V2>() {
-        @Override Map<K, V2> map() {
-          return TransformedEntriesMap.this;
-        }
+    Iterator<Entry<K, V2>> entryIterator() {
+      return Iterators.transform(
+          fromMap.entrySet().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+    }
 
-        @Override public Iterator<Entry<K, V2>> iterator() {
-          return Iterators.transform(fromMap.entrySet().iterator(),
-              Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
-        }
-      };
+    @Override
+    public Collection<V2> values() {
+      return new Values<K, V2>(this);
     }
   }
 
-  static class TransformedEntriesSortedMap<K, V1, V2>
-      extends TransformedEntriesMap<K, V1, V2> implements SortedMap<K, V2> {
+  static class TransformedEntriesSortedMap<K, V1, V2> extends TransformedEntriesMap<K, V1, V2>
+      implements SortedMap<K, V2> {
 
     protected SortedMap<K, V1> fromMap() {
       return (SortedMap<K, V1>) fromMap;
     }
 
-    TransformedEntriesSortedMap(SortedMap<K, V1> fromMap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+    TransformedEntriesSortedMap(
+        SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       super(fromMap, transformer);
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       return fromMap().comparator();
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       return fromMap().firstKey();
     }
 
-    @Override public SortedMap<K, V2> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V2> headMap(K toKey) {
       return transformEntries(fromMap().headMap(toKey), transformer);
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       return fromMap().lastKey();
     }
 
-    @Override public SortedMap<K, V2> subMap(K fromKey, K toKey) {
-      return transformEntries(
-          fromMap().subMap(fromKey, toKey), transformer);
+    @Override
+    public SortedMap<K, V2> subMap(K fromKey, K toKey) {
+      return transformEntries(fromMap().subMap(fromKey, toKey), transformer);
     }
 
-    @Override public SortedMap<K, V2> tailMap(K fromKey) {
+    @Override
+    public SortedMap<K, V2> tailMap(K fromKey) {
       return transformEntries(fromMap().tailMap(fromKey), transformer);
     }
   }
 
   @GwtIncompatible("NavigableMap")
   private static class TransformedEntriesNavigableMap<K, V1, V2>
-      extends TransformedEntriesSortedMap<K, V1, V2>
-      implements NavigableMap<K, V2> {
+      extends TransformedEntriesSortedMap<K, V1, V2> implements NavigableMap<K, V2> {
 
-    TransformedEntriesNavigableMap(NavigableMap<K, V1> fromMap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+    TransformedEntriesNavigableMap(
+        NavigableMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       super(fromMap, transformer);
     }
 
-    @Override public Entry<K, V2> ceilingEntry(K key) {
+    @Override
+    public Entry<K, V2> ceilingEntry(K key) {
       return transformEntry(fromMap().ceilingEntry(key));
     }
 
-    @Override public K ceilingKey(K key) {
+    @Override
+    public K ceilingKey(K key) {
       return fromMap().ceilingKey(key);
     }
 
-    @Override public NavigableSet<K> descendingKeySet() {
+    @Override
+    public NavigableSet<K> descendingKeySet() {
       return fromMap().descendingKeySet();
     }
 
-    @Override public NavigableMap<K, V2> descendingMap() {
+    @Override
+    public NavigableMap<K, V2> descendingMap() {
       return transformEntries(fromMap().descendingMap(), transformer);
     }
 
-    @Override public Entry<K, V2> firstEntry() {
+    @Override
+    public Entry<K, V2> firstEntry() {
       return transformEntry(fromMap().firstEntry());
     }
-    @Override public Entry<K, V2> floorEntry(K key) {
+
+    @Override
+    public Entry<K, V2> floorEntry(K key) {
       return transformEntry(fromMap().floorEntry(key));
     }
 
-    @Override public K floorKey(K key) {
+    @Override
+    public K floorKey(K key) {
       return fromMap().floorKey(key);
     }
 
-    @Override public NavigableMap<K, V2> headMap(K toKey) {
+    @Override
+    public NavigableMap<K, V2> headMap(K toKey) {
       return headMap(toKey, false);
     }
 
-    @Override public NavigableMap<K, V2> headMap(K toKey, boolean inclusive) {
-      return transformEntries(
-          fromMap().headMap(toKey, inclusive), transformer);
+    @Override
+    public NavigableMap<K, V2> headMap(K toKey, boolean inclusive) {
+      return transformEntries(fromMap().headMap(toKey, inclusive), transformer);
     }
 
-    @Override public Entry<K, V2> higherEntry(K key) {
+    @Override
+    public Entry<K, V2> higherEntry(K key) {
       return transformEntry(fromMap().higherEntry(key));
     }
 
-    @Override public K higherKey(K key) {
+    @Override
+    public K higherKey(K key) {
       return fromMap().higherKey(key);
     }
 
-    @Override public Entry<K, V2> lastEntry() {
+    @Override
+    public Entry<K, V2> lastEntry() {
       return transformEntry(fromMap().lastEntry());
     }
 
-    @Override public Entry<K, V2> lowerEntry(K key) {
+    @Override
+    public Entry<K, V2> lowerEntry(K key) {
       return transformEntry(fromMap().lowerEntry(key));
     }
 
-    @Override public K lowerKey(K key) {
+    @Override
+    public K lowerKey(K key) {
       return fromMap().lowerKey(key);
     }
 
-    @Override public NavigableSet<K> navigableKeySet() {
+    @Override
+    public NavigableSet<K> navigableKeySet() {
       return fromMap().navigableKeySet();
     }
 
-    @Override public Entry<K, V2> pollFirstEntry() {
+    @Override
+    public Entry<K, V2> pollFirstEntry() {
       return transformEntry(fromMap().pollFirstEntry());
     }
 
-    @Override public Entry<K, V2> pollLastEntry() {
+    @Override
+    public Entry<K, V2> pollLastEntry() {
       return transformEntry(fromMap().pollLastEntry());
     }
 
-    @Override public NavigableMap<K, V2> subMap(
+    @Override
+    public NavigableMap<K, V2> subMap(
         K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
       return transformEntries(
-          fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive),
-          transformer);
+          fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), transformer);
     }
 
-    @Override public NavigableMap<K, V2> subMap(K fromKey, K toKey) {
+    @Override
+    public NavigableMap<K, V2> subMap(K fromKey, K toKey) {
       return subMap(fromKey, true, toKey, false);
     }
 
-    @Override public NavigableMap<K, V2> tailMap(K fromKey) {
+    @Override
+    public NavigableMap<K, V2> tailMap(K fromKey) {
       return tailMap(fromKey, true);
     }
 
-    @Override public NavigableMap<K, V2> tailMap(K fromKey, boolean inclusive) {
-      return transformEntries(
-          fromMap().tailMap(fromKey, inclusive), transformer);
+    @Override
+    public NavigableMap<K, V2> tailMap(K fromKey, boolean inclusive) {
+      return transformEntries(fromMap().tailMap(fromKey, inclusive), transformer);
     }
 
     @Nullable
@@ -2074,7 +2154,8 @@ public final class Maps {
       return (entry == null) ? null : Maps.transformEntry(transformer, entry);
     }
 
-    @Override protected NavigableMap<K, V1> fromMap() {
+    @Override
+    protected NavigableMap<K, V1> fromMap() {
       return (NavigableMap<K, V1>) super.fromMap();
     }
   }
@@ -2115,6 +2196,7 @@ public final class Maps {
    * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
    * inconsistent with equals.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterKeys(
       Map<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -2126,8 +2208,7 @@ public final class Maps {
     Predicate<Entry<K, ?>> entryPredicate = keyPredicateOnEntries(keyPredicate);
     return (unfiltered instanceof AbstractFilteredMap)
         ? filterFiltered((AbstractFilteredMap<K, V>) unfiltered, entryPredicate)
-        : new FilteredKeyMap<K, V>(
-            checkNotNull(unfiltered), keyPredicate, entryPredicate);
+        : new FilteredKeyMap<K, V>(checkNotNull(unfiltered), keyPredicate, entryPredicate);
   }
 
   /**
@@ -2160,9 +2241,10 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterKeys(
       SortedMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
-    // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+    // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
     // performance.
     return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
   }
@@ -2198,9 +2280,10 @@ public final class Maps {
    * @since 14.0
    */
   @GwtIncompatible("NavigableMap")
+  @CheckReturnValue
   public static <K, V> NavigableMap<K, V> filterKeys(
       NavigableMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
-    // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+    // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
     // performance.
     return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
   }
@@ -2230,6 +2313,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterKeys(
       BiMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     checkNotNull(keyPredicate);
@@ -2265,6 +2349,7 @@ public final class Maps {
    * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
    * inconsistent with equals.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterValues(
       Map<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -2306,6 +2391,7 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterValues(
       SortedMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2343,6 +2429,7 @@ public final class Maps {
    * @since 14.0
    */
   @GwtIncompatible("NavigableMap")
+  @CheckReturnValue
   public static <K, V> NavigableMap<K, V> filterValues(
       NavigableMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2376,6 +2463,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterValues(
       BiMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2410,6 +2498,7 @@ public final class Maps {
    * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
    * equals</i>, as documented at {@link Predicate#apply}.
    */
+  @CheckReturnValue
   public static <K, V> Map<K, V> filterEntries(
       Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     if (unfiltered instanceof SortedMap) {
@@ -2454,15 +2543,14 @@ public final class Maps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> SortedMap<K, V> filterEntries(
-      SortedMap<K, V> unfiltered,
-      Predicate<? super Entry<K, V>> entryPredicate) {
+      SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     return Platform.mapsFilterSortedMap(unfiltered, entryPredicate);
   }
 
   static <K, V> SortedMap<K, V> filterSortedIgnoreNavigable(
-      SortedMap<K, V> unfiltered,
-      Predicate<? super Entry<K, V>> entryPredicate) {
+      SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
     return (unfiltered instanceof FilteredEntrySortedMap)
         ? filterFiltered((FilteredEntrySortedMap<K, V>) unfiltered, entryPredicate)
@@ -2501,9 +2589,9 @@ public final class Maps {
    * @since 14.0
    */
   @GwtIncompatible("NavigableMap")
+  @CheckReturnValue
   public static <K, V> NavigableMap<K, V> filterEntries(
-      NavigableMap<K, V> unfiltered,
-      Predicate<? super Entry<K, V>> entryPredicate) {
+      NavigableMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
     return (unfiltered instanceof FilteredEntryNavigableMap)
         ? filterFiltered((FilteredEntryNavigableMap<K, V>) unfiltered, entryPredicate)
@@ -2537,6 +2625,7 @@ public final class Maps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> BiMap<K, V> filterEntries(
       BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(unfiltered);
@@ -2550,19 +2639,17 @@ public final class Maps {
    * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
    * filtering a filtered map.
    */
-  private static <K, V> Map<K, V> filterFiltered(AbstractFilteredMap<K, V> map,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    return new FilteredEntryMap<K, V>(map.unfiltered,
-        Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
+  private static <K, V> Map<K, V> filterFiltered(
+      AbstractFilteredMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+    return new FilteredEntryMap<K, V>(
+        map.unfiltered, Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
   }
 
-  private abstract static class AbstractFilteredMap<K, V>
-      extends ImprovedAbstractMap<K, V> {
+  private abstract static class AbstractFilteredMap<K, V> extends ViewCachingAbstractMap<K, V> {
     final Map<K, V> unfiltered;
     final Predicate<? super Entry<K, V>> predicate;
 
-    AbstractFilteredMap(
-        Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
+    AbstractFilteredMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
       this.unfiltered = unfiltered;
       this.predicate = predicate;
     }
@@ -2575,32 +2662,38 @@ public final class Maps {
       return predicate.apply(Maps.immutableEntry(k, value));
     }
 
-    @Override public V put(K key, V value) {
+    @Override
+    public V put(K key, V value) {
       checkArgument(apply(key, value));
       return unfiltered.put(key, value);
     }
 
-    @Override public void putAll(Map<? extends K, ? extends V> map) {
+    @Override
+    public void putAll(Map<? extends K, ? extends V> map) {
       for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
         checkArgument(apply(entry.getKey(), entry.getValue()));
       }
       unfiltered.putAll(map);
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return unfiltered.containsKey(key) && apply(key, unfiltered.get(key));
     }
 
-    @Override public V get(Object key) {
+    @Override
+    public V get(Object key) {
       V value = unfiltered.get(key);
       return ((value != null) && apply(key, value)) ? value : null;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return entrySet().isEmpty();
     }
 
-    @Override public V remove(Object key) {
+    @Override
+    public V remove(Object key) {
       return containsKey(key) ? unfiltered.remove(key) : null;
     }
 
@@ -2614,38 +2707,45 @@ public final class Maps {
     Map<K, V> unfiltered;
     Predicate<? super Entry<K, V>> predicate;
 
-    FilteredMapValues(Map<K, V> filteredMap, Map<K, V> unfiltered,
-        Predicate<? super Entry<K, V>> predicate) {
+    FilteredMapValues(
+        Map<K, V> filteredMap, Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
       super(filteredMap);
       this.unfiltered = unfiltered;
       this.predicate = predicate;
     }
 
-    @Override public boolean remove(Object o) {
-      return Iterables.removeFirstMatching(unfiltered.entrySet(),
-          Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
+    @Override
+    public boolean remove(Object o) {
+      return Iterables.removeFirstMatching(
+              unfiltered.entrySet(),
+              Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
           != null;
     }
 
     private boolean removeIf(Predicate<? super V> valuePredicate) {
-      return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
-          predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
+      return Iterables.removeIf(
+          unfiltered.entrySet(),
+          Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
     }
 
-    @Override public boolean removeAll(Collection<?> collection) {
+    @Override
+    public boolean removeAll(Collection<?> collection) {
       return removeIf(in(collection));
     }
 
-    @Override public boolean retainAll(Collection<?> collection) {
+    @Override
+    public boolean retainAll(Collection<?> collection) {
       return removeIf(not(in(collection)));
     }
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       // creating an ArrayList so filtering happens once
       return Lists.newArrayList(iterator()).toArray();
     }
 
-    @Override public <T> T[] toArray(T[] array) {
+    @Override
+    public <T> T[] toArray(T[] array) {
       return Lists.newArrayList(iterator()).toArray(array);
     }
   }
@@ -2653,7 +2753,9 @@ public final class Maps {
   private static class FilteredKeyMap<K, V> extends AbstractFilteredMap<K, V> {
     Predicate<? super K> keyPredicate;
 
-    FilteredKeyMap(Map<K, V> unfiltered, Predicate<? super K> keyPredicate,
+    FilteredKeyMap(
+        Map<K, V> unfiltered,
+        Predicate<? super K> keyPredicate,
         Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
       this.keyPredicate = keyPredicate;
@@ -2685,8 +2787,7 @@ public final class Maps {
      */
     final Set<Entry<K, V>> filteredEntrySet;
 
-    FilteredEntryMap(
-        Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
+    FilteredEntryMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
       filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate);
     }
@@ -2696,12 +2797,15 @@ public final class Maps {
       return new EntrySet();
     }
 
+    @WeakOuter
     private class EntrySet extends ForwardingSet<Entry<K, V>> {
-      @Override protected Set<Entry<K, V>> delegate() {
+      @Override
+      protected Set<Entry<K, V>> delegate() {
         return filteredEntrySet;
       }
 
-      @Override public Iterator<Entry<K, V>> iterator() {
+      @Override
+      public Iterator<Entry<K, V>> iterator() {
         return new TransformedIterator<Entry<K, V>, Entry<K, V>>(filteredEntrySet.iterator()) {
           @Override
           Entry<K, V> transform(final Entry<K, V> entry) {
@@ -2727,12 +2831,14 @@ public final class Maps {
       return new KeySet();
     }
 
+    @WeakOuter
     class KeySet extends Maps.KeySet<K, V> {
       KeySet() {
         super(FilteredEntryMap.this);
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (containsKey(o)) {
           unfiltered.remove(o);
           return true;
@@ -2741,8 +2847,9 @@ public final class Maps {
       }
 
       private boolean removeIf(Predicate<? super K> keyPredicate) {
-        return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
-            predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
+        return Iterables.removeIf(
+            unfiltered.entrySet(),
+            Predicates.<Entry<K, V>>and(predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
       }
 
       @Override
@@ -2755,12 +2862,14 @@ public final class Maps {
         return removeIf(not(in(c)));
       }
 
-      @Override public Object[] toArray() {
+      @Override
+      public Object[] toArray() {
         // creating an ArrayList so filtering happens once
         return Lists.newArrayList(iterator()).toArray();
       }
 
-      @Override public <T> T[] toArray(T[] array) {
+      @Override
+      public <T> T[] toArray(T[] array) {
         return Lists.newArrayList(iterator()).toArray(array);
       }
     }
@@ -2771,18 +2880,16 @@ public final class Maps {
    * filtering a filtered sorted map.
    */
   private static <K, V> SortedMap<K, V> filterFiltered(
-      FilteredEntrySortedMap<K, V> map,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(map.predicate, entryPredicate);
+      FilteredEntrySortedMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(map.predicate, entryPredicate);
     return new FilteredEntrySortedMap<K, V>(map.sortedMap(), predicate);
   }
 
-  private static class FilteredEntrySortedMap<K, V>
-      extends FilteredEntryMap<K, V> implements SortedMap<K, V> {
+  private static class FilteredEntrySortedMap<K, V> extends FilteredEntryMap<K, V>
+      implements SortedMap<K, V> {
 
-    FilteredEntrySortedMap(SortedMap<K, V> unfiltered,
-        Predicate<? super Entry<K, V>> entryPredicate) {
+    FilteredEntrySortedMap(
+        SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
       super(unfiltered, entryPredicate);
     }
 
@@ -2790,7 +2897,8 @@ public final class Maps {
       return (SortedMap<K, V>) unfiltered;
     }
 
-    @Override public SortedSet<K> keySet() {
+    @Override
+    public SortedSet<K> keySet() {
       return (SortedSet<K>) super.keySet();
     }
 
@@ -2799,6 +2907,7 @@ public final class Maps {
       return new SortedKeySet();
     }
 
+    @WeakOuter
     class SortedKeySet extends KeySet implements SortedSet<K> {
       @Override
       public Comparator<? super K> comparator() {
@@ -2831,16 +2940,19 @@ public final class Maps {
       }
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       return sortedMap().comparator();
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       // correctly throws NoSuchElementException when filtered map is empty.
       return keySet().iterator().next();
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       SortedMap<K, V> headMap = sortedMap();
       while (true) {
         // correctly throws NoSuchElementException when filtered map is empty.
@@ -2852,18 +2964,19 @@ public final class Maps {
       }
     }
 
-    @Override public SortedMap<K, V> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V> headMap(K toKey) {
       return new FilteredEntrySortedMap<K, V>(sortedMap().headMap(toKey), predicate);
     }
 
-    @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
-      return new FilteredEntrySortedMap<K, V>(
-          sortedMap().subMap(fromKey, toKey), predicate);
+    @Override
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
+      return new FilteredEntrySortedMap<K, V>(sortedMap().subMap(fromKey, toKey), predicate);
     }
 
-    @Override public SortedMap<K, V> tailMap(K fromKey) {
-      return new FilteredEntrySortedMap<K, V>(
-          sortedMap().tailMap(fromKey), predicate);
+    @Override
+    public SortedMap<K, V> tailMap(K fromKey) {
+      return new FilteredEntrySortedMap<K, V>(sortedMap().tailMap(fromKey), predicate);
     }
   }
 
@@ -2873,10 +2986,8 @@ public final class Maps {
    */
   @GwtIncompatible("NavigableMap")
   private static <K, V> NavigableMap<K, V> filterFiltered(
-      FilteredEntryNavigableMap<K, V> map,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(map.entryPredicate, entryPredicate);
+      FilteredEntryNavigableMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(map.entryPredicate, entryPredicate);
     return new FilteredEntryNavigableMap<K, V>(map.unfiltered, predicate);
   }
 
@@ -2909,14 +3020,17 @@ public final class Maps {
       return new Maps.NavigableKeySet<K, V>(this) {
         @Override
         public boolean removeAll(Collection<?> c) {
-          return Iterators.removeIf(unfiltered.entrySet().iterator(),
+          return Iterators.removeIf(
+              unfiltered.entrySet().iterator(),
               Predicates.<Entry<K, V>>and(entryPredicate, Maps.<K>keyPredicateOnEntries(in(c))));
         }
 
         @Override
         public boolean retainAll(Collection<?> c) {
-          return Iterators.removeIf(unfiltered.entrySet().iterator(), Predicates.<Entry<K, V>>and(
-              entryPredicate, Maps.<K>keyPredicateOnEntries(not(in(c)))));
+          return Iterators.removeIf(
+              unfiltered.entrySet().iterator(),
+              Predicates.<Entry<K, V>>and(
+                  entryPredicate, Maps.<K>keyPredicateOnEntries(not(in(c)))));
         }
       };
     }
@@ -3034,22 +3148,19 @@ public final class Maps {
       return new Predicate<Entry<V, K>>() {
         @Override
         public boolean apply(Entry<V, K> input) {
-          return forwardPredicate.apply(
-              Maps.immutableEntry(input.getValue(), input.getKey()));
+          return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey()));
         }
       };
     }
 
-    FilteredEntryBiMap(BiMap<K, V> delegate,
-        Predicate<? super Entry<K, V>> predicate) {
+    FilteredEntryBiMap(BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate) {
       super(delegate, predicate);
-      this.inverse = new FilteredEntryBiMap<V, K>(
-          delegate.inverse(), inversePredicate(predicate), this);
+      this.inverse =
+          new FilteredEntryBiMap<V, K>(delegate.inverse(), inversePredicate(predicate), this);
     }
 
     private FilteredEntryBiMap(
-        BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate,
-        BiMap<V, K> inverse) {
+        BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate, BiMap<V, K> inverse) {
       super(delegate, predicate);
       this.inverse = inverse;
     }
@@ -3097,13 +3208,14 @@ public final class Maps {
     }
   }
 
-  @Nullable private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
+  @Nullable
+  private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
     return (entry == null) ? null : Maps.unmodifiableEntry(entry);
   }
 
   @GwtIncompatible("NavigableMap")
-  static class UnmodifiableNavigableMap<K, V>
-      extends ForwardingSortedMap<K, V> implements NavigableMap<K, V>, Serializable {
+  static class UnmodifiableNavigableMap<K, V> extends ForwardingSortedMap<K, V>
+      implements NavigableMap<K, V>, Serializable {
     private final NavigableMap<K, V> delegate;
 
     UnmodifiableNavigableMap(NavigableMap<K, V> delegate) {
@@ -3222,14 +3334,10 @@ public final class Maps {
     }
 
     @Override
-    public
-        NavigableMap<K, V>
-        subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
-      return Maps.unmodifiableNavigableMap(delegate.subMap(
-          fromKey,
-          fromInclusive,
-          toKey,
-          toInclusive));
+    public NavigableMap<K, V> subMap(
+        K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+      return Maps.unmodifiableNavigableMap(
+          delegate.subMap(fromKey, fromInclusive, toKey, toInclusive));
     }
 
     @Override
@@ -3298,14 +3406,11 @@ public final class Maps {
   }
 
   /**
-   * {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code
-   * entrySet().isEmpty()} instead of {@code size() == 0} to speed up
-   * implementations where {@code size()} is O(n), and it delegates the {@code
-   * isEmpty()} methods of its key set and value collection to this
-   * implementation.
+   * {@code AbstractMap} extension that makes it easy to cache customized keySet, values,
+   * and entrySet views.
    */
   @GwtCompatible
-  abstract static class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
+  abstract static class ViewCachingAbstractMap<K, V> extends AbstractMap<K, V> {
     /**
      * Creates the entry set to be returned by {@link #entrySet()}. This method
      * is invoked at most once on a given map, at the time when {@code entrySet}
@@ -3315,14 +3420,16 @@ public final class Maps {
 
     private transient Set<Entry<K, V>> entrySet;
 
-    @Override public Set<Entry<K, V>> entrySet() {
+    @Override
+    public Set<Entry<K, V>> entrySet() {
       Set<Entry<K, V>> result = entrySet;
       return (result == null) ? entrySet = createEntrySet() : result;
     }
 
     private transient Set<K> keySet;
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       Set<K> result = keySet;
       return (result == null) ? keySet = createKeySet() : result;
     }
@@ -3333,7 +3440,8 @@ public final class Maps {
 
     private transient Collection<V> values;
 
-    @Override public Collection<V> values() {
+    @Override
+    public Collection<V> values() {
       Collection<V> result = values;
       return (result == null) ? values = createValues() : result;
     }
@@ -3343,6 +3451,33 @@ public final class Maps {
     }
   }
 
+  abstract static class IteratorBasedAbstractMap<K, V> extends AbstractMap<K, V> {
+    @Override
+    public abstract int size();
+
+    abstract Iterator<Entry<K, V>> entryIterator();
+
+    @Override
+    public Set<Entry<K, V>> entrySet() {
+      return new EntrySet<K, V>() {
+        @Override
+        Map<K, V> map() {
+          return IteratorBasedAbstractMap.this;
+        }
+
+        @Override
+        public Iterator<Entry<K, V>> iterator() {
+          return entryIterator();
+        }
+      };
+    }
+
+    @Override
+    public void clear() {
+      Iterators.clear(entryIterator());
+    }
+  }
+
   /**
    * Delegates to {@link Map#get}. Returns {@code null} on {@code
    * ClassCastException} and {@code NullPointerException}.
@@ -3455,15 +3590,13 @@ public final class Maps {
     return false;
   }
 
-  static final MapJoiner STANDARD_JOINER =
-      Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
+  static final MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
 
   /**
    * An implementation of {@link Map#toString}.
    */
   static String toStringImpl(Map<?, ?> map) {
-    StringBuilder sb
-        = Collections2.newStringBuilderForCollection(map.size()).append('{');
+    StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{');
     STANDARD_JOINER.appendTo(sb, map);
     return sb.append('}').toString();
   }
@@ -3471,15 +3604,14 @@ public final class Maps {
   /**
    * An implementation of {@link Map#putAll}.
    */
-  static <K, V> void putAllImpl(
-      Map<K, V> self, Map<? extends K, ? extends V> map) {
+  static <K, V> void putAllImpl(Map<K, V> self, Map<? extends K, ? extends V> map) {
     for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
       self.put(entry.getKey(), entry.getValue());
     }
   }
 
   static class KeySet<K, V> extends Sets.ImprovedAbstractSet<K> {
-    final Map<K, V> map;
+    @Weak final Map<K, V> map;
 
     KeySet(Map<K, V> map) {
       this.map = checkNotNull(map);
@@ -3489,23 +3621,28 @@ public final class Maps {
       return map;
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return keyIterator(map().entrySet().iterator());
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return map().containsKey(o);
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       if (contains(o)) {
         map().remove(o);
         return true;
@@ -3513,7 +3650,8 @@ public final class Maps {
       return false;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
   }
@@ -3622,10 +3760,7 @@ public final class Maps {
 
     @Override
     public NavigableSet<K> subSet(
-        K fromElement,
-        boolean fromInclusive,
-        K toElement,
-        boolean toInclusive) {
+        K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) {
       return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet();
     }
 
@@ -3656,7 +3791,7 @@ public final class Maps {
   }
 
   static class Values<K, V> extends AbstractCollection<V> {
-    final Map<K, V> map;
+    @Weak final Map<K, V> map;
 
     Values(Map<K, V> map) {
       this.map = checkNotNull(map);
@@ -3666,11 +3801,13 @@ public final class Maps {
       return map;
     }
 
-    @Override public Iterator<V> iterator() {
+    @Override
+    public Iterator<V> iterator() {
       return valueIterator(map().entrySet().iterator());
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       try {
         return super.remove(o);
       } catch (UnsupportedOperationException e) {
@@ -3684,7 +3821,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       try {
         return super.removeAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -3698,7 +3836,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       try {
         return super.retainAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -3712,51 +3851,58 @@ public final class Maps {
       }
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       return map().containsValue(o);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
   }
 
-  abstract static class EntrySet<K, V>
-      extends Sets.ImprovedAbstractSet<Entry<K, V>> {
+  abstract static class EntrySet<K, V> extends Sets.ImprovedAbstractSet<Entry<K, V>> {
     abstract Map<K, V> map();
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return map().size();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       map().clear();
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       if (o instanceof Entry) {
         Entry<?, ?> entry = (Entry<?, ?>) o;
         Object key = entry.getKey();
         V value = Maps.safeGet(map(), key);
-        return Objects.equal(value, entry.getValue())
-            && (value != null || map().containsKey(key));
+        return Objects.equal(value, entry.getValue()) && (value != null || map().containsKey(key));
       }
       return false;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return map().isEmpty();
     }
 
-    @Override public boolean remove(Object o) {
+    @Override
+    public boolean remove(Object o) {
       if (contains(o)) {
         Entry<?, ?> entry = (Entry<?, ?>) o;
         return map().keySet().remove(entry.getKey());
@@ -3764,7 +3910,8 @@ public final class Maps {
       return false;
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       try {
         return super.removeAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -3773,7 +3920,8 @@ public final class Maps {
       }
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       try {
         return super.retainAll(checkNotNull(c));
       } catch (UnsupportedOperationException e) {
@@ -3908,7 +4056,8 @@ public final class Maps {
     abstract Iterator<Entry<K, V>> entryIterator();
 
     Set<Entry<K, V>> createEntrySet() {
-      return new EntrySet<K, V>() {
+      @WeakOuter
+      class EntrySetImpl extends EntrySet<K, V> {
         @Override
         Map<K, V> map() {
           return DescendingMap.this;
@@ -3918,7 +4067,8 @@ public final class Maps {
         public Iterator<Entry<K, V>> iterator() {
           return entryIterator();
         }
-      };
+      }
+      return new EntrySetImpl();
     }
 
     @Override
@@ -3940,9 +4090,8 @@ public final class Maps {
     }
 
     @Override
-    public
-    NavigableMap<K, V>
-    subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+    public NavigableMap<K, V> subMap(
+        K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
       return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap();
     }
 
@@ -3981,4 +4130,16 @@ public final class Maps {
       return standardToString();
     }
   }
+
+  /**
+   * Returns a map from the ith element of list to i.
+   */
+  static <E> ImmutableMap<E, Integer> indexMap(Collection<E> list) {
+    ImmutableMap.Builder<E, Integer> builder = new ImmutableMap.Builder<E, Integer>(list.size());
+    int i = 0;
+    for (E e : list) {
+      builder.put(e, i++);
+    }
+    return builder.build();
+  }
 }
diff --git a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
index bb23f40..451eec8 100644
--- a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
+++ b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
@@ -25,6 +25,8 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.math.IntMath;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.AbstractQueue;
 import java.util.ArrayDeque;
@@ -42,8 +44,15 @@ import java.util.Queue;
 /**
  * A double-ended priority queue, which provides constant-time access to both
  * its least element and its greatest element, as determined by the queue's
- * specified comparator. If no comparator is given at construction time, the
- * natural order of elements is used.
+ * specified comparator. If no comparator is given at creation time, the
+ * natural order of elements is used. If no maximum size is given at creation time,
+ * the queue is unbounded.
+ *
+ * <p>Usage example: <pre>   {@code
+ *
+ *   MinMaxPriorityQueue<User> users = MinMaxPriorityQueue.orderedBy(userComparator)
+ *       .maximumSize(1000)
+ *       .create();}</pre>
  *
  * <p>As a {@link Queue} it functions exactly as a {@link PriorityQueue}: its
  * head element -- the implicit target of the methods {@link #peek()}, {@link
@@ -70,13 +79,18 @@ import java.util.Queue;
  * <p><i>Performance notes:</i>
  *
  * <ul>
+ * <li>If you only access one end of the queue, and do use a maximum size,
+ *     this class will perform significantly worse than a {@code PriorityQueue}
+ *     with manual eviction above the maximum size.  In many cases
+ *     {@link Ordering#leastOf} may work for your use case with significantly
+ *     improved (and asymptotically superior) performance.
  * <li>The retrieval operations {@link #peek}, {@link #peekFirst}, {@link
- *     #peekLast}, {@link #element}, and {@link #size} are constant-time
+ *     #peekLast}, {@link #element}, and {@link #size} are constant-time.
  * <li>The enqueing and dequeing operations ({@link #offer}, {@link #add}, and
  *     all the forms of {@link #poll} and {@link #remove()}) run in {@code
- *     O(log n) time}
+ *     O(log n) time}.
  * <li>The {@link #remove(Object)} and {@link #contains} operations require
- *     linear ({@code O(n)}) time
+ *     linear ({@code O(n)}) time.
  * <li>If you only access one end of the queue, and don't use a maximum size,
  *     this class is functionally equivalent to {@link PriorityQueue}, but
  *     significantly slower.
@@ -122,8 +136,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    * expectedSize} elements.
    */
   public static Builder<Comparable> expectedSize(int expectedSize) {
-    return new Builder<Comparable>(Ordering.natural())
-        .expectedSize(expectedSize);
+    return new Builder<Comparable>(Ordering.natural()).expectedSize(expectedSize);
   }
 
   /**
@@ -134,8 +147,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    * the element that was just added.
    */
   public static Builder<Comparable> maximumSize(int maximumSize) {
-    return new Builder<Comparable>(Ordering.natural())
-        .maximumSize(maximumSize);
+    return new Builder<Comparable>(Ordering.natural()).maximumSize(maximumSize);
   }
 
   /**
@@ -201,10 +213,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
      * Builds a new min-max priority queue using the previously specified
      * options, and having the given initial elements.
      */
-    public <T extends B> MinMaxPriorityQueue<T> create(
-        Iterable<? extends T> initialContents) {
-      MinMaxPriorityQueue<T> queue = new MinMaxPriorityQueue<T>(
-          this, initialQueueSize(expectedSize, maximumSize, initialContents));
+    public <T extends B> MinMaxPriorityQueue<T> create(Iterable<? extends T> initialContents) {
+      MinMaxPriorityQueue<T> queue =
+          new MinMaxPriorityQueue<T>(
+              this, initialQueueSize(expectedSize, maximumSize, initialContents));
       for (T element : initialContents) {
         queue.offer(element);
       }
@@ -236,7 +248,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     this.queue = new Object[queueSize];
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return size;
   }
 
@@ -248,12 +261,14 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    *
    * @return {@code true} always
    */
-  @Override public boolean add(E element) {
+  @Override
+  public boolean add(E element) {
     offer(element);
     return true;
   }
 
-  @Override public boolean addAll(Collection<? extends E> newElements) {
+  @Override
+  public boolean addAll(Collection<? extends E> newElements) {
     boolean modified = false;
     for (E element : newElements) {
       offer(element);
@@ -268,7 +283,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    * greatest element (according to its comparator), which may be {@code
    * element} itself.
    */
-  @Override public boolean offer(E element) {
+  @Override
+  public boolean offer(E element) {
     checkNotNull(element);
     modCount++;
     int insertIndex = size++;
@@ -281,7 +297,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     return size <= maximumSize || pollLast() != element;
   }
 
-  @Override public E poll() {
+  @Override
+  public E poll() {
     return isEmpty() ? null : removeAndGet(0);
   }
 
@@ -290,7 +307,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     return (E) queue[index];
   }
 
-  @Override public E peek() {
+  @Override
+  public E peek() {
     return isEmpty() ? null : elementData(0);
   }
 
@@ -378,7 +396,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    * used by iterator.remove so as to visit elements during a traversal once and
    * only once.
    */
-  @VisibleForTesting MoveDesc<E> removeAt(int index) {
+  @VisibleForTesting
+  MoveDesc<E> removeAt(int index) {
     checkPositionIndex(index, size);
     modCount++;
     size--;
@@ -387,8 +406,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
       return null;
     }
     E actualLastElement = elementData(size);
-    int lastElementAt = heapForIndex(size)
-        .getCorrectLastElement(actualLastElement);
+    int lastElementAt = heapForIndex(size).getCorrectLastElement(actualLastElement);
     E toTrickle = elementData(size);
     queue[size] = null;
     MoveDesc<E> changes = fillHole(index, toTrickle);
@@ -425,9 +443,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
       // there.
       return heap.tryCrossOverAndBubbleUp(index, vacated, toTrickle);
     } else {
-      return (bubbledTo < index)
-          ? new MoveDesc<E>(toTrickle, elementData(index))
-          : null;
+      return (bubbledTo < index) ? new MoveDesc<E>(toTrickle, elementData(index)) : null;
     }
   }
 
@@ -458,7 +474,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
   private static final int EVEN_POWERS_OF_TWO = 0x55555555;
   private static final int ODD_POWERS_OF_TWO = 0xaaaaaaaa;
 
-  @VisibleForTesting static boolean isEvenLevel(int index) {
+  @VisibleForTesting
+  static boolean isEvenLevel(int index) {
     int oneBased = index + 1;
     checkState(oneBased > 0, "negative index");
     return (oneBased & EVEN_POWERS_OF_TWO) > (oneBased & ODD_POWERS_OF_TWO);
@@ -470,7 +487,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    *
    * TODO(kevinb): move to the test class?
    */
-  @VisibleForTesting boolean isIntact() {
+  @VisibleForTesting
+  boolean isIntact() {
     for (int i = 1; i < size; i++) {
       if (!heapForIndex(i).verifyIndex(i)) {
         return false;
@@ -485,9 +503,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    * array for storage, but for efficiency's sake they are stored interleaved on
    * alternate heap levels in the same array (MMPQ.queue).
    */
+  @WeakOuter
   private class Heap {
     final Ordering<E> ordering;
-    Heap otherHeap;
+    @Weak Heap otherHeap;
 
     Heap(Ordering<E> ordering) {
       this.ordering = ordering;
@@ -502,8 +521,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
      * bubble up there. If it moved before {@code removeIndex} this method
      * returns a pair as described in {@link #removeAt}.
      */
-    MoveDesc<E> tryCrossOverAndBubbleUp(
-        int removeIndex, int vacated, E toTrickle) {
+    MoveDesc<E> tryCrossOverAndBubbleUp(int removeIndex, int vacated, E toTrickle) {
       int crossOver = crossOver(vacated, toTrickle);
       if (crossOver == vacated) {
         return null;
@@ -522,8 +540,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
         parent = elementData(getParentIndex(removeIndex));
       }
       // bubble it up the opposite heap
-      if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle)
-          < removeIndex) {
+      if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle) < removeIndex) {
         return new MoveDesc<E>(toTrickle, parent);
       } else {
         return null;
@@ -621,8 +638,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
         // bubble up alternate levels, violating the invariant.
         int grandparentIndex = getParentIndex(parentIndex);
         int uncleIndex = getRightChildIndex(grandparentIndex);
-        if (uncleIndex != parentIndex
-            && getLeftChildIndex(uncleIndex) >= size) {
+        if (uncleIndex != parentIndex && getLeftChildIndex(uncleIndex) >= size) {
           E uncleElement = elementData(uncleIndex);
           if (ordering.compare(uncleElement, parentElement) < 0) {
             parentIndex = uncleIndex;
@@ -653,8 +669,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
       if (parentIndex != 0) {
         int grandparentIndex = getParentIndex(parentIndex);
         int uncleIndex = getRightChildIndex(grandparentIndex);
-        if (uncleIndex != parentIndex
-            && getLeftChildIndex(uncleIndex) >= size) {
+        if (uncleIndex != parentIndex && getLeftChildIndex(uncleIndex) >= size) {
           E uncleElement = elementData(uncleIndex);
           if (ordering.compare(uncleElement, actualLastElement) < 0) {
             queue[uncleIndex] = actualLastElement;
@@ -676,8 +691,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
       int minChildIndex = findMinChild(index);
       // TODO(kevinb): split the && into two if's and move crossOverUp so it's
       // only called when there's no child.
-      if ((minChildIndex > 0)
-          && (ordering.compare(elementData(minChildIndex), x) < 0)) {
+      if ((minChildIndex > 0) && (ordering.compare(elementData(minChildIndex), x) < 0)) {
         queue[index] = elementData(minChildIndex);
         queue[minChildIndex] = x;
         return minChildIndex;
@@ -703,12 +717,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     }
 
     private boolean verifyIndex(int i) {
-      if ((getLeftChildIndex(i) < size)
-          && (compareElements(i, getLeftChildIndex(i)) > 0)) {
+      if ((getLeftChildIndex(i) < size) && (compareElements(i, getLeftChildIndex(i)) > 0)) {
         return false;
       }
-      if ((getRightChildIndex(i) < size)
-          && (compareElements(i, getRightChildIndex(i)) > 0)) {
+      if ((getRightChildIndex(i) < size) && (compareElements(i, getRightChildIndex(i)) > 0)) {
         return false;
       }
       if ((i > 0) && (compareElements(i, getParentIndex(i)) > 0)) {
@@ -753,13 +765,15 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     private E lastFromForgetMeNot;
     private boolean canRemove;
 
-    @Override public boolean hasNext() {
+    @Override
+    public boolean hasNext() {
       checkModCount();
       return (nextNotInSkipMe(cursor + 1) < size())
           || ((forgetMeNot != null) && !forgetMeNot.isEmpty());
     }
 
-    @Override public E next() {
+    @Override
+    public E next() {
       checkModCount();
       int tempCursor = nextNotInSkipMe(cursor + 1);
       if (tempCursor < size()) {
@@ -774,11 +788,11 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
           return lastFromForgetMeNot;
         }
       }
-      throw new NoSuchElementException(
-          "iterator moved past last element in queue.");
+      throw new NoSuchElementException("iterator moved past last element in queue.");
     }
 
-    @Override public void remove() {
+    @Override
+    public void remove() {
       checkRemove(canRemove);
       checkModCount();
       canRemove = false;
@@ -863,18 +877,21 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
    *
    * @return an iterator over the elements contained in this collection
    */
-  @Override public Iterator<E> iterator() {
+  @Override
+  public Iterator<E> iterator() {
     return new QueueIterator();
   }
 
-  @Override public void clear() {
+  @Override
+  public void clear() {
     for (int i = 0; i < size; i++) {
       queue[i] = null;
     }
     size = 0;
   }
 
-  @Override public Object[] toArray() {
+  @Override
+  public Object[] toArray() {
     Object[] copyTo = new Object[size];
     System.arraycopy(queue, 0, copyTo, 0, size);
     return copyTo;
@@ -889,7 +906,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
     return minHeap.ordering;
   }
 
-  @VisibleForTesting int capacity() {
+  @VisibleForTesting
+  int capacity() {
     return queue.length;
   }
 
@@ -897,12 +915,14 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
 
   private static final int DEFAULT_CAPACITY = 11;
 
-  @VisibleForTesting static int initialQueueSize(int configuredExpectedSize,
-      int maximumSize, Iterable<?> initialContents) {
+  @VisibleForTesting
+  static int initialQueueSize(
+      int configuredExpectedSize, int maximumSize, Iterable<?> initialContents) {
     // Start with what they said, if they said it, otherwise DEFAULT_CAPACITY
-    int result = (configuredExpectedSize == Builder.UNSET_EXPECTED_SIZE)
-        ? DEFAULT_CAPACITY
-        : configuredExpectedSize;
+    int result =
+        (configuredExpectedSize == Builder.UNSET_EXPECTED_SIZE)
+            ? DEFAULT_CAPACITY
+            : configuredExpectedSize;
 
     // Enlarge to contain initial contents
     if (initialContents instanceof Collection) {
@@ -926,9 +946,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
   /** Returns ~2x the old capacity if small; ~1.5x otherwise. */
   private int calculateNewCapacity() {
     int oldCapacity = queue.length;
-    int newCapacity = (oldCapacity < 64)
-        ? (oldCapacity + 1) * 2
-        : IntMath.checkedMultiply(oldCapacity / 2, 3);
+    int newCapacity =
+        (oldCapacity < 64)
+            ? (oldCapacity + 1) * 2
+            : IntMath.checkedMultiply(oldCapacity / 2, 3);
     return capAtMaximumSize(newCapacity, maximumSize);
   }
 
diff --git a/guava/src/com/google/common/collect/Multimap.java b/guava/src/com/google/common/collect/Multimap.java
index 074dc0d..9924dd1 100644
--- a/guava/src/com/google/common/collect/Multimap.java
+++ b/guava/src/com/google/common/collect/Multimap.java
@@ -120,8 +120,8 @@ import javax.annotation.Nullable;
  * <li>There is no need to populate an empty collection before adding an entry
  *     with {@link #put put}.
  * <li>{@code get} never returns {@code null}, only an empty collection.
- * <li>A key is contained in the multimap if and only if it maps to at least 
- *     one value. Any operation that causes a key to have zero associated 
+ * <li>A key is contained in the multimap if and only if it maps to at least
+ *     one value. Any operation that causes a key to have zero associated
  *     values has the effect of <i>removing</i> that key from the multimap.
  * <li>The total entry count is available as {@link #size}.
  * <li>Many complex operations become easier; for example, {@code
@@ -142,10 +142,10 @@ import javax.annotation.Nullable;
  * to multimaps.
  *
  * <h3>Other Notes</h3>
- * 
- * <p>As with {@code Map}, the behavior of a {@code Multimap} is not specified 
- * if key objects already present in the multimap change in a manner that 
- * affects {@code equals} comparisons.  Use caution if mutable objects are used 
+ *
+ * <p>As with {@code Map}, the behavior of a {@code Multimap} is not specified
+ * if key objects already present in the multimap change in a manner that
+ * affects {@code equals} comparisons.  Use caution if mutable objects are used
  * as keys in a {@code Multimap}.
  *
  * <p>All methods that modify the multimap are optional. The view collections
@@ -154,11 +154,11 @@ import javax.annotation.Nullable;
  * UnsupportedOperationException}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface Multimap<K, V> {
@@ -230,11 +230,11 @@ public interface Multimap<K, V> {
    * Stores a key-value pair in this multimap for each of {@code values}, all
    * using the same key, {@code key}. Equivalent to (but expected to be more
    * efficient than): <pre>   {@code
-   * 
+   *
    *   for (V value : values) {
    *     put(key, value);
    *   }}</pre>
-   * 
+   *
    * <p>In particular, this is a no-op if {@code values} is empty.
    *
    * @return {@code true} if the multimap changed
@@ -252,8 +252,8 @@ public interface Multimap<K, V> {
   /**
    * Stores a collection of values with the same key, replacing any existing
    * values for that key.
-   * 
-   * <p>If {@code values} is empty, this is equivalent to 
+   *
+   * <p>If {@code values} is empty, this is equivalent to
    * {@link #removeAll(Object) removeAll(key)}.
    *
    * @return the collection of replaced values, or an empty collection if no
@@ -265,10 +265,10 @@ public interface Multimap<K, V> {
 
   /**
    * Removes all values associated with the key {@code key}.
-   * 
+   *
    * <p>Once this method returns, {@code key} will not be mapped to any values,
    * so it will not appear in {@link #keySet()}, {@link #asMap()}, or any other
-   * views. 
+   * views.
    *
    * @return the values that were removed (possibly empty). The returned
    *     collection <i>may</i> be modifiable, but updating it will have no
@@ -286,7 +286,7 @@ public interface Multimap<K, V> {
 
   /**
    * Returns a view collection of the values associated with {@code key} in this
-   * multimap, if any. Note that when {@code containsKey(key)} is false, this 
+   * multimap, if any. Note that when {@code containsKey(key)} is false, this
    * returns an empty collection, not {@code null}.
    *
    * <p>Changes to the returned collection will update the underlying multimap,
@@ -382,7 +382,7 @@ public interface Multimap<K, V> {
    * not have the same hash codes, depending on the implementation. For
    * example, two {@link SetMultimap} instances with the same key-value
    * mappings will have the same {@code hashCode}, but the {@code hashCode}
-   * of {@link ListMultimap} instances depends on the ordering of the values 
+   * of {@link ListMultimap} instances depends on the ordering of the values
    * for each key.
    */
   @Override
diff --git a/guava/src/com/google/common/collect/MultimapBuilder.java b/guava/src/com/google/common/collect/MultimapBuilder.java
index 89c796c..97738ef 100644
--- a/guava/src/com/google/common/collect/MultimapBuilder.java
+++ b/guava/src/com/google/common/collect/MultimapBuilder.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
+import static com.google.common.collect.Maps.newLinkedHashMapWithExpectedSize;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
@@ -41,6 +42,8 @@ import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * A builder for a multimap implementation that allows customization of the backing map and value
  * collection implementations used in a particular multimap.
@@ -68,6 +71,7 @@ import java.util.TreeSet;
  */
 @Beta
 @GwtCompatible
+ at CheckReturnValue
 public abstract class MultimapBuilder<K0, V0> {
   /*
    * Leaving K and V as upper bounds rather than the actual key and value types allows type
@@ -96,7 +100,7 @@ public abstract class MultimapBuilder<K0, V0> {
     return new MultimapBuilderWithKeys<Object>() {
       @Override
       <K, V> Map<K, Collection<V>> createMap() {
-        return new HashMap<K, Collection<V>>(expectedKeys);
+        return Maps.newHashMapWithExpectedSize(expectedKeys);
       }
     };
   }
@@ -127,7 +131,7 @@ public abstract class MultimapBuilder<K0, V0> {
     return new MultimapBuilderWithKeys<Object>() {
       @Override
       <K, V> Map<K, Collection<V>> createMap() {
-        return new LinkedHashMap<K, Collection<V>>(expectedKeys);
+        return newLinkedHashMapWithExpectedSize(expectedKeys);
       }
     };
   }
@@ -225,7 +229,7 @@ public abstract class MultimapBuilder<K0, V0> {
 
     @Override
     public Set<V> get() {
-      return new HashSet<V>(expectedValuesPerKey);
+      return Sets.newHashSetWithExpectedSize(expectedValuesPerKey);
     }
   }
 
@@ -238,7 +242,7 @@ public abstract class MultimapBuilder<K0, V0> {
 
     @Override
     public Set<V> get() {
-      return new LinkedHashSet<V>(expectedValuesPerKey);
+      return Sets.newLinkedHashSetWithExpectedSize(expectedValuesPerKey);
     }
   }
 
@@ -316,8 +320,7 @@ public abstract class MultimapBuilder<K0, V0> {
         @Override
         public <K extends K0, V> ListMultimap<K, V> build() {
           return Multimaps.newListMultimap(
-              MultimapBuilderWithKeys.this.<K, V>createMap(),
-              LinkedListSupplier.<V>instance());
+              MultimapBuilderWithKeys.this.<K, V>createMap(), LinkedListSupplier.<V>instance());
         }
       };
     }
@@ -392,8 +395,7 @@ public abstract class MultimapBuilder<K0, V0> {
         @Override
         public <K extends K0, V extends V0> SortedSetMultimap<K, V> build() {
           return Multimaps.newSortedSetMultimap(
-              MultimapBuilderWithKeys.this.<K, V>createMap(),
-              new TreeSetSupplier<V>(comparator));
+              MultimapBuilderWithKeys.this.<K, V>createMap(), new TreeSetSupplier<V>(comparator));
         }
       };
     }
@@ -411,9 +413,7 @@ public abstract class MultimapBuilder<K0, V0> {
           // (their subclasses are inaccessible)
           @SuppressWarnings({"unchecked", "rawtypes"})
           Supplier<Set<V>> factory = (Supplier) new EnumSetSupplier<V0>(valueClass);
-          return Multimaps.newSetMultimap(
-              MultimapBuilderWithKeys.this.<K, V>createMap(),
-              factory);
+          return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.<K, V>createMap(), factory);
         }
       };
     }
diff --git a/guava/src/com/google/common/collect/Multimaps.java b/guava/src/com/google/common/collect/Multimaps.java
index 14c8564..62cd1f3 100644
--- a/guava/src/com/google/common/collect/Multimaps.java
+++ b/guava/src/com/google/common/collect/Multimaps.java
@@ -28,6 +28,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.base.Supplier;
 import com.google.common.collect.Maps.EntryTransformer;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -46,20 +48,21 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.SortedSet;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
  * Provides static methods acting on or generating a {@code Multimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multimaps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multimaps">
  * {@code Multimaps}</a>.
  *
  * @author Jared Levy
  * @author Robert Konigsberg
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Multimaps {
@@ -108,21 +111,21 @@ public final class Multimaps {
    *     values for a given key
    * @throws IllegalArgumentException if {@code map} is not empty
    */
-  public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
-      final Supplier<? extends Collection<V>> factory) {
+  public static <K, V> Multimap<K, V> newMultimap(
+      Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory) {
     return new CustomMultimap<K, V>(map, factory);
   }
 
   private static class CustomMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
     transient Supplier<? extends Collection<V>> factory;
 
-    CustomMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends Collection<V>> factory) {
+    CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected Collection<V> createCollection() {
+    @Override
+    protected Collection<V> createCollection() {
       return factory.get();
     }
 
@@ -139,8 +142,7 @@ public final class Multimaps {
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked") // reading data stored by writeObject
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
       stream.defaultReadObject();
       factory = (Supplier<? extends Collection<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -194,17 +196,16 @@ public final class Multimaps {
     return new CustomListMultimap<K, V>(map, factory);
   }
 
-  private static class CustomListMultimap<K, V>
-      extends AbstractListMultimap<K, V> {
+  private static class CustomListMultimap<K, V> extends AbstractListMultimap<K, V> {
     transient Supplier<? extends List<V>> factory;
 
-    CustomListMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends List<V>> factory) {
+    CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected List<V> createCollection() {
+    @Override
+    protected List<V> createCollection() {
       return factory.get();
     }
 
@@ -218,8 +219,7 @@ public final class Multimaps {
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked") // reading data stored by writeObject
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
       stream.defaultReadObject();
       factory = (Supplier<? extends List<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -272,17 +272,16 @@ public final class Multimaps {
     return new CustomSetMultimap<K, V>(map, factory);
   }
 
-  private static class CustomSetMultimap<K, V>
-      extends AbstractSetMultimap<K, V> {
+  private static class CustomSetMultimap<K, V> extends AbstractSetMultimap<K, V> {
     transient Supplier<? extends Set<V>> factory;
 
-    CustomSetMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends Set<V>> factory) {
+    CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
     }
 
-    @Override protected Set<V> createCollection() {
+    @Override
+    protected Set<V> createCollection() {
       return factory.get();
     }
 
@@ -296,8 +295,7 @@ public final class Multimaps {
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked") // reading data stored by writeObject
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
       stream.defaultReadObject();
       factory = (Supplier<? extends Set<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -345,28 +343,27 @@ public final class Multimaps {
    * @throws IllegalArgumentException if {@code map} is not empty
    */
   public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
-      Map<K, Collection<V>> map,
-      final Supplier<? extends SortedSet<V>> factory) {
+      Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory) {
     return new CustomSortedSetMultimap<K, V>(map, factory);
   }
 
-  private static class CustomSortedSetMultimap<K, V>
-      extends AbstractSortedSetMultimap<K, V> {
+  private static class CustomSortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
     transient Supplier<? extends SortedSet<V>> factory;
     transient Comparator<? super V> valueComparator;
 
-    CustomSortedSetMultimap(Map<K, Collection<V>> map,
-        Supplier<? extends SortedSet<V>> factory) {
+    CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory) {
       super(map);
       this.factory = checkNotNull(factory);
       valueComparator = factory.get().comparator();
     }
 
-    @Override protected SortedSet<V> createCollection() {
+    @Override
+    protected SortedSet<V> createCollection() {
       return factory.get();
     }
 
-    @Override public Comparator<? super V> valueComparator() {
+    @Override
+    public Comparator<? super V> valueComparator() {
       return valueComparator;
     }
 
@@ -380,8 +377,7 @@ public final class Multimaps {
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked") // reading data stored by writeObject
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
       stream.defaultReadObject();
       factory = (Supplier<? extends SortedSet<V>>) stream.readObject();
       valueComparator = factory.get().comparator();
@@ -446,8 +442,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped in a synchronized view
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> Multimap<K, V> synchronizedMultimap(
-      Multimap<K, V> multimap) {
+  public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
     return Synchronized.multimap(multimap, null);
   }
 
@@ -468,10 +463,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> Multimap<K, V> unmodifiableMultimap(
-      Multimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableMultimap ||
-        delegate instanceof ImmutableMultimap) {
+  public static <K, V> Multimap<K, V> unmodifiableMultimap(Multimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) {
       return delegate;
     }
     return new UnmodifiableMultimap<K, V>(delegate);
@@ -483,13 +476,13 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
-      ImmutableMultimap<K, V> delegate) {
+  @Deprecated
+  public static <K, V> Multimap<K, V> unmodifiableMultimap(ImmutableMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
 
-  private static class UnmodifiableMultimap<K, V>
-      extends ForwardingMultimap<K, V> implements Serializable {
+  private static class UnmodifiableMultimap<K, V> extends ForwardingMultimap<K, V>
+      implements Serializable {
     final Multimap<K, V> delegate;
     transient Collection<Entry<K, V>> entries;
     transient Multiset<K> keys;
@@ -501,29 +494,36 @@ public final class Multimaps {
       this.delegate = checkNotNull(delegate);
     }
 
-    @Override protected Multimap<K, V> delegate() {
+    @Override
+    protected Multimap<K, V> delegate() {
       return delegate;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Map<K, Collection<V>> asMap() {
+    @Override
+    public Map<K, Collection<V>> asMap() {
       Map<K, Collection<V>> result = map;
       if (result == null) {
-        result = map = Collections.unmodifiableMap(
-            Maps.transformValues(delegate.asMap(), new Function<Collection<V>, Collection<V>>() {
-              @Override
-              public Collection<V> apply(Collection<V> collection) {
-                return unmodifiableValueCollection(collection);
-              }
-            }));
+        result = map =
+            Collections.unmodifiableMap(
+                Maps.transformValues(
+                    delegate.asMap(),
+                    new Function<Collection<V>, Collection<V>>() {
+                      @Override
+                      public Collection<V> apply(Collection<V> collection) {
+                        return unmodifiableValueCollection(collection);
+                      }
+                    }));
       }
       return result;
     }
 
-    @Override public Collection<Entry<K, V>> entries() {
+    @Override
+    public Collection<Entry<K, V>> entries() {
       Collection<Entry<K, V>> result = entries;
       if (result == null) {
         entries = result = unmodifiableEntries(delegate.entries());
@@ -531,11 +531,13 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public Collection<V> get(K key) {
+    @Override
+    public Collection<V> get(K key) {
       return unmodifiableValueCollection(delegate.get(key));
     }
 
-    @Override public Multiset<K> keys() {
+    @Override
+    public Multiset<K> keys() {
       Multiset<K> result = keys;
       if (result == null) {
         keys = result = Multisets.unmodifiableMultiset(delegate.keys());
@@ -543,7 +545,8 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       Set<K> result = keySet;
       if (result == null) {
         keySet = result = Collections.unmodifiableSet(delegate.keySet());
@@ -551,11 +554,13 @@ public final class Multimaps {
       return result;
     }
 
-    @Override public boolean put(K key, V value) {
+    @Override
+    public boolean put(K key, V value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(K key, Iterable<? extends V> values) {
+    @Override
+    public boolean putAll(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
@@ -564,20 +569,23 @@ public final class Multimaps {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean remove(Object key, Object value) {
+    @Override
+    public boolean remove(Object key, Object value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> removeAll(Object key) {
+    @Override
+    public Collection<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+    @Override
+    public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public Collection<V> values() {
+    @Override
+    public Collection<V> values() {
       Collection<V> result = values;
       if (result == null) {
         values = result = Collections.unmodifiableCollection(delegate.values());
@@ -588,77 +596,104 @@ public final class Multimaps {
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableListMultimap<K, V>
-      extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
+  private static class UnmodifiableListMultimap<K, V> extends UnmodifiableMultimap<K, V>
+      implements ListMultimap<K, V> {
     UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public ListMultimap<K, V> delegate() {
+
+    @Override
+    public ListMultimap<K, V> delegate() {
       return (ListMultimap<K, V>) super.delegate();
     }
-    @Override public List<V> get(K key) {
+
+    @Override
+    public List<V> get(K key) {
       return Collections.unmodifiableList(delegate().get(key));
     }
-    @Override public List<V> removeAll(Object key) {
+
+    @Override
+    public List<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public List<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public List<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableSetMultimap<K, V>
-      extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
+  private static class UnmodifiableSetMultimap<K, V> extends UnmodifiableMultimap<K, V>
+      implements SetMultimap<K, V> {
     UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public SetMultimap<K, V> delegate() {
+
+    @Override
+    public SetMultimap<K, V> delegate() {
       return (SetMultimap<K, V>) super.delegate();
     }
-    @Override public Set<V> get(K key) {
+
+    @Override
+    public Set<V> get(K key) {
       /*
        * Note that this doesn't return a SortedSet when delegate is a
        * SortedSetMultiset, unlike (SortedSet<V>) super.get().
        */
       return Collections.unmodifiableSet(delegate().get(key));
     }
-    @Override public Set<Map.Entry<K, V>> entries() {
+
+    @Override
+    public Set<Map.Entry<K, V>> entries() {
       return Maps.unmodifiableEntrySet(delegate().entries());
     }
-    @Override public Set<V> removeAll(Object key) {
+
+    @Override
+    public Set<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public Set<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  private static class UnmodifiableSortedSetMultimap<K, V>
-      extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+  private static class UnmodifiableSortedSetMultimap<K, V> extends UnmodifiableSetMultimap<K, V>
+      implements SortedSetMultimap<K, V> {
     UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
       super(delegate);
     }
-    @Override public SortedSetMultimap<K, V> delegate() {
+
+    @Override
+    public SortedSetMultimap<K, V> delegate() {
       return (SortedSetMultimap<K, V>) super.delegate();
     }
-    @Override public SortedSet<V> get(K key) {
+
+    @Override
+    public SortedSet<V> get(K key) {
       return Collections.unmodifiableSortedSet(delegate().get(key));
     }
-    @Override public SortedSet<V> removeAll(Object key) {
+
+    @Override
+    public SortedSet<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
-    @Override public SortedSet<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
+
     @Override
     public Comparator<? super V> valueComparator() {
       return delegate().valueComparator();
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -674,8 +709,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
-      SetMultimap<K, V> multimap) {
+  public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(SetMultimap<K, V> multimap) {
     return Synchronized.setMultimap(multimap, null);
   }
 
@@ -697,10 +731,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
-      SetMultimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableSetMultimap ||
-        delegate instanceof ImmutableSetMultimap) {
+  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(SetMultimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) {
       return delegate;
     }
     return new UnmodifiableSetMultimap<K, V>(delegate);
@@ -712,7 +744,8 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
+  @Deprecated
+  public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
       ImmutableSetMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
@@ -729,8 +762,8 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> SortedSetMultimap<K, V>
-      synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
+  public static <K, V> SortedSetMultimap<K, V> synchronizedSortedSetMultimap(
+      SortedSetMultimap<K, V> multimap) {
     return Synchronized.sortedSetMultimap(multimap, null);
   }
 
@@ -769,8 +802,7 @@ public final class Multimaps {
    * @param multimap the multimap to be wrapped
    * @return a synchronized view of the specified multimap
    */
-  public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
-      ListMultimap<K, V> multimap) {
+  public static <K, V> ListMultimap<K, V> synchronizedListMultimap(ListMultimap<K, V> multimap) {
     return Synchronized.listMultimap(multimap, null);
   }
 
@@ -792,10 +824,8 @@ public final class Multimaps {
    *     returned
    * @return an unmodifiable view of the specified multimap
    */
-  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
-      ListMultimap<K, V> delegate) {
-    if (delegate instanceof UnmodifiableListMultimap ||
-        delegate instanceof ImmutableListMultimap) {
+  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(ListMultimap<K, V> delegate) {
+    if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) {
       return delegate;
     }
     return new UnmodifiableListMultimap<K, V>(delegate);
@@ -807,7 +837,8 @@ public final class Multimaps {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
+  @Deprecated
+  public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
       ImmutableListMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
@@ -820,8 +851,7 @@ public final class Multimaps {
    * @param collection the collection for which to return an unmodifiable view
    * @return an unmodifiable view of the collection
    */
-  private static <V> Collection<V> unmodifiableValueCollection(
-      Collection<V> collection) {
+  private static <V> Collection<V> unmodifiableValueCollection(Collection<V> collection) {
     if (collection instanceof SortedSet) {
       return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
     } else if (collection instanceof Set) {
@@ -846,8 +876,7 @@ public final class Multimaps {
     if (entries instanceof Set) {
       return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
     }
-    return new Maps.UnmodifiableEntries<K, V>(
-        Collections.unmodifiableCollection(entries));
+    return new Maps.UnmodifiableEntries<K, V>(Collections.unmodifiableCollection(entries));
   }
 
   /**
@@ -886,8 +915,7 @@ public final class Multimaps {
   @Beta
   @SuppressWarnings("unchecked")
   // safe by specification of SortedSetMultimap.asMap()
-  public static <K, V> Map<K, SortedSet<V>> asMap(
-      SortedSetMultimap<K, V> multimap) {
+  public static <K, V> Map<K, SortedSet<V>> asMap(SortedSetMultimap<K, V> multimap) {
     return (Map<K, SortedSet<V>>) (Map<K, ?>) multimap.asMap();
   }
 
@@ -924,8 +952,8 @@ public final class Multimaps {
   }
 
   /** @see Multimaps#forMap */
-  private static class MapMultimap<K, V>
-      extends AbstractMultimap<K, V> implements SetMultimap<K, V>, Serializable {
+  private static class MapMultimap<K, V> extends AbstractMultimap<K, V>
+      implements SetMultimap<K, V>, Serializable {
     final Map<K, V> map;
 
     MapMultimap(Map<K, V> map) {
@@ -955,7 +983,8 @@ public final class Multimaps {
     @Override
     public Set<V> get(final K key) {
       return new Sets.ImprovedAbstractSet<V>() {
-        @Override public Iterator<V> iterator() {
+        @Override
+        public Iterator<V> iterator() {
           return new Iterator<V>() {
             int i;
 
@@ -982,7 +1011,8 @@ public final class Multimaps {
           };
         }
 
-        @Override public int size() {
+        @Override
+        public int size() {
           return map.containsKey(key) ? 1 : 0;
         }
       };
@@ -1042,7 +1072,7 @@ public final class Multimaps {
     public Set<Entry<K, V>> entries() {
       return map.entrySet();
     }
-    
+
     @Override
     Iterator<Entry<K, V>> entryIterator() {
       return map.entrySet().iterator();
@@ -1053,10 +1083,11 @@ public final class Multimaps {
       return new AsMap<K, V>(this);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return map.hashCode();
     }
-    
+
     private static final long serialVersionUID = 7845222491160860175L;
   }
 
@@ -1167,25 +1198,23 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> Multimap<K, V2> transformEntries(
-      Multimap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      Multimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
   }
 
-  private static class TransformedEntriesMultimap<K, V1, V2>
-      extends AbstractMultimap<K, V2> {
+  private static class TransformedEntriesMultimap<K, V1, V2> extends AbstractMultimap<K, V2> {
     final Multimap<K, V1> fromMultimap;
     final EntryTransformer<? super K, ? super V1, V2> transformer;
 
-    TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
+    TransformedEntriesMultimap(
+        Multimap<K, V1> fromMultimap,
         final EntryTransformer<? super K, ? super V1, V2> transformer) {
       this.fromMultimap = checkNotNull(fromMultimap);
       this.transformer = checkNotNull(transformer);
     }
 
     Collection<V2> transform(K key, Collection<V1> values) {
-      Function<? super V1, V2> function = 
-          Maps.asValueToValueFunction(transformer, key);
+      Function<? super V1, V2> function = Maps.asValueToValueFunction(transformer, key);
       if (values instanceof List) {
         return Lists.transform((List<V1>) values, function);
       } else {
@@ -1195,77 +1224,89 @@ public final class Multimaps {
 
     @Override
     Map<K, Collection<V2>> createAsMap() {
-      return Maps.transformEntries(fromMultimap.asMap(),
+      return Maps.transformEntries(
+          fromMultimap.asMap(),
           new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
-        @Override public Collection<V2> transformEntry(
-            K key, Collection<V1> value) {
-          return transform(key, value);
-        }
-      });
+            @Override
+            public Collection<V2> transformEntry(K key, Collection<V1> value) {
+              return transform(key, value);
+            }
+          });
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromMultimap.clear();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return fromMultimap.containsKey(key);
     }
 
     @Override
     Iterator<Entry<K, V2>> entryIterator() {
-      return Iterators.transform(fromMultimap.entries().iterator(), 
-          Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+      return Iterators.transform(
+          fromMultimap.entries().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
     }
 
-    @Override public Collection<V2> get(final K key) {
+    @Override
+    public Collection<V2> get(final K key) {
       return transform(key, fromMultimap.get(key));
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return fromMultimap.isEmpty();
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return fromMultimap.keySet();
     }
 
-    @Override public Multiset<K> keys() {
+    @Override
+    public Multiset<K> keys() {
       return fromMultimap.keys();
     }
 
-    @Override public boolean put(K key, V2 value) {
+    @Override
+    public boolean put(K key, V2 value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(K key, Iterable<? extends V2> values) {
+    @Override
+    public boolean putAll(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean putAll(
-        Multimap<? extends K, ? extends V2> multimap) {
+    @Override
+    public boolean putAll(Multimap<? extends K, ? extends V2> multimap) {
       throw new UnsupportedOperationException();
     }
 
     @SuppressWarnings("unchecked")
-    @Override public boolean remove(Object key, Object value) {
+    @Override
+    public boolean remove(Object key, Object value) {
       return get((K) key).remove(value);
     }
 
     @SuppressWarnings("unchecked")
-    @Override public Collection<V2> removeAll(Object key) {
+    @Override
+    public Collection<V2> removeAll(Object key) {
       return transform((K) key, fromMultimap.removeAll(key));
     }
 
-    @Override public Collection<V2> replaceValues(
-        K key, Iterable<? extends V2> values) {
+    @Override
+    public Collection<V2> replaceValues(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromMultimap.size();
     }
-    
+
     @Override
     Collection<V2> createValues() {
       return Collections2.transform(
@@ -1315,8 +1356,7 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> ListMultimap<K, V2> transformValues(
-      ListMultimap<K, V1> fromMultimap,
-      final Function<? super V1, V2> function) {
+      ListMultimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
     checkNotNull(function);
     EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function);
     return transformEntries(fromMultimap, transformer);
@@ -1375,35 +1415,36 @@ public final class Multimaps {
    * @since 7.0
    */
   public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
-      ListMultimap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      ListMultimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
   }
 
   private static final class TransformedEntriesListMultimap<K, V1, V2>
-      extends TransformedEntriesMultimap<K, V1, V2>
-      implements ListMultimap<K, V2> {
+      extends TransformedEntriesMultimap<K, V1, V2> implements ListMultimap<K, V2> {
 
-    TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
-        EntryTransformer<? super K, ? super V1, V2> transformer) {
+    TransformedEntriesListMultimap(
+        ListMultimap<K, V1> fromMultimap, EntryTransformer<? super K, ? super V1, V2> transformer) {
       super(fromMultimap, transformer);
     }
 
-    @Override List<V2> transform(K key, Collection<V1> values) {
+    @Override
+    List<V2> transform(K key, Collection<V1> values) {
       return Lists.transform((List<V1>) values, Maps.asValueToValueFunction(transformer, key));
     }
 
-    @Override public List<V2> get(K key) {
+    @Override
+    public List<V2> get(K key) {
       return transform(key, fromMultimap.get(key));
     }
 
     @SuppressWarnings("unchecked")
-    @Override public List<V2> removeAll(Object key) {
+    @Override
+    public List<V2> removeAll(Object key) {
       return transform((K) key, fromMultimap.removeAll(key));
     }
 
-    @Override public List<V2> replaceValues(
-        K key, Iterable<? extends V2> values) {
+    @Override
+    public List<V2> replaceValues(K key, Iterable<? extends V2> values) {
       throw new UnsupportedOperationException();
     }
   }
@@ -1501,8 +1542,7 @@ public final class Multimaps {
   public static <K, V> ImmutableListMultimap<K, V> index(
       Iterator<V> values, Function<? super V, K> keyFunction) {
     checkNotNull(keyFunction);
-    ImmutableListMultimap.Builder<K, V> builder
-        = ImmutableListMultimap.builder();
+    ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
     while (values.hasNext()) {
       V value = values.next();
       checkNotNull(value, values);
@@ -1512,18 +1552,18 @@ public final class Multimaps {
   }
 
   static class Keys<K, V> extends AbstractMultiset<K> {
-    final Multimap<K, V> multimap;
-    
+    @Weak final Multimap<K, V> multimap;
+
     Keys(Multimap<K, V> multimap) {
       this.multimap = multimap;
     }
 
-    @Override Iterator<Multiset.Entry<K>> entryIterator() {
+    @Override
+    Iterator<Multiset.Entry<K>> entryIterator() {
       return new TransformedIterator<Map.Entry<K, Collection<V>>, Multiset.Entry<K>>(
           multimap.asMap().entrySet().iterator()) {
         @Override
-        Multiset.Entry<K> transform(
-            final Map.Entry<K, Collection<V>> backingEntry) {
+        Multiset.Entry<K> transform(final Map.Entry<K, Collection<V>> backingEntry) {
           return new Multisets.AbstractEntry<K>() {
             @Override
             public K getElement() {
@@ -1539,32 +1579,40 @@ public final class Multimaps {
       };
     }
 
-    @Override int distinctElements() {
+    @Override
+    int distinctElements() {
       return multimap.asMap().size();
     }
 
-    @Override Set<Multiset.Entry<K>> createEntrySet() {
+    @Override
+    Set<Multiset.Entry<K>> createEntrySet() {
       return new KeysEntrySet();
     }
 
+    @WeakOuter
     class KeysEntrySet extends Multisets.EntrySet<K> {
-      @Override Multiset<K> multiset() {
+      @Override
+      Multiset<K> multiset() {
         return Keys.this;
       }
 
-      @Override public Iterator<Multiset.Entry<K>> iterator() {
+      @Override
+      public Iterator<Multiset.Entry<K>> iterator() {
         return entryIterator();
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         return distinctElements();
       }
 
-      @Override public boolean isEmpty() {
+      @Override
+      public boolean isEmpty() {
         return multimap.isEmpty();
       }
 
-      @Override public boolean contains(@Nullable Object o) {
+      @Override
+      public boolean contains(@Nullable Object o) {
         if (o instanceof Multiset.Entry) {
           Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
           Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1573,7 +1621,8 @@ public final class Multimaps {
         return false;
       }
 
-      @Override public boolean remove(@Nullable Object o) {
+      @Override
+      public boolean remove(@Nullable Object o) {
         if (o instanceof Multiset.Entry) {
           Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
           Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1586,20 +1635,24 @@ public final class Multimaps {
       }
     }
 
-    @Override public boolean contains(@Nullable Object element) {
+    @Override
+    public boolean contains(@Nullable Object element) {
       return multimap.containsKey(element);
     }
 
-    @Override public Iterator<K> iterator() {
+    @Override
+    public Iterator<K> iterator() {
       return Maps.keyIterator(multimap.entries().iterator());
     }
 
-    @Override public int count(@Nullable Object element) {
+    @Override
+    public int count(@Nullable Object element) {
       Collection<V> values = Maps.safeGet(multimap.asMap(), element);
       return (values == null) ? 0 : values.size();
     }
 
-    @Override public int remove(@Nullable Object element, int occurrences) {
+    @Override
+    public int remove(@Nullable Object element, int occurrences) {
       checkNonnegative(occurrences, "occurrences");
       if (occurrences == 0) {
         return count(element);
@@ -1624,11 +1677,13 @@ public final class Multimaps {
       return oldCount;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap.clear();
     }
 
-    @Override public Set<K> elementSet() {
+    @Override
+    public Set<K> elementSet() {
       return multimap.keySet();
     }
   }
@@ -1636,15 +1691,16 @@ public final class Multimaps {
   /**
    * A skeleton implementation of {@link Multimap#entries()}.
    */
-  abstract static class Entries<K, V> extends
-      AbstractCollection<Map.Entry<K, V>> {
+  abstract static class Entries<K, V> extends AbstractCollection<Map.Entry<K, V>> {
     abstract Multimap<K, V> multimap();
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return multimap().size();
     }
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       if (o instanceof Map.Entry) {
         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
         return multimap().containsEntry(entry.getKey(), entry.getValue());
@@ -1652,7 +1708,8 @@ public final class Multimaps {
       return false;
     }
 
-    @Override public boolean remove(@Nullable Object o) {
+    @Override
+    public boolean remove(@Nullable Object o) {
       if (o instanceof Map.Entry) {
         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
         return multimap().remove(entry.getKey(), entry.getValue());
@@ -1660,7 +1717,8 @@ public final class Multimaps {
       return false;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap().clear();
     }
   }
@@ -1668,19 +1726,20 @@ public final class Multimaps {
   /**
    * A skeleton implementation of {@link Multimap#asMap()}.
    */
-  static final class AsMap<K, V> extends
-      Maps.ImprovedAbstractMap<K, Collection<V>> {
-    private final Multimap<K, V> multimap;
-    
+  static final class AsMap<K, V> extends Maps.ViewCachingAbstractMap<K, Collection<V>> {
+    @Weak private final Multimap<K, V> multimap;
+
     AsMap(Multimap<K, V> multimap) {
       this.multimap = checkNotNull(multimap);
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return multimap.keySet().size();
     }
 
-    @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
+    @Override
+    protected Set<Entry<K, Collection<V>>> createEntrySet() {
       return new EntrySet();
     }
 
@@ -1688,21 +1747,27 @@ public final class Multimaps {
       multimap.keySet().remove(key);
     }
 
+    @WeakOuter
     class EntrySet extends Maps.EntrySet<K, Collection<V>> {
-      @Override Map<K, Collection<V>> map() {
+      @Override
+      Map<K, Collection<V>> map() {
         return AsMap.this;
       }
 
-      @Override public Iterator<Entry<K, Collection<V>>> iterator() {
-        return Maps.asMapEntryIterator(multimap.keySet(), new Function<K, Collection<V>>() {
-          @Override
-          public Collection<V> apply(K key) {
-            return multimap.get(key);
-          }
-        });
+      @Override
+      public Iterator<Entry<K, Collection<V>>> iterator() {
+        return Maps.asMapEntryIterator(
+            multimap.keySet(),
+            new Function<K, Collection<V>>() {
+              @Override
+              public Collection<V> apply(K key) {
+                return multimap.get(key);
+              }
+            });
       }
 
-      @Override public boolean remove(Object o) {
+      @Override
+      public boolean remove(Object o) {
         if (!contains(o)) {
           return false;
         }
@@ -1713,27 +1778,33 @@ public final class Multimaps {
     }
 
     @SuppressWarnings("unchecked")
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       return containsKey(key) ? multimap.get((K) key) : null;
     }
 
-    @Override public Collection<V> remove(Object key) {
+    @Override
+    public Collection<V> remove(Object key) {
       return containsKey(key) ? multimap.removeAll(key) : null;
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return multimap.keySet();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return multimap.isEmpty();
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return multimap.containsKey(key);
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multimap.clear();
     }
   }
@@ -1768,6 +1839,7 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterKeys(
       Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof SetMultimap) {
@@ -1776,8 +1848,8 @@ public final class Multimaps {
       return filterKeys((ListMultimap<K, V>) unfiltered, keyPredicate);
     } else if (unfiltered instanceof FilteredKeyMultimap) {
       FilteredKeyMultimap<K, V> prev = (FilteredKeyMultimap<K, V>) unfiltered;
-      return new FilteredKeyMultimap<K, V>(prev.unfiltered,
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeyMultimap<K, V>(
+          prev.unfiltered, Predicates.and(prev.keyPredicate, keyPredicate));
     } else if (unfiltered instanceof FilteredMultimap) {
       FilteredMultimap<K, V> prev = (FilteredMultimap<K, V>) unfiltered;
       return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1785,7 +1857,7 @@ public final class Multimaps {
       return new FilteredKeyMultimap<K, V>(unfiltered, keyPredicate);
     }
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose keys
    * satisfy a predicate. The returned multimap is a live view of
@@ -1816,12 +1888,13 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterKeys(
       SetMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof FilteredKeySetMultimap) {
       FilteredKeySetMultimap<K, V> prev = (FilteredKeySetMultimap<K, V>) unfiltered;
-      return new FilteredKeySetMultimap<K, V>(prev.unfiltered(),
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeySetMultimap<K, V>(
+          prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
     } else if (unfiltered instanceof FilteredSetMultimap) {
       FilteredSetMultimap<K, V> prev = (FilteredSetMultimap<K, V>) unfiltered;
       return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1829,7 +1902,7 @@ public final class Multimaps {
       return new FilteredKeySetMultimap<K, V>(unfiltered, keyPredicate);
     }
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose keys
    * satisfy a predicate. The returned multimap is a live view of
@@ -1860,12 +1933,13 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> ListMultimap<K, V> filterKeys(
       ListMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
     if (unfiltered instanceof FilteredKeyListMultimap) {
       FilteredKeyListMultimap<K, V> prev = (FilteredKeyListMultimap<K, V>) unfiltered;
-      return new FilteredKeyListMultimap<K, V>(prev.unfiltered(),
-          Predicates.and(prev.keyPredicate, keyPredicate));
+      return new FilteredKeyListMultimap<K, V>(
+          prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
     } else {
       return new FilteredKeyListMultimap<K, V>(unfiltered, keyPredicate);
     }
@@ -1901,11 +1975,12 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterValues(
       Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} whose values
    * satisfy a predicate. The returned multimap is a live view of
@@ -1936,6 +2011,7 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterValues(
       SetMultimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
     return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1969,6 +2045,7 @@ public final class Multimaps {
    *
    * @since 11.0
    */
+  @CheckReturnValue
   public static <K, V> Multimap<K, V> filterEntries(
       Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
@@ -1979,7 +2056,7 @@ public final class Multimaps {
         ? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate)
         : new FilteredEntryMultimap<K, V>(checkNotNull(unfiltered), entryPredicate);
   }
-  
+
   /**
    * Returns a multimap containing the mappings in {@code unfiltered} that
    * satisfy a predicate. The returned multimap is a live view of
@@ -2008,6 +2085,7 @@ public final class Multimaps {
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public static <K, V> SetMultimap<K, V> filterEntries(
       SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
     checkNotNull(entryPredicate);
@@ -2023,10 +2101,9 @@ public final class Multimaps {
    * operations would fail. This method combines the predicates to avoid that
    * problem.
    */
-  private static <K, V> Multimap<K, V> filterFiltered(FilteredMultimap<K, V> multimap,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(multimap.entryPredicate(), entryPredicate);
+  private static <K, V> Multimap<K, V> filterFiltered(
+      FilteredMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
     return new FilteredEntryMultimap<K, V>(multimap.unfiltered(), predicate);
   }
 
@@ -2037,13 +2114,11 @@ public final class Multimaps {
    * avoid that problem.
    */
   private static <K, V> SetMultimap<K, V> filterFiltered(
-      FilteredSetMultimap<K, V> multimap,
-      Predicate<? super Entry<K, V>> entryPredicate) {
-    Predicate<Entry<K, V>> predicate
-        = Predicates.and(multimap.entryPredicate(), entryPredicate);
+      FilteredSetMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+    Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
     return new FilteredEntrySetMultimap<K, V>(multimap.unfiltered(), predicate);
   }
-  
+
   static boolean equalsImpl(Multimap<?, ?> multimap, @Nullable Object object) {
     if (object == multimap) {
       return true;
diff --git a/guava/src/com/google/common/collect/Multiset.java b/guava/src/com/google/common/collect/Multiset.java
index b29b689..940a216 100644
--- a/guava/src/com/google/common/collect/Multiset.java
+++ b/guava/src/com/google/common/collect/Multiset.java
@@ -77,13 +77,13 @@ import javax.annotation.Nullable;
  * may wish to use {@link com.google.common.util.concurrent.AtomicLongMap}
  * instead. Note, however, that unlike {@code Multiset}, {@code AtomicLongMap}
  * does not automatically remove zeros.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface Multiset<E> extends Collection<E> {
@@ -229,7 +229,7 @@ public interface Multiset<E> extends Collection<E> {
    * snapshots. Note that this type is unrelated to the similarly-named type
    * {@code Map.Entry}.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   interface Entry<E> {
 
@@ -380,6 +380,9 @@ public interface Multiset<E> extends Collection<E> {
    * always increment the count of the element, and the overall size of the
    * collection, by one.
    *
+   * <p>To both add the element and obtain the previous count of that element,
+   * use {@link #add(E, int) add}{@code (element, 1)} instead.
+   *
    * @param element the element to add one occurrence of; may be null only if
    *     explicitly allowed by the implementation
    * @return {@code true} always, since this call is required to modify the
@@ -400,6 +403,9 @@ public interface Multiset<E> extends Collection<E> {
    * <b>may not</b> throw an exception in response to {@code element} being null
    * or of the wrong type.
    *
+   * <p>To both remove the element and obtain the previous count of that element,
+   * use {@link #remove(E, int) remove}{@code (element, 1)} instead.
+   *
    * @param element the element to remove one occurrence of
    * @return {@code true} if an occurrence was found and removed
    */
@@ -413,10 +419,10 @@ public interface Multiset<E> extends Collection<E> {
    * {@code c}, and only cares whether or not an element appears at all.
    * If you wish to remove one occurrence in this multiset for every occurrence
    * in {@code c}, see {@link Multisets#removeOccurrences(Multiset, Multiset)}.
-   * 
+   *
    * <p>This method refines {@link Collection#removeAll} to further specify that
    * it <b>may not</b> throw an exception in response to any of {@code elements}
-   * being null or of the wrong type. 
+   * being null or of the wrong type.
    */
   @Override
   boolean removeAll(Collection<?> c);
@@ -428,11 +434,11 @@ public interface Multiset<E> extends Collection<E> {
    * {@code c}, and only cares whether or not an element appears at all.
    * If you wish to remove one occurrence in this multiset for every occurrence
    * in {@code c}, see {@link Multisets#retainOccurrences(Multiset, Multiset)}.
-   * 
+   *
    * <p>This method refines {@link Collection#retainAll} to further specify that
    * it <b>may not</b> throw an exception in response to any of {@code elements}
    * being null or of the wrong type.
-   * 
+   *
    * @see Multisets#retainOccurrences(Multiset, Multiset)
    */
   @Override
diff --git a/guava/src/com/google/common/collect/Multisets.java b/guava/src/com/google/common/collect/Multisets.java
index 2ce27a5..2f4d184 100644
--- a/guava/src/com/google/common/collect/Multisets.java
+++ b/guava/src/com/google/common/collect/Multisets.java
@@ -37,6 +37,7 @@ import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -44,13 +45,13 @@ import javax.annotation.Nullable;
  * Multiset} instances.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multisets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multisets">
  * {@code Multisets}</a>.
  *
  * @author Kevin Bourrillion
  * @author Mike Bostock
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public final class Multisets {
@@ -69,10 +70,8 @@ public final class Multisets {
    *     generated
    * @return an unmodifiable view of the multiset
    */
-  public static <E> Multiset<E> unmodifiableMultiset(
-      Multiset<? extends E> multiset) {
-    if (multiset instanceof UnmodifiableMultiset ||
-        multiset instanceof ImmutableMultiset) {
+  public static <E> Multiset<E> unmodifiableMultiset(Multiset<? extends E> multiset) {
+    if (multiset instanceof UnmodifiableMultiset || multiset instanceof ImmutableMultiset) {
       // Since it's unmodifiable, the covariant cast is safe
       @SuppressWarnings("unchecked")
       Multiset<E> result = (Multiset<E>) multiset;
@@ -87,13 +86,12 @@ public final class Multisets {
    * @deprecated no need to use this
    * @since 10.0
    */
-  @Deprecated public static <E> Multiset<E> unmodifiableMultiset(
-      ImmutableMultiset<E> multiset) {
+  @Deprecated
+  public static <E> Multiset<E> unmodifiableMultiset(ImmutableMultiset<E> multiset) {
     return checkNotNull(multiset);
   }
 
-  static class UnmodifiableMultiset<E>
-      extends ForwardingMultiset<E> implements Serializable {
+  static class UnmodifiableMultiset<E> extends ForwardingMultiset<E> implements Serializable {
     final Multiset<? extends E> delegate;
 
     UnmodifiableMultiset(Multiset<? extends E> delegate) {
@@ -101,7 +99,8 @@ public final class Multisets {
     }
 
     @SuppressWarnings("unchecked")
-    @Override protected Multiset<E> delegate() {
+    @Override
+    protected Multiset<E> delegate() {
       // This is safe because all non-covariant methods are overriden
       return (Multiset<E>) delegate;
     }
@@ -121,7 +120,8 @@ public final class Multisets {
     transient Set<Multiset.Entry<E>> entrySet;
 
     @SuppressWarnings("unchecked")
-    @Override public Set<Multiset.Entry<E>> entrySet() {
+    @Override
+    public Set<Multiset.Entry<E>> entrySet() {
       Set<Multiset.Entry<E>> es = entrySet;
       return (es == null)
           // Safe because the returned set is made unmodifiable and Entry
@@ -131,48 +131,59 @@ public final class Multisets {
     }
 
     @SuppressWarnings("unchecked")
-    @Override public Iterator<E> iterator() {
+    @Override
+    public Iterator<E> iterator() {
       // Safe because the returned Iterator is made unmodifiable
       return (Iterator<E>) Iterators.unmodifiableIterator(delegate.iterator());
     }
 
-    @Override public boolean add(E element) {
+    @Override
+    public boolean add(E element) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public int add(E element, int occurences) {
+    @Override
+    public int add(E element, int occurences) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
+    @Override
+    public boolean addAll(Collection<? extends E> elementsToAdd) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean remove(Object element) {
+    @Override
+    public boolean remove(Object element) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public int remove(Object element, int occurrences) {
+    @Override
+    public int remove(Object element, int occurrences) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean removeAll(Collection<?> elementsToRemove) {
+    @Override
+    public boolean removeAll(Collection<?> elementsToRemove) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean retainAll(Collection<?> elementsToRetain) {
+    @Override
+    public boolean retainAll(Collection<?> elementsToRetain) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       throw new UnsupportedOperationException();
     }
 
-    @Override public int setCount(E element, int count) {
+    @Override
+    public int setCount(E element, int count) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public boolean setCount(E element, int oldCount, int newCount) {
+    @Override
+    public boolean setCount(E element, int oldCount, int newCount) {
       throw new UnsupportedOperationException();
     }
 
@@ -194,8 +205,7 @@ public final class Multisets {
    * @since 11.0
    */
   @Beta
-  public static <E> SortedMultiset<E> unmodifiableSortedMultiset(
-      SortedMultiset<E> sortedMultiset) {
+  public static <E> SortedMultiset<E> unmodifiableSortedMultiset(SortedMultiset<E> sortedMultiset) {
     // it's in its own file so it can be emulated for GWT
     return new UnmodifiableSortedMultiset<E>(checkNotNull(sortedMultiset));
   }
@@ -212,10 +222,9 @@ public final class Multisets {
     return new ImmutableEntry<E>(e, n);
   }
 
-  static final class ImmutableEntry<E> extends AbstractEntry<E> implements
-      Serializable {
-    @Nullable final E element;
-    final int count;
+  static class ImmutableEntry<E> extends AbstractEntry<E> implements Serializable {
+    @Nullable private final E element;
+    private final int count;
 
     ImmutableEntry(@Nullable E element, int count) {
       this.element = element;
@@ -224,15 +233,20 @@ public final class Multisets {
     }
 
     @Override
-    @Nullable public E getElement() {
+    @Nullable
+    public final E getElement() {
       return element;
     }
 
     @Override
-    public int getCount() {
+    public final int getCount() {
       return count;
     }
 
+    public ImmutableEntry<E> nextInBucket() {
+      return null;
+    }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -263,13 +277,13 @@ public final class Multisets {
    * @since 14.0
    */
   @Beta
+  @CheckReturnValue
   public static <E> Multiset<E> filter(Multiset<E> unfiltered, Predicate<? super E> predicate) {
     if (unfiltered instanceof FilteredMultiset) {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredMultiset<E> filtered = (FilteredMultiset<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
       return new FilteredMultiset<E>(filtered.unfiltered, combinedPredicate);
     }
     return new FilteredMultiset<E>(unfiltered, predicate);
@@ -296,12 +310,14 @@ public final class Multisets {
 
     @Override
     Set<Entry<E>> createEntrySet() {
-      return Sets.filter(unfiltered.entrySet(), new Predicate<Entry<E>>() {
-        @Override
-        public boolean apply(Entry<E> entry) {
-          return predicate.apply(entry.getElement());
-        }
-      });
+      return Sets.filter(
+          unfiltered.entrySet(),
+          new Predicate<Entry<E>>() {
+            @Override
+            public boolean apply(Entry<E> entry) {
+              return predicate.apply(entry.getElement());
+            }
+          });
     }
 
     @Override
@@ -327,8 +343,8 @@ public final class Multisets {
 
     @Override
     public int add(@Nullable E element, int occurrences) {
-      checkArgument(predicate.apply(element),
-          "Element %s does not match predicate %s", element, predicate);
+      checkArgument(
+          predicate.apply(element), "Element %s does not match predicate %s", element, predicate);
       return unfiltered.add(element, occurrences);
     }
 
@@ -405,11 +421,9 @@ public final class Multisets {
 
       @Override
       Iterator<Entry<E>> entryIterator() {
-        final Iterator<? extends Entry<? extends E>> iterator1
-            = multiset1.entrySet().iterator();
-        final Iterator<? extends Entry<? extends E>> iterator2
-            = multiset2.entrySet().iterator();
-        // TODO(user): consider making the entries live views
+        final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
+        final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
+        // TODO(lowasser): consider making the entries live views
         return new AbstractIterator<Entry<E>>() {
           @Override
           protected Entry<E> computeNext() {
@@ -466,14 +480,13 @@ public final class Multisets {
 
       @Override
       Set<E> createElementSet() {
-        return Sets.intersection(
-            multiset1.elementSet(), multiset2.elementSet());
+        return Sets.intersection(multiset1.elementSet(), multiset2.elementSet());
       }
 
       @Override
       Iterator<Entry<E>> entryIterator() {
         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
-        // TODO(user): consider making the entries live views
+        // TODO(lowasser): consider making the entries live views
         return new AbstractIterator<Entry<E>>() {
           @Override
           protected Entry<E> computeNext() {
@@ -518,7 +531,7 @@ public final class Multisets {
     checkNotNull(multiset1);
     checkNotNull(multiset2);
 
-    // TODO(user): consider making the entries live views
+    // TODO(lowasser): consider making the entries live views
     return new AbstractMultiset<E>() {
       @Override
       public boolean contains(@Nullable Object element) {
@@ -547,10 +560,8 @@ public final class Multisets {
 
       @Override
       Iterator<Entry<E>> entryIterator() {
-        final Iterator<? extends Entry<? extends E>> iterator1
-            = multiset1.entrySet().iterator();
-        final Iterator<? extends Entry<? extends E>> iterator2
-            = multiset2.entrySet().iterator();
+        final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
+        final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
         return new AbstractIterator<Entry<E>>() {
           @Override
           protected Entry<E> computeNext() {
@@ -600,13 +611,12 @@ public final class Multisets {
     checkNotNull(multiset1);
     checkNotNull(multiset2);
 
-    // TODO(user): consider making the entries live views
+    // TODO(lowasser): consider making the entries live views
     return new AbstractMultiset<E>() {
       @Override
       public int count(@Nullable Object element) {
         int count1 = multiset1.count(element);
-        return (count1 == 0) ? 0 :
-            Math.max(0, count1 - multiset2.count(element));
+        return (count1 == 0) ? 0 : Math.max(0, count1 - multiset2.count(element));
       }
 
       @Override
@@ -641,8 +651,7 @@ public final class Multisets {
    *
    * @since 10.0
    */
-  public static boolean containsOccurrences(
-      Multiset<?> superMultiset, Multiset<?> subMultiset) {
+  public static boolean containsOccurrences(Multiset<?> superMultiset, Multiset<?> subMultiset) {
     checkNotNull(superMultiset);
     checkNotNull(subMultiset);
     for (Entry<?> entry : subMultiset.entrySet()) {
@@ -673,8 +682,8 @@ public final class Multisets {
    *         of this operation
    * @since 10.0
    */
-  public static boolean retainOccurrences(Multiset<?> multisetToModify,
-      Multiset<?> multisetToRetain) {
+  public static boolean retainOccurrences(
+      Multiset<?> multisetToModify, Multiset<?> multisetToRetain) {
     return retainOccurrencesImpl(multisetToModify, multisetToRetain);
   }
 
@@ -709,7 +718,7 @@ public final class Multisets {
    * <p>Equivalently, this method modifies {@code multisetToModify} so that
    * {@code multisetToModify.count(e)} is set to
    * {@code Math.max(0, multisetToModify.count(e) -
-   * occurrencesToRemove.count(e))}.
+   * Iterables.frequency(occurrencesToRemove, e))}.
    *
    * <p>This is <i>not</i> the same as {@code multisetToModify.}
    * {@link Multiset#removeAll removeAll}{@code (occurrencesToRemove)}, which
@@ -729,37 +738,50 @@ public final class Multisets {
   public static boolean removeOccurrences(
       Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
     if (occurrencesToRemove instanceof Multiset) {
-      return removeOccurrencesImpl(
-          multisetToModify, (Multiset<?>) occurrencesToRemove);
+      return removeOccurrences(multisetToModify, (Multiset<?>) occurrencesToRemove);
     } else {
-      return removeOccurrencesImpl(multisetToModify, occurrencesToRemove);
-    }
-  }
-
-  private static boolean removeOccurrencesImpl(
-      Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
-    checkNotNull(multisetToModify);
-    checkNotNull(occurrencesToRemove);
-    boolean changed = false;
-    for (Object o : occurrencesToRemove) {
-      changed |= multisetToModify.remove(o);
+      checkNotNull(multisetToModify);
+      checkNotNull(occurrencesToRemove);
+      boolean changed = false;
+      for (Object o : occurrencesToRemove) {
+        changed |= multisetToModify.remove(o);
+      }
+      return changed;
     }
-    return changed;
   }
 
   /**
-   * Delegate that cares about the element types in multisetToModify.
+   * For each occurrence of an element {@code e} in {@code occurrencesToRemove},
+   * removes one occurrence of {@code e} in {@code multisetToModify}.
+   *
+   * <p>Equivalently, this method modifies {@code multisetToModify} so that
+   * {@code multisetToModify.count(e)} is set to
+   * {@code Math.max(0, multisetToModify.count(e) -
+   * occurrencesToRemove.count(e))}.
+   *
+   * <p>This is <i>not</i> the same as {@code multisetToModify.}
+   * {@link Multiset#removeAll removeAll}{@code (occurrencesToRemove)}, which
+   * removes all occurrences of elements that appear in
+   * {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent
+   * to, albeit sometimes more efficient than, the following: <pre>   {@code
+   *
+   *   for (E e : occurrencesToRemove) {
+   *     multisetToModify.remove(e);
+   *   }}</pre>
+   *
+   * @return {@code true} if {@code multisetToModify} was changed as a result of
+   *         this operation
+   * @since 10.0 (missing in 18.0 when only the overload taking an {@code Iterable} was present)
    */
-  private static <E> boolean removeOccurrencesImpl(
-      Multiset<E> multisetToModify, Multiset<?> occurrencesToRemove) {
-    // TODO(user): generalize to removing an Iterable, perhaps
+  public static boolean removeOccurrences(
+      Multiset<?> multisetToModify, Multiset<?> occurrencesToRemove) {
     checkNotNull(multisetToModify);
     checkNotNull(occurrencesToRemove);
 
     boolean changed = false;
-    Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
+    Iterator<? extends Entry<?>> entryIterator = multisetToModify.entrySet().iterator();
     while (entryIterator.hasNext()) {
-      Entry<E> entry = entryIterator.next();
+      Entry<?> entry = entryIterator.next();
       int removeCount = occurrencesToRemove.count(entry.getElement());
       if (removeCount >= entry.getCount()) {
         entryIterator.remove();
@@ -781,7 +803,8 @@ public final class Multisets {
      * Indicates whether an object equals this entry, following the behavior
      * specified in {@link Multiset.Entry#equals}.
      */
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object instanceof Multiset.Entry) {
         Multiset.Entry<?> that = (Multiset.Entry<?>) object;
         return this.getCount() == that.getCount()
@@ -794,7 +817,8 @@ public final class Multisets {
      * Return this entry's hash code, following the behavior specified in
      * {@link Multiset.Entry#hashCode}.
      */
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       E e = getElement();
       return ((e == null) ? 0 : e.hashCode()) ^ getCount();
     }
@@ -806,7 +830,8 @@ public final class Multisets {
      * " x " (space, x and space) followed by the count. Elements and counts are
      * converted to strings as by {@code String.valueOf}.
      */
-    @Override public String toString() {
+    @Override
+    public String toString() {
       String text = String.valueOf(getElement());
       int n = getCount();
       return (n == 1) ? text : (text + " x " + n);
@@ -828,8 +853,7 @@ public final class Multisets {
        * when passed unequal elements.
        */
 
-      if (multiset.size() != that.size()
-          || multiset.entrySet().size() != that.entrySet().size()) {
+      if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) {
         return false;
       }
       for (Entry<?> entry : that.entrySet()) {
@@ -845,8 +869,7 @@ public final class Multisets {
   /**
    * An implementation of {@link Multiset#addAll}.
    */
-  static <E> boolean addAllImpl(
-      Multiset<E> self, Collection<? extends E> elements) {
+  static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) {
     if (elements.isEmpty()) {
       return false;
     }
@@ -864,10 +887,11 @@ public final class Multisets {
   /**
    * An implementation of {@link Multiset#removeAll}.
    */
-  static boolean removeAllImpl(
-      Multiset<?> self, Collection<?> elementsToRemove) {
-    Collection<?> collection = (elementsToRemove instanceof Multiset)
-        ? ((Multiset<?>) elementsToRemove).elementSet() : elementsToRemove;
+  static boolean removeAllImpl(Multiset<?> self, Collection<?> elementsToRemove) {
+    Collection<?> collection =
+        (elementsToRemove instanceof Multiset)
+            ? ((Multiset<?>) elementsToRemove).elementSet()
+            : elementsToRemove;
 
     return self.elementSet().removeAll(collection);
   }
@@ -875,11 +899,12 @@ public final class Multisets {
   /**
    * An implementation of {@link Multiset#retainAll}.
    */
-  static boolean retainAllImpl(
-      Multiset<?> self, Collection<?> elementsToRetain) {
+  static boolean retainAllImpl(Multiset<?> self, Collection<?> elementsToRetain) {
     checkNotNull(elementsToRetain);
-    Collection<?> collection = (elementsToRetain instanceof Multiset)
-        ? ((Multiset<?>) elementsToRetain).elementSet() : elementsToRetain;
+    Collection<?> collection =
+        (elementsToRetain instanceof Multiset)
+            ? ((Multiset<?>) elementsToRetain).elementSet()
+            : elementsToRetain;
 
     return self.elementSet().retainAll(collection);
   }
@@ -905,8 +930,7 @@ public final class Multisets {
   /**
    * An implementation of {@link Multiset#setCount(Object, int, int)}.
    */
-  static <E> boolean setCountImpl(
-      Multiset<E> self, E element, int oldCount, int newCount) {
+  static <E> boolean setCountImpl(Multiset<E> self, E element, int oldCount, int newCount) {
     checkNonnegative(oldCount, "oldCount");
     checkNonnegative(newCount, "newCount");
 
@@ -921,23 +945,28 @@ public final class Multisets {
   abstract static class ElementSet<E> extends Sets.ImprovedAbstractSet<E> {
     abstract Multiset<E> multiset();
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multiset().clear();
     }
 
-    @Override public boolean contains(Object o) {
+    @Override
+    public boolean contains(Object o) {
       return multiset().contains(o);
     }
 
-    @Override public boolean containsAll(Collection<?> c) {
+    @Override
+    public boolean containsAll(Collection<?> c) {
       return multiset().containsAll(c);
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return multiset().isEmpty();
     }
 
-    @Override public Iterator<E> iterator() {
+    @Override
+    public Iterator<E> iterator() {
       return new TransformedIterator<Entry<E>, E>(multiset().entrySet().iterator()) {
         @Override
         E transform(Entry<E> entry) {
@@ -948,15 +977,11 @@ public final class Multisets {
 
     @Override
     public boolean remove(Object o) {
-      int count = multiset().count(o);
-      if (count > 0) {
-        multiset().remove(o, count);
-        return true;
-      }
-      return false;
+      return multiset().remove(o, Integer.MAX_VALUE) > 0;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return multiset().entrySet().size();
     }
   }
@@ -964,7 +989,8 @@ public final class Multisets {
   abstract static class EntrySet<E> extends Sets.ImprovedAbstractSet<Entry<E>> {
     abstract Multiset<E> multiset();
 
-    @Override public boolean contains(@Nullable Object o) {
+    @Override
+    public boolean contains(@Nullable Object o) {
       if (o instanceof Entry) {
         /*
          * The GWT compiler wrongly issues a warning here.
@@ -976,14 +1002,14 @@ public final class Multisets {
         }
         int count = multiset().count(entry.getElement());
         return count == entry.getCount();
-
       }
       return false;
     }
 
     // GWT compiler warning; see contains().
     @SuppressWarnings("cast")
-    @Override public boolean remove(Object object) {
+    @Override
+    public boolean remove(Object object) {
       if (object instanceof Multiset.Entry) {
         Entry<?> entry = (Entry<?>) object;
         Object element = entry.getElement();
@@ -998,7 +1024,8 @@ public final class Multisets {
       return false;
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       multiset().clear();
     }
   }
@@ -1007,22 +1034,23 @@ public final class Multisets {
    * An implementation of {@link Multiset#iterator}.
    */
   static <E> Iterator<E> iteratorImpl(Multiset<E> multiset) {
-    return new MultisetIteratorImpl<E>(
-        multiset, multiset.entrySet().iterator());
+    return new MultisetIteratorImpl<E>(multiset, multiset.entrySet().iterator());
   }
 
   static final class MultisetIteratorImpl<E> implements Iterator<E> {
     private final Multiset<E> multiset;
     private final Iterator<Entry<E>> entryIterator;
     private Entry<E> currentEntry;
+
     /** Count of subsequent elements equal to current element */
     private int laterCount;
+
     /** Count of all elements equal to current element */
     private int totalCount;
+
     private boolean canRemove;
 
-    MultisetIteratorImpl(
-        Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
+    MultisetIteratorImpl(Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
       this.multiset = multiset;
       this.entryIterator = entryIterator;
     }
@@ -1077,12 +1105,13 @@ public final class Multisets {
     return (Multiset<T>) iterable;
   }
 
-  private static final Ordering<Entry<?>> DECREASING_COUNT_ORDERING = new Ordering<Entry<?>>() {
-    @Override
-    public int compare(Entry<?> entry1, Entry<?> entry2) {
-      return Ints.compare(entry2.getCount(), entry1.getCount());
-    }
-  };
+  private static final Ordering<Entry<?>> DECREASING_COUNT_ORDERING =
+      new Ordering<Entry<?>>() {
+        @Override
+        public int compare(Entry<?> entry1, Entry<?> entry2) {
+          return Ints.compare(entry2.getCount(), entry1.getCount());
+        }
+      };
 
   /**
    * Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order is
diff --git a/guava/src/com/google/common/collect/MutableClassToInstanceMap.java b/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
index c723cea..4b4d771 100644
--- a/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
@@ -25,16 +25,15 @@ import java.util.Map;
 /**
  * A mutable class-to-instance map backed by an arbitrary user-provided map.
  * See also {@link ImmutableClassToInstanceMap}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap">
  * {@code ClassToInstanceMap}</a>.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
-public final class MutableClassToInstanceMap<B>
-    extends ConstrainedMap<Class<? extends B>, B>
+public final class MutableClassToInstanceMap<B> extends ConstrainedMap<Class<? extends B>, B>
     implements ClassToInstanceMap<B> {
 
   /**
@@ -42,8 +41,7 @@ public final class MutableClassToInstanceMap<B>
    * HashMap} using the default initial capacity and load factor.
    */
   public static <B> MutableClassToInstanceMap<B> create() {
-    return new MutableClassToInstanceMap<B>(
-        new HashMap<Class<? extends B>, B>());
+    return new MutableClassToInstanceMap<B>(new HashMap<Class<? extends B>, B>());
   }
 
   /**
@@ -51,8 +49,7 @@ public final class MutableClassToInstanceMap<B>
    * empty {@code backingMap}. The caller surrenders control of the backing map,
    * and thus should not allow any direct references to it to remain accessible.
    */
-  public static <B> MutableClassToInstanceMap<B> create(
-      Map<Class<? extends B>, B> backingMap) {
+  public static <B> MutableClassToInstanceMap<B> create(Map<Class<? extends B>, B> backingMap) {
     return new MutableClassToInstanceMap<B>(backingMap);
   }
 
@@ -60,13 +57,13 @@ public final class MutableClassToInstanceMap<B>
     super(delegate, VALUE_CAN_BE_CAST_TO_KEY);
   }
 
-  private static final MapConstraint<Class<?>, Object> VALUE_CAN_BE_CAST_TO_KEY
-      = new MapConstraint<Class<?>, Object>() {
-    @Override
-    public void checkKeyValue(Class<?> key, Object value) {
-      cast(key, value);
-    }
-  };
+  private static final MapConstraint<Class<?>, Object> VALUE_CAN_BE_CAST_TO_KEY =
+      new MapConstraint<Class<?>, Object>() {
+        @Override
+        public void checkKeyValue(Class<?> key, Object value) {
+          cast(key, value);
+        }
+      };
 
   @Override
   public <T extends B> T putInstance(Class<T> type, T value) {
diff --git a/guava/src/com/google/common/collect/NaturalOrdering.java b/guava/src/com/google/common/collect/NaturalOrdering.java
index a4c240f..fbacf01 100644
--- a/guava/src/com/google/common/collect/NaturalOrdering.java
+++ b/guava/src/com/google/common/collect/NaturalOrdering.java
@@ -25,17 +25,18 @@ import java.io.Serializable;
 /** An ordering that uses the natural order of the values. */
 @GwtCompatible(serializable = true)
 @SuppressWarnings("unchecked") // TODO(kevinb): the right way to explain this??
-final class NaturalOrdering
-    extends Ordering<Comparable> implements Serializable {
+final class NaturalOrdering extends Ordering<Comparable> implements Serializable {
   static final NaturalOrdering INSTANCE = new NaturalOrdering();
 
-  @Override public int compare(Comparable left, Comparable right) {
+  @Override
+  public int compare(Comparable left, Comparable right) {
     checkNotNull(left); // for GWT
     checkNotNull(right);
     return left.compareTo(right);
   }
 
-  @Override public <S extends Comparable> Ordering<S> reverse() {
+  @Override
+  public <S extends Comparable> Ordering<S> reverse() {
     return (Ordering<S>) ReverseNaturalOrdering.INSTANCE;
   }
 
@@ -44,7 +45,8 @@ final class NaturalOrdering
     return INSTANCE;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Ordering.natural()";
   }
 
diff --git a/guava/src/com/google/common/collect/NullsFirstOrdering.java b/guava/src/com/google/common/collect/NullsFirstOrdering.java
index 2e8a3ac..28d8fec 100644
--- a/guava/src/com/google/common/collect/NullsFirstOrdering.java
+++ b/guava/src/com/google/common/collect/NullsFirstOrdering.java
@@ -31,7 +31,8 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
     this.ordering = ordering;
   }
 
-  @Override public int compare(@Nullable T left, @Nullable T right) {
+  @Override
+  public int compare(@Nullable T left, @Nullable T right) {
     if (left == right) {
       return 0;
     }
@@ -44,21 +45,25 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
     return ordering.compare(left, right);
   }
 
-  @Override public <S extends T> Ordering<S> reverse() {
+  @Override
+  public <S extends T> Ordering<S> reverse() {
     // ordering.reverse() might be optimized, so let it do its thing
     return ordering.reverse().nullsLast();
   }
 
   @SuppressWarnings("unchecked") // still need the right way to explain this
-  @Override public <S extends T> Ordering<S> nullsFirst() {
+  @Override
+  public <S extends T> Ordering<S> nullsFirst() {
     return (Ordering<S>) this;
   }
 
-  @Override public <S extends T> Ordering<S> nullsLast() {
+  @Override
+  public <S extends T> Ordering<S> nullsLast() {
     return ordering.nullsLast();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -69,11 +74,13 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return ordering.hashCode() ^ 957692532; // meaningless
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return ordering + ".nullsFirst()";
   }
 
diff --git a/guava/src/com/google/common/collect/NullsLastOrdering.java b/guava/src/com/google/common/collect/NullsLastOrdering.java
index 9de17bd..a4b39db 100644
--- a/guava/src/com/google/common/collect/NullsLastOrdering.java
+++ b/guava/src/com/google/common/collect/NullsLastOrdering.java
@@ -31,7 +31,8 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
     this.ordering = ordering;
   }
 
-  @Override public int compare(@Nullable T left, @Nullable T right) {
+  @Override
+  public int compare(@Nullable T left, @Nullable T right) {
     if (left == right) {
       return 0;
     }
@@ -44,21 +45,25 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
     return ordering.compare(left, right);
   }
 
-  @Override public <S extends T> Ordering<S> reverse() {
+  @Override
+  public <S extends T> Ordering<S> reverse() {
     // ordering.reverse() might be optimized, so let it do its thing
     return ordering.reverse().nullsFirst();
   }
 
-  @Override public <S extends T> Ordering<S> nullsFirst() {
+  @Override
+  public <S extends T> Ordering<S> nullsFirst() {
     return ordering.nullsFirst();
   }
 
   @SuppressWarnings("unchecked") // still need the right way to explain this
-  @Override public <S extends T> Ordering<S> nullsLast() {
+  @Override
+  public <S extends T> Ordering<S> nullsLast() {
     return (Ordering<S>) this;
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -69,11 +74,13 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return ordering.hashCode() ^ -921210296; // meaningless
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return ordering + ".nullsLast()";
   }
 
diff --git a/guava/src/com/google/common/collect/ObjectArrays.java b/guava/src/com/google/common/collect/ObjectArrays.java
index 16f0e4e..2328002 100644
--- a/guava/src/com/google/common/collect/ObjectArrays.java
+++ b/guava/src/com/google/common/collect/ObjectArrays.java
@@ -30,7 +30,7 @@ import javax.annotation.Nullable;
  * Static utility methods pertaining to object arrays.
  *
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class ObjectArrays {
@@ -110,8 +110,7 @@ public final class ObjectArrays {
   /** GWT safe version of Arrays.copyOf. */
   static <T> T[] arraysCopyOf(T[] original, int newLength) {
     T[] copy = newArray(original, newLength);
-    System.arraycopy(
-        original, 0, copy, 0, Math.min(original.length, newLength));
+    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
     return copy;
   }
 
@@ -150,7 +149,7 @@ public final class ObjectArrays {
     }
     return array;
   }
-  
+
   /**
    * Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
    * array. the runtime type of the returned array is that of the specified array. If the collection
@@ -225,7 +224,7 @@ public final class ObjectArrays {
   static Object[] checkElementsNotNull(Object... array) {
     return checkElementsNotNull(array, array.length);
   }
-  
+
   static Object[] checkElementsNotNull(Object[] array, int length) {
     for (int i = 0; i < length; i++) {
       checkElementNotNull(array[i], i);
diff --git a/guava/src/com/google/common/collect/Ordering.java b/guava/src/com/google/common/collect/Ordering.java
index 8b15aef..f31a422 100644
--- a/guava/src/com/google/common/collect/Ordering.java
+++ b/guava/src/com/google/common/collect/Ordering.java
@@ -41,22 +41,30 @@ import java.util.concurrent.atomic.AtomicInteger;
 import javax.annotation.Nullable;
 
 /**
- * A comparator, with additional methods to support common operations. This is
- * an "enriched" version of {@code Comparator}, in the same sense that {@link
- * FluentIterable} is an enriched {@link Iterable}.
+ * A comparator, with additional methods to support common operations. This is an "enriched"
+ * version of {@code Comparator}, in the same sense that {@link FluentIterable} is an enriched
+ * {@link Iterable}.
+ *
+ * <h3>Three types of methods</h3>
+ *
+ * Like other fluent types, there are three types of methods present: methods for <i>acquiring</i>,
+ * <i>chaining</i>, and <i>using</i>.
+ *
+ * <h4>Acquiring</h4>
  *
  * <p>The common ways to get an instance of {@code Ordering} are:
  *
  * <ul>
- * <li>Subclass it and implement {@link #compare} instead of implementing
- *     {@link Comparator} directly
- * <li>Pass a <i>pre-existing</i> {@link Comparator} instance to {@link
- *     #from(Comparator)}
+ * <li>Subclass it and implement {@link #compare} instead of implementing {@link Comparator}
+ *     directly
+ * <li>Pass a <i>pre-existing</i> {@link Comparator} instance to {@link #from(Comparator)}
  * <li>Use the natural ordering, {@link Ordering#natural}
  * </ul>
  *
- * <p>Then you can use the <i>chaining</i> methods to get an altered version of
- * that {@code Ordering}, including:
+ * <h4>Chaining</h4>
+ *
+ * <p>Then you can use the <i>chaining</i> methods to get an altered version of that {@code
+ * Ordering}, including:
  *
  * <ul>
  * <li>{@link #reverse}
@@ -65,8 +73,10 @@ import javax.annotation.Nullable;
  * <li>{@link #nullsFirst} / {@link #nullsLast}
  * </ul>
  *
- * <p>Finally, use the resulting {@code Ordering} anywhere a {@link Comparator}
- * is required, or use any of its special operations, such as:</p>
+ * <h4>Using</h4>
+ *
+ * <p>Finally, use the resulting {@code Ordering} anywhere a {@link Comparator} is required, or use
+ * any of its special operations, such as:</p>
  *
  * <ul>
  * <li>{@link #immutableSortedCopy}
@@ -74,18 +84,49 @@ import javax.annotation.Nullable;
  * <li>{@link #min} / {@link #max}
  * </ul>
  *
+ * <h3>Understanding complex orderings</h3>
+ *
+ * <p>Complex chained orderings like the following example can be challenging to understand.
+ * <pre>   {@code
+ *
+ *   Ordering<Foo> ordering =
+ *       Ordering.natural()
+ *           .nullsFirst()
+ *           .onResultOf(getBarFunction)
+ *           .nullsLast();}</pre>
+ *
+ * Note that each chaining method returns a new ordering instance which is backed by the previous
+ * instance, but has the chance to act on values <i>before</i> handing off to that backing
+ * instance. As a result, it usually helps to read chained ordering expressions <i>backwards</i>.
+ * For example, when {@code compare} is called on the above ordering:
+ *
+ * <ol>
+ * <li>First, if only one {@code Foo} is null, that null value is treated as <i>greater</i>
+ * <li>Next, non-null {@code Foo} values are passed to {@code getBarFunction} (we will be
+ *     comparing {@code Bar} values from now on)
+ * <li>Next, if only one {@code Bar} is null, that null value is treated as <i>lesser</i>
+ * <li>Finally, natural ordering is used (i.e. the result of {@code Bar.compareTo(Bar)} is
+ *     returned)
+ * </ol>
+ *
+ * <p>Alas, {@link #reverse} is a little different. As you read backwards through a chain and
+ * encounter a call to {@code reverse}, continue working backwards until a result is determined,
+ * and then reverse that result.
+ *
+ * <h3>Additional notes</h3>
+ *
  * <p>Except as noted, the orderings returned by the factory methods of this
  * class are serializable if and only if the provided instances that back them
  * are. For example, if {@code ordering} and {@code function} can themselves be
  * serialized, then {@code ordering.onResultOf(function)} can as well.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/OrderingExplained">
+ * "https://github.com/google/guava/wiki/OrderingExplained">
  * {@code Ordering}</a>.
  *
  * @author Jesse Wilson
  * @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class Ordering<T> implements Comparator<T> {
@@ -132,7 +173,8 @@ public abstract class Ordering<T> implements Comparator<T> {
    * @deprecated no need to use this
    */
   @GwtCompatible(serializable = true)
-  @Deprecated public static <T> Ordering<T> from(Ordering<T> ordering) {
+  @Deprecated
+  public static <T> Ordering<T> from(Ordering<T> ordering) {
     return checkNotNull(ordering);
   }
 
@@ -186,8 +228,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    *     {@link Object#equals(Object)}) are present among the method arguments
    */
   @GwtCompatible(serializable = true)
-  public static <T> Ordering<T> explicit(
-      T leastValue, T... remainingValuesInOrder) {
+  public static <T> Ordering<T> explicit(T leastValue, T... remainingValuesInOrder) {
     return explicit(Lists.asList(leastValue, remainingValuesInOrder));
   }
 
@@ -261,19 +302,24 @@ public abstract class Ordering<T> implements Comparator<T> {
     static final Ordering<Object> ARBITRARY_ORDERING = new ArbitraryOrdering();
   }
 
-  @VisibleForTesting static class ArbitraryOrdering extends Ordering<Object> {
+  @VisibleForTesting
+  static class ArbitraryOrdering extends Ordering<Object> {
+
     @SuppressWarnings("deprecation") // TODO(kevinb): ?
     private Map<Object, Integer> uids =
-        Platform.tryWeakKeys(new MapMaker()).makeComputingMap(
-            new Function<Object, Integer>() {
-              final AtomicInteger counter = new AtomicInteger(0);
-              @Override
-              public Integer apply(Object from) {
-                return counter.getAndIncrement();
-              }
-            });
-
-    @Override public int compare(Object left, Object right) {
+        Platform.tryWeakKeys(new MapMaker())
+            .makeComputingMap(
+                new Function<Object, Integer>() {
+                  final AtomicInteger counter = new AtomicInteger(0);
+
+                  @Override
+                  public Integer apply(Object from) {
+                    return counter.getAndIncrement();
+                  }
+                });
+
+    @Override
+    public int compare(Object left, Object right) {
       if (left == right) {
         return 0;
       } else if (left == null) {
@@ -295,7 +341,8 @@ public abstract class Ordering<T> implements Comparator<T> {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Ordering.arbitrary()";
     }
 
@@ -385,8 +432,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    * the same component comparators.
    */
   @GwtCompatible(serializable = true)
-  public <U extends T> Ordering<U> compound(
-      Comparator<? super U> secondaryComparator) {
+  public <U extends T> Ordering<U> compound(Comparator<? super U> secondaryComparator) {
     return new CompoundOrdering<U>(this, checkNotNull(secondaryComparator));
   }
 
@@ -406,8 +452,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    * @param comparators the comparators to try in order
    */
   @GwtCompatible(serializable = true)
-  public static <T> Ordering<T> compound(
-      Iterable<? extends Comparator<? super T>> comparators) {
+  public static <T> Ordering<T> compound(Iterable<? extends Comparator<? super T>> comparators) {
     return new CompoundOrdering<T>(comparators);
   }
 
@@ -443,7 +488,8 @@ public abstract class Ordering<T> implements Comparator<T> {
   // Regular instance methods
 
   // Override to add @Nullable
-  @Override public abstract int compare(@Nullable T left, @Nullable T right);
+  @Override
+  public abstract int compare(@Nullable T left, @Nullable T right);
 
   /**
    * Returns the least of the specified values according to this ordering. If
@@ -510,8 +556,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    * @throws ClassCastException if the parameters are not <i>mutually
    *     comparable</i> under this ordering.
    */
-  public <E extends T> E min(
-      @Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
+  public <E extends T> E min(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
     E minSoFar = min(min(a, b), c);
 
     for (E r : rest) {
@@ -586,8 +631,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    * @throws ClassCastException if the parameters are not <i>mutually
    *     comparable</i> under this ordering.
    */
-  public <E extends T> E max(
-      @Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
+  public <E extends T> E max(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
     E maxSoFar = max(max(a, b), c);
 
     for (E r : rest) {
@@ -737,8 +781,7 @@ public abstract class Ordering<T> implements Comparator<T> {
     // We can't use ImmutableList; we have to be null-friendly!
   }
 
-  private <E extends T> int partition(
-      E[] values, int left, int right, int pivotIndex) {
+  private <E extends T> int partition(E[] values, int left, int right, int pivotIndex) {
     E pivotValue = values[pivotIndex];
 
     values[pivotIndex] = values[right];
@@ -836,8 +879,7 @@ public abstract class Ordering<T> implements Comparator<T> {
    *     elements} itself) is null
    * @since 3.0
    */
-  public <E extends T> ImmutableList<E> immutableSortedCopy(
-      Iterable<E> elements) {
+  public <E extends T> ImmutableList<E> immutableSortedCopy(Iterable<E> elements) {
     @SuppressWarnings("unchecked") // we'll only ever have E's in here
     E[] array = (E[]) Iterables.toArray(elements);
     for (E e : array) {
diff --git a/guava/src/com/google/common/collect/PeekingIterator.java b/guava/src/com/google/common/collect/PeekingIterator.java
index 294b2e6..13442a9 100644
--- a/guava/src/com/google/common/collect/PeekingIterator.java
+++ b/guava/src/com/google/common/collect/PeekingIterator.java
@@ -23,13 +23,13 @@ import java.util.NoSuchElementException;
 
 /**
  * An iterator that supports a one-element lookahead while iterating.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionHelpersExplained#PeekingIterator">
+ * "https://github.com/google/guava/wiki/CollectionHelpersExplained#peekingiterator">
  * {@code PeekingIterator}</a>.
  *
  * @author Mick Killianey
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface PeekingIterator<E> extends Iterator<E> {
diff --git a/guava/src/com/google/common/collect/Platform.java b/guava/src/com/google/common/collect/Platform.java
index 9fc907b..6e350b8 100644
--- a/guava/src/com/google/common/collect/Platform.java
+++ b/guava/src/com/google/common/collect/Platform.java
@@ -22,10 +22,12 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.Maps.EntryTransformer;
 
 import java.lang.reflect.Array;
+import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Map;
 import java.util.NavigableMap;
 import java.util.NavigableSet;
+import java.util.Queue;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
@@ -53,7 +55,7 @@ final class Platform {
     T[] result = (T[]) Array.newInstance(type, length);
     return result;
   }
-  
+
   static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
     return Collections.newSetFromMap(map);
   }
@@ -69,33 +71,35 @@ final class Platform {
   }
 
   static <K, V1, V2> SortedMap<K, V2> mapsTransformEntriesSortedMap(
-      SortedMap<K, V1> fromMap,
-      EntryTransformer<? super K, ? super V1, V2> transformer) {
+      SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
     return (fromMap instanceof NavigableMap)
         ? Maps.transformEntries((NavigableMap<K, V1>) fromMap, transformer)
         : Maps.transformEntriesIgnoreNavigable(fromMap, transformer);
   }
 
-  static <K, V> SortedMap<K, V> mapsAsMapSortedSet(SortedSet<K> set,
-      Function<? super K, V> function) {
+  static <K, V> SortedMap<K, V> mapsAsMapSortedSet(
+      SortedSet<K> set, Function<? super K, V> function) {
     return (set instanceof NavigableSet)
         ? Maps.asMap((NavigableSet<K>) set, function)
         : Maps.asMapSortedIgnoreNavigable(set, function);
   }
 
-  static <E> SortedSet<E> setsFilterSortedSet(SortedSet<E> set,
-      Predicate<? super E> predicate) {
+  static <E> SortedSet<E> setsFilterSortedSet(SortedSet<E> set, Predicate<? super E> predicate) {
     return (set instanceof NavigableSet)
         ? Sets.filter((NavigableSet<E>) set, predicate)
         : Sets.filterSortedIgnoreNavigable(set, predicate);
   }
-  
-  static <K, V> SortedMap<K, V> mapsFilterSortedMap(SortedMap<K, V> map,
-      Predicate<? super Map.Entry<K, V>> predicate) {
+
+  static <K, V> SortedMap<K, V> mapsFilterSortedMap(
+      SortedMap<K, V> map, Predicate<? super Map.Entry<K, V>> predicate) {
     return (map instanceof NavigableMap)
         ? Maps.filterEntries((NavigableMap<K, V>) map, predicate)
         : Maps.filterSortedIgnoreNavigable(map, predicate);
   }
 
+  static <E> Queue<E> newFastestQueue(int initialCapacity) {
+    return new ArrayDeque<E>(initialCapacity);
+  }
+
   private Platform() {}
 }
diff --git a/guava/src/com/google/common/collect/Queues.java b/guava/src/com/google/common/collect/Queues.java
index 1507838..bc8c0de 100644
--- a/guava/src/com/google/common/collect/Queues.java
+++ b/guava/src/com/google/common/collect/Queues.java
@@ -257,8 +257,13 @@ public final class Queues {
    * @throws InterruptedException if interrupted while waiting
    */
   @Beta
-  public static <E> int drain(BlockingQueue<E> q, Collection<? super E> buffer, int numElements,
-      long timeout, TimeUnit unit) throws InterruptedException {
+  public static <E> int drain(
+      BlockingQueue<E> q,
+      Collection<? super E> buffer,
+      int numElements,
+      long timeout,
+      TimeUnit unit)
+      throws InterruptedException {
     Preconditions.checkNotNull(buffer);
     /*
      * This code performs one System.nanoTime() more than necessary, and in return, the time to
@@ -282,13 +287,13 @@ public final class Queues {
     }
     return added;
   }
-  
+
   /**
-   * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)}, 
-   * but with a different behavior in case it is interrupted while waiting. In that case, the 
-   * operation will continue as usual, and in the end the thread's interruption status will be set 
-   * (no {@code InterruptedException} is thrown). 
-   * 
+   * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)},
+   * but with a different behavior in case it is interrupted while waiting. In that case, the
+   * operation will continue as usual, and in the end the thread's interruption status will be set
+   * (no {@code InterruptedException} is thrown).
+   *
    * @param q the blocking queue to be drained
    * @param buffer where to add the transferred elements
    * @param numElements the number of elements to be waited for
@@ -297,15 +302,19 @@ public final class Queues {
    * @return the number of elements transferred
    */
   @Beta
-  public static <E> int drainUninterruptibly(BlockingQueue<E> q, Collection<? super E> buffer, 
-      int numElements, long timeout, TimeUnit unit) {
+  public static <E> int drainUninterruptibly(
+      BlockingQueue<E> q,
+      Collection<? super E> buffer,
+      int numElements,
+      long timeout,
+      TimeUnit unit) {
     Preconditions.checkNotNull(buffer);
     long deadline = System.nanoTime() + unit.toNanos(timeout);
     int added = 0;
     boolean interrupted = false;
     try {
       while (added < numElements) {
-        // we could rely solely on #poll, but #drainTo might be more efficient when there are 
+        // we could rely solely on #poll, but #drainTo might be more efficient when there are
         // multiple elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
         added += q.drainTo(buffer, numElements - added);
         if (added < numElements) { // not enough elements immediately available; will have to poll
diff --git a/guava/src/com/google/common/collect/Range.java b/guava/src/com/google/common/collect/Range.java
index bb81d7e..f967633 100644
--- a/guava/src/com/google/common/collect/Range.java
+++ b/guava/src/com/google/common/collect/Range.java
@@ -104,7 +104,7 @@ import javax.annotation.Nullable;
  * <h3>Further reading</h3>
  *
  * <p>See the Guava User Guide article on
- * <a href="http://code.google.com/p/guava-libraries/wiki/RangesExplained">{@code Range}</a>.
+ * <a href="https://github.com/google/guava/wiki/RangesExplained">{@code Range}</a>.
  *
  * @author Kevin Bourrillion
  * @author Gregory Kick
@@ -114,42 +114,35 @@ import javax.annotation.Nullable;
 @SuppressWarnings("rawtypes")
 public final class Range<C extends Comparable> implements Predicate<C>, Serializable {
 
-  private static final Function<Range, Cut> LOWER_BOUND_FN = new Function<Range, Cut>() {
-    @Override
-    public Cut apply(Range range) {
-      return range.lowerBound;
-    }
-  };
+  private static final Function<Range, Cut> LOWER_BOUND_FN =
+      new Function<Range, Cut>() {
+        @Override
+        public Cut apply(Range range) {
+          return range.lowerBound;
+        }
+      };
 
   @SuppressWarnings("unchecked")
   static <C extends Comparable<?>> Function<Range<C>, Cut<C>> lowerBoundFn() {
     return (Function) LOWER_BOUND_FN;
   }
 
-  private static final Function<Range, Cut> UPPER_BOUND_FN = new Function<Range, Cut>() {
-    @Override
-    public Cut apply(Range range) {
-      return range.upperBound;
-    }
-  };
+  private static final Function<Range, Cut> UPPER_BOUND_FN =
+      new Function<Range, Cut>() {
+        @Override
+        public Cut apply(Range range) {
+          return range.upperBound;
+        }
+      };
 
   @SuppressWarnings("unchecked")
   static <C extends Comparable<?>> Function<Range<C>, Cut<C>> upperBoundFn() {
     return (Function) UPPER_BOUND_FN;
   }
 
-  static final Ordering<Range<?>> RANGE_LEX_ORDERING = new Ordering<Range<?>>() {
-    @Override
-    public int compare(Range<?> left, Range<?> right) {
-      return ComparisonChain.start()
-          .compare(left.lowerBound, right.lowerBound)
-          .compare(left.upperBound, right.upperBound)
-          .result();
-    }
-  };
+  static final Ordering<Range<?>> RANGE_LEX_ORDERING = new RangeLexOrdering();
 
-  static <C extends Comparable<?>> Range<C> create(
-      Cut<C> lowerBound, Cut<C> upperBound) {
+  static <C extends Comparable<?>> Range<C> create(Cut<C> lowerBound, Cut<C> upperBound) {
     return new Range<C>(lowerBound, upperBound);
   }
 
@@ -185,8 +178,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    *     upper}
    * @since 14.0
    */
-  public static <C extends Comparable<?>> Range<C> closedOpen(
-      C lower, C upper) {
+  public static <C extends Comparable<?>> Range<C> closedOpen(C lower, C upper) {
     return create(Cut.belowValue(lower), Cut.belowValue(upper));
   }
 
@@ -198,8 +190,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    *     upper}
    * @since 14.0
    */
-  public static <C extends Comparable<?>> Range<C> openClosed(
-      C lower, C upper) {
+  public static <C extends Comparable<?>> Range<C> openClosed(C lower, C upper) {
     return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
   }
 
@@ -217,12 +208,10 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
     checkNotNull(lowerType);
     checkNotNull(upperType);
 
-    Cut<C> lowerBound = (lowerType == BoundType.OPEN)
-        ? Cut.aboveValue(lower)
-        : Cut.belowValue(lower);
-    Cut<C> upperBound = (upperType == BoundType.OPEN)
-        ? Cut.belowValue(upper)
-        : Cut.aboveValue(upper);
+    Cut<C> lowerBound =
+        (lowerType == BoundType.OPEN) ? Cut.aboveValue(lower) : Cut.belowValue(lower);
+    Cut<C> upperBound =
+        (upperType == BoundType.OPEN) ? Cut.belowValue(upper) : Cut.aboveValue(upper);
     return create(lowerBound, upperBound);
   }
 
@@ -252,8 +241,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    *
    * @since 14.0
    */
-  public static <C extends Comparable<?>> Range<C> upTo(
-      C endpoint, BoundType boundType) {
+  public static <C extends Comparable<?>> Range<C> upTo(C endpoint, BoundType boundType) {
     switch (boundType) {
       case OPEN:
         return lessThan(endpoint);
@@ -290,8 +278,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    *
    * @since 14.0
    */
-  public static <C extends Comparable<?>> Range<C> downTo(
-      C endpoint, BoundType boundType) {
+  public static <C extends Comparable<?>> Range<C> downTo(C endpoint, BoundType boundType) {
     switch (boundType) {
       case OPEN:
         return greaterThan(endpoint);
@@ -326,7 +313,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
     return closed(value, value);
   }
 
-   /**
+  /**
    * Returns the minimal range that
    * {@linkplain Range#contains(Comparable) contains} all of the given values.
    * The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
@@ -337,8 +324,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    * @throws NullPointerException if any of {@code values} is null
    * @since 14.0
    */
-  public static <C extends Comparable<?>> Range<C> encloseAll(
-      Iterable<C> values) {
+  public static <C extends Comparable<?>> Range<C> encloseAll(Iterable<C> values) {
     checkNotNull(values);
     if (values instanceof ContiguousSet) {
       return ((ContiguousSet<C>) values).range();
@@ -358,12 +344,13 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
   final Cut<C> upperBound;
 
   private Range(Cut<C> lowerBound, Cut<C> upperBound) {
-    if (lowerBound.compareTo(upperBound) > 0 || lowerBound == Cut.<C>aboveAll()
+    this.lowerBound = checkNotNull(lowerBound);
+    this.upperBound = checkNotNull(upperBound);
+    if (lowerBound.compareTo(upperBound) > 0
+        || lowerBound == Cut.<C>aboveAll()
         || upperBound == Cut.<C>belowAll()) {
       throw new IllegalArgumentException("Invalid range: " + toString(lowerBound, upperBound));
     }
-    this.lowerBound = checkNotNull(lowerBound);
-    this.upperBound = checkNotNull(upperBound);
   }
 
   /**
@@ -633,17 +620,18 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    * Similarly, empty ranges are not equal unless they have exactly the same representation, so
    * {@code [3..3)}, {@code (3..3]}, {@code (4..4]} are all unequal.
    */
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object instanceof Range) {
       Range<?> other = (Range<?>) object;
-      return lowerBound.equals(other.lowerBound)
-          && upperBound.equals(other.upperBound);
+      return lowerBound.equals(other.lowerBound) && upperBound.equals(other.upperBound);
     }
     return false;
   }
 
   /** Returns a hash code for this range. */
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return lowerBound.hashCode() * 31 + upperBound.hashCode();
   }
 
@@ -651,7 +639,8 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
    * Returns a string representation of this range, such as {@code "[3..5)"} (other examples are
    * listed in the class documentation).
    */
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return toString(lowerBound, upperBound);
   }
 
@@ -683,5 +672,21 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
     return left.compareTo(right);
   }
 
+  /**
+   * Needed to serialize sorted collections of Ranges.
+   */
+  private static class RangeLexOrdering extends Ordering<Range<?>> implements Serializable {
+
+    @Override
+    public int compare(Range<?> left, Range<?> right) {
+      return ComparisonChain.start()
+          .compare(left.lowerBound, right.lowerBound)
+          .compare(left.upperBound, right.upperBound)
+          .result();
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
   private static final long serialVersionUID = 0;
 }
diff --git a/guava/src/com/google/common/collect/RangeMap.java b/guava/src/com/google/common/collect/RangeMap.java
index ba42985..ce41e6d 100644
--- a/guava/src/com/google/common/collect/RangeMap.java
+++ b/guava/src/com/google/common/collect/RangeMap.java
@@ -93,23 +93,39 @@ public interface RangeMap<K extends Comparable, V> {
    * Returns a view of this range map as an unmodifiable {@code Map<Range<K>, V>}.
    * Modifications to this range map are guaranteed to read through to the returned {@code Map}.
    *
+   * <p>The returned {@code Map} iterates over entries in ascending order of the bounds of the
+   * {@code Range} entries.
+   *
    * <p>It is guaranteed that no empty ranges will be in the returned {@code Map}.
    */
   Map<Range<K>, V> asMapOfRanges();
-  
+
+  /**
+   * Returns a view of this range map as an unmodifiable {@code Map<Range<K>, V>}.
+   * Modifications to this range map are guaranteed to read through to the returned {@code Map}.
+   *
+   * <p>The returned {@code Map} iterates over entries in descending order of the bounds of the
+   * {@code Range} entries.
+   *
+   * <p>It is guaranteed that no empty ranges will be in the returned {@code Map}.
+   *
+   * @since 19.0
+   */
+  Map<Range<K>, V> asDescendingMapOfRanges();
+
   /**
    * Returns a view of the part of this range map that intersects with {@code range}.
-   * 
-   * <p>For example, if {@code rangeMap} had the entries 
+   *
+   * <p>For example, if {@code rangeMap} had the entries
    * {@code [1, 5] => "foo", (6, 8) => "bar", (10, \u2025) => "baz"}
    * then {@code rangeMap.subRangeMap(Range.open(3, 12))} would return a range map
    * with the entries {@code (3, 5) => "foo", (6, 8) => "bar", (10, 12) => "baz"}.
-   * 
+   *
    * <p>The returned range map supports all optional operations that this range map supports,
    * except for {@code asMapOfRanges().iterator().remove()}.
-   * 
-   * <p>The returned range map will throw an {@link IllegalArgumentException} on an attempt to 
-   * insert a range not {@linkplain Range#encloses(Range) enclosed} by {@code range}. 
+   *
+   * <p>The returned range map will throw an {@link IllegalArgumentException} on an attempt to
+   * insert a range not {@linkplain Range#encloses(Range) enclosed} by {@code range}.
    */
   RangeMap<K, V> subRangeMap(Range<K> range);
 
diff --git a/guava/src/com/google/common/collect/RangeSet.java b/guava/src/com/google/common/collect/RangeSet.java
index 910597f..4d2523e 100644
--- a/guava/src/com/google/common/collect/RangeSet.java
+++ b/guava/src/com/google/common/collect/RangeSet.java
@@ -46,7 +46,7 @@ import javax.annotation.Nullable;
  */
 @Beta
 public interface RangeSet<C extends Comparable> {
-  
+
   // Query methods
 
   /**
@@ -91,7 +91,7 @@ public interface RangeSet<C extends Comparable> {
   Range<C> span();
 
   // Views
-  
+
   /**
    * Returns a view of the {@linkplain Range#isConnected disconnected} ranges that make up this
    * range set.  The returned set may be empty. The iterators returned by its
@@ -101,13 +101,23 @@ public interface RangeSet<C extends Comparable> {
   Set<Range<C>> asRanges();
 
   /**
+   * Returns a descending view of the {@linkplain Range#isConnected disconnected} ranges that
+   * make up this range set. The returned set may be empty. The iterators returned by its
+   * {@link Iterable#iterator} method return the ranges in decreasing order of lower bound
+   * (equivalently, of upper bound).
+   *
+   * @since 19.0
+   */
+  Set<Range<C>> asDescendingSetOfRanges();
+
+  /**
    * Returns a view of the complement of this {@code RangeSet}.
    *
    * <p>The returned view supports the {@link #add} operation if this {@code RangeSet} supports
    * {@link #remove}, and vice versa.
    */
   RangeSet<C> complement();
-  
+
   /**
    * Returns a view of the intersection of this {@code RangeSet} with the specified range.
    *
@@ -117,7 +127,7 @@ public interface RangeSet<C extends Comparable> {
    * {@code view}.
    */
   RangeSet<C> subRangeSet(Range<C> view);
-  
+
   // Modification
 
   /**
@@ -144,13 +154,13 @@ public interface RangeSet<C extends Comparable> {
    *         operation
    */
   void remove(Range<C> range);
-  
+
   /**
    * Removes all ranges from this {@code RangeSet} (optional operation).  After this operation,
    * {@code this.contains(c)} will return false for all {@code c}.
-   * 
+   *
    * <p>This is equivalent to {@code remove(Range.all())}.
-   * 
+   *
    * @throws UnsupportedOperationException if this range set does not support the {@code clear}
    *         operation
    */
@@ -180,7 +190,7 @@ public interface RangeSet<C extends Comparable> {
    *         operation
    */
   void removeAll(RangeSet<C> other);
-  
+
   // Object methods
 
   /**
@@ -189,7 +199,7 @@ public interface RangeSet<C extends Comparable> {
    */
   @Override
   boolean equals(@Nullable Object obj);
-  
+
   /**
    * Returns {@code asRanges().hashCode()}.
    */
diff --git a/guava/src/com/google/common/collect/RegularContiguousSet.java b/guava/src/com/google/common/collect/RegularContiguousSet.java
index 94b72a0..428377f 100644
--- a/guava/src/com/google/common/collect/RegularContiguousSet.java
+++ b/guava/src/com/google/common/collect/RegularContiguousSet.java
@@ -47,31 +47,37 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
         : new EmptyContiguousSet<C>(domain);
   }
 
-  @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
     return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
   }
 
-  @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
-      boolean toInclusive) {
+  @Override
+  ContiguousSet<C> subSetImpl(
+      C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
     if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
       // Range would reject our attempt to create (x, x).
       return new EmptyContiguousSet<C>(domain);
     }
-    return intersectionInCurrentDomain(Range.range(
-        fromElement, BoundType.forBoolean(fromInclusive),
-        toElement, BoundType.forBoolean(toInclusive)));
+    return intersectionInCurrentDomain(
+        Range.range(
+            fromElement, BoundType.forBoolean(fromInclusive),
+            toElement, BoundType.forBoolean(toInclusive)));
   }
 
-  @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
+  @Override
+  ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
     return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
   }
 
   @GwtIncompatible("not used by GWT emulation")
-  @Override int indexOf(Object target) {
+  @Override
+  int indexOf(Object target) {
     return contains(target) ? (int) domain.distance(first(), (C) target) : -1;
   }
 
-  @Override public UnmodifiableIterator<C> iterator() {
+  @Override
+  public UnmodifiableIterator<C> iterator() {
     return new AbstractSequentialIterator<C>(first()) {
       final C last = last();
 
@@ -83,7 +89,8 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
   }
 
   @GwtIncompatible("NavigableSet")
-  @Override public UnmodifiableIterator<C> descendingIterator() {
+  @Override
+  public UnmodifiableIterator<C> descendingIterator() {
     return new AbstractSequentialIterator<C>(last()) {
       final C first = first();
 
@@ -98,24 +105,29 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     return right != null && Range.compareOrThrow(left, right) == 0;
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
-  @Override public C first() {
+  @Override
+  public C first() {
     return range.lowerBound.leastValueAbove(domain);
   }
 
-  @Override public C last() {
+  @Override
+  public C last() {
     return range.upperBound.greatestValueBelow(domain);
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     long distance = domain.distance(first(), last());
     return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
   }
 
-  @Override public boolean contains(@Nullable Object object) {
+  @Override
+  public boolean contains(@Nullable Object object) {
     if (object == null) {
       return false;
     }
@@ -126,15 +138,18 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     }
   }
 
-  @Override public boolean containsAll(Collection<?> targets) {
+  @Override
+  public boolean containsAll(Collection<?> targets) {
     return Collections2.containsAllImpl(this, targets);
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return false;
   }
 
-  @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+  @Override
+  public ContiguousSet<C> intersection(ContiguousSet<C> other) {
     checkNotNull(other);
     checkArgument(this.domain.equals(other.domain));
     if (other.isEmpty()) {
@@ -148,30 +163,34 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
     }
   }
 
-  @Override public Range<C> range() {
+  @Override
+  public Range<C> range() {
     return range(CLOSED, CLOSED);
   }
 
-  @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
-    return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
+  @Override
+  public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+    return Range.create(
+        range.lowerBound.withLowerBoundType(lowerBoundType, domain),
         range.upperBound.withUpperBoundType(upperBoundType, domain));
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     } else if (object instanceof RegularContiguousSet) {
       RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
       if (this.domain.equals(that.domain)) {
-        return this.first().equals(that.first())
-            && this.last().equals(that.last());
+        return this.first().equals(that.first()) && this.last().equals(that.last());
       }
     }
     return super.equals(object);
   }
 
   // copied to make sure not to use the GWT-emulated version
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return Sets.hashCodeImpl(this);
   }
 
@@ -191,7 +210,8 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
   }
 
   @GwtIncompatible("serialization")
-  @Override Object writeReplace() {
+  @Override
+  Object writeReplace() {
     return new SerializedForm<C>(range, domain);
   }
 
diff --git a/guava/src/com/google/common/collect/RegularImmutableAsList.java b/guava/src/com/google/common/collect/RegularImmutableAsList.java
index 041d53d..49c4c4d 100644
--- a/guava/src/com/google/common/collect/RegularImmutableAsList.java
+++ b/guava/src/com/google/common/collect/RegularImmutableAsList.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
 
 /**
  * An {@link ImmutableAsList} implementation specialized for when the delegate collection is
@@ -28,7 +29,7 @@ import com.google.common.annotations.GwtIncompatible;
 @GwtCompatible(emulated = true)
 @SuppressWarnings("serial") // uses writeReplace, not default serialization
 class RegularImmutableAsList<E> extends ImmutableAsList<E> {
-  private final ImmutableCollection<E> delegate;
+  @Weak private final ImmutableCollection<E> delegate;
   private final ImmutableList<? extends E> delegateList;
 
   RegularImmutableAsList(ImmutableCollection<E> delegate, ImmutableList<? extends E> delegateList) {
@@ -49,7 +50,7 @@ class RegularImmutableAsList<E> extends ImmutableAsList<E> {
     return delegateList;
   }
 
-  @SuppressWarnings("unchecked")  // safe covariant cast!
+  @SuppressWarnings("unchecked") // safe covariant cast!
   @Override
   public UnmodifiableListIterator<E> listIterator(int index) {
     return (UnmodifiableListIterator<E>) delegateList.listIterator(index);
diff --git a/guava/src/com/google/common/collect/RegularImmutableBiMap.java b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
index fe8d1d2..b405c91 100644
--- a/guava/src/com/google/common/collect/RegularImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
@@ -16,102 +16,60 @@
 
 package com.google.common.collect;
 
+import static com.google.common.base.Preconditions.checkPositionIndex;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import static com.google.common.collect.ImmutableMapEntry.createEntryArray;
+import static com.google.common.collect.RegularImmutableMap.checkNoConflictInKeyBucket;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.common.collect.ImmutableMapEntry.NonTerminalImmutableBiMapEntry;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 
 import javax.annotation.Nullable;
 
 /**
- * Bimap with two or more mappings.
+ * Bimap with zero or more mappings.
  *
  * @author Louis Wasserman
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
 class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
-  
+  static final RegularImmutableBiMap<Object, Object> EMPTY =
+      new RegularImmutableBiMap<Object, Object>(
+          null, null, (Entry<Object, Object>[]) ImmutableMap.EMPTY_ENTRY_ARRAY, 0, 0);
+
   static final double MAX_LOAD_FACTOR = 1.2;
-  
+
   private final transient ImmutableMapEntry<K, V>[] keyTable;
   private final transient ImmutableMapEntry<K, V>[] valueTable;
-  private final transient ImmutableMapEntry<K, V>[] entries;
+  private final transient Entry<K, V>[] entries;
   private final transient int mask;
   private final transient int hashCode;
-  
-  RegularImmutableBiMap(TerminalEntry<?, ?>... entriesToAdd) {
-    this(entriesToAdd.length, entriesToAdd);
+
+  static <K, V> RegularImmutableBiMap<K, V> fromEntries(Entry<K, V>... entries) {
+    return fromEntryArray(entries.length, entries);
   }
-  
-  /**
-   * Constructor for RegularImmutableBiMap that takes as input an array of {@code TerminalEntry}
-   * entries.  Assumes that these entries have already been checked for null.
-   * 
-   * <p>This allows reuse of the entry objects from the array in the actual implementation.
-   */
-  RegularImmutableBiMap(int n, TerminalEntry<?, ?>[] entriesToAdd) {
+
+  static <K, V> RegularImmutableBiMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) {
+    checkPositionIndex(n, entryArray.length);
     int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
-    this.mask = tableSize - 1;
+    int mask = tableSize - 1;
     ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize);
     ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize);
-    ImmutableMapEntry<K, V>[] entries = createEntryArray(n);
-    int hashCode = 0;
-    
-    for (int i = 0; i < n; i++) {
-      @SuppressWarnings("unchecked")
-      TerminalEntry<K, V> entry = (TerminalEntry<K, V>) entriesToAdd[i];
-      K key = entry.getKey();
-      V value = entry.getValue();
-      
-      int keyHash = key.hashCode();
-      int valueHash = value.hashCode();
-      int keyBucket = Hashing.smear(keyHash) & mask;
-      int valueBucket = Hashing.smear(valueHash) & mask;
-      
-      ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket];
-      for (ImmutableMapEntry<K, V> keyEntry = nextInKeyBucket; keyEntry != null;
-           keyEntry = keyEntry.getNextInKeyBucket()) {
-        checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry);
-      }
-      ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket];
-      for (ImmutableMapEntry<K, V> valueEntry = nextInValueBucket; valueEntry != null;
-           valueEntry = valueEntry.getNextInValueBucket()) {
-        checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry);
-      }
-      ImmutableMapEntry<K, V> newEntry =
-          (nextInKeyBucket == null && nextInValueBucket == null)
-          ? entry
-          : new NonTerminalBiMapEntry<K, V>(entry, nextInKeyBucket, nextInValueBucket);
-      keyTable[keyBucket] = newEntry;
-      valueTable[valueBucket] = newEntry;
-      entries[i] = newEntry;
-      hashCode += keyHash ^ valueHash;
+    Entry<K, V>[] entries;
+    if (n == entryArray.length) {
+      entries = entryArray;
+    } else {
+      entries = createEntryArray(n);
     }
-    
-    this.keyTable = keyTable;
-    this.valueTable = valueTable;
-    this.entries = entries;
-    this.hashCode = hashCode;
-  }
-  
-  /**
-   * Constructor for RegularImmutableBiMap that makes no assumptions about the input entries.
-   */
-  RegularImmutableBiMap(Entry<?, ?>[] entriesToAdd) {
-    int n = entriesToAdd.length;
-    int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
-    this.mask = tableSize - 1;
-    ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize);
-    ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize);
-    ImmutableMapEntry<K, V>[] entries = createEntryArray(n);
     int hashCode = 0;
-    
+
     for (int i = 0; i < n; i++) {
       @SuppressWarnings("unchecked")
-      Entry<K, V> entry = (Entry<K, V>) entriesToAdd[i];
+      Entry<K, V> entry = entryArray[i];
       K key = entry.getKey();
       V value = entry.getValue();
       checkEntryNotNull(key, value);
@@ -119,114 +77,79 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
       int valueHash = value.hashCode();
       int keyBucket = Hashing.smear(keyHash) & mask;
       int valueBucket = Hashing.smear(valueHash) & mask;
-      
+
       ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket];
-      for (ImmutableMapEntry<K, V> keyEntry = nextInKeyBucket; keyEntry != null;
-           keyEntry = keyEntry.getNextInKeyBucket()) {
-        checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry);
-      }
+      checkNoConflictInKeyBucket(key, entry, nextInKeyBucket);
       ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket];
-      for (ImmutableMapEntry<K, V> valueEntry = nextInValueBucket; valueEntry != null;
-           valueEntry = valueEntry.getNextInValueBucket()) {
-        checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry);
+      checkNoConflictInValueBucket(value, entry, nextInValueBucket);
+      ImmutableMapEntry<K, V> newEntry;
+      if (nextInValueBucket == null && nextInKeyBucket == null) {
+        /*
+         * TODO(lowasser): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is
+         * nonnull but nextInValueBucket is null.  This may save a few bytes on some platforms, but
+         * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require
+         * benchmarking.
+         */
+        boolean reusable =
+            entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable();
+        newEntry = reusable
+            ? (ImmutableMapEntry<K, V>) entry
+            : new ImmutableMapEntry<K, V>(key, value);
+      } else {
+        newEntry = new NonTerminalImmutableBiMapEntry<K, V>(
+            key, value, nextInKeyBucket, nextInValueBucket);
       }
-      ImmutableMapEntry<K, V> newEntry =
-          (nextInKeyBucket == null && nextInValueBucket == null)
-          ? new TerminalEntry<K, V>(key, value)
-          : new NonTerminalBiMapEntry<K, V>(key, value, nextInKeyBucket, nextInValueBucket);
       keyTable[keyBucket] = newEntry;
       valueTable[valueBucket] = newEntry;
       entries[i] = newEntry;
       hashCode += keyHash ^ valueHash;
     }
-    
+    return new RegularImmutableBiMap<K, V>(keyTable, valueTable, entries, mask, hashCode);
+  }
+
+  private RegularImmutableBiMap(
+      ImmutableMapEntry<K, V>[] keyTable,
+      ImmutableMapEntry<K, V>[] valueTable,
+      Entry<K, V>[] entries,
+      int mask,
+      int hashCode) {
     this.keyTable = keyTable;
     this.valueTable = valueTable;
     this.entries = entries;
+    this.mask = mask;
     this.hashCode = hashCode;
   }
-  
-  private static final class NonTerminalBiMapEntry<K, V> extends ImmutableMapEntry<K, V> {
-    @Nullable private final ImmutableMapEntry<K, V> nextInKeyBucket;
-    @Nullable private final ImmutableMapEntry<K, V> nextInValueBucket;
-    
-    NonTerminalBiMapEntry(K key, V value, @Nullable ImmutableMapEntry<K, V> nextInKeyBucket,
-        @Nullable ImmutableMapEntry<K, V> nextInValueBucket) {
-      super(key, value);
-      this.nextInKeyBucket = nextInKeyBucket;
-      this.nextInValueBucket = nextInValueBucket;
-    }
 
-    NonTerminalBiMapEntry(ImmutableMapEntry<K, V> contents,
-        @Nullable ImmutableMapEntry<K, V> nextInKeyBucket,
-        @Nullable ImmutableMapEntry<K, V> nextInValueBucket) {
-      super(contents);
-      this.nextInKeyBucket = nextInKeyBucket;
-      this.nextInValueBucket = nextInValueBucket;
-    }
+  // checkNoConflictInKeyBucket is static imported from RegularImmutableMap
 
-    @Override
-    @Nullable
-    ImmutableMapEntry<K, V> getNextInKeyBucket() {
-      return nextInKeyBucket;
+  private static void checkNoConflictInValueBucket(
+      Object value, Entry<?, ?> entry, @Nullable ImmutableMapEntry<?, ?> valueBucketHead) {
+    for (; valueBucketHead != null; valueBucketHead = valueBucketHead.getNextInValueBucket()) {
+      checkNoConflict(!value.equals(valueBucketHead.getValue()), "value", entry, valueBucketHead);
     }
-
-    @Override
-    @Nullable
-    ImmutableMapEntry<K, V> getNextInValueBucket() {
-      return nextInValueBucket;
-    }
-  }
-  
-  @SuppressWarnings("unchecked")
-  private static <K, V> ImmutableMapEntry<K, V>[] createEntryArray(int length) {
-    return new ImmutableMapEntry[length];
   }
 
   @Override
   @Nullable
   public V get(@Nullable Object key) {
-    if (key == null) {
-      return null;
-    }
-    int bucket = Hashing.smear(key.hashCode()) & mask;
-    for (ImmutableMapEntry<K, V> entry = keyTable[bucket]; entry != null;
-         entry = entry.getNextInKeyBucket()) {
-      if (key.equals(entry.getKey())) {
-        return entry.getValue();
-      }
-    }
-    return null;
+    return (keyTable == null) ? null : RegularImmutableMap.get(key, keyTable, mask);
   }
 
   @Override
   ImmutableSet<Entry<K, V>> createEntrySet() {
-    return new ImmutableMapEntrySet<K, V>() {
-      @Override
-      ImmutableMap<K, V> map() {
-        return RegularImmutableBiMap.this;
-      }
-
-      @Override
-      public UnmodifiableIterator<Entry<K, V>> iterator() {
-        return asList().iterator();
-      }
-
-      @Override
-      ImmutableList<Entry<K, V>> createAsList() {
-        return new RegularImmutableAsList<Entry<K, V>>(this, entries);
-      }
+    return isEmpty()
+        ? ImmutableSet.<Entry<K, V>>of()
+        : new ImmutableMapEntrySet.RegularEntrySet<K, V>(this, entries);
+  }
 
-      @Override
-      boolean isHashCodeFast() {
-        return true;
-      }
+  @Override
+  boolean isHashCodeFast() {
+    return true;
+  }
 
-      @Override
-      public int hashCode() {
-        return hashCode;
-      }
-    };
+  @Override
+  public int hashCode() {
+    return hashCode;
   }
 
   @Override
@@ -238,15 +161,18 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
   public int size() {
     return entries.length;
   }
-  
+
   private transient ImmutableBiMap<V, K> inverse;
 
   @Override
   public ImmutableBiMap<V, K> inverse() {
+    if (isEmpty()) {
+      return ImmutableBiMap.of();
+    }
     ImmutableBiMap<V, K> result = inverse;
     return (result == null) ? inverse = new Inverse() : result;
   }
-  
+
   private final class Inverse extends ImmutableBiMap<V, K> {
 
     @Override
@@ -261,12 +187,13 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
 
     @Override
     public K get(@Nullable Object value) {
-      if (value == null) {
+      if (value == null || valueTable == null) {
         return null;
       }
       int bucket = Hashing.smear(value.hashCode()) & mask;
-      for (ImmutableMapEntry<K, V> entry = valueTable[bucket]; entry != null;
-           entry = entry.getNextInValueBucket()) {
+      for (ImmutableMapEntry<K, V> entry = valueTable[bucket];
+          entry != null;
+          entry = entry.getNextInValueBucket()) {
         if (value.equals(entry.getValue())) {
           return entry.getKey();
         }
@@ -278,7 +205,8 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
     ImmutableSet<Entry<V, K>> createEntrySet() {
       return new InverseEntrySet();
     }
-    
+
+    @WeakOuter
     final class InverseEntrySet extends ImmutableMapEntrySet<V, K> {
       @Override
       ImmutableMap<V, K> map() {
@@ -321,24 +249,24 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
     boolean isPartialView() {
       return false;
     }
-    
+
     @Override
     Object writeReplace() {
       return new InverseSerializedForm<K, V>(RegularImmutableBiMap.this);
     }
   }
-  
+
   private static class InverseSerializedForm<K, V> implements Serializable {
     private final ImmutableBiMap<K, V> forward;
-    
+
     InverseSerializedForm(ImmutableBiMap<K, V> forward) {
       this.forward = forward;
     }
-    
+
     Object readResolve() {
       return forward.inverse();
     }
-    
+
     private static final long serialVersionUID = 1;
   }
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableList.java b/guava/src/com/google/common/collect/RegularImmutableList.java
index c06d7b7..9436f09 100644
--- a/guava/src/com/google/common/collect/RegularImmutableList.java
+++ b/guava/src/com/google/common/collect/RegularImmutableList.java
@@ -19,16 +19,17 @@ package com.google.common.collect;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Preconditions;
 
-import javax.annotation.Nullable;
-
 /**
- * Implementation of {@link ImmutableList} with one or more elements.
+ * Implementation of {@link ImmutableList} used for 0 or 2+ elements (not 1).
  *
  * @author Kevin Bourrillion
  */
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
 class RegularImmutableList<E> extends ImmutableList<E> {
+  static final ImmutableList<Object> EMPTY =
+      new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
+
   private final transient int offset;
   private final transient int size;
   private final transient Object[] array;
@@ -48,7 +49,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
     return size;
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return size != array.length;
   }
 
@@ -67,35 +69,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
   }
 
   @Override
-  public int indexOf(@Nullable Object object) {
-    if (object == null) {
-      return -1;
-    }
-    for (int i = 0; i < size; i++) {
-      if (array[offset + i].equals(object)) {
-        return i;
-      }
-    }
-    return -1;
-  }
-
-  @Override
-  public int lastIndexOf(@Nullable Object object) {
-    if (object == null) {
-      return -1;
-    }
-    for (int i = size - 1; i >= 0; i--) {
-      if (array[offset + i].equals(object)) {
-        return i;
-      }
-    }
-    return -1;
-  }
-
-  @Override
   ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
-    return new RegularImmutableList<E>(
-        array, offset + fromIndex, toIndex - fromIndex);
+    return new RegularImmutableList<E>(array, offset + fromIndex, toIndex - fromIndex);
   }
 
   @SuppressWarnings("unchecked")
@@ -103,9 +78,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
   public UnmodifiableListIterator<E> listIterator(int index) {
     // for performance
     // The fake cast to E is safe because the creation methods only allow E's
-    return (UnmodifiableListIterator<E>)
-        Iterators.forArray(array, offset, size, index);
+    return (UnmodifiableListIterator<E>) Iterators.forArray(array, offset, size, index);
   }
 
-  // TODO(user): benchmark optimizations for equals() and see if they're worthwhile
+  // TODO(lowasser): benchmark optimizations for equals() and see if they're worthwhile
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableMap.java b/guava/src/com/google/common/collect/RegularImmutableMap.java
index b594be9..4c2cdfa 100644
--- a/guava/src/com/google/common/collect/RegularImmutableMap.java
+++ b/guava/src/com/google/common/collect/RegularImmutableMap.java
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2008 The Guava Authors
+ * 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.
@@ -16,10 +16,12 @@
 
 package com.google.common.collect;
 
+import static com.google.common.base.Preconditions.checkPositionIndex;
 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import static com.google.common.collect.ImmutableMapEntry.createEntryArray;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.common.collect.ImmutableMapEntry.NonTerminalImmutableMapEntry;
 
 import javax.annotation.Nullable;
 
@@ -34,101 +36,67 @@ import javax.annotation.Nullable;
 final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
 
   // entries in insertion order
-  private final transient ImmutableMapEntry<K, V>[] entries;
+  private final transient Entry<K, V>[] entries;
   // array of linked lists of entries
   private final transient ImmutableMapEntry<K, V>[] table;
   // 'and' with an int to get a table index
   private final transient int mask;
-  
-  RegularImmutableMap(TerminalEntry<?, ?>... theEntries) {
-    this(theEntries.length, theEntries);
+
+  static <K, V> RegularImmutableMap<K, V> fromEntries(Entry<K, V>... entries) {
+    return fromEntryArray(entries.length, entries);
   }
-  
+
   /**
-   * Constructor for RegularImmutableMap that takes as input an array of {@code TerminalEntry}
-   * entries.  Assumes that these entries have already been checked for null.
-   * 
-   * <p>This allows reuse of the entry objects from the array in the actual implementation.
+   * Creates a RegularImmutableMap from the first n entries in entryArray.  This implementation
+   * may replace the entries in entryArray with its own entry objects (though they will have the
+   * same key/value contents), and may take ownership of entryArray.
    */
-  RegularImmutableMap(int size, TerminalEntry<?, ?>[] theEntries) {
-    entries = createEntryArray(size);
-    int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
-    table = createEntryArray(tableSize);
-    mask = tableSize - 1;
-    for (int entryIndex = 0; entryIndex < size; entryIndex++) {
-      @SuppressWarnings("unchecked")
-      TerminalEntry<K, V> entry = (TerminalEntry<K, V>) theEntries[entryIndex];
-      K key = entry.getKey();
-      int tableIndex = Hashing.smear(key.hashCode()) & mask;
-      @Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
-      // prepend, not append, so the entries can be immutable
-      ImmutableMapEntry<K, V> newEntry = (existing == null)
-          ? entry
-          : new NonTerminalMapEntry<K, V>(entry, existing);
-      table[tableIndex] = newEntry;
-      entries[entryIndex] = newEntry;
-      checkNoConflictInBucket(key, newEntry, existing);
+  static <K, V> RegularImmutableMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) {
+    checkPositionIndex(n, entryArray.length);
+    Entry<K, V>[] entries;
+    if (n == entryArray.length) {
+      entries = entryArray;
+    } else {
+      entries = createEntryArray(n);
     }
-  }
-  
-  /**
-   * Constructor for RegularImmutableMap that makes no assumptions about the input entries.
-   */
-  RegularImmutableMap(Entry<?, ?>[] theEntries) {
-    int size = theEntries.length;
-    entries = createEntryArray(size);
-    int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
-    table = createEntryArray(tableSize);
-    mask = tableSize - 1;
-    for (int entryIndex = 0; entryIndex < size; entryIndex++) {
-      @SuppressWarnings("unchecked") // all our callers carefully put in only Entry<K, V>s
-      Entry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];
+    int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
+    ImmutableMapEntry<K, V>[] table = createEntryArray(tableSize);
+    int mask = tableSize - 1;
+    for (int entryIndex = 0; entryIndex < n; entryIndex++) {
+      Entry<K, V> entry = entryArray[entryIndex];
       K key = entry.getKey();
       V value = entry.getValue();
       checkEntryNotNull(key, value);
       int tableIndex = Hashing.smear(key.hashCode()) & mask;
       @Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
       // prepend, not append, so the entries can be immutable
-      ImmutableMapEntry<K, V> newEntry = (existing == null)
-          ? new TerminalEntry<K, V>(key, value)
-          : new NonTerminalMapEntry<K, V>(key, value, existing);
+      ImmutableMapEntry<K, V> newEntry;
+      if (existing == null) {
+        boolean reusable =
+            entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable();
+        newEntry =
+            reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value);
+      } else {
+        newEntry = new NonTerminalImmutableMapEntry<K, V>(key, value, existing);
+      }
       table[tableIndex] = newEntry;
       entries[entryIndex] = newEntry;
-      checkNoConflictInBucket(key, newEntry, existing);
+      checkNoConflictInKeyBucket(key, newEntry, existing);
     }
+    return new RegularImmutableMap<K, V>(entries, table, mask);
   }
 
-  private void checkNoConflictInBucket(
-      K key, ImmutableMapEntry<K, V> entry, ImmutableMapEntry<K, V> bucketHead) {
-    for (; bucketHead != null; bucketHead = bucketHead.getNextInKeyBucket()) {
-      checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead);
-    }
+  private RegularImmutableMap(Entry<K, V>[] entries, ImmutableMapEntry<K, V>[] table, int mask) {
+    this.entries = entries;
+    this.table = table;
+    this.mask = mask;
   }
-  
-  private static final class NonTerminalMapEntry<K, V> extends ImmutableMapEntry<K, V> {
-    private final ImmutableMapEntry<K, V> nextInKeyBucket;
-
-    NonTerminalMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {
-      super(key, value);
-      this.nextInKeyBucket = nextInKeyBucket;
-    }
-
-    NonTerminalMapEntry(ImmutableMapEntry<K, V> contents, ImmutableMapEntry<K, V> nextInKeyBucket) {
-      super(contents);
-      this.nextInKeyBucket = nextInKeyBucket;
-    }
-
-    @Override
-    ImmutableMapEntry<K, V> getNextInKeyBucket() {
-      return nextInKeyBucket;
-    }
 
-    @Override
-    @Nullable
-    ImmutableMapEntry<K, V> getNextInValueBucket() {
-      return null;
+  static void checkNoConflictInKeyBucket(
+      Object key, Entry<?, ?> entry, @Nullable ImmutableMapEntry<?, ?> keyBucketHead) {
+    for (; keyBucketHead != null; keyBucketHead = keyBucketHead.getNextInKeyBucket()) {
+      checkNoConflict(!key.equals(keyBucketHead.getKey()), "key", entry, keyBucketHead);
     }
-    
   }
 
   /**
@@ -138,25 +106,21 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
    */
   private static final double MAX_LOAD_FACTOR = 1.2;
 
-  /**
-   * Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The
-   * result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or
-   * allowed to escape the class.
-   */
-  @SuppressWarnings("unchecked") // Safe as long as the javadocs are followed
-  private ImmutableMapEntry<K, V>[] createEntryArray(int size) {
-    return new ImmutableMapEntry[size];
+  @Override
+  public V get(@Nullable Object key) {
+    return get(key, table, mask);
   }
 
-  @Override public V get(@Nullable Object key) {
+  @Nullable
+  static <V> V get(@Nullable Object key, ImmutableMapEntry<?, V>[] keyTable, int mask) {
     if (key == null) {
       return null;
     }
     int index = Hashing.smear(key.hashCode()) & mask;
-    for (ImmutableMapEntry<K, V> entry = table[index];
+    for (ImmutableMapEntry<?, V> entry = keyTable[index];
         entry != null;
         entry = entry.getNextInKeyBucket()) {
-      K candidateKey = entry.getKey();
+      Object candidateKey = entry.getKey();
 
       /*
        * Assume that equals uses the == optimization when appropriate, and that
@@ -175,31 +139,15 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
   public int size() {
     return entries.length;
   }
-  
-  @Override boolean isPartialView() {
+
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
   @Override
   ImmutableSet<Entry<K, V>> createEntrySet() {
-    return new EntrySet();
-  }
-
-  @SuppressWarnings("serial") // uses writeReplace(), not default serialization
-  private class EntrySet extends ImmutableMapEntrySet<K, V> {
-    @Override ImmutableMap<K, V> map() {
-      return RegularImmutableMap.this;
-    }
-
-    @Override
-    public UnmodifiableIterator<Entry<K, V>> iterator() {
-      return asList().iterator();
-    }
-
-    @Override
-    ImmutableList<Entry<K, V>> createAsList() {
-      return new RegularImmutableAsList<Entry<K, V>>(this, entries);
-    }
+    return new ImmutableMapEntrySet.RegularEntrySet<K, V>(this, entries);
   }
 
   // This class is never actually serialized directly, but we have to make the
diff --git a/guava/src/com/google/common/collect/RegularImmutableMultiset.java b/guava/src/com/google/common/collect/RegularImmutableMultiset.java
index 552c774..5181f57 100644
--- a/guava/src/com/google/common/collect/RegularImmutableMultiset.java
+++ b/guava/src/com/google/common/collect/RegularImmutableMultiset.java
@@ -1,24 +1,28 @@
 /*
  * 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
+ * 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.
+ * 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 com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+import com.google.common.collect.Multisets.ImmutableEntry;
+import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
 
-import java.util.Map;
+import java.util.Collection;
 
 import javax.annotation.Nullable;
 
@@ -29,26 +33,101 @@ import javax.annotation.Nullable;
  * @author Louis Wasserman
  */
 @GwtCompatible(serializable = true)
- at SuppressWarnings("serial")
-// uses writeReplace(), not default serialization
+ at SuppressWarnings("serial") // uses writeReplace(), not default serialization
 class RegularImmutableMultiset<E> extends ImmutableMultiset<E> {
-  private final transient ImmutableMap<E, Integer> map;
+  static final RegularImmutableMultiset<Object> EMPTY =
+      new RegularImmutableMultiset<Object>(ImmutableList.<Entry<Object>>of());
+
+  private final transient Multisets.ImmutableEntry<E>[] entries;
+  private final transient Multisets.ImmutableEntry<E>[] hashTable;
   private final transient int size;
+  private final transient int hashCode;
+
+  private transient ImmutableSet<E> elementSet;
+
+  RegularImmutableMultiset(Collection<? extends Entry<? extends E>> entries) {
+    int distinct = entries.size();
+    @SuppressWarnings("unchecked")
+    Multisets.ImmutableEntry<E>[] entryArray = new Multisets.ImmutableEntry[distinct];
+    if (distinct == 0) {
+      this.entries = entryArray;
+      this.hashTable = null;
+      this.size = 0;
+      this.hashCode = 0;
+      this.elementSet = ImmutableSet.of();
+    } else {
+      int tableSize = Hashing.closedTableSize(distinct, 1.0);
+      int mask = tableSize - 1;
+      @SuppressWarnings("unchecked")
+      Multisets.ImmutableEntry<E>[] hashTable = new Multisets.ImmutableEntry[tableSize];
+
+      int index = 0;
+      int hashCode = 0;
+      long size = 0;
+      for (Entry<? extends E> entry : entries) {
+        E element = checkNotNull(entry.getElement());
+        int count = entry.getCount();
+        int hash = element.hashCode();
+        int bucket = Hashing.smear(hash) & mask;
+        Multisets.ImmutableEntry<E> bucketHead = hashTable[bucket];
+        Multisets.ImmutableEntry<E> newEntry;
+        if (bucketHead == null) {
+          boolean canReuseEntry =
+              entry instanceof Multisets.ImmutableEntry && !(entry instanceof NonTerminalEntry);
+          newEntry =
+              canReuseEntry
+                  ? (Multisets.ImmutableEntry<E>) entry
+                  : new Multisets.ImmutableEntry<E>(element, count);
+        } else {
+          newEntry = new NonTerminalEntry<E>(element, count, bucketHead);
+        }
+        hashCode += hash ^ count;
+        entryArray[index++] = newEntry;
+        hashTable[bucket] = newEntry;
+        size += count;
+      }
+      this.entries = entryArray;
+      this.hashTable = hashTable;
+      this.size = Ints.saturatedCast(size);
+      this.hashCode = hashCode;
+    }
+  }
+
+  private static final class NonTerminalEntry<E> extends Multisets.ImmutableEntry<E> {
+    private final Multisets.ImmutableEntry<E> nextInBucket;
+
+    NonTerminalEntry(E element, int count, ImmutableEntry<E> nextInBucket) {
+      super(element, count);
+      this.nextInBucket = nextInBucket;
+    }
 
-  RegularImmutableMultiset(ImmutableMap<E, Integer> map, int size) {
-    this.map = map;
-    this.size = size;
+    @Override
+    public ImmutableEntry<E> nextInBucket() {
+      return nextInBucket;
+    }
   }
 
   @Override
   boolean isPartialView() {
-    return map.isPartialView();
+    return false;
   }
 
   @Override
   public int count(@Nullable Object element) {
-    Integer value = map.get(element);
-    return (value == null) ? 0 : value;
+    Multisets.ImmutableEntry<E>[] hashTable = this.hashTable;
+    if (element == null || hashTable == null) {
+      return 0;
+    }
+    int hash = Hashing.smearedHash(element);
+    int mask = hashTable.length - 1;
+    for (Multisets.ImmutableEntry<E> entry = hashTable[hash & mask];
+        entry != null;
+        entry = entry.nextInBucket()) {
+      if (Objects.equal(element, entry.getElement())) {
+        return entry.getCount();
+      }
+    }
+    return 0;
   }
 
   @Override
@@ -57,23 +136,42 @@ class RegularImmutableMultiset<E> extends ImmutableMultiset<E> {
   }
 
   @Override
-  public boolean contains(@Nullable Object element) {
-    return map.containsKey(element);
+  public ImmutableSet<E> elementSet() {
+    ImmutableSet<E> result = elementSet;
+    return (result == null) ? elementSet = new ElementSet() : result;
   }
 
-  @Override
-  public ImmutableSet<E> elementSet() {
-    return map.keySet();
+  @WeakOuter
+  private final class ElementSet extends ImmutableSet.Indexed<E> {
+
+    @Override
+    E get(int index) {
+      return entries[index].getElement();
+    }
+
+    @Override
+    public boolean contains(@Nullable Object object) {
+      return RegularImmutableMultiset.this.contains(object);
+    }
+
+    @Override
+    boolean isPartialView() {
+      return true;
+    }
+
+    @Override
+    public int size() {
+      return entries.length;
+    }
   }
 
   @Override
   Entry<E> getEntry(int index) {
-    Map.Entry<E, Integer> mapEntry = map.entrySet().asList().get(index);
-    return Multisets.immutableEntry(mapEntry.getKey(), mapEntry.getValue());
+    return entries[index];
   }
 
   @Override
   public int hashCode() {
-    return map.hashCode();
+    return hashCode;
   }
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableSet.java b/guava/src/com/google/common/collect/RegularImmutableSet.java
index f3cbb55..9bf70d7 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSet.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSet.java
@@ -19,6 +19,8 @@ package com.google.common.collect;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.VisibleForTesting;
 
+import javax.annotation.Nullable;
+
 /**
  * Implementation of {@link ImmutableSet} with two or more elements.
  *
@@ -27,31 +29,35 @@ import com.google.common.annotations.VisibleForTesting;
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
 final class RegularImmutableSet<E> extends ImmutableSet<E> {
-  private final Object[] elements;
+  static final RegularImmutableSet<Object> EMPTY =
+      new RegularImmutableSet<Object>(ObjectArrays.EMPTY_ARRAY, 0, null, 0);
+
+  private final transient Object[] elements;
   // the same elements in hashed positions (plus nulls)
   @VisibleForTesting final transient Object[] table;
   // 'and' with an int to get a valid table index.
   private final transient int mask;
   private final transient int hashCode;
 
-  RegularImmutableSet(
-      Object[] elements, int hashCode, Object[] table, int mask) {
+  RegularImmutableSet(Object[] elements, int hashCode, Object[] table, int mask) {
     this.elements = elements;
     this.table = table;
     this.mask = mask;
     this.hashCode = hashCode;
   }
 
-  @Override public boolean contains(Object target) {
-    if (target == null) {
+  @Override
+  public boolean contains(@Nullable Object target) {
+    Object[] table = this.table;
+    if (target == null || table == null) {
       return false;
     }
-    for (int i = Hashing.smear(target.hashCode()); true; i++) {
-      Object candidate = table[i & mask];
+    for (int i = Hashing.smearedHash(target); ; i++) {
+      i &= mask;
+      Object candidate = table[i];
       if (candidate == null) {
         return false;
-      }
-      if (candidate.equals(target)) {
+      } else if (candidate.equals(target)) {
         return true;
       }
     }
@@ -76,7 +82,7 @@ final class RegularImmutableSet<E> extends ImmutableSet<E> {
 
   @Override
   ImmutableList<E> createAsList() {
-    return new RegularImmutableAsList<E>(this, elements);
+    return (table == null) ? ImmutableList.<E>of() : new RegularImmutableAsList<E>(this, elements);
   }
 
   @Override
@@ -84,11 +90,13 @@ final class RegularImmutableSet<E> extends ImmutableSet<E> {
     return false;
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return hashCode;
   }
 
-  @Override boolean isHashCodeFast() {
+  @Override
+  boolean isHashCodeFast() {
     return true;
   }
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMap.java b/guava/src/com/google/common/collect/RegularImmutableSortedMap.java
deleted file mode 100644
index dd93b7f..0000000
--- a/guava/src/com/google/common/collect/RegularImmutableSortedMap.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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 com.google.common.annotations.GwtCompatible;
-
-import javax.annotation.Nullable;
-
-/**
- * An implementation of an immutable sorted map with one or more entries.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
- at SuppressWarnings("serial") // uses writeReplace, not default serialization
-final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
-  private final transient RegularImmutableSortedSet<K> keySet;
-  private final transient ImmutableList<V> valueList;
-
-  RegularImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
-    this.keySet = keySet;
-    this.valueList = valueList;
-  }
-
-  RegularImmutableSortedMap(
-      RegularImmutableSortedSet<K> keySet,
-      ImmutableList<V> valueList,
-      ImmutableSortedMap<K, V> descendingMap) {
-    super(descendingMap);
-    this.keySet = keySet;
-    this.valueList = valueList;
-  }
-
-  @Override
-  ImmutableSet<Entry<K, V>> createEntrySet() {
-    return new EntrySet();
-  }
-
-  private class EntrySet extends ImmutableMapEntrySet<K, V> {
-    @Override
-    public UnmodifiableIterator<Entry<K, V>> iterator() {
-      return asList().iterator();
-    }
-
-    @Override
-    ImmutableList<Entry<K, V>> createAsList() {
-      return new ImmutableAsList<Entry<K, V>>() {
-        // avoid additional indirection
-        private final ImmutableList<K> keyList = keySet().asList();
-
-        @Override
-        public Entry<K, V> get(int index) {
-          return Maps.immutableEntry(keyList.get(index), valueList.get(index));
-        }
-
-        @Override
-        ImmutableCollection<Entry<K, V>> delegateCollection() {
-          return EntrySet.this;
-        }
-      };
-    }
-
-    @Override
-    ImmutableMap<K, V> map() {
-      return RegularImmutableSortedMap.this;
-    }
-  }
-
-  @Override
-  public ImmutableSortedSet<K> keySet() {
-    return keySet;
-  }
-
-  @Override
-  public ImmutableCollection<V> values() {
-    return valueList;
-  }
-
-  @Override
-  public V get(@Nullable Object key) {
-    int index = keySet.indexOf(key);
-    return (index == -1) ? null : valueList.get(index);
-  }
-
-  private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
-    if (fromIndex == 0 && toIndex == size()) {
-      return this;
-    } else if (fromIndex == toIndex) {
-      return emptyMap(comparator());
-    } else {
-      return from(
-          keySet.getSubSet(fromIndex, toIndex),
-          valueList.subList(fromIndex, toIndex));
-    }
-  }
-
-  @Override
-  public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
-    return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
-  }
-
-  @Override
-  public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
-    return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
-  }
-
-  @Override
-  ImmutableSortedMap<K, V> createDescendingMap() {
-    return new RegularImmutableSortedMap<K, V>(
-        (RegularImmutableSortedSet<K>) keySet.descendingSet(),
-        valueList.reverse(),
-        this);
-  }
-
-}
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
index 5ef3e0d..bf39c07 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
@@ -20,6 +20,8 @@ import static com.google.common.collect.BoundType.CLOSED;
 
 import com.google.common.primitives.Ints;
 
+import java.util.Comparator;
+
 import javax.annotation.Nullable;
 
 /**
@@ -29,46 +31,51 @@ import javax.annotation.Nullable;
  */
 @SuppressWarnings("serial") // uses writeReplace, not default serialization
 final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
+  private static final long[] ZERO_CUMULATIVE_COUNTS = {0};
+
   private final transient RegularImmutableSortedSet<E> elementSet;
-  private final transient int[] counts;
   private final transient long[] cumulativeCounts;
   private final transient int offset;
   private final transient int length;
 
+  RegularImmutableSortedMultiset(Comparator<? super E> comparator) {
+    this.elementSet = ImmutableSortedSet.emptySet(comparator);
+    this.cumulativeCounts = ZERO_CUMULATIVE_COUNTS;
+    this.offset = 0;
+    this.length = 0;
+  }
+
   RegularImmutableSortedMultiset(
-      RegularImmutableSortedSet<E> elementSet,
-      int[] counts,
-      long[] cumulativeCounts,
-      int offset,
-      int length) {
+      RegularImmutableSortedSet<E> elementSet, long[] cumulativeCounts, int offset, int length) {
     this.elementSet = elementSet;
-    this.counts = counts;
     this.cumulativeCounts = cumulativeCounts;
     this.offset = offset;
     this.length = length;
   }
 
+  private int getCount(int index) {
+    return (int) (cumulativeCounts[offset + index + 1] - cumulativeCounts[offset + index]);
+  }
+
   @Override
   Entry<E> getEntry(int index) {
-    return Multisets.immutableEntry(
-        elementSet.asList().get(index),
-        counts[offset + index]);
+    return Multisets.immutableEntry(elementSet.asList().get(index), getCount(index));
   }
 
   @Override
   public Entry<E> firstEntry() {
-    return getEntry(0);
+    return isEmpty() ? null : getEntry(0);
   }
 
   @Override
   public Entry<E> lastEntry() {
-    return getEntry(length - 1);
+    return isEmpty() ? null : getEntry(length - 1);
   }
 
   @Override
   public int count(@Nullable Object element) {
     int index = elementSet.indexOf(element);
-    return (index == -1) ? 0 : counts[index + offset];
+    return (index >= 0) ? getCount(index) : 0;
   }
 
   @Override
@@ -89,8 +96,8 @@ final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E>
 
   @Override
   public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
-    return getSubMultiset(elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED),
-        length);
+    return getSubMultiset(
+        elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED), length);
   }
 
   ImmutableSortedMultiset<E> getSubMultiset(int from, int to) {
@@ -103,12 +110,12 @@ final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E>
       RegularImmutableSortedSet<E> subElementSet =
           (RegularImmutableSortedSet<E>) elementSet.getSubSet(from, to);
       return new RegularImmutableSortedMultiset<E>(
-          subElementSet, counts, cumulativeCounts, offset + from, to - from);
+          subElementSet, cumulativeCounts, offset + from, to - from);
     }
   }
 
   @Override
   boolean isPartialView() {
-    return offset > 0 || length < counts.length;
+    return offset > 0 || length < cumulativeCounts.length - 1;
   }
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
index 382e338..32883b0 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
@@ -16,7 +16,6 @@
 
 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.SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX;
 import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_HIGHER;
@@ -49,32 +48,29 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
 
   private transient final ImmutableList<E> elements;
 
-  RegularImmutableSortedSet(
-      ImmutableList<E> elements, Comparator<? super E> comparator) {
+  RegularImmutableSortedSet(ImmutableList<E> elements, Comparator<? super E> comparator) {
     super(comparator);
     this.elements = elements;
-    checkArgument(!elements.isEmpty());
   }
 
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     return elements.iterator();
   }
 
   @GwtIncompatible("NavigableSet")
-  @Override public UnmodifiableIterator<E> descendingIterator() {
+  @Override
+  public UnmodifiableIterator<E> descendingIterator() {
     return elements.reverse().iterator();
   }
 
-  @Override public boolean isEmpty() {
-    return false;
-  }
-
   @Override
   public int size() {
     return elements.size();
   }
 
-  @Override public boolean contains(Object o) {
+  @Override
+  public boolean contains(@Nullable Object o) {
     try {
       return o != null && unsafeBinarySearch(o) >= 0;
     } catch (ClassCastException e) {
@@ -82,7 +78,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     }
   }
 
-  @Override public boolean containsAll(Collection<?> targets) {
+  @Override
+  public boolean containsAll(Collection<?> targets) {
     // TODO(jlevy): For optimal performance, use a binary search when
     // targets.size() < size() / log(size())
     // TODO(kevinb): see if we can share code with OrderedIterator after it
@@ -90,8 +87,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     if (targets instanceof Multiset) {
       targets = ((Multiset<?>) targets).elementSet();
     }
-    if (!SortedIterables.hasSameComparator(comparator(), targets)
-        || (targets.size() <= 1)) {
+    if (!SortedIterables.hasSameComparator(comparator(), targets) || (targets.size() <= 1)) {
       return super.containsAll(targets);
     }
 
@@ -137,7 +133,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     return Collections.binarySearch(elements, key, unsafeComparator());
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return elements.isPartialView();
   }
 
@@ -146,7 +143,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     return elements.copyIntoArray(dst, offset);
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -157,6 +155,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     Set<?> that = (Set<?>) object;
     if (size() != that.size()) {
       return false;
+    } else if (isEmpty()) {
+      return true;
     }
 
     if (SortedIterables.hasSameComparator(comparator, that)) {
@@ -166,8 +166,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
         while (iterator.hasNext()) {
           Object element = iterator.next();
           Object otherElement = otherIterator.next();
-          if (otherElement == null
-              || unsafeCompare(element, otherElement) != 0) {
+          if (otherElement == null || unsafeCompare(element, otherElement) != 0) {
             return false;
           }
         }
@@ -183,11 +182,17 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
 
   @Override
   public E first() {
+    if (isEmpty()) {
+      throw new NoSuchElementException();
+    }
     return elements.get(0);
   }
 
   @Override
   public E last() {
+    if (isEmpty()) {
+      throw new NoSuchElementException();
+    }
     return elements.get(size() - 1);
   }
 
@@ -222,15 +227,17 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
 
   int headIndex(E toElement, boolean inclusive) {
     return SortedLists.binarySearch(
-        elements, checkNotNull(toElement), comparator(),
-        inclusive ? FIRST_AFTER : FIRST_PRESENT, NEXT_HIGHER);
+        elements,
+        checkNotNull(toElement),
+        comparator(),
+        inclusive ? FIRST_AFTER : FIRST_PRESENT,
+        NEXT_HIGHER);
   }
 
   @Override
   ImmutableSortedSet<E> subSetImpl(
       E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
-    return tailSetImpl(fromElement, fromInclusive)
-        .headSetImpl(toElement, toInclusive);
+    return tailSetImpl(fromElement, fromInclusive).headSetImpl(toElement, toInclusive);
   }
 
   @Override
@@ -243,7 +250,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
         elements,
         checkNotNull(fromElement),
         comparator(),
-        inclusive ? FIRST_PRESENT : FIRST_AFTER, NEXT_HIGHER);
+        inclusive ? FIRST_PRESENT : FIRST_AFTER,
+        NEXT_HIGHER);
   }
 
   // Pretend the comparator can compare anything. If it turns out it can't
@@ -254,7 +262,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     return (Comparator<Object>) comparator;
   }
 
-  ImmutableSortedSet<E> getSubSet(int newFromIndex, int newToIndex) {
+  RegularImmutableSortedSet<E> getSubSet(int newFromIndex, int newToIndex) {
     if (newFromIndex == 0 && newToIndex == size()) {
       return this;
     } else if (newFromIndex < newToIndex) {
@@ -265,27 +273,31 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
     }
   }
 
-  @Override int indexOf(@Nullable Object target) {
+  @Override
+  int indexOf(@Nullable Object target) {
     if (target == null) {
       return -1;
     }
     int position;
     try {
-      position = SortedLists.binarySearch(elements, target, unsafeComparator(),
-          ANY_PRESENT, INVERTED_INSERTION_INDEX);
+      position = SortedLists.binarySearch(
+          elements, target, unsafeComparator(), ANY_PRESENT, INVERTED_INSERTION_INDEX);
     } catch (ClassCastException e) {
       return -1;
     }
     return (position >= 0) ? position : -1;
   }
 
-  @Override ImmutableList<E> createAsList() {
-    return new ImmutableSortedAsList<E>(this, elements);
+  @Override
+  ImmutableList<E> createAsList() {
+    return (size() <= 1) ? elements : new ImmutableSortedAsList<E>(this, elements);
   }
 
   @Override
   ImmutableSortedSet<E> createDescendingSet() {
-    return new RegularImmutableSortedSet<E>(elements.reverse(),
-        Ordering.from(comparator).reverse());
+    Ordering<E> reversedOrder = Ordering.from(comparator).reverse();
+    return isEmpty()
+        ? emptySet(reversedOrder)
+        : new RegularImmutableSortedSet<E>(elements.reverse(), reversedOrder);
   }
 }
diff --git a/guava/src/com/google/common/collect/RegularImmutableTable.java b/guava/src/com/google/common/collect/RegularImmutableTable.java
index 6bbec91..0bbbe39 100644
--- a/guava/src/com/google/common/collect/RegularImmutableTable.java
+++ b/guava/src/com/google/common/collect/RegularImmutableTable.java
@@ -17,10 +17,14 @@ package com.google.common.collect;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.Table.Cell;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -33,45 +37,31 @@ import javax.annotation.Nullable;
 @GwtCompatible
 abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
   RegularImmutableTable() {}
-  
+
   abstract Cell<R, C, V> getCell(int iterationIndex);
-  
+
   @Override
   final ImmutableSet<Cell<R, C, V>> createCellSet() {
     return isEmpty() ? ImmutableSet.<Cell<R, C, V>>of() : new CellSet();
   }
 
-  private final class CellSet extends ImmutableSet<Cell<R, C, V>> {
+  @WeakOuter
+  private final class CellSet extends ImmutableSet.Indexed<Cell<R, C, V>> {
     @Override
     public int size() {
       return RegularImmutableTable.this.size();
     }
 
     @Override
-    public UnmodifiableIterator<Cell<R, C, V>> iterator() {
-      return asList().iterator();
-    }
-
-    @Override
-    ImmutableList<Cell<R, C, V>> createAsList() {
-      return new ImmutableAsList<Cell<R, C, V>>() {
-        @Override
-        public Cell<R, C, V> get(int index) {
-          return getCell(index);
-        }
-
-        @Override
-        ImmutableCollection<Cell<R, C, V>> delegateCollection() {
-          return CellSet.this;
-        }
-      };
+    Cell<R, C, V> get(int index) {
+      return getCell(index);
     }
 
     @Override
     public boolean contains(@Nullable Object object) {
       if (object instanceof Cell) {
         Cell<?, ?, ?> cell = (Cell<?, ?, ?>) object;
-        Object value = get(cell.getRowKey(), cell.getColumnKey());
+        Object value = RegularImmutableTable.this.get(cell.getRowKey(), cell.getColumnKey());
         return value != null && value.equals(cell.getValue());
       }
       return false;
@@ -82,14 +72,15 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
       return false;
     }
   }
-  
+
   abstract V getValue(int iterationIndex);
 
   @Override
   final ImmutableCollection<V> createValues() {
     return isEmpty() ? ImmutableList.<V>of() : new Values();
   }
-  
+
+  @WeakOuter
   private final class Values extends ImmutableList<V> {
     @Override
     public int size() {
@@ -120,24 +111,28 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
        * provided but a row Comparator isn't, cellSet() iterates across the rows in the first
        * column, the rows in the second column, etc.
        */
-      Comparator<Cell<R, C, V>> comparator = new Comparator<Cell<R, C, V>>() {
-        @Override public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
-          int rowCompare = (rowComparator == null) ? 0
-            : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
-          if (rowCompare != 0) {
-            return rowCompare;
-          }
-          return (columnComparator == null) ? 0
-              : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
-        }
-      };
+      Comparator<Cell<R, C, V>> comparator =
+          new Comparator<Cell<R, C, V>>() {
+            @Override
+            public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
+              int rowCompare =
+                  (rowComparator == null)
+                      ? 0
+                      : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
+              if (rowCompare != 0) {
+                return rowCompare;
+              }
+              return (columnComparator == null)
+                  ? 0
+                  : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
+            }
+          };
       Collections.sort(cells, comparator);
     }
     return forCellsInternal(cells, rowComparator, columnComparator);
   }
 
-  static <R, C, V> RegularImmutableTable<R, C, V> forCells(
-      Iterable<Cell<R, C, V>> cells) {
+  static <R, C, V> RegularImmutableTable<R, C, V> forCells(Iterable<Cell<R, C, V>> cells) {
     return forCellsInternal(cells, null, null);
   }
 
@@ -145,35 +140,33 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
    * A factory that chooses the most space-efficient representation of the
    * table.
    */
-  private static final <R, C, V> RegularImmutableTable<R, C, V>
-      forCellsInternal(Iterable<Cell<R, C, V>> cells,
-          @Nullable Comparator<? super R> rowComparator,
-          @Nullable Comparator<? super C> columnComparator) {
-    ImmutableSet.Builder<R> rowSpaceBuilder = ImmutableSet.builder();
-    ImmutableSet.Builder<C> columnSpaceBuilder = ImmutableSet.builder();
+  private static final <R, C, V> RegularImmutableTable<R, C, V> forCellsInternal(
+      Iterable<Cell<R, C, V>> cells,
+      @Nullable Comparator<? super R> rowComparator,
+      @Nullable Comparator<? super C> columnComparator) {
+    Set<R> rowSpaceBuilder = new LinkedHashSet<R>();
+    Set<C> columnSpaceBuilder = new LinkedHashSet<C>();
     ImmutableList<Cell<R, C, V>> cellList = ImmutableList.copyOf(cells);
-    for (Cell<R, C, V> cell : cellList) {
+    for (Cell<R, C, V> cell : cells) {
       rowSpaceBuilder.add(cell.getRowKey());
       columnSpaceBuilder.add(cell.getColumnKey());
     }
 
-    ImmutableSet<R> rowSpace = rowSpaceBuilder.build();
-    if (rowComparator != null) {
-      List<R> rowList = Lists.newArrayList(rowSpace);
-      Collections.sort(rowList, rowComparator);
-      rowSpace = ImmutableSet.copyOf(rowList);
-    }
-    ImmutableSet<C> columnSpace = columnSpaceBuilder.build();
-    if (columnComparator != null) {
-      List<C> columnList = Lists.newArrayList(columnSpace);
-      Collections.sort(columnList, columnComparator);
-      columnSpace = ImmutableSet.copyOf(columnList);
-    }
+    ImmutableSet<R> rowSpace =
+        (rowComparator == null)
+            ? ImmutableSet.copyOf(rowSpaceBuilder)
+            : ImmutableSet.copyOf(
+                Ordering.from(rowComparator).immutableSortedCopy(rowSpaceBuilder));
+    ImmutableSet<C> columnSpace =
+        (columnComparator == null)
+            ? ImmutableSet.copyOf(columnSpaceBuilder)
+            : ImmutableSet.copyOf(
+                Ordering.from(columnComparator).immutableSortedCopy(columnSpaceBuilder));
 
     // use a dense table if more than half of the cells have values
     // TODO(gak): tune this condition based on empirical evidence
-    return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2)) ?
-        new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace) :
-        new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
+    return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2))
+        ? new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace)
+        : new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
   }
 }
diff --git a/guava/src/com/google/common/collect/ReverseNaturalOrdering.java b/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
index 9a73613..d94fc0c 100644
--- a/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
+++ b/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
@@ -26,11 +26,11 @@ import java.util.Iterator;
 /** An ordering that uses the reverse of the natural order of the values. */
 @GwtCompatible(serializable = true)
 @SuppressWarnings("unchecked") // TODO(kevinb): the right way to explain this??
-final class ReverseNaturalOrdering
-    extends Ordering<Comparable> implements Serializable {
+final class ReverseNaturalOrdering extends Ordering<Comparable> implements Serializable {
   static final ReverseNaturalOrdering INSTANCE = new ReverseNaturalOrdering();
 
-  @Override public int compare(Comparable left, Comparable right) {
+  @Override
+  public int compare(Comparable left, Comparable right) {
     checkNotNull(left); // right null is caught later
     if (left == right) {
       return 0;
@@ -39,41 +39,50 @@ final class ReverseNaturalOrdering
     return right.compareTo(left);
   }
 
-  @Override public <S extends Comparable> Ordering<S> reverse() {
+  @Override
+  public <S extends Comparable> Ordering<S> reverse() {
     return Ordering.natural();
   }
 
   // Override the min/max methods to "hoist" delegation outside loops
 
-  @Override public <E extends Comparable> E min(E a, E b) {
+  @Override
+  public <E extends Comparable> E min(E a, E b) {
     return NaturalOrdering.INSTANCE.max(a, b);
   }
 
-  @Override public <E extends Comparable> E min(E a, E b, E c, E... rest) {
+  @Override
+  public <E extends Comparable> E min(E a, E b, E c, E... rest) {
     return NaturalOrdering.INSTANCE.max(a, b, c, rest);
   }
 
-  @Override public <E extends Comparable> E min(Iterator<E> iterator) {
+  @Override
+  public <E extends Comparable> E min(Iterator<E> iterator) {
     return NaturalOrdering.INSTANCE.max(iterator);
   }
 
-  @Override public <E extends Comparable> E min(Iterable<E> iterable) {
+  @Override
+  public <E extends Comparable> E min(Iterable<E> iterable) {
     return NaturalOrdering.INSTANCE.max(iterable);
   }
 
-  @Override public <E extends Comparable> E max(E a, E b) {
+  @Override
+  public <E extends Comparable> E max(E a, E b) {
     return NaturalOrdering.INSTANCE.min(a, b);
   }
 
-  @Override public <E extends Comparable> E max(E a, E b, E c, E... rest) {
+  @Override
+  public <E extends Comparable> E max(E a, E b, E c, E... rest) {
     return NaturalOrdering.INSTANCE.min(a, b, c, rest);
   }
 
-  @Override public <E extends Comparable> E max(Iterator<E> iterator) {
+  @Override
+  public <E extends Comparable> E max(Iterator<E> iterator) {
     return NaturalOrdering.INSTANCE.min(iterator);
   }
 
-  @Override public <E extends Comparable> E max(Iterable<E> iterable) {
+  @Override
+  public <E extends Comparable> E max(Iterable<E> iterable) {
     return NaturalOrdering.INSTANCE.min(iterable);
   }
 
@@ -82,7 +91,8 @@ final class ReverseNaturalOrdering
     return INSTANCE;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Ordering.natural().reverse()";
   }
 
diff --git a/guava/src/com/google/common/collect/ReverseOrdering.java b/guava/src/com/google/common/collect/ReverseOrdering.java
index 36ae02c..30ffbf8 100644
--- a/guava/src/com/google/common/collect/ReverseOrdering.java
+++ b/guava/src/com/google/common/collect/ReverseOrdering.java
@@ -34,54 +34,66 @@ final class ReverseOrdering<T> extends Ordering<T> implements Serializable {
     this.forwardOrder = checkNotNull(forwardOrder);
   }
 
-  @Override public int compare(T a, T b) {
+  @Override
+  public int compare(T a, T b) {
     return forwardOrder.compare(b, a);
   }
 
   @SuppressWarnings("unchecked") // how to explain?
-  @Override public <S extends T> Ordering<S> reverse() {
+  @Override
+  public <S extends T> Ordering<S> reverse() {
     return (Ordering<S>) forwardOrder;
   }
 
   // Override the min/max methods to "hoist" delegation outside loops
 
-  @Override public <E extends T> E min(E a, E b) {
+  @Override
+  public <E extends T> E min(E a, E b) {
     return forwardOrder.max(a, b);
   }
 
-  @Override public <E extends T> E min(E a, E b, E c, E... rest) {
+  @Override
+  public <E extends T> E min(E a, E b, E c, E... rest) {
     return forwardOrder.max(a, b, c, rest);
   }
 
-  @Override public <E extends T> E min(Iterator<E> iterator) {
+  @Override
+  public <E extends T> E min(Iterator<E> iterator) {
     return forwardOrder.max(iterator);
   }
 
-  @Override public <E extends T> E min(Iterable<E> iterable) {
+  @Override
+  public <E extends T> E min(Iterable<E> iterable) {
     return forwardOrder.max(iterable);
   }
 
-  @Override public <E extends T> E max(E a, E b) {
+  @Override
+  public <E extends T> E max(E a, E b) {
     return forwardOrder.min(a, b);
   }
 
-  @Override public <E extends T> E max(E a, E b, E c, E... rest) {
+  @Override
+  public <E extends T> E max(E a, E b, E c, E... rest) {
     return forwardOrder.min(a, b, c, rest);
   }
 
-  @Override public <E extends T> E max(Iterator<E> iterator) {
+  @Override
+  public <E extends T> E max(Iterator<E> iterator) {
     return forwardOrder.min(iterator);
   }
 
-  @Override public <E extends T> E max(Iterable<E> iterable) {
+  @Override
+  public <E extends T> E max(Iterable<E> iterable) {
     return forwardOrder.min(iterable);
   }
 
-  @Override public int hashCode() {
+  @Override
+  public int hashCode() {
     return -forwardOrder.hashCode();
   }
 
-  @Override public boolean equals(@Nullable Object object) {
+  @Override
+  public boolean equals(@Nullable Object object) {
     if (object == this) {
       return true;
     }
@@ -92,7 +104,8 @@ final class ReverseOrdering<T> extends Ordering<T> implements Serializable {
     return false;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return forwardOrder + ".reverse()";
   }
 
diff --git a/guava/src/com/google/common/collect/RowSortedTable.java b/guava/src/com/google/common/collect/RowSortedTable.java
index 4b597b7..76d8ad6 100644
--- a/guava/src/com/google/common/collect/RowSortedTable.java
+++ b/guava/src/com/google/common/collect/RowSortedTable.java
@@ -43,7 +43,8 @@ public interface RowSortedTable<R, C, V> extends Table<R, C, V> {
    * <p>This method returns a {@link SortedSet}, instead of the {@code Set}
    * specified in the {@link Table} interface.
    */
-  @Override SortedSet<R> rowKeySet();
+  @Override
+  SortedSet<R> rowKeySet();
 
   /**
    * {@inheritDoc}
@@ -51,5 +52,6 @@ public interface RowSortedTable<R, C, V> extends Table<R, C, V> {
    * <p>This method returns a {@link SortedMap}, instead of the {@code Map}
    * specified in the {@link Table} interface.
    */
-  @Override SortedMap<R, Map<C, V>> rowMap();
+  @Override
+  SortedMap<R, Map<C, V>> rowMap();
 }
diff --git a/guava/src/com/google/common/collect/Serialization.java b/guava/src/com/google/common/collect/Serialization.java
index 2541548..6f57fdc 100644
--- a/guava/src/com/google/common/collect/Serialization.java
+++ b/guava/src/com/google/common/collect/Serialization.java
@@ -42,9 +42,6 @@ final class Serialization {
    * #writeMultiset(Multiset, ObjectOutputStream)}, or the number of distinct
    * keys in a multimap serialized by {@link
    * #writeMultimap(Multimap, ObjectOutputStream)}.
-   *
-   * <p>The returned count may be used to construct an empty collection of the
-   * appropriate capacity before calling any of the {@code populate} methods.
    */
   static int readCount(ObjectInputStream stream) throws IOException {
     return stream.readInt();
@@ -58,8 +55,7 @@ final class Serialization {
    * <p>The serialized output consists of the number of entries, first key,
    * first value, second key, second value, and so on.
    */
-  static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream)
-      throws IOException {
+  static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream) throws IOException {
     stream.writeInt(map.size());
     for (Map.Entry<K, V> entry : map.entrySet()) {
       stream.writeObject(entry.getKey());
@@ -82,8 +78,8 @@ final class Serialization {
    * See {@link #writeMap} for the data format. The size is determined by a
    * prior call to {@link #readCount}.
    */
-  static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream,
-      int size) throws IOException, ClassNotFoundException {
+  static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream, int size)
+      throws IOException, ClassNotFoundException {
     for (int i = 0; i < size; i++) {
       @SuppressWarnings("unchecked") // reading data stored by writeMap
       K key = (K) stream.readObject();
@@ -101,8 +97,8 @@ final class Serialization {
    * <p>The serialized output consists of the number of distinct elements, the
    * first element, its count, the second element, its count, and so on.
    */
-  static <E> void writeMultiset(
-      Multiset<E> multiset, ObjectOutputStream stream) throws IOException {
+  static <E> void writeMultiset(Multiset<E> multiset, ObjectOutputStream stream)
+      throws IOException {
     int entryCount = multiset.entrySet().size();
     stream.writeInt(entryCount);
     for (Multiset.Entry<E> entry : multiset.entrySet()) {
@@ -115,8 +111,7 @@ final class Serialization {
    * Populates a multiset by reading an input stream, as part of
    * deserialization. See {@link #writeMultiset} for the data format.
    */
-  static <E> void populateMultiset(
-      Multiset<E> multiset, ObjectInputStream stream)
+  static <E> void populateMultiset(Multiset<E> multiset, ObjectInputStream stream)
       throws IOException, ClassNotFoundException {
     int distinctElements = stream.readInt();
     populateMultiset(multiset, stream, distinctElements);
@@ -148,8 +143,8 @@ final class Serialization {
    * for each distinct key: the key, the number of values for that key, and the
    * key's values.
    */
-  static <K, V> void writeMultimap(
-      Multimap<K, V> multimap, ObjectOutputStream stream) throws IOException {
+  static <K, V> void writeMultimap(Multimap<K, V> multimap, ObjectOutputStream stream)
+      throws IOException {
     stream.writeInt(multimap.asMap().size());
     for (Map.Entry<K, Collection<V>> entry : multimap.asMap().entrySet()) {
       stream.writeObject(entry.getKey());
@@ -164,8 +159,7 @@ final class Serialization {
    * Populates a multimap by reading an input stream, as part of
    * deserialization. See {@link #writeMultimap} for the data format.
    */
-  static <K, V> void populateMultimap(
-      Multimap<K, V> multimap, ObjectInputStream stream)
+  static <K, V> void populateMultimap(Multimap<K, V> multimap, ObjectInputStream stream)
       throws IOException, ClassNotFoundException {
     int distinctKeys = stream.readInt();
     populateMultimap(multimap, stream, distinctKeys);
@@ -193,8 +187,7 @@ final class Serialization {
   }
 
   // Secret sauce for setting final fields; don't make it public.
-  static <T> FieldSetter<T> getFieldSetter(
-      final Class<T> clazz, String fieldName) {
+  static <T> FieldSetter<T> getFieldSetter(final Class<T> clazz, String fieldName) {
     try {
       Field field = clazz.getDeclaredField(fieldName);
       return new FieldSetter<T>(field);
diff --git a/guava/src/com/google/common/collect/SetMultimap.java b/guava/src/com/google/common/collect/SetMultimap.java
index 8c28d6b..46ae17a 100644
--- a/guava/src/com/google/common/collect/SetMultimap.java
+++ b/guava/src/com/google/common/collect/SetMultimap.java
@@ -37,19 +37,19 @@ import javax.annotation.Nullable;
  * <p>If the values corresponding to a single key should be ordered according to
  * a {@link java.util.Comparator} (or the natural order), see the
  * {@link SortedSetMultimap} subinterface.
- * 
+ *
  * <p>Since the value collections are sets, the behavior of a {@code SetMultimap}
- * is not specified if key <em>or value</em> objects already present in the 
- * multimap change in a manner that affects {@code equals} comparisons.  
- * Use caution if mutable objects are used as keys or values in a 
+ * is not specified if key <em>or value</em> objects already present in the
+ * multimap change in a manner that affects {@code equals} comparisons.
+ * Use caution if mutable objects are used as keys or values in a
  * {@code SetMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface SetMultimap<K, V> extends Multimap<K, V> {
diff --git a/guava/src/com/google/common/collect/Sets.java b/guava/src/com/google/common/collect/Sets.java
index 4218725..5d0142c 100644
--- a/guava/src/com/google/common/collect/Sets.java
+++ b/guava/src/com/google/common/collect/Sets.java
@@ -45,6 +45,7 @@ import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -52,13 +53,13 @@ import javax.annotation.Nullable;
  * class's counterparts {@link Lists}, {@link Maps} and {@link Queues}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Sets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#sets">
  * {@code Sets}</a>.
  *
  * @author Kevin Bourrillion
  * @author Jared Levy
  * @author Chris Povirk
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class Sets {
@@ -111,8 +112,7 @@ public final class Sets {
    */
   // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
   @GwtCompatible(serializable = true)
-  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(
-      Iterable<E> elements) {
+  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(Iterable<E> elements) {
     if (elements instanceof ImmutableEnumSet) {
       return (ImmutableEnumSet<E>) elements;
     } else if (elements instanceof Collection) {
@@ -135,13 +135,12 @@ public final class Sets {
   }
 
   /**
-   * Returns a new {@code EnumSet} instance containing the given elements.
-   * Unlike {@link EnumSet#copyOf(Collection)}, this method does not produce an
-   * exception on an empty collection, and it may be called on any iterable, not
-   * just a {@code Collection}.
+   * Returns a new, <i>mutable</i> {@code EnumSet} instance containing the given elements in their
+   * natural order. This method behaves identically to {@link EnumSet#copyOf(Collection)}, but also
+   * accepts non-{@code Collection} iterables and empty iterables.
    */
-  public static <E extends Enum<E>> EnumSet<E> newEnumSet(Iterable<E> iterable,
-      Class<E> elementType) {
+  public static <E extends Enum<E>> EnumSet<E> newEnumSet(
+      Iterable<E> iterable, Class<E> elementType) {
     EnumSet<E> set = EnumSet.noneOf(elementType);
     Iterables.addAll(set, iterable);
     return set;
@@ -150,33 +149,33 @@ public final class Sets {
   // HashSet
 
   /**
-   * Creates a <i>mutable</i>, empty {@code HashSet} instance.
+   * Creates a <i>mutable</i>, initially empty {@code HashSet} instance.
    *
-   * <p><b>Note:</b> if mutability is not required, use {@link
-   * ImmutableSet#of()} instead.
+   * <p><b>Note:</b> if mutability is not required, use {@link ImmutableSet#of()} instead. If
+   * {@code E} is an {@link Enum} type, use {@link EnumSet#noneOf} instead. Otherwise, strongly
+   * consider using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to
+   * get deterministic iteration behavior.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
-   * EnumSet#noneOf} instead.
-   *
-   * @return a new, empty {@code HashSet}
+   * <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
+   * deprecated. Instead, use the {@code HashSet} constructor directly, taking advantage of the new
+   * <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
    */
   public static <E> HashSet<E> newHashSet() {
     return new HashSet<E>();
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
-   *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use an overload of {@link ImmutableSet#of()} (for varargs) or
-   * {@link ImmutableSet#copyOf(Object[])} (for an array) instead.
+   * Creates a <i>mutable</i> {@code HashSet} instance initially containing the given elements.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
-   * EnumSet#of(Enum, Enum[])} instead.
+   * <p><b>Note:</b> if elements are non-null and won't be added or removed after this point, use
+   * {@link ImmutableSet#of()} or {@link ImmutableSet#copyOf(Object[])} instead. If {@code E} is an
+   * {@link Enum} type, use {@link EnumSet#of(Enum, Enum[])} instead. Otherwise, strongly consider
+   * using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to get
+   * deterministic iteration behavior.
    *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p>This method is just a small convenience, either for {@code newHashSet(}{@link Arrays#asList
+   * asList}{@code (...))}, or for creating an empty set then calling {@link Collections#addAll}.
+   * This method is not actually very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(E... elements) {
     HashSet<E> set = newHashSetWithExpectedSize(elements.length);
@@ -185,11 +184,10 @@ public final class Sets {
   }
 
   /**
-   * Creates a {@code HashSet} instance, with a high enough "initial capacity"
-   * that it <i>should</i> hold {@code expectedSize} elements without growth.
-   * This behavior cannot be broadly guaranteed, but it is observed to be true
-   * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
-   * inadvertently <i>oversizing</i> the returned set.
+   * Creates a {@code HashSet} instance, with a high enough initial table size that it <i>should</i>
+   * hold {@code expectedSize} elements without resizing. This behavior cannot be broadly
+   * guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the
+   * method isn't inadvertently <i>oversizing</i> the returned set.
    *
    * @param expectedSize the number of elements you expect to add to the
    *        returned set
@@ -202,17 +200,22 @@ public final class Sets {
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
+   * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+   * convenience for creating an empty set then calling {@link Collection#addAll} or {@link
+   * Iterables#addAll}.
    *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+   * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+   * ImmutableSet#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
+   * FluentIterable} and call {@code elements.toSet()}.)
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use
-   * {@link #newEnumSet(Iterable, Class)} instead.
+   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link #newEnumSet(Iterable, Class)}
+   * instead.
    *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
+   * need this method. Instead, use the {@code HashSet} constructor directly, taking advantage of
+   * the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
+   *
+   * <p>Overall, this method is not very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
     return (elements instanceof Collection)
@@ -221,17 +224,16 @@ public final class Sets {
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashSet} instance containing the given
-   * elements in unspecified order.
+   * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+   * convenience for creating an empty set and then calling {@link Iterators#addAll}.
    *
-   * <p><b>Note:</b> if mutability is not required and the elements are
-   * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+   * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+   * ImmutableSet#copyOf(Iterator)} instead.
    *
-   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an
-   * {@link EnumSet} instead.
+   * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an {@link EnumSet}
+   * instead.
    *
-   * @param elements the elements that the set should contain
-   * @return a new {@code HashSet} containing those elements (minus duplicates)
+   * <p>Overall, this method is not very useful and will likely be deprecated in the future.
    */
   public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
     HashSet<E> set = newHashSet();
@@ -268,8 +270,7 @@ public final class Sets {
    *      null
    * @since 15.0
    */
-  public static <E> Set<E> newConcurrentHashSet(
-      Iterable<? extends E> elements) {
+  public static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) {
     Set<E> set = newConcurrentHashSet();
     Iterables.addAll(set, elements);
     return set;
@@ -303,8 +304,7 @@ public final class Sets {
    * @throws IllegalArgumentException if {@code expectedSize} is negative
    * @since 11.0
    */
-  public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(
-      int expectedSize) {
+  public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(int expectedSize) {
     return new LinkedHashSet<E>(Maps.capacity(expectedSize));
   }
 
@@ -319,8 +319,7 @@ public final class Sets {
    * @return a new {@code LinkedHashSet} containing those elements (minus
    *     duplicates)
    */
-  public static <E> LinkedHashSet<E> newLinkedHashSet(
-      Iterable<? extends E> elements) {
+  public static <E> LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements) {
     if (elements instanceof Collection) {
       return new LinkedHashSet<E>(Collections2.cast(elements));
     }
@@ -359,8 +358,7 @@ public final class Sets {
    * @param elements the elements that the set should contain
    * @return a new {@code TreeSet} containing those elements (minus duplicates)
    */
-  public static <E extends Comparable> TreeSet<E> newTreeSet(
-      Iterable<? extends E> elements) {
+  public static <E extends Comparable> TreeSet<E> newTreeSet(Iterable<? extends E> elements) {
     TreeSet<E> set = newTreeSet();
     Iterables.addAll(set, elements);
     return set;
@@ -417,13 +415,13 @@ public final class Sets {
    * @since 12.0
    */
   @GwtIncompatible("CopyOnWriteArraySet")
-  public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(
-      Iterable<? extends E> elements) {
+  public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements) {
     // We copy elements to an ArrayList first, rather than incurring the
     // quadratic cost of adding them to the COWAS directly.
-    Collection<? extends E> elementsCollection = (elements instanceof Collection)
-        ? Collections2.cast(elements)
-        : Lists.newArrayList(elements);
+    Collection<? extends E> elementsCollection =
+        (elements instanceof Collection)
+            ? Collections2.cast(elements)
+            : Lists.newArrayList(elements);
     return new CopyOnWriteArraySet<E>(elementsCollection);
   }
 
@@ -442,13 +440,12 @@ public final class Sets {
    * @throws IllegalArgumentException if {@code collection} is not an
    *     {@code EnumSet} instance and contains no elements
    */
-  public static <E extends Enum<E>> EnumSet<E> complementOf(
-      Collection<E> collection) {
+  public static <E extends Enum<E>> EnumSet<E> complementOf(Collection<E> collection) {
     if (collection instanceof EnumSet) {
       return EnumSet.complementOf((EnumSet<E>) collection);
     }
-    checkArgument(!collection.isEmpty(),
-        "collection is empty; use the other version of this method");
+    checkArgument(
+        !collection.isEmpty(), "collection is empty; use the other version of this method");
     Class<E> type = collection.iterator().next().getDeclaringClass();
     return makeComplementByHand(collection, type);
   }
@@ -503,14 +500,15 @@ public final class Sets {
    *   Set<Object> identityHashSet = Sets.newSetFromMap(
    *       new IdentityHashMap<Object, Boolean>());}</pre>
    *
-   * <p>This method has the same behavior as the JDK 6 method
-   * {@code Collections.newSetFromMap()}. The returned set is serializable if
-   * the backing map is.
+   * <p>The returned set is serializable if the backing map is.
    *
    * @param map the backing map
    * @return the set backed by the map
    * @throws IllegalArgumentException if {@code map} is not empty
+   * @deprecated Use {@link Collections#newSetFromMap} instead. This method
+   *     will be removed in August 2017.
    */
+  @Deprecated
   public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
     return Platform.newSetFromMap(map);
   }
@@ -523,7 +521,7 @@ public final class Sets {
    * as a plain {@link Set}, or immediately invoke {@link #immutableCopy} or
    * {@link #copyInto} and forget the {@code SetView} itself.
    *
-   * @since 2.0 (imported from Google Collections Library)
+   * @since 2.0
    */
   public abstract static class SetView<E> extends AbstractSet<E> {
     private SetView() {} // no subclasses but our own
@@ -576,35 +574,44 @@ public final class Sets {
    * {@code union = Sets.union(union, anotherSet);}, since iterating over the resulting
    * set has a cubic complexity to the depth of the nesting.
    */
-  public static <E> SetView<E> union(
-      final Set<? extends E> set1, final Set<? extends E> set2) {
+  public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Set<? extends E> set2minus1 = difference(set2, set1);
 
     return new SetView<E>() {
-      @Override public int size() {
+      @Override
+      public int size() {
         return set1.size() + set2minus1.size();
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return set1.isEmpty() && set2.isEmpty();
       }
-      @Override public Iterator<E> iterator() {
+
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.unmodifiableIterator(
             Iterators.concat(set1.iterator(), set2minus1.iterator()));
       }
-      @Override public boolean contains(Object object) {
+
+      @Override
+      public boolean contains(Object object) {
         return set1.contains(object) || set2.contains(object);
       }
-      @Override public <S extends Set<E>> S copyInto(S set) {
+
+      @Override
+      public <S extends Set<E>> S copyInto(S set) {
         set.addAll(set1);
         set.addAll(set2);
         return set;
       }
-      @Override public ImmutableSet<E> immutableCopy() {
-        return new ImmutableSet.Builder<E>()
-            .addAll(set1).addAll(set2).build();
+
+      @Override
+      public ImmutableSet<E> immutableCopy() {
+        return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
       }
     };
   }
@@ -635,28 +642,35 @@ public final class Sets {
    *
    * <p>This is unfortunate, but should come up only very rarely.
    */
-  public static <E> SetView<E> intersection(
-      final Set<E> set1, final Set<?> set2) {
+  public static <E> SetView<E> intersection(final Set<E> set1, final Set<?> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Predicate<Object> inSet2 = Predicates.in(set2);
     return new SetView<E>() {
-      @Override public Iterator<E> iterator() {
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.filter(set1.iterator(), inSet2);
       }
-      @Override public int size() {
+
+      @Override
+      public int size() {
         return Iterators.size(iterator());
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return !iterator().hasNext();
       }
-      @Override public boolean contains(Object object) {
+
+      @Override
+      public boolean contains(Object object) {
         return set1.contains(object) && set2.contains(object);
       }
-      @Override public boolean containsAll(Collection<?> collection) {
-        return set1.containsAll(collection)
-            && set2.containsAll(collection);
+
+      @Override
+      public boolean containsAll(Collection<?> collection) {
+        return set1.containsAll(collection) && set2.containsAll(collection);
       }
     };
   }
@@ -672,23 +686,29 @@ public final class Sets {
    * on different equivalence relations (as {@code HashSet}, {@code TreeSet},
    * and the keySet of an {@code IdentityHashMap} all are).
    */
-  public static <E> SetView<E> difference(
-      final Set<E> set1, final Set<?> set2) {
+  public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
     final Predicate<Object> notInSet2 = Predicates.not(Predicates.in(set2));
     return new SetView<E>() {
-      @Override public Iterator<E> iterator() {
+      @Override
+      public Iterator<E> iterator() {
         return Iterators.filter(set1.iterator(), notInSet2);
       }
-      @Override public int size() {
+
+      @Override
+      public int size() {
         return Iterators.size(iterator());
       }
-      @Override public boolean isEmpty() {
+
+      @Override
+      public boolean isEmpty() {
         return set2.containsAll(set1);
       }
-      @Override public boolean contains(Object element) {
+
+      @Override
+      public boolean contains(Object element) {
         return set1.contains(element) && !set2.contains(element);
       }
     };
@@ -707,12 +727,50 @@ public final class Sets {
    * @since 3.0
    */
   public static <E> SetView<E> symmetricDifference(
-      Set<? extends E> set1, Set<? extends E> set2) {
+      final Set<? extends E> set1, final Set<? extends E> set2) {
     checkNotNull(set1, "set1");
     checkNotNull(set2, "set2");
 
-    // TODO(kevinb): Replace this with a more efficient implementation
-    return difference(union(set1, set2), intersection(set1, set2));
+    return new SetView<E>() {
+      @Override
+      public Iterator<E> iterator() {
+        final Iterator<? extends E> itr1 = set1.iterator();
+        final Iterator<? extends E> itr2 = set2.iterator();
+        return new AbstractIterator<E>() {
+          @Override
+          public E computeNext() {
+            while (itr1.hasNext()) {
+              E elem1 = itr1.next();
+              if (!set2.contains(elem1)) {
+                return elem1;
+              }
+            }
+            while (itr2.hasNext()) {
+              E elem2 = itr2.next();
+              if (!set1.contains(elem2)) {
+                return elem2;
+              }
+            }
+            return endOfData();
+          }
+        };
+      }
+
+      @Override
+      public int size() {
+        return Iterators.size(iterator());
+      }
+
+      @Override
+      public boolean isEmpty() {
+        return set1.equals(set2);
+      }
+
+      @Override
+      public boolean contains(Object element) {
+        return set1.contains(element) ^ set2.contains(element);
+      }
+    };
   }
 
   /**
@@ -742,8 +800,8 @@ public final class Sets {
    * functionality.)
    */
   // TODO(kevinb): how to omit that last sentence when building GWT javadoc?
-  public static <E> Set<E> filter(
-      Set<E> unfiltered, Predicate<? super E> predicate) {
+  @CheckReturnValue
+  public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) {
     if (unfiltered instanceof SortedSet) {
       return filter((SortedSet<E>) unfiltered, predicate);
     }
@@ -751,27 +809,25 @@ public final class Sets {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
-      return new FilteredSet<E>(
-          (Set<E>) filtered.unfiltered, combinedPredicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+      return new FilteredSet<E>((Set<E>) filtered.unfiltered, combinedPredicate);
     }
 
-    return new FilteredSet<E>(
-        checkNotNull(unfiltered), checkNotNull(predicate));
+    return new FilteredSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
-  private static class FilteredSet<E> extends FilteredCollection<E>
-      implements Set<E> {
+  private static class FilteredSet<E> extends FilteredCollection<E> implements Set<E> {
     FilteredSet(Set<E> unfiltered, Predicate<? super E> predicate) {
       super(unfiltered, predicate);
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       return equalsImpl(this, object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return hashCodeImpl(this);
     }
   }
@@ -805,8 +861,8 @@ public final class Sets {
    *
    * @since 11.0
    */
-  public static <E> SortedSet<E> filter(
-      SortedSet<E> unfiltered, Predicate<? super E> predicate) {
+  @CheckReturnValue
+  public static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
     return Platform.setsFilterSortedSet(unfiltered, predicate);
   }
 
@@ -816,18 +872,14 @@ public final class Sets {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
-      return new FilteredSortedSet<E>(
-          (SortedSet<E>) filtered.unfiltered, combinedPredicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+      return new FilteredSortedSet<E>((SortedSet<E>) filtered.unfiltered, combinedPredicate);
     }
 
-    return new FilteredSortedSet<E>(
-        checkNotNull(unfiltered), checkNotNull(predicate));
+    return new FilteredSortedSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
-  private static class FilteredSortedSet<E> extends FilteredSet<E>
-      implements SortedSet<E> {
+  private static class FilteredSortedSet<E> extends FilteredSet<E> implements SortedSet<E> {
 
     FilteredSortedSet(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
       super(unfiltered, predicate);
@@ -840,8 +892,8 @@ public final class Sets {
 
     @Override
     public SortedSet<E> subSet(E fromElement, E toElement) {
-      return new FilteredSortedSet<E>(((SortedSet<E>) unfiltered).subSet(fromElement, toElement),
-          predicate);
+      return new FilteredSortedSet<E>(
+          ((SortedSet<E>) unfiltered).subSet(fromElement, toElement), predicate);
     }
 
     @Override
@@ -903,20 +955,18 @@ public final class Sets {
    */
   @GwtIncompatible("NavigableSet")
   @SuppressWarnings("unchecked")
+  @CheckReturnValue
   public static <E> NavigableSet<E> filter(
       NavigableSet<E> unfiltered, Predicate<? super E> predicate) {
     if (unfiltered instanceof FilteredSet) {
       // Support clear(), removeAll(), and retainAll() when filtering a filtered
       // collection.
       FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
-      Predicate<E> combinedPredicate
-          = Predicates.<E>and(filtered.predicate, predicate);
-      return new FilteredNavigableSet<E>(
-          (NavigableSet<E>) filtered.unfiltered, combinedPredicate);
+      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+      return new FilteredNavigableSet<E>((NavigableSet<E>) filtered.unfiltered, combinedPredicate);
     }
 
-    return new FilteredNavigableSet<E>(
-        checkNotNull(unfiltered), checkNotNull(predicate));
+    return new FilteredNavigableSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
   }
 
   @GwtIncompatible("NavigableSet")
@@ -1050,8 +1100,7 @@ public final class Sets {
    *     or any element of a provided set is null
    * @since 2.0
    */
-  public static <B> Set<List<B>> cartesianProduct(
-      List<? extends Set<? extends B>> sets) {
+  public static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
     return CartesianSet.create(sets);
   }
 
@@ -1110,13 +1159,12 @@ public final class Sets {
    *     or any element of a provided set is null
    * @since 2.0
    */
-  public static <B> Set<List<B>> cartesianProduct(
-      Set<? extends B>... sets) {
+  public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) {
     return cartesianProduct(Arrays.asList(sets));
   }
 
-  private static final class CartesianSet<E>
-      extends ForwardingCollection<List<E>> implements Set<List<E>> {
+  private static final class CartesianSet<E> extends ForwardingCollection<List<E>>
+      implements Set<List<E>> {
     private transient final ImmutableList<ImmutableSet<E>> axes;
     private transient final CartesianList<E> delegate;
 
@@ -1131,28 +1179,27 @@ public final class Sets {
         axesBuilder.add(copy);
       }
       final ImmutableList<ImmutableSet<E>> axes = axesBuilder.build();
-      ImmutableList<List<E>> listAxes = new ImmutableList<List<E>>() {
-
-        @Override
-        public int size() {
-          return axes.size();
-        }
-
-        @Override
-        public List<E> get(int index) {
-          return axes.get(index).asList();
-        }
-
-        @Override
-        boolean isPartialView() {
-          return true;
-        }
-      };
+      ImmutableList<List<E>> listAxes =
+          new ImmutableList<List<E>>() {
+            @Override
+            public int size() {
+              return axes.size();
+            }
+
+            @Override
+            public List<E> get(int index) {
+              return axes.get(index).asList();
+            }
+
+            @Override
+            boolean isPartialView() {
+              return true;
+            }
+          };
       return new CartesianSet<E>(axes, new CartesianList<E>(listAxes));
     }
 
-    private CartesianSet(
-        ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
+    private CartesianSet(ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
       this.axes = axes;
       this.delegate = delegate;
     }
@@ -1162,7 +1209,8 @@ public final class Sets {
       return delegate;
     }
 
-    @Override public boolean equals(@Nullable Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       // Warning: this is broken if size() == 0, so it is critical that we
       // substitute an empty ImmutableSet to the user in place of this
       if (object instanceof CartesianSet) {
@@ -1277,33 +1325,33 @@ public final class Sets {
     final ImmutableMap<E, Integer> inputSet;
 
     PowerSet(Set<E> input) {
-      ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
-      int i = 0;
-      for (E e : checkNotNull(input)) {
-        builder.put(e, i++);
-      }
-      this.inputSet = builder.build();
-      checkArgument(inputSet.size() <= 30,
-          "Too many elements to create power set: %s > 30", inputSet.size());
+      this.inputSet = Maps.indexMap(input);
+      checkArgument(
+          inputSet.size() <= 30, "Too many elements to create power set: %s > 30", inputSet.size());
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return 1 << inputSet.size();
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Iterator<Set<E>> iterator() {
+    @Override
+    public Iterator<Set<E>> iterator() {
       return new AbstractIndexedListIterator<Set<E>>(size()) {
-        @Override protected Set<E> get(final int setBits) {
+        @Override
+        protected Set<E> get(final int setBits) {
           return new SubSet<E>(inputSet, setBits);
         }
       };
     }
 
-    @Override public boolean contains(@Nullable Object obj) {
+    @Override
+    public boolean contains(@Nullable Object obj) {
       if (obj instanceof Set) {
         Set<?> set = (Set<?>) obj;
         return inputSet.keySet().containsAll(set);
@@ -1311,7 +1359,8 @@ public final class Sets {
       return false;
     }
 
-    @Override public boolean equals(@Nullable Object obj) {
+    @Override
+    public boolean equals(@Nullable Object obj) {
       if (obj instanceof PowerSet) {
         PowerSet<?> that = (PowerSet<?>) obj;
         return inputSet.equals(that.inputSet);
@@ -1319,7 +1368,8 @@ public final class Sets {
       return super.equals(obj);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       /*
        * The sum of the sums of the hash codes in each subset is just the sum of
        * each input element's hash code times the number of sets that element
@@ -1328,7 +1378,8 @@ public final class Sets {
       return inputSet.keySet().hashCode() << (inputSet.size() - 1);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "powerSet(" + inputSet + ")";
     }
   }
@@ -1385,18 +1436,16 @@ public final class Sets {
    * @since 12.0
    */
   @GwtIncompatible("NavigableSet")
-  public static <E> NavigableSet<E> unmodifiableNavigableSet(
-      NavigableSet<E> set) {
-    if (set instanceof ImmutableSortedSet
-        || set instanceof UnmodifiableNavigableSet) {
+  public static <E> NavigableSet<E> unmodifiableNavigableSet(NavigableSet<E> set) {
+    if (set instanceof ImmutableSortedSet || set instanceof UnmodifiableNavigableSet) {
       return set;
     }
     return new UnmodifiableNavigableSet<E>(set);
   }
 
   @GwtIncompatible("NavigableSet")
-  static final class UnmodifiableNavigableSet<E>
-      extends ForwardingSortedSet<E> implements NavigableSet<E>, Serializable {
+  static final class UnmodifiableNavigableSet<E> extends ForwardingSortedSet<E>
+      implements NavigableSet<E>, Serializable {
     private final NavigableSet<E> delegate;
 
     UnmodifiableNavigableSet(NavigableSet<E> delegate) {
@@ -1444,8 +1493,7 @@ public final class Sets {
     public NavigableSet<E> descendingSet() {
       UnmodifiableNavigableSet<E> result = descendingSet;
       if (result == null) {
-        result = descendingSet = new UnmodifiableNavigableSet<E>(
-            delegate.descendingSet());
+        result = descendingSet = new UnmodifiableNavigableSet<E>(delegate.descendingSet());
         result.descendingSet = this;
       }
       return result;
@@ -1458,15 +1506,9 @@ public final class Sets {
 
     @Override
     public NavigableSet<E> subSet(
-        E fromElement,
-        boolean fromInclusive,
-        E toElement,
-        boolean toInclusive) {
-      return unmodifiableNavigableSet(delegate.subSet(
-          fromElement,
-          fromInclusive,
-          toElement,
-          toInclusive));
+        E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+      return unmodifiableNavigableSet(
+          delegate.subSet(fromElement, fromInclusive, toElement, toInclusive));
     }
 
     @Override
@@ -1476,8 +1518,7 @@ public final class Sets {
 
     @Override
     public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
-      return unmodifiableNavigableSet(
-          delegate.tailSet(fromElement, inclusive));
+      return unmodifiableNavigableSet(delegate.tailSet(fromElement, inclusive));
     }
 
     private static final long serialVersionUID = 0;
@@ -1527,8 +1568,7 @@ public final class Sets {
    * @since 13.0
    */
   @GwtIncompatible("NavigableSet")
-  public static <E> NavigableSet<E> synchronizedNavigableSet(
-      NavigableSet<E> navigableSet) {
+  public static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet) {
     return Synchronized.navigableSet(navigableSet);
   }
 
@@ -1617,10 +1657,7 @@ public final class Sets {
 
     @Override
     public NavigableSet<E> subSet(
-        E fromElement,
-        boolean fromInclusive,
-        E toElement,
-        boolean toInclusive) {
+        E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
       return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet();
     }
 
diff --git a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
index ffc93e9..d330190 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
@@ -41,18 +41,14 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
     this.singleValue = singleValue;
   }
 
-  private SingletonImmutableBiMap(K singleKey, V singleValue,
-      ImmutableBiMap<V, K> inverse) {
+  private SingletonImmutableBiMap(K singleKey, V singleValue, ImmutableBiMap<V, K> inverse) {
     this.singleKey = singleKey;
     this.singleValue = singleValue;
     this.inverse = inverse;
   }
 
-  SingletonImmutableBiMap(Entry<? extends K, ? extends V> entry) {
-    this(entry.getKey(), entry.getValue());
-  }
-
-  @Override public V get(@Nullable Object key) {
+  @Override
+  public V get(@Nullable Object key) {
     return singleKey.equals(key) ? singleValue : null;
   }
 
@@ -61,15 +57,18 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
     return 1;
   }
 
-  @Override public boolean containsKey(@Nullable Object key) {
+  @Override
+  public boolean containsKey(@Nullable Object key) {
     return singleKey.equals(key);
   }
 
-  @Override public boolean containsValue(@Nullable Object value) {
+  @Override
+  public boolean containsValue(@Nullable Object value) {
     return singleValue.equals(value);
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
@@ -90,8 +89,7 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
     // racy single-check idiom
     ImmutableBiMap<V, K> result = inverse;
     if (result == null) {
-      return inverse = new SingletonImmutableBiMap<V, K>(
-          singleValue, singleKey, this);
+      return inverse = new SingletonImmutableBiMap<V, K>(singleValue, singleKey, this);
     } else {
       return result;
     }
diff --git a/guava/src/com/google/common/collect/SingletonImmutableList.java b/guava/src/com/google/common/collect/SingletonImmutableList.java
index 18d8290..267d946 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableList.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableList.java
@@ -21,10 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Preconditions;
 
-import java.util.List;
-
-import javax.annotation.Nullable;
-
 /**
  * Implementation of {@link ImmutableList} with exactly one element.
  *
@@ -46,54 +42,24 @@ final class SingletonImmutableList<E> extends ImmutableList<E> {
     return element;
   }
 
-  @Override public int indexOf(@Nullable Object object) {
-    return element.equals(object) ? 0 : -1;
-  }
-
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     return Iterators.singletonIterator(element);
   }
 
-  @Override public int lastIndexOf(@Nullable Object object) {
-    return indexOf(object);
-  }
-
   @Override
   public int size() {
     return 1;
   }
 
-  @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
+  @Override
+  public ImmutableList<E> subList(int fromIndex, int toIndex) {
     Preconditions.checkPositionIndexes(fromIndex, toIndex, 1);
     return (fromIndex == toIndex) ? ImmutableList.<E>of() : this;
   }
 
-  @Override public ImmutableList<E> reverse() {
-    return this;
-  }
-
-  @Override public boolean contains(@Nullable Object object) {
-    return element.equals(object);
-  }
-
-  @Override public boolean equals(@Nullable Object object) {
-    if (object == this) {
-      return true;
-    }
-    if (object instanceof List) {
-      List<?> that = (List<?>) object;
-      return that.size() == 1 && element.equals(that.get(0));
-    }
-    return false;
-  }
-
-  @Override public int hashCode() {
-    // not caching hash code since it could change if the element is mutable
-    // in a way that modifies its hash code.
-    return 31 + element.hashCode();
-  }
-
-  @Override public String toString() {
+  @Override
+  public String toString() {
     String elementToString = element.toString();
     return new StringBuilder(elementToString.length() + 2)
         .append('[')
@@ -102,17 +68,8 @@ final class SingletonImmutableList<E> extends ImmutableList<E> {
         .toString();
   }
 
-  @Override public boolean isEmpty() {
-    return false;
-  }
-
-  @Override boolean isPartialView() {
-    return false;
-  }
-
   @Override
-  int copyIntoArray(Object[] dst, int offset) {
-    dst[offset] = element;
-    return offset + 1;
+  boolean isPartialView() {
+    return false;
   }
 }
diff --git a/guava/src/com/google/common/collect/SingletonImmutableSet.java b/guava/src/com/google/common/collect/SingletonImmutableSet.java
index 50c932c..9067e60 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableSet.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableSet.java
@@ -19,10 +19,6 @@ package com.google.common.collect;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Preconditions;
 
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
 /**
  * Implementation of {@link ImmutableSet} with exactly one element.
  *
@@ -58,19 +54,18 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
     return 1;
   }
 
-  @Override public boolean isEmpty() {
-    return false;
-  }
-
-  @Override public boolean contains(Object target) {
+  @Override
+  public boolean contains(Object target) {
     return element.equals(target);
   }
 
-  @Override public UnmodifiableIterator<E> iterator() {
+  @Override
+  public UnmodifiableIterator<E> iterator() {
     return Iterators.singletonIterator(element);
   }
 
-  @Override boolean isPartialView() {
+  @Override
+  boolean isPartialView() {
     return false;
   }
 
@@ -80,18 +75,8 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
     return offset + 1;
   }
 
-  @Override public boolean equals(@Nullable Object object) {
-    if (object == this) {
-      return true;
-    }
-    if (object instanceof Set) {
-      Set<?> that = (Set<?>) object;
-      return that.size() == 1 && element.equals(that.iterator().next());
-    }
-    return false;
-  }
-
-  @Override public final int hashCode() {
+  @Override
+  public final int hashCode() {
     // Racy single-check.
     int code = cachedHashCode;
     if (code == 0) {
@@ -100,11 +85,13 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
     return code;
   }
 
-  @Override boolean isHashCodeFast() {
+  @Override
+  boolean isHashCodeFast() {
     return cachedHashCode != 0;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     String elementToString = element.toString();
     return new StringBuilder(elementToString.length() + 2)
         .append('[')
diff --git a/guava/src/com/google/common/collect/SingletonImmutableTable.java b/guava/src/com/google/common/collect/SingletonImmutableTable.java
index 490ece7..33e89cd 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableTable.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableTable.java
@@ -43,34 +43,36 @@ class SingletonImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
     this(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
   }
 
-  @Override public ImmutableMap<R, V> column(C columnKey) {
+  @Override
+  public ImmutableMap<R, V> column(C columnKey) {
     checkNotNull(columnKey);
     return containsColumn(columnKey)
         ? ImmutableMap.of(singleRowKey, singleValue)
         : ImmutableMap.<R, V>of();
   }
 
-  @Override public ImmutableMap<C, Map<R, V>> columnMap() {
-    return ImmutableMap.of(singleColumnKey,
-        (Map<R, V>) ImmutableMap.of(singleRowKey, singleValue));
+  @Override
+  public ImmutableMap<C, Map<R, V>> columnMap() {
+    return ImmutableMap.of(singleColumnKey, (Map<R, V>) ImmutableMap.of(singleRowKey, singleValue));
   }
 
-  @Override public ImmutableMap<R, Map<C, V>> rowMap() {
-    return ImmutableMap.of(singleRowKey,
-        (Map<C, V>) ImmutableMap.of(singleColumnKey, singleValue));
+  @Override
+  public ImmutableMap<R, Map<C, V>> rowMap() {
+    return ImmutableMap.of(singleRowKey, (Map<C, V>) ImmutableMap.of(singleColumnKey, singleValue));
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     return 1;
   }
 
   @Override
   ImmutableSet<Cell<R, C, V>> createCellSet() {
-    return ImmutableSet.of(
-        cellOf(singleRowKey, singleColumnKey, singleValue));
+    return ImmutableSet.of(cellOf(singleRowKey, singleColumnKey, singleValue));
   }
 
-  @Override ImmutableCollection<V> createValues() {
+  @Override
+  ImmutableCollection<V> createValues() {
     return ImmutableSet.of(singleValue);
   }
 }
diff --git a/guava/src/com/google/common/collect/SortedLists.java b/guava/src/com/google/common/collect/SortedLists.java
index 6fc0d71..bc7cad7 100644
--- a/guava/src/com/google/common/collect/SortedLists.java
+++ b/guava/src/com/google/common/collect/SortedLists.java
@@ -128,6 +128,7 @@ import javax.annotation.Nullable;
         return FIRST_PRESENT.resultIndex(comparator, key, list, foundIndex) - 1;
       }
     };
+
     abstract <E> int resultIndex(
         Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex);
   }
@@ -186,11 +187,13 @@ import javax.annotation.Nullable;
    * <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior,
    * KeyAbsentBehavior)} using {@link Ordering#natural}.
    */
-  public static <E extends Comparable> int binarySearch(List<? extends E> list, E e,
-      KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) {
+  public static <E extends Comparable> int binarySearch(
+      List<? extends E> list,
+      E e,
+      KeyPresentBehavior presentBehavior,
+      KeyAbsentBehavior absentBehavior) {
     checkNotNull(e);
-    return binarySearch(
-        list, checkNotNull(e), Ordering.natural(), presentBehavior, absentBehavior);
+    return binarySearch(list, e, Ordering.natural(), presentBehavior, absentBehavior);
   }
 
   /**
@@ -199,16 +202,14 @@ import javax.annotation.Nullable;
    * <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior,
    * KeyAbsentBehavior)} using {@link Ordering#natural}.
    */
-  public static <E, K extends Comparable> int binarySearch(List<E> list,
-      Function<? super E, K> keyFunction, @Nullable K key, KeyPresentBehavior presentBehavior,
+  public static <E, K extends Comparable> int binarySearch(
+      List<E> list,
+      Function<? super E, K> keyFunction,
+      @Nullable K key,
+      KeyPresentBehavior presentBehavior,
       KeyAbsentBehavior absentBehavior) {
     return binarySearch(
-        list,
-        keyFunction,
-        key,
-        Ordering.natural(),
-        presentBehavior,
-        absentBehavior);
+        list, keyFunction, key, Ordering.natural(), presentBehavior, absentBehavior);
   }
 
   /**
@@ -252,8 +253,11 @@ import javax.annotation.Nullable;
    * @return the index determined by the {@code KeyPresentBehavior}, if the key is in the list;
    *         otherwise the index determined by the {@code KeyAbsentBehavior}.
    */
-  public static <E> int binarySearch(List<? extends E> list, @Nullable E key,
-      Comparator<? super E> comparator, KeyPresentBehavior presentBehavior,
+  public static <E> int binarySearch(
+      List<? extends E> list,
+      @Nullable E key,
+      Comparator<? super E> comparator,
+      KeyPresentBehavior presentBehavior,
       KeyAbsentBehavior absentBehavior) {
     checkNotNull(comparator);
     checkNotNull(list);
@@ -262,7 +266,7 @@ import javax.annotation.Nullable;
     if (!(list instanceof RandomAccess)) {
       list = Lists.newArrayList(list);
     }
-    // TODO(user): benchmark when it's best to do a linear search
+    // TODO(lowasser): benchmark when it's best to do a linear search
 
     int lower = 0;
     int upper = list.size() - 1;
diff --git a/guava/src/com/google/common/collect/SortedMultiset.java b/guava/src/com/google/common/collect/SortedMultiset.java
index de1f3e0..8c92212 100644
--- a/guava/src/com/google/common/collect/SortedMultiset.java
+++ b/guava/src/com/google/common/collect/SortedMultiset.java
@@ -1,12 +1,12 @@
 /*
  * 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
@@ -33,16 +33,16 @@ import java.util.Set;
  * this implementation uses {@link Comparable#compareTo} or
  * {@link Comparator#compare} instead of {@link Object#equals} to determine
  * equivalence of instances.
- * 
+ *
  * <p><b>Warning:</b> The comparison must be <i>consistent with equals</i> as
  * explained by the {@link Comparable} class specification. Otherwise, the
  * resulting multiset will violate the {@link Collection} contract, which it is
  * specified in terms of {@link Object#equals}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
- * 
+ *
  * @author Louis Wasserman
  * @since 11.0
  */
@@ -81,18 +81,20 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
 
   /**
    * Returns a {@link NavigableSet} view of the distinct elements in this multiset.
-   * 
+   *
    * @since 14.0 (present with return type {@code SortedSet} since 11.0)
    */
-  @Override NavigableSet<E> elementSet();
-  
+  @Override
+  NavigableSet<E> elementSet();
+
   /**
    * {@inheritDoc}
    *
    * <p>The {@code entrySet}'s iterator returns entries in ascending element
    * order according to the this multiset's comparator.
    */
-  @Override Set<Entry<E>> entrySet();
+  @Override
+  Set<Entry<E>> entrySet();
 
   /**
    * {@inheritDoc}
@@ -100,7 +102,8 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
    * <p>The iterator returns the elements in ascending order according to this
    * multiset's comparator.
    */
-  @Override Iterator<E> iterator();
+  @Override
+  Iterator<E> iterator();
 
   /**
    * Returns a descending view of this multiset. Modifications made to either
@@ -114,7 +117,7 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
    * returned multiset is a view of this multiset, so changes to one will be
    * reflected in the other. The returned multiset supports all operations that
    * this multiset supports.
-   * 
+   *
    * <p>The returned multiset will throw an {@link IllegalArgumentException} on
    * attempts to add elements outside its range.
    */
@@ -125,16 +128,16 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
    * {@code lowerBound} and {@code upperBound}. The returned multiset is a view
    * of this multiset, so changes to one will be reflected in the other. The
    * returned multiset supports all operations that this multiset supports.
-   * 
+   *
    * <p>The returned multiset will throw an {@link IllegalArgumentException} on
    * attempts to add elements outside its range.
-   * 
+   *
    * <p>This method is equivalent to
    * {@code tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound,
    * upperBoundType)}.
    */
-  SortedMultiset<E> subMultiset(E lowerBound, BoundType lowerBoundType,
-      E upperBound, BoundType upperBoundType);
+  SortedMultiset<E> subMultiset(
+      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType);
 
   /**
    * Returns a view of this multiset restricted to the elements greater than
@@ -142,7 +145,7 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
    * returned multiset is a view of this multiset, so changes to one will be
    * reflected in the other. The returned multiset supports all operations that
    * this multiset supports.
-   * 
+   *
    * <p>The returned multiset will throw an {@link IllegalArgumentException} on
    * attempts to add elements outside its range.
    */
diff --git a/guava/src/com/google/common/collect/SortedMultisetBridge.java b/guava/src/com/google/common/collect/SortedMultisetBridge.java
index 669b54d..a2d04ed 100644
--- a/guava/src/com/google/common/collect/SortedMultisetBridge.java
+++ b/guava/src/com/google/common/collect/SortedMultisetBridge.java
@@ -22,7 +22,7 @@ import java.util.SortedSet;
  * Superinterface of {@link SortedMultiset} to introduce a bridge method for
  * {@code elementSet()}, to ensure binary compatibility with older Guava versions
  * that specified {@code elementSet()} to return {@code SortedSet}.
- * 
+ *
  * @author Louis Wasserman
  */
 interface SortedMultisetBridge<E> extends Multiset<E> {
diff --git a/guava/src/com/google/common/collect/SortedMultisets.java b/guava/src/com/google/common/collect/SortedMultisets.java
index 1055664..b0695a2 100644
--- a/guava/src/com/google/common/collect/SortedMultisets.java
+++ b/guava/src/com/google/common/collect/SortedMultisets.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.BoundType.OPEN;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.collect.Multiset.Entry;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.Comparator;
 import java.util.Iterator;
@@ -39,45 +40,50 @@ import javax.annotation.Nullable;
  */
 @GwtCompatible(emulated = true)
 final class SortedMultisets {
-  private SortedMultisets() {
-  }
+  private SortedMultisets() {}
 
   /**
    * A skeleton implementation for {@link SortedMultiset#elementSet}.
    */
-  static class ElementSet<E> extends Multisets.ElementSet<E> implements
-      SortedSet<E> {
-    private final SortedMultiset<E> multiset;
+  static class ElementSet<E> extends Multisets.ElementSet<E> implements SortedSet<E> {
+    @Weak private final SortedMultiset<E> multiset;
 
     ElementSet(SortedMultiset<E> multiset) {
       this.multiset = multiset;
     }
 
-    @Override final SortedMultiset<E> multiset() {
+    @Override
+    final SortedMultiset<E> multiset() {
       return multiset;
     }
 
-    @Override public Comparator<? super E> comparator() {
+    @Override
+    public Comparator<? super E> comparator() {
       return multiset().comparator();
     }
 
-    @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+    @Override
+    public SortedSet<E> subSet(E fromElement, E toElement) {
       return multiset().subMultiset(fromElement, CLOSED, toElement, OPEN).elementSet();
     }
 
-    @Override public SortedSet<E> headSet(E toElement) {
+    @Override
+    public SortedSet<E> headSet(E toElement) {
       return multiset().headMultiset(toElement, OPEN).elementSet();
     }
 
-    @Override public SortedSet<E> tailSet(E fromElement) {
+    @Override
+    public SortedSet<E> tailSet(E fromElement) {
       return multiset().tailMultiset(fromElement, CLOSED).elementSet();
     }
 
-    @Override public E first() {
+    @Override
+    public E first() {
       return getElementOrThrow(multiset().firstEntry());
     }
 
-    @Override public E last() {
+    @Override
+    public E last() {
       return getElementOrThrow(multiset().lastEntry());
     }
   }
@@ -134,9 +140,10 @@ final class SortedMultisets {
     @Override
     public NavigableSet<E> subSet(
         E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
-      return new NavigableElementSet<E>(multiset().subMultiset(
-          fromElement, BoundType.forBoolean(fromInclusive),
-          toElement, BoundType.forBoolean(toInclusive)));
+      return new NavigableElementSet<E>(
+          multiset().subMultiset(
+              fromElement, BoundType.forBoolean(fromInclusive),
+              toElement, BoundType.forBoolean(toInclusive)));
     }
 
     @Override
diff --git a/guava/src/com/google/common/collect/SortedSetMultimap.java b/guava/src/com/google/common/collect/SortedSetMultimap.java
index 8077618..436ca5d 100644
--- a/guava/src/com/google/common/collect/SortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/SortedSetMultimap.java
@@ -39,13 +39,13 @@ import javax.annotation.Nullable;
  * returns a {@link Set} of map entries. Though the method signature doesn't say
  * so explicitly, the map returned by {@link #asMap} has {@code SortedSet}
  * values.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
@@ -105,7 +105,8 @@ public interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
    * {@code Map<K, SortedSet<V>>}, call
    * {@link Multimaps#asMap(SortedSetMultimap)} instead.
    */
-  @Override Map<K, Collection<V>> asMap();
+  @Override
+  Map<K, Collection<V>> asMap();
 
   /**
    * Returns the comparator that orders the multimap values, with {@code null}
diff --git a/guava/src/com/google/common/collect/SparseImmutableTable.java b/guava/src/com/google/common/collect/SparseImmutableTable.java
index 7be096b..deebd11 100644
--- a/guava/src/com/google/common/collect/SparseImmutableTable.java
+++ b/guava/src/com/google/common/collect/SparseImmutableTable.java
@@ -26,20 +26,20 @@ import javax.annotation.concurrent.Immutable;
  */
 @GwtCompatible
 @Immutable
-final class SparseImmutableTable<R, C, V>
-    extends RegularImmutableTable<R, C, V> {
+final class SparseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> {
 
   private final ImmutableMap<R, Map<C, V>> rowMap;
   private final ImmutableMap<C, Map<R, V>> columnMap;
   private final int[] iterationOrderRow;
   private final int[] iterationOrderColumn;
 
-  SparseImmutableTable(ImmutableList<Cell<R, C, V>> cellList,
-      ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
-    Map<R, Integer> rowIndex = Maps.newHashMap();
+  SparseImmutableTable(
+      ImmutableList<Cell<R, C, V>> cellList,
+      ImmutableSet<R> rowSpace,
+      ImmutableSet<C> columnSpace) {
+    Map<R, Integer> rowIndex = Maps.indexMap(rowSpace);
     Map<R, Map<C, V>> rows = Maps.newLinkedHashMap();
     for (R row : rowSpace) {
-      rowIndex.put(row, rows.size());
       rows.put(row, new LinkedHashMap<C, V>());
     }
     Map<C, Map<R, V>> columns = Maps.newLinkedHashMap();
@@ -53,37 +53,42 @@ final class SparseImmutableTable<R, C, V>
       R rowKey = cell.getRowKey();
       C columnKey = cell.getColumnKey();
       V value = cell.getValue();
-      
+
       iterationOrderRow[i] = rowIndex.get(rowKey);
       Map<C, V> thisRow = rows.get(rowKey);
       iterationOrderColumn[i] = thisRow.size();
       V oldValue = thisRow.put(columnKey, value);
       if (oldValue != null) {
-        throw new IllegalArgumentException("Duplicate value for row=" + rowKey + ", column="
-            + columnKey + ": " + value + ", " + oldValue);
+        throw new IllegalArgumentException(
+            "Duplicate value for row=" + rowKey + ", column=" + columnKey + ": "
+                + value + ", " + oldValue);
       }
       columns.get(columnKey).put(rowKey, value);
     }
     this.iterationOrderRow = iterationOrderRow;
     this.iterationOrderColumn = iterationOrderColumn;
-    ImmutableMap.Builder<R, Map<C, V>> rowBuilder = ImmutableMap.builder();
+    ImmutableMap.Builder<R, Map<C, V>> rowBuilder =
+        new ImmutableMap.Builder<R, Map<C, V>>(rows.size());
     for (Map.Entry<R, Map<C, V>> row : rows.entrySet()) {
       rowBuilder.put(row.getKey(), ImmutableMap.copyOf(row.getValue()));
     }
     this.rowMap = rowBuilder.build();
-    
-    ImmutableMap.Builder<C, Map<R, V>> columnBuilder = ImmutableMap.builder();
+
+    ImmutableMap.Builder<C, Map<R, V>> columnBuilder =
+        new ImmutableMap.Builder<C, Map<R, V>>(columns.size());
     for (Map.Entry<C, Map<R, V>> col : columns.entrySet()) {
       columnBuilder.put(col.getKey(), ImmutableMap.copyOf(col.getValue()));
     }
     this.columnMap = columnBuilder.build();
   }
 
-  @Override public ImmutableMap<C, Map<R, V>> columnMap() {
+  @Override
+  public ImmutableMap<C, Map<R, V>> columnMap() {
     return columnMap;
   }
 
-  @Override public ImmutableMap<R, Map<C, V>> rowMap() {
+  @Override
+  public ImmutableMap<R, Map<C, V>> rowMap() {
     return rowMap;
   }
 
@@ -91,7 +96,7 @@ final class SparseImmutableTable<R, C, V>
   public int size() {
     return iterationOrderRow.length;
   }
-  
+
   @Override
   Cell<R, C, V> getCell(int index) {
     int rowIndex = iterationOrderRow[index];
diff --git a/guava/src/com/google/common/collect/StandardRowSortedTable.java b/guava/src/com/google/common/collect/StandardRowSortedTable.java
index eaaf002..54bd03c 100644
--- a/guava/src/com/google/common/collect/StandardRowSortedTable.java
+++ b/guava/src/com/google/common/collect/StandardRowSortedTable.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Supplier;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Comparator;
 import java.util.Map;
@@ -54,8 +55,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
    * RowSortedTable subinterface with the revised methods?
    */
 
-  StandardRowSortedTable(SortedMap<R, Map<C, V>> backingMap,
-      Supplier<? extends Map<C, V>> factory) {
+  StandardRowSortedTable(
+      SortedMap<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
     super(backingMap, factory);
   }
 
@@ -69,7 +70,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
    * <p>This method returns a {@link SortedSet}, instead of the {@code Set}
    * specified in the {@link Table} interface.
    */
-  @Override public SortedSet<R> rowKeySet() {
+  @Override
+  public SortedSet<R> rowKeySet() {
     return (SortedSet<R>) rowMap().keySet();
   }
 
@@ -79,7 +81,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
    * <p>This method returns a {@link SortedMap}, instead of the {@code Map}
    * specified in the {@link Table} interface.
    */
-  @Override public SortedMap<R, Map<C, V>> rowMap() {
+  @Override
+  public SortedMap<R, Map<C, V>> rowMap() {
     return (SortedMap<R, Map<C, V>>) super.rowMap();
   }
 
@@ -88,6 +91,7 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
     return new RowSortedMap();
   }
 
+  @WeakOuter
   private class RowSortedMap extends RowMap implements SortedMap<R, Map<C, V>> {
     @Override
     public SortedSet<R> keySet() {
@@ -117,23 +121,23 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
     @Override
     public SortedMap<R, Map<C, V>> headMap(R toKey) {
       checkNotNull(toKey);
-      return new StandardRowSortedTable<R, C, V>(
-          sortedBackingMap().headMap(toKey), factory).rowMap();
+      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().headMap(toKey), factory)
+          .rowMap();
     }
 
     @Override
     public SortedMap<R, Map<C, V>> subMap(R fromKey, R toKey) {
       checkNotNull(fromKey);
       checkNotNull(toKey);
-      return new StandardRowSortedTable<R, C, V>(
-          sortedBackingMap().subMap(fromKey, toKey), factory).rowMap();
+      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().subMap(fromKey, toKey), factory)
+          .rowMap();
     }
 
     @Override
     public SortedMap<R, Map<C, V>> tailMap(R fromKey) {
       checkNotNull(fromKey);
-      return new StandardRowSortedTable<R, C, V>(
-          sortedBackingMap().tailMap(fromKey), factory).rowMap();
+      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().tailMap(fromKey), factory)
+          .rowMap();
     }
   }
 
diff --git a/guava/src/com/google/common/collect/StandardTable.java b/guava/src/com/google/common/collect/StandardTable.java
index 06aa37d..6d7d751 100644
--- a/guava/src/com/google/common/collect/StandardTable.java
+++ b/guava/src/com/google/common/collect/StandardTable.java
@@ -28,8 +28,10 @@ import com.google.common.annotations.GwtCompatible;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
 import com.google.common.collect.Sets.ImprovedAbstractSet;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.io.Serializable;
 import java.util.Collection;
@@ -68,20 +70,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
   @GwtTransient final Map<R, Map<C, V>> backingMap;
   @GwtTransient final Supplier<? extends Map<C, V>> factory;
 
-  StandardTable(Map<R, Map<C, V>> backingMap,
-      Supplier<? extends Map<C, V>> factory) {
+  StandardTable(Map<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
     this.backingMap = backingMap;
     this.factory = factory;
   }
 
   // Accessors
 
-  @Override public boolean contains(
-      @Nullable Object rowKey, @Nullable Object columnKey) {
+  @Override
+  public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
     return rowKey != null && columnKey != null && super.contains(rowKey, columnKey);
   }
 
-  @Override public boolean containsColumn(@Nullable Object columnKey) {
+  @Override
+  public boolean containsColumn(@Nullable Object columnKey) {
     if (columnKey == null) {
       return false;
     }
@@ -93,25 +95,28 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     return false;
   }
 
-  @Override public boolean containsRow(@Nullable Object rowKey) {
+  @Override
+  public boolean containsRow(@Nullable Object rowKey) {
     return rowKey != null && safeContainsKey(backingMap, rowKey);
   }
 
-  @Override public boolean containsValue(@Nullable Object value) {
+  @Override
+  public boolean containsValue(@Nullable Object value) {
     return value != null && super.containsValue(value);
   }
 
-  @Override public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
-    return (rowKey == null || columnKey == null)
-        ? null
-        : super.get(rowKey, columnKey);
+  @Override
+  public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
+    return (rowKey == null || columnKey == null) ? null : super.get(rowKey, columnKey);
   }
 
-  @Override public boolean isEmpty() {
+  @Override
+  public boolean isEmpty() {
     return backingMap.isEmpty();
   }
 
-  @Override public int size() {
+  @Override
+  public int size() {
     int size = 0;
     for (Map<C, V> map : backingMap.values()) {
       size += map.size();
@@ -121,7 +126,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
 
   // Mutators
 
-  @Override public void clear() {
+  @Override
+  public void clear() {
     backingMap.clear();
   }
 
@@ -134,15 +140,16 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     return map;
   }
 
-  @Override public V put(R rowKey, C columnKey, V value) {
+  @Override
+  public V put(R rowKey, C columnKey, V value) {
     checkNotNull(rowKey);
     checkNotNull(columnKey);
     checkNotNull(value);
     return getOrCreate(rowKey).put(columnKey, value);
   }
 
-  @Override public V remove(
-      @Nullable Object rowKey, @Nullable Object columnKey) {
+  @Override
+  public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
     if ((rowKey == null) || (columnKey == null)) {
       return null;
     }
@@ -159,8 +166,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
 
   private Map<R, V> removeColumn(Object column) {
     Map<R, V> output = new LinkedHashMap<R, V>();
-    Iterator<Entry<R, Map<C, V>>> iterator
-        = backingMap.entrySet().iterator();
+    Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
     while (iterator.hasNext()) {
       Entry<R, Map<C, V>> entry = iterator.next();
       V value = entry.getValue().remove(column);
@@ -174,8 +180,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     return output;
   }
 
-  private boolean containsMapping(
-      Object rowKey, Object columnKey, Object value) {
+  private boolean containsMapping(Object rowKey, Object columnKey, Object value) {
     return value != null && value.equals(get(rowKey, columnKey));
   }
 
@@ -194,12 +199,15 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
    * Abstract set whose {@code isEmpty()} returns whether the table is empty and
    * whose {@code clear()} clears all table mappings.
    */
+  @WeakOuter
   private abstract class TableSet<T> extends ImprovedAbstractSet<T> {
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return backingMap.isEmpty();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       backingMap.clear();
     }
   }
@@ -214,36 +222,38 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
    * mapping, taken at the time the cell is returned by a method call to the
    * set or its iterator.
    */
-  @Override public Set<Cell<R, C, V>> cellSet() {
+  @Override
+  public Set<Cell<R, C, V>> cellSet() {
     return super.cellSet();
   }
 
-  @Override Iterator<Cell<R, C, V>> cellIterator() {
+  @Override
+  Iterator<Cell<R, C, V>> cellIterator() {
     return new CellIterator();
   }
 
   private class CellIterator implements Iterator<Cell<R, C, V>> {
-    final Iterator<Entry<R, Map<C, V>>> rowIterator
-        = backingMap.entrySet().iterator();
+    final Iterator<Entry<R, Map<C, V>>> rowIterator = backingMap.entrySet().iterator();
     Entry<R, Map<C, V>> rowEntry;
-    Iterator<Entry<C, V>> columnIterator
-        = Iterators.emptyModifiableIterator();
+    Iterator<Entry<C, V>> columnIterator = Iterators.emptyModifiableIterator();
 
-    @Override public boolean hasNext() {
+    @Override
+    public boolean hasNext() {
       return rowIterator.hasNext() || columnIterator.hasNext();
     }
 
-    @Override public Cell<R, C, V> next() {
+    @Override
+    public Cell<R, C, V> next() {
       if (!columnIterator.hasNext()) {
         rowEntry = rowIterator.next();
         columnIterator = rowEntry.getValue().entrySet().iterator();
       }
       Entry<C, V> columnEntry = columnIterator.next();
-      return Tables.immutableCell(
-          rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
+      return Tables.immutableCell(rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
     }
 
-    @Override public void remove() {
+    @Override
+    public void remove() {
       columnIterator.remove();
       if (rowEntry.getValue().isEmpty()) {
         rowIterator.remove();
@@ -251,11 +261,12 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     }
   }
 
-  @Override public Map<C, V> row(R rowKey) {
+  @Override
+  public Map<C, V> row(R rowKey) {
     return new Row(rowKey);
   }
 
-  class Row extends ImprovedAbstractMap<C, V> {
+  class Row extends IteratorBasedAbstractMap<C, V> {
     final R rowKey;
 
     Row(R rowKey) {
@@ -265,8 +276,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     Map<C, V> backingRowMap;
 
     Map<C, V> backingRowMap() {
-      return (backingRowMap == null
-              || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
+      return (backingRowMap == null || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
           ? backingRowMap = computeBackingRowMap()
           : backingRowMap;
     }
@@ -286,16 +296,13 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     @Override
     public boolean containsKey(Object key) {
       Map<C, V> backingRowMap = backingRowMap();
-      return (key != null && backingRowMap != null)
-          && Maps.safeContainsKey(backingRowMap, key);
+      return (key != null && backingRowMap != null) && Maps.safeContainsKey(backingRowMap, key);
     }
 
     @Override
     public V get(Object key) {
       Map<C, V> backingRowMap = backingRowMap();
-      return (key != null && backingRowMap != null)
-          ? Maps.safeGet(backingRowMap, key)
-          : null;
+      return (key != null && backingRowMap != null) ? Maps.safeGet(backingRowMap, key) : null;
     }
 
     @Override
@@ -329,57 +336,52 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     }
 
     @Override
-    protected Set<Entry<C, V>> createEntrySet() {
-      return new RowEntrySet();
+    public int size() {
+      Map<C, V> map = backingRowMap();
+      return (map == null) ? 0 : map.size();
     }
 
-    private final class RowEntrySet extends Maps.EntrySet<C, V> {
-      @Override
-      Map<C, V> map() {
-        return Row.this;
-      }
-
-      @Override
-      public int size() {
-        Map<C, V> map = backingRowMap();
-        return (map == null) ? 0 : map.size();
-      }
+    @Override
+    Iterator<Entry<C, V>> entryIterator() {
+      final Map<C, V> map = backingRowMap();
+      if (map == null) {
+        return Iterators.emptyModifiableIterator();
+      }
+      final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
+      return new Iterator<Entry<C, V>>() {
+        @Override
+        public boolean hasNext() {
+          return iterator.hasNext();
+        }
 
-      @Override
-      public Iterator<Entry<C, V>> iterator() {
-        final Map<C, V> map = backingRowMap();
-        if (map == null) {
-          return Iterators.emptyModifiableIterator();
+        @Override
+        public Entry<C, V> next() {
+          final Entry<C, V> entry = iterator.next();
+          return new ForwardingMapEntry<C, V>() {
+            @Override
+            protected Entry<C, V> delegate() {
+              return entry;
+            }
+
+            @Override
+            public V setValue(V value) {
+              return super.setValue(checkNotNull(value));
+            }
+
+            @Override
+            public boolean equals(Object object) {
+              // TODO(lowasser): identify why this affects GWT tests
+              return standardEquals(object);
+            }
+          };
         }
-        final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
-        return new Iterator<Entry<C, V>>() {
-          @Override public boolean hasNext() {
-            return iterator.hasNext();
-          }
-          @Override public Entry<C, V> next() {
-            final Entry<C, V> entry = iterator.next();
-            return new ForwardingMapEntry<C, V>() {
-              @Override protected Entry<C, V> delegate() {
-                return entry;
-              }
-              @Override public V setValue(V value) {
-                return super.setValue(checkNotNull(value));
-              }
-              @Override
-              public boolean equals(Object object) {
-                // TODO(user): identify why this affects GWT tests
-                return standardEquals(object);
-              }
-            };
-          }
 
-          @Override
-          public void remove() {
-            iterator.remove();
-            maintainEmptyInvariant();
-          }
-        };
-      }
+        @Override
+        public void remove() {
+          iterator.remove();
+          maintainEmptyInvariant();
+        }
+      };
     }
   }
 
@@ -389,30 +391,35 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
    * <p>The returned map's views have iterators that don't support
    * {@code remove()}.
    */
-  @Override public Map<R, V> column(C columnKey) {
+  @Override
+  public Map<R, V> column(C columnKey) {
     return new Column(columnKey);
   }
 
-  private class Column extends ImprovedAbstractMap<R, V> {
+  private class Column extends ViewCachingAbstractMap<R, V> {
     final C columnKey;
 
     Column(C columnKey) {
       this.columnKey = checkNotNull(columnKey);
     }
 
-    @Override public V put(R key, V value) {
+    @Override
+    public V put(R key, V value) {
       return StandardTable.this.put(key, columnKey, value);
     }
 
-    @Override public V get(Object key) {
+    @Override
+    public V get(Object key) {
       return StandardTable.this.get(key, columnKey);
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return StandardTable.this.contains(key, columnKey);
     }
 
-    @Override public V remove(Object key) {
+    @Override
+    public V remove(Object key) {
       return StandardTable.this.remove(key, columnKey);
     }
 
@@ -422,14 +429,12 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
      */
     boolean removeFromColumnIf(Predicate<? super Entry<R, V>> predicate) {
       boolean changed = false;
-      Iterator<Entry<R, Map<C, V>>> iterator
-          = backingMap.entrySet().iterator();
+      Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
       while (iterator.hasNext()) {
         Entry<R, Map<C, V>> entry = iterator.next();
         Map<C, V> map = entry.getValue();
         V value = map.get(columnKey);
-        if (value != null
-            && predicate.apply(Maps.immutableEntry(entry.getKey(), value))) {
+        if (value != null && predicate.apply(Maps.immutableEntry(entry.getKey(), value))) {
           map.remove(columnKey);
           changed = true;
           if (map.isEmpty()) {
@@ -440,16 +445,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       return changed;
     }
 
-    @Override Set<Entry<R, V>> createEntrySet() {
+    @Override
+    Set<Entry<R, V>> createEntrySet() {
       return new EntrySet();
     }
 
+    @WeakOuter
     private class EntrySet extends ImprovedAbstractSet<Entry<R, V>> {
-      @Override public Iterator<Entry<R, V>> iterator() {
+      @Override
+      public Iterator<Entry<R, V>> iterator() {
         return new EntrySetIterator();
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         int size = 0;
         for (Map<C, V> map : backingMap.values()) {
           if (map.containsKey(columnKey)) {
@@ -459,15 +468,18 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return size;
       }
 
-      @Override public boolean isEmpty() {
+      @Override
+      public boolean isEmpty() {
         return !containsColumn(columnKey);
       }
 
-      @Override public void clear() {
+      @Override
+      public void clear() {
         removeFromColumnIf(alwaysTrue());
       }
 
-      @Override public boolean contains(Object o) {
+      @Override
+      public boolean contains(Object o) {
         if (o instanceof Entry) {
           Entry<?, ?> entry = (Entry<?, ?>) o;
           return containsMapping(entry.getKey(), columnKey, entry.getValue());
@@ -475,7 +487,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         if (obj instanceof Entry) {
           Entry<?, ?> entry = (Entry<?, ?>) obj;
           return removeMapping(entry.getKey(), columnKey, entry.getValue());
@@ -483,53 +496,67 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean retainAll(Collection<?> c) {
+      @Override
+      public boolean retainAll(Collection<?> c) {
         return removeFromColumnIf(not(in(c)));
       }
     }
 
     private class EntrySetIterator extends AbstractIterator<Entry<R, V>> {
-      final Iterator<Entry<R, Map<C, V>>> iterator
-          = backingMap.entrySet().iterator();
-      @Override protected Entry<R, V> computeNext() {
+      final Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
+
+      @Override
+      protected Entry<R, V> computeNext() {
         while (iterator.hasNext()) {
           final Entry<R, Map<C, V>> entry = iterator.next();
           if (entry.getValue().containsKey(columnKey)) {
-            return new AbstractMapEntry<R, V>() {
-              @Override public R getKey() {
+            @WeakOuter
+            class EntryImpl extends AbstractMapEntry<R, V> {
+              @Override
+              public R getKey() {
                 return entry.getKey();
               }
-              @Override public V getValue() {
+
+              @Override
+              public V getValue() {
                 return entry.getValue().get(columnKey);
               }
-              @Override public V setValue(V value) {
+
+              @Override
+              public V setValue(V value) {
                 return entry.getValue().put(columnKey, checkNotNull(value));
               }
-            };
+            }
+            return new EntryImpl();
           }
         }
         return endOfData();
       }
     }
 
-    @Override Set<R> createKeySet() {
+    @Override
+    Set<R> createKeySet() {
       return new KeySet();
     }
 
+    @WeakOuter
     private class KeySet extends Maps.KeySet<R, V> {
       KeySet() {
         super(Column.this);
       }
 
-      @Override public boolean contains(Object obj) {
+      @Override
+      public boolean contains(Object obj) {
         return StandardTable.this.contains(obj, columnKey);
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         return StandardTable.this.remove(obj, columnKey) != null;
       }
 
-      @Override public boolean retainAll(final Collection<?> c) {
+      @Override
+      public boolean retainAll(final Collection<?> c) {
         return removeFromColumnIf(Maps.<R>keyPredicateOnEntries(not(in(c))));
       }
     }
@@ -539,26 +566,31 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       return new Values();
     }
 
+    @WeakOuter
     private class Values extends Maps.Values<R, V> {
       Values() {
         super(Column.this);
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         return obj != null && removeFromColumnIf(Maps.<V>valuePredicateOnEntries(equalTo(obj)));
       }
 
-      @Override public boolean removeAll(final Collection<?> c) {
+      @Override
+      public boolean removeAll(final Collection<?> c) {
         return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(in(c)));
       }
 
-      @Override public boolean retainAll(final Collection<?> c) {
+      @Override
+      public boolean retainAll(final Collection<?> c) {
         return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(not(in(c))));
       }
     }
   }
 
-  @Override public Set<R> rowKeySet() {
+  @Override
+  public Set<R> rowKeySet() {
     return rowMap().keySet();
   }
 
@@ -579,16 +611,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     return (result == null) ? columnKeySet = new ColumnKeySet() : result;
   }
 
+  @WeakOuter
   private class ColumnKeySet extends TableSet<C> {
-    @Override public Iterator<C> iterator() {
+    @Override
+    public Iterator<C> iterator() {
       return createColumnKeyIterator();
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return Iterators.size(iterator());
     }
 
-    @Override public boolean remove(Object obj) {
+    @Override
+    public boolean remove(Object obj) {
       if (obj == null) {
         return false;
       }
@@ -606,7 +642,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       return changed;
     }
 
-    @Override public boolean removeAll(Collection<?> c) {
+    @Override
+    public boolean removeAll(Collection<?> c) {
       checkNotNull(c);
       boolean changed = false;
       Iterator<Map<C, V>> iterator = backingMap.values().iterator();
@@ -624,7 +661,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       return changed;
     }
 
-    @Override public boolean retainAll(Collection<?> c) {
+    @Override
+    public boolean retainAll(Collection<?> c) {
       checkNotNull(c);
       boolean changed = false;
       Iterator<Map<C, V>> iterator = backingMap.values().iterator();
@@ -640,7 +678,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       return changed;
     }
 
-    @Override public boolean contains(Object obj) {
+    @Override
+    public boolean contains(Object obj) {
       return containsColumn(obj);
     }
   }
@@ -660,7 +699,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     final Iterator<Map<C, V>> mapIterator = backingMap.values().iterator();
     Iterator<Entry<C, V>> entryIterator = Iterators.emptyIterator();
 
-    @Override protected C computeNext() {
+    @Override
+    protected C computeNext() {
       while (true) {
         if (entryIterator.hasNext()) {
           Entry<C, V> entry = entryIterator.next();
@@ -683,13 +723,15 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
    * <p>The collection's iterator traverses the values for the first row,
    * the values for the second row, and so on.
    */
-  @Override public Collection<V> values() {
+  @Override
+  public Collection<V> values() {
     return super.values();
   }
 
   private transient Map<R, Map<C, V>> rowMap;
 
-  @Override public Map<R, Map<C, V>> rowMap() {
+  @Override
+  public Map<R, Map<C, V>> rowMap() {
     Map<R, Map<C, V>> result = rowMap;
     return (result == null) ? rowMap = createRowMap() : result;
   }
@@ -698,40 +740,51 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
     return new RowMap();
   }
 
-  class RowMap extends ImprovedAbstractMap<R, Map<C, V>> {
-    @Override public boolean containsKey(Object key) {
+  @WeakOuter
+  class RowMap extends ViewCachingAbstractMap<R, Map<C, V>> {
+    @Override
+    public boolean containsKey(Object key) {
       return containsRow(key);
     }
 
     // performing cast only when key is in backing map and has the correct type
     @SuppressWarnings("unchecked")
-    @Override public Map<C, V> get(Object key) {
+    @Override
+    public Map<C, V> get(Object key) {
       return containsRow(key) ? row((R) key) : null;
     }
 
-    @Override public Map<C, V> remove(Object key) {
+    @Override
+    public Map<C, V> remove(Object key) {
       return (key == null) ? null : backingMap.remove(key);
     }
 
-    @Override protected Set<Entry<R, Map<C, V>>> createEntrySet() {
+    @Override
+    protected Set<Entry<R, Map<C, V>>> createEntrySet() {
       return new EntrySet();
     }
 
+    @WeakOuter
     class EntrySet extends TableSet<Entry<R, Map<C, V>>> {
-      @Override public Iterator<Entry<R, Map<C, V>>> iterator() {
-        return Maps.asMapEntryIterator(backingMap.keySet(), new Function<R, Map<C, V>>() {
-          @Override
-          public Map<C, V> apply(R rowKey) {
-            return row(rowKey);
-          }
-        });
+      @Override
+      public Iterator<Entry<R, Map<C, V>>> iterator() {
+        return Maps.asMapEntryIterator(
+            backingMap.keySet(),
+            new Function<R, Map<C, V>>() {
+              @Override
+              public Map<C, V> apply(R rowKey) {
+                return row(rowKey);
+              }
+            });
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         return backingMap.size();
       }
 
-      @Override public boolean contains(Object obj) {
+      @Override
+      public boolean contains(Object obj) {
         if (obj instanceof Entry) {
           Entry<?, ?> entry = (Entry<?, ?>) obj;
           return entry.getKey() != null
@@ -741,7 +794,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         if (obj instanceof Entry) {
           Entry<?, ?> entry = (Entry<?, ?>) obj;
           return entry.getKey() != null
@@ -755,54 +809,68 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
 
   private transient ColumnMap columnMap;
 
-  @Override public Map<C, Map<R, V>> columnMap() {
+  @Override
+  public Map<C, Map<R, V>> columnMap() {
     ColumnMap result = columnMap;
     return (result == null) ? columnMap = new ColumnMap() : result;
   }
 
-  private class ColumnMap extends ImprovedAbstractMap<C, Map<R, V>> {
+  @WeakOuter
+  private class ColumnMap extends ViewCachingAbstractMap<C, Map<R, V>> {
     // The cast to C occurs only when the key is in the map, implying that it
     // has the correct type.
     @SuppressWarnings("unchecked")
-    @Override public Map<R, V> get(Object key) {
+    @Override
+    public Map<R, V> get(Object key) {
       return containsColumn(key) ? column((C) key) : null;
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return containsColumn(key);
     }
 
-    @Override public Map<R, V> remove(Object key) {
+    @Override
+    public Map<R, V> remove(Object key) {
       return containsColumn(key) ? removeColumn(key) : null;
     }
 
-    @Override public Set<Entry<C, Map<R, V>>> createEntrySet() {
+    @Override
+    public Set<Entry<C, Map<R, V>>> createEntrySet() {
       return new ColumnMapEntrySet();
     }
 
-    @Override public Set<C> keySet() {
+    @Override
+    public Set<C> keySet() {
       return columnKeySet();
     }
 
-    @Override Collection<Map<R, V>> createValues() {
+    @Override
+    Collection<Map<R, V>> createValues() {
       return new ColumnMapValues();
     }
 
+    @WeakOuter
     class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> {
-      @Override public Iterator<Entry<C, Map<R, V>>> iterator() {
-        return Maps.asMapEntryIterator(columnKeySet(), new Function<C, Map<R, V>>() {
-          @Override
-          public Map<R, V> apply(C columnKey) {
-            return column(columnKey);
-          }
-        });
+      @Override
+      public Iterator<Entry<C, Map<R, V>>> iterator() {
+        return Maps.asMapEntryIterator(
+            columnKeySet(),
+            new Function<C, Map<R, V>>() {
+              @Override
+              public Map<R, V> apply(C columnKey) {
+                return column(columnKey);
+              }
+            });
       }
 
-      @Override public int size() {
+      @Override
+      public int size() {
         return columnKeySet().size();
       }
 
-      @Override public boolean contains(Object obj) {
+      @Override
+      public boolean contains(Object obj) {
         if (obj instanceof Entry) {
           Entry<?, ?> entry = (Entry<?, ?>) obj;
           if (containsColumn(entry.getKey())) {
@@ -816,7 +884,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         if (contains(obj)) {
           Entry<?, ?> entry = (Entry<?, ?>) obj;
           removeColumn(entry.getKey());
@@ -825,7 +894,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean removeAll(Collection<?> c) {
+      @Override
+      public boolean removeAll(Collection<?> c) {
         /*
          * We can't inherit the normal implementation (which calls
          * Sets.removeAllImpl(Set, *Collection*) because, under some
@@ -836,7 +906,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return Sets.removeAllImpl(this, c.iterator());
       }
 
-      @Override public boolean retainAll(Collection<?> c) {
+      @Override
+      public boolean retainAll(Collection<?> c) {
         checkNotNull(c);
         boolean changed = false;
         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
@@ -849,12 +920,14 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
       }
     }
 
+    @WeakOuter
     private class ColumnMapValues extends Maps.Values<C, Map<R, V>> {
       ColumnMapValues() {
         super(ColumnMap.this);
       }
 
-      @Override public boolean remove(Object obj) {
+      @Override
+      public boolean remove(Object obj) {
         for (Entry<C, Map<R, V>> entry : ColumnMap.this.entrySet()) {
           if (entry.getValue().equals(obj)) {
             removeColumn(entry.getKey());
@@ -864,7 +937,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return false;
       }
 
-      @Override public boolean removeAll(Collection<?> c) {
+      @Override
+      public boolean removeAll(Collection<?> c) {
         checkNotNull(c);
         boolean changed = false;
         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
@@ -876,7 +950,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
         return changed;
       }
 
-      @Override public boolean retainAll(Collection<?> c) {
+      @Override
+      public boolean retainAll(Collection<?> c) {
         checkNotNull(c);
         boolean changed = false;
         for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
diff --git a/guava/src/com/google/common/collect/Synchronized.java b/guava/src/com/google/common/collect/Synchronized.java
index f8633bd..29c43ef 100644
--- a/guava/src/com/google/common/collect/Synchronized.java
+++ b/guava/src/com/google/common/collect/Synchronized.java
@@ -75,7 +75,8 @@ final class Synchronized {
 
     // No equals and hashCode; see ForwardingObject for details.
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       synchronized (mutex) {
         return delegate.toString();
       }
@@ -97,20 +98,19 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static <E> Collection<E> collection(
-      Collection<E> collection, @Nullable Object mutex) {
+  private static <E> Collection<E> collection(Collection<E> collection, @Nullable Object mutex) {
     return new SynchronizedCollection<E>(collection, mutex);
   }
 
-  @VisibleForTesting static class SynchronizedCollection<E>
-      extends SynchronizedObject implements Collection<E> {
-    private SynchronizedCollection(
-        Collection<E> delegate, @Nullable Object mutex) {
+  @VisibleForTesting
+  static class SynchronizedCollection<E> extends SynchronizedObject implements Collection<E> {
+    private SynchronizedCollection(Collection<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
     @SuppressWarnings("unchecked")
-    @Override Collection<E> delegate() {
+    @Override
+    Collection<E> delegate() {
       return (Collection<E>) super.delegate();
     }
 
@@ -206,22 +206,24 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  @VisibleForTesting static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
+  @VisibleForTesting
+  static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
     return new SynchronizedSet<E>(set, mutex);
   }
 
-  static class SynchronizedSet<E>
-      extends SynchronizedCollection<E> implements Set<E> {
+  static class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {
 
     SynchronizedSet(Set<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override Set<E> delegate() {
+    @Override
+    Set<E> delegate() {
       return (Set<E>) super.delegate();
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -230,7 +232,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -239,18 +242,17 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static <E> SortedSet<E> sortedSet(
-      SortedSet<E> set, @Nullable Object mutex) {
+  private static <E> SortedSet<E> sortedSet(SortedSet<E> set, @Nullable Object mutex) {
     return new SynchronizedSortedSet<E>(set, mutex);
   }
 
-  static class SynchronizedSortedSet<E> extends SynchronizedSet<E>
-      implements SortedSet<E> {
+  static class SynchronizedSortedSet<E> extends SynchronizedSet<E> implements SortedSet<E> {
     SynchronizedSortedSet(SortedSet<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override SortedSet<E> delegate() {
+    @Override
+    SortedSet<E> delegate() {
       return (SortedSet<E>) super.delegate();
     }
 
@@ -305,13 +307,13 @@ final class Synchronized {
         : new SynchronizedList<E>(list, mutex);
   }
 
-  private static class SynchronizedList<E> extends SynchronizedCollection<E>
-      implements List<E> {
+  private static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
     SynchronizedList(List<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override List<E> delegate() {
+    @Override
+    List<E> delegate() {
       return (List<E>) super.delegate();
     }
 
@@ -381,7 +383,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -390,7 +393,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -399,18 +403,17 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedRandomAccessList<E>
-      extends SynchronizedList<E> implements RandomAccess {
+  private static class SynchronizedRandomAccessList<E> extends SynchronizedList<E>
+      implements RandomAccess {
     SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) {
       super(list, mutex);
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  static <E> Multiset<E> multiset(
-      Multiset<E> multiset, @Nullable Object mutex) {
-    if (multiset instanceof SynchronizedMultiset ||
-        multiset instanceof ImmutableMultiset) {
+  static <E> Multiset<E> multiset(Multiset<E> multiset, @Nullable Object mutex) {
+    if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) {
       return multiset;
     }
     return new SynchronizedMultiset<E>(multiset, mutex);
@@ -425,7 +428,8 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override Multiset<E> delegate() {
+    @Override
+    Multiset<E> delegate() {
       return (Multiset<E>) super.delegate();
     }
 
@@ -484,7 +488,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -493,7 +498,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -502,10 +508,8 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> Multimap<K, V> multimap(
-      Multimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedMultimap ||
-        multimap instanceof ImmutableMultimap) {
+  static <K, V> Multimap<K, V> multimap(Multimap<K, V> multimap, @Nullable Object mutex) {
+    if (multimap instanceof SynchronizedMultimap || multimap instanceof ImmutableMultimap) {
       return multimap;
     }
     return new SynchronizedMultimap<K, V>(multimap, mutex);
@@ -520,7 +524,8 @@ final class Synchronized {
     transient Multiset<K> keys;
 
     @SuppressWarnings("unchecked")
-    @Override Multimap<K, V> delegate() {
+    @Override
+    Multimap<K, V> delegate() {
       return (Multimap<K, V>) super.delegate();
     }
 
@@ -669,7 +674,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -678,7 +684,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -689,78 +696,90 @@ final class Synchronized {
 
   static <K, V> ListMultimap<K, V> listMultimap(
       ListMultimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedListMultimap ||
-        multimap instanceof ImmutableListMultimap) {
+    if (multimap instanceof SynchronizedListMultimap || multimap instanceof ImmutableListMultimap) {
       return multimap;
     }
     return new SynchronizedListMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedListMultimap<K, V>
-      extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> {
-    SynchronizedListMultimap(
-        ListMultimap<K, V> delegate, @Nullable Object mutex) {
+  private static class SynchronizedListMultimap<K, V> extends SynchronizedMultimap<K, V>
+      implements ListMultimap<K, V> {
+    SynchronizedListMultimap(ListMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override ListMultimap<K, V> delegate() {
+
+    @Override
+    ListMultimap<K, V> delegate() {
       return (ListMultimap<K, V>) super.delegate();
     }
-    @Override public List<V> get(K key) {
+
+    @Override
+    public List<V> get(K key) {
       synchronized (mutex) {
         return list(delegate().get(key), mutex);
       }
     }
-    @Override public List<V> removeAll(Object key) {
+
+    @Override
+    public List<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public List<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public List<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> SetMultimap<K, V> setMultimap(
-      SetMultimap<K, V> multimap, @Nullable Object mutex) {
-    if (multimap instanceof SynchronizedSetMultimap ||
-        multimap instanceof ImmutableSetMultimap) {
+  static <K, V> SetMultimap<K, V> setMultimap(SetMultimap<K, V> multimap, @Nullable Object mutex) {
+    if (multimap instanceof SynchronizedSetMultimap || multimap instanceof ImmutableSetMultimap) {
       return multimap;
     }
     return new SynchronizedSetMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedSetMultimap<K, V>
-      extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> {
+  private static class SynchronizedSetMultimap<K, V> extends SynchronizedMultimap<K, V>
+      implements SetMultimap<K, V> {
     transient Set<Map.Entry<K, V>> entrySet;
 
-    SynchronizedSetMultimap(
-        SetMultimap<K, V> delegate, @Nullable Object mutex) {
+    SynchronizedSetMultimap(SetMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override SetMultimap<K, V> delegate() {
+
+    @Override
+    SetMultimap<K, V> delegate() {
       return (SetMultimap<K, V>) super.delegate();
     }
-    @Override public Set<V> get(K key) {
+
+    @Override
+    public Set<V> get(K key) {
       synchronized (mutex) {
         return set(delegate().get(key), mutex);
       }
     }
-    @Override public Set<V> removeAll(Object key) {
+
+    @Override
+    public Set<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public Set<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
-    @Override public Set<Map.Entry<K, V>> entries() {
+
+    @Override
+    public Set<Map.Entry<K, V>> entries() {
       synchronized (mutex) {
         if (entrySet == null) {
           entrySet = set(delegate().entries(), mutex);
@@ -768,6 +787,7 @@ final class Synchronized {
         return entrySet;
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -779,37 +799,45 @@ final class Synchronized {
     return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex);
   }
 
-  private static class SynchronizedSortedSetMultimap<K, V>
-      extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
-    SynchronizedSortedSetMultimap(
-        SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
+  private static class SynchronizedSortedSetMultimap<K, V> extends SynchronizedSetMultimap<K, V>
+      implements SortedSetMultimap<K, V> {
+    SynchronizedSortedSetMultimap(SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
-    @Override SortedSetMultimap<K, V> delegate() {
+
+    @Override
+    SortedSetMultimap<K, V> delegate() {
       return (SortedSetMultimap<K, V>) super.delegate();
     }
-    @Override public SortedSet<V> get(K key) {
+
+    @Override
+    public SortedSet<V> get(K key) {
       synchronized (mutex) {
         return sortedSet(delegate().get(key), mutex);
       }
     }
-    @Override public SortedSet<V> removeAll(Object key) {
+
+    @Override
+    public SortedSet<V> removeAll(Object key) {
       synchronized (mutex) {
         return delegate().removeAll(key); // copy not synchronized
       }
     }
-    @Override public SortedSet<V> replaceValues(
-        K key, Iterable<? extends V> values) {
+
+    @Override
+    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
       synchronized (mutex) {
         return delegate().replaceValues(key, values); // copy not synchronized
       }
     }
+
     @Override
     public Comparator<? super V> valueComparator() {
       synchronized (mutex) {
         return delegate().valueComparator();
       }
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -827,8 +855,7 @@ final class Synchronized {
     return collection(collection, mutex);
   }
 
-  private static <E> Set<E> typePreservingSet(
-      Set<E> set, @Nullable Object mutex) {
+  private static <E> Set<E> typePreservingSet(Set<E> set, @Nullable Object mutex) {
     if (set instanceof SortedSet) {
       return sortedSet((SortedSet<E>) set, mutex);
     } else {
@@ -838,26 +865,25 @@ final class Synchronized {
 
   private static class SynchronizedAsMapEntries<K, V>
       extends SynchronizedSet<Map.Entry<K, Collection<V>>> {
-    SynchronizedAsMapEntries(
-        Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
+    SynchronizedAsMapEntries(Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+    @Override
+    public Iterator<Map.Entry<K, Collection<V>>> iterator() {
       // Must be manually synchronized.
-      final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator();
-      return new ForwardingIterator<Map.Entry<K, Collection<V>>>() {
-        @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() {
-          return iterator;
-        }
-
-        @Override public Map.Entry<K, Collection<V>> next() {
-          final Map.Entry<K, Collection<V>> entry = super.next();
+      return new TransformedIterator<Map.Entry<K, Collection<V>>, Map.Entry<K, Collection<V>>>(
+          super.iterator()) {
+        @Override
+        Map.Entry<K, Collection<V>> transform(final Map.Entry<K, Collection<V>> entry) {
           return new ForwardingMapEntry<K, Collection<V>>() {
-            @Override protected Map.Entry<K, Collection<V>> delegate() {
+            @Override
+            protected Map.Entry<K, Collection<V>> delegate() {
               return entry;
             }
-            @Override public Collection<V> getValue() {
+
+            @Override
+            public Collection<V> getValue() {
               return typePreservingCollection(entry.getValue(), mutex);
             }
           };
@@ -867,27 +893,36 @@ final class Synchronized {
 
     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
 
-    @Override public Object[] toArray() {
+    @Override
+    public Object[] toArray() {
       synchronized (mutex) {
         return ObjectArrays.toArrayImpl(delegate());
       }
     }
-    @Override public <T> T[] toArray(T[] array) {
+
+    @Override
+    public <T> T[] toArray(T[] array) {
       synchronized (mutex) {
         return ObjectArrays.toArrayImpl(delegate(), array);
       }
     }
-    @Override public boolean contains(Object o) {
+
+    @Override
+    public boolean contains(Object o) {
       synchronized (mutex) {
         return Maps.containsEntryImpl(delegate(), o);
       }
     }
-    @Override public boolean containsAll(Collection<?> c) {
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
       synchronized (mutex) {
         return Collections2.containsAllImpl(delegate(), c);
       }
     }
-    @Override public boolean equals(Object o) {
+
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -895,17 +930,23 @@ final class Synchronized {
         return Sets.equalsImpl(delegate(), o);
       }
     }
-    @Override public boolean remove(Object o) {
+
+    @Override
+    public boolean remove(Object o) {
       synchronized (mutex) {
         return Maps.removeEntryImpl(delegate(), o);
       }
     }
-    @Override public boolean removeAll(Collection<?> c) {
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
       synchronized (mutex) {
         return Iterators.removeAll(delegate().iterator(), c);
       }
     }
-    @Override public boolean retainAll(Collection<?> c) {
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
       synchronized (mutex) {
         return Iterators.retainAll(delegate().iterator(), c);
       }
@@ -919,8 +960,7 @@ final class Synchronized {
     return new SynchronizedMap<K, V>(map, mutex);
   }
 
-  private static class SynchronizedMap<K, V> extends SynchronizedObject
-      implements Map<K, V> {
+  private static class SynchronizedMap<K, V> extends SynchronizedObject implements Map<K, V> {
     transient Set<K> keySet;
     transient Collection<V> values;
     transient Set<Map.Entry<K, V>> entrySet;
@@ -930,7 +970,8 @@ final class Synchronized {
     }
 
     @SuppressWarnings("unchecked")
-    @Override Map<K, V> delegate() {
+    @Override
+    Map<K, V> delegate() {
       return (Map<K, V>) super.delegate();
     }
 
@@ -1027,7 +1068,8 @@ final class Synchronized {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o == this) {
         return true;
       }
@@ -1036,7 +1078,8 @@ final class Synchronized {
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
@@ -1045,8 +1088,7 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  static <K, V> SortedMap<K, V> sortedMap(
-      SortedMap<K, V> sortedMap, @Nullable Object mutex) {
+  static <K, V> SortedMap<K, V> sortedMap(SortedMap<K, V> sortedMap, @Nullable Object mutex) {
     return new SynchronizedSortedMap<K, V>(sortedMap, mutex);
   }
 
@@ -1057,41 +1099,48 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override SortedMap<K, V> delegate() {
+    @Override
+    SortedMap<K, V> delegate() {
       return (SortedMap<K, V>) super.delegate();
     }
 
-    @Override public Comparator<? super K> comparator() {
+    @Override
+    public Comparator<? super K> comparator() {
       synchronized (mutex) {
         return delegate().comparator();
       }
     }
 
-    @Override public K firstKey() {
+    @Override
+    public K firstKey() {
       synchronized (mutex) {
         return delegate().firstKey();
       }
     }
 
-    @Override public SortedMap<K, V> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V> headMap(K toKey) {
       synchronized (mutex) {
         return sortedMap(delegate().headMap(toKey), mutex);
       }
     }
 
-    @Override public K lastKey() {
+    @Override
+    public K lastKey() {
       synchronized (mutex) {
         return delegate().lastKey();
       }
     }
 
-    @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+    @Override
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
       synchronized (mutex) {
         return sortedMap(delegate().subMap(fromKey, toKey), mutex);
       }
     }
 
-    @Override public SortedMap<K, V> tailMap(K fromKey) {
+    @Override
+    public SortedMap<K, V> tailMap(K fromKey) {
       synchronized (mutex) {
         return sortedMap(delegate().tailMap(fromKey), mutex);
       }
@@ -1101,29 +1150,31 @@ final class Synchronized {
   }
 
   static <K, V> BiMap<K, V> biMap(BiMap<K, V> bimap, @Nullable Object mutex) {
-    if (bimap instanceof SynchronizedBiMap ||
-        bimap instanceof ImmutableBiMap) {
+    if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) {
       return bimap;
     }
     return new SynchronizedBiMap<K, V>(bimap, mutex, null);
   }
 
-  @VisibleForTesting static class SynchronizedBiMap<K, V>
-      extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable {
+  @VisibleForTesting
+  static class SynchronizedBiMap<K, V> extends SynchronizedMap<K, V>
+      implements BiMap<K, V>, Serializable {
     private transient Set<V> valueSet;
     private transient BiMap<V, K> inverse;
 
-    private SynchronizedBiMap(BiMap<K, V> delegate, @Nullable Object mutex,
-        @Nullable BiMap<V, K> inverse) {
+    private SynchronizedBiMap(
+        BiMap<K, V> delegate, @Nullable Object mutex, @Nullable BiMap<V, K> inverse) {
       super(delegate, mutex);
       this.inverse = inverse;
     }
 
-    @Override BiMap<K, V> delegate() {
+    @Override
+    BiMap<K, V> delegate() {
       return (BiMap<K, V>) super.delegate();
     }
 
-    @Override public Set<V> values() {
+    @Override
+    public Set<V> values() {
       synchronized (mutex) {
         if (valueSet == null) {
           valueSet = set(delegate().values(), mutex);
@@ -1143,8 +1194,7 @@ final class Synchronized {
     public BiMap<V, K> inverse() {
       synchronized (mutex) {
         if (inverse == null) {
-          inverse
-              = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
+          inverse = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
         }
         return inverse;
       }
@@ -1153,8 +1203,7 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedAsMap<K, V>
-      extends SynchronizedMap<K, Collection<V>> {
+  private static class SynchronizedAsMap<K, V> extends SynchronizedMap<K, Collection<V>> {
     transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet;
     transient Collection<Collection<V>> asMapValues;
 
@@ -1162,35 +1211,36 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override public Collection<V> get(Object key) {
+    @Override
+    public Collection<V> get(Object key) {
       synchronized (mutex) {
         Collection<V> collection = super.get(key);
-        return (collection == null) ? null
-            : typePreservingCollection(collection, mutex);
+        return (collection == null) ? null : typePreservingCollection(collection, mutex);
       }
     }
 
-    @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
+    @Override
+    public Set<Map.Entry<K, Collection<V>>> entrySet() {
       synchronized (mutex) {
         if (asMapEntrySet == null) {
-          asMapEntrySet = new SynchronizedAsMapEntries<K, V>(
-              delegate().entrySet(), mutex);
+          asMapEntrySet = new SynchronizedAsMapEntries<K, V>(delegate().entrySet(), mutex);
         }
         return asMapEntrySet;
       }
     }
 
-    @Override public Collection<Collection<V>> values() {
+    @Override
+    public Collection<Collection<V>> values() {
       synchronized (mutex) {
         if (asMapValues == null) {
-          asMapValues
-              = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
+          asMapValues = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
         }
         return asMapValues;
       }
     }
 
-    @Override public boolean containsValue(Object o) {
+    @Override
+    public boolean containsValue(Object o) {
       // values() and its contains() method are both synchronized.
       return values().contains(o);
     }
@@ -1198,22 +1248,18 @@ final class Synchronized {
     private static final long serialVersionUID = 0;
   }
 
-  private static class SynchronizedAsMapValues<V>
-      extends SynchronizedCollection<Collection<V>> {
-    SynchronizedAsMapValues(
-        Collection<Collection<V>> delegate, @Nullable Object mutex) {
+  private static class SynchronizedAsMapValues<V> extends SynchronizedCollection<Collection<V>> {
+    SynchronizedAsMapValues(Collection<Collection<V>> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override public Iterator<Collection<V>> iterator() {
+    @Override
+    public Iterator<Collection<V>> iterator() {
       // Must be manually synchronized.
-      final Iterator<Collection<V>> iterator = super.iterator();
-      return new ForwardingIterator<Collection<V>>() {
-        @Override protected Iterator<Collection<V>> delegate() {
-          return iterator;
-        }
-        @Override public Collection<V> next() {
-          return typePreservingCollection(super.next(), mutex);
+      return new TransformedIterator<Collection<V>, Collection<V>>(super.iterator()) {
+        @Override
+        Collection<V> transform(Collection<V> from) {
+          return typePreservingCollection(from, mutex);
         }
       };
     }
@@ -1229,27 +1275,30 @@ final class Synchronized {
       super(delegate, mutex);
     }
 
-    @Override NavigableSet<E> delegate() {
+    @Override
+    NavigableSet<E> delegate() {
       return (NavigableSet<E>) super.delegate();
     }
 
-    @Override public E ceiling(E e) {
+    @Override
+    public E ceiling(E e) {
       synchronized (mutex) {
         return delegate().ceiling(e);
       }
     }
 
-    @Override public Iterator<E> descendingIterator() {
+    @Override
+    public Iterator<E> descendingIterator() {
       return delegate().descendingIterator(); // manually synchronized
     }
 
     transient NavigableSet<E> descendingSet;
 
-    @Override public NavigableSet<E> descendingSet() {
+    @Override
+    public NavigableSet<E> descendingSet() {
       synchronized (mutex) {
         if (descendingSet == null) {
-          NavigableSet<E> dS =
-              Synchronized.navigableSet(delegate().descendingSet(), mutex);
+          NavigableSet<E> dS = Synchronized.navigableSet(delegate().descendingSet(), mutex);
           descendingSet = dS;
           return dS;
         }
@@ -1257,67 +1306,76 @@ final class Synchronized {
       }
     }
 
-    @Override public E floor(E e) {
+    @Override
+    public E floor(E e) {
       synchronized (mutex) {
         return delegate().floor(e);
       }
     }
 
-    @Override public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+    @Override
+    public NavigableSet<E> headSet(E toElement, boolean inclusive) {
       synchronized (mutex) {
-        return Synchronized.navigableSet(
-            delegate().headSet(toElement, inclusive), mutex);
+        return Synchronized.navigableSet(delegate().headSet(toElement, inclusive), mutex);
       }
     }
 
-    @Override public E higher(E e) {
+    @Override
+    public E higher(E e) {
       synchronized (mutex) {
         return delegate().higher(e);
       }
     }
 
-    @Override public E lower(E e) {
+    @Override
+    public E lower(E e) {
       synchronized (mutex) {
         return delegate().lower(e);
       }
     }
 
-    @Override public E pollFirst() {
+    @Override
+    public E pollFirst() {
       synchronized (mutex) {
         return delegate().pollFirst();
       }
     }
 
-    @Override public E pollLast() {
+    @Override
+    public E pollLast() {
       synchronized (mutex) {
         return delegate().pollLast();
       }
     }
 
-    @Override public NavigableSet<E> subSet(E fromElement,
-        boolean fromInclusive, E toElement, boolean toInclusive) {
+    @Override
+    public NavigableSet<E> subSet(
+        E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
       synchronized (mutex) {
-        return Synchronized.navigableSet(delegate().subSet(
-            fromElement, fromInclusive, toElement, toInclusive), mutex);
+        return Synchronized.navigableSet(
+            delegate().subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
       }
     }
 
-    @Override public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+    @Override
+    public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
       synchronized (mutex) {
-        return Synchronized.navigableSet(
-            delegate().tailSet(fromElement, inclusive), mutex);
+        return Synchronized.navigableSet(delegate().tailSet(fromElement, inclusive), mutex);
       }
     }
 
-    @Override public SortedSet<E> headSet(E toElement) {
+    @Override
+    public SortedSet<E> headSet(E toElement) {
       return headSet(toElement, false);
     }
 
-    @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+    @Override
+    public SortedSet<E> subSet(E fromElement, E toElement) {
       return subSet(fromElement, true, toElement, false);
     }
 
-    @Override public SortedSet<E> tailSet(E fromElement) {
+    @Override
+    public SortedSet<E> tailSet(E fromElement) {
       return tailSet(fromElement, true);
     }
 
@@ -1325,8 +1383,7 @@ final class Synchronized {
   }
 
   @GwtIncompatible("NavigableSet")
-  static <E> NavigableSet<E> navigableSet(
-      NavigableSet<E> navigableSet, @Nullable Object mutex) {
+  static <E> NavigableSet<E> navigableSet(NavigableSet<E> navigableSet, @Nullable Object mutex) {
     return new SynchronizedNavigableSet<E>(navigableSet, mutex);
   }
 
@@ -1336,8 +1393,7 @@ final class Synchronized {
   }
 
   @GwtIncompatible("NavigableMap")
-  static <K, V> NavigableMap<K, V> navigableMap(
-      NavigableMap<K, V> navigableMap) {
+  static <K, V> NavigableMap<K, V> navigableMap(NavigableMap<K, V> navigableMap) {
     return navigableMap(navigableMap, null);
   }
 
@@ -1348,25 +1404,28 @@ final class Synchronized {
   }
 
   @GwtIncompatible("NavigableMap")
-  @VisibleForTesting static class SynchronizedNavigableMap<K, V>
-      extends SynchronizedSortedMap<K, V> implements NavigableMap<K, V> {
+  @VisibleForTesting
+  static class SynchronizedNavigableMap<K, V> extends SynchronizedSortedMap<K, V>
+      implements NavigableMap<K, V> {
 
-    SynchronizedNavigableMap(
-        NavigableMap<K, V> delegate, @Nullable Object mutex) {
+    SynchronizedNavigableMap(NavigableMap<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override NavigableMap<K, V> delegate() {
+    @Override
+    NavigableMap<K, V> delegate() {
       return (NavigableMap<K, V>) super.delegate();
     }
 
-    @Override public Entry<K, V> ceilingEntry(K key) {
+    @Override
+    public Entry<K, V> ceilingEntry(K key) {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().ceilingEntry(key), mutex);
       }
     }
 
-    @Override public K ceilingKey(K key) {
+    @Override
+    public K ceilingKey(K key) {
       synchronized (mutex) {
         return delegate().ceilingKey(key);
       }
@@ -1374,11 +1433,11 @@ final class Synchronized {
 
     transient NavigableSet<K> descendingKeySet;
 
-    @Override public NavigableSet<K> descendingKeySet() {
+    @Override
+    public NavigableSet<K> descendingKeySet() {
       synchronized (mutex) {
         if (descendingKeySet == null) {
-          return descendingKeySet =
-              Synchronized.navigableSet(delegate().descendingKeySet(), mutex);
+          return descendingKeySet = Synchronized.navigableSet(delegate().descendingKeySet(), mutex);
         }
         return descendingKeySet;
       }
@@ -1386,124 +1445,137 @@ final class Synchronized {
 
     transient NavigableMap<K, V> descendingMap;
 
-    @Override public NavigableMap<K, V> descendingMap() {
+    @Override
+    public NavigableMap<K, V> descendingMap() {
       synchronized (mutex) {
         if (descendingMap == null) {
-          return descendingMap =
-              navigableMap(delegate().descendingMap(), mutex);
+          return descendingMap = navigableMap(delegate().descendingMap(), mutex);
         }
         return descendingMap;
       }
     }
 
-    @Override public Entry<K, V> firstEntry() {
+    @Override
+    public Entry<K, V> firstEntry() {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().firstEntry(), mutex);
       }
     }
 
-    @Override public Entry<K, V> floorEntry(K key) {
+    @Override
+    public Entry<K, V> floorEntry(K key) {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().floorEntry(key), mutex);
       }
     }
 
-    @Override public K floorKey(K key) {
+    @Override
+    public K floorKey(K key) {
       synchronized (mutex) {
         return delegate().floorKey(key);
       }
     }
 
-    @Override public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+    @Override
+    public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
       synchronized (mutex) {
-        return navigableMap(
-            delegate().headMap(toKey, inclusive), mutex);
+        return navigableMap(delegate().headMap(toKey, inclusive), mutex);
       }
     }
 
-    @Override public Entry<K, V> higherEntry(K key) {
+    @Override
+    public Entry<K, V> higherEntry(K key) {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().higherEntry(key), mutex);
       }
     }
 
-    @Override public K higherKey(K key) {
+    @Override
+    public K higherKey(K key) {
       synchronized (mutex) {
         return delegate().higherKey(key);
       }
     }
 
-    @Override public Entry<K, V> lastEntry() {
+    @Override
+    public Entry<K, V> lastEntry() {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().lastEntry(), mutex);
       }
     }
 
-    @Override public Entry<K, V> lowerEntry(K key) {
+    @Override
+    public Entry<K, V> lowerEntry(K key) {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().lowerEntry(key), mutex);
       }
     }
 
-    @Override public K lowerKey(K key) {
+    @Override
+    public K lowerKey(K key) {
       synchronized (mutex) {
         return delegate().lowerKey(key);
       }
     }
 
-    @Override public Set<K> keySet() {
+    @Override
+    public Set<K> keySet() {
       return navigableKeySet();
     }
 
     transient NavigableSet<K> navigableKeySet;
 
-    @Override public NavigableSet<K> navigableKeySet() {
+    @Override
+    public NavigableSet<K> navigableKeySet() {
       synchronized (mutex) {
         if (navigableKeySet == null) {
-          return navigableKeySet =
-              Synchronized.navigableSet(delegate().navigableKeySet(), mutex);
+          return navigableKeySet = Synchronized.navigableSet(delegate().navigableKeySet(), mutex);
         }
         return navigableKeySet;
       }
     }
 
-    @Override public Entry<K, V> pollFirstEntry() {
+    @Override
+    public Entry<K, V> pollFirstEntry() {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().pollFirstEntry(), mutex);
       }
     }
 
-    @Override public Entry<K, V> pollLastEntry() {
+    @Override
+    public Entry<K, V> pollLastEntry() {
       synchronized (mutex) {
         return nullableSynchronizedEntry(delegate().pollLastEntry(), mutex);
       }
     }
 
-    @Override public NavigableMap<K, V> subMap(
+    @Override
+    public NavigableMap<K, V> subMap(
         K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
       synchronized (mutex) {
-        return navigableMap(
-            delegate().subMap(fromKey, fromInclusive, toKey, toInclusive),
-            mutex);
+        return navigableMap(delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
       }
     }
 
-    @Override public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+    @Override
+    public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
       synchronized (mutex) {
-        return navigableMap(
-            delegate().tailMap(fromKey, inclusive), mutex);
+        return navigableMap(delegate().tailMap(fromKey, inclusive), mutex);
       }
     }
 
-    @Override public SortedMap<K, V> headMap(K toKey) {
+    @Override
+    public SortedMap<K, V> headMap(K toKey) {
       return headMap(toKey, false);
     }
 
-    @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+    @Override
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
       return subMap(fromKey, true, toKey, false);
     }
 
-    @Override public SortedMap<K, V> tailMap(K fromKey) {
+    @Override
+    public SortedMap<K, V> tailMap(K fromKey) {
       return tailMap(fromKey, true);
     }
 
@@ -1520,43 +1592,48 @@ final class Synchronized {
   }
 
   @GwtIncompatible("works but is needed only for NavigableMap")
-  private static class SynchronizedEntry<K, V> extends SynchronizedObject
-      implements Entry<K, V> {
+  private static class SynchronizedEntry<K, V> extends SynchronizedObject implements Entry<K, V> {
 
     SynchronizedEntry(Entry<K, V> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
     @SuppressWarnings("unchecked") // guaranteed by the constructor
-    @Override Entry<K, V> delegate() {
+    @Override
+    Entry<K, V> delegate() {
       return (Entry<K, V>) super.delegate();
     }
 
-    @Override public boolean equals(Object obj) {
+    @Override
+    public boolean equals(Object obj) {
       synchronized (mutex) {
         return delegate().equals(obj);
       }
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       synchronized (mutex) {
         return delegate().hashCode();
       }
     }
 
-    @Override public K getKey() {
+    @Override
+    public K getKey() {
       synchronized (mutex) {
         return delegate().getKey();
       }
     }
 
-    @Override public V getValue() {
+    @Override
+    public V getValue() {
       synchronized (mutex) {
         return delegate().getValue();
       }
     }
 
-    @Override public V setValue(V value) {
+    @Override
+    public V setValue(V value) {
       synchronized (mutex) {
         return delegate().setValue(value);
       }
@@ -1566,19 +1643,17 @@ final class Synchronized {
   }
 
   static <E> Queue<E> queue(Queue<E> queue, @Nullable Object mutex) {
-    return (queue instanceof SynchronizedQueue)
-        ? queue
-        : new SynchronizedQueue<E>(queue, mutex);
+    return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex);
   }
 
-  private static class SynchronizedQueue<E> extends SynchronizedCollection<E>
-      implements Queue<E> {
+  private static class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
 
     SynchronizedQueue(Queue<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override Queue<E> delegate() {
+    @Override
+    Queue<E> delegate() {
       return (Queue<E>) super.delegate();
     }
 
@@ -1626,14 +1701,14 @@ final class Synchronized {
   }
 
   @GwtIncompatible("Deque")
-  private static final class SynchronizedDeque<E>
-      extends SynchronizedQueue<E> implements Deque<E> {
+  private static final class SynchronizedDeque<E> extends SynchronizedQueue<E> implements Deque<E> {
 
     SynchronizedDeque(Deque<E> delegate, @Nullable Object mutex) {
       super(delegate, mutex);
     }
 
-    @Override Deque<E> delegate() {
+    @Override
+    Deque<E> delegate() {
       return (Deque<E>) super.delegate();
     }
 
diff --git a/guava/src/com/google/common/collect/Table.java b/guava/src/com/google/common/collect/Table.java
index c384bf8..b993fb7 100644
--- a/guava/src/com/google/common/collect/Table.java
+++ b/guava/src/com/google/common/collect/Table.java
@@ -43,9 +43,9 @@ import javax.annotation.Nullable;
  * <p>All methods that modify the table are optional, and the views returned by
  * the table may or may not be modifiable. When modification isn't supported,
  * those methods will throw an {@link UnsupportedOperationException}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
  * {@code Table}</a>.
  *
  * @author Jared Levy
@@ -140,6 +140,7 @@ public interface Table<R, C, V> {
    * @return the value previously associated with the keys, or {@code null} if
    *     no mapping existed for the keys
    */
+  @Nullable
   V put(R rowKey, C columnKey, V value);
 
   /**
@@ -159,6 +160,7 @@ public interface Table<R, C, V> {
    * @return the value previously associated with the keys, or {@code null} if
    *     no such value existed
    */
+  @Nullable
   V remove(@Nullable Object rowKey, @Nullable Object columnKey);
 
   // Views
@@ -265,16 +267,19 @@ public interface Table<R, C, V> {
     /**
      * Returns the row key of this cell.
      */
+    @Nullable
     R getRowKey();
 
     /**
      * Returns the column key of this cell.
      */
+    @Nullable
     C getColumnKey();
 
     /**
      * Returns the value of this cell.
      */
+    @Nullable
     V getValue();
 
     /**
diff --git a/guava/src/com/google/common/collect/Tables.java b/guava/src/com/google/common/collect/Tables.java
index db8cfcc..8f438a5 100644
--- a/guava/src/com/google/common/collect/Tables.java
+++ b/guava/src/com/google/common/collect/Tables.java
@@ -39,9 +39,9 @@ import javax.annotation.Nullable;
 
 /**
  * Provides static methods that involve a {@code Table}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Tables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#tables">
  * {@code Tables}</a>.
  *
  * @author Jared Levy
@@ -67,14 +67,12 @@ public final class Tables {
     return new ImmutableCell<R, C, V>(rowKey, columnKey, value);
   }
 
-  static final class ImmutableCell<R, C, V>
-      extends AbstractCell<R, C, V> implements Serializable {
+  static final class ImmutableCell<R, C, V> extends AbstractCell<R, C, V> implements Serializable {
     private final R rowKey;
     private final C columnKey;
     private final V value;
 
-    ImmutableCell(
-        @Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
+    ImmutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
       this.rowKey = rowKey;
       this.columnKey = columnKey;
       this.value = value;
@@ -84,10 +82,12 @@ public final class Tables {
     public R getRowKey() {
       return rowKey;
     }
+
     @Override
     public C getColumnKey() {
       return columnKey;
     }
+
     @Override
     public V getValue() {
       return value;
@@ -100,7 +100,8 @@ public final class Tables {
     // needed for serialization
     AbstractCell() {}
 
-    @Override public boolean equals(Object obj) {
+    @Override
+    public boolean equals(Object obj) {
       if (obj == this) {
         return true;
       }
@@ -113,11 +114,13 @@ public final class Tables {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Objects.hashCode(getRowKey(), getColumnKey(), getValue());
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue();
     }
   }
@@ -170,8 +173,7 @@ public final class Tables {
     }
 
     @Override
-    public boolean contains(
-        @Nullable Object rowKey, @Nullable Object columnKey) {
+    public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
       return original.contains(columnKey, rowKey);
     }
 
@@ -240,8 +242,7 @@ public final class Tables {
         new Function<Cell<?, ?, ?>, Cell<?, ?, ?>>() {
           @Override
           public Cell<?, ?, ?> apply(Cell<?, ?, ?> cell) {
-            return immutableCell(
-                cell.getColumnKey(), cell.getRowKey(), cell.getValue());
+            return immutableCell(cell.getColumnKey(), cell.getRowKey(), cell.getValue());
           }
         };
 
@@ -334,64 +335,70 @@ public final class Tables {
     return new TransformedTable<R, C, V1, V2>(fromTable, function);
   }
 
-  private static class TransformedTable<R, C, V1, V2>
-      extends AbstractTable<R, C, V2> {
+  private static class TransformedTable<R, C, V1, V2> extends AbstractTable<R, C, V2> {
     final Table<R, C, V1> fromTable;
     final Function<? super V1, V2> function;
 
-    TransformedTable(
-        Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
+    TransformedTable(Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
       this.fromTable = checkNotNull(fromTable);
       this.function = checkNotNull(function);
     }
 
-    @Override public boolean contains(Object rowKey, Object columnKey) {
+    @Override
+    public boolean contains(Object rowKey, Object columnKey) {
       return fromTable.contains(rowKey, columnKey);
     }
 
-    @Override public V2 get(Object rowKey, Object columnKey) {
+    @Override
+    public V2 get(Object rowKey, Object columnKey) {
       // The function is passed a null input only when the table contains a null
       // value.
-      return contains(rowKey, columnKey)
-          ? function.apply(fromTable.get(rowKey, columnKey)) : null;
+      return contains(rowKey, columnKey) ? function.apply(fromTable.get(rowKey, columnKey)) : null;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return fromTable.size();
     }
 
-    @Override public void clear() {
+    @Override
+    public void clear() {
       fromTable.clear();
     }
 
-    @Override public V2 put(R rowKey, C columnKey, V2 value) {
+    @Override
+    public V2 put(R rowKey, C columnKey, V2 value) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public void putAll(
-        Table<? extends R, ? extends C, ? extends V2> table) {
+    @Override
+    public void putAll(Table<? extends R, ? extends C, ? extends V2> table) {
       throw new UnsupportedOperationException();
     }
 
-    @Override public V2 remove(Object rowKey, Object columnKey) {
+    @Override
+    public V2 remove(Object rowKey, Object columnKey) {
       return contains(rowKey, columnKey)
-          ? function.apply(fromTable.remove(rowKey, columnKey)) : null;
+          ? function.apply(fromTable.remove(rowKey, columnKey))
+          : null;
     }
 
-    @Override public Map<C, V2> row(R rowKey) {
+    @Override
+    public Map<C, V2> row(R rowKey) {
       return Maps.transformValues(fromTable.row(rowKey), function);
     }
 
-    @Override public Map<R, V2> column(C columnKey) {
+    @Override
+    public Map<R, V2> column(C columnKey) {
       return Maps.transformValues(fromTable.column(columnKey), function);
     }
 
     Function<Cell<R, C, V1>, Cell<R, C, V2>> cellFunction() {
       return new Function<Cell<R, C, V1>, Cell<R, C, V2>>() {
-        @Override public Cell<R, C, V2> apply(Cell<R, C, V1> cell) {
+        @Override
+        public Cell<R, C, V2> apply(Cell<R, C, V1> cell) {
           return immutableCell(
-              cell.getRowKey(), cell.getColumnKey(),
-              function.apply(cell.getValue()));
+              cell.getRowKey(), cell.getColumnKey(), function.apply(cell.getValue()));
         }
       };
     }
@@ -401,11 +408,13 @@ public final class Tables {
       return Iterators.transform(fromTable.cellSet().iterator(), cellFunction());
     }
 
-    @Override public Set<R> rowKeySet() {
+    @Override
+    public Set<R> rowKeySet() {
       return fromTable.rowKeySet();
     }
 
-    @Override public Set<C> columnKeySet() {
+    @Override
+    public Set<C> columnKeySet() {
       return fromTable.columnKeySet();
     }
 
@@ -414,37 +423,41 @@ public final class Tables {
       return Collections2.transform(fromTable.values(), function);
     }
 
-    @Override public Map<R, Map<C, V2>> rowMap() {
+    @Override
+    public Map<R, Map<C, V2>> rowMap() {
       Function<Map<C, V1>, Map<C, V2>> rowFunction =
           new Function<Map<C, V1>, Map<C, V2>>() {
-            @Override public Map<C, V2> apply(Map<C, V1> row) {
+            @Override
+            public Map<C, V2> apply(Map<C, V1> row) {
               return Maps.transformValues(row, function);
             }
           };
       return Maps.transformValues(fromTable.rowMap(), rowFunction);
     }
 
-    @Override public Map<C, Map<R, V2>> columnMap() {
+    @Override
+    public Map<C, Map<R, V2>> columnMap() {
       Function<Map<R, V1>, Map<R, V2>> columnFunction =
           new Function<Map<R, V1>, Map<R, V2>>() {
-            @Override public Map<R, V2> apply(Map<R, V1> column) {
+            @Override
+            public Map<R, V2> apply(Map<R, V1> column) {
               return Maps.transformValues(column, function);
             }
           };
       return Maps.transformValues(fromTable.columnMap(), columnFunction);
     }
   }
-  
+
   /**
    * Returns an unmodifiable view of the specified table. This method allows modules to provide
    * users with "read-only" access to internal tables. Query operations on the returned table
    * "read through" to the specified table, and attempts to modify the returned table, whether
    * direct or via its collection views, result in an {@code UnsupportedOperationException}.
-   * 
+   *
    * <p>The returned table will be serializable if the specified table is serializable.
    *
    * <p>Consider using an {@link ImmutableTable}, which is guaranteed never to change.
-   * 
+   *
    * @param table
    *          the table for which an unmodifiable view is to be returned
    * @return an unmodifiable view of the specified table
@@ -454,9 +467,9 @@ public final class Tables {
       Table<? extends R, ? extends C, ? extends V> table) {
     return new UnmodifiableTable<R, C, V>(table);
   }
-  
-  private static class UnmodifiableTable<R, C, V>
-      extends ForwardingTable<R, C, V> implements Serializable {
+
+  private static class UnmodifiableTable<R, C, V> extends ForwardingTable<R, C, V>
+      implements Serializable {
     final Table<? extends R, ? extends C, ? extends V> delegate;
 
     UnmodifiableTable(Table<? extends R, ? extends C, ? extends V> delegate) {
@@ -530,7 +543,7 @@ public final class Tables {
     public Collection<V> values() {
       return Collections.unmodifiableCollection(super.values());
     }
-    
+
     private static final long serialVersionUID = 0;
   }
 
@@ -539,9 +552,9 @@ public final class Tables {
    * provide users with "read-only" access to internal tables. Query operations on the returned
    * table "read through" to the specified table, and attemps to modify the returned table, whether
    * direct or via its collection views, result in an {@code UnsupportedOperationException}.
-   * 
+   *
    * <p>The returned table will be serializable if the specified table is serializable.
-   * 
+   *
    * @param table the row-sorted table for which an unmodifiable view is to be returned
    * @return an unmodifiable view of the specified table
    * @since 11.0
@@ -556,7 +569,7 @@ public final class Tables {
      */
     return new UnmodifiableRowSortedMap<R, C, V>(table);
   }
-  
+
   static final class UnmodifiableRowSortedMap<R, C, V> extends UnmodifiableTable<R, C, V>
       implements RowSortedTable<R, C, V> {
 
@@ -595,7 +608,7 @@ public final class Tables {
           return Collections.unmodifiableMap(input);
         }
       };
-      
+
   static boolean equalsImpl(Table<?, ?, ?> table, @Nullable Object obj) {
     if (obj == table) {
       return true;
diff --git a/guava/src/com/google/common/collect/TreeBasedTable.java b/guava/src/com/google/common/collect/TreeBasedTable.java
index 29bf65a..10023d3 100644
--- a/guava/src/com/google/common/collect/TreeBasedTable.java
+++ b/guava/src/com/google/common/collect/TreeBasedTable.java
@@ -67,7 +67,7 @@ import javax.annotation.Nullable;
  * must be synchronized externally.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
  * {@code Table}</a>.
  *
  * @author Jared Levy
@@ -79,16 +79,18 @@ import javax.annotation.Nullable;
 public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
   private final Comparator<? super C> columnComparator;
 
-  private static class Factory<C, V>
-      implements Supplier<TreeMap<C, V>>, Serializable {
+  private static class Factory<C, V> implements Supplier<TreeMap<C, V>>, Serializable {
     final Comparator<? super C> comparator;
+
     Factory(Comparator<? super C> comparator) {
       this.comparator = comparator;
     }
+
     @Override
     public TreeMap<C, V> get() {
       return new TreeMap<C, V>(comparator);
     }
+
     private static final long serialVersionUID = 0;
   }
 
@@ -101,10 +103,8 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
    * and the same for {@code C}. That's necessary to support classes defined
    * without generics.
    */
-  public static <R extends Comparable, C extends Comparable, V>
-      TreeBasedTable<R, C, V> create() {
-    return new TreeBasedTable<R, C, V>(Ordering.natural(),
-        Ordering.natural());
+  public static <R extends Comparable, C extends Comparable, V> TreeBasedTable<R, C, V> create() {
+    return new TreeBasedTable<R, C, V>(Ordering.natural(), Ordering.natural());
   }
 
   /**
@@ -115,8 +115,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
    * @param columnComparator the comparator that orders the column keys
    */
   public static <R, C, V> TreeBasedTable<R, C, V> create(
-      Comparator<? super R> rowComparator,
-      Comparator<? super C> columnComparator) {
+      Comparator<? super R> rowComparator, Comparator<? super C> columnComparator) {
     checkNotNull(rowComparator);
     checkNotNull(columnComparator);
     return new TreeBasedTable<R, C, V>(rowComparator, columnComparator);
@@ -126,19 +125,15 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
    * Creates a {@code TreeBasedTable} with the same mappings and sort order
    * as the specified {@code TreeBasedTable}.
    */
-  public static <R, C, V> TreeBasedTable<R, C, V> create(
-      TreeBasedTable<R, C, ? extends V> table) {
-    TreeBasedTable<R, C, V> result
-        = new TreeBasedTable<R, C, V>(
-            table.rowComparator(), table.columnComparator());
+  public static <R, C, V> TreeBasedTable<R, C, V> create(TreeBasedTable<R, C, ? extends V> table) {
+    TreeBasedTable<R, C, V> result =
+        new TreeBasedTable<R, C, V>(table.rowComparator(), table.columnComparator());
     result.putAll(table);
     return result;
   }
 
-  TreeBasedTable(Comparator<? super R> rowComparator,
-      Comparator<? super C> columnComparator) {
-    super(new TreeMap<R, Map<C, V>>(rowComparator),
-        new Factory<C, V>(columnComparator));
+  TreeBasedTable(Comparator<? super R> rowComparator, Comparator<? super C> columnComparator) {
+    super(new TreeMap<R, Map<C, V>>(rowComparator), new Factory<C, V>(columnComparator));
     this.columnComparator = columnComparator;
   }
 
@@ -160,7 +155,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
     return columnComparator;
   }
 
-  // TODO(user): make column return a SortedMap
+  // TODO(lowasser): make column return a SortedMap
 
   /**
    * {@inheritDoc}
@@ -169,7 +164,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
    * row, this method returns a {@link SortedMap}, instead of the {@link Map}
    * specified in the {@link Table} interface.
    * @since 10.0
-   *     (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+   *     (<a href="https://github.com/google/guava/wiki/Compatibility"
    *     >mostly source-compatible</a> since 7.0)
    */
   @Override
@@ -189,15 +184,17 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
       super(rowKey);
       this.lowerBound = lowerBound;
       this.upperBound = upperBound;
-      checkArgument(lowerBound == null || upperBound == null
-          || compare(lowerBound, upperBound) <= 0);
+      checkArgument(
+          lowerBound == null || upperBound == null || compare(lowerBound, upperBound) <= 0);
     }
 
-    @Override public SortedSet<C> keySet() {
+    @Override
+    public SortedSet<C> keySet() {
       return new Maps.SortedKeySet<C, V>(this);
     }
 
-    @Override public Comparator<? super C> comparator() {
+    @Override
+    public Comparator<? super C> comparator() {
       return columnComparator();
     }
 
@@ -209,27 +206,31 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
     }
 
     boolean rangeContains(@Nullable Object o) {
-      return o != null && (lowerBound == null || compare(lowerBound, o) <= 0)
+      return o != null
+          && (lowerBound == null || compare(lowerBound, o) <= 0)
           && (upperBound == null || compare(upperBound, o) > 0);
     }
 
-    @Override public SortedMap<C, V> subMap(C fromKey, C toKey) {
-      checkArgument(rangeContains(checkNotNull(fromKey))
-          && rangeContains(checkNotNull(toKey)));
+    @Override
+    public SortedMap<C, V> subMap(C fromKey, C toKey) {
+      checkArgument(rangeContains(checkNotNull(fromKey)) && rangeContains(checkNotNull(toKey)));
       return new TreeRow(rowKey, fromKey, toKey);
     }
 
-    @Override public SortedMap<C, V> headMap(C toKey) {
+    @Override
+    public SortedMap<C, V> headMap(C toKey) {
       checkArgument(rangeContains(checkNotNull(toKey)));
       return new TreeRow(rowKey, lowerBound, toKey);
     }
 
-    @Override public SortedMap<C, V> tailMap(C fromKey) {
+    @Override
+    public SortedMap<C, V> tailMap(C fromKey) {
       checkArgument(rangeContains(checkNotNull(fromKey)));
       return new TreeRow(rowKey, fromKey, upperBound);
     }
 
-    @Override public C firstKey() {
+    @Override
+    public C firstKey() {
       SortedMap<C, V> backing = backingRowMap();
       if (backing == null) {
         throw new NoSuchElementException();
@@ -237,7 +238,8 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
       return backingRowMap().firstKey();
     }
 
-    @Override public C lastKey() {
+    @Override
+    public C lastKey() {
       SortedMap<C, V> backing = backingRowMap();
       if (backing == null) {
         throw new NoSuchElementException();
@@ -252,8 +254,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
      * time we're queried.
      */
     SortedMap<C, V> wholeRow() {
-      if (wholeRow == null
-          || (wholeRow.isEmpty() && backingMap.containsKey(rowKey))) {
+      if (wholeRow == null || (wholeRow.isEmpty() && backingMap.containsKey(rowKey))) {
         wholeRow = (SortedMap<C, V>) backingMap.get(rowKey);
       }
       return wholeRow;
@@ -288,11 +289,13 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
       }
     }
 
-    @Override public boolean containsKey(Object key) {
+    @Override
+    public boolean containsKey(Object key) {
       return rangeContains(key) && super.containsKey(key);
     }
 
-    @Override public V put(C key, V value) {
+    @Override
+    public V put(C key, V value) {
       checkArgument(rangeContains(checkNotNull(key)));
       return super.put(key, value);
     }
@@ -300,11 +303,13 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
 
   // rowKeySet() and rowMap() are defined here so they appear in the Javadoc.
 
-  @Override public SortedSet<R> rowKeySet() {
+  @Override
+  public SortedSet<R> rowKeySet() {
     return super.rowKeySet();
   }
 
-  @Override public SortedMap<R, Map<C, V>> rowMap() {
+  @Override
+  public SortedMap<R, Map<C, V>> rowMap() {
     return super.rowMap();
   }
 
@@ -317,13 +322,16 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
     final Comparator<? super C> comparator = columnComparator();
 
     final Iterator<C> merged =
-        Iterators.mergeSorted(Iterables.transform(backingMap.values(),
-            new Function<Map<C, V>, Iterator<C>>() {
-              @Override
-              public Iterator<C> apply(Map<C, V> input) {
-                return input.keySet().iterator();
-              }
-            }), comparator);
+        Iterators.mergeSorted(
+            Iterables.transform(
+                backingMap.values(),
+                new Function<Map<C, V>, Iterator<C>>() {
+                  @Override
+                  public Iterator<C> apply(Map<C, V> input) {
+                    return input.keySet().iterator();
+                  }
+                }),
+            comparator);
 
     return new AbstractIterator<C>() {
       C lastValue;
@@ -332,8 +340,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
       protected C computeNext() {
         while (merged.hasNext()) {
           C next = merged.next();
-          boolean duplicate =
-              lastValue != null && comparator.compare(next, lastValue) == 0;
+          boolean duplicate = lastValue != null && comparator.compare(next, lastValue) == 0;
 
           // Keep looping till we find a non-duplicate value.
           if (!duplicate) {
diff --git a/guava/src/com/google/common/collect/TreeMultimap.java b/guava/src/com/google/common/collect/TreeMultimap.java
index 433774d..e3586e0 100644
--- a/guava/src/com/google/common/collect/TreeMultimap.java
+++ b/guava/src/com/google/common/collect/TreeMultimap.java
@@ -68,12 +68,12 @@ import javax.annotation.Nullable;
  * Multimaps#synchronizedSortedSetMultimap}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
  * {@code Multimap}</a>.
  *
  * @author Jared Levy
  * @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(serializable = true, emulated = true)
 public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V> {
@@ -84,8 +84,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * Creates an empty {@code TreeMultimap} ordered by the natural ordering of
    * its keys and values.
    */
-  public static <K extends Comparable, V extends Comparable>
-      TreeMultimap<K, V> create() {
+  public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create() {
     return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural());
   }
 
@@ -98,10 +97,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * @param valueComparator the comparator that determines the value ordering
    */
   public static <K, V> TreeMultimap<K, V> create(
-      Comparator<? super K> keyComparator,
-      Comparator<? super V> valueComparator) {
-    return new TreeMultimap<K, V>(checkNotNull(keyComparator),
-        checkNotNull(valueComparator));
+      Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
+    return new TreeMultimap<K, V>(checkNotNull(keyComparator), checkNotNull(valueComparator));
   }
 
   /**
@@ -110,20 +107,19 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    *
    * @param multimap the multimap whose contents are copied to this multimap
    */
-  public static <K extends Comparable, V extends Comparable>
-      TreeMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
-    return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(),
-        multimap);
+  public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create(
+      Multimap<? extends K, ? extends V> multimap) {
+    return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(), multimap);
   }
 
-  TreeMultimap(Comparator<? super K> keyComparator,
-      Comparator<? super V> valueComparator) {
+  TreeMultimap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
     super(new TreeMap<K, Collection<V>>(keyComparator));
     this.keyComparator = keyComparator;
     this.valueComparator = valueComparator;
   }
 
-  private TreeMultimap(Comparator<? super K> keyComparator,
+  private TreeMultimap(
+      Comparator<? super K> keyComparator,
       Comparator<? super V> valueComparator,
       Multimap<? extends K, ? extends V> multimap) {
     this(keyComparator, valueComparator);
@@ -138,7 +134,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * @return a new {@code TreeSet} containing a collection of values for one
    *     key
    */
-  @Override SortedSet<V> createCollection() {
+  @Override
+  SortedSet<V> createCollection() {
     return new TreeSet<V>(valueComparator);
   }
 
@@ -163,17 +160,17 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
   }
 
   /*
-   * The following @GwtIncompatible methods override the methods in 
+   * The following @GwtIncompatible methods override the methods in
    * AbstractSortedKeySortedSetMultimap, so GWT will fall back to the ASKSSM implementations,
    * which return SortedSets and SortedMaps.
    */
-  
+
   @Override
   @GwtIncompatible("NavigableMap")
   NavigableMap<K, Collection<V>> backingMap() {
     return (NavigableMap<K, Collection<V>>) super.backingMap();
   }
-  
+
   /**
    * @since 14.0 (present with return type {@code SortedSet} since 2.0)
    */
@@ -201,11 +198,11 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * <p>Because a {@code TreeMultimap} has unique sorted keys, this method
    * returns a {@link NavigableSet}, instead of the {@link java.util.Set} specified
    * in the {@link Multimap} interface.
-   * 
+   *
    * @since 14.0 (present with return type {@code SortedSet} since 2.0)
    */
   @Override
-  @GwtIncompatible("NavigableSet") 
+  @GwtIncompatible("NavigableSet")
   public NavigableSet<K> keySet() {
     return (NavigableSet<K>) super.keySet();
   }
@@ -222,10 +219,10 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
    * <p>Because a {@code TreeMultimap} has unique sorted keys, this method
    * returns a {@link NavigableMap}, instead of the {@link java.util.Map} specified
    * in the {@link Multimap} interface.
-   * 
+   *
    * @since 14.0 (present with return type {@code SortedMap} since 2.0)
    */
-  @Override 
+  @Override
   @GwtIncompatible("NavigableMap")
   public NavigableMap<K, Collection<V>> asMap() {
     return (NavigableMap<K, Collection<V>>) super.asMap();
@@ -252,8 +249,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
 
   @GwtIncompatible("java.io.ObjectInputStream")
   @SuppressWarnings("unchecked") // reading data stored by writeObject
-  private void readObject(ObjectInputStream stream)
-      throws IOException, ClassNotFoundException {
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     stream.defaultReadObject();
     keyComparator = checkNotNull((Comparator<? super K>) stream.readObject());
     valueComparator = checkNotNull((Comparator<? super V>) stream.readObject());
diff --git a/guava/src/com/google/common/collect/TreeMultiset.java b/guava/src/com/google/common/collect/TreeMultiset.java
index cd4c445..5d0fbb8 100644
--- a/guava/src/com/google/common/collect/TreeMultiset.java
+++ b/guava/src/com/google/common/collect/TreeMultiset.java
@@ -48,12 +48,12 @@ import javax.annotation.Nullable;
  * {@link java.util.Collection} contract, which is specified in terms of {@link Object#equals}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
  * {@code Multiset}</a>.
  *
  * @author Louis Wasserman
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible(emulated = true)
 public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements Serializable {
@@ -153,6 +153,7 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
         return (root == null) ? 0 : root.distinctElements;
       }
     };
+
     abstract int nodeAggregate(AvlNode<?> node);
 
     abstract long treeAggregate(@Nullable AvlNode<?> root);
@@ -187,7 +188,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
           throw new AssertionError();
       }
     } else {
-      return aggr.treeAggregate(node.left) + aggr.nodeAggregate(node)
+      return aggr.treeAggregate(node.left)
+          + aggr.nodeAggregate(node)
           + aggregateBelowRange(aggr, node.right);
     }
   }
@@ -209,7 +211,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
           throw new AssertionError();
       }
     } else {
-      return aggr.treeAggregate(node.right) + aggr.nodeAggregate(node)
+      return aggr.treeAggregate(node.right)
+          + aggr.nodeAggregate(node)
           + aggregateAboveRange(aggr, node.left);
     }
   }
@@ -353,7 +356,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
   /**
    * Returns the first node in the tree that is in range.
    */
-  @Nullable private AvlNode<E> firstNode() {
+  @Nullable
+  private AvlNode<E> firstNode() {
     AvlNode<E> root = rootReference.get();
     if (root == null) {
       return null;
@@ -375,7 +379,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
     return (node == header || !range.contains(node.getElement())) ? null : node;
   }
 
-  @Nullable private AvlNode<E> lastNode() {
+  @Nullable
+  private AvlNode<E> lastNode() {
     AvlNode<E> root = rootReference.get();
     if (root == null) {
       return null;
@@ -483,18 +488,18 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
 
   @Override
   public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) {
-    return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.upTo(
-        comparator(),
-        upperBound,
-        boundType)), header);
+    return new TreeMultiset<E>(
+        rootReference,
+        range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)),
+        header);
   }
 
   @Override
   public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
-    return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.downTo(
-        comparator(),
-        lowerBound,
-        boundType)), header);
+    return new TreeMultiset<E>(
+        rootReference,
+        range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
+        header);
   }
 
   static int distinctElements(@Nullable AvlNode<?> node) {
@@ -504,7 +509,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
   private static final class Reference<T> {
     @Nullable private T value;
 
-    @Nullable public T get() {
+    @Nullable
+    public T get() {
       return value;
     }
 
@@ -828,8 +834,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
     }
 
     private void recomputeMultiset() {
-      this.distinctElements = 1 + TreeMultiset.distinctElements(left)
-          + TreeMultiset.distinctElements(right);
+      this.distinctElements =
+          1 + TreeMultiset.distinctElements(left) + TreeMultiset.distinctElements(right);
       this.totalCount = elemCount + totalCount(left) + totalCount(right);
     }
 
@@ -896,7 +902,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
       return (node == null) ? 0 : node.height;
     }
 
-    @Nullable private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
+    @Nullable
+    private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
       int cmp = comparator.compare(e, elem);
       if (cmp < 0) {
         return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
@@ -907,7 +914,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
       }
     }
 
-    @Nullable private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
+    @Nullable
+    private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
       int cmp = comparator.compare(e, elem);
       if (cmp > 0) {
         return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
@@ -968,17 +976,16 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
     // reading data stored by writeObject
     Comparator<? super E> comparator = (Comparator<? super E>) stream.readObject();
     Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator);
-    Serialization.getFieldSetter(TreeMultiset.class, "range").set(
-        this,
-        GeneralRange.all(comparator));
-    Serialization.getFieldSetter(TreeMultiset.class, "rootReference").set(
-        this,
-        new Reference<AvlNode<E>>());
+    Serialization.getFieldSetter(TreeMultiset.class, "range")
+        .set(this, GeneralRange.all(comparator));
+    Serialization.getFieldSetter(TreeMultiset.class, "rootReference")
+        .set(this, new Reference<AvlNode<E>>());
     AvlNode<E> header = new AvlNode<E>(null, 1);
     Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header);
     successor(header, header);
     Serialization.populateMultiset(this, stream);
   }
 
-  @GwtIncompatible("not needed in emulated source") private static final long serialVersionUID = 1;
+  @GwtIncompatible("not needed in emulated source")
+  private static final long serialVersionUID = 1;
 }
diff --git a/guava/src/com/google/common/collect/TreeRangeMap.java b/guava/src/com/google/common/collect/TreeRangeMap.java
index 82c3206..3495707 100644
--- a/guava/src/com/google/common/collect/TreeRangeMap.java
+++ b/guava/src/com/google/common/collect/TreeRangeMap.java
@@ -26,9 +26,9 @@ import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicate;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
 
 import java.util.AbstractMap;
-import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -150,8 +150,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
       throw new NoSuchElementException();
     }
     return Range.create(
-        firstEntry.getValue().getKey().lowerBound,
-        lastEntry.getValue().getKey().upperBound);
+        firstEntry.getValue().getKey().lowerBound, lastEntry.getValue().getKey().upperBound);
   }
 
   private void putRangeMapEntry(Cut<K> lowerBound, Cut<K> upperBound, V value) {
@@ -178,11 +177,15 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
         if (rangeMapEntry.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) {
           // we know ( [ ] ), so insert the range ] ) back into the map --
           // it's being split apart
-          putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry.getUpperBound(),
+          putRangeMapEntry(
+              rangeToRemove.upperBound,
+              rangeMapEntry.getUpperBound(),
               mapEntryBelowToTruncate.getValue().getValue());
         }
         // overwrite mapEntryToTruncateBelow with a truncated range
-        putRangeMapEntry(rangeMapEntry.getLowerBound(), rangeToRemove.lowerBound,
+        putRangeMapEntry(
+            rangeMapEntry.getLowerBound(),
+            rangeToRemove.lowerBound,
             mapEntryBelowToTruncate.getValue().getValue());
       }
     }
@@ -195,7 +198,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
       if (rangeMapEntry.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) {
         // we know ( ] ), and since we dealt with truncating below already,
         // we know [ ( ] )
-        putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry.getUpperBound(),
+        putRangeMapEntry(
+            rangeToRemove.upperBound,
+            rangeMapEntry.getUpperBound(),
             mapEntryAboveToTruncate.getValue().getValue());
         entriesByLowerBound.remove(rangeToRemove.lowerBound);
       }
@@ -205,10 +210,22 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
 
   @Override
   public Map<Range<K>, V> asMapOfRanges() {
-    return new AsMapOfRanges();
+    return new AsMapOfRanges(entriesByLowerBound.values());
   }
 
-  private final class AsMapOfRanges extends AbstractMap<Range<K>, V> {
+  @Override
+  public Map<Range<K>, V> asDescendingMapOfRanges() {
+    return new AsMapOfRanges(entriesByLowerBound.descendingMap().values());
+  }
+
+  private final class AsMapOfRanges extends IteratorBasedAbstractMap<Range<K>, V> {
+
+    final Iterable<Entry<Range<K>, V>> entryIterable;
+
+    @SuppressWarnings("unchecked") // it's safe to upcast iterables
+    AsMapOfRanges(Iterable<RangeMapEntry<K, V>> entryIterable) {
+      this.entryIterable = (Iterable) entryIterable;
+    }
 
     @Override
     public boolean containsKey(@Nullable Object key) {
@@ -228,23 +245,16 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
     }
 
     @Override
-    public Set<Entry<Range<K>, V>> entrySet() {
-      return new AbstractSet<Entry<Range<K>, V>>() {
-
-        @SuppressWarnings("unchecked") // it's safe to upcast iterators
-        @Override
-        public Iterator<Entry<Range<K>, V>> iterator() {
-          return (Iterator) entriesByLowerBound.values().iterator();
-        }
+    public int size() {
+      return entriesByLowerBound.size();
+    }
 
-        @Override
-        public int size() {
-          return entriesByLowerBound.size();
-        }
-      };
+    @Override
+    Iterator<Entry<Range<K>, V>> entryIterator() {
+      return entryIterable.iterator();
     }
   }
-  
+
   @Override
   public RangeMap<K, V> subRangeMap(Range<K> subRange) {
     if (subRange.equals(Range.all())) {
@@ -253,13 +263,13 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
       return new SubRangeMap(subRange);
     }
   }
-  
+
   @SuppressWarnings("unchecked")
   private RangeMap<K, V> emptySubRangeMap() {
     return EMPTY_SUB_RANGE_MAP;
   }
-  
-  private static final RangeMap EMPTY_SUB_RANGE_MAP = 
+
+  private static final RangeMap EMPTY_SUB_RANGE_MAP =
       new RangeMap() {
         @Override
         @Nullable
@@ -307,16 +317,21 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
         }
 
         @Override
+        public Map<Range, Object> asDescendingMapOfRanges() {
+          return Collections.emptyMap();
+        }
+
+        @Override
         public RangeMap subRangeMap(Range range) {
           checkNotNull(range);
           return this;
         }
       };
-  
+
   private class SubRangeMap implements RangeMap<K, V> {
 
     private final Range<K> subRange;
-    
+
     SubRangeMap(Range<K> subRange) {
       this.subRange = subRange;
     }
@@ -324,9 +339,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
     @Override
     @Nullable
     public V get(K key) {
-      return subRange.contains(key)
-          ? TreeRangeMap.this.get(key)
-          : null;
+      return subRange.contains(key) ? TreeRangeMap.this.get(key) : null;
     }
 
     @Override
@@ -346,8 +359,8 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
       Cut<K> lowerBound;
       Entry<Cut<K>, RangeMapEntry<K, V>> lowerEntry =
           entriesByLowerBound.floorEntry(subRange.lowerBound);
-      if (lowerEntry != null && 
-          lowerEntry.getValue().getUpperBound().compareTo(subRange.lowerBound) > 0) {
+      if (lowerEntry != null
+          && lowerEntry.getValue().getUpperBound().compareTo(subRange.lowerBound) > 0) {
         lowerBound = subRange.lowerBound;
       } else {
         lowerBound = entriesByLowerBound.ceilingKey(subRange.lowerBound);
@@ -355,9 +368,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
           throw new NoSuchElementException();
         }
       }
-      
+
       Cut<K> upperBound;
-      Entry<Cut<K>, RangeMapEntry<K, V>> upperEntry = 
+      Entry<Cut<K>, RangeMapEntry<K, V>> upperEntry =
           entriesByLowerBound.lowerEntry(subRange.upperBound);
       if (upperEntry == null) {
         throw new NoSuchElementException();
@@ -371,8 +384,8 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
 
     @Override
     public void put(Range<K> range, V value) {
-      checkArgument(subRange.encloses(range), 
-          "Cannot put range %s into a subRangeMap(%s)", range, subRange);
+      checkArgument(
+          subRange.encloses(range), "Cannot put range %s into a subRangeMap(%s)", range, subRange);
       TreeRangeMap.this.put(range, value);
     }
 
@@ -382,8 +395,11 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
         return;
       }
       Range<K> span = rangeMap.span();
-      checkArgument(subRange.encloses(span), 
-          "Cannot putAll rangeMap with span %s into a subRangeMap(%s)", span, subRange);
+      checkArgument(
+          subRange.encloses(span),
+          "Cannot putAll rangeMap with span %s into a subRangeMap(%s)",
+          span,
+          subRange);
       TreeRangeMap.this.putAll(rangeMap);
     }
 
@@ -414,6 +430,39 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
     }
 
     @Override
+    public Map<Range<K>, V> asDescendingMapOfRanges() {
+      return new SubRangeMapAsMap() {
+
+        @Override
+        Iterator<Entry<Range<K>, V>> entryIterator() {
+          if (subRange.isEmpty()) {
+            return Iterators.emptyIterator();
+          }
+          final Iterator<RangeMapEntry<K, V>> backingItr =
+              entriesByLowerBound
+                  .headMap(subRange.upperBound, false)
+                  .descendingMap()
+                  .values()
+                  .iterator();
+          return new AbstractIterator<Entry<Range<K>, V>>() {
+
+            @Override
+            protected Entry<Range<K>, V> computeNext() {
+              while (backingItr.hasNext()) {
+                RangeMapEntry<K, V> entry = backingItr.next();
+                if (entry.getUpperBound().compareTo(subRange.lowerBound) <= 0) {
+                  return endOfData();
+                }
+                return Maps.immutableEntry(entry.getKey().intersection(subRange), entry.getValue());
+              }
+              return endOfData();
+            }
+          };
+        }
+      };
+    }
+
+    @Override
     public boolean equals(@Nullable Object o) {
       if (o instanceof RangeMap) {
         RangeMap<?, ?> rangeMap = (RangeMap<?, ?>) o;
@@ -431,9 +480,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
     public String toString() {
       return asMapOfRanges().toString();
     }
-    
+
     class SubRangeMapAsMap extends AbstractMap<Range<K>, V> {
-      
+
       @Override
       public boolean containsKey(Object key) {
         return get(key) != null;
@@ -451,7 +500,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
             RangeMapEntry<K, V> candidate = null;
             if (r.lowerBound.compareTo(subRange.lowerBound) == 0) {
               // r could be truncated on the left
-              Entry<Cut<K>, RangeMapEntry<K, V>> entry = 
+              Entry<Cut<K>, RangeMapEntry<K, V>> entry =
                   entriesByLowerBound.floorEntry(r.lowerBound);
               if (entry != null) {
                 candidate = entry.getValue();
@@ -459,8 +508,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
             } else {
               candidate = entriesByLowerBound.get(r.lowerBound);
             }
-            
-            if (candidate != null && candidate.getKey().isConnected(subRange)
+
+            if (candidate != null
+                && candidate.getKey().isConnected(subRange)
                 && candidate.getKey().intersection(subRange).equals(r)) {
               return candidate.getValue();
             }
@@ -487,7 +537,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
       public void clear() {
         SubRangeMap.this.clear();
       }
-      
+
       private boolean removeEntryIf(Predicate<? super Entry<Range<K>, V>> predicate) {
         List<Range<K>> toRemove = Lists.newArrayList();
         for (Entry<Range<K>, V> entry : entrySet()) {
@@ -508,7 +558,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
           public boolean remove(@Nullable Object o) {
             return SubRangeMapAsMap.this.remove(o) != null;
           }
-          
+
           @Override
           public boolean retainAll(Collection<?> c) {
             return removeEntryIf(compose(not(in(c)), Maps.<Range<K>>keyFunction()));
@@ -526,57 +576,61 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
 
           @Override
           public Iterator<Entry<Range<K>, V>> iterator() {
-            if (subRange.isEmpty()) {
-              return Iterators.emptyIterator();
-            }
-            Cut<K> cutToStart = MoreObjects.firstNonNull(
-                entriesByLowerBound.floorKey(subRange.lowerBound), subRange.lowerBound);
-            final Iterator<RangeMapEntry<K, V>> backingItr = 
-                entriesByLowerBound.tailMap(cutToStart, true).values().iterator();
-            return new AbstractIterator<Entry<Range<K>, V>>() {
-
-              @Override
-              protected Entry<Range<K>, V> computeNext() {
-                while (backingItr.hasNext()) {
-                  RangeMapEntry<K, V> entry = backingItr.next();
-                  if (entry.getLowerBound().compareTo(subRange.upperBound) >= 0) {
-                    break;
-                  } else if (entry.getUpperBound().compareTo(subRange.lowerBound) > 0) {
-                    // this might not be true e.g. at the start of the iteration
-                    return Maps.immutableEntry(
-                        entry.getKey().intersection(subRange), entry.getValue());
-                  }
-                }
-                return endOfData();
-              }
-            };
+            return entryIterator();
           }
-          
+
           @Override
           public boolean retainAll(Collection<?> c) {
             return removeEntryIf(not(in(c)));
           }
-          
+
           @Override
           public int size() {
             return Iterators.size(iterator());
           }
-          
+
           @Override
           public boolean isEmpty() {
             return !iterator().hasNext();
           }
         };
       }
-      
+
+      Iterator<Entry<Range<K>, V>> entryIterator() {
+        if (subRange.isEmpty()) {
+          return Iterators.emptyIterator();
+        }
+        Cut<K> cutToStart =
+            MoreObjects.firstNonNull(
+                entriesByLowerBound.floorKey(subRange.lowerBound), subRange.lowerBound);
+        final Iterator<RangeMapEntry<K, V>> backingItr =
+            entriesByLowerBound.tailMap(cutToStart, true).values().iterator();
+        return new AbstractIterator<Entry<Range<K>, V>>() {
+
+          @Override
+          protected Entry<Range<K>, V> computeNext() {
+            while (backingItr.hasNext()) {
+              RangeMapEntry<K, V> entry = backingItr.next();
+              if (entry.getLowerBound().compareTo(subRange.upperBound) >= 0) {
+                return endOfData();
+              } else if (entry.getUpperBound().compareTo(subRange.lowerBound) > 0) {
+                // this might not be true e.g. at the start of the iteration
+                return Maps.immutableEntry(entry.getKey().intersection(subRange), entry.getValue());
+              }
+            }
+            return endOfData();
+          }
+        };
+      }
+
       @Override
       public Collection<V> values() {
-        return new Maps.Values<Range<K>, V>(this) {          
+        return new Maps.Values<Range<K>, V>(this) {
           @Override
           public boolean removeAll(Collection<?> c) {
-            return removeEntryIf(compose(in(c), Maps.<V>valueFunction()));            
+            return removeEntryIf(compose(in(c), Maps.<V>valueFunction()));
           }
-          
+
           @Override
           public boolean retainAll(Collection<?> c) {
             return removeEntryIf(compose(not(in(c)), Maps.<V>valueFunction()));
diff --git a/guava/src/com/google/common/collect/TreeRangeSet.java b/guava/src/com/google/common/collect/TreeRangeSet.java
index 606b3bc..9bb5c2f 100644
--- a/guava/src/com/google/common/collect/TreeRangeSet.java
+++ b/guava/src/com/google/common/collect/TreeRangeSet.java
@@ -41,11 +41,9 @@ import javax.annotation.Nullable;
  */
 @Beta
 @GwtIncompatible("uses NavigableMap")
-public class TreeRangeSet<C extends Comparable<?>>
-    extends AbstractRangeSet<C> {
+public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> {
 
-  @VisibleForTesting
-  final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
+  @VisibleForTesting final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
 
   /**
    * Creates an empty {@code TreeRangeSet} instance.
@@ -53,7 +51,7 @@ public class TreeRangeSet<C extends Comparable<?>>
   public static <C extends Comparable<?>> TreeRangeSet<C> create() {
     return new TreeRangeSet<C>(new TreeMap<Cut<C>, Range<C>>());
   }
-  
+
   /**
    * Returns a {@code TreeRangeSet} initialized with the ranges in the specified range set.
    */
@@ -68,17 +66,33 @@ public class TreeRangeSet<C extends Comparable<?>>
   }
 
   private transient Set<Range<C>> asRanges;
+  private transient Set<Range<C>> asDescendingSetOfRanges;
 
   @Override
   public Set<Range<C>> asRanges() {
     Set<Range<C>> result = asRanges;
-    return (result == null) ? asRanges = new AsRanges() : result;
+    return (result == null) ? asRanges = new AsRanges(rangesByLowerBound.values()) : result;
+  }
+
+  @Override
+  public Set<Range<C>> asDescendingSetOfRanges() {
+    Set<Range<C>> result = asDescendingSetOfRanges;
+    return (result == null)
+        ? asDescendingSetOfRanges = new AsRanges(rangesByLowerBound.descendingMap().values())
+        : result;
   }
 
   final class AsRanges extends ForwardingCollection<Range<C>> implements Set<Range<C>> {
+
+    final Collection<Range<C>> delegate;
+
+    AsRanges(Collection<Range<C>> delegate) {
+      this.delegate = delegate;
+    }
+
     @Override
     protected Collection<Range<C>> delegate() {
-      return rangesByLowerBound.values();
+      return delegate;
     }
 
     @Override
@@ -111,7 +125,7 @@ public class TreeRangeSet<C extends Comparable<?>>
     Entry<Cut<C>, Range<C>> floorEntry = rangesByLowerBound.floorEntry(range.lowerBound);
     return floorEntry != null && floorEntry.getValue().encloses(range);
   }
-  
+
   @Nullable
   private Range<C> rangeEnclosing(Range<C> range) {
     checkNotNull(range);
@@ -236,18 +250,18 @@ public class TreeRangeSet<C extends Comparable<?>>
     RangeSet<C> result = complement;
     return (result == null) ? complement = new Complement() : result;
   }
-  
+
   @VisibleForTesting
   static final class RangesByUpperBound<C extends Comparable<?>>
       extends AbstractNavigableMap<Cut<C>, Range<C>> {
     private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
-    
+
     /**
      * upperBoundWindow represents the headMap/subMap/tailMap view of the entire "ranges by upper
      * bound" map; it's a constraint on the *keys*, and does not affect the values.
      */
     private final Range<Cut<C>> upperBoundWindow;
-    
+
     RangesByUpperBound(NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
       this.rangesByLowerBound = rangesByLowerBound;
       this.upperBoundWindow = Range.all();
@@ -270,9 +284,10 @@ public class TreeRangeSet<C extends Comparable<?>>
     @Override
     public NavigableMap<Cut<C>, Range<C>> subMap(
         Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
-      return subMap(Range.range(
-          fromKey, BoundType.forBoolean(fromInclusive),
-          toKey, BoundType.forBoolean(toInclusive)));
+      return subMap(
+          Range.range(
+              fromKey, BoundType.forBoolean(fromInclusive),
+              toKey, BoundType.forBoolean(toInclusive)));
     }
 
     @Override
@@ -332,8 +347,10 @@ public class TreeRangeSet<C extends Comparable<?>>
         } else if (upperBoundWindow.lowerBound.isLessThan(lowerEntry.getValue().upperBound)) {
           backingItr = rangesByLowerBound.tailMap(lowerEntry.getKey(), true).values().iterator();
         } else {
-          backingItr = rangesByLowerBound.tailMap(upperBoundWindow.lowerEndpoint(), true)
-              .values().iterator();
+          backingItr = rangesByLowerBound
+              .tailMap(upperBoundWindow.lowerEndpoint(), true)
+              .values()
+              .iterator();
         }
       }
       return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
@@ -356,8 +373,11 @@ public class TreeRangeSet<C extends Comparable<?>>
     Iterator<Entry<Cut<C>, Range<C>>> descendingEntryIterator() {
       Collection<Range<C>> candidates;
       if (upperBoundWindow.hasUpperBound()) {
-        candidates = rangesByLowerBound.headMap(upperBoundWindow.upperEndpoint(), false)
-            .descendingMap().values();
+        candidates =
+            rangesByLowerBound
+                .headMap(upperBoundWindow.upperEndpoint(), false)
+                .descendingMap()
+                .values();
       } else {
         candidates = rangesByLowerBound.descendingMap().values();
       }
@@ -373,7 +393,7 @@ public class TreeRangeSet<C extends Comparable<?>>
             return endOfData();
           }
           Range<C> range = backingItr.next();
-          return upperBoundWindow.lowerBound.isLessThan(range.upperBound) 
+          return upperBoundWindow.lowerBound.isLessThan(range.upperBound)
               ? Maps.immutableEntry(range.upperBound, range)
               : endOfData();
         }
@@ -387,7 +407,7 @@ public class TreeRangeSet<C extends Comparable<?>>
       }
       return Iterators.size(entryIterator());
     }
-    
+
     @Override
     public boolean isEmpty() {
       return upperBoundWindow.equals(Range.all())
@@ -395,25 +415,25 @@ public class TreeRangeSet<C extends Comparable<?>>
           : !entryIterator().hasNext();
     }
   }
-  
+
   private static final class ComplementRangesByLowerBound<C extends Comparable<?>>
       extends AbstractNavigableMap<Cut<C>, Range<C>> {
     private final NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound;
     private final NavigableMap<Cut<C>, Range<C>> positiveRangesByUpperBound;
-    
+
     /**
      * complementLowerBoundWindow represents the headMap/subMap/tailMap view of the entire
      * "complement ranges by lower bound" map; it's a constraint on the *keys*, and does not affect
      * the values.
      */
     private final Range<Cut<C>> complementLowerBoundWindow;
-    
+
     ComplementRangesByLowerBound(NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound) {
       this(positiveRangesByLowerBound, Range.<Cut<C>>all());
     }
 
-    private ComplementRangesByLowerBound(NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound,
-        Range<Cut<C>> window) {
+    private ComplementRangesByLowerBound(
+        NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound, Range<Cut<C>> window) {
       this.positiveRangesByLowerBound = positiveRangesByLowerBound;
       this.positiveRangesByUpperBound = new RangesByUpperBound<C>(positiveRangesByLowerBound);
       this.complementLowerBoundWindow = window;
@@ -421,7 +441,7 @@ public class TreeRangeSet<C extends Comparable<?>>
 
     private NavigableMap<Cut<C>, Range<C>> subMap(Range<Cut<C>> subWindow) {
       if (!complementLowerBoundWindow.isConnected(subWindow)) {
-        return ImmutableSortedMap.of(); 
+        return ImmutableSortedMap.of();
       } else {
         subWindow = subWindow.intersection(complementLowerBoundWindow);
         return new ComplementRangesByLowerBound<C>(positiveRangesByLowerBound, subWindow);
@@ -431,9 +451,10 @@ public class TreeRangeSet<C extends Comparable<?>>
     @Override
     public NavigableMap<Cut<C>, Range<C>> subMap(
         Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
-      return subMap(Range.range(
-          fromKey, BoundType.forBoolean(fromInclusive),
-          toKey, BoundType.forBoolean(toInclusive)));
+      return subMap(
+          Range.range(
+              fromKey, BoundType.forBoolean(fromInclusive),
+              toKey, BoundType.forBoolean(toInclusive)));
     }
 
     @Override
@@ -464,17 +485,20 @@ public class TreeRangeSet<C extends Comparable<?>>
        */
       Collection<Range<C>> positiveRanges;
       if (complementLowerBoundWindow.hasLowerBound()) {
-        positiveRanges = positiveRangesByUpperBound.tailMap(
-            complementLowerBoundWindow.lowerEndpoint(),
-            complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values();
+        positiveRanges =
+            positiveRangesByUpperBound
+                .tailMap(
+                    complementLowerBoundWindow.lowerEndpoint(),
+                    complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
+                .values();
       } else {
         positiveRanges = positiveRangesByUpperBound.values();
       }
-      final PeekingIterator<Range<C>> positiveItr = Iterators.peekingIterator(
-          positiveRanges.iterator());
+      final PeekingIterator<Range<C>> positiveItr =
+          Iterators.peekingIterator(positiveRanges.iterator());
       final Cut<C> firstComplementRangeLowerBound;
-      if (complementLowerBoundWindow.contains(Cut.<C>belowAll()) && 
-          (!positiveItr.hasNext() || positiveItr.peek().lowerBound != Cut.<C>belowAll())) {
+      if (complementLowerBoundWindow.contains(Cut.<C>belowAll())
+          && (!positiveItr.hasNext() || positiveItr.peek().lowerBound != Cut.<C>belowAll())) {
         firstComplementRangeLowerBound = Cut.belowAll();
       } else if (positiveItr.hasNext()) {
         firstComplementRangeLowerBound = positiveItr.next().upperBound;
@@ -514,18 +538,24 @@ public class TreeRangeSet<C extends Comparable<?>>
        * firstComplementRangeUpperBound. (Positive range upper bounds correspond to complement range
        * lower bounds.)
        */
-      Cut<C> startingPoint = complementLowerBoundWindow.hasUpperBound()
-          ? complementLowerBoundWindow.upperEndpoint()
-          : Cut.<C>aboveAll();
-      boolean inclusive = complementLowerBoundWindow.hasUpperBound()
-          && complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED;
+      Cut<C> startingPoint =
+          complementLowerBoundWindow.hasUpperBound()
+              ? complementLowerBoundWindow.upperEndpoint()
+              : Cut.<C>aboveAll();
+      boolean inclusive =
+          complementLowerBoundWindow.hasUpperBound()
+              && complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED;
       final PeekingIterator<Range<C>> positiveItr =
-          Iterators.peekingIterator(positiveRangesByUpperBound.headMap(startingPoint, inclusive)
-              .descendingMap().values().iterator());
+          Iterators.peekingIterator(
+              positiveRangesByUpperBound
+                  .headMap(startingPoint, inclusive)
+                  .descendingMap()
+                  .values()
+                  .iterator());
       Cut<C> cut;
       if (positiveItr.hasNext()) {
-        cut = (positiveItr.peek().upperBound == Cut.<C>aboveAll()) 
-            ? positiveItr.next().lowerBound 
+        cut = (positiveItr.peek().upperBound == Cut.<C>aboveAll())
+            ? positiveItr.next().lowerBound
             : positiveRangesByLowerBound.higherKey(positiveItr.peek().upperBound);
       } else if (!complementLowerBoundWindow.contains(Cut.<C>belowAll())
           || positiveRangesByLowerBound.containsKey(Cut.belowAll())) {
@@ -551,8 +581,7 @@ public class TreeRangeSet<C extends Comparable<?>>
               return Maps.immutableEntry(negativeRange.lowerBound, negativeRange);
             }
           } else if (complementLowerBoundWindow.lowerBound.isLessThan(Cut.<C>belowAll())) {
-            Range<C> negativeRange =
-                Range.create(Cut.<C>belowAll(), nextComplementRangeUpperBound);
+            Range<C> negativeRange = Range.create(Cut.<C>belowAll(), nextComplementRangeUpperBound);
             nextComplementRangeUpperBound = Cut.belowAll();
             return Maps.immutableEntry(Cut.<C>belowAll(), negativeRange);
           }
@@ -610,7 +639,7 @@ public class TreeRangeSet<C extends Comparable<?>>
     public boolean contains(C value) {
       return !TreeRangeSet.this.contains(value);
     }
-    
+
     @Override
     public RangeSet<C> complement() {
       return TreeRangeSet.this;
@@ -634,7 +663,9 @@ public class TreeRangeSet<C extends Comparable<?>>
     private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
     private final NavigableMap<Cut<C>, Range<C>> rangesByUpperBound;
 
-    private SubRangeSetRangesByLowerBound(Range<Cut<C>> lowerBoundWindow, Range<C> restriction,
+    private SubRangeSetRangesByLowerBound(
+        Range<Cut<C>> lowerBoundWindow,
+        Range<C> restriction,
         NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
       this.lowerBoundWindow = checkNotNull(lowerBoundWindow);
       this.restriction = checkNotNull(restriction);
@@ -654,8 +685,12 @@ public class TreeRangeSet<C extends Comparable<?>>
     @Override
     public NavigableMap<Cut<C>, Range<C>> subMap(
         Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
-      return subMap(Range.range(
-          fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive)));
+      return subMap(
+          Range.range(
+              fromKey,
+              BoundType.forBoolean(fromInclusive),
+              toKey,
+              BoundType.forBoolean(toInclusive)));
     }
 
     @Override
@@ -685,7 +720,8 @@ public class TreeRangeSet<C extends Comparable<?>>
         try {
           @SuppressWarnings("unchecked") // we catch CCE's
           Cut<C> cut = (Cut<C>) key;
-          if (!lowerBoundWindow.contains(cut) || cut.compareTo(restriction.lowerBound) < 0
+          if (!lowerBoundWindow.contains(cut)
+              || cut.compareTo(restriction.lowerBound) < 0
               || cut.compareTo(restriction.upperBound) >= 0) {
             return null;
           } else if (cut.equals(restriction.lowerBound)) {
@@ -721,11 +757,17 @@ public class TreeRangeSet<C extends Comparable<?>>
             rangesByUpperBound.tailMap(restriction.lowerBound, false).values().iterator();
       } else {
         // starts at the first range with lower bound above lowerBoundWindow.lowerBound
-        completeRangeItr = rangesByLowerBound.tailMap(lowerBoundWindow.lowerBound.endpoint(),
-            lowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values().iterator();
+        completeRangeItr =
+            rangesByLowerBound
+                .tailMap(
+                    lowerBoundWindow.lowerBound.endpoint(),
+                    lowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
+                .values()
+                .iterator();
       }
-      final Cut<Cut<C>> upperBoundOnLowerBounds = Ordering.natural()
-          .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
+      final Cut<Cut<C>> upperBoundOnLowerBounds =
+          Ordering.natural()
+              .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
       return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
         @Override
         protected Entry<Cut<C>, Range<C>> computeNext() {
@@ -748,12 +790,17 @@ public class TreeRangeSet<C extends Comparable<?>>
       if (restriction.isEmpty()) {
         return Iterators.emptyIterator();
       }
-      Cut<Cut<C>> upperBoundOnLowerBounds = Ordering.natural()
-          .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
-      final Iterator<Range<C>> completeRangeItr = rangesByLowerBound.headMap(
-          upperBoundOnLowerBounds.endpoint(),
-          upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED)
-          .descendingMap().values().iterator();
+      Cut<Cut<C>> upperBoundOnLowerBounds =
+          Ordering.natural()
+              .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
+      final Iterator<Range<C>> completeRangeItr =
+          rangesByLowerBound
+              .headMap(
+                  upperBoundOnLowerBounds.endpoint(),
+                  upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED)
+              .descendingMap()
+              .values()
+              .iterator();
       return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
         @Override
         protected Entry<Cut<C>, Range<C>> computeNext() {
@@ -779,12 +826,12 @@ public class TreeRangeSet<C extends Comparable<?>>
       return Iterators.size(entryIterator());
     }
   }
-  
+
   @Override
   public RangeSet<C> subRangeSet(Range<C> view) {
     return view.equals(Range.<C>all()) ? this : new SubRangeSet(view);
   }
-  
+
   private final class SubRangeSet extends TreeRangeSet<C> {
     private final Range<C> restriction;
 
@@ -815,8 +862,11 @@ public class TreeRangeSet<C extends Comparable<?>>
 
     @Override
     public void add(Range<C> rangeToAdd) {
-      checkArgument(restriction.encloses(rangeToAdd), "Cannot add range %s to subRangeSet(%s)",
-          rangeToAdd, restriction);
+      checkArgument(
+          restriction.encloses(rangeToAdd),
+          "Cannot add range %s to subRangeSet(%s)",
+          rangeToAdd,
+          restriction);
       super.add(rangeToAdd);
     }
 
diff --git a/guava/src/com/google/common/collect/TreeTraverser.java b/guava/src/com/google/common/collect/TreeTraverser.java
index 60459ae..2f3183c 100644
--- a/guava/src/com/google/common/collect/TreeTraverser.java
+++ b/guava/src/com/google/common/collect/TreeTraverser.java
@@ -52,7 +52,7 @@ import java.util.Queue;
 @Beta
 @GwtCompatible(emulated = true)
 public abstract class TreeTraverser<T> {
-  // TODO(user): make this GWT-compatible when we've checked in ArrayDeque emulation
+  // TODO(lowasser): make this GWT-compatible when we've checked in ArrayDeque emulation
 
   /**
    * Returns the children of the specified node.  Must not contain null.
diff --git a/guava/src/com/google/common/collect/UnmodifiableIterator.java b/guava/src/com/google/common/collect/UnmodifiableIterator.java
index 55ceef9..73e8c90 100644
--- a/guava/src/com/google/common/collect/UnmodifiableIterator.java
+++ b/guava/src/com/google/common/collect/UnmodifiableIterator.java
@@ -23,8 +23,12 @@ import java.util.Iterator;
 /**
  * An iterator that does not support {@link #remove}.
  *
+ * <p>{@code UnmodifiableIterator} is used primarily in conjunction with implementations of
+ * {@link ImmutableCollection}, such as {@link ImmutableList}. You can, however, convert an existing
+ * iterator to an {@code UnmodifiableIterator} using {@link Iterators#unmodifiableIterator}.
+ *
  * @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
  */
 @GwtCompatible
 public abstract class UnmodifiableIterator<E> implements Iterator<E> {
diff --git a/guava/src/com/google/common/collect/UnmodifiableListIterator.java b/guava/src/com/google/common/collect/UnmodifiableListIterator.java
index 8e535a3..37e1bbf 100644
--- a/guava/src/com/google/common/collect/UnmodifiableListIterator.java
+++ b/guava/src/com/google/common/collect/UnmodifiableListIterator.java
@@ -28,8 +28,8 @@ import java.util.ListIterator;
  * @author Louis Wasserman
  */
 @GwtCompatible
-public abstract class UnmodifiableListIterator<E>
-    extends UnmodifiableIterator<E> implements ListIterator<E> {
+public abstract class UnmodifiableListIterator<E> extends UnmodifiableIterator<E>
+    implements ListIterator<E> {
   /** Constructor for use by subclasses. */
   protected UnmodifiableListIterator() {}
 
@@ -39,7 +39,9 @@ public abstract class UnmodifiableListIterator<E>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final void add(E e) {
+  @Deprecated
+  @Override
+  public final void add(E e) {
     throw new UnsupportedOperationException();
   }
 
@@ -49,7 +51,9 @@ public abstract class UnmodifiableListIterator<E>
    * @throws UnsupportedOperationException always
    * @deprecated Unsupported operation.
    */
-  @Deprecated @Override public final void set(E e) {
+  @Deprecated
+  @Override
+  public final void set(E e) {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
index 4b353cb..446da96 100644
--- a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
@@ -26,12 +26,12 @@ import java.util.NavigableSet;
  * Implementation of {@link Multisets#unmodifiableSortedMultiset(SortedMultiset)},
  * split out into its own file so it can be GWT emulated (to deal with the differing
  * elementSet() types in GWT and non-GWT).
- * 
+ *
  * @author Louis Wasserman
  */
 @GwtCompatible(emulated = true)
-final class UnmodifiableSortedMultiset<E>
-    extends UnmodifiableMultiset<E> implements SortedMultiset<E> {
+final class UnmodifiableSortedMultiset<E> extends UnmodifiableMultiset<E>
+    implements SortedMultiset<E> {
   UnmodifiableSortedMultiset(SortedMultiset<E> delegate) {
     super(delegate);
   }
@@ -62,8 +62,7 @@ final class UnmodifiableSortedMultiset<E>
   public SortedMultiset<E> descendingMultiset() {
     UnmodifiableSortedMultiset<E> result = descendingMultiset;
     if (result == null) {
-      result = new UnmodifiableSortedMultiset<E>(
-          delegate().descendingMultiset());
+      result = new UnmodifiableSortedMultiset<E>(delegate().descendingMultiset());
       result.descendingMultiset = this;
       return descendingMultiset = result;
     }
@@ -92,23 +91,20 @@ final class UnmodifiableSortedMultiset<E>
 
   @Override
   public SortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
-    return Multisets.unmodifiableSortedMultiset(
-        delegate().headMultiset(upperBound, boundType));
+    return Multisets.unmodifiableSortedMultiset(delegate().headMultiset(upperBound, boundType));
   }
 
   @Override
   public SortedMultiset<E> subMultiset(
-      E lowerBound, BoundType lowerBoundType,
-      E upperBound, BoundType upperBoundType) {
-    return Multisets.unmodifiableSortedMultiset(delegate().subMultiset(
-        lowerBound, lowerBoundType, upperBound, upperBoundType));
+      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
+    return Multisets.unmodifiableSortedMultiset(
+        delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType));
   }
 
   @Override
   public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
-    return Multisets.unmodifiableSortedMultiset(
-        delegate().tailMultiset(lowerBound, boundType));
+    return Multisets.unmodifiableSortedMultiset(delegate().tailMultiset(lowerBound, boundType));
   }
 
   private static final long serialVersionUID = 0;
-}
\ No newline at end of file
+}
diff --git a/guava/src/com/google/common/collect/UsingToStringOrdering.java b/guava/src/com/google/common/collect/UsingToStringOrdering.java
index adb6aa7..d4ce5bb 100644
--- a/guava/src/com/google/common/collect/UsingToStringOrdering.java
+++ b/guava/src/com/google/common/collect/UsingToStringOrdering.java
@@ -25,11 +25,11 @@ import java.io.Serializable;
  * values.
  */
 @GwtCompatible(serializable = true)
-final class UsingToStringOrdering
-    extends Ordering<Object> implements Serializable {
+final class UsingToStringOrdering extends Ordering<Object> implements Serializable {
   static final UsingToStringOrdering INSTANCE = new UsingToStringOrdering();
 
-  @Override public int compare(Object left, Object right) {
+  @Override
+  public int compare(Object left, Object right) {
     return left.toString().compareTo(right.toString());
   }
 
@@ -38,7 +38,8 @@ final class UsingToStringOrdering
     return INSTANCE;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Ordering.usingToString()";
   }
 
diff --git a/guava/src/com/google/common/collect/WellBehavedMap.java b/guava/src/com/google/common/collect/WellBehavedMap.java
index c68cc5e..16993d0 100644
--- a/guava/src/com/google/common/collect/WellBehavedMap.java
+++ b/guava/src/com/google/common/collect/WellBehavedMap.java
@@ -17,6 +17,7 @@
 package com.google.common.collect;
 
 import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.Iterator;
 import java.util.Map;
@@ -52,11 +53,13 @@ final class WellBehavedMap<K, V> extends ForwardingMap<K, V> {
     return new WellBehavedMap<K, V>(delegate);
   }
 
-  @Override protected Map<K, V> delegate() {
+  @Override
+  protected Map<K, V> delegate() {
     return delegate;
   }
 
-  @Override public Set<Entry<K, V>> entrySet() {
+  @Override
+  public Set<Entry<K, V>> entrySet() {
     Set<Entry<K, V>> es = entrySet;
     if (es != null) {
       return es;
@@ -64,6 +67,7 @@ final class WellBehavedMap<K, V> extends ForwardingMap<K, V> {
     return entrySet = new EntrySet();
   }
 
+  @WeakOuter
   private final class EntrySet extends Maps.EntrySet<K, V> {
     @Override
     Map<K, V> map() {
diff --git a/guava/src/com/google/common/escape/CharEscaper.java b/guava/src/com/google/common/escape/CharEscaper.java
index 4be21a6..2648540 100644
--- a/guava/src/com/google/common/escape/CharEscaper.java
+++ b/guava/src/com/google/common/escape/CharEscaper.java
@@ -34,9 +34,9 @@ import com.google.common.annotations.GwtCompatible;
  * <p>A {@code CharEscaper} instance is required to be stateless, and safe when used concurrently by
  * multiple threads.
  *
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link com.google.common.xml.XmlEscapers}, and {@link
- * SourceCodeEscapers}. To create your own escapers extend this class and implement the {@link
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers extend this class and implement the {@link
  * #escape(char)} method.
  *
  * @author Sven Mawson
diff --git a/guava/src/com/google/common/escape/Escaper.java b/guava/src/com/google/common/escape/Escaper.java
index 396a388..f0ddfc1 100644
--- a/guava/src/com/google/common/escape/Escaper.java
+++ b/guava/src/com/google/common/escape/Escaper.java
@@ -48,10 +48,10 @@ import com.google.common.base.Function;
  * extend one of these classes. If you find that you are unable to achieve the desired behavior
  * using either of these classes, please contact the Java libraries team for advice.
  *
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link com.google.common.xml.XmlEscapers}, and {@link
- * SourceCodeEscapers}. To create your own escapers, use {@link CharEscaperBuilder}, or extend
- * {@code CharEscaper} or {@code UnicodeEscaper}.
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers, use {@link CharEscaperBuilder}, or extend {@code CharEscaper}
+ * or {@code UnicodeEscaper}.
  *
  * @author David Beaumont
  * @since 15.0
diff --git a/guava/src/com/google/common/escape/UnicodeEscaper.java b/guava/src/com/google/common/escape/UnicodeEscaper.java
index dec65e9..92e98b9 100644
--- a/guava/src/com/google/common/escape/UnicodeEscaper.java
+++ b/guava/src/com/google/common/escape/UnicodeEscaper.java
@@ -46,10 +46,9 @@ import com.google.common.annotations.GwtCompatible;
  * <p>A {@code UnicodeEscaper} instance is required to be stateless, and safe
  * when used concurrently by multiple threads.
  *
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link
- * com.google.common.xml.XmlEscapers}, and {@link SourceCodeEscapers}. To create
- * your own escapers extend this class and implement the {@link #escape(int)}
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers extend this class and implement the {@link #escape(int)}
  * method.
  *
  * @author David Beaumont
diff --git a/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java b/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java
deleted file mode 100644
index b1c38ff..0000000
--- a/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.eventbus;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.UncheckedExecutionException;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * A {@link SubscriberFindingStrategy} for collecting all event subscriber methods that are marked
- * with the {@link Subscribe} annotation.
- *
- * @author Cliff Biffle
- * @author Louis Wasserman
- */
-class AnnotatedSubscriberFinder implements SubscriberFindingStrategy {
-  /**
-   * A thread-safe cache that contains the mapping from each class to all methods in that class and
-   * all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
-   * instances of this class; this greatly improves performance if multiple EventBus instances are
-   * created and objects of the same class are registered on all of them.
-   */
-  private static final LoadingCache<Class<?>, ImmutableList<Method>> subscriberMethodsCache =
-      CacheBuilder.newBuilder()
-          .weakKeys()
-          .build(new CacheLoader<Class<?>, ImmutableList<Method>>() {
-            @Override
-            public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
-              return getAnnotatedMethodsInternal(concreteClass);
-            }
-          });
-
-  /**
-   * {@inheritDoc}
-   *
-   * This implementation finds all methods marked with a {@link Subscribe} annotation.
-   */
-  @Override
-  public Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object listener) {
-    Multimap<Class<?>, EventSubscriber> methodsInListener = HashMultimap.create();
-    Class<?> clazz = listener.getClass();
-    for (Method method : getAnnotatedMethods(clazz)) {
-      Class<?>[] parameterTypes = method.getParameterTypes();
-      Class<?> eventType = parameterTypes[0];
-      EventSubscriber subscriber = makeSubscriber(listener, method);
-      methodsInListener.put(eventType, subscriber);
-    }
-    return methodsInListener;
-  }
-
-  private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
-    try {
-      return subscriberMethodsCache.getUnchecked(clazz);
-    } catch (UncheckedExecutionException e) {
-      throw Throwables.propagate(e.getCause());
-    }
-  }
-
-  private static final class MethodIdentifier {
-    private final String name;
-    private final List<Class<?>> parameterTypes;
-
-    MethodIdentifier(Method method) {
-      this.name = method.getName();
-      this.parameterTypes = Arrays.asList(method.getParameterTypes());
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(name, parameterTypes);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-      if (o instanceof MethodIdentifier) {
-        MethodIdentifier ident = (MethodIdentifier) o;
-        return name.equals(ident.name) && parameterTypes.equals(ident.parameterTypes);
-      }
-      return false;
-    }
-  }
-
-  private static ImmutableList<Method> getAnnotatedMethodsInternal(Class<?> clazz) {
-    Set<? extends Class<?>> supers = TypeToken.of(clazz).getTypes().rawTypes();
-    Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
-    for (Class<?> superClazz : supers) {
-      for (Method superClazzMethod : superClazz.getMethods()) {
-        if (superClazzMethod.isAnnotationPresent(Subscribe.class)
-            && !superClazzMethod.isBridge()) {
-          Class<?>[] parameterTypes = superClazzMethod.getParameterTypes();
-          if (parameterTypes.length != 1) {
-            throw new IllegalArgumentException("Method " + superClazzMethod
-                + " has @Subscribe annotation, but requires " + parameterTypes.length
-                + " arguments.  Event subscriber methods must require a single argument.");
-          }
-
-          MethodIdentifier ident = new MethodIdentifier(superClazzMethod);
-          if (!identifiers.containsKey(ident)) {
-            identifiers.put(ident, superClazzMethod);
-          }
-        }
-      }
-    }
-    return ImmutableList.copyOf(identifiers.values());
-  }
-
-  /**
-   * Creates an {@code EventSubscriber} for subsequently calling {@code method} on
-   * {@code listener}.
-   * Selects an EventSubscriber implementation based on the annotations on
-   * {@code method}.
-   *
-   * @param listener  object bearing the event subscriber method.
-   * @param method  the event subscriber method to wrap in an EventSubscriber.
-   * @return an EventSubscriber that will call {@code method} on {@code listener}
-   *         when invoked.
-   */
-  private static EventSubscriber makeSubscriber(Object listener, Method method) {
-    EventSubscriber wrapper;
-    if (methodIsDeclaredThreadSafe(method)) {
-      wrapper = new EventSubscriber(listener, method);
-    } else {
-      wrapper = new SynchronizedEventSubscriber(listener, method);
-    }
-    return wrapper;
-  }
-
-  /**
-   * Checks whether {@code method} is thread-safe, as indicated by the
-   * {@link AllowConcurrentEvents} annotation.
-   *
-   * @param method  subscriber method to check.
-   * @return {@code true} if {@code subscriber} is marked as thread-safe,
-   *         {@code false} otherwise.
-   */
-  private static boolean methodIsDeclaredThreadSafe(Method method) {
-    return method.getAnnotation(AllowConcurrentEvents.class) != null;
-  }
-}
diff --git a/guava/src/com/google/common/eventbus/AsyncEventBus.java b/guava/src/com/google/common/eventbus/AsyncEventBus.java
index 4fd3550..a150a8a 100644
--- a/guava/src/com/google/common/eventbus/AsyncEventBus.java
+++ b/guava/src/com/google/common/eventbus/AsyncEventBus.java
@@ -16,11 +16,8 @@
 
 package com.google.common.eventbus;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import com.google.common.annotations.Beta;
 
-import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 
 /**
@@ -32,11 +29,6 @@ import java.util.concurrent.Executor;
  */
 @Beta
 public class AsyncEventBus extends EventBus {
-  private final Executor executor;
-
-  /** the queue of events is shared across all threads */
-  private final ConcurrentLinkedQueue<EventWithSubscriber> eventsToDispatch =
-      new ConcurrentLinkedQueue<EventWithSubscriber>();
 
   /**
    * Creates a new AsyncEventBus that will use {@code executor} to dispatch
@@ -48,8 +40,7 @@ public class AsyncEventBus extends EventBus {
    *        been posted to this event bus.
    */
   public AsyncEventBus(String identifier, Executor executor) {
-    super(identifier);
-    this.executor = checkNotNull(executor);
+    super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
   }
 
   /**
@@ -64,8 +55,7 @@ public class AsyncEventBus extends EventBus {
    * @since 16.0
    */
   public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
-    super(subscriberExceptionHandler);
-    this.executor = checkNotNull(executor);
+    super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
   }
 
   /**
@@ -77,45 +67,6 @@ public class AsyncEventBus extends EventBus {
    *        been posted to this event bus.
    */
   public AsyncEventBus(Executor executor) {
-    super("default");
-    this.executor = checkNotNull(executor);
-  }
-
-  @Override
-  void enqueueEvent(Object event, EventSubscriber subscriber) {
-    eventsToDispatch.offer(new EventWithSubscriber(event, subscriber));
-  }
-
-  /**
-   * Dispatch {@code events} in the order they were posted, regardless of
-   * the posting thread.
-   */
-  @SuppressWarnings("deprecation") // only deprecated for external subclasses
-  @Override
-  protected void dispatchQueuedEvents() {
-    while (true) {
-      EventWithSubscriber eventWithSubscriber = eventsToDispatch.poll();
-      if (eventWithSubscriber == null) {
-        break;
-      }
-
-      dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);
-    }
-  }
-
-  /**
-   * Calls the {@link #executor} to dispatch {@code event} to {@code subscriber}.
-   */
-  @Override
-  void dispatch(final Object event, final EventSubscriber subscriber) {
-    checkNotNull(event);
-    checkNotNull(subscriber);
-    executor.execute(
-        new Runnable() {
-          @Override
-          public void run() {
-            AsyncEventBus.super.dispatch(event, subscriber);
-          }
-        });
+    super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
   }
 }
diff --git a/guava/src/com/google/common/eventbus/DeadEvent.java b/guava/src/com/google/common/eventbus/DeadEvent.java
index 41f15d3..90929f7 100644
--- a/guava/src/com/google/common/eventbus/DeadEvent.java
+++ b/guava/src/com/google/common/eventbus/DeadEvent.java
@@ -19,6 +19,7 @@ package com.google.common.eventbus;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
 
 /**
  * Wraps an event that was posted, but which had no subscribers and thus could
@@ -68,4 +69,11 @@ public class DeadEvent {
     return event;
   }
 
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+      .add("source", source)
+      .add("event", event)
+      .toString();
+  }
 }
diff --git a/guava/src/com/google/common/eventbus/Dispatcher.java b/guava/src/com/google/common/eventbus/Dispatcher.java
new file mode 100644
index 0000000..c406c7e
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/Dispatcher.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 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.eventbus;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.Queues;
+
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Handler for dispatching events to subscribers, providing different event ordering guarantees that
+ * make sense for different situations.
+ *
+ * <p><b>Note:</b> The dispatcher is orthogonal to the subscriber's {@code Executor}. The dispatcher
+ * controls the order in which events are dispatched, while the executor controls how (i.e. on which
+ * thread) the subscriber is actually called when an event is dispatched to it.
+ *
+ * @author Colin Decker
+ */
+abstract class Dispatcher {
+
+  /**
+   * Returns a dispatcher that queues events that are posted reentrantly on a thread that is already
+   * dispatching an event, guaranteeing that all events posted on a single thread are dispatched to
+   * all subscribers in the order they are posted.
+   *
+   * <p>When all subscribers are dispatched to using a <i>direct</i> executor (which dispatches on
+   * the same thread that posts the event), this yields a breadth-first dispatch order on each
+   * thread. That is, all subscribers to a single event A will be called before any subscribers to
+   * any events B and C that are posted to the event bus by the subscribers to A.
+   */
+  static Dispatcher perThreadDispatchQueue() {
+    return new PerThreadQueuedDispatcher();
+  }
+
+  /**
+   * Returns a dispatcher that queues events that are posted in a single global queue. This
+   * behavior matches the original behavior of AsyncEventBus exactly, but is otherwise not
+   * especially useful. For async dispatch, an {@linkplain #immediate() immediate} dispatcher
+   * should generally be preferable.
+   */
+  static Dispatcher legacyAsync() {
+    return new LegacyAsyncDispatcher();
+  }
+
+  /**
+   * Returns a dispatcher that dispatches events to subscribers immediately as they're posted
+   * without using an intermediate queue to change the dispatch order. This is effectively a
+   * depth-first dispatch order, vs. breadth-first when using a queue.
+   */
+  static Dispatcher immediate() {
+    return ImmediateDispatcher.INSTANCE;
+  }
+
+  /**
+   * Dispatches the given {@code event} to the given {@code subscribers}.
+   */
+  abstract void dispatch(Object event, Iterator<Subscriber> subscribers);
+
+  /**
+   * Implementation of a {@link #perThreadDispatchQueue()} dispatcher.
+   */
+  private static final class PerThreadQueuedDispatcher extends Dispatcher {
+
+    // This dispatcher matches the original dispatch behavior of EventBus.
+
+    /**
+     * Per-thread queue of events to dispatch.
+     */
+    private final ThreadLocal<Queue<Event>> queue =
+        new ThreadLocal<Queue<Event>>() {
+          @Override
+          protected Queue<Event> initialValue() {
+            return Queues.newArrayDeque();
+          }
+        };
+
+    /**
+     * Per-thread dispatch state, used to avoid reentrant event dispatching.
+     */
+    private final ThreadLocal<Boolean> dispatching =
+        new ThreadLocal<Boolean>() {
+          @Override
+          protected Boolean initialValue() {
+            return false;
+          }
+        };
+
+    @Override
+    void dispatch(Object event, Iterator<Subscriber> subscribers) {
+      checkNotNull(event);
+      checkNotNull(subscribers);
+      Queue<Event> queueForThread = queue.get();
+      queueForThread.offer(new Event(event, subscribers));
+
+      if (!dispatching.get()) {
+        dispatching.set(true);
+        try {
+          Event nextEvent;
+          while ((nextEvent = queueForThread.poll()) != null) {
+            while (nextEvent.subscribers.hasNext()) {
+              nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
+            }
+          }
+        } finally {
+          dispatching.remove();
+          queue.remove();
+        }
+      }
+    }
+
+    private static final class Event {
+      private final Object event;
+      private final Iterator<Subscriber> subscribers;
+
+      private Event(Object event, Iterator<Subscriber> subscribers) {
+        this.event = event;
+        this.subscribers = subscribers;
+      }
+    }
+  }
+
+  /**
+   * Implementation of a {@link #legacyAsync()} dispatcher.
+   */
+  private static final class LegacyAsyncDispatcher extends Dispatcher {
+
+    // This dispatcher matches the original dispatch behavior of AsyncEventBus.
+    //
+    // We can't really make any guarantees about the overall dispatch order for this dispatcher in
+    // a multithreaded environment for a couple reasons:
+    //
+    // 1. Subscribers to events posted on different threads can be interleaved with each other
+    //    freely. (A event on one thread, B event on another could yield any of
+    //    [a1, a2, a3, b1, b2], [a1, b2, a2, a3, b2], [a1, b2, b3, a2, a3], etc.)
+    // 2. It's possible for subscribers to actually be dispatched to in a different order than they
+    //    were added to the queue. It's easily possible for one thread to take the head of the
+    //    queue, immediately followed by another thread taking the next element in the queue. That
+    //    second thread can then dispatch to the subscriber it took before the first thread does.
+    //
+    // All this makes me really wonder if there's any value in queueing here at all. A dispatcher
+    // that simply loops through the subscribers and dispatches the event to each would actually
+    // probably provide a stronger order guarantee, though that order would obviously be different
+    // in some cases.
+
+    /**
+     * Global event queue.
+     */
+    private final ConcurrentLinkedQueue<EventWithSubscriber> queue =
+        Queues.newConcurrentLinkedQueue();
+
+    @Override
+    void dispatch(Object event, Iterator<Subscriber> subscribers) {
+      checkNotNull(event);
+      while (subscribers.hasNext()) {
+        queue.add(new EventWithSubscriber(event, subscribers.next()));
+      }
+
+      EventWithSubscriber e;
+      while ((e = queue.poll()) != null) {
+        e.subscriber.dispatchEvent(e.event);
+      }
+    }
+
+    private static final class EventWithSubscriber {
+      private final Object event;
+      private final Subscriber subscriber;
+
+      private EventWithSubscriber(Object event, Subscriber subscriber) {
+        this.event = event;
+        this.subscriber = subscriber;
+      }
+    }
+  }
+
+  /**
+   * Implementation of {@link #immediate()}.
+   */
+  private static final class ImmediateDispatcher extends Dispatcher {
+    private static final ImmediateDispatcher INSTANCE = new ImmediateDispatcher();
+
+    @Override
+    void dispatch(Object event, Iterator<Subscriber> subscribers) {
+      checkNotNull(event);
+      while (subscribers.hasNext()) {
+        subscribers.next().dispatchEvent(event);
+      }
+    }
+  }
+}
diff --git a/guava/src/com/google/common/eventbus/EventBus.java b/guava/src/com/google/common/eventbus/EventBus.java
index 6f3df55..08aa78d 100644
--- a/guava/src/com/google/common/eventbus/EventBus.java
+++ b/guava/src/com/google/common/eventbus/EventBus.java
@@ -19,25 +19,13 @@ package com.google.common.eventbus;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.SetMultimap;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.google.common.base.MoreObjects;
+import com.google.common.util.concurrent.MoreExecutors;
 
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Map.Entry;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.concurrent.Executor;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -104,7 +92,7 @@ import java.util.logging.Logger;
  * <p>This class is safe for concurrent use.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/EventBusExplained">
+ * "https://github.com/google/guava/wiki/EventBusExplained">
  * {@code EventBus}</a>.
  *
  * @author Cliff Biffle
@@ -113,56 +101,14 @@ import java.util.logging.Logger;
 @Beta
 public class EventBus {
 
-  /**
-   * A thread-safe cache for flattenHierarchy(). The Class class is immutable. This cache is shared
-   * across all EventBus instances, which greatly improves performance if multiple such instances
-   * are created and objects of the same class are posted on all of them.
-   */
-  private static final LoadingCache<Class<?>, Set<Class<?>>> flattenHierarchyCache =
-      CacheBuilder.newBuilder()
-          .weakKeys()
-          .build(new CacheLoader<Class<?>, Set<Class<?>>>() {
-            @SuppressWarnings({"unchecked", "rawtypes"}) // safe cast
-            @Override
-            public Set<Class<?>> load(Class<?> concreteClass) {
-              return (Set) TypeToken.of(concreteClass).getTypes().rawTypes();
-            }
-          });
-
-  /**
-   * All registered event subscribers, indexed by event type.
-   *
-   * <p>This SetMultimap is NOT safe for concurrent use; all access should be
-   * made after acquiring a read or write lock via {@link #subscribersByTypeLock}.
-   */
-  private final SetMultimap<Class<?>, EventSubscriber> subscribersByType =
-      HashMultimap.create();
-  private final ReadWriteLock subscribersByTypeLock = new ReentrantReadWriteLock();
-
-  /**
-   * Strategy for finding subscriber methods in registered objects.  Currently,
-   * only the {@link AnnotatedSubscriberFinder} is supported, but this is
-   * encapsulated for future expansion.
-   */
-  private final SubscriberFindingStrategy finder = new AnnotatedSubscriberFinder();
+  private static final Logger logger = Logger.getLogger(EventBus.class.getName());
 
-  /** queues of events for the current thread to dispatch */
-  private final ThreadLocal<Queue<EventWithSubscriber>> eventsToDispatch =
-      new ThreadLocal<Queue<EventWithSubscriber>>() {
-    @Override protected Queue<EventWithSubscriber> initialValue() {
-      return new LinkedList<EventWithSubscriber>();
-    }
-  };
-
-  /** true if the current thread is currently dispatching an event */
-  private final ThreadLocal<Boolean> isDispatching =
-      new ThreadLocal<Boolean>() {
-    @Override protected Boolean initialValue() {
-      return false;
-    }
-  };
+  private final String identifier;
+  private final Executor executor;
+  private final SubscriberExceptionHandler exceptionHandler;
 
-  private SubscriberExceptionHandler subscriberExceptionHandler;
+  private final SubscriberRegistry subscribers = new SubscriberRegistry(this);
+  private final Dispatcher dispatcher;
 
   /**
    * Creates a new EventBus named "default".
@@ -178,36 +124,68 @@ public class EventBus {
    *                    be a valid Java identifier.
    */
   public EventBus(String identifier) {
-    this(new LoggingSubscriberExceptionHandler(identifier));
+    this(identifier, MoreExecutors.directExecutor(),
+        Dispatcher.perThreadDispatchQueue(), LoggingHandler.INSTANCE);
   }
 
   /**
    * Creates a new EventBus with the given {@link SubscriberExceptionHandler}.
    * 
-   * @param subscriberExceptionHandler Handler for subscriber exceptions.
+   * @param exceptionHandler Handler for subscriber exceptions.
    * @since 16.0
    */
-  public EventBus(SubscriberExceptionHandler subscriberExceptionHandler) {
-    this.subscriberExceptionHandler = checkNotNull(subscriberExceptionHandler);
+  public EventBus(SubscriberExceptionHandler exceptionHandler) {
+    this("default",
+        MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);
+  }
+
+  EventBus(String identifier, Executor executor, Dispatcher dispatcher,
+      SubscriberExceptionHandler exceptionHandler) {
+    this.identifier = checkNotNull(identifier);
+    this.executor = checkNotNull(executor);
+    this.dispatcher = checkNotNull(dispatcher);
+    this.exceptionHandler = checkNotNull(exceptionHandler);
+  }
+
+  /**
+   * Returns the identifier for this event bus.
+   *
+   * @since 19.0
+   */
+  public final String identifier() {
+    return identifier;
+  }
+
+  /**
+   * Returns the default executor this event bus uses for dispatching events to subscribers.
+   */
+  final Executor executor() {
+    return executor;
+  }
+
+  /**
+   * Handles the given exception thrown by a subscriber with the given context.
+   */
+  void handleSubscriberException(Throwable e, SubscriberExceptionContext context) {
+    checkNotNull(e);
+    checkNotNull(context);
+    try {
+      exceptionHandler.handleException(e, context);
+    } catch (Throwable e2) {
+      // if the handler threw an exception... well, just log it
+      logger.log(Level.SEVERE,
+          String.format(Locale.ROOT, "Exception %s thrown while handling exception: %s", e2, e),
+          e2);
+    }
   }
 
   /**
    * Registers all subscriber methods on {@code object} to receive events.
-   * Subscriber methods are selected and classified using this EventBus's
-   * {@link SubscriberFindingStrategy}; the default strategy is the
-   * {@link AnnotatedSubscriberFinder}.
    *
    * @param object  object whose subscriber methods should be registered.
    */
   public void register(Object object) {
-    Multimap<Class<?>, EventSubscriber> methodsInListener =
-        finder.findAllSubscribers(object);
-    subscribersByTypeLock.writeLock().lock();
-    try {
-      subscribersByType.putAll(methodsInListener);
-    } finally {
-      subscribersByTypeLock.writeLock().unlock();
-    }
+    subscribers.register(object);
   }
 
   /**
@@ -217,24 +195,7 @@ public class EventBus {
    * @throws IllegalArgumentException if the object was not previously registered.
    */
   public void unregister(Object object) {
-    Multimap<Class<?>, EventSubscriber> methodsInListener = finder.findAllSubscribers(object);
-    for (Entry<Class<?>, Collection<EventSubscriber>> entry :
-          methodsInListener.asMap().entrySet()) {
-      Class<?> eventType = entry.getKey();
-      Collection<EventSubscriber> eventMethodsInListener = entry.getValue();
-
-      subscribersByTypeLock.writeLock().lock();
-      try {
-        Set<EventSubscriber> currentSubscribers = subscribersByType.get(eventType);
-        if (!currentSubscribers.containsAll(eventMethodsInListener)) {
-          throw new IllegalArgumentException(
-              "missing event subscriber for an annotated method. Is " + object + " registered?");
-        }
-        currentSubscribers.removeAll(eventMethodsInListener);
-      } finally {
-        subscribersByTypeLock.writeLock().unlock();
-      }
-    }
+    subscribers.unregister(object);
   }
 
   /**
@@ -249,151 +210,46 @@ public class EventBus {
    * @param event  event to post.
    */
   public void post(Object event) {
-    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
-
-    boolean dispatched = false;
-    for (Class<?> eventType : dispatchTypes) {
-      subscribersByTypeLock.readLock().lock();
-      try {
-        Set<EventSubscriber> wrappers = subscribersByType.get(eventType);
-
-        if (!wrappers.isEmpty()) {
-          dispatched = true;
-          for (EventSubscriber wrapper : wrappers) {
-            enqueueEvent(event, wrapper);
-          }
-        }
-      } finally {
-        subscribersByTypeLock.readLock().unlock();
-      }
-    }
-
-    if (!dispatched && !(event instanceof DeadEvent)) {
+    Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
+    if (eventSubscribers.hasNext()) {
+      dispatcher.dispatch(event, eventSubscribers);
+    } else if (!(event instanceof DeadEvent)) {
+      // the event had no subscribers and was not itself a DeadEvent
       post(new DeadEvent(this, event));
     }
-
-    dispatchQueuedEvents();
   }
 
-  /**
-   * Queue the {@code event} for dispatch during
-   * {@link #dispatchQueuedEvents()}. Events are queued in-order of occurrence
-   * so they can be dispatched in the same order.
-   */
-  void enqueueEvent(Object event, EventSubscriber subscriber) {
-    eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber));
-  }
-
-  /**
-   * Drain the queue of events to be dispatched. As the queue is being drained,
-   * new events may be posted to the end of the queue.
-   */
-  void dispatchQueuedEvents() {
-    // don't dispatch if we're already dispatching, that would allow reentrancy
-    // and out-of-order events. Instead, leave the events to be dispatched
-    // after the in-progress dispatch is complete.
-    if (isDispatching.get()) {
-      return;
-    }
-
-    isDispatching.set(true);
-    try {
-      Queue<EventWithSubscriber> events = eventsToDispatch.get();
-      EventWithSubscriber eventWithSubscriber;
-      while ((eventWithSubscriber = events.poll()) != null) {
-        dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);
-      }
-    } finally {
-      isDispatching.remove();
-      eventsToDispatch.remove();
-    }
-  }
-
-  /**
-   * Dispatches {@code event} to the subscriber in {@code wrapper}.  This method
-   * is an appropriate override point for subclasses that wish to make
-   * event delivery asynchronous.
-   *
-   * @param event  event to dispatch.
-   * @param wrapper  wrapper that will call the subscriber.
-   */
-  void dispatch(Object event, EventSubscriber wrapper) {
-    try {
-      wrapper.handleEvent(event);
-    } catch (InvocationTargetException e) {
-      try {
-        subscriberExceptionHandler.handleException(
-            e.getCause(),
-            new SubscriberExceptionContext(
-                this,
-                event,
-                wrapper.getSubscriber(),
-                wrapper.getMethod()));
-      } catch (Throwable t) {
-        // If the exception handler throws, log it. There isn't much else to do!
-        Logger.getLogger(EventBus.class.getName()).log(Level.SEVERE,
-             String.format(
-            "Exception %s thrown while handling exception: %s", t,
-            e.getCause()),
-            t);
-      }
-    }
-  }
-
-  /**
-   * Flattens a class's type hierarchy into a set of Class objects.  The set
-   * will include all superclasses (transitively), and all interfaces
-   * implemented by these superclasses.
-   *
-   * @param concreteClass  class whose type hierarchy will be retrieved.
-   * @return {@code clazz}'s complete type hierarchy, flattened and uniqued.
-   */
-  @VisibleForTesting
-  Set<Class<?>> flattenHierarchy(Class<?> concreteClass) {
-    try {
-      return flattenHierarchyCache.getUnchecked(concreteClass);
-    } catch (UncheckedExecutionException e) {
-      throw Throwables.propagate(e.getCause());
-    }
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .addValue(identifier)
+        .toString();
   }
 
   /**
    * Simple logging handler for subscriber exceptions.
    */
-  private static final class LoggingSubscriberExceptionHandler
-      implements SubscriberExceptionHandler {
-
-    /**
-     * Logger for event dispatch failures.  Named by the fully-qualified name of
-     * this class, followed by the identifier provided at construction.
-     */
-    private final Logger logger;
+  static final class LoggingHandler implements SubscriberExceptionHandler {
+    static final LoggingHandler INSTANCE = new LoggingHandler();
 
-    /**
-     * @param identifier a brief name for this bus, for logging purposes. Should
-     *        be a valid Java identifier.
-     */
-    public LoggingSubscriberExceptionHandler(String identifier) {
-      logger = Logger.getLogger(
-          EventBus.class.getName() + "." + checkNotNull(identifier));
+    @Override
+    public void handleException(Throwable exception, SubscriberExceptionContext context) {
+      Logger logger = logger(context);
+      if (logger.isLoggable(Level.SEVERE)) {
+        logger.log(Level.SEVERE, message(context), exception);
+      }
     }
 
-    @Override
-    public void handleException(Throwable exception,
-        SubscriberExceptionContext context) {
-      logger.log(Level.SEVERE, "Could not dispatch event: " 
-          + context.getSubscriber() + " to " + context.getSubscriberMethod(),
-          exception.getCause());
+    private static Logger logger(SubscriberExceptionContext context) {
+      return Logger.getLogger(EventBus.class.getName() + "." + context.getEventBus().identifier());
     }
-  }
 
-  /** simple struct representing an event and it's subscriber */
-  static class EventWithSubscriber {
-    final Object event;
-    final EventSubscriber subscriber;
-    public EventWithSubscriber(Object event, EventSubscriber subscriber) {
-      this.event = checkNotNull(event);
-      this.subscriber = checkNotNull(subscriber);
+    private static String message(SubscriberExceptionContext context) {
+      Method method = context.getSubscriberMethod();
+      return "Exception thrown by subscriber method "
+          + method.getName() + '(' + method.getParameterTypes()[0].getName() + ')'
+          + " on subscriber " + context.getSubscriber()
+          + " when dispatching event: " + context.getEvent();
     }
   }
 }
diff --git a/guava/src/com/google/common/eventbus/EventSubscriber.java b/guava/src/com/google/common/eventbus/EventSubscriber.java
deleted file mode 100644
index 058aeab..0000000
--- a/guava/src/com/google/common/eventbus/EventSubscriber.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.eventbus;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.base.Preconditions;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.annotation.Nullable;
-
-/**
- * Wraps a single-argument subscriber method on a specific object.
- *
- * <p>This class only verifies the suitability of the method and event type if
- * something fails.  Callers are expected to verify their uses of this class.
- *
- * <p>Two EventSubscribers are equivalent when they refer to the same method on the
- * same object (not class).   This property is used to ensure that no subscriber
- * method is registered more than once.
- *
- * @author Cliff Biffle
- */
-class EventSubscriber {
-
-  /** Object sporting the subscriber method. */
-  private final Object target;
-  /** Subscriber method. */
-  private final Method method;
-
-  /**
-   * Creates a new EventSubscriber to wrap {@code method} on @{code target}.
-   *
-   * @param target  object to which the method applies.
-   * @param method  subscriber method.
-   */
-  EventSubscriber(Object target, Method method) {
-    Preconditions.checkNotNull(target,
-        "EventSubscriber target cannot be null.");
-    Preconditions.checkNotNull(method, "EventSubscriber method cannot be null.");
-
-    this.target = target;
-    this.method = method;
-    method.setAccessible(true);
-  }
-
-  /**
-   * Invokes the wrapped subscriber method to handle {@code event}.
-   *
-   * @param event  event to handle
-   * @throws InvocationTargetException  if the wrapped method throws any
-   *     {@link Throwable} that is not an {@link Error} ({@code Error} instances are
-   *     propagated as-is).
-   */
-  public void handleEvent(Object event) throws InvocationTargetException {
-    checkNotNull(event);
-    try {
-      method.invoke(target, new Object[] { event });
-    } catch (IllegalArgumentException e) {
-      throw new Error("Method rejected target/argument: " + event, e);
-    } catch (IllegalAccessException e) {
-      throw new Error("Method became inaccessible: " + event, e);
-    } catch (InvocationTargetException e) {
-      if (e.getCause() instanceof Error) {
-        throw (Error) e.getCause();
-      }
-      throw e;
-    }
-  }
-
-  @Override public String toString() {
-    return "[wrapper " + method + "]";
-  }
-
-  @Override public int hashCode() {
-    final int PRIME = 31;
-    return (PRIME + method.hashCode()) * PRIME
-        + System.identityHashCode(target);
-  }
-
-  @Override public boolean equals(@Nullable Object obj) {
-    if (obj instanceof EventSubscriber) {
-      EventSubscriber that = (EventSubscriber) obj;
-      // Use == so that different equal instances will still receive events.
-      // We only guard against the case that the same object is registered
-      // multiple times
-      return target == that.target && method.equals(that.method);
-    }
-    return false;
-  }
-
-  public Object getSubscriber() {
-    return target;
-  }
-
-  public Method getMethod() {
-    return method;
-  }
-}
diff --git a/guava/src/com/google/common/eventbus/Subscriber.java b/guava/src/com/google/common/eventbus/Subscriber.java
new file mode 100644
index 0000000..9e38f08
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/Subscriber.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 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.eventbus;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.j2objc.annotations.Weak;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+
+import javax.annotation.Nullable;
+
+/**
+ * A subscriber method on a specific object, plus the executor that should be used for
+ * dispatching events to it.
+ *
+ * <p>Two subscribers are equivalent when they refer to the same method on the same object (not
+ * class). This property is used to ensure that no subscriber method is registered more than once.
+ *
+ * @author Colin Decker
+ */
+class Subscriber {
+
+  /**
+   * Creates a {@code Subscriber} for {@code method} on {@code listener}.
+   */
+  static Subscriber create(EventBus bus, Object listener, Method method) {
+    return isDeclaredThreadSafe(method)
+        ? new Subscriber(bus, listener, method)
+        : new SynchronizedSubscriber(bus, listener, method);
+  }
+
+  /** The event bus this subscriber belongs to. */
+  @Weak private EventBus bus;
+
+  /** Object sporting the subscriber method. */
+  @VisibleForTesting
+  final Object target;
+
+  /** Subscriber method. */
+  private final Method method;
+
+  /** Executor to use for dispatching events to this subscriber. */
+  private final Executor executor;
+
+  private Subscriber(EventBus bus, Object target, Method method) {
+    this.bus = bus;
+    this.target = checkNotNull(target);
+    this.method = method;
+    method.setAccessible(true);
+
+    this.executor = bus.executor();
+  }
+
+  /**
+   * Dispatches {@code event} to this subscriber using the proper executor.
+   */
+  final void dispatchEvent(final Object event) {
+    executor.execute(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          invokeSubscriberMethod(event);
+        } catch (InvocationTargetException e) {
+          bus.handleSubscriberException(e.getCause(), context(event));
+        }
+      }
+    });
+  }
+
+  /**
+   * Invokes the subscriber method. This method can be overridden to make the invocation
+   * synchronized.
+   */
+  @VisibleForTesting
+  void invokeSubscriberMethod(Object event) throws InvocationTargetException {
+    try {
+      method.invoke(target, checkNotNull(event));
+    } catch (IllegalArgumentException e) {
+      throw new Error("Method rejected target/argument: " + event, e);
+    } catch (IllegalAccessException e) {
+      throw new Error("Method became inaccessible: " + event, e);
+    } catch (InvocationTargetException e) {
+      if (e.getCause() instanceof Error) {
+        throw (Error) e.getCause();
+      }
+      throw e;
+    }
+  }
+
+  /**
+   * Gets the context for the given event.
+   */
+  private SubscriberExceptionContext context(Object event) {
+    return new SubscriberExceptionContext(bus, event, target, method);
+  }
+
+  @Override
+  public final int hashCode() {
+    return (31 + method.hashCode()) * 31 + System.identityHashCode(target);
+  }
+
+  @Override
+  public final boolean equals(@Nullable Object obj) {
+    if (obj instanceof Subscriber) {
+      Subscriber that = (Subscriber) obj;
+      // Use == so that different equal instances will still receive events.
+      // We only guard against the case that the same object is registered
+      // multiple times
+      return target == that.target && method.equals(that.method);
+    }
+    return false;
+  }
+
+  /**
+   * Checks whether {@code method} is thread-safe, as indicated by the presence of the
+   * {@link AllowConcurrentEvents} annotation.
+   */
+  private static boolean isDeclaredThreadSafe(Method method) {
+    return method.getAnnotation(AllowConcurrentEvents.class) != null;
+  }
+
+  /**
+   * Subscriber that synchronizes invocations of a method to ensure that only one thread may enter
+   * the method at a time.
+   */
+  @VisibleForTesting
+  static final class SynchronizedSubscriber extends Subscriber {
+
+    private SynchronizedSubscriber(EventBus bus, Object target, Method method) {
+      super(bus, target, method);
+    }
+
+    @Override
+    void invokeSubscriberMethod(Object event) throws InvocationTargetException {
+      synchronized (this) {
+        super.invokeSubscriberMethod(event);
+      }
+    }
+  }
+}
diff --git a/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java b/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java
deleted file mode 100644
index e238e42..0000000
--- a/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.eventbus;
-
-import com.google.common.collect.Multimap;
-
-/**
- * A method for finding event subscriber methods in objects, for use by
- * {@link EventBus}.
- *
- * @author Cliff Biffle
- */
-interface SubscriberFindingStrategy {
-
-  /**
-   * Finds all suitable event subscriber methods in {@code source}, organizes them
-   * by the type of event they handle, and wraps them in {@link EventSubscriber} instances.
-   *
-   * @param source  object whose subscribers are desired.
-   * @return EventSubscriber objects for each subscriber method, organized by event
-   *         type.
-   *
-   * @throws IllegalArgumentException if {@code source} is not appropriate for
-   *         this strategy (in ways that this interface does not define).
-   */
-  Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object source);
-
-}
diff --git a/guava/src/com/google/common/eventbus/SubscriberRegistry.java b/guava/src/com/google/common/eventbus/SubscriberRegistry.java
new file mode 100644
index 0000000..f0c220d
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/SubscriberRegistry.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 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.eventbus;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.reflect.TypeToken;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.google.j2objc.annotations.Weak;
+
+import java.lang.reflect.Method;
+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 java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.annotation.Nullable;
+
+/**
+ * Registry of subscribers to a single event bus.
+ *
+ * @author Colin Decker
+ */
+final class SubscriberRegistry {
+
+  /**
+   * All registered subscribers, indexed by event type.
+   *
+   * <p>The {@link CopyOnWriteArraySet} values make it easy and relatively lightweight to get an
+   * immutable snapshot of all current subscribers to an event without any locking.
+   */
+  private final ConcurrentMap<Class<?>, CopyOnWriteArraySet<Subscriber>> subscribers =
+      Maps.newConcurrentMap();
+
+  /**
+   * The event bus this registry belongs to.
+   */
+  @Weak private final EventBus bus;
+
+  SubscriberRegistry(EventBus bus) {
+    this.bus = checkNotNull(bus);
+  }
+
+  /**
+   * Registers all subscriber methods on the given listener object.
+   */
+  void register(Object listener) {
+    Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);
+
+    for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
+      Class<?> eventType = entry.getKey();
+      Collection<Subscriber> eventMethodsInListener = entry.getValue();
+
+      CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
+
+      if (eventSubscribers == null) {
+        CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<Subscriber>();
+        eventSubscribers = MoreObjects.firstNonNull(
+            subscribers.putIfAbsent(eventType, newSet), newSet);
+      }
+
+      eventSubscribers.addAll(eventMethodsInListener);
+    }
+  }
+
+  /**
+   * Unregisters all subscribers on the given listener object.
+   */
+  void unregister(Object listener) {
+    Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);
+
+    for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
+      Class<?> eventType = entry.getKey();
+      Collection<Subscriber> listenerMethodsForType = entry.getValue();
+
+      CopyOnWriteArraySet<Subscriber> currentSubscribers = subscribers.get(eventType);
+      if (currentSubscribers == null || !currentSubscribers.removeAll(listenerMethodsForType)) {
+        // if removeAll returns true, all we really know is that at least one subscriber was
+        // removed... however, barring something very strange we can assume that if at least one
+        // subscriber was removed, all subscribers on listener for that event type were... after
+        // all, the definition of subscribers on a particular class is totally static
+        throw new IllegalArgumentException(
+            "missing event subscriber for an annotated method. Is " + listener + " registered?");
+      }
+
+      // don't try to remove the set if it's empty; that can't be done safely without a lock
+      // anyway, if the set is empty it'll just be wrapping an array of length 0
+    }
+  }
+
+  @VisibleForTesting
+  Set<Subscriber> getSubscribersForTesting(Class<?> eventType) {
+    return MoreObjects.firstNonNull(subscribers.get(eventType), ImmutableSet.<Subscriber>of());
+  }
+
+  /**
+   * Gets an iterator representing an immutable snapshot of all subscribers to the given event at
+   * the time this method is called.
+   */
+  Iterator<Subscriber> getSubscribers(Object event) {
+    ImmutableSet<Class<?>> eventTypes = flattenHierarchy(event.getClass());
+
+    List<Iterator<Subscriber>> subscriberIterators =
+        Lists.newArrayListWithCapacity(eventTypes.size());
+
+    for (Class<?> eventType : eventTypes) {
+      CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
+      if (eventSubscribers != null) {
+        // eager no-copy snapshot
+        subscriberIterators.add(eventSubscribers.iterator());
+      }
+    }
+
+    return Iterators.concat(subscriberIterators.iterator());
+  }
+
+  /**
+   * A thread-safe cache that contains the mapping from each class to all methods in that class and
+   * all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
+   * instances of this class; this greatly improves performance if multiple EventBus instances are
+   * created and objects of the same class are registered on all of them.
+   */
+  private static final LoadingCache<Class<?>, ImmutableList<Method>> subscriberMethodsCache =
+      CacheBuilder.newBuilder()
+          .weakKeys()
+          .build(new CacheLoader<Class<?>, ImmutableList<Method>>() {
+            @Override
+            public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
+              return getAnnotatedMethodsNotCached(concreteClass);
+            }
+          });
+
+  /**
+   * Returns all subscribers for the given listener grouped by the type of event they subscribe to.
+   */
+  private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
+    Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
+    Class<?> clazz = listener.getClass();
+    for (Method method : getAnnotatedMethods(clazz)) {
+      Class<?>[] parameterTypes = method.getParameterTypes();
+      Class<?> eventType = parameterTypes[0];
+      methodsInListener.put(eventType, Subscriber.create(bus, listener, method));
+    }
+    return methodsInListener;
+  }
+
+  private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
+    return subscriberMethodsCache.getUnchecked(clazz);
+  }
+
+  private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz) {
+    Set<? extends Class<?>> supertypes = TypeToken.of(clazz).getTypes().rawTypes();
+    Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
+    for (Class<?> supertype : supertypes) {
+      for (Method method : supertype.getDeclaredMethods()) {
+        if (method.isAnnotationPresent(Subscribe.class) && !method.isSynthetic()) {
+          // TODO(cgdecker): Should check for a generic parameter type and error out
+          Class<?>[] parameterTypes = method.getParameterTypes();
+          checkArgument(parameterTypes.length == 1,
+              "Method %s has @Subscribe annotation but has %s parameters."
+                  + "Subscriber methods must have exactly 1 parameter.",
+              method, parameterTypes.length);
+
+          MethodIdentifier ident = new MethodIdentifier(method);
+          if (!identifiers.containsKey(ident)) {
+            identifiers.put(ident, method);
+          }
+        }
+      }
+    }
+    return ImmutableList.copyOf(identifiers.values());
+  }
+
+  /**
+   * Global cache of classes to their flattened hierarchy of supertypes.
+   */
+  private static final LoadingCache<Class<?>, ImmutableSet<Class<?>>> flattenHierarchyCache =
+      CacheBuilder.newBuilder()
+          .weakKeys()
+          .build(new CacheLoader<Class<?>, ImmutableSet<Class<?>>>() {
+            @SuppressWarnings("RedundantTypeArguments") // <Class<?>> is actually needed to compile
+            @Override
+            public ImmutableSet<Class<?>> load(Class<?> concreteClass) {
+              return ImmutableSet.<Class<?>>copyOf(
+                  TypeToken.of(concreteClass).getTypes().rawTypes());
+            }
+          });
+
+  /**
+   * Flattens a class's type hierarchy into a set of {@code Class} objects including all
+   * superclasses (transitively) and all interfaces implemented by these superclasses.
+   */
+  @VisibleForTesting
+  static ImmutableSet<Class<?>> flattenHierarchy(Class<?> concreteClass) {
+    try {
+      return flattenHierarchyCache.getUnchecked(concreteClass);
+    } catch (UncheckedExecutionException e) {
+      throw Throwables.propagate(e.getCause());
+    }
+  }
+
+  private static final class MethodIdentifier {
+
+    private final String name;
+    private final List<Class<?>> parameterTypes;
+
+    MethodIdentifier(Method method) {
+      this.name = method.getName();
+      this.parameterTypes = Arrays.asList(method.getParameterTypes());
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(name, parameterTypes);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+      if (o instanceof MethodIdentifier) {
+        MethodIdentifier ident = (MethodIdentifier) o;
+        return name.equals(ident.name) && parameterTypes.equals(ident.parameterTypes);
+      }
+      return false;
+    }
+  }
+}
diff --git a/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java b/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java
deleted file mode 100644
index a074818..0000000
--- a/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.eventbus;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Wraps a single-argument subscriber method on a specific object, and ensures
- * that only one thread may enter the method at a time.
- *
- * <p>Beyond synchronization, this class behaves identically to
- * {@link EventSubscriber}.
- *
- * @author Cliff Biffle
- */
-final class SynchronizedEventSubscriber extends EventSubscriber {
-  /**
-   * Creates a new SynchronizedEventSubscriber to wrap {@code method} on
-   * {@code target}.
-   *
-   * @param target  object to which the method applies.
-   * @param method  subscriber method.
-   */
-  public SynchronizedEventSubscriber(Object target, Method method) {
-    super(target, method);
-  }
-
-  @Override
-  public void handleEvent(Object event) throws InvocationTargetException {
-    // https://code.google.com/p/guava-libraries/issues/detail?id=1403
-    synchronized (this) {
-      super.handleEvent(event);
-    }
-  }
-}
diff --git a/guava/src/com/google/common/eventbus/package-info.java b/guava/src/com/google/common/eventbus/package-info.java
index 84c2d9b..f7b333c 100644
--- a/guava/src/com/google/common/eventbus/package-info.java
+++ b/guava/src/com/google/common/eventbus/package-info.java
@@ -23,7 +23,7 @@
  * intended for interprocess communication.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/EventBusExplained">
+ * "https://github.com/google/guava/wiki/EventBusExplained">
  * {@code EventBus}</a>.
  *
  * <h2>One-Minute Guide</h2>
diff --git a/guava/src/com/google/common/hash/AbstractByteHasher.java b/guava/src/com/google/common/hash/AbstractByteHasher.java
index 90210df..dbddf9c 100644
--- a/guava/src/com/google/common/hash/AbstractByteHasher.java
+++ b/guava/src/com/google/common/hash/AbstractByteHasher.java
@@ -34,7 +34,6 @@ import java.nio.ByteOrder;
  * @author Colin Decker
  */
 abstract class AbstractByteHasher extends AbstractHasher {
-
   private final ByteBuffer scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
 
   /**
diff --git a/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java b/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
index 43d5fa9..2122908 100644
--- a/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
@@ -52,98 +52,112 @@ abstract class AbstractCompositeHashFunction extends AbstractStreamingHashFuncti
       hashers[i] = functions[i].newHasher();
     }
     return new Hasher() {
-      @Override public Hasher putByte(byte b) {
+      @Override
+      public Hasher putByte(byte b) {
         for (Hasher hasher : hashers) {
           hasher.putByte(b);
         }
         return this;
       }
 
-      @Override public Hasher putBytes(byte[] bytes) {
+      @Override
+      public Hasher putBytes(byte[] bytes) {
         for (Hasher hasher : hashers) {
           hasher.putBytes(bytes);
         }
         return this;
       }
 
-      @Override public Hasher putBytes(byte[] bytes, int off, int len) {
+      @Override
+      public Hasher putBytes(byte[] bytes, int off, int len) {
         for (Hasher hasher : hashers) {
           hasher.putBytes(bytes, off, len);
         }
         return this;
       }
 
-      @Override public Hasher putShort(short s) {
+      @Override
+      public Hasher putShort(short s) {
         for (Hasher hasher : hashers) {
           hasher.putShort(s);
         }
         return this;
       }
 
-      @Override public Hasher putInt(int i) {
+      @Override
+      public Hasher putInt(int i) {
         for (Hasher hasher : hashers) {
           hasher.putInt(i);
         }
         return this;
       }
 
-      @Override public Hasher putLong(long l) {
+      @Override
+      public Hasher putLong(long l) {
         for (Hasher hasher : hashers) {
           hasher.putLong(l);
         }
         return this;
       }
 
-      @Override public Hasher putFloat(float f) {
+      @Override
+      public Hasher putFloat(float f) {
         for (Hasher hasher : hashers) {
           hasher.putFloat(f);
         }
         return this;
       }
 
-      @Override public Hasher putDouble(double d) {
+      @Override
+      public Hasher putDouble(double d) {
         for (Hasher hasher : hashers) {
           hasher.putDouble(d);
         }
         return this;
       }
 
-      @Override public Hasher putBoolean(boolean b) {
+      @Override
+      public Hasher putBoolean(boolean b) {
         for (Hasher hasher : hashers) {
           hasher.putBoolean(b);
         }
         return this;
       }
 
-      @Override public Hasher putChar(char c) {
+      @Override
+      public Hasher putChar(char c) {
         for (Hasher hasher : hashers) {
           hasher.putChar(c);
         }
         return this;
       }
 
-      @Override public Hasher putUnencodedChars(CharSequence chars) {
+      @Override
+      public Hasher putUnencodedChars(CharSequence chars) {
         for (Hasher hasher : hashers) {
           hasher.putUnencodedChars(chars);
         }
         return this;
       }
 
-      @Override public Hasher putString(CharSequence chars, Charset charset) {
+      @Override
+      public Hasher putString(CharSequence chars, Charset charset) {
         for (Hasher hasher : hashers) {
           hasher.putString(chars, charset);
         }
         return this;
       }
 
-      @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
+      @Override
+      public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
         for (Hasher hasher : hashers) {
           hasher.putObject(instance, funnel);
         }
         return this;
       }
 
-      @Override public HashCode hash() {
+      @Override
+      public HashCode hash() {
         return makeHash(hashers);
       }
     };
diff --git a/guava/src/com/google/common/hash/AbstractHasher.java b/guava/src/com/google/common/hash/AbstractHasher.java
index a23786f..df572e5 100644
--- a/guava/src/com/google/common/hash/AbstractHasher.java
+++ b/guava/src/com/google/common/hash/AbstractHasher.java
@@ -24,26 +24,31 @@ import java.nio.charset.Charset;
  * @author Dimitris Andreou
  */
 abstract class AbstractHasher implements Hasher {
-  @Override public final Hasher putBoolean(boolean b) {
+  @Override
+  public final Hasher putBoolean(boolean b) {
     return putByte(b ? (byte) 1 : (byte) 0);
   }
 
-  @Override public final Hasher putDouble(double d) {
+  @Override
+  public final Hasher putDouble(double d) {
     return putLong(Double.doubleToRawLongBits(d));
   }
 
-  @Override public final Hasher putFloat(float f) {
+  @Override
+  public final Hasher putFloat(float f) {
     return putInt(Float.floatToRawIntBits(f));
   }
 
-  @Override public Hasher putUnencodedChars(CharSequence charSequence) {
+  @Override
+  public Hasher putUnencodedChars(CharSequence charSequence) {
     for (int i = 0, len = charSequence.length(); i < len; i++) {
       putChar(charSequence.charAt(i));
     }
     return this;
   }
 
-  @Override public Hasher putString(CharSequence charSequence, Charset charset) {
+  @Override
+  public Hasher putString(CharSequence charSequence, Charset charset) {
     return putBytes(charSequence.toString().getBytes(charset));
   }
 }
diff --git a/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java b/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
index 7c08b70..f1838ee 100644
--- a/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
@@ -41,11 +41,13 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
     return new BufferingHasher(expectedInputSize);
   }
 
-  @Override public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
+  @Override
+  public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
     return newHasher().putObject(instance, funnel).hash();
   }
 
-  @Override public HashCode hashUnencodedChars(CharSequence input) {
+  @Override
+  public HashCode hashUnencodedChars(CharSequence input) {
     int len = input.length();
     Hasher hasher = newHasher(len * 2);
     for (int i = 0; i < len; i++) {
@@ -54,19 +56,23 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
     return hasher.hash();
   }
 
-  @Override public HashCode hashString(CharSequence input, Charset charset) {
+  @Override
+  public HashCode hashString(CharSequence input, Charset charset) {
     return hashBytes(input.toString().getBytes(charset));
   }
 
-  @Override public HashCode hashInt(int input) {
+  @Override
+  public HashCode hashInt(int input) {
     return newHasher(4).putInt(input).hash();
   }
 
-  @Override public HashCode hashLong(long input) {
+  @Override
+  public HashCode hashLong(long input) {
     return newHasher(8).putLong(input).hash();
   }
 
-  @Override public HashCode hashBytes(byte[] input) {
+  @Override
+  public HashCode hashBytes(byte[] input) {
     return hashBytes(input, 0, input.length);
   }
 
@@ -106,7 +112,7 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
     @Override
     public Hasher putShort(short s) {
       stream.write(s & BOTTOM_BYTE);
-      stream.write((s >>> 8)  & BOTTOM_BYTE);
+      stream.write((s >>> 8) & BOTTOM_BYTE);
       return this;
     }
 
@@ -151,9 +157,11 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
     ExposedByteArrayOutputStream(int expectedInputSize) {
       super(expectedInputSize);
     }
+
     byte[] byteArray() {
       return buf;
     }
+
     int length() {
       return count;
     }
diff --git a/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java b/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
index 302399f..8d8bf9b 100644
--- a/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
@@ -33,35 +33,43 @@ import java.nio.charset.Charset;
  * @author Kevin Bourrillion
  */
 abstract class AbstractStreamingHashFunction implements HashFunction {
-  @Override public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
+  @Override
+  public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
     return newHasher().putObject(instance, funnel).hash();
   }
 
-  @Override public HashCode hashUnencodedChars(CharSequence input) {
+  @Override
+  public HashCode hashUnencodedChars(CharSequence input) {
     return newHasher().putUnencodedChars(input).hash();
   }
 
-  @Override public HashCode hashString(CharSequence input, Charset charset) {
+  @Override
+  public HashCode hashString(CharSequence input, Charset charset) {
     return newHasher().putString(input, charset).hash();
   }
 
-  @Override public HashCode hashInt(int input) {
+  @Override
+  public HashCode hashInt(int input) {
     return newHasher().putInt(input).hash();
   }
 
-  @Override public HashCode hashLong(long input) {
+  @Override
+  public HashCode hashLong(long input) {
     return newHasher().putLong(input).hash();
   }
 
-  @Override public HashCode hashBytes(byte[] input) {
+  @Override
+  public HashCode hashBytes(byte[] input) {
     return newHasher().putBytes(input).hash();
   }
 
-  @Override public HashCode hashBytes(byte[] input, int off, int len) {
+  @Override
+  public HashCode hashBytes(byte[] input, int off, int len) {
     return newHasher().putBytes(input, off, len).hash();
   }
 
-  @Override public Hasher newHasher(int expectedInputSize) {
+  @Override
+  public Hasher newHasher(int expectedInputSize) {
     Preconditions.checkArgument(expectedInputSize >= 0);
     return newHasher();
   }
@@ -109,9 +117,8 @@ abstract class AbstractStreamingHashFunction implements HashFunction {
       checkArgument(bufferSize % chunkSize == 0);
 
       // TODO(user): benchmark performance difference with longer buffer
-      this.buffer = ByteBuffer
-          .allocate(bufferSize + 7) // always space for a single primitive
-          .order(ByteOrder.LITTLE_ENDIAN);
+      // always space for a single primitive
+      this.buffer = ByteBuffer.allocate(bufferSize + 7).order(ByteOrder.LITTLE_ENDIAN);
       this.bufferSize = bufferSize;
       this.chunkSize = chunkSize;
     }
@@ -183,6 +190,16 @@ abstract class AbstractStreamingHashFunction implements HashFunction {
       return this;
     }
 
+    /*
+     * Note: hashString(CharSequence, Charset) is intentionally not overridden.
+     *
+     * While intuitively, using CharsetEncoder to encode the CharSequence directly to the buffer
+     * (or even to an intermediate buffer) should be considerably more efficient than potentially
+     * copying the CharSequence to a String and then calling getBytes(Charset) on that String, in
+     * reality there are optimizations that make the getBytes(Charset) approach considerably faster,
+     * at least for commonly used charsets like UTF-8.
+     */
+
     @Override
     public final Hasher putByte(byte b) {
       buffer.put(b);
diff --git a/guava/src/com/google/common/hash/BloomFilter.java b/guava/src/com/google/common/hash/BloomFilter.java
index 1c04f8d..4c70575 100644
--- a/guava/src/com/google/common/hash/BloomFilter.java
+++ b/guava/src/com/google/common/hash/BloomFilter.java
@@ -32,6 +32,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -108,12 +109,11 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
   /**
    * Creates a BloomFilter.
    */
-  private BloomFilter(BitArray bits, int numHashFunctions, Funnel<? super T> funnel,
-      Strategy strategy) {
-    checkArgument(numHashFunctions > 0,
-        "numHashFunctions (%s) must be > 0", numHashFunctions);
-    checkArgument(numHashFunctions <= 255,
-        "numHashFunctions (%s) must be <= 255", numHashFunctions);
+  private BloomFilter(
+      BitArray bits, int numHashFunctions, Funnel<? super T> funnel, Strategy strategy) {
+    checkArgument(numHashFunctions > 0, "numHashFunctions (%s) must be > 0", numHashFunctions);
+    checkArgument(
+        numHashFunctions <= 255, "numHashFunctions (%s) must be <= 255", numHashFunctions);
     this.bits = checkNotNull(bits);
     this.numHashFunctions = numHashFunctions;
     this.funnel = checkNotNull(funnel);
@@ -126,6 +126,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    *
    * @since 12.0
    */
+  @CheckReturnValue
   public BloomFilter<T> copy() {
     return new BloomFilter<T>(bits.copy(), numHashFunctions, funnel, strategy);
   }
@@ -134,6 +135,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    * Returns {@code true} if the element <i>might</i> have been put in this Bloom filter,
    * {@code false} if this is <i>definitely</i> not the case.
    */
+  @CheckReturnValue
   public boolean mightContain(T object) {
     return strategy.mightContain(object, funnel, numHashFunctions, bits);
   }
@@ -144,6 +146,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    */
   @Deprecated
   @Override
+  @CheckReturnValue
   public boolean apply(T input) {
     return mightContain(input);
   }
@@ -175,6 +178,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    *
    * @since 14.0 (since 11.0 as expectedFalsePositiveProbability())
    */
+  @CheckReturnValue
   public double expectedFpp() {
     // You down with FPP? (Yeah you know me!) Who's down with FPP? (Every last homie!)
     return Math.pow((double) bits.bitCount() / bitSize(), numHashFunctions);
@@ -183,7 +187,8 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
   /**
    * Returns the number of bits in the underlying bit array.
    */
-  @VisibleForTesting long bitSize() {
+  @VisibleForTesting
+  long bitSize() {
     return bits.bitSize();
   }
 
@@ -202,13 +207,14 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    * @param that The bloom filter to check for compatibility.
    * @since 15.0
    */
+  @CheckReturnValue
   public boolean isCompatible(BloomFilter<T> that) {
     checkNotNull(that);
-    return (this != that) &&
-        (this.numHashFunctions == that.numHashFunctions) &&
-        (this.bitSize() == that.bitSize()) &&
-        (this.strategy.equals(that.strategy)) &&
-        (this.funnel.equals(that.funnel));
+    return (this != that)
+        && (this.numHashFunctions == that.numHashFunctions)
+        && (this.bitSize() == that.bitSize())
+        && (this.strategy.equals(that.strategy))
+        && (this.funnel.equals(that.funnel));
   }
 
   /**
@@ -224,18 +230,26 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
   public void putAll(BloomFilter<T> that) {
     checkNotNull(that);
     checkArgument(this != that, "Cannot combine a BloomFilter with itself.");
-    checkArgument(this.numHashFunctions == that.numHashFunctions,
+    checkArgument(
+        this.numHashFunctions == that.numHashFunctions,
         "BloomFilters must have the same number of hash functions (%s != %s)",
-        this.numHashFunctions, that.numHashFunctions);
-    checkArgument(this.bitSize() == that.bitSize(),
+        this.numHashFunctions,
+        that.numHashFunctions);
+    checkArgument(
+        this.bitSize() == that.bitSize(),
         "BloomFilters must have the same size underlying bit arrays (%s != %s)",
-        this.bitSize(), that.bitSize());
-    checkArgument(this.strategy.equals(that.strategy),
+        this.bitSize(),
+        that.bitSize());
+    checkArgument(
+        this.strategy.equals(that.strategy),
         "BloomFilters must have equal strategies (%s != %s)",
-        this.strategy, that.strategy);
-    checkArgument(this.funnel.equals(that.funnel),
+        this.strategy,
+        that.strategy);
+    checkArgument(
+        this.funnel.equals(that.funnel),
         "BloomFilters must have equal funnels (%s != %s)",
-        this.funnel, that.funnel);
+        this.funnel,
+        that.funnel);
     this.bits.putAll(that.bits);
   }
 
@@ -259,8 +273,32 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
     return Objects.hashCode(numHashFunctions, funnel, strategy, bits);
   }
 
-  private static final Strategy DEFAULT_STRATEGY =
-      BloomFilterStrategies.MURMUR128_MITZ_64;
+  /**
+   * Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
+   * insertions and expected false positive probability.
+   *
+   * <p>Note that overflowing a {@code BloomFilter} with significantly more elements
+   * than specified, will result in its saturation, and a sharp deterioration of its
+   * false positive probability.
+   *
+   * <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
+   * {@code Funnel<T>} is.
+   *
+   * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+   * benefit of ensuring proper serialization and deserialization, which is important
+   * since {@link #equals} also relies on object identity of funnels.
+   *
+   * @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
+   * @param expectedInsertions the number of expected insertions to the constructed
+   *     {@code BloomFilter<T>}; must be positive
+   * @param fpp the desired false positive probability (must be positive and less than 1.0)
+   * @return a {@code BloomFilter}
+   */
+  @CheckReturnValue
+  public static <T> BloomFilter<T> create(
+      Funnel<? super T> funnel, int expectedInsertions, double fpp) {
+    return create(funnel, (long) expectedInsertions, fpp);
+  }
 
   /**
    * Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
@@ -282,18 +320,20 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    *     {@code BloomFilter<T>}; must be positive
    * @param fpp the desired false positive probability (must be positive and less than 1.0)
    * @return a {@code BloomFilter}
+   * @since 19.0
    */
+  @CheckReturnValue
   public static <T> BloomFilter<T> create(
-      Funnel<? super T> funnel, int expectedInsertions /* n */, double fpp) {
-    return create(funnel, expectedInsertions, fpp, DEFAULT_STRATEGY);
+      Funnel<? super T> funnel, long expectedInsertions, double fpp) {
+    return create(funnel, expectedInsertions, fpp, BloomFilterStrategies.MURMUR128_MITZ_64);
   }
 
   @VisibleForTesting
   static <T> BloomFilter<T> create(
-      Funnel<? super T> funnel, int expectedInsertions /* n */, double fpp, Strategy strategy) {
+      Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy) {
     checkNotNull(funnel);
-    checkArgument(expectedInsertions >= 0, "Expected insertions (%s) must be >= 0",
-        expectedInsertions);
+    checkArgument(
+        expectedInsertions >= 0, "Expected insertions (%s) must be >= 0", expectedInsertions);
     checkArgument(fpp > 0.0, "False positive probability (%s) must be > 0.0", fpp);
     checkArgument(fpp < 1.0, "False positive probability (%s) must be < 1.0", fpp);
     checkNotNull(strategy);
@@ -327,13 +367,43 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    * <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
    * {@code Funnel<T>} is.
    *
+   * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+   * benefit of ensuring proper serialization and deserialization, which is important
+   * since {@link #equals} also relies on object identity of funnels.
+   *
    * @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
    * @param expectedInsertions the number of expected insertions to the constructed
    *     {@code BloomFilter<T>}; must be positive
    * @return a {@code BloomFilter}
    */
-  public static <T> BloomFilter<T> create(
-      Funnel<? super T> funnel, int expectedInsertions /* n */) {
+  @CheckReturnValue
+  public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions) {
+    return create(funnel, (long) expectedInsertions);
+  }
+
+  /**
+   * Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
+   * insertions and a default expected false positive probability of 3%.
+   *
+   * <p>Note that overflowing a {@code BloomFilter} with significantly more elements
+   * than specified, will result in its saturation, and a sharp deterioration of its
+   * false positive probability.
+   *
+   * <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
+   * {@code Funnel<T>} is.
+   *
+   * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+   * benefit of ensuring proper serialization and deserialization, which is important
+   * since {@link #equals} also relies on object identity of funnels.
+   *
+   * @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
+   * @param expectedInsertions the number of expected insertions to the constructed
+   *     {@code BloomFilter<T>}; must be positive
+   * @return a {@code BloomFilter}
+   * @since 19.0
+   */
+  @CheckReturnValue
+  public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {
     return create(funnel, expectedInsertions, 0.03); // FYI, for 3%, we always get 5 hash functions
   }
 
@@ -399,9 +469,11 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
       this.funnel = bf.funnel;
       this.strategy = bf.strategy;
     }
+
     Object readResolve() {
       return new BloomFilter<T>(new BitArray(data), numHashFunctions, funnel, strategy);
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -441,6 +513,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
    *     not appear to be a BloomFilter serialized using the
    *     {@linkplain #writeTo(OutputStream)} method.
    */
+  @CheckReturnValue
   public static <T> BloomFilter<T> readFrom(InputStream in, Funnel<T> funnel) throws IOException {
     checkNotNull(in, "InputStream");
     checkNotNull(funnel, "Funnel");
@@ -465,9 +538,9 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
     } catch (RuntimeException e) {
       IOException ioException = new IOException(
           "Unable to deserialize BloomFilter from InputStream."
-          + " strategyOrdinal: " + strategyOrdinal
-          + " numHashFunctions: " + numHashFunctions
-          + " dataLength: " + dataLength);
+              + " strategyOrdinal: " + strategyOrdinal
+              + " numHashFunctions: " + numHashFunctions
+              + " dataLength: " + dataLength);
       ioException.initCause(e);
       throw ioException;
     }
diff --git a/guava/src/com/google/common/hash/BloomFilterStrategies.java b/guava/src/com/google/common/hash/BloomFilterStrategies.java
index 3dd8535..2d464cc 100644
--- a/guava/src/com/google/common/hash/BloomFilterStrategies.java
+++ b/guava/src/com/google/common/hash/BloomFilterStrategies.java
@@ -42,8 +42,9 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
    * performance of a Bloom filter (yet only needs two 32bit hash functions).
    */
   MURMUR128_MITZ_32() {
-    @Override public <T> boolean put(T object, Funnel<? super T> funnel,
-        int numHashFunctions, BitArray bits) {
+    @Override
+    public <T> boolean put(
+        T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
       long bitSize = bits.bitSize();
       long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
       int hash1 = (int) hash64;
@@ -61,8 +62,9 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
       return bitsChanged;
     }
 
-    @Override public <T> boolean mightContain(T object, Funnel<? super T> funnel,
-        int numHashFunctions, BitArray bits) {
+    @Override
+    public <T> boolean mightContain(
+        T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
       long bitSize = bits.bitSize();
       long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
       int hash1 = (int) hash64;
@@ -89,8 +91,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
    */
   MURMUR128_MITZ_64() {
     @Override
-    public <T> boolean put(T object, Funnel<? super T> funnel,
-        int numHashFunctions, BitArray bits) {
+    public <T> boolean put(
+        T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
       long bitSize = bits.bitSize();
       byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal();
       long hash1 = lowerEight(bytes);
@@ -107,8 +109,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
     }
 
     @Override
-    public <T> boolean mightContain(T object, Funnel<? super T> funnel,
-        int numHashFunctions, BitArray bits) {
+    public <T> boolean mightContain(
+        T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
       long bitSize = bits.bitSize();
       byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal();
       long hash1 = lowerEight(bytes);
@@ -186,8 +188,11 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
 
     /** Combines the two BitArrays using bitwise OR. */
     void putAll(BitArray array) {
-      checkArgument(data.length == array.data.length,
-          "BitArrays must be of equal length (%s != %s)", data.length, array.data.length);
+      checkArgument(
+          data.length == array.data.length,
+          "BitArrays must be of equal length (%s != %s)",
+          data.length,
+          array.data.length);
       bitCount = 0;
       for (int i = 0; i < data.length; i++) {
         data[i] |= array.data[i];
@@ -195,7 +200,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
       }
     }
 
-    @Override public boolean equals(Object o) {
+    @Override
+    public boolean equals(Object o) {
       if (o instanceof BitArray) {
         BitArray bitArray = (BitArray) o;
         return Arrays.equals(data, bitArray.data);
@@ -203,7 +209,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return Arrays.hashCode(data);
     }
   }
diff --git a/guava/src/com/google/common/hash/ChecksumHashFunction.java b/guava/src/com/google/common/hash/ChecksumHashFunction.java
index c99ccb7..ebcc1d6 100644
--- a/guava/src/com/google/common/hash/ChecksumHashFunction.java
+++ b/guava/src/com/google/common/hash/ChecksumHashFunction.java
@@ -28,7 +28,6 @@ import java.util.zip.Checksum;
  * @author Colin Decker
  */
 final class ChecksumHashFunction extends AbstractStreamingHashFunction implements Serializable {
-
   private final Supplier<? extends Checksum> checksumSupplier;
   private final int bits;
   private final String toString;
@@ -59,7 +58,6 @@ final class ChecksumHashFunction extends AbstractStreamingHashFunction implement
    * Hasher that updates a checksum.
    */
   private final class ChecksumHasher extends AbstractByteHasher {
-
     private final Checksum checksum;
 
     private ChecksumHasher(Checksum checksum) {
diff --git a/guava/src/com/google/common/hash/Crc32cHashFunction.java b/guava/src/com/google/common/hash/Crc32cHashFunction.java
index dd9d7f3..a3530b7 100644
--- a/guava/src/com/google/common/hash/Crc32cHashFunction.java
+++ b/guava/src/com/google/common/hash/Crc32cHashFunction.java
@@ -21,7 +21,6 @@ package com.google.common.hash;
  * @author Kurt Alfred Kluever
  */
 final class Crc32cHashFunction extends AbstractStreamingHashFunction {
-
   @Override
   public int bits() {
     return 32;
diff --git a/guava/src/com/google/common/hash/Funnels.java b/guava/src/com/google/common/hash/Funnels.java
index 08b814a..627683d 100644
--- a/guava/src/com/google/common/hash/Funnels.java
+++ b/guava/src/com/google/common/hash/Funnels.java
@@ -21,6 +21,7 @@ import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.charset.Charset;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -30,6 +31,7 @@ import javax.annotation.Nullable;
  * @since 11.0
  */
 @Beta
+ at CheckReturnValue
 public final class Funnels {
   private Funnels() {}
 
@@ -47,7 +49,8 @@ public final class Funnels {
       into.putBytes(from);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Funnels.byteArrayFunnel()";
     }
   }
@@ -70,7 +73,8 @@ public final class Funnels {
       into.putUnencodedChars(from);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Funnels.unencodedCharsFunnel()";
     }
   }
@@ -96,11 +100,13 @@ public final class Funnels {
       into.putString(from, charset);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Funnels.stringFunnel(" + charset.name() + ")";
     }
 
-    @Override public boolean equals(@Nullable Object o) {
+    @Override
+    public boolean equals(@Nullable Object o) {
       if (o instanceof StringCharsetFunnel) {
         StringCharsetFunnel funnel = (StringCharsetFunnel) o;
         return this.charset.equals(funnel.charset);
@@ -108,7 +114,8 @@ public final class Funnels {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return StringCharsetFunnel.class.hashCode() ^ charset.hashCode();
     }
 
@@ -126,7 +133,7 @@ public final class Funnels {
       private Object readResolve() {
         return stringFunnel(Charset.forName(charsetCanonicalName));
       }
-    
+
       private static final long serialVersionUID = 0;
     }
   }
@@ -147,7 +154,8 @@ public final class Funnels {
       into.putInt(from);
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Funnels.integerFunnel()";
     }
   }
@@ -175,11 +183,13 @@ public final class Funnels {
       }
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       return "Funnels.sequentialFunnel(" + elementFunnel + ")";
     }
 
-    @Override public boolean equals(@Nullable Object o) {
+    @Override
+    public boolean equals(@Nullable Object o) {
       if (o instanceof SequentialFunnel) {
         SequentialFunnel<?> funnel = (SequentialFunnel<?>) o;
         return elementFunnel.equals(funnel.elementFunnel);
@@ -187,65 +197,72 @@ public final class Funnels {
       return false;
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       return SequentialFunnel.class.hashCode() ^ elementFunnel.hashCode();
     }
   }
 
   /**
    * Returns a funnel for longs.
-   * 
+   *
    * @since 13.0
    */
   public static Funnel<Long> longFunnel() {
     return LongFunnel.INSTANCE;
   }
-  
+
   private enum LongFunnel implements Funnel<Long> {
     INSTANCE;
-    
+
     public void funnel(Long from, PrimitiveSink into) {
       into.putLong(from);
     }
-    
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "Funnels.longFunnel()";
     }
   }
-  
+
   /**
    * Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
    * {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
-   * if there is already a way to write the contents of the object to an {@code OutputStream}.  
-   * 
+   * if there is already a way to write the contents of the object to an {@code OutputStream}.
+   *
    * <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
    * do nothing, and no method throws {@code IOException}.
-   * 
+   *
    * @since 13.0
    */
   public static OutputStream asOutputStream(PrimitiveSink sink) {
     return new SinkAsStream(sink);
   }
-  
+
   private static class SinkAsStream extends OutputStream {
     final PrimitiveSink sink;
+
     SinkAsStream(PrimitiveSink sink) {
       this.sink = Preconditions.checkNotNull(sink);
     }
-    
-    @Override public void write(int b) {
+
+    @Override
+    public void write(int b) {
       sink.putByte((byte) b);
     }
 
-    @Override public void write(byte[] bytes) {
+    @Override
+    public void write(byte[] bytes) {
       sink.putBytes(bytes);
     }
 
-    @Override public void write(byte[] bytes, int off, int len) {
+    @Override
+    public void write(byte[] bytes, int off, int len) {
       sink.putBytes(bytes, off, len);
     }
-    
-    @Override public String toString() {
+
+    @Override
+    public String toString() {
       return "Funnels.asOutputStream(" + sink + ")";
     }
   }
diff --git a/guava/src/com/google/common/hash/HashCode.java b/guava/src/com/google/common/hash/HashCode.java
index 7ee228d..7115b28 100644
--- a/guava/src/com/google/common/hash/HashCode.java
+++ b/guava/src/com/google/common/hash/HashCode.java
@@ -24,8 +24,8 @@ import com.google.common.primitives.Ints;
 import com.google.common.primitives.UnsignedInts;
 
 import java.io.Serializable;
-import java.security.MessageDigest;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -42,6 +42,7 @@ public abstract class HashCode {
   /**
    * Returns the number of bits in this hash code; a positive multiple of 8.
    */
+  @CheckReturnValue
   public abstract int bits();
 
   /**
@@ -50,6 +51,7 @@ public abstract class HashCode {
    *
    * @throws IllegalStateException if {@code bits() < 32}
    */
+  @CheckReturnValue
   public abstract int asInt();
 
   /**
@@ -58,6 +60,7 @@ public abstract class HashCode {
    *
    * @throws IllegalStateException if {@code bits() < 64}
    */
+  @CheckReturnValue
   public abstract long asLong();
 
   /**
@@ -67,6 +70,7 @@ public abstract class HashCode {
    *
    * @since 14.0 (since 11.0 as {@code Hashing.padToLong(HashCode)})
    */
+  @CheckReturnValue
   public abstract long padToLong();
 
   /**
@@ -75,6 +79,7 @@ public abstract class HashCode {
    * returned by this method.
    */
   // TODO(user): consider ByteString here, when that is available
+  @CheckReturnValue
   public abstract byte[] asBytes();
 
   /**
@@ -116,6 +121,7 @@ public abstract class HashCode {
    *
    * @since 15.0 (since 12.0 in HashCodes)
    */
+  @CheckReturnValue
   public static HashCode fromInt(int hash) {
     return new IntHashCode(hash);
   }
@@ -135,10 +141,11 @@ public abstract class HashCode {
     @Override
     public byte[] asBytes() {
       return new byte[] {
-          (byte) hash,
-          (byte) (hash >> 8),
-          (byte) (hash >> 16),
-          (byte) (hash >> 24)};
+        (byte) hash,
+        (byte) (hash >> 8),
+        (byte) (hash >> 16),
+        (byte) (hash >> 24)
+      };
     }
 
     @Override
@@ -163,7 +170,8 @@ public abstract class HashCode {
       }
     }
 
-    @Override boolean equalsSameBits(HashCode that) {
+    @Override
+    boolean equalsSameBits(HashCode that) {
       return hash == that.asInt();
     }
 
@@ -176,6 +184,7 @@ public abstract class HashCode {
    *
    * @since 15.0 (since 12.0 in HashCodes)
    */
+  @CheckReturnValue
   public static HashCode fromLong(long hash) {
     return new LongHashCode(hash);
   }
@@ -195,14 +204,15 @@ public abstract class HashCode {
     @Override
     public byte[] asBytes() {
       return new byte[] {
-          (byte) hash,
-          (byte) (hash >> 8),
-          (byte) (hash >> 16),
-          (byte) (hash >> 24),
-          (byte) (hash >> 32),
-          (byte) (hash >> 40),
-          (byte) (hash >> 48),
-          (byte) (hash >> 56)};
+        (byte) hash,
+        (byte) (hash >> 8),
+        (byte) (hash >> 16),
+        (byte) (hash >> 24),
+        (byte) (hash >> 32),
+        (byte) (hash >> 40),
+        (byte) (hash >> 48),
+        (byte) (hash >> 56)
+      };
     }
 
     @Override
@@ -241,6 +251,7 @@ public abstract class HashCode {
    *
    * @since 15.0 (since 12.0 in HashCodes)
    */
+  @CheckReturnValue
   public static HashCode fromBytes(byte[] bytes) {
     checkArgument(bytes.length >= 1, "A HashCode must contain at least 1 byte.");
     return fromBytesNoCopy(bytes.clone());
@@ -273,8 +284,10 @@ public abstract class HashCode {
 
     @Override
     public int asInt() {
-      checkState(bytes.length >= 4,
-          "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).", bytes.length);
+      checkState(
+          bytes.length >= 4,
+          "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).",
+          bytes.length);
       return (bytes[0] & 0xFF)
           | ((bytes[1] & 0xFF) << 8)
           | ((bytes[2] & 0xFF) << 16)
@@ -283,8 +296,10 @@ public abstract class HashCode {
 
     @Override
     public long asLong() {
-      checkState(bytes.length >= 8,
-          "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).", bytes.length);
+      checkState(
+          bytes.length >= 8,
+          "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).",
+          bytes.length);
       return padToLong();
     }
 
@@ -309,7 +324,17 @@ public abstract class HashCode {
 
     @Override
     boolean equalsSameBits(HashCode that) {
-      return MessageDigest.isEqual(bytes, that.getBytesInternal());
+      // We don't use MessageDigest.isEqual() here because its contract does not guarantee
+      // constant-time evaluation (no short-circuiting).
+      if (this.bytes.length != that.getBytesInternal().length) {
+        return false;
+      }
+
+      boolean areEqual = true;
+      for (int i = 0; i < this.bytes.length; i++) {
+        areEqual &= (this.bytes[i] == that.getBytesInternal()[i]);
+      }
+      return areEqual;
     }
 
     private static final long serialVersionUID = 0;
@@ -325,11 +350,14 @@ public abstract class HashCode {
    *
    * @since 15.0
    */
+  @CheckReturnValue
   public static HashCode fromString(String string) {
-    checkArgument(string.length() >= 2,
-        "input string (%s) must have at least 2 characters", string);
-    checkArgument(string.length() % 2 == 0,
-        "input string (%s) must have an even number of characters", string);
+    checkArgument(
+        string.length() >= 2, "input string (%s) must have at least 2 characters", string);
+    checkArgument(
+        string.length() % 2 == 0,
+        "input string (%s) must have an even number of characters",
+        string);
 
     byte[] bytes = new byte[string.length() / 2];
     for (int i = 0; i < string.length(); i += 2) {
@@ -350,6 +378,13 @@ public abstract class HashCode {
     throw new IllegalArgumentException("Illegal hexadecimal character: " + ch);
   }
 
+  /**
+   * Returns {@code true} if {@code object} is a {@link HashCode} instance with the identical byte
+   * representation to this hash code.
+   *
+   * <p>Security note:</p> this method uses a constant-time (not short-circuiting) implementation
+   * to protect against <a href="http://en.wikipedia.org/wiki/Timing_attack">timing attacks</a>.
+   */
   @Override
   public final boolean equals(@Nullable Object object) {
     if (object instanceof HashCode) {
@@ -372,7 +407,7 @@ public abstract class HashCode {
       return asInt();
     }
     // If we have less than 4 bytes, use them all.
-    byte[] bytes = asBytes();
+    byte[] bytes = getBytesInternal();
     int val = (bytes[0] & 0xFF);
     for (int i = 1; i < bytes.length; i++) {
       val |= ((bytes[i] & 0xFF) << (i * 8));
@@ -393,7 +428,7 @@ public abstract class HashCode {
    */
   @Override
   public final String toString() {
-    byte[] bytes = asBytes();
+    byte[] bytes = getBytesInternal();
     StringBuilder sb = new StringBuilder(2 * bytes.length);
     for (byte b : bytes) {
       sb.append(hexDigits[(b >> 4) & 0xf]).append(hexDigits[b & 0xf]);
diff --git a/guava/src/com/google/common/hash/Hasher.java b/guava/src/com/google/common/hash/Hasher.java
index 2dd4a9a..df9c6bc 100644
--- a/guava/src/com/google/common/hash/Hasher.java
+++ b/guava/src/com/google/common/hash/Hasher.java
@@ -18,6 +18,8 @@ import com.google.common.annotations.Beta;
 
 import java.nio.charset.Charset;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * A {@link PrimitiveSink} that can compute a hash code after reading the input. Each hasher should
  * translate all multibyte values ({@link #putInt(int)}, {@link #putLong(long)}, etc) to bytes
@@ -51,28 +53,44 @@ import java.nio.charset.Charset;
  */
 @Beta
 public interface Hasher extends PrimitiveSink {
-  @Override Hasher putByte(byte b);
-  @Override Hasher putBytes(byte[] bytes);
-  @Override Hasher putBytes(byte[] bytes, int off, int len);
-  @Override Hasher putShort(short s);
-  @Override Hasher putInt(int i);
-  @Override Hasher putLong(long l);
+  @Override
+  Hasher putByte(byte b);
+
+  @Override
+  Hasher putBytes(byte[] bytes);
+
+  @Override
+  Hasher putBytes(byte[] bytes, int off, int len);
+
+  @Override
+  Hasher putShort(short s);
+
+  @Override
+  Hasher putInt(int i);
+
+  @Override
+  Hasher putLong(long l);
 
   /**
    * Equivalent to {@code putInt(Float.floatToRawIntBits(f))}.
    */
-  @Override Hasher putFloat(float f);
+  @Override
+  Hasher putFloat(float f);
 
   /**
    * Equivalent to {@code putLong(Double.doubleToRawLongBits(d))}.
    */
-  @Override Hasher putDouble(double d);
+  @Override
+  Hasher putDouble(double d);
 
   /**
    * Equivalent to {@code putByte(b ? (byte) 1 : (byte) 0)}.
    */
-  @Override Hasher putBoolean(boolean b);
-  @Override Hasher putChar(char c);
+  @Override
+  Hasher putBoolean(boolean b);
+
+  @Override
+  Hasher putChar(char c);
 
   /**
    * Equivalent to processing each {@code char} value in the {@code CharSequence}, in order.
@@ -80,12 +98,14 @@ public interface Hasher extends PrimitiveSink {
    *
    * @since 15.0 (since 11.0 as putString(CharSequence)).
    */
-  @Override Hasher putUnencodedChars(CharSequence charSequence);
+  @Override
+  Hasher putUnencodedChars(CharSequence charSequence);
 
   /**
    * Equivalent to {@code putBytes(charSequence.toString().getBytes(charset))}.
    */
-  @Override Hasher putString(CharSequence charSequence, Charset charset);
+  @Override
+  Hasher putString(CharSequence charSequence, Charset charset);
 
   /**
    * A simple convenience for {@code funnel.funnel(object, this)}.
@@ -96,5 +116,16 @@ public interface Hasher extends PrimitiveSink {
    * Computes a hash code based on the data that have been provided to this hasher. The result is
    * unspecified if this method is called more than once on the same instance.
    */
+  @CheckReturnValue
   HashCode hash();
+
+  /**
+   * {@inheritDoc}
+   *
+   * @deprecated This returns {@link Object#hashCode()}; you almost certainly mean to call
+   *     {@code hash().asInt()}.
+   */
+  @Override
+  @Deprecated
+  int hashCode();
 }
diff --git a/guava/src/com/google/common/hash/Hashing.java b/guava/src/com/google/common/hash/Hashing.java
index 74ab112..3cb9cff 100644
--- a/guava/src/com/google/common/hash/Hashing.java
+++ b/guava/src/com/google/common/hash/Hashing.java
@@ -15,17 +15,21 @@
 package com.google.common.hash;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Supplier;
 
 import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.zip.Adler32;
 import java.util.zip.CRC32;
 import java.util.zip.Checksum;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -41,6 +45,7 @@ import javax.annotation.Nullable;
  * @since 11.0
  */
 @Beta
+ at CheckReturnValue
 public final class Hashing {
   /**
    * Returns a general-purpose, <b>temporary-use</b>, non-cryptographic hash function. The algorithm
@@ -195,8 +200,7 @@ public final class Hashing {
   }
 
   private static class Sha1Holder {
-    static final HashFunction SHA_1 =
-        new MessageDigestHashFunction("SHA-1", "Hashing.sha1()");
+    static final HashFunction SHA_1 = new MessageDigestHashFunction("SHA-1", "Hashing.sha1()");
   }
 
   /**
@@ -213,6 +217,21 @@ public final class Hashing {
   }
 
   /**
+   * Returns a hash function implementing the SHA-384 algorithm (384 hash bits) by delegating to
+   * the SHA-384 {@link MessageDigest}.
+   *
+   * @since 19.0
+   */
+  public static HashFunction sha384() {
+    return Sha384Holder.SHA_384;
+  }
+
+  private static class Sha384Holder {
+    static final HashFunction SHA_384 =
+        new MessageDigestHashFunction("SHA-384", "Hashing.sha384()");
+  }
+
+  /**
    * Returns a hash function implementing the SHA-512 algorithm (512 hash bits) by delegating to the
    * SHA-512 {@link MessageDigest}.
    */
@@ -253,8 +272,7 @@ public final class Hashing {
   }
 
   private static class Crc32Holder {
-    static final HashFunction CRC_32 =
-        checksumHashFunction(ChecksumType.CRC_32, "Hashing.crc32()");
+    static final HashFunction CRC_32 = checksumHashFunction(ChecksumType.CRC_32, "Hashing.crc32()");
   }
 
   /**
@@ -304,34 +322,70 @@ public final class Hashing {
   }
 
   /**
-   * Assigns to {@code hashCode} a "bucket" in the range {@code [0, buckets)}, in a uniform
-   * manner that minimizes the need for remapping as {@code buckets} grows. That is,
-   * {@code consistentHash(h, n)} equals:
+   * Assigns to {@code hashCode} a "bucket" in the range {@code [0, buckets)}, in a uniform manner
+   * that minimizes the need for remapping as {@code buckets} grows. That is, {@code
+   * consistentHash(h, n)} equals:
    *
    * <ul>
    * <li>{@code n - 1}, with approximate probability {@code 1/n}
    * <li>{@code consistentHash(h, n - 1)}, otherwise (probability {@code 1 - 1/n})
    * </ul>
    *
-   * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">wikipedia
-   * article on consistent hashing</a> for more information.
+   * <p>This method is suitable for the common use case of dividing work among buckets that meet the
+   * following conditions:
+   *
+   * <ul>
+   * <li>You want to assign the same fraction of inputs to each bucket.
+   * <li>When you reduce the number of buckets, you can accept that the most recently added buckets
+   * will be removed first. More concretely, if you are dividing traffic among tasks, you can
+   * decrease the number of tasks from 15 and 10, killing off the final 5 tasks, and {@code
+   * consistentHash} will handle it. If, however, you are dividing traffic among servers {@code
+   * alpha}, {@code bravo}, and {@code charlie} and you occasionally need to take each of the
+   * servers offline, {@code consistentHash} will be a poor fit: It provides no way for you to
+   * specify which of the three buckets is disappearing. Thus, if your buckets change from {@code
+   * [alpha, bravo, charlie]} to {@code [bravo, charlie]}, it will assign all the old {@code alpha}
+   * traffic to {@code bravo} and all the old {@code bravo} traffic to {@code charlie}, rather than
+   * letting {@code bravo} keep its traffic.
+   * </ul>
+   *
+   *
+   * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">Wikipedia article on
+   * consistent hashing</a> for more information.
    */
   public static int consistentHash(HashCode hashCode, int buckets) {
     return consistentHash(hashCode.padToLong(), buckets);
   }
 
   /**
-   * Assigns to {@code input} a "bucket" in the range {@code [0, buckets)}, in a uniform
-   * manner that minimizes the need for remapping as {@code buckets} grows. That is,
-   * {@code consistentHash(h, n)} equals:
+   * Assigns to {@code input} a "bucket" in the range {@code [0, buckets)}, in a uniform manner that
+   * minimizes the need for remapping as {@code buckets} grows. That is, {@code consistentHash(h,
+   * n)} equals:
    *
    * <ul>
    * <li>{@code n - 1}, with approximate probability {@code 1/n}
    * <li>{@code consistentHash(h, n - 1)}, otherwise (probability {@code 1 - 1/n})
    * </ul>
    *
-   * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">wikipedia
-   * article on consistent hashing</a> for more information.
+   * <p>This method is suitable for the common use case of dividing work among buckets that meet the
+   * following conditions:
+   *
+   * <ul>
+   * <li>You want to assign the same fraction of inputs to each bucket.
+   * <li>When you reduce the number of buckets, you can accept that the most recently added buckets
+   * will be removed first. More concretely, if you are dividing traffic among tasks, you can
+   * decrease the number of tasks from 15 and 10, killing off the final 5 tasks, and {@code
+   * consistentHash} will handle it. If, however, you are dividing traffic among servers {@code
+   * alpha}, {@code bravo}, and {@code charlie} and you occasionally need to take each of the
+   * servers offline, {@code consistentHash} will be a poor fit: It provides no way for you to
+   * specify which of the three buckets is disappearing. Thus, if your buckets change from {@code
+   * [alpha, bravo, charlie]} to {@code [bravo, charlie]}, it will assign all the old {@code alpha}
+   * traffic to {@code bravo} and all the old {@code bravo} traffic to {@code charlie}, rather than
+   * letting {@code bravo} keep its traffic.
+   * </ul>
+   *
+   *
+   * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">Wikipedia article on
+   * consistent hashing</a> for more information.
    */
   public static int consistentHash(long input, int buckets) {
     checkArgument(buckets > 0, "buckets must be positive: %s", buckets);
@@ -367,8 +421,8 @@ public final class Hashing {
     byte[] resultBytes = new byte[bits / 8];
     for (HashCode hashCode : hashCodes) {
       byte[] nextBytes = hashCode.asBytes();
-      checkArgument(nextBytes.length == resultBytes.length,
-          "All hashcodes must have the same bit length.");
+      checkArgument(
+          nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length.");
       for (int i = 0; i < nextBytes.length; i++) {
         resultBytes[i] = (byte) (resultBytes[i] * 37 ^ nextBytes[i]);
       }
@@ -392,8 +446,8 @@ public final class Hashing {
     byte[] resultBytes = new byte[iterator.next().bits() / 8];
     for (HashCode hashCode : hashCodes) {
       byte[] nextBytes = hashCode.asBytes();
-      checkArgument(nextBytes.length == resultBytes.length,
-          "All hashcodes must have the same bit length.");
+      checkArgument(
+          nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length.");
       for (int i = 0; i < nextBytes.length; i++) {
         resultBytes[i] += nextBytes[i];
       }
@@ -409,16 +463,62 @@ public final class Hashing {
     return (bits + 31) & ~31;
   }
 
-  // TODO(kevinb): Maybe expose this class via a static Hashing method?
-  @VisibleForTesting
-  static final class ConcatenatedHashFunction extends AbstractCompositeHashFunction {
+  /**
+   * Returns a hash function which computes its hash code by concatenating the hash codes of the
+   * underlying hash functions together. This can be useful if you need to generate hash codes
+   * of a specific length.
+   *
+   * <p>For example, if you need 1024-bit hash codes, you could join two {@link Hashing#sha512}
+   * hash functions together: {@code Hashing.concatenating(Hashing.sha512(), Hashing.sha512())}.
+   *
+   * @since 19.0
+   */
+  public static HashFunction concatenating(
+      HashFunction first, HashFunction second, HashFunction... rest) {
+    // We can't use Lists.asList() here because there's no hash->collect dependency
+    List<HashFunction> list = new ArrayList<HashFunction>();
+    list.add(first);
+    list.add(second);
+    for (HashFunction hashFunc : rest) {
+      list.add(hashFunc);
+    }
+    return new ConcatenatedHashFunction(list.toArray(new HashFunction[0]));
+  }
+
+  /**
+   * Returns a hash function which computes its hash code by concatenating the hash codes of the
+   * underlying hash functions together. This can be useful if you need to generate hash codes
+   * of a specific length.
+   *
+   * <p>For example, if you need 1024-bit hash codes, you could join two {@link Hashing#sha512}
+   * hash functions together: {@code Hashing.concatenating(Hashing.sha512(), Hashing.sha512())}.
+   *
+   * @since 19.0
+   */
+  public static HashFunction concatenating(Iterable<HashFunction> hashFunctions) {
+    checkNotNull(hashFunctions);
+    // We can't use Iterables.toArray() here because there's no hash->collect dependency
+    List<HashFunction> list = new ArrayList<HashFunction>();
+    for (HashFunction hashFunction : hashFunctions) {
+      list.add(hashFunction);
+    }
+    checkArgument(list.size() > 0, "number of hash functions (%s) must be > 0", list.size());
+    return new ConcatenatedHashFunction(list.toArray(new HashFunction[0]));
+  }
+
+  private static final class ConcatenatedHashFunction extends AbstractCompositeHashFunction {
     private final int bits;
 
-    ConcatenatedHashFunction(HashFunction... functions) {
+    private ConcatenatedHashFunction(HashFunction... functions) {
       super(functions);
       int bitSum = 0;
       for (HashFunction function : functions) {
         bitSum += function.bits();
+        checkArgument(
+            function.bits() % 8 == 0,
+            "the number of bits (%s) in hashFunction (%s) must be divisible by 8",
+            function.bits(),
+            function);
       }
       this.bits = bitSum;
     }
@@ -443,26 +543,14 @@ public final class Hashing {
     public boolean equals(@Nullable Object object) {
       if (object instanceof ConcatenatedHashFunction) {
         ConcatenatedHashFunction other = (ConcatenatedHashFunction) object;
-        if (bits != other.bits || functions.length != other.functions.length) {
-          return false;
-        }
-        for (int i = 0; i < functions.length; i++) {
-          if (!functions[i].equals(other.functions[i])) {
-            return false;
-          }
-        }
-        return true;
+        return Arrays.equals(functions, other.functions);
       }
       return false;
     }
 
     @Override
     public int hashCode() {
-      int hash = bits;
-      for (HashFunction function : functions) {
-        hash ^= function.hashCode();
-      }
-      return hash;
+      return Arrays.hashCode(functions) * 31 + bits;
     }
   }
 
diff --git a/guava/src/com/google/common/hash/HashingInputStream.java b/guava/src/com/google/common/hash/HashingInputStream.java
index 3fcc621..b6262e8 100644
--- a/guava/src/com/google/common/hash/HashingInputStream.java
+++ b/guava/src/com/google/common/hash/HashingInputStream.java
@@ -22,6 +22,8 @@ import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * An {@link InputStream} that maintains a hash of the data read from it.
  *
@@ -74,6 +76,7 @@ public final class HashingInputStream extends FilterInputStream {
    * @return {@code false} always
    */
   @Override
+  @CheckReturnValue
   public boolean markSupported() {
     return false;
   }
@@ -97,6 +100,7 @@ public final class HashingInputStream extends FilterInputStream {
    * Returns the {@link HashCode} based on the data read from this stream. The result is
    * unspecified if this method is called more than once on the same instance.
    */
+  @CheckReturnValue
   public HashCode hash() {
     return hasher.hash();
   }
diff --git a/guava/src/com/google/common/hash/HashingOutputStream.java b/guava/src/com/google/common/hash/HashingOutputStream.java
index 057b577..df57920 100644
--- a/guava/src/com/google/common/hash/HashingOutputStream.java
+++ b/guava/src/com/google/common/hash/HashingOutputStream.java
@@ -22,6 +22,8 @@ import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * An {@link OutputStream} that maintains a hash of the data written to it.
  *
@@ -47,12 +49,14 @@ public final class HashingOutputStream extends FilterOutputStream {
     this.hasher = checkNotNull(hashFunction.newHasher());
   }
 
-  @Override public void write(int b) throws IOException {
+  @Override
+  public void write(int b) throws IOException {
     hasher.putByte((byte) b);
     out.write(b);
   }
 
-  @Override public void write(byte[] bytes, int off, int len) throws IOException {
+  @Override
+  public void write(byte[] bytes, int off, int len) throws IOException {
     hasher.putBytes(bytes, off, len);
     out.write(bytes, off, len);
   }
@@ -61,6 +65,7 @@ public final class HashingOutputStream extends FilterOutputStream {
    * Returns the {@link HashCode} based on the data written to this stream. The result is
    * unspecified if this method is called more than once on the same instance.
    */
+  @CheckReturnValue
   public HashCode hash() {
     return hasher.hash();
   }
@@ -68,7 +73,8 @@ public final class HashingOutputStream extends FilterOutputStream {
   // Overriding close() because FilterOutputStream's close() method pre-JDK8 has bad behavior:
   // it silently ignores any exception thrown by flush(). Instead, just close the delegate stream.
   // It should flush itself if necessary.
-  @Override public void close() throws IOException {
+  @Override
+  public void close() throws IOException {
     out.close();
   }
 }
diff --git a/guava/src/com/google/common/hash/MessageDigestHashFunction.java b/guava/src/com/google/common/hash/MessageDigestHashFunction.java
index e160833..80fcec4 100644
--- a/guava/src/com/google/common/hash/MessageDigestHashFunction.java
+++ b/guava/src/com/google/common/hash/MessageDigestHashFunction.java
@@ -47,8 +47,8 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
     this.toString = checkNotNull(toString);
     this.prototype = getMessageDigest(algorithmName);
     int maxLength = prototype.getDigestLength();
-    checkArgument(bytes >= 4 && bytes <= maxLength,
-        "bytes (%s) must be >= 4 and < %s", bytes, maxLength);
+    checkArgument(
+        bytes >= 4 && bytes <= maxLength, "bytes (%s) must be >= 4 and < %s", bytes, maxLength);
     this.bytes = bytes;
     this.supportsClone = supportsClone();
   }
@@ -62,11 +62,13 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
     }
   }
 
-  @Override public int bits() {
+  @Override
+  public int bits() {
     return bytes * Byte.SIZE;
   }
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return toString;
   }
 
@@ -78,7 +80,8 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
     }
   }
 
-  @Override public Hasher newHasher() {
+  @Override
+  public Hasher newHasher() {
     if (supportsClone) {
       try {
         return new MessageDigestHasher((MessageDigest) prototype.clone(), bytes);
@@ -115,7 +118,6 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
    * Hasher that updates a message digest.
    */
   private static final class MessageDigestHasher extends AbstractByteHasher {
-
     private final MessageDigest digest;
     private final int bytes;
     private boolean done;
diff --git a/guava/src/com/google/common/hash/Murmur3_128HashFunction.java b/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
index 1fde761..05aa9c1 100644
--- a/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
+++ b/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
@@ -48,11 +48,13 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
     this.seed = seed;
   }
 
-  @Override public int bits() {
+  @Override
+  public int bits() {
     return 128;
   }
 
-  @Override public Hasher newHasher() {
+  @Override
+  public Hasher newHasher() {
     return new Murmur3_128Hasher(seed);
   }
 
@@ -90,7 +92,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
       this.length = 0;
     }
 
-    @Override protected void process(ByteBuffer bb) {
+    @Override
+    protected void process(ByteBuffer bb) {
       long k1 = bb.getLong();
       long k2 = bb.getLong();
       bmix64(k1, k2);
@@ -111,7 +114,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
       h2 = h2 * 5 + 0x38495ab5;
     }
 
-    @Override protected void processRemaining(ByteBuffer bb) {
+    @Override
+    protected void processRemaining(ByteBuffer bb) {
       long k1 = 0;
       long k2 = 0;
       length += bb.remaining();
@@ -155,7 +159,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
       h2 ^= mixK2(k2);
     }
 
-    @Override public HashCode makeHash() {
+    @Override
+    public HashCode makeHash() {
       h1 ^= length;
       h2 ^= length;
 
@@ -168,12 +173,12 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
       h1 += h2;
       h2 += h1;
 
-      return HashCode.fromBytesNoCopy(ByteBuffer
-          .wrap(new byte[CHUNK_SIZE])
-          .order(ByteOrder.LITTLE_ENDIAN)
-          .putLong(h1)
-          .putLong(h2)
-          .array());
+      return HashCode.fromBytesNoCopy(
+          ByteBuffer.wrap(new byte[CHUNK_SIZE])
+              .order(ByteOrder.LITTLE_ENDIAN)
+              .putLong(h1)
+              .putLong(h2)
+              .array());
     }
 
     private static long fmix64(long k) {
diff --git a/guava/src/com/google/common/hash/Murmur3_32HashFunction.java b/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
index db6e673..22f53cf 100644
--- a/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
+++ b/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
@@ -54,11 +54,13 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
     this.seed = seed;
   }
 
-  @Override public int bits() {
+  @Override
+  public int bits() {
     return 32;
   }
 
-  @Override public Hasher newHasher() {
+  @Override
+  public Hasher newHasher() {
     return new Murmur3_32Hasher(seed);
   }
 
@@ -81,14 +83,16 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
     return getClass().hashCode() ^ seed;
   }
 
-  @Override public HashCode hashInt(int input) {
+  @Override
+  public HashCode hashInt(int input) {
     int k1 = mixK1(input);
     int h1 = mixH1(seed, k1);
 
     return fmix(h1, Ints.BYTES);
   }
 
-  @Override public HashCode hashLong(long input) {
+  @Override
+  public HashCode hashLong(long input) {
     int low = (int) input;
     int high = (int) (input >>> 32);
 
@@ -101,8 +105,9 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
     return fmix(h1, Longs.BYTES);
   }
 
-  // TODO(user): Maybe implement #hashBytes instead?
-  @Override public HashCode hashUnencodedChars(CharSequence input) {
+  // TODO(kak): Maybe implement #hashBytes instead?
+  @Override
+  public HashCode hashUnencodedChars(CharSequence input) {
     int h1 = seed;
 
     // step through the CharSequence 2 chars at a time
@@ -158,13 +163,15 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
       this.length = 0;
     }
 
-    @Override protected void process(ByteBuffer bb) {
+    @Override
+    protected void process(ByteBuffer bb) {
       int k1 = Murmur3_32HashFunction.mixK1(bb.getInt());
       h1 = Murmur3_32HashFunction.mixH1(h1, k1);
       length += CHUNK_SIZE;
     }
 
-    @Override protected void processRemaining(ByteBuffer bb) {
+    @Override
+    protected void processRemaining(ByteBuffer bb) {
       length += bb.remaining();
       int k1 = 0;
       for (int i = 0; bb.hasRemaining(); i += 8) {
@@ -173,7 +180,8 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
       h1 ^= Murmur3_32HashFunction.mixK1(k1);
     }
 
-    @Override public HashCode makeHash() {
+    @Override
+    public HashCode makeHash() {
       return Murmur3_32HashFunction.fmix(h1, length);
     }
   }
diff --git a/guava/src/com/google/common/hash/SipHashFunction.java b/guava/src/com/google/common/hash/SipHashFunction.java
index 0496a3c..5bac1c1 100644
--- a/guava/src/com/google/common/hash/SipHashFunction.java
+++ b/guava/src/com/google/common/hash/SipHashFunction.java
@@ -50,27 +50,30 @@ final class SipHashFunction extends AbstractStreamingHashFunction implements Ser
    * @param k1 the second half of the key
    */
   SipHashFunction(int c, int d, long k0, long k1) {
-    checkArgument(c > 0,
-        "The number of SipRound iterations (c=%s) during Compression must be positive.", c);
-    checkArgument(d > 0,
-        "The number of SipRound iterations (d=%s) during Finalization must be positive.", d);
+    checkArgument(
+        c > 0, "The number of SipRound iterations (c=%s) during Compression must be positive.", c);
+    checkArgument(
+        d > 0, "The number of SipRound iterations (d=%s) during Finalization must be positive.", d);
     this.c = c;
     this.d = d;
     this.k0 = k0;
     this.k1 = k1;
   }
 
-  @Override public int bits() {
+  @Override
+  public int bits() {
     return 64;
   }
 
-  @Override public Hasher newHasher() {
+  @Override
+  public Hasher newHasher() {
     return new SipHasher(c, d, k0, k1);
   }
 
-  // TODO(user): Implement and benchmark the hashFoo() shortcuts.
+  // TODO(kak): Implement and benchmark the hashFoo() shortcuts.
 
-  @Override public String toString() {
+  @Override
+  public String toString() {
     return "Hashing.sipHash" + c + "" + d + "(" + k0 + ", " + k1 + ")";
   }
 
@@ -125,19 +128,22 @@ final class SipHashFunction extends AbstractStreamingHashFunction implements Ser
       this.v3 ^= k1;
     }
 
-    @Override protected void process(ByteBuffer buffer) {
+    @Override
+    protected void process(ByteBuffer buffer) {
       b += CHUNK_SIZE;
       processM(buffer.getLong());
     }
 
-    @Override protected void processRemaining(ByteBuffer buffer) {
+    @Override
+    protected void processRemaining(ByteBuffer buffer) {
       b += buffer.remaining();
       for (int i = 0; buffer.hasRemaining(); i += 8) {
         finalM ^= (buffer.get() & 0xFFL) << i;
       }
     }
 
-    @Override public HashCode makeHash() {
+    @Override
+    public HashCode makeHash() {
       // End with a byte encoding the positive integer b mod 256.
       finalM ^= b << 56;
       processM(finalM);
diff --git a/guava/src/com/google/common/hash/package-info.java b/guava/src/com/google/common/hash/package-info.java
index 7df4e73..a55060a 100644
--- a/guava/src/com/google/common/hash/package-info.java
+++ b/guava/src/com/google/common/hash/package-info.java
@@ -17,7 +17,7 @@
  * Hash functions and related structures.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/HashingExplained">
+ * "https://github.com/google/guava/wiki/HashingExplained">
  * hashing</a>.
  */
 @ParametersAreNonnullByDefault
diff --git a/guava/src/com/google/common/html/HtmlEscapers.java b/guava/src/com/google/common/html/HtmlEscapers.java
index d96febf..c2009dd 100644
--- a/guava/src/com/google/common/html/HtmlEscapers.java
+++ b/guava/src/com/google/common/html/HtmlEscapers.java
@@ -26,6 +26,9 @@ import com.google.common.escape.Escapers;
  * attribute values and <em>most</em> elements' text contents. When possible,
  * avoid manual escaping by using templating systems and high-level APIs that
  * provide autoescaping.
+ * One Google-authored templating system available for external use is <a
+ * href="https://developers.google.com/closure/templates/">Closure
+ * Templates</a>.
  *
  * <p>HTML escaping is particularly tricky: For example, <a
  * href="http://goo.gl/5TgZb">some elements' text contents must not be HTML
diff --git a/guava/src/com/google/common/io/BaseEncoding.java b/guava/src/com/google/common/io/BaseEncoding.java
index 13c3f55..cb21d4b 100644
--- a/guava/src/com/google/common/io/BaseEncoding.java
+++ b/guava/src/com/google/common/io/BaseEncoding.java
@@ -18,11 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkPositionIndexes;
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.io.GwtWorkarounds.asCharInput;
-import static com.google.common.io.GwtWorkarounds.asCharOutput;
-import static com.google.common.io.GwtWorkarounds.asInputStream;
-import static com.google.common.io.GwtWorkarounds.asOutputStream;
-import static com.google.common.io.GwtWorkarounds.stringBuilderOutput;
 import static com.google.common.math.IntMath.divide;
 import static com.google.common.math.IntMath.log2;
 import static java.math.RoundingMode.CEILING;
@@ -34,10 +29,6 @@ import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Ascii;
 import com.google.common.base.CharMatcher;
-import com.google.common.io.GwtWorkarounds.ByteInput;
-import com.google.common.io.GwtWorkarounds.ByteOutput;
-import com.google.common.io.GwtWorkarounds.CharInput;
-import com.google.common.io.GwtWorkarounds.CharOutput;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -131,7 +122,7 @@ import javax.annotation.Nullable;
 @Beta
 @GwtCompatible(emulated = true)
 public abstract class BaseEncoding {
-  // TODO(user): consider adding encodeTo(Appendable, byte[], [int, int])
+  // TODO(lowasser): consider making encodeTo(Appendable, byte[], int, int) public.
 
   BaseEncoding() {}
 
@@ -155,7 +146,7 @@ public abstract class BaseEncoding {
    * Encodes the specified byte array, and returns the encoded {@code String}.
    */
   public String encode(byte[] bytes) {
-    return encode(checkNotNull(bytes), 0, bytes.length);
+    return encode(bytes, 0, bytes.length);
   }
 
   /**
@@ -163,17 +154,12 @@ public abstract class BaseEncoding {
    * {@code String}.
    */
   public final String encode(byte[] bytes, int off, int len) {
-    checkNotNull(bytes);
     checkPositionIndexes(off, off + len, bytes.length);
-    CharOutput result = stringBuilderOutput(maxEncodedSize(len));
-    ByteOutput byteOutput = encodingStream(result);
+    StringBuilder result = new StringBuilder(maxEncodedSize(len));
     try {
-      for (int i = 0; i < len; i++) {
-        byteOutput.write(bytes[off + i]);
-      }
-      byteOutput.close();
+      encodeTo(result, bytes, off, len);
     } catch (IOException impossible) {
-      throw new AssertionError("impossible");
+      throw new AssertionError(impossible);
     }
     return result.toString();
   }
@@ -184,9 +170,7 @@ public abstract class BaseEncoding {
    * {@code Writer}.
    */
   @GwtIncompatible("Writer,OutputStream")
-  public final OutputStream encodingStream(Writer writer) {
-    return asOutputStream(encodingStream(asCharOutput(writer)));
-  }
+  public abstract OutputStream encodingStream(Writer writer);
 
   /**
    * Returns a {@code ByteSink} that writes base-encoded bytes to the specified {@code CharSink}.
@@ -202,7 +186,7 @@ public abstract class BaseEncoding {
     };
   }
 
-  // TODO(user): document the extent of leniency, probably after adding ignore(CharMatcher)
+  // TODO(lowasser): document the extent of leniency, probably after adding ignore(CharMatcher)
 
   private static byte[] extract(byte[] result, int length) {
     if (length == result.length) {
@@ -238,19 +222,9 @@ public abstract class BaseEncoding {
    */
   final byte[] decodeChecked(CharSequence chars) throws DecodingException {
     chars = padding().trimTrailingFrom(chars);
-    ByteInput decodedInput = decodingStream(asCharInput(chars));
     byte[] tmp = new byte[maxDecodedSize(chars.length())];
-    int index = 0;
-    try {
-      for (int i = decodedInput.read(); i != -1; i = decodedInput.read()) {
-        tmp[index++] = (byte) i;
-      }
-    } catch (DecodingException badInput) {
-      throw badInput;
-    } catch (IOException impossible) {
-      throw new AssertionError(impossible);
-    }
-    return extract(tmp, index);
+    int len = decodeTo(tmp, chars);
+    return extract(tmp, len);
   }
 
   /**
@@ -259,9 +233,7 @@ public abstract class BaseEncoding {
    * errors.
    */
   @GwtIncompatible("Reader,InputStream")
-  public final InputStream decodingStream(Reader reader) {
-    return asInputStream(decodingStream(asCharInput(reader)));
-  }
+  public abstract InputStream decodingStream(Reader reader);
 
   /**
    * Returns a {@code ByteSource} that reads base-encoded bytes from the specified
@@ -282,11 +254,11 @@ public abstract class BaseEncoding {
 
   abstract int maxEncodedSize(int bytes);
 
-  abstract ByteOutput encodingStream(CharOutput charOutput);
+  abstract void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException;
 
   abstract int maxDecodedSize(int chars);
 
-  abstract ByteInput decodingStream(CharInput charInput);
+  abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException;
 
   abstract CharMatcher padding();
 
@@ -342,7 +314,7 @@ public abstract class BaseEncoding {
   @CheckReturnValue
   public abstract BaseEncoding lowerCase();
 
-  private static final BaseEncoding BASE64 = new StandardBaseEncoding(
+  private static final BaseEncoding BASE64 = new Base64Encoding(
       "base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", '=');
 
   /**
@@ -362,7 +334,7 @@ public abstract class BaseEncoding {
     return BASE64;
   }
 
-  private static final BaseEncoding BASE64_URL = new StandardBaseEncoding(
+  private static final BaseEncoding BASE64_URL = new Base64Encoding(
       "base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", '=');
 
   /**
@@ -422,8 +394,7 @@ public abstract class BaseEncoding {
     return BASE32_HEX;
   }
 
-  private static final BaseEncoding BASE16 =
-      new StandardBaseEncoding("base16()", "0123456789ABCDEF", null);
+  private static final BaseEncoding BASE16 = new Base16Encoding("base16()", "0123456789ABCDEF");
 
   /**
    * The "base16" encoding specified by <a
@@ -498,9 +469,10 @@ public abstract class BaseEncoding {
       return validPadding[index % charsPerChunk];
     }
 
-    int decode(char ch) throws IOException {
+    int decode(char ch) throws DecodingException {
       if (ch > Ascii.MAX || decodabet[ch] == -1) {
-        throw new DecodingException("Unrecognized character: " + ch);
+        throw new DecodingException("Unrecognized character: "
+            + (CharMatcher.INVISIBLE.matches(ch) ? "0x" + Integer.toHexString(ch) : ch));
       }
       return decodabet[ch];
     }
@@ -560,12 +532,12 @@ public abstract class BaseEncoding {
     }
   }
 
-  static final class StandardBaseEncoding extends BaseEncoding {
-    // TODO(user): provide a useful toString
-    private final Alphabet alphabet;
+  static class StandardBaseEncoding extends BaseEncoding {
+    // TODO(lowasser): provide a useful toString
+    final Alphabet alphabet;
 
     @Nullable
-    private final Character paddingChar;
+    final Character paddingChar;
 
     StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) {
       this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
@@ -588,16 +560,17 @@ public abstract class BaseEncoding {
       return alphabet.charsPerChunk * divide(bytes, alphabet.bytesPerChunk, CEILING);
     }
 
+    @GwtIncompatible("Writer,OutputStream")
     @Override
-    ByteOutput encodingStream(final CharOutput out) {
+    public OutputStream encodingStream(final Writer out) {
       checkNotNull(out);
-      return new ByteOutput() {
+      return new OutputStream() {
         int bitBuffer = 0;
         int bitBufferLength = 0;
         int writtenChars = 0;
 
         @Override
-        public void write(byte b) throws IOException {
+        public void write(int b) throws IOException {
           bitBuffer <<= 8;
           bitBuffer |= b & 0xFF;
           bitBufferLength += 8;
@@ -635,14 +608,75 @@ public abstract class BaseEncoding {
     }
 
     @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      for (int i = 0; i < len; i += alphabet.bytesPerChunk) {
+        encodeChunkTo(target, bytes, off + i, Math.min(alphabet.bytesPerChunk, len - i));
+      }
+    }
+
+    void encodeChunkTo(Appendable target, byte[] bytes, int off, int len)
+        throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      checkArgument(len <= alphabet.bytesPerChunk);
+      long bitBuffer = 0;
+      for (int i = 0; i < len; ++i) {
+        bitBuffer |= bytes[off + i] & 0xFF;
+        bitBuffer <<= 8; // Add additional zero byte in the end.
+      }
+      // Position of first character is length of bitBuffer minus bitsPerChar.
+      final int bitOffset = (len + 1) * 8 - alphabet.bitsPerChar;
+      int bitsProcessed = 0;
+      while (bitsProcessed < len * 8) {
+        int charIndex = (int) (bitBuffer >>> (bitOffset - bitsProcessed)) & alphabet.mask;
+        target.append(alphabet.encode(charIndex));
+        bitsProcessed += alphabet.bitsPerChar;
+      }
+      if (paddingChar != null) {
+        while (bitsProcessed < alphabet.bytesPerChunk * 8) {
+          target.append(paddingChar.charValue());
+          bitsProcessed += alphabet.bitsPerChar;
+        }
+      }
+    }
+
+    @Override
     int maxDecodedSize(int chars) {
       return (int) ((alphabet.bitsPerChar * (long) chars + 7L) / 8L);
     }
 
     @Override
-    ByteInput decodingStream(final CharInput reader) {
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      chars = padding().trimTrailingFrom(chars);
+      if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int charIdx = 0; charIdx < chars.length(); charIdx += alphabet.charsPerChunk) {
+        long chunk = 0;
+        int charsProcessed = 0;
+        for (int i = 0; i < alphabet.charsPerChunk; i++) {
+          chunk <<= alphabet.bitsPerChar;
+          if (charIdx + i < chars.length()) {
+            chunk |= alphabet.decode(chars.charAt(charIdx + charsProcessed++));
+          }
+        }
+        final int minOffset = alphabet.bytesPerChunk * 8 - charsProcessed * alphabet.bitsPerChar;
+        for (int offset = (alphabet.bytesPerChunk - 1) * 8; offset >= minOffset; offset -= 8) {
+          target[bytesWritten++] = (byte) ((chunk >>> offset) & 0xFF);
+        }
+      }
+      return bytesWritten;
+    }
+
+    @GwtIncompatible("Reader,InputStream")
+    @Override
+    public InputStream decodingStream(final Reader reader) {
       checkNotNull(reader);
-      return new ByteInput() {
+      return new InputStream() {
         int bitBuffer = 0;
         int bitBufferLength = 0;
         int readChars = 0;
@@ -692,7 +726,7 @@ public abstract class BaseEncoding {
 
     @Override
     public BaseEncoding omitPadding() {
-      return (paddingChar == null) ? this : new StandardBaseEncoding(alphabet, null);
+      return (paddingChar == null) ? this : newInstance(alphabet, null);
     }
 
     @Override
@@ -701,15 +735,14 @@ public abstract class BaseEncoding {
           (paddingChar != null && paddingChar.charValue() == padChar)) {
         return this;
       } else {
-        return new StandardBaseEncoding(alphabet, padChar);
+        return newInstance(alphabet, padChar);
       }
     }
 
     @Override
     public BaseEncoding withSeparator(String separator, int afterEveryChars) {
-      checkNotNull(separator);
       checkArgument(padding().or(alphabet).matchesNoneOf(separator),
-          "Separator cannot contain alphabet or padding characters");
+          "Separator (%s) cannot contain alphabet or padding characters", separator);
       return new SeparatedBaseEncoding(this, separator, afterEveryChars);
     }
 
@@ -722,7 +755,7 @@ public abstract class BaseEncoding {
       if (result == null) {
         Alphabet upper = alphabet.upperCase();
         result = upperCase =
-            (upper == alphabet) ? this : new StandardBaseEncoding(upper, paddingChar);
+            (upper == alphabet) ? this : newInstance(upper, paddingChar);
       }
       return result;
     }
@@ -733,11 +766,15 @@ public abstract class BaseEncoding {
       if (result == null) {
         Alphabet lower = alphabet.lowerCase();
         result = lowerCase =
-            (lower == alphabet) ? this : new StandardBaseEncoding(lower, paddingChar);
+            (lower == alphabet) ? this : newInstance(lower, paddingChar);
       }
       return result;
     }
 
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new StandardBaseEncoding(alphabet, paddingChar);
+    }
+
     @Override
     public String toString() {
       StringBuilder builder = new StringBuilder("BaseEncoding.");
@@ -753,10 +790,115 @@ public abstract class BaseEncoding {
     }
   }
 
-  static CharInput ignoringInput(final CharInput delegate, final CharMatcher toIgnore) {
+  static final class Base16Encoding extends StandardBaseEncoding {
+    final char[] encoding = new char[512];
+
+    Base16Encoding(String name, String alphabetChars) {
+      this(new Alphabet(name, alphabetChars.toCharArray()));
+    }
+
+    private Base16Encoding(Alphabet alphabet) {
+      super(alphabet, null);
+      checkArgument(alphabet.chars.length == 16);
+      for (int i = 0; i < 256; ++i) {
+        encoding[i] = alphabet.encode(i >>> 4);
+        encoding[i | 0x100] = alphabet.encode(i & 0xF);
+      }
+    }
+
+    @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      for (int i = 0; i < len; ++i) {
+        int b = bytes[off + i] & 0xFF;
+        target.append(encoding[b]);
+        target.append(encoding[b | 0x100]);
+      }
+    }
+
+    @Override
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      if (chars.length() % 2 == 1) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int i = 0; i < chars.length(); i += 2) {
+        int decoded = alphabet.decode(chars.charAt(i)) << 4 | alphabet.decode(chars.charAt(i + 1));
+        target[bytesWritten++] = (byte) decoded;
+      }
+      return bytesWritten;
+    }
+
+    @Override
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new Base16Encoding(alphabet);
+    }
+  }
+
+  static final class Base64Encoding extends StandardBaseEncoding {
+    Base64Encoding(String name, String alphabetChars, @Nullable Character paddingChar) {
+      this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
+    }
+
+    private Base64Encoding(Alphabet alphabet, @Nullable Character paddingChar) {
+      super(alphabet, paddingChar);
+      checkArgument(alphabet.chars.length == 64);
+    }
+
+    @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      checkNotNull(target);
+      checkPositionIndexes(off, off + len, bytes.length);
+      int i = off;
+      for (int remaining = len; remaining >= 3; remaining -= 3) {
+        int chunk = (bytes[i++] & 0xFF) << 16 | (bytes[i++] & 0xFF) << 8 | bytes[i++] & 0xFF;
+        target.append(alphabet.encode(chunk >>> 18));
+        target.append(alphabet.encode((chunk >>> 12) & 0x3F));
+        target.append(alphabet.encode((chunk >>> 6) & 0x3F));
+        target.append(alphabet.encode(chunk & 0x3F));
+      }
+      if (i < off + len) {
+        encodeChunkTo(target, bytes, i, off + len - i);
+      }
+    }
+
+    @Override
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      checkNotNull(target);
+      chars = padding().trimTrailingFrom(chars);
+      if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+        throw new DecodingException("Invalid input length " + chars.length());
+      }
+      int bytesWritten = 0;
+      for (int i = 0; i < chars.length();) {
+        int chunk = alphabet.decode(chars.charAt(i++)) << 18;
+        chunk |= alphabet.decode(chars.charAt(i++)) << 12;
+        target[bytesWritten++] = (byte) (chunk >>> 16);
+        if (i < chars.length()) {
+          chunk |= alphabet.decode(chars.charAt(i++)) << 6;
+          target[bytesWritten++] = (byte) ((chunk >>> 8) & 0xFF);
+          if (i < chars.length()) {
+            chunk |= alphabet.decode(chars.charAt(i++));
+            target[bytesWritten++] = (byte) (chunk & 0xFF);
+          }
+        }
+      }
+      return bytesWritten;
+    }
+
+    @Override
+    BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+      return new Base64Encoding(alphabet, paddingChar);
+    }
+  }
+
+  @GwtIncompatible("Reader")
+  static Reader ignoringReader(final Reader delegate, final CharMatcher toIgnore) {
     checkNotNull(delegate);
     checkNotNull(toIgnore);
-    return new CharInput() {
+    return new Reader() {
       @Override
       public int read() throws IOException {
         int readChar;
@@ -767,30 +909,62 @@ public abstract class BaseEncoding {
       }
 
       @Override
+      public int read(char[] cbuf, int off, int len) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
       public void close() throws IOException {
         delegate.close();
       }
     };
   }
 
-  static CharOutput separatingOutput(
-      final CharOutput delegate, final String separator, final int afterEveryChars) {
+  static Appendable separatingAppendable(
+      final Appendable delegate, final String separator, final int afterEveryChars) {
     checkNotNull(delegate);
     checkNotNull(separator);
     checkArgument(afterEveryChars > 0);
-    return new CharOutput() {
+    return new Appendable() {
       int charsUntilSeparator = afterEveryChars;
 
       @Override
-      public void write(char c) throws IOException {
+      public Appendable append(char c) throws IOException {
         if (charsUntilSeparator == 0) {
-          for (int i = 0; i < separator.length(); i++) {
-            delegate.write(separator.charAt(i));
-          }
+          delegate.append(separator);
           charsUntilSeparator = afterEveryChars;
         }
-        delegate.write(c);
+        delegate.append(c);
         charsUntilSeparator--;
+        return this;
+      }
+
+      @Override
+      public Appendable append(CharSequence chars, int off, int len) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public Appendable append(CharSequence chars) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+
+  @GwtIncompatible("Writer")
+  static Writer separatingWriter(
+      final Writer delegate, final String separator, final int afterEveryChars) {
+    final Appendable seperatingAppendable =
+        separatingAppendable(delegate, separator, afterEveryChars);
+    return new Writer() {
+      @Override
+      public void write(int c) throws IOException {
+        seperatingAppendable.append((char) c);
+      }
+
+      @Override
+      public void write(char[] chars, int off, int len) throws IOException {
+        throw new UnsupportedOperationException();
       }
 
       @Override
@@ -832,9 +1006,15 @@ public abstract class BaseEncoding {
           * divide(Math.max(0, unseparatedSize - 1), afterEveryChars, FLOOR);
     }
 
+    @GwtIncompatible("Writer,OutputStream")
     @Override
-    ByteOutput encodingStream(final CharOutput output) {
-      return delegate.encodingStream(separatingOutput(output, separator, afterEveryChars));
+    public OutputStream encodingStream(final Writer output) {
+      return delegate.encodingStream(separatingWriter(output, separator, afterEveryChars));
+    }
+
+    @Override
+    void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+      delegate.encodeTo(separatingAppendable(target, separator, afterEveryChars), bytes, off, len);
     }
 
     @Override
@@ -843,8 +1023,14 @@ public abstract class BaseEncoding {
     }
 
     @Override
-    ByteInput decodingStream(final CharInput input) {
-      return delegate.decodingStream(ignoringInput(input, separatorChars));
+    int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+      return delegate.decodeTo(target, separatorChars.removeFrom(chars));
+    }
+
+    @GwtIncompatible("Reader,InputStream")
+    @Override
+    public InputStream decodingStream(final Reader reader) {
+      return delegate.decodingStream(ignoringReader(reader, separatorChars));
     }
 
     @Override
diff --git a/guava/src/com/google/common/io/ByteArrayDataInput.java b/guava/src/com/google/common/io/ByteArrayDataInput.java
index 3f4a467..8e029ef 100644
--- a/guava/src/com/google/common/io/ByteArrayDataInput.java
+++ b/guava/src/com/google/common/io/ByteArrayDataInput.java
@@ -23,7 +23,7 @@ import java.io.IOException;
  * An extension of {@code DataInput} for reading from in-memory byte arrays; its
  * methods offer identical functionality but do not throw {@link IOException}.
  *
- * <p><b>Warning:<b> The caller is responsible for not attempting to read past
+ * <p><b>Warning:</b> The caller is responsible for not attempting to read past
  * the end of the array. If any method encounters the end of the array
  * prematurely, it throws {@link IllegalStateException} to signify <i>programmer
  * error</i>. This behavior is a technical violation of the supertype's
diff --git a/guava/src/com/google/common/io/ByteSource.java b/guava/src/com/google/common/io/ByteSource.java
index 4cddcdd..b829cc5 100644
--- a/guava/src/com/google/common/io/ByteSource.java
+++ b/guava/src/com/google/common/io/ByteSource.java
@@ -18,9 +18,12 @@ package com.google.common.io;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.io.ByteStreams.BUF_SIZE;
+import static com.google.common.io.ByteStreams.skipUpTo;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Ascii;
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.hash.Funnels;
 import com.google.common.hash.HashCode;
@@ -58,8 +61,6 @@ import java.util.Iterator;
  */
 public abstract class ByteSource {
 
-  private static final int BUF_SIZE = 0x1000; // 4K
-
   /**
    * Constructor for use by subclasses.
    */
@@ -104,7 +105,10 @@ public abstract class ByteSource {
 
   /**
    * Returns a view of a slice of this byte source that is at most {@code length} bytes long
-   * starting at the given {@code offset}.
+   * starting at the given {@code offset}. If {@code offset} is greater than the size of this
+   * source, the returned source will be empty. If {@code offset + length} is greater than the size
+   * of this source, the returned source will contain the slice starting at {@code offset} and
+   * ending at the end of this source.
    *
    * @throws IllegalArgumentException if {@code offset} or {@code length} is negative
    */
@@ -113,13 +117,23 @@ public abstract class ByteSource {
   }
 
   /**
-   * Returns whether the source has zero bytes. The default implementation is to open a stream and
-   * check for EOF.
+   * Returns whether the source has zero bytes. The default implementation returns true if
+   * {@link #sizeIfKnown} returns zero, falling back to opening a stream and checking for
+   * EOF if the size is not known.
+   *
+   * <p>Note that, in cases where {@code sizeIfKnown} returns zero, it is <i>possible</i> that bytes
+   * are actually available for reading. (For example, some special files may return a size of 0
+   * despite actually having content when read.) This means that a source may return {@code true}
+   * from {@code isEmpty()} despite having readable content.
    *
    * @throws IOException if an I/O error occurs
    * @since 15.0
    */
   public boolean isEmpty() throws IOException {
+    Optional<Long> sizeIfKnown = sizeIfKnown();
+    if (sizeIfKnown.isPresent() && sizeIfKnown.get() == 0L) {
+      return true;
+    }
     Closer closer = Closer.create();
     try {
       InputStream in = closer.register(openStream());
@@ -132,21 +146,49 @@ public abstract class ByteSource {
   }
 
   /**
-   * Returns the size of this source in bytes. For most implementations, this is a heavyweight
-   * operation that will open a stream, read (or {@link InputStream#skip(long) skip}, if possible)
-   * to the end of the stream and return the total number of bytes that were read.
+   * Returns the size of this source in bytes, if the size can be easily determined without
+   * actually opening the data stream.
+   *
+   * <p>The default implementation returns {@link Optional#absent}. Some sources, such as a file,
+   * may return a non-absent value. Note that in such cases, it is <i>possible</i> that this method
+   * will return a different number of bytes than would be returned by reading all of the bytes (for
+   * example, some special files may return a size of 0 despite actually having content when read).
+   *
+   * <p>Additionally, for mutable sources such as files, a subsequent read may return a different
+   * number of bytes if the contents are changed.
+   *
+   * @since 19.0
+   */
+  @Beta
+  public Optional<Long> sizeIfKnown() {
+    return Optional.absent();
+  }
+
+  /**
+   * Returns the size of this source in bytes, even if doing so requires opening and traversing
+   * an entire stream. To avoid a potentially expensive operation, see {@link #sizeIfKnown}.
    *
-   * <p>For some sources, such as a file, this method may use a more efficient implementation. Note
-   * that in such cases, it is <i>possible</i> that this method will return a different number of
-   * bytes than would be returned by reading all of the bytes (for example, some special files may
-   * return a size of 0 despite actually having content when read).
+   * <p>The default implementation calls {@link #sizeIfKnown} and returns the value if present.
+   * If absent, it will fall back to a heavyweight operation that will open a stream, read (or
+   * {@link InputStream#skip(long) skip}, if possible) to the end of the stream and return the total
+   * number of bytes that were read.
    *
-   * <p>In either case, if this is a mutable source such as a file, the size it returns may not be
-   * the same number of bytes a subsequent read would return.
+   * <p>Note that for some sources that implement {@link #sizeIfKnown} to provide a more efficient
+   * implementation, it is <i>possible</i> that this method will return a different number of bytes
+   * than would be returned by reading all of the bytes (for example, some special files may return
+   * a size of 0 despite actually having content when read).
+   *
+   * <p>In either case, for mutable sources such as files, a subsequent read may return a different
+   * number of bytes if the contents are changed.
    *
    * @throws IOException if an I/O error occurs in the process of reading the size of this source
    */
   public long size() throws IOException {
+    Optional<Long> sizeIfKnown = sizeIfKnown();
+    if (sizeIfKnown.isPresent()) {
+      return sizeIfKnown.get();
+    }
+
     Closer closer = Closer.create();
     try {
       InputStream in = closer.register(openStream());
@@ -174,31 +216,17 @@ public abstract class ByteSource {
    */
   private long countBySkipping(InputStream in) throws IOException {
     long count = 0;
-    while (true) {
-      // don't try to skip more than available()
-      // things may work really wrong with FileInputStream otherwise
-      long skipped = in.skip(Math.min(in.available(), Integer.MAX_VALUE));
-      if (skipped <= 0) {
-        if (in.read() == -1) {
-          return count;
-        } else if (count == 0 && in.available() == 0) {
-          // if available is still zero after reading a single byte, it
-          // will probably always be zero, so we should countByReading
-          throw new IOException();
-        }
-        count++;
-      } else {
-        count += skipped;
-      }
+    long skipped;
+    while ((skipped = skipUpTo(in, Integer.MAX_VALUE)) > 0) {
+      count += skipped;
     }
+    return count;
   }
 
-  private static final byte[] countBuffer = new byte[BUF_SIZE];
-
   private long countByReading(InputStream in) throws IOException {
     long count = 0;
     long read;
-    while ((read = in.read(countBuffer)) != -1) {
+    while ((read = in.read(ByteStreams.skipBuffer)) != -1) {
       count += read;
     }
     return count;
@@ -431,10 +459,10 @@ public abstract class ByteSource {
    */
   private final class SlicedByteSource extends ByteSource {
 
-    private final long offset;
-    private final long length;
+    final long offset;
+    final long length;
 
-    private SlicedByteSource(long offset, long length) {
+    SlicedByteSource(long offset, long length) {
       checkArgument(offset >= 0, "offset (%s) may not be negative", offset);
       checkArgument(length >= 0, "length (%s) may not be negative", length);
       this.offset = offset;
@@ -453,8 +481,9 @@ public abstract class ByteSource {
 
     private InputStream sliceStream(InputStream in) throws IOException {
       if (offset > 0) {
+        long skipped;
         try {
-          ByteStreams.skipFully(in, offset);
+          skipped = ByteStreams.skipUpTo(in, offset);
         } catch (Throwable e) {
           Closer closer = Closer.create();
           closer.register(in);
@@ -464,6 +493,12 @@ public abstract class ByteSource {
             closer.close();
           }
         }
+
+        if (skipped < offset) {
+          // offset was beyond EOF
+          in.close();
+          return new ByteArrayInputStream(new byte[0]);
+        }
       }
       return ByteStreams.limit(in, length);
     }
@@ -482,6 +517,17 @@ public abstract class ByteSource {
     }
 
     @Override
+    public Optional<Long> sizeIfKnown() {
+      Optional<Long> optionalUnslicedSize = ByteSource.this.sizeIfKnown();
+      if (optionalUnslicedSize.isPresent()) {
+        long unslicedSize = optionalUnslicedSize.get();
+        long off = Math.min(offset, unslicedSize);
+        return Optional.of(Math.min(length, unslicedSize - off));
+      }
+      return Optional.absent();
+    }
+
+    @Override
     public String toString() {
       return ByteSource.this.toString() + ".slice(" + offset + ", " + length + ")";
     }
@@ -489,15 +535,24 @@ public abstract class ByteSource {
 
   private static class ByteArrayByteSource extends ByteSource {
 
-    protected final byte[] bytes;
+    final byte[] bytes;
+    final int offset;
+    final int length;
+
+    ByteArrayByteSource(byte[] bytes) {
+      this(bytes, 0, bytes.length);
+    }
 
-    protected ByteArrayByteSource(byte[] bytes) {
-      this.bytes = checkNotNull(bytes);
+    // NOTE: Preconditions are enforced by slice, the only non-trivial caller.
+    ByteArrayByteSource(byte[] bytes, int offset, int length) {
+      this.bytes = bytes;
+      this.offset = offset;
+      this.length = length;
     }
 
     @Override
     public InputStream openStream() {
-      return new ByteArrayInputStream(bytes);
+      return new ByteArrayInputStream(bytes, offset, length);
     }
 
     @Override
@@ -507,50 +562,64 @@ public abstract class ByteSource {
 
     @Override
     public boolean isEmpty() {
-      return bytes.length == 0;
+      return length == 0;
     }
 
     @Override
     public long size() {
-      return bytes.length;
+      return length;
+    }
+
+    @Override
+    public Optional<Long> sizeIfKnown() {
+      return Optional.of((long) length);
     }
 
     @Override
     public byte[] read() {
-      return bytes.clone();
+      return Arrays.copyOfRange(bytes, offset, offset + length);
     }
 
     @Override
     public long copyTo(OutputStream output) throws IOException {
-      output.write(bytes);
-      return bytes.length;
+      output.write(bytes, offset, length);
+      return length;
     }
 
     @Override
     public <T> T read(ByteProcessor<T> processor) throws IOException {
-      processor.processBytes(bytes, 0, bytes.length);
+      processor.processBytes(bytes, offset, length);
       return processor.getResult();
     }
 
     @Override
     public HashCode hash(HashFunction hashFunction) throws IOException {
-      return hashFunction.hashBytes(bytes);
+      return hashFunction.hashBytes(bytes, offset, length);
     }
 
-    // TODO(user): Possibly override slice()
+    @Override
+    public ByteSource slice(long offset, long length) {
+      checkArgument(offset >= 0, "offset (%s) may not be negative", offset);
+      checkArgument(length >= 0, "length (%s) may not be negative", length);
+
+      offset = Math.min(offset, this.length);
+      length = Math.min(length, this.length - offset);
+      int newOffset = this.offset + (int) offset;
+      return new ByteArrayByteSource(bytes, newOffset, (int) length);
+    }
 
     @Override
     public String toString() {
       return "ByteSource.wrap("
-          + Ascii.truncate(BaseEncoding.base16().encode(bytes), 30, "...") + ")";
+          + Ascii.truncate(BaseEncoding.base16().encode(bytes, offset, length), 30, "...") + ")";
     }
   }
 
   private static final class EmptyByteSource extends ByteArrayByteSource {
 
-    private static final EmptyByteSource INSTANCE = new EmptyByteSource();
+    static final EmptyByteSource INSTANCE = new EmptyByteSource();
 
-    private EmptyByteSource() {
+    EmptyByteSource() {
       super(new byte[0]);
     }
 
@@ -573,7 +642,7 @@ public abstract class ByteSource {
 
   private static final class ConcatenatedByteSource extends ByteSource {
 
-    private final Iterable<? extends ByteSource> sources;
+    final Iterable<? extends ByteSource> sources;
 
     ConcatenatedByteSource(Iterable<? extends ByteSource> sources) {
       this.sources = checkNotNull(sources);
@@ -595,6 +664,19 @@ public abstract class ByteSource {
     }
 
     @Override
+    public Optional<Long> sizeIfKnown() {
+      long result = 0L;
+      for (ByteSource source : sources) {
+        Optional<Long> sizeIfKnown = source.sizeIfKnown();
+        if (!sizeIfKnown.isPresent()) {
+          return Optional.absent();
+        }
+        result += sizeIfKnown.get();
+      }
+      return Optional.of(result);
+    }
+
+    @Override
     public long size() throws IOException {
       long result = 0L;
       for (ByteSource source : sources) {
diff --git a/guava/src/com/google/common/io/ByteStreams.java b/guava/src/com/google/common/io/ByteStreams.java
index db83a7f..4d2d36c 100644
--- a/guava/src/com/google/common/io/ByteStreams.java
+++ b/guava/src/com/google/common/io/ByteStreams.java
@@ -34,6 +34,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.util.Arrays;
@@ -47,7 +48,46 @@ import java.util.Arrays;
  */
 @Beta
 public final class ByteStreams {
-  private static final int BUF_SIZE = 0x1000; // 4K
+
+  /**
+   * Default size of buffers allocated for copies.
+   */
+  static final int BUF_SIZE = 8192;
+
+  /**
+   * A buffer for skipping bytes in an input stream. Only written to and never read, so actual
+   * contents don't matter.
+   */
+  static final byte[] skipBuffer = new byte[BUF_SIZE];
+
+  /**
+   * There are three methods to implement {@link FileChannel#transferTo(long, long,
+   *  WritableByteChannel)}:
+   *
+   * <ol>
+   * <li> Use sendfile(2) or equivalent. Requires that both the input channel and the output channel
+   *    have their own file descriptors. Generally this only happens when both channels are files or
+   *    sockets. This performs zero copies - the bytes never enter userspace.</li>
+   * <li> Use mmap(2) or equivalent. Requires that either the input channel or the output channel
+   *    have file descriptors. Bytes are copied from the file into a kernel buffer, then directly
+   *    into the other buffer (userspace). Note that if the file is very large, a naive
+   *    implementation will effectively put the whole file in memory. On many systems with paging
+   *    and virtual memory, this is not a problem - because it is mapped read-only, the kernel can
+   *    always page it to disk "for free". However, on systems where killing processes happens all
+   *    the time in normal conditions (i.e., android) the OS must make a tradeoff between paging
+   *    memory and killing other processes - so allocating a gigantic buffer and then sequentially
+   *    accessing it could result in other processes dying. This is solvable via madvise(2), but
+   *    that obviously doesn't exist in java.</li>
+   * <li> Ordinary copy. Kernel copies bytes into a kernel buffer, from a kernel buffer into a
+   *    userspace buffer (byte[] or ByteBuffer), then copies them from that buffer into the
+   *    destination channel.</li>
+   * </ol>
+   *
+   * This value is intended to be large enough to make the overhead of system calls negligible,
+   * without being so large that it causes problems for systems with atypical memory management if
+   * approaches 2 or 3 are used.
+   */
+  private static final int ZERO_COPY_CHUNK_SIZE = 512 * 1024;
 
   private ByteStreams() {}
 
@@ -90,6 +130,19 @@ public final class ByteStreams {
       WritableByteChannel to) throws IOException {
     checkNotNull(from);
     checkNotNull(to);
+    if (from instanceof FileChannel) {
+      FileChannel sourceChannel = (FileChannel) from;
+      long oldPosition = sourceChannel.position();
+      long position = oldPosition;
+      long copied;
+      do {
+        copied = sourceChannel.transferTo(position, ZERO_COPY_CHUNK_SIZE, to);
+        position += copied;
+        sourceChannel.position(position);
+      } while (copied > 0 || position < sourceChannel.size());
+      return position - oldPosition;
+    }
+
     ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
     long total = 0;
     while (from.read(buf) != -1) {
@@ -346,7 +399,11 @@ public final class ByteStreams {
    * @throws IllegalArgumentException if {@code size} is negative
    */
   public static ByteArrayDataOutput newDataOutput(int size) {
-    checkArgument(size >= 0, "Invalid size: %s", size);
+    // When called at high frequency, boxing size generates too much garbage,
+    // so avoid doing that if we can.
+    if (size < 0) {
+      throw new IllegalArgumentException(String.format("Invalid size: %s", size));
+    }
     return newDataOutput(new ByteArrayOutputStream(size));
   }
 
@@ -658,21 +715,53 @@ public final class ByteStreams {
    *     support skipping
    */
   public static void skipFully(InputStream in, long n) throws IOException {
-    long toSkip = n;
-    while (n > 0) {
-      long amt = in.skip(n);
-      if (amt == 0) {
-        // Force a blocking read to avoid infinite loop
-        if (in.read() == -1) {
-          long skipped = toSkip - n;
-          throw new EOFException("reached end of stream after skipping "
-              + skipped + " bytes; " + toSkip + " bytes expected");
+    long skipped = skipUpTo(in, n);
+    if (skipped < n) {
+      throw new EOFException("reached end of stream after skipping "
+          + skipped + " bytes; " + n + " bytes expected");
+    }
+  }
+
+  /**
+   * Discards up to {@code n} bytes of data from the input stream. This method
+   * will block until either the full amount has been skipped or until the end
+   * of the stream is reached, whichever happens first. Returns the total number
+   * of bytes skipped.
+   */
+  static long skipUpTo(InputStream in, final long n) throws IOException {
+    long totalSkipped = 0;
+
+    while (totalSkipped < n) {
+      long remaining = n - totalSkipped;
+
+      long skipped = skipSafely(in, remaining);
+
+      if (skipped == 0) {
+        // Do a buffered read since skipSafely could return 0 repeatedly, for example if
+        // in.available() always returns 0 (the default).
+        int skip = (int) Math.min(remaining, skipBuffer.length);
+        if ((skipped = in.read(skipBuffer, 0, skip)) == -1) {
+          // Reached EOF
+          break;
         }
-        n--;
-      } else {
-        n -= amt;
       }
+
+      totalSkipped += skipped;
     }
+
+    return totalSkipped;
+  }
+
+  /**
+   * Attempts to skip up to {@code n} bytes from the given input stream, but not more than
+   * {@code in.available()} bytes. This prevents {@code FileInputStream} from skipping more bytes
+   * than actually remain in the file, something that it
+   * {@linkplain FileInputStream#skip(long) specifies} it can do in its Javadoc despite the fact
+   * that it is violating the contract of {@code InputStream.skip()}.
+   */
+  private static long skipSafely(InputStream in, long n) throws IOException {
+    int available = in.available();
+    return available == 0 ? 0 : in.skip(Math.min(available, n));
   }
 
   /**
diff --git a/guava/src/com/google/common/io/CharSequenceReader.java b/guava/src/com/google/common/io/CharSequenceReader.java
index 34ef832..afe0c73 100644
--- a/guava/src/com/google/common/io/CharSequenceReader.java
+++ b/guava/src/com/google/common/io/CharSequenceReader.java
@@ -30,7 +30,7 @@ import java.nio.CharBuffer;
  *
  * @author Colin Decker
  */
-// TODO(user): make this public? as a type, or a method in CharStreams?
+// TODO(cgdecker): make this public? as a type, or a method in CharStreams?
 final class CharSequenceReader extends Reader {
 
   private CharSequence seq;
diff --git a/guava/src/com/google/common/io/CharSource.java b/guava/src/com/google/common/io/CharSource.java
index fd47bbf..32273b0 100644
--- a/guava/src/com/google/common/io/CharSource.java
+++ b/guava/src/com/google/common/io/CharSource.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Ascii;
+import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
 import com.google.common.collect.AbstractIterator;
 import com.google.common.collect.ImmutableList;
@@ -95,6 +96,71 @@ public abstract class CharSource {
   }
 
   /**
+   * Returns the size of this source in chars, if the size can be easily determined without
+   * actually opening the data stream.
+   *
+   * <p>The default implementation returns {@link Optional#absent}. Some sources, such as a
+   * {@code CharSequence}, may return a non-absent value. Note that in such cases, it is
+   * <i>possible</i> that this method will return a different number of chars than would be
+   * returned by reading all of the chars.
+   *
+   * <p>Additionally, for mutable sources such as {@code StringBuilder}s, a subsequent read
+   * may return a different number of chars if the contents are changed.
+   *
+   * @since 19.0
+   */
+  @Beta
+  public Optional<Long> lengthIfKnown() {
+    return Optional.absent();
+  }
+
+  /**
+   * Returns the length of this source in chars, even if doing so requires opening and traversing
+   * an entire stream. To avoid a potentially expensive operation, see {@link #lengthIfKnown}.
+   *
+   * <p>The default implementation calls {@link #lengthIfKnown} and returns the value if present.
+   * If absent, it will fall back to a heavyweight operation that will open a stream,
+   * {@link Reader#skip(long) skip} to the end of the stream, and return the total number of chars
+   * that were skipped.
+   *
+   * <p>Note that for sources that implement {@link #lengthIfKnown} to provide a more efficient
+   * implementation, it is <i>possible</i> that this method will return a different number of chars
+   * than would be returned by reading all of the chars.
+   *
+   * <p>In either case, for mutable sources such as files, a subsequent read may return a different
+   * number of chars if the contents are changed.
+   *
+   * @throws IOException if an I/O error occurs in the process of reading the length of this source
+   * @since 19.0
+   */
+  @Beta
+  public long length() throws IOException {
+    Optional<Long> lengthIfKnown = lengthIfKnown();
+    if (lengthIfKnown.isPresent()) {
+      return lengthIfKnown.get();
+    }
+
+    Closer closer = Closer.create();
+    try {
+      Reader reader = closer.register(openStream());
+      return countBySkipping(reader);
+    } catch (Throwable e) {
+      throw closer.rethrow(e);
+    } finally {
+      closer.close();
+    }
+  }
+
+  private long countBySkipping(Reader reader) throws IOException {
+    long count = 0;
+    long read;
+    while ((read = reader.skip(Long.MAX_VALUE)) != 0) {
+      count += read;
+    }
+    return count;
+  }
+
+  /**
    * Appends the contents of this source to the given {@link Appendable} (such as a {@link Writer}).
    * Does not close {@code appendable} if it is {@code Closeable}.
    *
@@ -162,7 +228,7 @@ public abstract class CharSource {
    *
    * @throws IOException if an I/O error occurs in the process of reading from this source
    */
-  public @Nullable String readFirstLine() throws IOException {
+  @Nullable public String readFirstLine() throws IOException {
     Closer closer = Closer.create();
     try {
       BufferedReader reader = closer.register(openBufferedStream());
@@ -231,13 +297,22 @@ public abstract class CharSource {
   }
 
   /**
-   * Returns whether the source has zero chars. The default implementation is to open a stream and
-   * check for EOF.
+   * Returns whether the source has zero chars. The default implementation returns true if
+   * {@link #lengthIfKnown} returns zero, falling back to opening a stream and checking
+   * for EOF if the length is not known.
+   *
+   * <p>Note that, in cases where {@code lengthIfKnown} returns zero, it is <i>possible</i> that
+   * chars are actually available for reading. This means that a source may return {@code true} from
+   * {@code isEmpty()} despite having readable content.
    *
    * @throws IOException if an I/O error occurs
    * @since 15.0
    */
   public boolean isEmpty() throws IOException {
+    Optional<Long> lengthIfKnown = lengthIfKnown();
+    if (lengthIfKnown.isPresent() && lengthIfKnown.get() == 0L) {
+      return true;
+    }
     Closer closer = Closer.create();
     try {
       Reader reader = closer.register(openStream());
@@ -348,6 +423,16 @@ public abstract class CharSource {
       return seq.length() == 0;
     }
 
+    @Override
+    public long length() {
+      return seq.length();
+    }
+
+    @Override
+    public Optional<Long> lengthIfKnown() {
+      return Optional.of((long) seq.length());
+    }
+
     /**
      * Returns an iterable over the lines in the string. If the string ends in
      * a newline, a final empty string is not included to match the behavior of
@@ -441,6 +526,28 @@ public abstract class CharSource {
     }
 
     @Override
+    public Optional<Long> lengthIfKnown() {
+      long result = 0L;
+      for (CharSource source : sources) {
+        Optional<Long> lengthIfKnown = source.lengthIfKnown();
+        if (!lengthIfKnown.isPresent()) {
+          return Optional.absent();
+        }
+        result += lengthIfKnown.get();
+      }
+      return Optional.of(result);
+    }
+
+    @Override
+    public long length() throws IOException {
+      long result = 0L;
+      for (CharSource source : sources) {
+        result += source.length();
+      }
+      return result;
+    }
+
+    @Override
     public String toString() {
       return "CharSource.concat(" + sources + ")";
     }
diff --git a/guava/src/com/google/common/io/CharStreams.java b/guava/src/com/google/common/io/CharStreams.java
index 8c8adce..696417d 100644
--- a/guava/src/com/google/common/io/CharStreams.java
+++ b/guava/src/com/google/common/io/CharStreams.java
@@ -164,14 +164,9 @@ public final class CharStreams {
     while (n > 0) {
       long amt = reader.skip(n);
       if (amt == 0) {
-        // force a blocking read
-        if (reader.read() == -1) {
-          throw new EOFException();
-        }
-        n--;
-      } else {
-        n -= amt;
+        throw new EOFException();
       }
+      n -= amt;
     }
   }
 
@@ -260,7 +255,7 @@ public final class CharStreams {
     return new AppendableWriter(target);
   }
 
-  // TODO(user): Remove these once Input/OutputSupplier methods are removed
+  // TODO(cgdecker): Remove these once Input/OutputSupplier methods are removed
 
   static Reader asReader(final Readable readable) {
     checkNotNull(readable);
diff --git a/guava/src/com/google/common/io/CountingInputStream.java b/guava/src/com/google/common/io/CountingInputStream.java
index 573099a..eeb4d00 100644
--- a/guava/src/com/google/common/io/CountingInputStream.java
+++ b/guava/src/com/google/common/io/CountingInputStream.java
@@ -16,14 +16,14 @@
 
 package com.google.common.io;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.common.annotations.Beta;
 
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import javax.annotation.Nullable;
-
 /**
  * An {@link InputStream} that counts the number of bytes read.
  *
@@ -41,8 +41,8 @@ public final class CountingInputStream extends FilterInputStream {
    *
    * @param in the input stream to be wrapped
    */
-  public CountingInputStream(@Nullable InputStream in) {
-    super(in);
+  public CountingInputStream(InputStream in) {
+    super(checkNotNull(in));
   }
 
   /** Returns the number of bytes read. */
diff --git a/guava/src/com/google/common/io/CountingOutputStream.java b/guava/src/com/google/common/io/CountingOutputStream.java
index 8b6a4fe..e6ba21e 100644
--- a/guava/src/com/google/common/io/CountingOutputStream.java
+++ b/guava/src/com/google/common/io/CountingOutputStream.java
@@ -16,14 +16,14 @@
 
 package com.google.common.io;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.common.annotations.Beta;
 
 import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
-import javax.annotation.Nullable;
-
 /**
  * An OutputStream that counts the number of bytes written.
  *
@@ -40,8 +40,8 @@ public final class CountingOutputStream extends FilterOutputStream {
    *
    * @param out the output stream to be wrapped
    */
-  public CountingOutputStream(@Nullable OutputStream out) {
-    super(out);
+  public CountingOutputStream(OutputStream out) {
+    super(checkNotNull(out));
   }
 
   /** Returns the number of bytes written. */
diff --git a/guava/src/com/google/common/io/Files.java b/guava/src/com/google/common/io/Files.java
index 2eef50e..c83a1b2 100644
--- a/guava/src/com/google/common/io/Files.java
+++ b/guava/src/com/google/common/io/Files.java
@@ -23,6 +23,7 @@ import static com.google.common.io.FileWriteMode.APPEND;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Charsets;
 import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableSet;
@@ -126,6 +127,15 @@ public final class Files {
     }
 
     @Override
+    public Optional<Long> sizeIfKnown() {
+      if (file.isFile()) {
+        return Optional.of(file.length());
+      } else {
+        return Optional.absent();
+      }
+    }
+
+    @Override
     public long size() throws IOException {
       if (!file.isFile()) {
         throw new FileNotFoundException(file.toString());
diff --git a/guava/src/com/google/common/io/GwtWorkarounds.java b/guava/src/com/google/common/io/GwtWorkarounds.java
deleted file mode 100644
index 285df59..0000000
--- a/guava/src/com/google/common/io/GwtWorkarounds.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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.io;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkPositionIndexes;
-
-import com.google.common.annotations.GwtCompatible;
-import com.google.common.annotations.GwtIncompatible;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-
-/**
- * Provides simple GWT-compatible substitutes for {@code InputStream}, {@code OutputStream},
- * {@code Reader}, and {@code Writer} so that {@code BaseEncoding} can use streaming implementations
- * while remaining GWT-compatible.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
-final class GwtWorkarounds {
-  private GwtWorkarounds() {}
-
-  /**
-   * A GWT-compatible substitute for a {@code Reader}.
-   */
-  interface CharInput {
-    int read() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Views a {@code Reader} as a {@code CharInput}.
-   */
-  @GwtIncompatible("Reader")
-  static CharInput asCharInput(final Reader reader) {
-    checkNotNull(reader);
-    return new CharInput() {
-      @Override
-      public int read() throws IOException {
-        return reader.read();
-      }
-
-      @Override
-      public void close() throws IOException {
-        reader.close();
-      }
-    };
-  }
-
-  /**
-   * Views a {@code CharSequence} as a {@code CharInput}.
-   */
-  static CharInput asCharInput(final CharSequence chars) {
-    checkNotNull(chars);
-    return new CharInput() {
-      int index = 0;
-
-      @Override
-      public int read() {
-        if (index < chars.length()) {
-          return chars.charAt(index++);
-        } else {
-          return -1;
-        }
-      }
-
-      @Override
-      public void close() {
-        index = chars.length();
-      }
-    };
-  }
-
-  /**
-   * A GWT-compatible substitute for an {@code InputStream}.
-   */
-  interface ByteInput {
-    int read() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Views a {@code ByteInput} as an {@code InputStream}.
-   */
-  @GwtIncompatible("InputStream")
-  static InputStream asInputStream(final ByteInput input) {
-    checkNotNull(input);
-    return new InputStream() {
-      @Override
-      public int read() throws IOException {
-        return input.read();
-      }
-
-      @Override
-      public int read(byte[] b, int off, int len) throws IOException {
-        checkNotNull(b);
-        checkPositionIndexes(off, off + len, b.length);
-        if (len == 0) {
-          return 0;
-        }
-        int firstByte = read();
-        if (firstByte == -1) {
-          return -1;
-        }
-        b[off] = (byte) firstByte;
-        for (int dst = 1; dst < len; dst++) {
-          int readByte = read();
-          if (readByte == -1) {
-            return dst;
-          }
-          b[off + dst] = (byte) readByte;
-        }
-        return len;
-      }
-
-      @Override
-      public void close() throws IOException {
-        input.close();
-      }
-    };
-  }
-
-  /**
-   * A GWT-compatible substitute for an {@code OutputStream}.
-   */
-  interface ByteOutput {
-    void write(byte b) throws IOException;
-    void flush() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Views a {@code ByteOutput} as an {@code OutputStream}.
-   */
-  @GwtIncompatible("OutputStream")
-  static OutputStream asOutputStream(final ByteOutput output) {
-    checkNotNull(output);
-    return new OutputStream() {
-      @Override
-      public void write(int b) throws IOException {
-        output.write((byte) b);
-      }
-
-      @Override
-      public void flush() throws IOException {
-        output.flush();
-      }
-
-      @Override
-      public void close() throws IOException {
-        output.close();
-      }
-    };
-  }
-
-  /**
-   * A GWT-compatible substitute for a {@code Writer}.
-   */
-  interface CharOutput {
-    void write(char c) throws IOException;
-    void flush() throws IOException;
-    void close() throws IOException;
-  }
-
-  /**
-   * Views a {@code Writer} as a {@code CharOutput}.
-   */
-  @GwtIncompatible("Writer")
-  static CharOutput asCharOutput(final Writer writer) {
-    checkNotNull(writer);
-    return new CharOutput() {
-      @Override
-      public void write(char c) throws IOException {
-        writer.append(c);
-      }
-
-      @Override
-      public void flush() throws IOException {
-        writer.flush();
-      }
-
-      @Override
-      public void close() throws IOException {
-        writer.close();
-      }
-    };
-  }
-
-  /**
-   * Returns a {@code CharOutput} whose {@code toString()} method can be used
-   * to get the combined output.
-   */
-  static CharOutput stringBuilderOutput(int initialSize) {
-    final StringBuilder builder = new StringBuilder(initialSize);
-    return new CharOutput() {
-
-      @Override
-      public void write(char c) {
-        builder.append(c);
-      }
-
-      @Override
-      public void flush() {}
-
-      @Override
-      public void close() {}
-
-      @Override
-      public String toString() {
-        return builder.toString();
-      }
-    };
-  }
-}
diff --git a/guava/src/com/google/common/io/package-info.java b/guava/src/com/google/common/io/package-info.java
index b9df46e..252313a 100644
--- a/guava/src/com/google/common/io/package-info.java
+++ b/guava/src/com/google/common/io/package-info.java
@@ -28,7 +28,7 @@
  * <p>This package is a part of the open-source
  * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>. For more information on
  * Sources and Sinks as well as other features of this package, see
- * <a href="https://code.google.com/p/guava-libraries/wiki/IOExplained">I/O Explained</a> on the
+ * <a href="https://github.com/google/guava/wiki/IOExplained">I/O Explained</a> on the
  * Guava wiki.
  *
  * @author Chris Nokleberg
diff --git a/guava/src/com/google/common/math/DoubleMath.java b/guava/src/com/google/common/math/DoubleMath.java
index 66c5e8d..ee9b693 100644
--- a/guava/src/com/google/common/math/DoubleMath.java
+++ b/guava/src/com/google/common/math/DoubleMath.java
@@ -383,91 +383,120 @@ public final class DoubleMath {
     }
   }
 
-  @GwtIncompatible("com.google.common.math.DoubleUtils")
-  private static final class MeanAccumulator {
-
-    private long count = 0;
-    private double mean = 0.0;
-
-    void add(double value) {
-      checkArgument(isFinite(value));
-      ++count;
-      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
-      mean += (value - mean) / count;
-    }
-
-    double mean() {
-      checkArgument(count > 0, "Cannot take mean of 0 values");
-      return mean;
-    }
-  }
-
   /**
-   * Returns the arithmetic mean of the values. There must be at least one value, and they must all
-   * be finite.
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values
+   * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
    */
-  @GwtIncompatible("MeanAccumulator")
+  @GwtIncompatible("com.google.common.math.DoubleUtils")
   public static double mean(double... values) {
-    MeanAccumulator accumulator = new MeanAccumulator();
-    for (double value : values) {
-      accumulator.add(value);
+    checkArgument(values.length > 0, "Cannot take mean of 0 values");
+    long count = 1;
+    double mean = checkFinite(values[0]);
+    for (int index = 1; index < values.length; ++index) {
+      checkFinite(values[index]);
+      count++;
+      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+      mean += (values[index] - mean) / count;
     }
-    return accumulator.mean();
+    return mean;
   }
 
   /**
-   * Returns the arithmetic mean of the values. There must be at least one value. The values will
-   * be converted to doubles, which does not cause any loss of precision for ints.
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values
+   * @throws IllegalArgumentException if {@code values} is empty
    */
-  @GwtIncompatible("MeanAccumulator")
   public static double mean(int... values) {
-    MeanAccumulator accumulator = new MeanAccumulator();
-    for (int value : values) {
-      accumulator.add(value);
+    checkArgument(values.length > 0, "Cannot take mean of 0 values");
+    // The upper bound on the the length of an array and the bounds on the int values mean that, in
+    // this case only, we can compute the sum as a long without risking overflow or loss of
+    // precision. So we do that, as it's slightly quicker than the Knuth algorithm.
+    long sum = 0;
+    for (int index = 0; index < values.length; ++index) {
+      sum += values[index];
     }
-    return accumulator.mean();
+    return (double) sum / values.length;
   }
 
   /**
-   * Returns the arithmetic mean of the values. There must be at least one value. The values will
-   * be converted to doubles, which causes loss of precision for longs of magnitude over 2^53
-   * (slightly over 9e15).
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values, which will be converted to {@code double} values
+   *     (this may cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
+   * @throws IllegalArgumentException if {@code values} is empty
    */
-  @GwtIncompatible("MeanAccumulator")
   public static double mean(long... values) {
-    MeanAccumulator accumulator = new MeanAccumulator();
-    for (long value : values) {
-      accumulator.add(value);
+    checkArgument(values.length > 0, "Cannot take mean of 0 values");
+    long count = 1;
+    double mean = values[0];
+    for (int index = 1; index < values.length; ++index) {
+      count++;
+      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+      mean += (values[index] - mean) / count;
     }
-    return accumulator.mean();
+    return mean;
   }
 
   /**
-   * Returns the arithmetic mean of the values. There must be at least one value, and they must all
-   * be finite. The values will be converted to doubles, which may cause loss of precision for some
-   * numeric types.
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values, which will be converted to {@code double} values
+   *     (this may cause loss of precision)
+   * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
    */
-  @GwtIncompatible("MeanAccumulator")
+  @GwtIncompatible("com.google.common.math.DoubleUtils")
   public static double mean(Iterable<? extends Number> values) {
-    MeanAccumulator accumulator = new MeanAccumulator();
-    for (Number value : values) {
-      accumulator.add(value.doubleValue());
-    }
-    return accumulator.mean();
+    return mean(values.iterator());
   }
 
   /**
-   * Returns the arithmetic mean of the values. There must be at least one value, and they must all
-   * be finite. The values will be converted to doubles, which may cause loss of precision for some
-   * numeric types.
+   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+   * {@code values}.
+   *
+   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+   * the arithmetic mean of the population.
+   *
+   * @param values a nonempty series of values, which will be converted to {@code double} values
+   *     (this may cause loss of precision)
+   * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
    */
-  @GwtIncompatible("MeanAccumulator")
+  @GwtIncompatible("com.google.common.math.DoubleUtils")
   public static double mean(Iterator<? extends Number> values) {
-    MeanAccumulator accumulator = new MeanAccumulator();
+    checkArgument(values.hasNext(), "Cannot take mean of 0 values");
+    long count = 1;
+    double mean = checkFinite(values.next().doubleValue());
     while (values.hasNext()) {
-      accumulator.add(values.next().doubleValue());
+      double value = checkFinite(values.next().doubleValue());
+      count++;
+      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+      mean += (value - mean) / count;
     }
-    return accumulator.mean();
+    return mean;
+  }
+
+  @GwtIncompatible("com.google.common.math.DoubleUtils")
+  private static double checkFinite(double argument) {
+    checkArgument(isFinite(argument));
+    return argument;
   }
 
   private DoubleMath() {}
diff --git a/guava/src/com/google/common/math/LongMath.java b/guava/src/com/google/common/math/LongMath.java
index 425aac6..7380ce7 100644
--- a/guava/src/com/google/common/math/LongMath.java
+++ b/guava/src/com/google/common/math/LongMath.java
@@ -30,6 +30,7 @@ import static java.math.RoundingMode.HALF_UP;
 import com.google.common.annotations.GwtCompatible;
 import com.google.common.annotations.GwtIncompatible;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLongs;
 
 import java.math.BigInteger;
 import java.math.RoundingMode;
@@ -593,7 +594,7 @@ public final class LongMath {
           }
           k >>= 1;
           if (k > 0) {
-            checkNoOverflow(b <= FLOOR_SQRT_MAX_LONG);
+            checkNoOverflow(-FLOOR_SQRT_MAX_LONG <= b && b <= FLOOR_SQRT_MAX_LONG);
             b *= b;
           }
       }
@@ -757,5 +758,188 @@ public final class LongMath {
     return (x & y) + ((x ^ y) >> 1);
   }
 
+  /*
+   * If n <= millerRabinBases[i][0], then testing n against bases millerRabinBases[i][1..]
+   * suffices to prove its primality.  Values from miller-rabin.appspot.com.
+   *
+   * NOTE: We could get slightly better bases that would be treated as unsigned, but benchmarks
+   * showed negligible performance improvements.
+   */
+  private static final long[][] millerRabinBaseSets = {
+    {291830, 126401071349994536L},
+    {885594168, 725270293939359937L, 3569819667048198375L},
+    {273919523040L, 15, 7363882082L, 992620450144556L},
+    {47636622961200L, 2, 2570940, 211991001, 3749873356L},
+    {7999252175582850L,
+      2, 4130806001517L, 149795463772692060L, 186635894390467037L, 3967304179347715805L},
+    {585226005592931976L,
+      2, 123635709730000L, 9233062284813009L, 43835965440333360L, 761179012939631437L,
+      1263739024124850375L},
+    {Long.MAX_VALUE,
+        2, 325, 9375, 28178, 450775, 9780504, 1795265022}
+  };
+
+  private enum MillerRabinTester {
+    /**
+     * Works for inputs <= FLOOR_SQRT_MAX_LONG.
+     */
+    SMALL {
+      @Override
+      long mulMod(long a, long b, long m) {
+        /*
+         * NOTE(lowasser, 2015-Feb-12): Benchmarks suggest that changing this to
+         * UnsignedLongs.remainder and increasing the threshold to 2^32 doesn't pay for itself,
+         * and adding another enum constant hurts performance further -- I suspect because
+         * bimorphic implementation is a sweet spot for the JVM.
+         */
+        return (a * b) % m;
+      }
+
+      @Override
+      long squareMod(long a, long m) {
+        return (a * a) % m;
+      }
+    },
+    /**
+     * Works for all nonnegative signed longs.
+     */
+    LARGE {
+      /**
+       * Returns (a + b) mod m.  Precondition: 0 <= a, b < m < 2^63.
+       */
+      private long plusMod(long a, long b, long m) {
+        return (a >= m - b) ? (a + b - m) : (a + b);
+      }
+
+      /**
+       * Returns (a * 2^32) mod m.  a may be any unsigned long.
+       */
+      private long times2ToThe32Mod(long a, long m) {
+        int remainingPowersOf2 = 32;
+        do {
+          int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a));
+          // shift is either the number of powers of 2 left to multiply a by, or the biggest shift
+          // possible while keeping a in an unsigned long.
+          a = UnsignedLongs.remainder(a << shift, m);
+          remainingPowersOf2 -= shift;
+        } while (remainingPowersOf2 > 0);
+        return a;
+      }
+
+      @Override
+      long mulMod(long a, long b, long m) {
+        long aHi = a >>> 32; // < 2^31
+        long bHi = b >>> 32; // < 2^31
+        long aLo = a & 0xFFFFFFFFL; // < 2^32
+        long bLo = b & 0xFFFFFFFFL; // < 2^32
+
+        /*
+         * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^63 + aLo * bLo.
+         *       == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo
+         *
+         * We carry out this computation in modular arithmetic.  Since times2ToThe32Mod accepts
+         * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+         * results can exceed 2^63.
+         */
+        long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63
+        result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64
+        if (result < 0) {
+          result = UnsignedLongs.remainder(result, m);
+        }
+        // result < 2^63 again
+        result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64
+        result = times2ToThe32Mod(result, m); // result < m < 2^63
+        return plusMod(
+            result,
+            UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m),
+            m);
+      }
+
+      @Override
+      long squareMod(long a, long m) {
+        long aHi = a >>> 32; // < 2^31
+        long aLo = a & 0xFFFFFFFFL; // < 2^32
+
+        /*
+         * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2
+         *     == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2
+         * We carry out this computation in modular arithmetic.  Since times2ToThe32Mod accepts
+         * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+         * results can exceed 2^63.
+         */
+        long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63
+        long hiLo = aHi * aLo * 2;
+        if (hiLo < 0) {
+          hiLo = UnsignedLongs.remainder(hiLo, m);
+        }
+        // hiLo < 2^63
+        result += hiLo; // result < 2^64
+        result = times2ToThe32Mod(result, m); // result < m < 2^63
+        return plusMod(
+            result,
+            UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m),
+            m);
+      }
+    };
+
+    static boolean test(long base, long n) {
+      // Since base will be considered % n, it's okay if base > FLOOR_SQRT_MAX_LONG,
+      // so long as n <= FLOOR_SQRT_MAX_LONG.
+      return ((n <= FLOOR_SQRT_MAX_LONG) ? SMALL : LARGE).testWitness(base, n);
+    }
+
+    /**
+     * Returns a * b mod m.
+     */
+    abstract long mulMod(long a, long b, long m);
+
+    /**
+     * Returns a^2 mod m.
+     */
+    abstract long squareMod(long a, long m);
+
+    /**
+     * Returns a^p mod m.
+     */
+    private long powMod(long a, long p, long m) {
+      long res = 1;
+      for (; p != 0; p >>= 1) {
+        if ((p & 1) != 0) {
+          res = mulMod(res, a, m);
+        }
+        a = squareMod(a, m);
+      }
+      return res;
+    }
+
+    /**
+     * Returns true if n is a strong probable prime relative to the specified base.
+     */
+    private boolean testWitness(long base, long n) {
+      int r = Long.numberOfTrailingZeros(n - 1);
+      long d = (n - 1) >> r;
+      base %= n;
+      if (base == 0) {
+        return true;
+      }
+      // Calculate a := base^d mod n.
+      long a = powMod(base, d, n);
+      // n passes this test if
+      //    base^d = 1 (mod n)
+      // or base^(2^j * d) = -1 (mod n) for some 0 <= j < r.
+      if (a == 1) {
+        return true;
+      }
+      int j = 0;
+      while (a != n - 1) {
+        if (++j == r) {
+          return false;
+        }
+        a = squareMod(a, n);
+      }
+      return true;
+    }
+  }
+
   private LongMath() {}
 }
diff --git a/guava/src/com/google/common/math/package-info.java b/guava/src/com/google/common/math/package-info.java
index bd17e52..f6720d1 100644
--- a/guava/src/com/google/common/math/package-info.java
+++ b/guava/src/com/google/common/math/package-info.java
@@ -21,7 +21,7 @@
  * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/MathExplained">
+ * "https://github.com/google/guava/wiki/MathExplained">
  * math utilities</a>.
  */
 @ParametersAreNonnullByDefault
diff --git a/guava/src/com/google/common/net/HttpHeaders.java b/guava/src/com/google/common/net/HttpHeaders.java
index 5e3dbf6..d24e69e 100644
--- a/guava/src/com/google/common/net/HttpHeaders.java
+++ b/guava/src/com/google/common/net/HttpHeaders.java
@@ -248,4 +248,18 @@ public final class HttpHeaders {
   public static final String X_USER_IP = "X-User-IP";
   /** The HTTP {@code X-XSS-Protection} header field name. */
   public static final String X_XSS_PROTECTION = "X-XSS-Protection";
+  /**
+   * The HTTP <a href="http://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing">
+   * {@code Ping-From}</a> header field name.
+   *
+   * @since 19.0
+   */
+  public static final String PING_FROM = "Ping-From";
+  /**
+   * The HTTP <a href="http://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing">
+   * {@code Ping-To}</a> header field name.
+   *
+   * @since 19.0
+   */
+  public static final String PING_TO = "Ping-To";
 }
diff --git a/guava/src/com/google/common/net/InetAddresses.java b/guava/src/com/google/common/net/InetAddresses.java
index 20eb18e..ed8502c 100644
--- a/guava/src/com/google/common/net/InetAddresses.java
+++ b/guava/src/com/google/common/net/InetAddresses.java
@@ -29,6 +29,7 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.Locale;
 
 import javax.annotation.Nullable;
 
@@ -150,8 +151,7 @@ public final class InetAddresses {
 
     // The argument was malformed, i.e. not an IP string literal.
     if (addr == null) {
-      throw new IllegalArgumentException(
-          String.format("'%s' is not an IP string literal.", ipString));
+      throw formatIllegalArgumentException("'%s' is not an IP string literal.", ipString);
     }
 
     return bytesToInetAddress(addr);
@@ -319,7 +319,7 @@ public final class InetAddresses {
    * Convert a byte array into an InetAddress.
    *
    * {@link InetAddress#getByAddress} is documented as throwing a checked
-   * exception "if IP address if of illegal length."  We replace it with
+   * exception "if IP address is of illegal length."  We replace it with
    * an unchecked exception, for use by callers who already know that addr
    * is an array of length 4 or 16.
    *
@@ -498,8 +498,7 @@ public final class InetAddresses {
     // Parse the address, and make sure the length/version is correct.
     byte[] addr = ipStringToBytes(ipString);
     if (addr == null || addr.length != expectBytes) {
-      throw new IllegalArgumentException(
-          String.format("Not a valid URI IP literal: '%s'", hostAddr));
+      throw formatIllegalArgumentException("Not a valid URI IP literal: '%s'", hostAddr);
     }
 
     return bytesToInetAddress(addr);
@@ -804,8 +803,7 @@ public final class InetAddresses {
       return getTeredoInfo(ip).getClient();
     }
 
-    throw new IllegalArgumentException(
-        String.format("'%s' has no embedded IPv4 address.", toAddrString(ip)));
+    throw formatIllegalArgumentException("'%s' has no embedded IPv4 address.", toAddrString(ip));
   }
 
   /**
@@ -1031,4 +1029,9 @@ public final class InetAddresses {
     }
     return true;
   }
+
+  private static IllegalArgumentException formatIllegalArgumentException(
+      String format, Object... args) {
+    return new IllegalArgumentException(String.format(Locale.ROOT, format, args));
+  }
 }
diff --git a/guava/src/com/google/common/net/MediaType.java b/guava/src/com/google/common/net/MediaType.java
index 1cfd741..3eff0f1 100644
--- a/guava/src/com/google/common/net/MediaType.java
+++ b/guava/src/com/google/common/net/MediaType.java
@@ -230,6 +230,21 @@ public final class MediaType {
   public static final MediaType BZIP2 = createConstant(APPLICATION_TYPE, "x-bzip2");
 
   /**
+   * Media type for <a href="https://www.dartlang.org/articles/embedding-in-html/">dart files</a>.
+   *
+   * @since 19.0
+   */
+  public static final MediaType DART_UTF_8 = createConstantUtf8(APPLICATION_TYPE, "dart");
+
+  /**
+   * Media type for <a href="https://goo.gl/dNnKKj">Apple Passbook</a>.
+   *
+   * @since 19.0
+   */
+  public static final MediaType APPLE_PASSBOOK = createConstant(APPLICATION_TYPE,
+      "vnd.apple.pkpass");
+
+  /**
    * Media type for <a href="http://en.wikipedia.org/wiki/Embedded_OpenType">Embedded OpenType</a>
    * fonts. This is
    * <a href="http://www.iana.org/assignments/media-types/application/vnd.ms-fontobject">registered
@@ -279,6 +294,14 @@ public final class MediaType {
   public static final MediaType JAVASCRIPT_UTF_8 =
       createConstantUtf8(APPLICATION_TYPE, "javascript");
   public static final MediaType JSON_UTF_8 = createConstantUtf8(APPLICATION_TYPE, "json");
+  /**
+   * Media type for the
+   * <a href="http://www.w3.org/TR/appmanifest/">Manifest for a web application</a>.
+   *
+   * @since 19.0
+   */
+  public static final MediaType MANIFEST_JSON_UTF_8 =
+      createConstantUtf8(APPLICATION_TYPE, "manifest+json");
   public static final MediaType KML = createConstant(APPLICATION_TYPE, "vnd.google-earth.kml+xml");
   public static final MediaType KMZ = createConstant(APPLICATION_TYPE, "vnd.google-earth.kmz");
   public static final MediaType MBOX = createConstant(APPLICATION_TYPE, "mbox");
@@ -360,6 +383,10 @@ public final class MediaType {
   private final String subtype;
   private final ImmutableListMultimap<String, String> parameters;
 
+  private String toString;
+
+  private int hashCode;
+
   private MediaType(String type, String subtype,
       ImmutableListMultimap<String, String> parameters) {
     this.type = type;
@@ -692,7 +719,13 @@ public final class MediaType {
   }
 
   @Override public int hashCode() {
-    return Objects.hashCode(type, subtype, parametersAsMap());
+    // racy single-check idiom
+    int h = hashCode;
+    if (h == 0) {
+      h = Objects.hashCode(type, subtype, parametersAsMap());
+      hashCode = h;
+    }
+    return h;
   }
 
   private static final MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("=");
@@ -702,6 +735,16 @@ public final class MediaType {
    * href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
    */
   @Override public String toString() {
+    // racy single-check idiom, safe because String is immutable
+    String result = toString;
+    if (result == null) {
+      result = computeToString();
+      toString = result;
+    }
+    return result;
+  }
+
+  private String computeToString() {
     StringBuilder builder = new StringBuilder().append(type).append('/').append(subtype);
     if (!parameters.isEmpty()) {
       builder.append("; ");
@@ -718,7 +761,8 @@ public final class MediaType {
 
   private static String escapeAndQuote(String value) {
     StringBuilder escaped = new StringBuilder(value.length() + 16).append('"');
-    for (char ch : value.toCharArray()) {
+    for (int i = 0; i < value.length(); i++) {
+      char ch = value.charAt(i);
       if (ch == '\r' || ch == '\\' || ch == '"') {
         escaped.append('\\');
       }
diff --git a/guava/src/com/google/common/primitives/Booleans.java b/guava/src/com/google/common/primitives/Booleans.java
index faef910..d8ced70 100644
--- a/guava/src/com/google/common/primitives/Booleans.java
+++ b/guava/src/com/google/common/primitives/Booleans.java
@@ -27,24 +27,27 @@ import com.google.common.annotations.GwtCompatible;
 import java.io.Serializable;
 import java.util.AbstractList;
 import java.util.Arrays;
-import java.util.BitSet;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code boolean} primitives, that are not
  * already found in either {@link Boolean} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Booleans {
   private Booleans() {}
@@ -82,7 +85,7 @@ public final class Booleans {
    * {@code array}.
    *
    * <p><b>Note:</b> consider representing the array as a {@link
-   * BitSet} instead, replacing {@code Booleans.contains(array, true)}
+   * java.util.BitSet} instead, replacing {@code Booleans.contains(array, true)}
    * with {@code !bitSet.isEmpty()} and {@code Booleans.contains(array, false)}
    * with {@code bitSet.nextClearBit(0) == sizeOfBitSet}.
    *
@@ -104,9 +107,10 @@ public final class Booleans {
    * Returns the index of the first appearance of the value {@code target} in
    * {@code array}.
    *
-   * <p><b>Note:</b> consider representing the array as a {@link BitSet}
-   * instead, and using {@link BitSet#nextSetBit(int)} or {@link
-   * BitSet#nextClearBit(int)}.
+   * <p><b>Note:</b> consider representing the array as a {@link
+   * java.util.BitSet} instead, and using {@link
+   * java.util.BitSet#nextSetBit(int)} or {@link
+   * java.util.BitSet#nextClearBit(int)}.
    *
    * @param array an array of {@code boolean} values, possibly empty
    * @param target a primitive {@code boolean} value
@@ -118,8 +122,7 @@ public final class Booleans {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      boolean[] array, boolean target, int start, int end) {
+  private static int indexOf(boolean[] array, boolean target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -172,8 +175,7 @@ public final class Booleans {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      boolean[] array, boolean target, int start, int end) {
+  private static int lastIndexOf(boolean[] array, boolean target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -221,8 +223,7 @@ public final class Booleans {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static boolean[] ensureCapacity(
-      boolean[] array, int minLength, int padding) {
+  public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -306,7 +307,7 @@ public final class Booleans {
    * that method.
    *
    * <p><b>Note:</b> consider representing the collection as a {@link
-   * BitSet} instead.
+   * java.util.BitSet} instead.
    *
    * @param collection a collection of {@code Boolean} objects
    * @return an array containing the same values as {@code collection}, in the
@@ -367,26 +368,31 @@ public final class Booleans {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Boolean get(int index) {
+    @Override
+    public Boolean get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
       return (target instanceof Boolean)
           && Booleans.indexOf(array, (Boolean) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Boolean) {
         int i = Booleans.indexOf(array, (Boolean) target, start, end);
@@ -397,7 +403,8 @@ public final class Booleans {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Boolean) {
         int i = Booleans.lastIndexOf(array, (Boolean) target, start, end);
@@ -408,7 +415,8 @@ public final class Booleans {
       return -1;
     }
 
-    @Override public Boolean set(int index, Boolean element) {
+    @Override
+    public Boolean set(int index, Boolean element) {
       checkElementIndex(index, size());
       boolean oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -416,7 +424,8 @@ public final class Booleans {
       return oldValue;
     }
 
-    @Override public List<Boolean> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Boolean> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -425,7 +434,8 @@ public final class Booleans {
       return new BooleanArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -445,7 +455,8 @@ public final class Booleans {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Booleans.hashCode(array[i]);
@@ -453,7 +464,8 @@ public final class Booleans {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 7);
       builder.append(array[start] ? "[true" : "[false");
       for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Bytes.java b/guava/src/com/google/common/primitives/Bytes.java
index d9c5e1f..fec061f 100644
--- a/guava/src/com/google/common/primitives/Bytes.java
+++ b/guava/src/com/google/common/primitives/Bytes.java
@@ -31,6 +31,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code byte} primitives, that are not
  * already found in either {@link Byte} or {@link Arrays}, <i>and interpret
@@ -39,7 +42,7 @@ import java.util.RandomAccess;
  * UnsignedBytes}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
@@ -47,6 +50,7 @@ import java.util.RandomAccess;
  */
 // TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
 // javadoc?
+ at CheckReturnValue
 @GwtCompatible
 public final class Bytes {
   private Bytes() {}
@@ -94,8 +98,7 @@ public final class Bytes {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      byte[] array, byte target, int start, int end) {
+  private static int indexOf(byte[] array, byte target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -148,8 +151,7 @@ public final class Bytes {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      byte[] array, byte target, int start, int end) {
+  private static int lastIndexOf(byte[] array, byte target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -197,8 +199,7 @@ public final class Bytes {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static byte[] ensureCapacity(
-      byte[] array, int minLength, int padding) {
+  public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -281,26 +282,30 @@ public final class Bytes {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Byte get(int index) {
+    @Override
+    public Byte get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Byte)
-          && Bytes.indexOf(array, (Byte) target, start, end) != -1;
+      return (target instanceof Byte) && Bytes.indexOf(array, (Byte) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Byte) {
         int i = Bytes.indexOf(array, (Byte) target, start, end);
@@ -311,7 +316,8 @@ public final class Bytes {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Byte) {
         int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
@@ -322,7 +328,8 @@ public final class Bytes {
       return -1;
     }
 
-    @Override public Byte set(int index, Byte element) {
+    @Override
+    public Byte set(int index, Byte element) {
       checkElementIndex(index, size());
       byte oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -330,7 +337,8 @@ public final class Bytes {
       return oldValue;
     }
 
-    @Override public List<Byte> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Byte> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -339,7 +347,8 @@ public final class Bytes {
       return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -359,7 +368,8 @@ public final class Bytes {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Bytes.hashCode(array[i]);
@@ -367,7 +377,8 @@ public final class Bytes {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 5);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Chars.java b/guava/src/com/google/common/primitives/Chars.java
index 65fe8b1..fa5f4e4 100644
--- a/guava/src/com/google/common/primitives/Chars.java
+++ b/guava/src/com/google/common/primitives/Chars.java
@@ -33,6 +33,9 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code char} primitives, that are not
  * already found in either {@link Character} or {@link Arrays}.
@@ -41,12 +44,13 @@ import java.util.RandomAccess;
  * numerically; they are neither Unicode-aware nor locale-dependent.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Chars {
   private Chars() {}
@@ -151,8 +155,7 @@ public final class Chars {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      char[] array, char target, int start, int end) {
+  private static int indexOf(char[] array, char target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -205,8 +208,7 @@ public final class Chars {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      char[] array, char target, int start, int end) {
+  private static int lastIndexOf(char[] array, char target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -289,9 +291,7 @@ public final class Chars {
    */
   @GwtIncompatible("doesn't work")
   public static byte[] toByteArray(char value) {
-    return new byte[] {
-        (byte) (value >> 8),
-        (byte) value};
+    return new byte[] {(byte) (value >> 8), (byte) value};
   }
 
   /**
@@ -308,8 +308,7 @@ public final class Chars {
    */
   @GwtIncompatible("doesn't work")
   public static char fromByteArray(byte[] bytes) {
-    checkArgument(bytes.length >= BYTES,
-        "array too small: %s < %s", bytes.length, BYTES);
+    checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
     return fromBytes(bytes[0], bytes[1]);
   }
 
@@ -341,8 +340,7 @@ public final class Chars {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static char[] ensureCapacity(
-      char[] array, int minLength, int padding) {
+  public static char[] ensureCapacity(char[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -373,8 +371,7 @@ public final class Chars {
       return "";
     }
 
-    StringBuilder builder
-        = new StringBuilder(len + separator.length() * (len - 1));
+    StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
     builder.append(array[0]);
     for (int i = 1; i < len; i++) {
       builder.append(separator).append(array[i]);
@@ -485,26 +482,31 @@ public final class Chars {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Character get(int index) {
+    @Override
+    public Character get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
       return (target instanceof Character)
           && Chars.indexOf(array, (Character) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Character) {
         int i = Chars.indexOf(array, (Character) target, start, end);
@@ -515,7 +517,8 @@ public final class Chars {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Character) {
         int i = Chars.lastIndexOf(array, (Character) target, start, end);
@@ -526,7 +529,8 @@ public final class Chars {
       return -1;
     }
 
-    @Override public Character set(int index, Character element) {
+    @Override
+    public Character set(int index, Character element) {
       checkElementIndex(index, size());
       char oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -534,7 +538,8 @@ public final class Chars {
       return oldValue;
     }
 
-    @Override public List<Character> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Character> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -543,7 +548,8 @@ public final class Chars {
       return new CharArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -563,7 +569,8 @@ public final class Chars {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Chars.hashCode(array[i]);
@@ -571,7 +578,8 @@ public final class Chars {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 3);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Doubles.java b/guava/src/com/google/common/primitives/Doubles.java
index 8e86e8f..a482cdc 100644
--- a/guava/src/com/google/common/primitives/Doubles.java
+++ b/guava/src/com/google/common/primitives/Doubles.java
@@ -38,6 +38,8 @@ import java.util.List;
 import java.util.RandomAccess;
 import java.util.regex.Pattern;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -45,12 +47,13 @@ import javax.annotation.Nullable;
  * already found in either {@link Double} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Doubles {
   private Doubles() {}
@@ -141,8 +144,7 @@ public final class Doubles {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      double[] array, double target, int start, int end) {
+  private static int indexOf(double[] array, double target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -199,8 +201,7 @@ public final class Doubles {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      double[] array, double target, int start, int end) {
+  private static int lastIndexOf(double[] array, double target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -268,8 +269,8 @@ public final class Doubles {
     return result;
   }
 
-  private static final class DoubleConverter
-      extends Converter<String, Double> implements Serializable {
+  private static final class DoubleConverter extends Converter<String, Double>
+      implements Serializable {
     static final DoubleConverter INSTANCE = new DoubleConverter();
 
     @Override
@@ -290,6 +291,7 @@ public final class Doubles {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -320,8 +322,7 @@ public final class Doubles {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static double[] ensureCapacity(
-      double[] array, int minLength, int padding) {
+  public static double[] ensureCapacity(double[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -472,26 +473,31 @@ public final class Doubles {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Double get(int index) {
+    @Override
+    public Double get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
       return (target instanceof Double)
           && Doubles.indexOf(array, (Double) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Double) {
         int i = Doubles.indexOf(array, (Double) target, start, end);
@@ -502,7 +508,8 @@ public final class Doubles {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Double) {
         int i = Doubles.lastIndexOf(array, (Double) target, start, end);
@@ -513,7 +520,8 @@ public final class Doubles {
       return -1;
     }
 
-    @Override public Double set(int index, Double element) {
+    @Override
+    public Double set(int index, Double element) {
       checkElementIndex(index, size());
       double oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -521,7 +529,8 @@ public final class Doubles {
       return oldValue;
     }
 
-    @Override public List<Double> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Double> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -530,7 +539,8 @@ public final class Doubles {
       return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -550,7 +560,8 @@ public final class Doubles {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Doubles.hashCode(array[i]);
@@ -558,7 +569,8 @@ public final class Doubles {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 12);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
@@ -616,12 +628,13 @@ public final class Doubles {
    *     parsed as a {@code double} value
    * @since 14.0
    */
-  @GwtIncompatible("regular expressions")
-  @Nullable
   @Beta
+  @Nullable
+  @CheckForNull
+  @GwtIncompatible("regular expressions")
   public static Double tryParse(String string) {
     if (FLOATING_POINT_PATTERN.matcher(string).matches()) {
-      // TODO(user): could be potentially optimized, but only with
+      // TODO(lowasser): could be potentially optimized, but only with
       // extensive testing
       try {
         return Double.parseDouble(string);
diff --git a/guava/src/com/google/common/primitives/Floats.java b/guava/src/com/google/common/primitives/Floats.java
index 167089e..4776386 100644
--- a/guava/src/com/google/common/primitives/Floats.java
+++ b/guava/src/com/google/common/primitives/Floats.java
@@ -37,6 +37,8 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -44,12 +46,13 @@ import javax.annotation.Nullable;
  * already found in either {@link Float} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Floats {
   private Floats() {}
@@ -137,8 +140,7 @@ public final class Floats {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      float[] array, float target, int start, int end) {
+  private static int indexOf(float[] array, float target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -195,8 +197,7 @@ public final class Floats {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      float[] array, float target, int start, int end) {
+  private static int lastIndexOf(float[] array, float target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -225,7 +226,7 @@ public final class Floats {
 
   /**
    * Returns the greatest value present in {@code array}, using the same rules
-   * of comparison as {@link Math#min(float, float)}.
+   * of comparison as {@link Math#max(float, float)}.
    *
    * @param array a <i>nonempty</i> array of {@code float} values
    * @return the value present in {@code array} that is greater than or equal to
@@ -264,8 +265,8 @@ public final class Floats {
     return result;
   }
 
-  private static final class FloatConverter
-      extends Converter<String, Float> implements Serializable {
+  private static final class FloatConverter extends Converter<String, Float>
+      implements Serializable {
     static final FloatConverter INSTANCE = new FloatConverter();
 
     @Override
@@ -286,6 +287,7 @@ public final class Floats {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -316,8 +318,7 @@ public final class Floats {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static float[] ensureCapacity(
-      float[] array, int minLength, int padding) {
+  public static float[] ensureCapacity(float[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -468,26 +469,30 @@ public final class Floats {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Float get(int index) {
+    @Override
+    public Float get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Float)
-          && Floats.indexOf(array, (Float) target, start, end) != -1;
+      return (target instanceof Float) && Floats.indexOf(array, (Float) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Float) {
         int i = Floats.indexOf(array, (Float) target, start, end);
@@ -498,7 +503,8 @@ public final class Floats {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Float) {
         int i = Floats.lastIndexOf(array, (Float) target, start, end);
@@ -509,7 +515,8 @@ public final class Floats {
       return -1;
     }
 
-    @Override public Float set(int index, Float element) {
+    @Override
+    public Float set(int index, Float element) {
       checkElementIndex(index, size());
       float oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -517,7 +524,8 @@ public final class Floats {
       return oldValue;
     }
 
-    @Override public List<Float> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Float> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -526,7 +534,8 @@ public final class Floats {
       return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -546,7 +555,8 @@ public final class Floats {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Floats.hashCode(array[i]);
@@ -554,7 +564,8 @@ public final class Floats {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 12);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
@@ -593,12 +604,13 @@ public final class Floats {
    *     parsed as a {@code float} value
    * @since 14.0
    */
-  @GwtIncompatible("regular expressions")
-  @Nullable
   @Beta
+  @Nullable
+  @CheckForNull
+  @GwtIncompatible("regular expressions")
   public static Float tryParse(String string) {
     if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) {
-      // TODO(user): could be potentially optimized, but only with
+      // TODO(lowasser): could be potentially optimized, but only with
       // extensive testing
       try {
         return Float.parseFloat(string);
diff --git a/guava/src/com/google/common/primitives/Ints.java b/guava/src/com/google/common/primitives/Ints.java
index c0d0126..6249f99 100644
--- a/guava/src/com/google/common/primitives/Ints.java
+++ b/guava/src/com/google/common/primitives/Ints.java
@@ -36,18 +36,21 @@ import java.util.List;
 import java.util.RandomAccess;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
 
 /**
  * Static utility methods pertaining to {@code int} primitives, that are not
  * already found in either {@link Integer} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Ints {
   private Ints() {}
@@ -159,8 +162,7 @@ public final class Ints {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      int[] array, int target, int start, int end) {
+  private static int indexOf(int[] array, int target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -213,8 +215,7 @@ public final class Ints {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      int[] array, int target, int start, int end) {
+  private static int lastIndexOf(int[] array, int target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -298,10 +299,11 @@ public final class Ints {
   @GwtIncompatible("doesn't work")
   public static byte[] toByteArray(int value) {
     return new byte[] {
-        (byte) (value >> 24),
-        (byte) (value >> 16),
-        (byte) (value >> 8),
-        (byte) value};
+      (byte) (value >> 24),
+      (byte) (value >> 16),
+      (byte) (value >> 8),
+      (byte) value
+    };
   }
 
   /**
@@ -318,8 +320,7 @@ public final class Ints {
    */
   @GwtIncompatible("doesn't work")
   public static int fromByteArray(byte[] bytes) {
-    checkArgument(bytes.length >= BYTES,
-        "array too small: %s < %s", bytes.length, BYTES);
+    checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
     return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]);
   }
 
@@ -335,8 +336,8 @@ public final class Ints {
     return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
   }
 
-  private static final class IntConverter
-      extends Converter<String, Integer> implements Serializable {
+  private static final class IntConverter extends Converter<String, Integer>
+      implements Serializable {
     static final IntConverter INSTANCE = new IntConverter();
 
     @Override
@@ -357,6 +358,7 @@ public final class Ints {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -387,8 +389,7 @@ public final class Ints {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static int[] ensureCapacity(
-      int[] array, int minLength, int padding) {
+  public static int[] ensureCapacity(int[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -530,26 +531,30 @@ public final class Ints {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Integer get(int index) {
+    @Override
+    public Integer get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Integer)
-          && Ints.indexOf(array, (Integer) target, start, end) != -1;
+      return (target instanceof Integer) && Ints.indexOf(array, (Integer) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Integer) {
         int i = Ints.indexOf(array, (Integer) target, start, end);
@@ -560,7 +565,8 @@ public final class Ints {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Integer) {
         int i = Ints.lastIndexOf(array, (Integer) target, start, end);
@@ -571,7 +577,8 @@ public final class Ints {
       return -1;
     }
 
-    @Override public Integer set(int index, Integer element) {
+    @Override
+    public Integer set(int index, Integer element) {
       checkElementIndex(index, size());
       int oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -579,7 +586,8 @@ public final class Ints {
       return oldValue;
     }
 
-    @Override public List<Integer> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Integer> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -588,7 +596,8 @@ public final class Ints {
       return new IntArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -608,7 +617,8 @@ public final class Ints {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Ints.hashCode(array[i]);
@@ -616,7 +626,8 @@ public final class Ints {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 5);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
@@ -636,23 +647,6 @@ public final class Ints {
     private static final long serialVersionUID = 0;
   }
 
-  private static final byte[] asciiDigits = new byte[128];
-
-  static {
-    Arrays.fill(asciiDigits, (byte) -1);
-    for (int i = 0; i <= 9; i++) {
-      asciiDigits['0' + i] = (byte) i;
-    }
-    for (int i = 0; i <= 26; i++) {
-      asciiDigits['A' + i] = (byte) (10 + i);
-      asciiDigits['a' + i] = (byte) (10 + i);
-    }
-  }
-
-  private static int digit(char c) {
-    return (c < 128) ? asciiDigits[c] : -1;
-  }
-
   /**
    * Parses the specified string as a signed decimal integer value. The ASCII
    * character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -674,6 +668,7 @@ public final class Ints {
    * @since 11.0
    */
   @Beta
+  @Nullable
   @CheckForNull
   public static Integer tryParse(String string) {
     return tryParse(string, 10);
@@ -700,47 +695,18 @@ public final class Ints {
    *     or cannot be parsed as an integer value
    * @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
    *     {@code radix > Character.MAX_RADIX}
+   * @since 19.0
    */
-  @CheckForNull static Integer tryParse(
+  @Beta
+  @Nullable
+  @CheckForNull
+  public static Integer tryParse(
       String string, int radix) {
-    if (checkNotNull(string).isEmpty()) {
-      return null;
-    }
-    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
-      throw new IllegalArgumentException(
-          "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
-    }
-    boolean negative = string.charAt(0) == '-';
-    int index = negative ? 1 : 0;
-    if (index == string.length()) {
-      return null;
-    }
-    int digit = digit(string.charAt(index++));
-    if (digit < 0 || digit >= radix) {
-      return null;
-    }
-    int accum = -digit;
-
-    int cap = Integer.MIN_VALUE / radix;
-
-    while (index < string.length()) {
-      digit = digit(string.charAt(index++));
-      if (digit < 0 || digit >= radix || accum < cap) {
-        return null;
-      }
-      accum *= radix;
-      if (accum < Integer.MIN_VALUE + digit) {
-        return null;
-      }
-      accum -= digit;
-    }
-
-    if (negative) {
-      return accum;
-    } else if (accum == Integer.MIN_VALUE) {
+    Long result = Longs.tryParse(string, radix);
+    if (result == null || result.longValue() != result.intValue()) {
       return null;
     } else {
-      return -accum;
+      return result.intValue();
     }
   }
 }
diff --git a/guava/src/com/google/common/primitives/Longs.java b/guava/src/com/google/common/primitives/Longs.java
index 1078850..2e36fcb 100644
--- a/guava/src/com/google/common/primitives/Longs.java
+++ b/guava/src/com/google/common/primitives/Longs.java
@@ -34,17 +34,22 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
 /**
  * Static utility methods pertaining to {@code long} primitives, that are not
  * already found in either {@link Long} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible
 public final class Longs {
   private Longs() {}
@@ -126,8 +131,7 @@ public final class Longs {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      long[] array, long target, int start, int end) {
+  private static int indexOf(long[] array, long target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -180,8 +184,7 @@ public final class Longs {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      long[] array, long target, int start, int end) {
+  private static int lastIndexOf(long[] array, long target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -287,10 +290,9 @@ public final class Longs {
    *     elements
    */
   public static long fromByteArray(byte[] bytes) {
-    checkArgument(bytes.length >= BYTES,
-        "array too small: %s < %s", bytes.length, BYTES);
-    return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3],
-        bytes[4], bytes[5], bytes[6], bytes[7]) ;
+    checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
+    return fromBytes(
+        bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]);
   }
 
   /**
@@ -300,8 +302,8 @@ public final class Longs {
    *
    * @since 7.0
    */
-  public static long fromBytes(byte b1, byte b2, byte b3, byte b4,
-      byte b5, byte b6, byte b7, byte b8) {
+  public static long fromBytes(
+      byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8) {
     return (b1 & 0xFFL) << 56
         | (b2 & 0xFFL) << 48
         | (b3 & 0xFFL) << 40
@@ -312,6 +314,25 @@ public final class Longs {
         | (b8 & 0xFFL);
   }
 
+  private static final byte[] asciiDigits = createAsciiDigits();
+
+  private static byte[] createAsciiDigits() {
+    byte[] result = new byte[128];
+    Arrays.fill(result, (byte) -1);
+    for (int i = 0; i <= 9; i++) {
+      result['0' + i] = (byte) i;
+    }
+    for (int i = 0; i <= 26; i++) {
+      result['A' + i] = (byte) (10 + i);
+      result['a' + i] = (byte) (10 + i);
+    }
+    return result;
+  }
+
+  private static int digit(char c) {
+    return (c < 128) ? asciiDigits[c] : -1;
+  }
+
   /**
    * Parses the specified string as a signed decimal long value. The ASCII
    * character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -333,26 +354,65 @@ public final class Longs {
    * @since 14.0
    */
   @Beta
+  @Nullable
+  @CheckForNull
   public static Long tryParse(String string) {
+    return tryParse(string, 10);
+  }
+
+  /**
+   * Parses the specified string as a signed long value using the specified
+   * radix. The ASCII character {@code '-'} (<code>'\u002D'</code>) is
+   * recognized as the minus sign.
+   *
+   * <p>Unlike {@link Long#parseLong(String, int)}, this method returns
+   * {@code null} instead of throwing an exception if parsing fails.
+   * Additionally, this method only accepts ASCII digits, and returns
+   * {@code null} if non-ASCII digits are present in the string.
+   *
+   * <p>Note that strings prefixed with ASCII {@code '+'} are rejected, even
+   * under JDK 7, despite the change to {@link Long#parseLong(String, int)}
+   * for that version.
+   *
+   * @param string the string representation of an long value
+   * @param radix the radix to use when parsing
+   * @return the long value represented by {@code string} using
+   *     {@code radix}, or {@code null} if {@code string} has a length of zero
+   *     or cannot be parsed as a long value
+   * @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
+   *     {@code radix > Character.MAX_RADIX}
+   * @since 19.0
+   */
+  @Beta
+  @Nullable
+  @CheckForNull
+  public static Long tryParse(String string, int radix) {
     if (checkNotNull(string).isEmpty()) {
       return null;
     }
+    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+      throw new IllegalArgumentException(
+          "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
+    }
     boolean negative = string.charAt(0) == '-';
     int index = negative ? 1 : 0;
     if (index == string.length()) {
       return null;
     }
-    int digit = string.charAt(index++) - '0';
-    if (digit < 0 || digit > 9) {
+    int digit = digit(string.charAt(index++));
+    if (digit < 0 || digit >= radix) {
       return null;
     }
     long accum = -digit;
+
+    long cap = Long.MIN_VALUE / radix;
+
     while (index < string.length()) {
-      digit = string.charAt(index++) - '0';
-      if (digit < 0 || digit > 9 || accum < Long.MIN_VALUE / 10) {
+      digit = digit(string.charAt(index++));
+      if (digit < 0 || digit >= radix || accum < cap) {
         return null;
       }
-      accum *= 10;
+      accum *= radix;
       if (accum < Long.MIN_VALUE + digit) {
         return null;
       }
@@ -389,6 +449,7 @@ public final class Longs {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -419,8 +480,7 @@ public final class Longs {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static long[] ensureCapacity(
-      long[] array, int minLength, int padding) {
+  public static long[] ensureCapacity(long[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -563,26 +623,30 @@ public final class Longs {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Long get(int index) {
+    @Override
+    public Long get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Long)
-          && Longs.indexOf(array, (Long) target, start, end) != -1;
+      return (target instanceof Long) && Longs.indexOf(array, (Long) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Long) {
         int i = Longs.indexOf(array, (Long) target, start, end);
@@ -593,7 +657,8 @@ public final class Longs {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Long) {
         int i = Longs.lastIndexOf(array, (Long) target, start, end);
@@ -604,7 +669,8 @@ public final class Longs {
       return -1;
     }
 
-    @Override public Long set(int index, Long element) {
+    @Override
+    public Long set(int index, Long element) {
       checkElementIndex(index, size());
       long oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -612,7 +678,8 @@ public final class Longs {
       return oldValue;
     }
 
-    @Override public List<Long> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Long> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -621,7 +688,8 @@ public final class Longs {
       return new LongArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(@Nullable Object object) {
       if (object == this) {
         return true;
       }
@@ -641,7 +709,8 @@ public final class Longs {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Longs.hashCode(array[i]);
@@ -649,7 +718,8 @@ public final class Longs {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 10);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/ParseRequest.java b/guava/src/com/google/common/primitives/ParseRequest.java
index 98f29b4..dd5d5e3 100644
--- a/guava/src/com/google/common/primitives/ParseRequest.java
+++ b/guava/src/com/google/common/primitives/ParseRequest.java
@@ -16,9 +16,12 @@ package com.google.common.primitives;
 
 import com.google.common.annotations.GwtCompatible;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * A string to be parsed as a number and the radix to interpret it in.
  */
+ at CheckReturnValue
 @GwtCompatible
 final class ParseRequest {
   final String rawValue;
diff --git a/guava/src/com/google/common/primitives/Primitives.java b/guava/src/com/google/common/primitives/Primitives.java
index 08c6f31..81588ab 100644
--- a/guava/src/com/google/common/primitives/Primitives.java
+++ b/guava/src/com/google/common/primitives/Primitives.java
@@ -23,6 +23,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Contains static utility methods pertaining to primitive types and their
  * corresponding wrapper types.
@@ -30,6 +32,7 @@ import java.util.Set;
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 public final class Primitives {
   private Primitives() {}
 
@@ -40,7 +43,7 @@ public final class Primitives {
   private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
 
   // Sad that we can't use a BiMap. :(
-  
+
   static {
     Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
     Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
@@ -59,8 +62,11 @@ public final class Primitives {
     WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
   }
 
-  private static void add(Map<Class<?>, Class<?>> forward,
-      Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
+  private static void add(
+      Map<Class<?>, Class<?>> forward,
+      Map<Class<?>, Class<?>> backward,
+      Class<?> key,
+      Class<?> value) {
     forward.put(key, value);
     backward.put(value, key);
   }
diff --git a/guava/src/com/google/common/primitives/Shorts.java b/guava/src/com/google/common/primitives/Shorts.java
index 1a4ba4c..a2ad0e8 100644
--- a/guava/src/com/google/common/primitives/Shorts.java
+++ b/guava/src/com/google/common/primitives/Shorts.java
@@ -35,17 +35,20 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.RandomAccess;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code short} primitives, that are not
  * already found in either {@link Short} or {@link Arrays}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
  * @since 1.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class Shorts {
   private Shorts() {}
@@ -158,8 +161,7 @@ public final class Shorts {
   }
 
   // TODO(kevinb): consider making this public
-  private static int indexOf(
-      short[] array, short target, int start, int end) {
+  private static int indexOf(short[] array, short target, int start, int end) {
     for (int i = start; i < end; i++) {
       if (array[i] == target) {
         return i;
@@ -212,8 +214,7 @@ public final class Shorts {
   }
 
   // TODO(kevinb): consider making this public
-  private static int lastIndexOf(
-      short[] array, short target, int start, int end) {
+  private static int lastIndexOf(short[] array, short target, int start, int end) {
     for (int i = end - 1; i >= start; i--) {
       if (array[i] == target) {
         return i;
@@ -298,8 +299,9 @@ public final class Shorts {
   @GwtIncompatible("doesn't work")
   public static byte[] toByteArray(short value) {
     return new byte[] {
-        (byte) (value >> 8),
-        (byte) value};
+      (byte) (value >> 8),
+      (byte) value
+    };
   }
 
   /**
@@ -316,8 +318,7 @@ public final class Shorts {
    */
   @GwtIncompatible("doesn't work")
   public static short fromByteArray(byte[] bytes) {
-    checkArgument(bytes.length >= BYTES,
-        "array too small: %s < %s", bytes.length, BYTES);
+    checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
     return fromBytes(bytes[0], bytes[1]);
   }
 
@@ -333,8 +334,8 @@ public final class Shorts {
     return (short) ((b1 << 8) | (b2 & 0xFF));
   }
 
-  private static final class ShortConverter
-      extends Converter<String, Short> implements Serializable {
+  private static final class ShortConverter extends Converter<String, Short>
+      implements Serializable {
     static final ShortConverter INSTANCE = new ShortConverter();
 
     @Override
@@ -355,6 +356,7 @@ public final class Shorts {
     private Object readResolve() {
       return INSTANCE;
     }
+
     private static final long serialVersionUID = 1;
   }
 
@@ -385,8 +387,7 @@ public final class Shorts {
    * @return an array containing the values of {@code array}, with guaranteed
    *     minimum length {@code minLength}
    */
-  public static short[] ensureCapacity(
-      short[] array, int minLength, int padding) {
+  public static short[] ensureCapacity(short[] array, int minLength, int padding) {
     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
     checkArgument(padding >= 0, "Invalid padding: %s", padding);
     return (array.length < minLength)
@@ -529,26 +530,30 @@ public final class Shorts {
       this.end = end;
     }
 
-    @Override public int size() {
+    @Override
+    public int size() {
       return end - start;
     }
 
-    @Override public boolean isEmpty() {
+    @Override
+    public boolean isEmpty() {
       return false;
     }
 
-    @Override public Short get(int index) {
+    @Override
+    public Short get(int index) {
       checkElementIndex(index, size());
       return array[start + index];
     }
 
-    @Override public boolean contains(Object target) {
+    @Override
+    public boolean contains(Object target) {
       // Overridden to prevent a ton of boxing
-      return (target instanceof Short)
-          && Shorts.indexOf(array, (Short) target, start, end) != -1;
+      return (target instanceof Short) && Shorts.indexOf(array, (Short) target, start, end) != -1;
     }
 
-    @Override public int indexOf(Object target) {
+    @Override
+    public int indexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Short) {
         int i = Shorts.indexOf(array, (Short) target, start, end);
@@ -559,7 +564,8 @@ public final class Shorts {
       return -1;
     }
 
-    @Override public int lastIndexOf(Object target) {
+    @Override
+    public int lastIndexOf(Object target) {
       // Overridden to prevent a ton of boxing
       if (target instanceof Short) {
         int i = Shorts.lastIndexOf(array, (Short) target, start, end);
@@ -570,7 +576,8 @@ public final class Shorts {
       return -1;
     }
 
-    @Override public Short set(int index, Short element) {
+    @Override
+    public Short set(int index, Short element) {
       checkElementIndex(index, size());
       short oldValue = array[start + index];
       // checkNotNull for GWT (do not optimize)
@@ -578,7 +585,8 @@ public final class Shorts {
       return oldValue;
     }
 
-    @Override public List<Short> subList(int fromIndex, int toIndex) {
+    @Override
+    public List<Short> subList(int fromIndex, int toIndex) {
       int size = size();
       checkPositionIndexes(fromIndex, toIndex, size);
       if (fromIndex == toIndex) {
@@ -587,7 +595,8 @@ public final class Shorts {
       return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
     }
 
-    @Override public boolean equals(Object object) {
+    @Override
+    public boolean equals(Object object) {
       if (object == this) {
         return true;
       }
@@ -607,7 +616,8 @@ public final class Shorts {
       return super.equals(object);
     }
 
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
       int result = 1;
       for (int i = start; i < end; i++) {
         result = 31 * result + Shorts.hashCode(array[i]);
@@ -615,7 +625,8 @@ public final class Shorts {
       return result;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
       StringBuilder builder = new StringBuilder(size() * 6);
       builder.append('[').append(array[start]);
       for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/SignedBytes.java b/guava/src/com/google/common/primitives/SignedBytes.java
index 77a0ff5..4a8f131 100644
--- a/guava/src/com/google/common/primitives/SignedBytes.java
+++ b/guava/src/com/google/common/primitives/SignedBytes.java
@@ -23,14 +23,16 @@ import com.google.common.annotations.GwtCompatible;
 
 import java.util.Comparator;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code byte} primitives that
  * interpret values as signed. The corresponding methods that treat the values
  * as unsigned are found in {@link UnsignedBytes}, and the methods for which
  * signedness is not an issue are in {@link Bytes}.
- * 
+ *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
@@ -38,17 +40,18 @@ import java.util.Comparator;
  */
 // TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
 // javadoc?
+ at CheckReturnValue
 @GwtCompatible
 public final class SignedBytes {
   private SignedBytes() {}
 
   /**
-   * The largest power of two that can be represented as a signed {@code byte}. 
+   * The largest power of two that can be represented as a signed {@code byte}.
    *
    * @since 10.0
    */
   public static final byte MAX_POWER_OF_TWO = 1 << 6;
-  
+
   /**
    * Returns the {@code byte} value that is equal to {@code value}, if possible.
    *
diff --git a/guava/src/com/google/common/primitives/UnsignedBytes.java b/guava/src/com/google/common/primitives/UnsignedBytes.java
index cc16b0c..6ec6338 100644
--- a/guava/src/com/google/common/primitives/UnsignedBytes.java
+++ b/guava/src/com/google/common/primitives/UnsignedBytes.java
@@ -27,6 +27,8 @@ import sun.misc.Unsafe;
 import java.nio.ByteOrder;
 import java.util.Comparator;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code byte} primitives that interpret
  * values as <i>unsigned</i> (that is, any negative value {@code b} is treated
@@ -35,7 +37,7 @@ import java.util.Comparator;
  * which signedness is not an issue are in {@link Bytes}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * @author Kevin Bourrillion
@@ -71,6 +73,7 @@ public final class UnsignedBytes {
    *
    * @since 6.0
    */
+  @CheckReturnValue
   public static int toInt(byte value) {
     return value & UNSIGNED_MASK;
   }
@@ -122,6 +125,7 @@ public final class UnsignedBytes {
    * @return a negative value if {@code a} is less than {@code b}; a positive
    *     value if {@code a} is greater than {@code b}; or zero if they are equal
    */
+  @CheckReturnValue
   public static int compare(byte a, byte b) {
     return toInt(a) - toInt(b);
   }
@@ -134,6 +138,7 @@ public final class UnsignedBytes {
    *     every other value in the array
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static byte min(byte... array) {
     checkArgument(array.length > 0);
     int min = toInt(array[0]);
@@ -154,6 +159,7 @@ public final class UnsignedBytes {
    *     to every other value in the array
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static byte max(byte... array) {
     checkArgument(array.length > 0);
     int max = toInt(array[0]);
@@ -172,6 +178,7 @@ public final class UnsignedBytes {
    * @since 13.0
    */
   @Beta
+  @CheckReturnValue
   public static String toString(byte x) {
     return toString(x, 10);
   }
@@ -187,9 +194,12 @@ public final class UnsignedBytes {
    * @since 13.0
    */
   @Beta
+  @CheckReturnValue
   public static String toString(byte x, int radix) {
-    checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
-        "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
+    checkArgument(
+        radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
+        "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX",
+        radix);
     // Benchmarks indicate this is probably not worth optimizing.
     return Integer.toString(toInt(x), radix);
   }
@@ -199,7 +209,7 @@ public final class UnsignedBytes {
    *
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code byte}
    *         value
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Byte#parseByte(String)})
    * @since 13.0
    */
@@ -216,7 +226,7 @@ public final class UnsignedBytes {
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code byte}
    *         with the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX}
    *         and {@link Character#MAX_RADIX}.
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Byte#parseByte(String)})
    * @since 13.0
    */
@@ -240,6 +250,7 @@ public final class UnsignedBytes {
    *     the resulting string (but not at the start or end)
    * @param array an array of {@code byte} values, possibly empty
    */
+  @CheckReturnValue
   public static String join(String separator, byte... array) {
     checkNotNull(separator);
     if (array.length == 0) {
@@ -271,6 +282,7 @@ public final class UnsignedBytes {
    *     Lexicographical order article at Wikipedia</a>
    * @since 2.0
    */
+  @CheckReturnValue
   public static Comparator<byte[]> lexicographicalComparator() {
     return LexicographicalComparatorHolder.BEST_COMPARATOR;
   }
@@ -298,8 +310,7 @@ public final class UnsignedBytes {
     enum UnsafeComparator implements Comparator<byte[]> {
       INSTANCE;
 
-      static final boolean BIG_ENDIAN =
-          ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
+      static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
 
       /*
        * The following static final fields exist for performance reasons.
@@ -335,7 +346,7 @@ public final class UnsignedBytes {
           throw new AssertionError();
         }
       }
-      
+
       /**
        * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
        * Replace with a simple call to Unsafe.getUnsafe when integrating
@@ -344,29 +355,33 @@ public final class UnsignedBytes {
        * @return a sun.misc.Unsafe
        */
       private static sun.misc.Unsafe getUnsafe() {
-          try {
-              return sun.misc.Unsafe.getUnsafe();
-          } catch (SecurityException tryReflectionInstead) {}
-          try {
-              return java.security.AccessController.doPrivileged
-              (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
-                  public sun.misc.Unsafe run() throws Exception {
-                      Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
-                      for (java.lang.reflect.Field f : k.getDeclaredFields()) {
-                          f.setAccessible(true);
-                          Object x = f.get(null);
-                          if (k.isInstance(x))
-                              return k.cast(x);
-                      }
-                      throw new NoSuchFieldError("the Unsafe");
-                  }});
-          } catch (java.security.PrivilegedActionException e) {
-              throw new RuntimeException("Could not initialize intrinsics",
-                                         e.getCause());
-          }
+        try {
+          return sun.misc.Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+          // that's okay; try reflection instead
+        }
+        try {
+          return java.security.AccessController.doPrivileged(
+              new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
+                public sun.misc.Unsafe run() throws Exception {
+                  Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+                  for (java.lang.reflect.Field f : k.getDeclaredFields()) {
+                    f.setAccessible(true);
+                    Object x = f.get(null);
+                    if (k.isInstance(x)) {
+                      return k.cast(x);
+                    }
+                  }
+                  throw new NoSuchFieldError("the Unsafe");
+                }
+              });
+        } catch (java.security.PrivilegedActionException e) {
+          throw new RuntimeException("Could not initialize intrinsics", e.getCause());
+        }
       }
 
-      @Override public int compare(byte[] left, byte[] right) {
+      @Override
+      public int compare(byte[] left, byte[] right) {
         int minLength = Math.min(left.length, right.length);
         int minWords = minLength / Longs.BYTES;
 
@@ -386,8 +401,8 @@ public final class UnsignedBytes {
             /*
              * We want to compare only the first index where left[index] != right[index].
              * This corresponds to the least significant nonzero byte in lw ^ rw, since lw
-             * and rw are little-endian.  Long.numberOfTrailingZeros(diff) tells us the least 
-             * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the 
+             * and rw are little-endian.  Long.numberOfTrailingZeros(diff) tells us the least
+             * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the
              * shift to get that least significant nonzero byte.
              */
             int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
@@ -409,7 +424,8 @@ public final class UnsignedBytes {
     enum PureJavaComparator implements Comparator<byte[]> {
       INSTANCE;
 
-      @Override public int compare(byte[] left, byte[] right) {
+      @Override
+      public int compare(byte[] left, byte[] right) {
         int minLength = Math.min(left.length, right.length);
         for (int i = 0; i < minLength; i++) {
           int result = UnsignedBytes.compare(left[i], right[i]);
@@ -431,8 +447,7 @@ public final class UnsignedBytes {
 
         // yes, UnsafeComparator does implement Comparator<byte[]>
         @SuppressWarnings("unchecked")
-        Comparator<byte[]> comparator =
-            (Comparator<byte[]>) theClass.getEnumConstants()[0];
+        Comparator<byte[]> comparator = (Comparator<byte[]>) theClass.getEnumConstants()[0];
         return comparator;
       } catch (Throwable t) { // ensure we really catch *everything*
         return lexicographicalComparatorJavaImpl();
diff --git a/guava/src/com/google/common/primitives/UnsignedInteger.java b/guava/src/com/google/common/primitives/UnsignedInteger.java
index 1b87e2d..0ba7a4a 100644
--- a/guava/src/com/google/common/primitives/UnsignedInteger.java
+++ b/guava/src/com/google/common/primitives/UnsignedInteger.java
@@ -35,12 +35,13 @@ import javax.annotation.Nullable;
  * treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
  * unsigned primitive utilities</a>.
  *
  * @author Louis Wasserman
  * @since 11.0
  */
+ at CheckReturnValue
 @GwtCompatible(emulated = true)
 public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
   public static final UnsignedInteger ZERO = fromIntBits(0);
@@ -75,8 +76,10 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    * if possible.  The inverse operation of {@link #longValue()}.
    */
   public static UnsignedInteger valueOf(long value) {
-    checkArgument((value & INT_MASK) == value,
-        "value (%s) is outside the range for an unsigned integer value", value);
+    checkArgument(
+        (value & INT_MASK) == value,
+        "value (%s) is outside the range for an unsigned integer value",
+        value);
     return fromIntBits((int) value);
   }
 
@@ -88,8 +91,10 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    */
   public static UnsignedInteger valueOf(BigInteger value) {
     checkNotNull(value);
-    checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
-        "value (%s) is outside the range for an unsigned integer value", value);
+    checkArgument(
+        value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
+        "value (%s) is outside the range for an unsigned integer value",
+        value);
     return fromIntBits(value.intValue());
   }
 
@@ -121,7 +126,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    *
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger plus(UnsignedInteger val) {
     return fromIntBits(this.value + checkNotNull(val).value);
   }
@@ -132,7 +136,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    *
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger minus(UnsignedInteger val) {
     return fromIntBits(value - checkNotNull(val).value);
   }
@@ -143,10 +146,9 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    *
    * @since 14.0
    */
-  @CheckReturnValue
   @GwtIncompatible("Does not truncate correctly")
   public UnsignedInteger times(UnsignedInteger val) {
-    // TODO(user): make this GWT-compatible
+    // TODO(lowasser): make this GWT-compatible
     return fromIntBits(value * checkNotNull(val).value);
   }
 
@@ -156,7 +158,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    * @throws ArithmeticException if {@code val} is zero
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger dividedBy(UnsignedInteger val) {
     return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
   }
@@ -167,7 +168,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
    * @throws ArithmeticException if {@code val} is zero
    * @since 14.0
    */
-  @CheckReturnValue
   public UnsignedInteger mod(UnsignedInteger val) {
     return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
   }
diff --git a/guava/src/com/google/common/primitives/UnsignedInts.java b/guava/src/com/google/common/primitives/UnsignedInts.java
index 762b841..e6841c0 100644
--- a/guava/src/com/google/common/primitives/UnsignedInts.java
+++ b/guava/src/com/google/common/primitives/UnsignedInts.java
@@ -23,6 +23,8 @@ import com.google.common.annotations.GwtCompatible;
 import java.util.Arrays;
 import java.util.Comparator;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code int} primitives that interpret values as
  * <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value
@@ -38,7 +40,7 @@ import java.util.Comparator;
  * class be used, at a small efficiency penalty, to enforce the distinction in the type system.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
  * unsigned primitive utilities</a>.
  *
  * @author Louis Wasserman
@@ -64,6 +66,7 @@ public final class UnsignedInts {
    * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
    *         greater than {@code b}; or zero if they are equal
    */
+  @CheckReturnValue
   public static int compare(int a, int b) {
     return Ints.compare(flip(a), flip(b));
   }
@@ -71,6 +74,7 @@ public final class UnsignedInts {
   /**
    * Returns the value of the given {@code int} as a {@code long}, when treated as unsigned.
    */
+  @CheckReturnValue
   public static long toLong(int value) {
     return value & INT_MASK;
   }
@@ -83,6 +87,7 @@ public final class UnsignedInts {
    *         the array according to {@link #compare}
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static int min(int... array) {
     checkArgument(array.length > 0);
     int min = flip(array[0]);
@@ -103,6 +108,7 @@ public final class UnsignedInts {
    *         in the array according to {@link #compare}
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static int max(int... array) {
     checkArgument(array.length > 0);
     int max = flip(array[0]);
@@ -123,6 +129,7 @@ public final class UnsignedInts {
    *        string (but not at the start or end)
    * @param array an array of unsigned {@code int} values, possibly empty
    */
+  @CheckReturnValue
   public static String join(String separator, int... array) {
     checkNotNull(separator);
     if (array.length == 0) {
@@ -150,6 +157,7 @@ public final class UnsignedInts {
    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order"> Lexicographical order
    *      article at Wikipedia</a>
    */
+  @CheckReturnValue
   public static Comparator<int[]> lexicographicalComparator() {
     return LexicographicalComparator.INSTANCE;
   }
@@ -177,6 +185,7 @@ public final class UnsignedInts {
    * @param divisor the divisor (denominator)
    * @throws ArithmeticException if divisor is 0
    */
+  @CheckReturnValue
   public static int divide(int dividend, int divisor) {
     return (int) (toLong(dividend) / toLong(divisor));
   }
@@ -189,6 +198,7 @@ public final class UnsignedInts {
    * @param divisor the divisor (denominator)
    * @throws ArithmeticException if divisor is 0
    */
+  @CheckReturnValue
   public static int remainder(int dividend, int divisor) {
     return (int) (toLong(dividend) % toLong(divisor));
   }
@@ -225,7 +235,7 @@ public final class UnsignedInts {
    * Returns the unsigned {@code int} value represented by the given decimal string.
    *
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code int} value
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Integer#parseInt(String)})
    */
   public static int parseUnsignedInt(String s) {
@@ -240,15 +250,15 @@ public final class UnsignedInts {
    *        {@link Character#MIN_RADIX} and {@link Character#MAX_RADIX}.
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code int}, or
    *         if supplied radix is invalid.
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Integer#parseInt(String)})
    */
   public static int parseUnsignedInt(String string, int radix) {
     checkNotNull(string);
     long result = Long.parseLong(string, radix);
     if ((result & INT_MASK) != result) {
-      throw new NumberFormatException("Input " + string + " in base " + radix
-          + " is not in the range of an unsigned integer");
+      throw new NumberFormatException(
+          "Input " + string + " in base " + radix + " is not in the range of an unsigned integer");
     }
     return (int) result;
   }
@@ -256,6 +266,7 @@ public final class UnsignedInts {
   /**
    * Returns a string representation of x, where x is treated as unsigned.
    */
+  @CheckReturnValue
   public static String toString(int x) {
     return toString(x, 10);
   }
@@ -269,6 +280,7 @@ public final class UnsignedInts {
    * @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX}
    *         and {@link Character#MAX_RADIX}.
    */
+  @CheckReturnValue
   public static String toString(int x, int radix) {
     long asLong = x & INT_MASK;
     return Long.toString(asLong, radix);
diff --git a/guava/src/com/google/common/primitives/UnsignedLong.java b/guava/src/com/google/common/primitives/UnsignedLong.java
index 314818f..4bf00c4 100644
--- a/guava/src/com/google/common/primitives/UnsignedLong.java
+++ b/guava/src/com/google/common/primitives/UnsignedLong.java
@@ -32,7 +32,7 @@ import javax.annotation.Nullable;
  * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
  * unsigned primitive utilities</a>.
  *
  * @author Louis Wasserman
@@ -68,7 +68,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    * @since 14.0
    */
   public static UnsignedLong fromLongBits(long bits) {
-    // TODO(user): consider caching small values, like Long.valueOf
+    // TODO(lowasser): consider caching small values, like Long.valueOf
     return new UnsignedLong(bits);
   }
 
@@ -79,8 +79,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    * @since 14.0
    */
   public static UnsignedLong valueOf(long value) {
-    checkArgument(value >= 0,
-        "value (%s) is outside the range for an unsigned long value", value);
+    checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
     return fromLongBits(value);
   }
 
@@ -92,8 +91,10 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    */
   public static UnsignedLong valueOf(BigInteger value) {
     checkNotNull(value);
-    checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
-        "value (%s) is outside the range for an unsigned long value", value);
+    checkArgument(
+        value.signum() >= 0 && value.bitLength() <= Long.SIZE,
+        "value (%s) is outside the range for an unsigned long value",
+        value);
     return fromLongBits(value.longValue());
   }
 
@@ -102,7 +103,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    * an unsigned {@code long} value.
    *
    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
-   *         value
+   *     value
    */
   public static UnsignedLong valueOf(String string) {
     return valueOf(string, 10);
@@ -113,8 +114,8 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    * an unsigned {@code long} value in the specified radix.
    *
    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
-   *         value, or {@code radix} is not between {@link Character#MIN_RADIX} and
-   *         {@link Character#MAX_RADIX}
+   *     value, or {@code radix} is not between {@link Character#MIN_RADIX} and
+   *     {@link Character#MAX_RADIX}
    */
   public static UnsignedLong valueOf(String string, int radix) {
     return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
@@ -126,6 +127,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public UnsignedLong plus(UnsignedLong val) {
     return fromLongBits(this.value + checkNotNull(val).value);
   }
@@ -136,6 +138,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
    *
    * @since 14.0
    */
+  @CheckReturnValue
   public UnsignedLong minus(UnsignedLong val) {
     return fromLongBits(this.value - checkNotNull(val).value);
   }
diff --git a/guava/src/com/google/common/primitives/UnsignedLongs.java b/guava/src/com/google/common/primitives/UnsignedLongs.java
index cb9923f..a4e6f10 100644
--- a/guava/src/com/google/common/primitives/UnsignedLongs.java
+++ b/guava/src/com/google/common/primitives/UnsignedLongs.java
@@ -24,6 +24,8 @@ import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.Comparator;
 
+import javax.annotation.CheckReturnValue;
+
 /**
  * Static utility methods pertaining to {@code long} primitives that interpret values as
  * <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value
@@ -39,7 +41,7 @@ import java.util.Comparator;
  * class be used, at a small efficiency penalty, to enforce the distinction in the type system.
  *
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
  * unsigned primitive utilities</a>.
  *
  * @author Louis Wasserman
@@ -72,6 +74,7 @@ public final class UnsignedLongs {
    * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
    *         greater than {@code b}; or zero if they are equal
    */
+  @CheckReturnValue
   public static int compare(long a, long b) {
     return Longs.compare(flip(a), flip(b));
   }
@@ -84,6 +87,7 @@ public final class UnsignedLongs {
    *         the array according to {@link #compare}
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static long min(long... array) {
     checkArgument(array.length > 0);
     long min = flip(array[0]);
@@ -104,6 +108,7 @@ public final class UnsignedLongs {
    *         in the array according to {@link #compare}
    * @throws IllegalArgumentException if {@code array} is empty
    */
+  @CheckReturnValue
   public static long max(long... array) {
     checkArgument(array.length > 0);
     long max = flip(array[0]);
@@ -124,6 +129,7 @@ public final class UnsignedLongs {
    *        string (but not at the start or end)
    * @param array an array of unsigned {@code long} values, possibly empty
    */
+  @CheckReturnValue
   public static String join(String separator, long... array) {
     checkNotNull(separator);
     if (array.length == 0) {
@@ -152,6 +158,7 @@ public final class UnsignedLongs {
    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">Lexicographical order
    *      article at Wikipedia</a>
    */
+  @CheckReturnValue
   public static Comparator<long[]> lexicographicalComparator() {
     return LexicographicalComparator.INSTANCE;
   }
@@ -179,6 +186,7 @@ public final class UnsignedLongs {
    * @param divisor the divisor (denominator)
    * @throws ArithmeticException if divisor is 0
    */
+  @CheckReturnValue
   public static long divide(long dividend, long divisor) {
     if (divisor < 0) { // i.e., divisor >= 2^63:
       if (compare(dividend, divisor) < 0) {
@@ -213,6 +221,7 @@ public final class UnsignedLongs {
    * @throws ArithmeticException if divisor is 0
    * @since 11.0
    */
+  @CheckReturnValue
   public static long remainder(long dividend, long divisor) {
     if (divisor < 0) { // i.e., divisor >= 2^63:
       if (compare(dividend, divisor) < 0) {
@@ -243,7 +252,7 @@ public final class UnsignedLongs {
    *
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code long}
    *         value
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Long#parseLong(String)})
    */
   public static long parseUnsignedLong(String s) {
@@ -287,7 +296,7 @@ public final class UnsignedLongs {
    * @throws NumberFormatException if the string does not contain a valid unsigned {@code long}
    *         with the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX}
    *         and {@link Character#MAX_RADIX}.
-   * @throws NullPointerException if {@code s} is null 
+   * @throws NullPointerException if {@code s} is null
    *         (in contrast to {@link Long#parseLong(String)})
    */
   public static long parseUnsignedLong(String s, int radix) {
@@ -340,6 +349,7 @@ public final class UnsignedLongs {
   /**
    * Returns a string representation of x, where x is treated as unsigned.
    */
+  @CheckReturnValue
   public static String toString(long x) {
     return toString(x, 10);
   }
@@ -353,9 +363,12 @@ public final class UnsignedLongs {
    * @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX}
    *         and {@link Character#MAX_RADIX}.
    */
+  @CheckReturnValue
   public static String toString(long x, int radix) {
-    checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
-        "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
+    checkArgument(
+        radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
+        "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX",
+        radix);
     if (x == 0) {
       // Simply return "0"
       return "0";
@@ -384,6 +397,7 @@ public final class UnsignedLongs {
   private static final long[] maxValueDivs = new long[Character.MAX_RADIX + 1];
   private static final int[] maxValueMods = new int[Character.MAX_RADIX + 1];
   private static final int[] maxSafeDigits = new int[Character.MAX_RADIX + 1];
+
   static {
     BigInteger overflow = new BigInteger("10000000000000000", 16);
     for (int i = Character.MIN_RADIX; i <= Character.MAX_RADIX; i++) {
diff --git a/guava/src/com/google/common/primitives/package-info.java b/guava/src/com/google/common/primitives/package-info.java
index 205183f..52a4fe5 100644
--- a/guava/src/com/google/common/primitives/package-info.java
+++ b/guava/src/com/google/common/primitives/package-info.java
@@ -22,7 +22,7 @@
  * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
  * primitive utilities</a>.
  *
  * <h2>Contents</h2>
diff --git a/guava/src/com/google/common/reflect/ClassPath.java b/guava/src/com/google/common/reflect/ClassPath.java
index cadb825..59763d2 100644
--- a/guava/src/com/google/common/reflect/ClassPath.java
+++ b/guava/src/com/google/common/reflect/ClassPath.java
@@ -26,20 +26,20 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Ordering;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
@@ -87,10 +87,8 @@ public final class ClassPath {
    *         failed.
    */
   public static ClassPath from(ClassLoader classloader) throws IOException {
-    Scanner scanner = new Scanner();
-    for (Map.Entry<URI, ClassLoader> entry : getClassPathEntries(classloader).entrySet()) {
-      scanner.scan(entry.getKey(), entry.getValue());
-    }
+    DefaultScanner scanner = new DefaultScanner();
+    scanner.scan(classloader);
     return new ClassPath(scanner.getResources());
   }
 
@@ -153,6 +151,7 @@ public final class ClassPath {
   @Beta
   public static class ResourceInfo {
     private final String resourceName;
+
     final ClassLoader loader;
 
     static ResourceInfo of(String resourceName, ClassLoader loader) {
@@ -162,16 +161,25 @@ public final class ClassPath {
         return new ResourceInfo(resourceName, loader);
       }
     }
-  
-    ResourceInfo(String resourceName, ClassLoader loader) {
+
+    ResourceInfo(String resourceName,  ClassLoader loader) {
       this.resourceName = checkNotNull(resourceName);
       this.loader = checkNotNull(loader);
     }
 
-    /** Returns the url identifying the resource. */
-    public final URL url() {
-      return checkNotNull(loader.getResource(resourceName),
-          "Failed to load resource: %s", resourceName);
+    /**
+     * Returns the url identifying the resource.
+     *
+     * <p>See {@link ClassLoader#getResource}
+     * @throws NoSuchElementException if the resource cannot be loaded through the class loader,
+     *         despite physically existing in the class path.
+     */
+    public final URL url() throws NoSuchElementException {
+      URL url = loader.getResource(resourceName);
+      if (url == null) {
+        throw new NoSuchElementException(resourceName);
+      }
+      return url;
     }
 
     /** Returns the fully qualified name of the resource. Such as "com/mycomp/foo/bar.txt". */
@@ -212,19 +220,19 @@ public final class ClassPath {
       this.className = getClassName(resourceName);
     }
 
-    /** 
+    /**
      * Returns the package name of the class, without attempting to load the class.
-     * 
-     * <p>Behaves identically to {@link Package#getName()} but does not require the class (or 
+     *
+     * <p>Behaves identically to {@link Package#getName()} but does not require the class (or
      * package) to be loaded.
      */
     public String getPackageName() {
       return Reflection.getPackageName(className);
     }
 
-    /** 
+    /**
      * Returns the simple name of the underlying class as given in the source code.
-     * 
+     *
      * <p>Behaves identically to {@link Class#getSimpleName()} but does not require the class to be
      * loaded.
      */
@@ -232,7 +240,7 @@ public final class ClassPath {
       int lastDollarSign = className.lastIndexOf('$');
       if (lastDollarSign != -1) {
         String innerClassName = className.substring(lastDollarSign + 1);
-        // local and anonymous classes are prefixed with number (1,2,3...), anonymous classes are 
+        // local and anonymous classes are prefixed with number (1,2,3...), anonymous classes are
         // entirely numeric whereas local classes have the user supplied name as a suffix
         return CharMatcher.DIGIT.trimLeadingFrom(innerClassName);
       }
@@ -245,9 +253,9 @@ public final class ClassPath {
       return className.substring(packageName.length() + 1);
     }
 
-    /** 
-     * Returns the fully qualified name of the class. 
-     * 
+    /**
+     * Returns the fully qualified name of the class.
+     *
      * <p>Behaves identically to {@link Class#getName()} but does not require the class to be
      * loaded.
      */
@@ -275,94 +283,47 @@ public final class ClassPath {
     }
   }
 
-  @VisibleForTesting static ImmutableMap<URI, ClassLoader> getClassPathEntries(
-      ClassLoader classloader) {
-    LinkedHashMap<URI, ClassLoader> entries = Maps.newLinkedHashMap();
-    // Search parent first, since it's the order ClassLoader#loadClass() uses.
-    ClassLoader parent = classloader.getParent();
-    if (parent != null) {
-      entries.putAll(getClassPathEntries(parent));
-    }
-    if (classloader instanceof URLClassLoader) {
-      URLClassLoader urlClassLoader = (URLClassLoader) classloader;
-      for (URL entry : urlClassLoader.getURLs()) {
-        URI uri;
-        try {
-          uri = entry.toURI();
-        } catch (URISyntaxException e) {
-          throw new IllegalArgumentException(e);
-        }
-        if (!entries.containsKey(uri)) {
-          entries.put(uri, classloader);
-        }
+  /**
+   * Abstract class that scans through the class path represented by a {@link ClassLoader} and calls
+   * {@link #scanDirectory} and {@link #scanJarFile} for directories and jar files on the class path
+   * respectively.
+   */
+  abstract static class Scanner {
+
+    // We only scan each file once independent of the classloader that resource might be associated
+    // with.
+    private final Set<File> scannedUris = Sets.newHashSet();
+
+    public final void scan(ClassLoader classloader) throws IOException {
+      for (Map.Entry<File, ClassLoader> entry : getClassPathEntries(classloader).entrySet()) {
+        scan(entry.getKey(), entry.getValue());
       }
     }
-    return ImmutableMap.copyOf(entries);
-  }
 
-  @VisibleForTesting static final class Scanner {
+    /** Called when a directory is scanned for resource files. */
+    protected abstract void scanDirectory(ClassLoader loader, File directory)
+        throws IOException;
 
-    private final ImmutableSortedSet.Builder<ResourceInfo> resources =
-        new ImmutableSortedSet.Builder<ResourceInfo>(Ordering.usingToString());
-    private final Set<URI> scannedUris = Sets.newHashSet();
+    /** Called when a jar file is scanned for resource entries. */
+    protected abstract void scanJarFile(ClassLoader loader, JarFile file) throws IOException;
 
-    ImmutableSortedSet<ResourceInfo> getResources() {
-      return resources.build();
-    }
-
-    void scan(URI uri, ClassLoader classloader) throws IOException {
-      if (uri.getScheme().equals("file") && scannedUris.add(uri)) {
-        scanFrom(new File(uri), classloader);
+    @VisibleForTesting final void scan(File file, ClassLoader classloader) throws IOException {
+      if (scannedUris.add(file.getCanonicalFile())) {
+        scanFrom(file, classloader);
       }
     }
-  
-    @VisibleForTesting void scanFrom(File file, ClassLoader classloader)
-        throws IOException {
+
+    private void scanFrom(File file, ClassLoader classloader) throws IOException {
       if (!file.exists()) {
         return;
       }
       if (file.isDirectory()) {
-        scanDirectory(file, classloader);
+        scanDirectory(classloader, file);
       } else {
         scanJar(file, classloader);
       }
     }
-  
-    private void scanDirectory(File directory, ClassLoader classloader) throws IOException {
-      scanDirectory(directory, classloader, "", ImmutableSet.<File>of());
-    }
-  
-    private void scanDirectory(
-        File directory, ClassLoader classloader, String packagePrefix,
-        ImmutableSet<File> ancestors) throws IOException {
-      File canonical = directory.getCanonicalFile();
-      if (ancestors.contains(canonical)) {
-        // A cycle in the filesystem, for example due to a symbolic link.
-        return;
-      }
-      File[] files = directory.listFiles();
-      if (files == null) {
-        logger.warning("Cannot read directory " + directory);
-        // IO error, just skip the directory
-        return;
-      }
-      ImmutableSet<File> newAncestors = ImmutableSet.<File>builder()
-          .addAll(ancestors)
-          .add(canonical)
-          .build();
-      for (File f : files) {
-        String name = f.getName();
-        if (f.isDirectory()) {
-          scanDirectory(f, classloader, packagePrefix + name + "/", newAncestors);
-        } else {
-          String resourceName = packagePrefix + name;
-          if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
-            resources.add(ResourceInfo.of(resourceName, classloader));
-          }
-        }
-      }
-    }
-  
+
     private void scanJar(File file, ClassLoader classloader) throws IOException {
       JarFile jarFile;
       try {
@@ -372,67 +333,130 @@ public final class ClassPath {
         return;
       }
       try {
-        for (URI uri : getClassPathFromManifest(file, jarFile.getManifest())) {
-          scan(uri, classloader);
-        }
-        Enumeration<JarEntry> entries = jarFile.entries();
-        while (entries.hasMoreElements()) {
-          JarEntry entry = entries.nextElement();
-          if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
-            continue;
-          }
-          resources.add(ResourceInfo.of(entry.getName(), classloader));
+        for (File path : getClassPathFromManifest(file, jarFile.getManifest())) {
+          scan(path, classloader);
         }
+        scanJarFile(classloader, jarFile);
       } finally {
         try {
           jarFile.close();
         } catch (IOException ignored) {}
       }
     }
-  
+
     /**
      * Returns the class path URIs specified by the {@code Class-Path} manifest attribute, according
-     * to <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes">
+     * to
+     * <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Main_Attributes">
      * JAR File Specification</a>. If {@code manifest} is null, it means the jar file has no
      * manifest, and an empty set will be returned.
      */
-    @VisibleForTesting static ImmutableSet<URI> getClassPathFromManifest(
+    @VisibleForTesting static ImmutableSet<File> getClassPathFromManifest(
         File jarFile, @Nullable Manifest manifest) {
       if (manifest == null) {
         return ImmutableSet.of();
       }
-      ImmutableSet.Builder<URI> builder = ImmutableSet.builder();
+      ImmutableSet.Builder<File> builder = ImmutableSet.builder();
       String classpathAttribute = manifest.getMainAttributes()
           .getValue(Attributes.Name.CLASS_PATH.toString());
       if (classpathAttribute != null) {
         for (String path : CLASS_PATH_ATTRIBUTE_SEPARATOR.split(classpathAttribute)) {
-          URI uri;
+          URL url;
           try {
-            uri = getClassPathEntry(jarFile, path);
-          } catch (URISyntaxException e) {
+            url = getClassPathEntry(jarFile, path);
+          } catch (MalformedURLException e) {
             // Ignore bad entry
             logger.warning("Invalid Class-Path entry: " + path);
             continue;
           }
-          builder.add(uri);
+          if (url.getProtocol().equals("file")) {
+            builder.add(new File(url.getFile()));
+          }
         }
       }
       return builder.build();
     }
-  
+
+    @VisibleForTesting static ImmutableMap<File, ClassLoader> getClassPathEntries(
+        ClassLoader classloader) {
+      LinkedHashMap<File, ClassLoader> entries = Maps.newLinkedHashMap();
+      // Search parent first, since it's the order ClassLoader#loadClass() uses.
+      ClassLoader parent = classloader.getParent();
+      if (parent != null) {
+        entries.putAll(getClassPathEntries(parent));
+      }
+      if (classloader instanceof URLClassLoader) {
+        URLClassLoader urlClassLoader = (URLClassLoader) classloader;
+        for (URL entry : urlClassLoader.getURLs()) {
+          if (entry.getProtocol().equals("file")) {
+            File file = new File(entry.getFile());
+            if (!entries.containsKey(file)) {
+              entries.put(file, classloader);
+            }
+          }
+        }
+      }
+      return ImmutableMap.copyOf(entries);
+    }
+
     /**
      * Returns the absolute uri of the Class-Path entry value as specified in
-     * <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes">
+     * <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Main_Attributes">
      * JAR File Specification</a>. Even though the specification only talks about relative urls,
      * absolute urls are actually supported too (for example, in Maven surefire plugin).
      */
-    @VisibleForTesting static URI getClassPathEntry(File jarFile, String path)
-        throws URISyntaxException {
-      URI uri = new URI(path);
-      if (uri.isAbsolute()) {
-        return uri;
-      } else {
-        return new File(jarFile.getParentFile(), path.replace('/', File.separatorChar)).toURI();
+    @VisibleForTesting static URL getClassPathEntry(File jarFile, String path)
+        throws MalformedURLException {
+      return new URL(jarFile.toURI().toURL(), path);
+    }
+  }
+
+  @VisibleForTesting static final class DefaultScanner extends Scanner {
+    private final SetMultimap<ClassLoader, String> resources =
+        MultimapBuilder.hashKeys().linkedHashSetValues().build();
+
+    ImmutableSet<ResourceInfo> getResources() {
+      ImmutableSet.Builder<ResourceInfo> builder = ImmutableSet.builder();
+      for (Map.Entry<ClassLoader, String> entry : resources.entries()) {
+        builder.add(ResourceInfo.of(entry.getValue(), entry.getKey()));
+      }
+      return builder.build();
+    }
+
+    @Override protected void scanJarFile(ClassLoader classloader, JarFile file) {
+      Enumeration<JarEntry> entries = file.entries();
+      while (entries.hasMoreElements()) {
+        JarEntry entry = entries.nextElement();
+        if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
+          continue;
+        }
+        resources.get(classloader).add(entry.getName());
+      }
+    }
+
+    @Override protected void scanDirectory(ClassLoader classloader, File directory)
+        throws IOException {
+      scanDirectory(directory, classloader, "");
+    }
+
+    private void scanDirectory(
+        File directory, ClassLoader classloader, String packagePrefix) throws IOException {
+      File[] files = directory.listFiles();
+      if (files == null) {
+        logger.warning("Cannot read directory " + directory);
+        // IO error, just skip the directory
+        return;
+      }
+      for (File f : files) {
+        String name = f.getName();
+        if (f.isDirectory()) {
+          scanDirectory(f, classloader, packagePrefix + name + "/");
+        } else {
+          String resourceName = packagePrefix + name;
+          if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
+            resources.get(classloader).add(resourceName);
+          }
+        }
       }
     }
   }
diff --git a/guava/src/com/google/common/reflect/Invokable.java b/guava/src/com/google/common/reflect/Invokable.java
index b281faf..73fb009 100644
--- a/guava/src/com/google/common/reflect/Invokable.java
+++ b/guava/src/com/google/common/reflect/Invokable.java
@@ -150,7 +150,7 @@ public abstract class Invokable<T, R> extends Element implements GenericDeclarat
 
   /** Explicitly specifies the return type of this {@code Invokable}. */
   public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) {
-    if (!returnType.isAssignableFrom(getReturnType())) {
+    if (!returnType.isSupertypeOf(getReturnType())) {
       throw new IllegalArgumentException(
           "Invokable is known to return " + getReturnType() + ", not " + returnType);
     }
diff --git a/guava/src/com/google/common/reflect/TypeResolver.java b/guava/src/com/google/common/reflect/TypeResolver.java
index 2eec8ea..452cf01 100644
--- a/guava/src/com/google/common/reflect/TypeResolver.java
+++ b/guava/src/com/google/common/reflect/TypeResolver.java
@@ -103,6 +103,11 @@ public final class TypeResolver {
     if (from.equals(to)) {
       return;
     }
+    if (to instanceof WildcardType != from instanceof WildcardType) {
+      // When we are saying "assuming <?> is T, there really isn't any useful type mapping.
+      // Similarly, saying "assuming T is <?>" is meaningless. Of course it is.
+      return;
+    }
     new TypeVisitor() {
       @Override void visitTypeVariable(TypeVariable<?> typeVariable) {
         mappings.put(new TypeVariableKey(typeVariable), to);
diff --git a/guava/src/com/google/common/reflect/TypeToken.java b/guava/src/com/google/common/reflect/TypeToken.java
index bc33e8f..093f152 100644
--- a/guava/src/com/google/common/reflect/TypeToken.java
+++ b/guava/src/com/google/common/reflect/TypeToken.java
@@ -45,6 +45,7 @@ import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Nullable;
 
@@ -52,9 +53,8 @@ import javax.annotation.Nullable;
  * A {@link Type} with generics.
  *
  * <p>Operations that are otherwise only available in {@link Class} are implemented to support
- * {@code Type}, for example {@link #isAssignableFrom}, {@link #isArray} and {@link
- * #getComponentType}. It also provides additional utilities such as {@link #getTypes} and {@link
- * #resolveType} etc.
+ * {@code Type}, for example {@link #isSubtypeOf}, {@link #isArray} and {@link #getComponentType}.
+ * It also provides additional utilities such as {@link #getTypes}, {@link #resolveType}, etc.
  *
  * <p>There are three ways to get a {@code TypeToken} instance: <ul>
  * <li>Wrap a {@code Type} obtained via reflection. For example: {@code
@@ -112,11 +112,11 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
   protected TypeToken() {
     this.runtimeType = capture();
     checkState(!(runtimeType instanceof TypeVariable),
-        "Cannot construct a TypeToken for a type variable.\n" +
-        "You probably meant to call new TypeToken<%s>(getClass()) " +
-        "that can resolve the type variable for you.\n" +
-        "If you do need to create a TypeToken of a type variable, " +
-        "please use TypeToken.of() instead.", runtimeType);
+        "Cannot construct a TypeToken for a type variable.\n"
+        + "You probably meant to call new TypeToken<%s>(getClass()) "
+        + "that can resolve the type variable for you.\n"
+        + "If you do need to create a TypeToken of a type variable, "
+        + "please use TypeToken.of() instead.", runtimeType);
   }
 
   /**
@@ -174,23 +174,13 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
    * </ul>
    */
   public final Class<? super T> getRawType() {
-    Class<?> rawType = getRawType(runtimeType);
+    // For wildcard or type variable, the first bound determines the runtime type.
+    Class<?> rawType = getRawTypes().iterator().next();
     @SuppressWarnings("unchecked") // raw type is |T|
     Class<? super T> result = (Class<? super T>) rawType;
     return result;
   }
 
-  /**
-   * Returns the raw type of the class or parameterized type; if {@code T} is type variable or
-   * wildcard type, the raw types of all its upper bounds are returned.
-   */
-  private ImmutableSet<Class<? super T>> getImmediateRawTypes() {
-    // Cast from ImmutableSet<Class<?>> to ImmutableSet<Class<? super T>>
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    ImmutableSet<Class<? super T>> result = (ImmutableSet) getRawTypes(runtimeType);
-    return result;
-  }
-
   /** Returns the represented type. */
   public final Type getType() {
     return runtimeType;
@@ -373,7 +363,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
    * input {@code Iterable.class}.
    */
   public final TypeToken<? super T> getSupertype(Class<? super T> superclass) {
-    checkArgument(superclass.isAssignableFrom(getRawType()),
+    checkArgument(this.someRawTypeIsSubclassOf(superclass),
         "%s is not a super class of %s", superclass, this);
     if (runtimeType instanceof TypeVariable) {
       return getSupertypeFromUpperBounds(superclass, ((TypeVariable<?>) runtimeType).getBounds());
@@ -401,26 +391,156 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
     if (runtimeType instanceof WildcardType) {
       return getSubtypeFromLowerBounds(subclass, ((WildcardType) runtimeType).getLowerBounds());
     }
-    checkArgument(getRawType().isAssignableFrom(subclass),
-        "%s isn't a subclass of %s", subclass, this);
     // unwrap array type if necessary
     if (isArray()) {
       return getArraySubtype(subclass);
     }
+    // At this point, it's either a raw class or parameterized type.
+    checkArgument(getRawType().isAssignableFrom(subclass),
+        "%s isn't a subclass of %s", subclass, this);
+    Type resolvedTypeArgs = resolveTypeArgsForSubclass(subclass);
     @SuppressWarnings("unchecked") // guarded by the isAssignableFrom() statement above
     TypeToken<? extends T> subtype = (TypeToken<? extends T>)
-        of(resolveTypeArgsForSubclass(subclass));
+        of(replaceTypeVariablesWithWildcard(resolvedTypeArgs, subclass));
     return subtype;
   }
 
-  /** Returns true if this type is assignable from the given {@code type}. */
+  private static final Type replaceTypeVariablesWithWildcard(
+      Type type, final Class<?> declaringClass) {
+    checkNotNull(declaringClass);
+    final AtomicReference<Type> result = new AtomicReference<Type>();
+    result.set(type);
+    new TypeVisitor() {
+      @Override void visitTypeVariable(TypeVariable<?> var) {
+        if (var.getGenericDeclaration() == declaringClass) {
+          result.set(Types.subtypeOf(Object.class));
+        }
+      }
+      @Override void visitParameterizedType(ParameterizedType pt) {
+        result.set(Types.newParameterizedTypeWithOwner(
+            // Replaces type vars on the owner type if it's owner type of declaringClass.
+            declaringClass.getEnclosingClass() == null
+                ? pt.getOwnerType()
+                : replaceTypeVariablesWithWildcard(
+                    pt.getOwnerType(), declaringClass.getEnclosingClass()),
+            (Class<?>) pt.getRawType(),
+            replaceTypeVariablesWithWildcard(pt.getActualTypeArguments(), declaringClass)));
+      }
+      @Override void visitWildcardType(WildcardType t) {}
+      @Override void visitGenericArrayType(GenericArrayType t) {}
+      @Override void visitClass(Class<?> t) {}
+    }.visit(type);
+    return result.get();
+  }
+
+  private static final Type[] replaceTypeVariablesWithWildcard(
+      Type[] types, Class<?> declaringClass) {
+    Type[] result = new Type[types.length];
+    for (int i = 0; i < types.length; i++) {
+      result[i] = replaceTypeVariablesWithWildcard(types[i], declaringClass);
+    }
+    return result;
+  }
+
+  /**
+   * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @deprecated Use the method under its new name, {@link #isSupertypeOf(TypeToken)}. This method
+   *     will be removed in Guava release 20.0.
+   */
+  @Deprecated
   public final boolean isAssignableFrom(TypeToken<?> type) {
-    return isAssignableFrom(type.runtimeType);
+    return isSupertypeOf(type);
   }
 
-  /** Check if this type is assignable from the given {@code type}. */
+  /**
+   * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @deprecated Use the method under its new name, {@link #isSupertypeOf(Type)}. This method will
+   *     be removed in Guava release 20.0.
+   */
+  @Deprecated
   public final boolean isAssignableFrom(Type type) {
-    return isAssignable(checkNotNull(type), runtimeType);
+    return isSupertypeOf(type);
+  }
+
+  /**
+   * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @since 19.0
+   */
+  public final boolean isSupertypeOf(TypeToken<?> type) {
+    return type.isSubtypeOf(getType());
+  }
+
+  /**
+   * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @since 19.0
+   */
+  public final boolean isSupertypeOf(Type type) {
+    return of(type).isSubtypeOf(getType());
+  }
+
+  /**
+   * Returns true if this type is a subtype of the given {@code type}. "Subtype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @since 19.0
+   */
+  public final boolean isSubtypeOf(TypeToken<?> type) {
+    return isSubtypeOf(type.getType());
+  }
+
+  /**
+   * Returns true if this type is a subtype of the given {@code type}. "Subtype" is defined
+   * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+   * >the rules for type arguments</a> introduced with Java generics.
+   *
+   * @since 19.0
+   */
+  public final boolean isSubtypeOf(Type supertype) {
+    checkNotNull(supertype);
+    if (supertype instanceof WildcardType) {
+      // if 'supertype' is <? super Foo>, 'this' can be:
+      // Foo, SubFoo, <? extends Foo>.
+      // if 'supertype' is <? extends Foo>, nothing is a subtype.
+      return any(((WildcardType) supertype).getLowerBounds()).isSupertypeOf(runtimeType);
+    }
+    // if 'this' is wildcard, it's a suptype of to 'supertype' if any of its "extends"
+    // bounds is a subtype of 'supertype'.
+    if (runtimeType instanceof WildcardType) {
+      // <? super Base> is of no use in checking 'from' being a subtype of 'to'.
+      return any(((WildcardType) runtimeType).getUpperBounds()).isSubtypeOf(supertype);
+    }
+    // if 'this' is type variable, it's a subtype if any of its "extends"
+    // bounds is a subtype of 'supertype'.
+    if (runtimeType instanceof TypeVariable) {
+      return runtimeType.equals(supertype)
+          || any(((TypeVariable<?>) runtimeType).getBounds()).isSubtypeOf(supertype);
+    }
+    if (runtimeType instanceof GenericArrayType) {
+      return of(supertype).isSuperTypeOfArray((GenericArrayType) runtimeType);
+    }
+    // Proceed to regular Type subtype check
+    if (supertype instanceof Class) {
+      return this.someRawTypeIsSubclassOf((Class<?>) supertype);
+    } else if (supertype instanceof ParameterizedType) {
+      return this.isSubtypeOfParameterizedType((ParameterizedType) supertype);
+    } else if (supertype instanceof GenericArrayType) {
+      return this.isSubTypeOfArrayType((GenericArrayType) supertype);
+    } else { // to instanceof TypeVariable
+      return false;
+    }
   }
 
   /**
@@ -450,7 +570,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
     if (isPrimitive()) {
       @SuppressWarnings("unchecked") // this is a primitive class
       Class<T> type = (Class<T>) runtimeType;
-      return TypeToken.of(Primitives.wrap(type));
+      return of(Primitives.wrap(type));
     }
     return this;
   }
@@ -469,7 +589,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
     if (isWrapper()) {
       @SuppressWarnings("unchecked") // this is a wrapper class
       Class<T> type = (Class<T>) runtimeType;
-      return TypeToken.of(Primitives.unwrap(type));
+      return of(Primitives.unwrap(type));
     }
     return this;
   }
@@ -492,7 +612,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
    * @since 14.0
    */
   public final Invokable<T, Object> method(Method method) {
-    checkArgument(of(method.getDeclaringClass()).isAssignableFrom(this),
+    checkArgument(this.someRawTypeIsSubclassOf(method.getDeclaringClass()),
         "%s not declared by %s", method, this);
     return new Invokable.MethodInvokable<T>(method) {
       @Override Type getGenericReturnType() {
@@ -580,7 +700,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
       // Java has no way to express ? super T when we parameterize TypeToken vs. Class.
       @SuppressWarnings({"unchecked", "rawtypes"})
       ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
-          TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes());
+          TypeCollector.FOR_RAW_TYPE.collectTypes(getRawTypes());
       return ImmutableSet.copyOf(collectedTypes);
     }
 
@@ -589,7 +709,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
 
   private final class InterfaceSet extends TypeSet {
 
-    private transient final TypeSet allTypes;
+    private final transient TypeSet allTypes;
     private transient ImmutableSet<TypeToken<? super T>> interfaces;
 
     InterfaceSet(TypeSet allTypes) {
@@ -615,7 +735,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
       // Java has no way to express ? super T when we parameterize TypeToken vs. Class.
       @SuppressWarnings({"unchecked", "rawtypes"})
       ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
-          TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes());
+          TypeCollector.FOR_RAW_TYPE.collectTypes(getRawTypes());
       return FluentIterable.from(collectedTypes)
           .filter(new Predicate<Class<?>>() {
             @Override public boolean apply(Class<?> type) {
@@ -662,7 +782,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
       // Java has no way to express ? super T when we parameterize TypeToken vs. Class.
       @SuppressWarnings({"unchecked", "rawtypes"})
       ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
-          TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(getImmediateRawTypes());
+          TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(getRawTypes());
       return ImmutableSet.copyOf(collectedTypes);
     }
 
@@ -743,183 +863,131 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
     return this;
   }
 
-  private static boolean isAssignable(Type from, Type to) {
-    if (to.equals(from)) {
-      return true;
-    }
-    if (to instanceof WildcardType) {
-      return isAssignableToWildcardType(from, (WildcardType) to);
-    }
-    // if "from" is type variable, it's assignable if any of its "extends"
-    // bounds is assignable to "to".
-    if (from instanceof TypeVariable) {
-      return isAssignableFromAny(((TypeVariable<?>) from).getBounds(), to);
-    }
-    // if "from" is wildcard, it'a assignable to "to" if any of its "extends"
-    // bounds is assignable to "to".
-    if (from instanceof WildcardType) {
-      return isAssignableFromAny(((WildcardType) from).getUpperBounds(), to);
-    }
-    if (from instanceof GenericArrayType) {
-      return isAssignableFromGenericArrayType((GenericArrayType) from, to);
-    }
-    // Proceed to regular Type assignability check
-    if (to instanceof Class) {
-      return isAssignableToClass(from, (Class<?>) to);
-    } else if (to instanceof ParameterizedType) {
-      return isAssignableToParameterizedType(from, (ParameterizedType) to);
-    } else if (to instanceof GenericArrayType) {
-      return isAssignableToGenericArrayType(from, (GenericArrayType) to);
-    } else { // to instanceof TypeVariable
-      return false;
-    }
-  }
-
-  private static boolean isAssignableFromAny(Type[] fromTypes, Type to) {
-    for (Type from : fromTypes) {
-      if (isAssignable(from, to)) {
+  private boolean someRawTypeIsSubclassOf(Class<?> superclass) {
+    for (Class<?> rawType : getRawTypes()) {
+      if (superclass.isAssignableFrom(rawType)) {
         return true;
       }
     }
     return false;
   }
 
-  private static boolean isAssignableToClass(Type from, Class<?> to) {
-    return to.isAssignableFrom(getRawType(from));
-  }
-
-  private static boolean isAssignableToWildcardType(
-      Type from, WildcardType to) {
-    // if "to" is <? extends Foo>, "from" can be:
-    // Foo, SubFoo, <? extends Foo>, <? extends SubFoo>, <T extends Foo> or
-    // <T extends SubFoo>.
-    // if "to" is <? super Foo>, "from" can be:
-    // Foo, SuperFoo, <? super Foo> or <? super SuperFoo>.
-    return isAssignable(from, supertypeBound(to)) && isAssignableBySubtypeBound(from, to);
-  }
-
-  private static boolean isAssignableBySubtypeBound(Type from, WildcardType to) {
-    Type toSubtypeBound = subtypeBound(to);
-    if (toSubtypeBound == null) {
-      return true;
-    }
-    Type fromSubtypeBound = subtypeBound(from);
-    if (fromSubtypeBound == null) {
-      return false;
-    }
-    return isAssignable(toSubtypeBound, fromSubtypeBound);
-  }
-
-  private static boolean isAssignableToParameterizedType(Type from, ParameterizedType to) {
-    Class<?> matchedClass = getRawType(to);
-    if (!matchedClass.isAssignableFrom(getRawType(from))) {
+  private boolean isSubtypeOfParameterizedType(ParameterizedType supertype) {
+    Class<?> matchedClass = of(supertype).getRawType();
+    if (!this.someRawTypeIsSubclassOf(matchedClass)) {
       return false;
     }
     Type[] typeParams = matchedClass.getTypeParameters();
-    Type[] toTypeArgs = to.getActualTypeArguments();
-    TypeToken<?> fromTypeToken = of(from);
+    Type[] toTypeArgs = supertype.getActualTypeArguments();
     for (int i = 0; i < typeParams.length; i++) {
-      // If "to" is "List<? extends CharSequence>"
-      // and "from" is StringArrayList,
+      // If 'supertype' is "List<? extends CharSequence>"
+      // and 'this' is StringArrayList,
       // First step is to figure out StringArrayList "is-a" List<E> and <E> is
       // String.
       // typeParams[0] is E and fromTypeToken.get(typeParams[0]) will resolve to
       // String.
       // String is then matched against <? extends CharSequence>.
-      Type fromTypeArg = fromTypeToken.resolveType(typeParams[i]).runtimeType;
-      if (!matchTypeArgument(fromTypeArg, toTypeArgs[i])) {
+      if (!resolveType(typeParams[i]).is(toTypeArgs[i])) {
         return false;
       }
     }
     return true;
   }
 
-  private static boolean isAssignableToGenericArrayType(Type from, GenericArrayType to) {
-    if (from instanceof Class) {
-      Class<?> fromClass = (Class<?>) from;
+  private boolean isSubTypeOfArrayType(GenericArrayType supertype) {
+    if (runtimeType instanceof Class) {
+      Class<?> fromClass = (Class<?>) runtimeType;
       if (!fromClass.isArray()) {
         return false;
       }
-      return isAssignable(fromClass.getComponentType(), to.getGenericComponentType());
-    } else if (from instanceof GenericArrayType) {
-      GenericArrayType fromArrayType = (GenericArrayType) from;
-      return isAssignable(fromArrayType.getGenericComponentType(), to.getGenericComponentType());
+      return of(fromClass.getComponentType()).isSubtypeOf(supertype.getGenericComponentType());
+    } else if (runtimeType instanceof GenericArrayType) {
+      GenericArrayType fromArrayType = (GenericArrayType) runtimeType;
+      return of(fromArrayType.getGenericComponentType())
+          .isSubtypeOf(supertype.getGenericComponentType());
     } else {
       return false;
     }
   }
 
-  private static boolean isAssignableFromGenericArrayType(GenericArrayType from, Type to) {
-    if (to instanceof Class) {
-      Class<?> toClass = (Class<?>) to;
-      if (!toClass.isArray()) {
-        return toClass == Object.class; // any T[] is assignable to Object
+  private boolean isSuperTypeOfArray(GenericArrayType subtype) {
+    if (runtimeType instanceof Class) {
+      Class<?> thisClass = (Class<?>) runtimeType;
+      if (!thisClass.isArray()) {
+        return thisClass.isAssignableFrom(Object[].class);
       }
-      return isAssignable(from.getGenericComponentType(), toClass.getComponentType());
-    } else if (to instanceof GenericArrayType) {
-      GenericArrayType toArrayType = (GenericArrayType) to;
-      return isAssignable(from.getGenericComponentType(), toArrayType.getGenericComponentType());
+      return of(subtype.getGenericComponentType()).isSubtypeOf(thisClass.getComponentType());
+    } else if (runtimeType instanceof GenericArrayType) {
+      return of(subtype.getGenericComponentType())
+          .isSubtypeOf(((GenericArrayType) runtimeType).getGenericComponentType());
     } else {
       return false;
     }
   }
 
-  private static boolean matchTypeArgument(Type from, Type to) {
-    if (from.equals(to)) {
+  /**
+   * Return true if any of the following conditions is met: <ul>
+   * <li>'this' and {@code formalType} are equal
+   * <li>{@code formalType} is {@code <? extends Foo>} and 'this' is a subtype of {@code Foo}
+   * <li>{@code formalType} is {@code <? super Foo>} and 'this' is a supertype of {@code Foo}
+   * </ul>
+   */
+  private boolean is(Type formalType) {
+    if (runtimeType.equals(formalType)) {
       return true;
     }
-    if (to instanceof WildcardType) {
-      return isAssignableToWildcardType(from, (WildcardType) to);
+    if (formalType instanceof WildcardType) {
+      // if "formalType" is <? extends Foo>, "this" can be:
+      // Foo, SubFoo, <? extends Foo>, <? extends SubFoo>, <T extends Foo> or
+      // <T extends SubFoo>.
+      // if "formalType" is <? super Foo>, "this" can be:
+      // Foo, SuperFoo, <? super Foo> or <? super SuperFoo>.
+      return every(((WildcardType) formalType).getUpperBounds()).isSupertypeOf(runtimeType)
+          && every(((WildcardType) formalType).getLowerBounds()).isSubtypeOf(runtimeType);
     }
     return false;
   }
 
-  private static Type supertypeBound(Type type) {
-    if (type instanceof WildcardType) {
-      return supertypeBound((WildcardType) type);
-    }
-    return type;
+  private static Bounds every(Type[] bounds) {
+    // Every bound must match. On any false, result is false.
+    return new Bounds(bounds, false);
   }
 
-  private static Type supertypeBound(WildcardType type) {
-    Type[] upperBounds = type.getUpperBounds();
-    if (upperBounds.length == 1) {
-      return supertypeBound(upperBounds[0]);
-    } else if (upperBounds.length == 0) {
-      return Object.class;
-    } else {
-      throw new AssertionError(
-          "There should be at most one upper bound for wildcard type: " + type);
-    }
+  private static Bounds any(Type[] bounds) {
+    // Any bound matches. On any true, result is true.
+    return new Bounds(bounds, true);
   }
 
-  @Nullable private static Type subtypeBound(Type type) {
-    if (type instanceof WildcardType) {
-      return subtypeBound((WildcardType) type);
-    } else {
-      return type;
+  private static class Bounds {
+    private final Type[] bounds;
+    private final boolean target;
+
+    Bounds(Type[] bounds, boolean target) {
+      this.bounds = bounds;
+      this.target = target;
     }
-  }
 
-  @Nullable private static Type subtypeBound(WildcardType type) {
-    Type[] lowerBounds = type.getLowerBounds();
-    if (lowerBounds.length == 1) {
-      return subtypeBound(lowerBounds[0]);
-    } else if (lowerBounds.length == 0) {
-      return null;
-    } else {
-      throw new AssertionError(
-          "Wildcard should have at most one lower bound: " + type);
+    boolean isSubtypeOf(Type supertype) {
+      for (Type bound : bounds) {
+        if (of(bound).isSubtypeOf(supertype) == target) {
+          return target;
+        }
+      }
+      return !target;
     }
-  }
 
-  @VisibleForTesting static Class<?> getRawType(Type type) {
-    // For wildcard or type variable, the first bound determines the runtime type.
-    return getRawTypes(type).iterator().next();
+    boolean isSupertypeOf(Type subtype) {
+      TypeToken<?> type = of(subtype);
+      for (Type bound : bounds) {
+        if (type.isSubtypeOf(bound) == target) {
+          return target;
+        }
+      }
+      return !target;
+    }
   }
 
-  @VisibleForTesting static ImmutableSet<Class<?>> getRawTypes(Type type) {
-    checkNotNull(type);
+  private ImmutableSet<Class<? super T>> getRawTypes() {
     final ImmutableSet.Builder<Class<?>> builder = ImmutableSet.builder();
     new TypeVisitor() {
       @Override void visitTypeVariable(TypeVariable<?> t) {
@@ -935,11 +1003,15 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
         builder.add(t);
       }
       @Override void visitGenericArrayType(GenericArrayType t) {
-        builder.add(Types.getArrayClass(getRawType(t.getGenericComponentType())));
+        builder.add(Types.getArrayClass(
+            of(t.getGenericComponentType()).getRawType()));
       }
 
-    }.visit(type);
-    return builder.build();
+    }.visit(runtimeType);
+    // Cast from ImmutableSet<Class<?>> to ImmutableSet<Class<? super T>>
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    ImmutableSet<Class<? super T>> result = (ImmutableSet) builder.build();
+    return result;
   }
 
   /**
@@ -959,10 +1031,13 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
       return result;
     }
     TypeVariable<Class<T>>[] typeParams = cls.getTypeParameters();
-    if (typeParams.length > 0) {
+    Type ownerType = cls.isMemberClass()
+        ? toGenericType(cls.getEnclosingClass()).runtimeType : null;
+
+    if ((typeParams.length > 0) || (ownerType != cls.getEnclosingClass())) {
       @SuppressWarnings("unchecked") // Like, it's Iterable<T> for Iterable.class
       TypeToken<? extends T> type = (TypeToken<? extends T>)
-          of(Types.newParameterizedType(cls, typeParams));
+          of(Types.newParameterizedTypeWithOwner(ownerType, cls, typeParams));
       return type;
     } else {
       return of(cls);
@@ -974,8 +1049,8 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
     for (Type upperBound : upperBounds) {
       @SuppressWarnings("unchecked") // T's upperbound is <? super T>.
       TypeToken<? super T> bound = (TypeToken<? super T>) of(upperBound);
-      if (of(supertype).isAssignableFrom(bound)) {
-        @SuppressWarnings({"rawtypes", "unchecked"}) // guarded by the isAssignableFrom check.
+      if (bound.isSubtypeOf(supertype)) {
+        @SuppressWarnings({"rawtypes", "unchecked"}) // guarded by the isSubtypeOf check.
         TypeToken<? super T> result = bound.getSupertype((Class) supertype);
         return result;
       }
diff --git a/guava/src/com/google/common/reflect/Types.java b/guava/src/com/google/common/reflect/Types.java
index d6c56e8..a86e5a2 100644
--- a/guava/src/com/google/common/reflect/Types.java
+++ b/guava/src/com/google/common/reflect/Types.java
@@ -26,6 +26,7 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
 import java.io.Serializable;
@@ -33,12 +34,15 @@ import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.lang.reflect.WildcardType;
+import java.security.AccessControlException;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.concurrent.atomic.AtomicReference;
@@ -149,7 +153,7 @@ final class Types {
    */
   static <D extends GenericDeclaration> TypeVariable<D> newArtificialTypeVariable(
       D declaration, String name, Type... bounds) {
-    return new TypeVariableImpl<D>(
+    return newTypeVariableImpl(
         declaration,
         name,
         (bounds.length == 0)
@@ -317,8 +321,76 @@ final class Types {
     private static final long serialVersionUID = 0;
   }
 
-  private static final class TypeVariableImpl<D extends GenericDeclaration>
-      implements TypeVariable<D> {
+  private static <D extends GenericDeclaration> TypeVariable<D> newTypeVariableImpl(
+      D genericDeclaration, String name, Type[] bounds) {
+    TypeVariableImpl<D> typeVariableImpl =
+        new TypeVariableImpl<D>(genericDeclaration, name, bounds);
+    @SuppressWarnings("unchecked")
+    TypeVariable<D> typeVariable = Reflection.newProxy(
+        TypeVariable.class, new TypeVariableInvocationHandler(typeVariableImpl));
+    return typeVariable;
+  }
+
+  /**
+   * Invocation handler to work around a compatibility problem between Java 7 and Java 8.
+   *
+   * <p>Java 8 introduced a new method {@code getAnnotatedBounds()} in the {@link TypeVariable}
+   * interface, whose return type {@code AnnotatedType[]} is also new in Java 8. That means that we
+   * cannot implement that interface in source code in a way that will compile on both Java 7 and
+   * Java 8. If we include the {@code getAnnotatedBounds()} method then its return type means
+   * it won't compile on Java 7, while if we don't include the method then the compiler will
+   * complain that an abstract method is unimplemented. So instead we use a dynamic proxy to
+   * get an implementation. If the method being called on the {@code TypeVariable} instance has
+   * the same name as one of the public methods of {@link TypeVariableImpl}, the proxy calls
+   * the same method on its instance of {@code TypeVariableImpl}. Otherwise it throws {@link
+   * UnsupportedOperationException}; this should only apply to {@code getAnnotatedBounds()}. This
+   * does mean that users on Java 8 who obtain an instance of {@code TypeVariable} from {@link
+   * TypeResolver#resolveType} will not be able to call {@code getAnnotatedBounds()} on it, but that
+   * should hopefully be rare.
+   *
+   * <p>This workaround should be removed at a distant future time when we no longer support Java
+   * versions earlier than 8.
+   */
+  private static final class TypeVariableInvocationHandler implements InvocationHandler {
+    private static final ImmutableMap<String, Method> typeVariableMethods;
+    static {
+      ImmutableMap.Builder<String, Method> builder = ImmutableMap.builder();
+      for (Method method : TypeVariableImpl.class.getMethods()) {
+        if (method.getDeclaringClass().equals(TypeVariableImpl.class)) {
+          try {
+            method.setAccessible(true);
+          } catch (AccessControlException e) {
+            // OK: the method is accessible to us anyway. The setAccessible call is only for
+            // unusual execution environments where that might not be true.
+          }
+          builder.put(method.getName(), method);
+        }
+      }
+      typeVariableMethods = builder.build();
+    }
+
+    private final TypeVariableImpl<?> typeVariableImpl;
+
+    TypeVariableInvocationHandler(TypeVariableImpl<?> typeVariableImpl) {
+      this.typeVariableImpl = typeVariableImpl;
+    }
+
+    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+      String methodName = method.getName();
+      Method typeVariableMethod = typeVariableMethods.get(methodName);
+      if (typeVariableMethod == null) {
+        throw new UnsupportedOperationException(methodName);
+      } else {
+        try {
+          return typeVariableMethod.invoke(typeVariableImpl, args);
+        } catch (InvocationTargetException e) {
+          throw e.getCause();
+        }
+      }
+    }
+  }
+
+  private static final class TypeVariableImpl<D extends GenericDeclaration> {
 
     private final D genericDeclaration;
     private final String name;
@@ -331,15 +403,19 @@ final class Types {
       this.bounds = ImmutableList.copyOf(bounds);
     }
 
-    @Override public Type[] getBounds() {
+    public Type[] getBounds() {
       return toArray(bounds);
     }
 
-    @Override public D getGenericDeclaration() {
+    public D getGenericDeclaration() {
       return genericDeclaration;
     }
 
-    @Override public String getName() {
+    public String getName() {
+      return name;
+    }
+
+    public String getTypeName() {
       return name;
     }
 
@@ -354,8 +430,12 @@ final class Types {
     @Override public boolean equals(Object obj) {
       if (NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
         // equal only to our TypeVariable implementation with identical bounds
-        if (obj instanceof TypeVariableImpl) {
-          TypeVariableImpl<?> that = (TypeVariableImpl<?>) obj;
+        if (obj != null
+            && Proxy.isProxyClass(obj.getClass())
+            && Proxy.getInvocationHandler(obj) instanceof TypeVariableInvocationHandler) {
+          TypeVariableInvocationHandler typeVariableInvocationHandler =
+              (TypeVariableInvocationHandler) Proxy.getInvocationHandler(obj);
+          TypeVariableImpl<?> that = typeVariableInvocationHandler.typeVariableImpl;
           return name.equals(that.getName())
               && genericDeclaration.equals(that.getGenericDeclaration())
               && bounds.equals(that.bounds);
diff --git a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
index aefe27f..68a36ca 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
@@ -18,7 +18,6 @@ package com.google.common.util.concurrent;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -54,7 +53,8 @@ public abstract class AbstractExecutionThreadService implements Service {
           try {
             startUp();
             notifyStarted();
-
+            // If stopAsync() is called while starting we may be in the STOPPING state in which
+            // case we should skip right down to shutdown.
             if (isRunning()) {
               try {
                 AbstractExecutionThreadService.this.run();
@@ -62,11 +62,14 @@ public abstract class AbstractExecutionThreadService implements Service {
                 try {
                   shutDown();
                 } catch (Exception ignored) {
+                  // TODO(lukes): if guava ever moves to java7, this would be a good candidate for
+                  // a suppressed exception, or maybe we could generalize Closer.Suppressor
                   logger.log(Level.WARNING, 
                       "Error while attempting to shut down the service"
                       + " after failure.", ignored);
                 }
-                throw t;
+                notifyFailed(t);
+                return;
               }
             }
 
@@ -74,7 +77,6 @@ public abstract class AbstractExecutionThreadService implements Service {
             notifyStopped();
           } catch (Throwable t) {
             notifyFailed(t);
-            throw Throwables.propagate(t);
           }
         }
       });
@@ -83,6 +85,10 @@ public abstract class AbstractExecutionThreadService implements Service {
     @Override protected void doStop() {
       triggerShutdown();
     }
+    
+    @Override public String toString() {
+      return AbstractExecutionThreadService.this.toString();
+    }
   };
 
   /**
diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
index 8f6bb0f..bd891e0 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractFuture.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
@@ -17,58 +17,286 @@
 package com.google.common.util.concurrent;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
 
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Throwables;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.locks.LockSupport;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.annotation.Nullable;
 
 /**
- * An abstract implementation of the {@link ListenableFuture} interface. This
- * class is preferable to {@link java.util.concurrent.FutureTask} for two
- * reasons: It implements {@code ListenableFuture}, and it does not implement
- * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code
- * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your
- * tasks to a {@link ListeningExecutorService}.)
- *
- * <p>This class implements all methods in {@code ListenableFuture}.
- * Subclasses should provide a way to set the result of the computation through
- * the protected methods {@link #set(Object)} and
- * {@link #setException(Throwable)}. Subclasses may also override {@link
- * #interruptTask()}, which will be invoked automatically if a call to {@link
- * #cancel(boolean) cancel(true)} succeeds in canceling the future.
- *
- * <p>{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal
- * with concurrency issues and guarantee thread safety.
- *
- * <p>The state changing methods all return a boolean indicating success or
- * failure in changing the future's state.  Valid states are running,
- * completed, failed, or cancelled.
+ * An abstract implementation of {@link ListenableFuture}, intended for advanced users only. More
+ * common ways to create a {@code ListenableFuture} include instantiating a {@link SettableFuture},
+ * submitting a task to a {@link ListeningExecutorService}, and deriving a {@code Future} from an
+ * existing one, typically using methods like {@link Futures#transform(ListenableFuture, Function)
+ * Futures.transform} and {@link Futures#catching(ListenableFuture, Class, Function)
+ * Futures.catching}.
  *
- * <p>This class uses an {@link ExecutionList} to guarantee that all registered
- * listeners will be executed, either when the future finishes or, for listeners
- * that are added after the future completes, immediately.
- * {@code Runnable}-{@code Executor} pairs are stored in the execution list but
- * are not necessarily executed in the order in which they were added.  (If a
- * listener is added after the Future is complete, it will be executed
- * immediately, even if earlier listeners have not been executed. Additionally,
- * executors need not guarantee FIFO execution, or different listeners may run
- * in different executors.)
+ * <p>This class implements all methods in {@code ListenableFuture}. Subclasses should provide a way
+ * to set the result of the computation through the protected methods {@link #set(Object)}, {@link
+ * #setFuture(ListenableFuture)} and {@link #setException(Throwable)}. Subclasses may also override
+ * {@link #interruptTask()}, which will be invoked automatically if a call to {@link
+ * #cancel(boolean) cancel(true)} succeeds in canceling the future. Subclasses should rarely
+ * override other methods.
  *
  * @author Sven Mawson
+ * @author Luke Sandberg
  * @since 1.0
  */
+ at GwtCompatible(emulated = true)
 public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+  private static final boolean GENERATE_CANCELLATION_CAUSES =
+      Boolean.parseBoolean(
+          System.getProperty("guava.concurrent.generate_cancellation_cause", "false"));
+
+  /**
+   * A less abstract subclass of AbstractFuture.  This can be used to optimize setFuture by ensuring
+   * that {@link #get} calls exactly the implementation of {@link AbstractFuture#get}.
+   */
+  abstract static class TrustedFuture<V> extends AbstractFuture<V> {
+    // N.B. cancel is not overridden to be final, because many future utilities need to override
+    // cancel in order to propagate cancellation to other futures.
+    // TODO(lukes): with maybePropagateCancellation this is no longer really true.  Track down the
+    // final few cases and eliminate their overrides of cancel()
+
+    @Override public final V get() throws InterruptedException, ExecutionException {
+      return super.get();
+    }
+
+    @Override public final V get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException {
+      return super.get(timeout, unit);
+    }
+
+    @Override public final boolean isDone() {
+      return super.isDone();
+    }
+
+    @Override public final boolean isCancelled() {
+      return super.isCancelled();
+    }
+
+    @Override public final void addListener(Runnable listener, Executor executor) {
+      super.addListener(listener, executor);
+    }
+  }
+
+  // Logger to log exceptions caught when running listeners.
+  private static final Logger log = Logger.getLogger(AbstractFuture.class.getName());
+
+  // A heuristic for timed gets.  If the remaining timeout is less than this, spin instead of
+  // blocking.  This value is what AbstractQueuedSynchronizer uses.
+  private static final long SPIN_THRESHOLD_NANOS = 1000L;
+
+  private static final AtomicHelper ATOMIC_HELPER;
+
+  static {
+    AtomicHelper helper;
+
+    try {
+      helper = new UnsafeAtomicHelper();
+    } catch (Throwable unsafeFailure) {
+      // catch absolutely everything and fall through to our 'SafeAtomicHelper'
+      // The access control checks that ARFU does means the caller class has to be AbstractFuture
+      // instead of SafeAtomicHelper, so we annoyingly define these here
+      try {
+        helper = new SafeAtomicHelper(
+            newUpdater(Waiter.class, Thread.class, "thread"),
+            newUpdater(Waiter.class, Waiter.class, "next"),
+            newUpdater(AbstractFuture.class, Waiter.class, "waiters"),
+            newUpdater(AbstractFuture.class, Listener.class, "listeners"),
+            newUpdater(AbstractFuture.class, Object.class, "value"));
+      } catch (Throwable atomicReferenceFieldUpdaterFailure) {
+        // Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause
+        // getDeclaredField to throw a NoSuchFieldException when the field is definitely there.
+        // For these users fallback to a suboptimal implementation, based on synchronized.  This
+        // will be a definite performance hit to those users.
+        log.log(Level.SEVERE, "UnsafeAtomicHelper is broken!", unsafeFailure);
+        log.log(Level.SEVERE, "SafeAtomicHelper is broken!", atomicReferenceFieldUpdaterFailure);
+        helper = new SynchronizedHelper();
+      }
+    }
+    ATOMIC_HELPER = helper;
+
+    // Prevent rare disastrous classloading in first call to LockSupport.park.
+    // See: https://bugs.openjdk.java.net/browse/JDK-8074773
+    @SuppressWarnings("unused")
+    Class<?> ensureLoaded = LockSupport.class;
+  }
+
+  /**
+   * Waiter links form a Treiber stack, in the {@link #waiters} field.
+   */
+  private static final class Waiter {
+    static final Waiter TOMBSTONE = new Waiter(false /* ignored param */);
+
+    @Nullable volatile Thread thread;
+    @Nullable volatile Waiter next;
+
+    // Constructor for the TOMBSTONE, avoids use of ATOMIC_HELPER in case this class is loaded
+    // before the ATOMIC_HELPER.  Apparently this is possible on some android platforms.
+    Waiter(boolean unused) {}
+
+    Waiter() {
+      // avoid volatile write, write is made visible by subsequent CAS on waiters field
+      ATOMIC_HELPER.putThread(this, Thread.currentThread());
+    }
+
+    // non-volatile write to the next field. Should be made visible by subsequent CAS on waiters
+    // field.
+    void setNext(Waiter next) {
+      ATOMIC_HELPER.putNext(this, next);
+    }
+
+    void unpark() {
+      // This is racy with removeWaiter.  The consequence of the race is that we may spuriously
+      // call unpark even though the thread has already removed itself from the list.  But even if
+      // we did use a CAS, that race would still exist (it would just be ever so slightly smaller).
+      Thread w = thread;
+      if (w != null) {
+        thread = null;
+        LockSupport.unpark(w);
+      }
+    }
+  }
+
+  /**
+   * Marks the given node as 'deleted' (null waiter) and then scans the list to unlink all deleted
+   * nodes.  This is an O(n) operation in the common case (and O(n^2) in the worst), but we are
+   * saved by two things.
+   * <ul>
+   *   <li>This is only called when a waiting thread times out or is interrupted.  Both of which
+   *       should be rare.
+   *   <li>The waiters list should be very short.
+   * </ul>
+   */
+  private void removeWaiter(Waiter node) {
+    node.thread = null;  // mark as 'deleted'
+    restart: while (true) {
+      Waiter pred = null;
+      Waiter curr = waiters;
+      if (curr == Waiter.TOMBSTONE) {
+        return;  // give up if someone is calling complete
+      }
+      Waiter succ;
+      while (curr != null) {
+        succ = curr.next;
+        if (curr.thread != null) {  // we aren't unlinking this node, update pred.
+          pred = curr;
+        } else if (pred != null) { // We are unlinking this node and it has a predecessor.
+          pred.next = succ;
+          if (pred.thread == null) {  // We raced with another node that unlinked pred. Restart.
+            continue restart;
+          }
+        } else if (!ATOMIC_HELPER.casWaiters(this, curr, succ)) {  // We are unlinking head
+          continue restart;  // We raced with an add or complete
+        }
+        curr = succ;
+      }
+      break;
+    }
+  }
+
+  /** Listeners also form a stack through the {@link #listeners} field. */
+  private static final class Listener {
+    static final Listener TOMBSTONE = new Listener(null, null);
+    final Runnable task;
+    final Executor executor;
+
+    // writes to next are made visible by subsequent CAS's on the listeners field
+    @Nullable Listener next;
+
+    Listener(Runnable task, Executor executor) {
+      this.task = task;
+      this.executor = executor;
+    }
+  }
+
+  /** A special value to represent {@code null}. */
+  private static final Object NULL = new Object();
+
+  /** A special value to represent failure, when {@link #setException} is called successfully. */
+  private static final class Failure {
+    static final Failure FALLBACK_INSTANCE = new Failure(
+        new Throwable("Failure occurred while trying to finish a future.") {
+          @Override public synchronized Throwable fillInStackTrace() {
+            return this;  // no stack trace
+          }
+        });
+    final Throwable exception;
 
-  /** Synchronization control for AbstractFutures. */
-  private final Sync<V> sync = new Sync<V>();
+    Failure(Throwable exception) {
+      this.exception = checkNotNull(exception);
+    }
+  }
+
+  /** A special value to represent cancellation and the 'wasInterrupted' bit. */
+  private static final class Cancellation {
+    final boolean wasInterrupted;
+    @Nullable final Throwable cause;
+
+    Cancellation(boolean wasInterrupted, @Nullable Throwable cause) {
+      this.wasInterrupted = wasInterrupted;
+      this.cause = cause;
+    }
+  }
+
+  /** A special value that encodes the 'setFuture' state. */
+  private final class SetFuture implements Runnable {
+    final ListenableFuture<? extends V> future;
+
+    SetFuture(ListenableFuture<? extends V> future) {
+      this.future = future;
+    }
+
+    @Override public void run() {
+      if (value != this) {
+        // nothing to do, we must have been cancelled
+        return;
+      }
+      completeWithFuture(future, this);
+    }
+  }
+
+  // TODO(lukes): investigate using the @Contended annotation on these fields when jdk8 is
+  // available.
+  /**
+   * This field encodes the current state of the future.
+   *
+   * <p>The valid values are:
+   * <ul>
+   *   <li>{@code null} initial state, nothing has happened.
+   *   <li>{@link Cancellation} terminal state, {@code cancel} was called.
+   *   <li>{@link Failure} terminal state, {@code setException} was called.
+   *   <li>{@link SetFuture} intermediate state, {@code setFuture} was called.
+   *   <li>{@link #NULL} terminal state, {@code set(null)} was called.
+   *   <li>Any other non-null value, terminal state, {@code set} was called with a non-null
+   *       argument.
+   * </ul>
+   */
+  private volatile Object value;
+
+  /** All listeners. */
+  private volatile Listener listeners;
 
-  // The execution list to hold our executors.
-  private final ExecutionList executionList = new ExecutionList();
+  /** All waiting threads. */
+  private volatile Waiter waiters;
 
   /**
    * Constructor for use by subclasses.
@@ -79,6 +307,31 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
    * Improve the documentation of when InterruptedException is thrown. Our
    * behavior matches the JDK's, but the JDK's documentation is misleading.
    */
+
+  // Gets and Timed Gets
+  //
+  // * Be responsive to interruption
+  // * Don't create Waiter nodes if you aren't going to park, this helps reduce contention on the
+  //   waiters field.
+  // * Future completion is defined by when #value becomes non-null/non SetFuture
+  // * Future completion can be observed if the waiters field contains a TOMBSTONE
+
+  // Timed Get
+  // There are a few design constraints to consider
+  // * We want to be responsive to small timeouts, unpark() has non trivial latency overheads (I
+  //   have observed 12 micros on 64 bit linux systems to wake up a parked thread).  So if the
+  //   timeout is small we shouldn't park().  This needs to be traded off with the cpu overhead of
+  //   spinning, so we use SPIN_THRESHOLD_NANOS which is what AbstractQueuedSynchronizer uses for
+  //   similar purposes.
+  // * We want to behave reasonably for timeouts of 0
+  // * We are more responsive to completion than timeouts.  This is because parkNanos depends on
+  //   system scheduling and as such we could either miss our deadline, or unpark() could be delayed
+  //   so that it looks like we timed out even though we didn't.  For comparison FutureTask respects
+  //   completion preferably and AQS is non-deterministic (depends on where in the queue the waiter
+  //   is).  If we wanted to be strict about it, we could store the unpark() time in the Waiter
+  //   node and we could use that to make a decision about whether or not we timed out prior to
+  //   being unparked.
+
   /**
    * {@inheritDoc}
    *
@@ -91,9 +344,71 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
    * @throws CancellationException {@inheritDoc}
    */
   @Override
-  public V get(long timeout, TimeUnit unit) throws InterruptedException,
-      TimeoutException, ExecutionException {
-    return sync.get(unit.toNanos(timeout));
+  public V get(long timeout, TimeUnit unit)
+      throws InterruptedException, TimeoutException, ExecutionException {
+    // NOTE: if timeout < 0, remainingNanos will be < 0 and we will fall into the while(true) loop
+    // at the bottom and throw a timeoutexception.
+    long remainingNanos = unit.toNanos(timeout); // we rely on the implicit null check on unit.
+    if (Thread.interrupted()) {
+      throw new InterruptedException();
+    }
+    Object localValue = value;
+    if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+      return getDoneValue(localValue);
+    }
+    // we delay calling nanoTime until we know we will need to either park or spin
+    final long endNanos = remainingNanos > 0 ? System.nanoTime() + remainingNanos : 0;
+    long_wait_loop: if (remainingNanos >= SPIN_THRESHOLD_NANOS) {
+      Waiter oldHead = waiters;
+      if (oldHead != Waiter.TOMBSTONE) {
+        Waiter node = new Waiter();
+        do {
+          node.setNext(oldHead);
+          if (ATOMIC_HELPER.casWaiters(this, oldHead, node)) {
+            while (true) {
+              LockSupport.parkNanos(this, remainingNanos);
+              // Check interruption first, if we woke up due to interruption we need to honor that.
+              if (Thread.interrupted()) {
+                removeWaiter(node);
+                throw new InterruptedException();
+              }
+
+              // Otherwise re-read and check doneness.  If we loop then it must have been a spurious
+              // wakeup
+              localValue = value;
+              if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+                return getDoneValue(localValue);
+              }
+
+              // timed out?
+              remainingNanos = endNanos - System.nanoTime();
+              if (remainingNanos < SPIN_THRESHOLD_NANOS) {
+                // Remove the waiter, one way or another we are done parking this thread.
+                removeWaiter(node);
+                break long_wait_loop;  // jump down to the busy wait loop
+              }
+            }
+          }
+          oldHead = waiters;  // re-read and loop.
+        } while (oldHead != Waiter.TOMBSTONE);
+      }
+      // re-read value, if we get here then we must have observed a TOMBSTONE while trying to add a
+      // waiter.
+      return getDoneValue(value);
+    }
+    // If we get here then we have remainingNanos < SPIN_THRESHOLD_NANOS and there is no node on the
+    // waiters list
+    while (remainingNanos > 0) {
+      localValue = value;
+      if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+        return getDoneValue(localValue);
+      }
+      if (Thread.interrupted()) {
+        throw new InterruptedException();
+      }
+      remainingNanos = endNanos - System.nanoTime();
+    }
+    throw new TimeoutException();
   }
 
   /*
@@ -111,31 +426,125 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
    *     or during the call (optional but recommended).
    * @throws CancellationException {@inheritDoc}
    */
-  @Override
-  public V get() throws InterruptedException, ExecutionException {
-    return sync.get();
+  @Override public V get() throws InterruptedException, ExecutionException {
+    if (Thread.interrupted()) {
+      throw new InterruptedException();
+    }
+    Object localValue = value;
+    if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+      return getDoneValue(localValue);
+    }
+    Waiter oldHead = waiters;
+    if (oldHead != Waiter.TOMBSTONE) {
+      Waiter node = new Waiter();
+      do {
+        node.setNext(oldHead);
+        if (ATOMIC_HELPER.casWaiters(this, oldHead, node)) {
+          // we are on the stack, now wait for completion.
+          while (true) {
+            LockSupport.park(this);
+            // Check interruption first, if we woke up due to interruption we need to honor that.
+            if (Thread.interrupted()) {
+              removeWaiter(node);
+              throw new InterruptedException();
+            }
+            // Otherwise re-read and check doneness.  If we loop then it must have been a spurious
+            // wakeup
+            localValue = value;
+            if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+              return getDoneValue(localValue);
+            }
+          }
+        }
+        oldHead = waiters;  // re-read and loop.
+      } while (oldHead != Waiter.TOMBSTONE);
+    }
+    // re-read value, if we get here then we must have observed a TOMBSTONE while trying to add a
+    // waiter.
+    return getDoneValue(value);
+  }
+
+  /**
+   * Unboxes {@code obj}.  Assumes that obj is not {@code null} or a {@link SetFuture}.
+   */
+  private V getDoneValue(Object obj) throws ExecutionException {
+    // While this seems like it might be too branch-y, simple benchmarking proves it to be
+    // unmeasurable (comparing done AbstractFutures with immediateFuture)
+    if (obj instanceof Cancellation) {
+      throw cancellationExceptionWithCause("Task was cancelled.", ((Cancellation) obj).cause);
+    } else if (obj instanceof Failure) {
+      throw new ExecutionException(((Failure) obj).exception);
+    } else if (obj == NULL) {
+      return null;
+    } else {
+      @SuppressWarnings("unchecked")  // this is the only other option
+      V asV = (V) obj;
+      return asV;
+    }
   }
 
   @Override
   public boolean isDone() {
-    return sync.isDone();
+    final Object localValue = value;
+    return localValue != null & !(localValue instanceof AbstractFuture.SetFuture);
   }
 
   @Override
   public boolean isCancelled() {
-    return sync.isCancelled();
+    final Object localValue = value;
+    return localValue instanceof Cancellation;
   }
 
+  /**
+   * {@inheritDoc}
+   *
+   * <p>If a cancellation attempt succeeds on a {@code Future} that had previously been {@linkplain
+   * #setFuture set asynchronously}, then the cancellation will also be propagated to the delegate
+   * {@code Future} that was supplied in the {@code setFuture} call.
+   */
   @Override
   public boolean cancel(boolean mayInterruptIfRunning) {
-    if (!sync.cancel(mayInterruptIfRunning)) {
-      return false;
-    }
-    executionList.execute();
-    if (mayInterruptIfRunning) {
-      interruptTask();
+    Object localValue = value;
+    if (localValue == null | localValue instanceof AbstractFuture.SetFuture) {
+      // Try to delay allocating the exception.  At this point we may still lose the CAS, but it is
+      // certainly less likely.
+      // TODO(lukes): this exception actually makes cancellation significantly more expensive :(
+      // I wonder if we should consider removing it or providing a mechanism to not do it.
+      Throwable cause = GENERATE_CANCELLATION_CAUSES ? newCancellationCause() : null;
+      Object valueToSet = new Cancellation(mayInterruptIfRunning, cause);
+      do {
+        if (ATOMIC_HELPER.casValue(this, localValue, valueToSet)) {
+          // We call interuptTask before calling complete(), first which is consistent with
+          // FutureTask
+          if (mayInterruptIfRunning) {
+            interruptTask();
+          }
+          complete();
+          if (localValue instanceof AbstractFuture.SetFuture) {
+            // propagate cancellation to the future set in setfuture, this is racy, and we don't
+            // care if we are successful or not.
+            ((AbstractFuture<?>.SetFuture) localValue).future.cancel(mayInterruptIfRunning);
+          }
+          return true;
+        }
+        // obj changed, reread
+        localValue = value;
+        // obj cannot be null at this point, because value can only change from null to non-null. So
+        // if value changed (and it did since we lost the CAS), then it cannot be null.
+      } while (localValue instanceof AbstractFuture.SetFuture);
     }
-    return true;
+    return false;
+  }
+
+  /**
+   * Returns an exception to be used as the cause of the CancellationException thrown by
+   * {@link #get}.
+   *
+   * <p>Note: this method may be called speculatively.  There is no guarantee that the future will
+   * be cancelled if this method is called.
+   */
+  private Throwable newCancellationCause() {
+    return new CancellationException("Future.cancel() was called.");
   }
 
   /**
@@ -157,7 +566,8 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
    * @since 14.0
    */
   protected final boolean wasInterrupted() {
-    return sync.wasInterrupted();
+    final Object localValue = value;
+    return (localValue instanceof Cancellation) && ((Cancellation) localValue).wasInterrupted;
   }
 
   /**
@@ -166,231 +576,453 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
    * @since 10.0
    */
   @Override
-  public void addListener(Runnable listener, Executor exec) {
-    executionList.add(listener, exec);
+  public void addListener(Runnable listener, Executor executor) {
+    checkNotNull(listener, "Runnable was null.");
+    checkNotNull(executor, "Executor was null.");
+    Listener oldHead = listeners;
+    if (oldHead != Listener.TOMBSTONE) {
+      Listener newNode = new Listener(listener, executor);
+      do {
+        newNode.next = oldHead;
+        if (ATOMIC_HELPER.casListeners(this, oldHead, newNode)) {
+          return;
+        }
+        oldHead = listeners;  // re-read
+      } while (oldHead != Listener.TOMBSTONE);
+    }
+    // If we get here then the Listener TOMBSTONE was set, which means the future is done, call
+    // the listener.
+    executeListener(listener, executor);
   }
 
   /**
-   * Subclasses should invoke this method to set the result of the computation
-   * to {@code value}.  This will set the state of the future to
-   * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
-   * state was successfully changed.
+   * Sets the result of this {@code Future} unless this {@code Future} has already been cancelled or
+   * set (including {@linkplain #setFuture set asynchronously}). When a call to this method returns,
+   * the {@code Future} is guaranteed to be {@linkplain #isDone done} <b>only if</b> the call was
+   * accepted (in which case it returns {@code true}). If it returns {@code false}, the {@code
+   * Future} may have previously been set asynchronously, in which case its result may not be known
+   * yet. That result, though not yet known, cannot by overridden by a call to a {@code set*}
+   * method, only by a call to {@link #cancel}.
    *
-   * @param value the value that was the result of the task.
-   * @return true if the state was successfully changed.
+   * @param value the value to be used as the result
+   * @return true if the attempt was accepted, completing the {@code Future}
    */
   protected boolean set(@Nullable V value) {
-    boolean result = sync.set(value);
-    if (result) {
-      executionList.execute();
+    Object valueToSet = value == null ? NULL : value;
+    if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+      complete();
+      return true;
     }
-    return result;
+    return false;
   }
 
   /**
-   * Subclasses should invoke this method to set the result of the computation
-   * to an error, {@code throwable}.  This will set the state of the future to
-   * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
-   * state was successfully changed.
+   * Sets the failed result of this {@code Future} unless this {@code Future} has already been
+   * cancelled or set (including {@linkplain #setFuture set asynchronously}). When a call to this
+   * method returns, the {@code Future} is guaranteed to be {@linkplain #isDone done} <b>only if</b>
+   * the call was accepted (in which case it returns {@code true}). If it returns {@code false}, the
+   * {@code Future} may have previously been set asynchronously, in which case its result may not be
+   * known yet. That result, though not yet known, cannot by overridden by a call to a {@code set*}
+   * method, only by a call to {@link #cancel}.
    *
-   * @param throwable the exception that the task failed with.
-   * @return true if the state was successfully changed.
+   * @param throwable the exception to be used as the failed result
+   * @return true if the attempt was accepted, completing the {@code Future}
    */
   protected boolean setException(Throwable throwable) {
-    boolean result = sync.setException(checkNotNull(throwable));
-    if (result) {
-      executionList.execute();
+    Object valueToSet = new Failure(checkNotNull(throwable));
+    if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+      complete();
+      return true;
     }
-    return result;
+    return false;
   }
 
   /**
-   * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a
-   * private subclass to hold the synchronizer.  This synchronizer is used to
-   * implement the blocking and waiting calls as well as to handle state changes
-   * in a thread-safe manner.  The current state of the future is held in the
-   * Sync state, and the lock is released whenever the state changes to
-   * {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}
+   * Sets the result of this {@code Future} to match the supplied input {@code Future} once the
+   * supplied {@code Future} is done, unless this {@code Future} has already been cancelled or set
+   * (including "set asynchronously," defined below).
    *
-   * <p>To avoid races between threads doing release and acquire, we transition
-   * to the final state in two steps.  One thread will successfully CAS from
-   * RUNNING to COMPLETING, that thread will then set the result of the
-   * computation, and only then transition to COMPLETED, CANCELLED, or
-   * INTERRUPTED.
+   * <p>If the supplied future is {@linkplain #isDone done} when this method is called and the call
+   * is accepted, then this future is guaranteed to have been completed with the supplied future by
+   * the time this method returns. If the supplied future is not done and the call is accepted, then
+   * the future will be <i>set asynchronously</i>. Note that such a result, though not yet known,
+   * cannot by overridden by a call to a {@code set*} method, only by a call to {@link #cancel}.
    *
-   * <p>We don't use the integer argument passed between acquire methods so we
-   * pass around a -1 everywhere.
+   * <p>If the call {@code setFuture(delegate)} is accepted and this {@code Future} is later
+   * cancelled, cancellation will be propagated to {@code delegate}. Additionally, any call to
+   * {@code setFuture} after any cancellation will propagate cancellation to the supplied {@code
+   * Future}.
+   *
+   * @param future the future to delegate to
+   * @return true if the attempt was accepted, indicating that the {@code Future} was not previously
+   *     cancelled or set.
+   * @since 19.0
+   */
+  @Beta protected boolean setFuture(ListenableFuture<? extends V> future) {
+    checkNotNull(future);
+    Object localValue = value;
+    if (localValue == null) {
+      if (future.isDone()) {
+        return completeWithFuture(future, null);
+      }
+      SetFuture valueToSet = new SetFuture(future);
+      if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+        // the listener is responsible for calling completeWithFuture, directExecutor is appropriate
+        // since all we are doing is unpacking a completed future which should be fast.
+        try {
+          future.addListener(valueToSet, directExecutor());
+        } catch (Throwable t) {
+          // addListener has thrown an exception!  SetFuture.run can't throw any exceptions so this
+          // must have been caused by addListener itself.  The most likely explanation is a
+          // misconfigured mock.  Try to switch to Failure.
+          Failure failure;
+          try {
+            failure = new Failure(t);
+          } catch (Throwable oomMostLikely) {
+            failure = Failure.FALLBACK_INSTANCE;
+          }
+          // Note: The only way this CAS could fail is if cancel() has raced with us. That is ok.
+          ATOMIC_HELPER.casValue(this, valueToSet, failure);
+        }
+        return true;
+      }
+      localValue = value;  // we lost the cas, fall through and maybe cancel
+    }
+    // The future has already been set to something.  If it is cancellation we should cancel the
+    // incoming future.
+    if (localValue instanceof Cancellation) {
+      // we don't care if it fails, this is best-effort.
+      future.cancel(((Cancellation) localValue).wasInterrupted);
+    }
+    return false;
+  }
+
+  /**
+   * Called when a future passed via setFuture has completed.
+   *
+   * @param future the done future to complete this future with.
+   * @param expected the expected value of the {@link #value} field.
    */
-  static final class Sync<V> extends AbstractQueuedSynchronizer {
+  private boolean completeWithFuture(ListenableFuture<? extends V> future, Object expected) {
+    Object valueToSet;
+    if (future instanceof TrustedFuture) {
+      // Break encapsulation for TrustedFuture instances since we know that subclasses cannot
+      // override .get() (since it is final) and therefore this is equivalent to calling .get()
+      // and unpacking the exceptions like we do below (just much faster because it is a single
+      // field read instead of a read, several branches and possibly creating exceptions).
+      valueToSet = ((AbstractFuture<?>) future).value;
+    } else {
+      // Otherwise calculate valueToSet by calling .get()
+      try {
+        V v = Uninterruptibles.getUninterruptibly(future);
+        valueToSet = v == null ? NULL : v;
+      } catch (ExecutionException exception) {
+        valueToSet = new Failure(exception.getCause());
+      } catch (CancellationException cancellation) {
+        valueToSet = new Cancellation(false, cancellation);
+      } catch (Throwable t) {
+        valueToSet = new Failure(t);
+      }
+    }
+    // The only way this can fail is if we raced with another thread calling cancel(). If we lost
+    // that race then there is nothing to do.
+    if (ATOMIC_HELPER.casValue(AbstractFuture.this, expected, valueToSet)) {
+      complete();
+      return true;
+    }
+    return false;
+  }
 
-    private static final long serialVersionUID = 0L;
+  /** Unblocks all threads and runs all listeners. */
+  private void complete() {
+    for (Waiter currentWaiter = clearWaiters();
+        currentWaiter != null;
+        currentWaiter = currentWaiter.next) {
+      currentWaiter.unpark();
+    }
+    // We need to reverse the list to handle buggy listeners that depend on ordering.
+    Listener currentListener = clearListeners();
+    Listener reversedList = null;
+    while (currentListener != null) {
+      Listener tmp = currentListener;
+      currentListener = currentListener.next;
+      tmp.next = reversedList;
+      reversedList = tmp;
+    }
+    for (; reversedList != null; reversedList = reversedList.next) {
+      executeListener(reversedList.task, reversedList.executor);
+    }
+    // We call this after the listeners on the theory that done() will only be used for 'cleanup'
+    // oriented tasks (e.g. clearing fields) and so can wait behind listeners which may be executing
+    // more important work.  A counter argument would be that done() is trusted code and therefore
+    // it would be safe to run before potentially slow or poorly behaved listeners.  Reevaluate this
+    // once we have more examples of done() implementations.
+    done();
+  }
 
-    /* Valid states. */
-    static final int RUNNING = 0;
-    static final int COMPLETING = 1;
-    static final int COMPLETED = 2;
-    static final int CANCELLED = 4;
-    static final int INTERRUPTED = 8;
+  /**
+   * Callback method that is called immediately after the future is completed.
+   *
+   * <p>This is called exactly once, after all listeners have executed.  By default it does nothing.
+   */
+  void done() {}
 
-    private V value;
-    private Throwable exception;
+  /**
+   * Returns the exception that this {@code Future} completed with. This includes completion through
+   * a call to {@link setException} or {@link setFuture}{@code (failedFuture)} but not cancellation.
+   *
+   * @throws RuntimeException if the {@code Future} has not failed
+   */
+  final Throwable trustedGetException() {
+    return ((Failure) value).exception;
+  }
 
-    /*
-     * Acquisition succeeds if the future is done, otherwise it fails.
-     */
-    @Override
-    protected int tryAcquireShared(int ignored) {
-      if (isDone()) {
-        return 1;
+  /**
+   * If this future has been cancelled (and possibly interrupted), cancels (and possibly interrupts)
+   * the given future (if available).
+   *
+   * <p>This method should be used only when this future is completed. It is designed to be called
+   * from {@code done}.
+   */
+  final void maybePropagateCancellation(@Nullable Future<?> related) {
+    if (related != null & isCancelled()) {
+      related.cancel(wasInterrupted());
+    }
+  }
+
+  /** Clears the {@link #waiters} list and returns the most recently added value. */
+  private Waiter clearWaiters() {
+    Waiter head;
+    do {
+      head = waiters;
+    } while (!ATOMIC_HELPER.casWaiters(this, head, Waiter.TOMBSTONE));
+    return head;
+  }
+
+  /** Clears the {@link #listeners} list and returns the most recently added value. */
+  private Listener clearListeners() {
+    Listener head;
+    do {
+      head = listeners;
+    } while (!ATOMIC_HELPER.casListeners(this, head, Listener.TOMBSTONE));
+    return head;
+  }
+
+  /**
+   * Submits the given runnable to the given {@link Executor} catching and logging all
+   * {@linkplain RuntimeException runtime exceptions} thrown by the executor.
+   */
+  private static void executeListener(Runnable runnable, Executor executor) {
+    try {
+      executor.execute(runnable);
+    } catch (RuntimeException e) {
+      // Log it and keep going, bad runnable and/or executor.  Don't
+      // punish the other runnables if we're given a bad one.  We only
+      // catch RuntimeException because we want Errors to propagate up.
+      log.log(Level.SEVERE, "RuntimeException while executing runnable "
+          + runnable + " with executor " + executor, e);
+    }
+  }
+
+  static final CancellationException cancellationExceptionWithCause(
+      @Nullable String message, @Nullable Throwable cause) {
+    CancellationException exception = new CancellationException(message);
+    exception.initCause(cause);
+    return exception;
+  }
+
+  private abstract static class AtomicHelper {
+    /** Non volatile write of the thread to the {@link Waiter#thread} field. */
+    abstract void putThread(Waiter waiter, Thread newValue);
+
+    /** Non volatile write of the waiter to the {@link Waiter#next} field. */
+    abstract void putNext(Waiter waiter, Waiter newValue);
+
+    /** Performs a CAS operation on the {@link #waiters} field. */
+    abstract boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update);
+
+    /** Performs a CAS operation on the {@link #listeners} field. */
+    abstract boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update);
+
+    /** Performs a CAS operation on the {@link #value} field. */
+    abstract boolean casValue(AbstractFuture<?> future, Object expect, Object update);
+  }
+
+  /**
+   * {@link AtomicHelper} based on {@link sun.misc.Unsafe}.
+   *
+   * <p>Static initialization of this class will fail if the {@link sun.misc.Unsafe} object cannot
+   * be accessed.
+   */
+  private static final class UnsafeAtomicHelper extends AtomicHelper {
+    static final sun.misc.Unsafe UNSAFE;
+    static final long LISTENERS_OFFSET;
+    static final long WAITERS_OFFSET;
+    static final long VALUE_OFFSET;
+    static final long WAITER_THREAD_OFFSET;
+    static final long WAITER_NEXT_OFFSET;
+
+    static {
+      sun.misc.Unsafe unsafe = null;
+      try {
+        unsafe = sun.misc.Unsafe.getUnsafe();
+      } catch (SecurityException tryReflectionInstead) {
+        try {
+          unsafe = AccessController.doPrivileged(
+              new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+                @Override public sun.misc.Unsafe run() throws Exception {
+                  Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+                  for (java.lang.reflect.Field f : k.getDeclaredFields()) {
+                    f.setAccessible(true);
+                    Object x = f.get(null);
+                    if (k.isInstance(x)) {
+                      return k.cast(x);
+                    }
+                  }
+                  throw new NoSuchFieldError("the Unsafe");
+                }
+              });
+        } catch (PrivilegedActionException e) {
+          throw new RuntimeException("Could not initialize intrinsics", e.getCause());
+        }
+      }
+      try {
+        Class<?> abstractFuture = AbstractFuture.class;
+        WAITERS_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("waiters"));
+        LISTENERS_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("listeners"));
+        VALUE_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("value"));
+        WAITER_THREAD_OFFSET = unsafe.objectFieldOffset(Waiter.class.getDeclaredField("thread"));
+        WAITER_NEXT_OFFSET = unsafe.objectFieldOffset(Waiter.class.getDeclaredField("next"));
+        UNSAFE = unsafe;
+      } catch (Exception e) {
+        throw Throwables.propagate(e);
       }
-      return -1;
     }
 
-    /*
-     * We always allow a release to go through, this means the state has been
-     * successfully changed and the result is available.
-     */
     @Override
-    protected boolean tryReleaseShared(int finalState) {
-      setState(finalState);
-      return true;
+    void putThread(Waiter waiter, Thread newValue) {
+      UNSAFE.putObject(waiter, WAITER_THREAD_OFFSET, newValue);
     }
 
-    /**
-     * Blocks until the task is complete or the timeout expires.  Throws a
-     * {@link TimeoutException} if the timer expires, otherwise behaves like
-     * {@link #get()}.
-     */
-    V get(long nanos) throws TimeoutException, CancellationException,
-        ExecutionException, InterruptedException {
+    @Override
+    void putNext(Waiter waiter, Waiter newValue) {
+      UNSAFE.putObject(waiter, WAITER_NEXT_OFFSET, newValue);
+    }
 
-      // Attempt to acquire the shared lock with a timeout.
-      if (!tryAcquireSharedNanos(-1, nanos)) {
-        throw new TimeoutException("Timeout waiting for task.");
-      }
+    /** Performs a CAS operation on the {@link #waiters} field. */
+    @Override
+    boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+      return UNSAFE.compareAndSwapObject(future, WAITERS_OFFSET, expect, update);
+    }
 
-      return getValue();
-    }
-
-    /**
-     * Blocks until {@link #complete(Object, Throwable, int)} has been
-     * successfully called.  Throws a {@link CancellationException} if the task
-     * was cancelled, or a {@link ExecutionException} if the task completed with
-     * an error.
-     */
-    V get() throws CancellationException, ExecutionException,
-        InterruptedException {
-
-      // Acquire the shared lock allowing interruption.
-      acquireSharedInterruptibly(-1);
-      return getValue();
-    }
-
-    /**
-     * Implementation of the actual value retrieval.  Will return the value
-     * on success, an exception on failure, a cancellation on cancellation, or
-     * an illegal state if the synchronizer is in an invalid state.
-     */
-    private V getValue() throws CancellationException, ExecutionException {
-      int state = getState();
-      switch (state) {
-        case COMPLETED:
-          if (exception != null) {
-            throw new ExecutionException(exception);
-          } else {
-            return value;
-          }
+    /** Performs a CAS operation on the {@link #listeners} field. */
+    @Override
+    boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+      return UNSAFE.compareAndSwapObject(future, LISTENERS_OFFSET, expect, update);
+    }
+
+    /** Performs a CAS operation on the {@link #value} field. */
+    @Override
+    boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+      return UNSAFE.compareAndSwapObject(future, VALUE_OFFSET, expect, update);
+    }
+  }
+
+  /** {@link AtomicHelper} based on {@link AtomicReferenceFieldUpdater}. */
+  private static final class SafeAtomicHelper extends AtomicHelper {
+    final AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater;
+    final AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater;
+    final AtomicReferenceFieldUpdater<AbstractFuture, Waiter> waitersUpdater;
+    final AtomicReferenceFieldUpdater<AbstractFuture, Listener> listenersUpdater;
+    final AtomicReferenceFieldUpdater<AbstractFuture, Object> valueUpdater;
+
+    SafeAtomicHelper(
+        AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater,
+        AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater,
+        AtomicReferenceFieldUpdater<AbstractFuture, Waiter> waitersUpdater,
+        AtomicReferenceFieldUpdater<AbstractFuture, Listener> listenersUpdater,
+        AtomicReferenceFieldUpdater<AbstractFuture, Object> valueUpdater) {
+      this.waiterThreadUpdater = waiterThreadUpdater;
+      this.waiterNextUpdater = waiterNextUpdater;
+      this.waitersUpdater = waitersUpdater;
+      this.listenersUpdater = listenersUpdater;
+      this.valueUpdater = valueUpdater;
+    }
+
+    @Override
+    void putThread(Waiter waiter, Thread newValue) {
+      waiterThreadUpdater.lazySet(waiter, newValue);
+    }
+
+    @Override
+    void putNext(Waiter waiter, Waiter newValue) {
+      waiterNextUpdater.lazySet(waiter, newValue);
+    }
+
+    @Override
+    boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+      return waitersUpdater.compareAndSet(future, expect, update);
+    }
+
+    @Override
+    boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+      return listenersUpdater.compareAndSet(future, expect, update);
+    }
+
+    @Override
+    boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+      return valueUpdater.compareAndSet(future, expect, update);
+    }
+  }
+
+  /**
+   * {@link AtomicHelper} based on {@code synchronized} and volatile writes.
+   *
+   * <p>This is an implementation of last resort for when certain basic VM features are broken
+   * (like AtomicReferenceFieldUpdater).
+   */
+  private static final class SynchronizedHelper extends AtomicHelper {
+    @Override
+    void putThread(Waiter waiter, Thread newValue) {
+      waiter.thread = newValue;
+    }
 
-        case CANCELLED:
-        case INTERRUPTED:
-          throw cancellationExceptionWithCause(
-              "Task was cancelled.", exception);
+    @Override
+    void putNext(Waiter waiter, Waiter newValue) {
+      waiter.next = newValue;
+    }
 
-        default:
-          throw new IllegalStateException(
-              "Error, synchronizer in invalid state: " + state);
+    @Override
+    boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+      synchronized (future) {
+        if (future.waiters == expect) {
+          future.waiters = update;
+          return true;
+        }
+        return false;
       }
     }
 
-    /**
-     * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link
-     * INTERRUPTED}.
-     */
-    boolean isDone() {
-      return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0;
-    }
-
-    /**
-     * Checks if the state is {@link #CANCELLED} or {@link #INTERRUPTED}.
-     */
-    boolean isCancelled() {
-      return (getState() & (CANCELLED | INTERRUPTED)) != 0;
-    }
-
-    /**
-     * Checks if the state is {@link #INTERRUPTED}.
-     */
-    boolean wasInterrupted() {
-      return getState() == INTERRUPTED;
-    }
-
-    /**
-     * Transition to the COMPLETED state and set the value.
-     */
-    boolean set(@Nullable V v) {
-      return complete(v, null, COMPLETED);
-    }
-
-    /**
-     * Transition to the COMPLETED state and set the exception.
-     */
-    boolean setException(Throwable t) {
-      return complete(null, t, COMPLETED);
-    }
-
-    /**
-     * Transition to the CANCELLED or INTERRUPTED state.
-     */
-    boolean cancel(boolean interrupt) {
-      return complete(null, null, interrupt ? INTERRUPTED : CANCELLED);
-    }
-
-    /**
-     * Implementation of completing a task.  Either {@code v} or {@code t} will
-     * be set but not both.  The {@code finalState} is the state to change to
-     * from {@link #RUNNING}.  If the state is not in the RUNNING state we
-     * return {@code false} after waiting for the state to be set to a valid
-     * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link
-     * #INTERRUPTED}).
-     *
-     * @param v the value to set as the result of the computation.
-     * @param t the exception to set as the result of the computation.
-     * @param finalState the state to transition to.
-     */
-    private boolean complete(@Nullable V v, @Nullable Throwable t,
-        int finalState) {
-      boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
-      if (doCompletion) {
-        // If this thread successfully transitioned to COMPLETING, set the value
-        // and exception and then release to the final state.
-        this.value = v;
-        // Don't actually construct a CancellationException until necessary.
-        this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0)
-            ? new CancellationException("Future.cancel() was called.") : t;
-        releaseShared(finalState);
-      } else if (getState() == COMPLETING) {
-        // If some other thread is currently completing the future, block until
-        // they are done so we can guarantee completion.
-        acquireShared(-1);
+    @Override
+    boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+      synchronized (future) {
+        if (future.listeners == expect) {
+          future.listeners = update;
+          return true;
+        }
+        return false;
       }
-      return doCompletion;
     }
-  }
 
-  static final CancellationException cancellationExceptionWithCause(
-      @Nullable String message, @Nullable Throwable cause) {
-    CancellationException exception = new CancellationException(message);
-    exception.initCause(cause);
-    return exception;
+    @Override
+    boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+      synchronized (future) {
+        if (future.value == expect) {
+          future.value = update;
+          return true;
+        }
+        return false;
+      }
+    }
   }
 }
diff --git a/guava/src/com/google/common/util/concurrent/AbstractIdleService.java b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
index 23a56e1..9b2d1a2 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
@@ -18,7 +18,7 @@ package com.google.common.util.concurrent;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -38,14 +38,20 @@ import java.util.concurrent.TimeoutException;
 public abstract class AbstractIdleService implements Service {
 
   /* Thread names will look like {@code "MyService STARTING"}. */
-  private final Supplier<String> threadNameSupplier = new Supplier<String>() {
+  private final Supplier<String> threadNameSupplier = new ThreadNameSupplier();
+
+  @WeakOuter
+  private final class ThreadNameSupplier implements Supplier<String> {
     @Override public String get() {
       return serviceName() + " " + state();
     }
-  };
+  }
 
   /* use AbstractService for state management */
-  private final Service delegate = new AbstractService() {
+  private final Service delegate = new DelegateService();
+
+  @WeakOuter
+  private final class DelegateService extends AbstractService {
     @Override protected final void doStart() {
       MoreExecutors.renamingDecorator(executor(), threadNameSupplier)
           .execute(new Runnable() {
@@ -55,7 +61,6 @@ public abstract class AbstractIdleService implements Service {
                 notifyStarted();
               } catch (Throwable t) {
                 notifyFailed(t);
-                throw Throwables.propagate(t);
               }
             }
           });
@@ -70,12 +75,15 @@ public abstract class AbstractIdleService implements Service {
                 notifyStopped();
               } catch (Throwable t) {
                 notifyFailed(t);
-                throw Throwables.propagate(t);
               }
             }
           });
     }
-  };
+
+    @Override public String toString() {
+      return AbstractIdleService.this.toString();
+    }
+  }
 
   /** Constructor for use by subclasses. */
   protected AbstractIdleService() {}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
index 1208153..a1c4f3b 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
@@ -20,13 +20,14 @@ import com.google.common.annotations.Beta;
 
 import java.util.concurrent.AbstractExecutorService;
 import java.util.concurrent.Callable;
+import java.util.concurrent.RunnableFuture;
 
 import javax.annotation.Nullable;
 
 /**
- * Abstract {@link ListeningExecutorService} implementation that creates
- * {@link ListenableFutureTask} instances for each {@link Runnable} and {@link Callable} submitted
- * to it. These tasks are run with the abstract {@link #execute execute(Runnable)} method.
+ * Abstract {@link ListeningExecutorService} implementation that creates {@link ListenableFuture}
+ * instances for each {@link Runnable} and {@link Callable} submitted to it. These tasks are run
+ * with the abstract {@link #execute execute(Runnable)} method.
  *
  * <p>In addition to {@link #execute}, subclasses must implement all methods related to shutdown and
  * termination.
@@ -38,12 +39,14 @@ import javax.annotation.Nullable;
 public abstract class AbstractListeningExecutorService
     extends AbstractExecutorService implements ListeningExecutorService {
 
-  @Override protected final <T> ListenableFutureTask<T> newTaskFor(Runnable runnable, T value) {
-    return ListenableFutureTask.create(runnable, value);
+  /** @since 19.0 (present with return type {@code ListenableFutureTask} since 14.0) */
+  @Override protected final <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+    return TrustedListenableFutureTask.create(runnable, value);
   }
 
-  @Override protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
-    return ListenableFutureTask.create(callable);
+  /** @since 19.0 (present with return type {@code ListenableFutureTask} since 14.0) */
+  @Override protected final <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+    return TrustedListenableFutureTask.create(callable);
   }
 
   @Override public ListenableFuture<?> submit(Runnable task) {
diff --git a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
index b45440e..70a5fac 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
@@ -16,12 +16,13 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
@@ -120,6 +121,8 @@ public abstract class AbstractScheduledService implements Service {
      */
     public static Scheduler newFixedDelaySchedule(final long initialDelay, final long delay, 
         final TimeUnit unit) {
+      checkNotNull(unit);
+      checkArgument(delay > 0, "delay must be > 0, found %s", delay);
       return new Scheduler() {
         @Override
         public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
@@ -139,6 +142,8 @@ public abstract class AbstractScheduledService implements Service {
      */
     public static Scheduler newFixedRateSchedule(final long initialDelay, final long period, 
         final TimeUnit unit) {
+      checkNotNull(unit);
+      checkArgument(period > 0, "period must be > 0, found %s", period);
       return new Scheduler() {
         @Override
         public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
@@ -156,7 +161,10 @@ public abstract class AbstractScheduledService implements Service {
   }
   
   /* use AbstractService for state management */
-  private final AbstractService delegate = new AbstractService() {
+  private final AbstractService delegate = new ServiceDelegate();
+
+  @WeakOuter
+  private final class ServiceDelegate extends AbstractService {
     
     // A handle to the running task so that we can stop it when a shutdown has been requested.
     // These two fields are volatile because their values will be accessed from multiple threads.
@@ -165,28 +173,37 @@ public abstract class AbstractScheduledService implements Service {
     
     // This lock protects the task so we can ensure that none of the template methods (startUp, 
     // shutDown or runOneIteration) run concurrently with one another.
+    // TODO(lukes):  why don't we use ListenableFuture to sequence things?  Then we could drop the
+    // lock.
     private final ReentrantLock lock = new ReentrantLock();
-    
-    private final Runnable task = new Runnable() {
+
+    @WeakOuter
+    class Task implements Runnable {
       @Override public void run() {
         lock.lock();
         try {
+          if (runningTask.isCancelled()) {
+            // task may have been cancelled while blocked on the lock.
+            return;
+          }
           AbstractScheduledService.this.runOneIteration();
         } catch (Throwable t) {
           try {
             shutDown();
           } catch (Exception ignored) {
-            logger.log(Level.WARNING, 
+            logger.log(Level.WARNING,
                 "Error while attempting to shut down the service after failure.", ignored);
           }
           notifyFailed(t);
-          throw Throwables.propagate(t);
+          runningTask.cancel(false);  // prevent future invocations.
         } finally {
           lock.unlock();
         }
       }
-    };
-    
+    }
+
+    private final Runnable task = new Task();
+
     @Override protected final void doStart() {
       executorService = MoreExecutors.renamingDecorator(executor(), new Supplier<String>() {
         @Override public String get() {
@@ -202,7 +219,10 @@ public abstract class AbstractScheduledService implements Service {
             notifyStarted();
           } catch (Throwable t) {
             notifyFailed(t);
-            throw Throwables.propagate(t);
+            if (runningTask != null) {
+              // prevent the task from running if possible
+              runningTask.cancel(false);
+            }
           } finally {
             lock.unlock();
           }
@@ -211,7 +231,7 @@ public abstract class AbstractScheduledService implements Service {
     }
 
     @Override protected final void doStop() {
-      runningTask.cancel(false); 
+      runningTask.cancel(false);
       executorService.execute(new Runnable() {
         @Override public void run() {
           try {
@@ -231,13 +251,16 @@ public abstract class AbstractScheduledService implements Service {
             notifyStopped();
           } catch (Throwable t) {
             notifyFailed(t);
-            throw Throwables.propagate(t);
           }
         }
       });
     }
-  };
-  
+    
+    @Override public String toString() {
+      return AbstractScheduledService.this.toString();
+    }
+  }
+
   /** Constructor for use by subclasses. */
   protected AbstractScheduledService() {}
 
@@ -284,12 +307,13 @@ public abstract class AbstractScheduledService implements Service {
    * {@linkplain Service.State#TERMINATED fails}.
    */
   protected ScheduledExecutorService executor() {
-    final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
-        new ThreadFactory() {
-          @Override public Thread newThread(Runnable runnable) {
-            return MoreExecutors.newThread(serviceName(), runnable);
-          }
-        });
+    @WeakOuter class ThreadFactoryImpl implements ThreadFactory {
+      @Override public Thread newThread(Runnable runnable) {
+        return MoreExecutors.newThread(serviceName(), runnable);
+      }
+    }
+    final ScheduledExecutorService executor =
+        Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl());
     // Add a listener to shutdown the executor after the service is stopped.  This ensures that the
     // JVM shutdown will not be prevented from exiting after this service has stopped or failed.
     // Technically this listener is added after start() was called so it is a little gross, but it
@@ -443,14 +467,22 @@ public abstract class AbstractScheduledService implements Service {
        * Atomically reschedules this task and assigns the new future to {@link #currentFuture}.
        */
       public void reschedule() {
+        // invoke the callback outside the lock, prevents some shenanigans.
+        Schedule schedule;
+        try {
+          schedule = CustomScheduler.this.getNextSchedule();
+        } catch (Throwable t) {
+          service.notifyFailed(t);
+          return;
+        }
         // We reschedule ourselves with a lock held for two reasons. 1. we want to make sure that
         // cancel calls cancel on the correct future. 2. we want to make sure that the assignment
         // to currentFuture doesn't race with itself so that currentFuture is assigned in the 
         // correct order.
+        Throwable scheduleFailure = null;
         lock.lock();
         try {
           if (currentFuture == null || !currentFuture.isCancelled()) {
-            final Schedule schedule = CustomScheduler.this.getNextSchedule();
             currentFuture = executor.schedule(this, schedule.delay, schedule.unit);
           }
         } catch (Throwable e) {
@@ -459,10 +491,17 @@ public abstract class AbstractScheduledService implements Service {
           // because the service does not monitor the state of the future so if the exception is not
           // caught and forwarded to the service the task would stop executing but the service would
           // have no idea.
-          service.notifyFailed(e);
+          // TODO(lukes): consider building everything in terms of ListenableScheduledFuture then
+          // the AbstractService could monitor the future directly.  Rescheduling is still hard...
+          // but it would help with some of these lock ordering issues.
+          scheduleFailure = e;
         } finally {
           lock.unlock();
         }
+        // Call notifyFailed outside the lock to avoid lock ordering issues.
+        if (scheduleFailure != null) {
+          service.notifyFailed(scheduleFailure);
+        }
       }
       
       // N.B. Only protect cancel and isCancelled because those are the only methods that are 
@@ -478,9 +517,20 @@ public abstract class AbstractScheduledService implements Service {
         }
       }
 
+      @Override 
+      public boolean isCancelled() {
+        lock.lock();
+        try {
+          return currentFuture.isCancelled();
+        } finally {
+          lock.unlock();
+        }
+      }
+
       @Override
       protected Future<Void> delegate() {
-        throw new UnsupportedOperationException("Only cancel is supported by this future");
+        throw new UnsupportedOperationException(
+            "Only cancel and isCancelled is supported by this future");
       }
     }
     
@@ -510,7 +560,7 @@ public abstract class AbstractScheduledService implements Service {
        */
       public Schedule(long delay, TimeUnit unit) {
         this.delay = delay;
-        this.unit = Preconditions.checkNotNull(unit);
+        this.unit = checkNotNull(unit);
       }
     }
     
diff --git a/guava/src/com/google/common/util/concurrent/AbstractService.java b/guava/src/com/google/common/util/concurrent/AbstractService.java
index 0e996ed..fa5f0b2 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractService.java
@@ -30,6 +30,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.util.concurrent.ListenerCallQueue.Callback;
 import com.google.common.util.concurrent.Monitor.Guard;
 import com.google.common.util.concurrent.Service.State; // javadoc needs this
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -54,28 +55,28 @@ import javax.annotation.concurrent.Immutable;
  */
 @Beta
 public abstract class AbstractService implements Service {
-  private static final Callback<Listener> STARTING_CALLBACK =
+  private static final Callback<Listener> STARTING_CALLBACK = 
       new Callback<Listener>("starting()") {
         @Override void call(Listener listener) {
           listener.starting();
         }
       };
-  private static final Callback<Listener> RUNNING_CALLBACK =
+  private static final Callback<Listener> RUNNING_CALLBACK = 
       new Callback<Listener>("running()") {
         @Override void call(Listener listener) {
           listener.running();
         }
       };
-  private static final Callback<Listener> STOPPING_FROM_STARTING_CALLBACK =
+  private static final Callback<Listener> STOPPING_FROM_STARTING_CALLBACK = 
       stoppingCallback(STARTING);
-  private static final Callback<Listener> STOPPING_FROM_RUNNING_CALLBACK =
+  private static final Callback<Listener> STOPPING_FROM_RUNNING_CALLBACK = 
       stoppingCallback(RUNNING);
-
-  private static final Callback<Listener> TERMINATED_FROM_NEW_CALLBACK =
+  
+  private static final Callback<Listener> TERMINATED_FROM_NEW_CALLBACK = 
       terminatedCallback(NEW);
-  private static final Callback<Listener> TERMINATED_FROM_RUNNING_CALLBACK =
+  private static final Callback<Listener> TERMINATED_FROM_RUNNING_CALLBACK = 
       terminatedCallback(RUNNING);
-  private static final Callback<Listener> TERMINATED_FROM_STOPPING_CALLBACK =
+  private static final Callback<Listener> TERMINATED_FROM_STOPPING_CALLBACK = 
       terminatedCallback(STOPPING);
 
   private static Callback<Listener> terminatedCallback(final State from) {
@@ -85,7 +86,7 @@ public abstract class AbstractService implements Service {
       }
     };
   }
-
+  
   private static Callback<Listener> stoppingCallback(final State from) {
     return new Callback<Listener>("stopping({from = " + from + "})") {
       @Override void call(Listener listener) {
@@ -93,47 +94,75 @@ public abstract class AbstractService implements Service {
       }
     };
   }
-
+  
   private final Monitor monitor = new Monitor();
 
-  private final Guard isStartable = new Guard(monitor) {
+  private final Guard isStartable = new IsStartableGuard();
+
+  @WeakOuter
+  private final class IsStartableGuard extends Guard {
+    IsStartableGuard() {
+      super(AbstractService.this.monitor);
+    }
+
     @Override public boolean isSatisfied() {
       return state() == NEW;
     }
-  };
+  }
+
+  private final Guard isStoppable = new IsStoppableGuard();
+
+  @WeakOuter
+  private final class IsStoppableGuard extends Guard {
+    IsStoppableGuard() {
+      super(AbstractService.this.monitor);
+    }
 
-  private final Guard isStoppable = new Guard(monitor) {
     @Override public boolean isSatisfied() {
       return state().compareTo(RUNNING) <= 0;
     }
-  };
+  }
+
+  private final Guard hasReachedRunning = new HasReachedRunningGuard();
+
+  @WeakOuter
+  private final class HasReachedRunningGuard extends Guard {
+    HasReachedRunningGuard() {
+      super(AbstractService.this.monitor);
+    }
 
-  private final Guard hasReachedRunning = new Guard(monitor) {
     @Override public boolean isSatisfied() {
       return state().compareTo(RUNNING) >= 0;
     }
-  };
+  }
+
+  private final Guard isStopped = new IsStoppedGuard();
+
+  @WeakOuter
+  private final class IsStoppedGuard extends Guard {
+    IsStoppedGuard() {
+      super(AbstractService.this.monitor);
+    }
 
-  private final Guard isStopped = new Guard(monitor) {
     @Override public boolean isSatisfied() {
       return state().isTerminal();
     }
-  };
+  }
 
   /**
    * The listeners to notify during a state transition.
    */
   @GuardedBy("monitor")
-  private final List<ListenerCallQueue<Listener>> listeners =
+  private final List<ListenerCallQueue<Listener>> listeners = 
       Collections.synchronizedList(new ArrayList<ListenerCallQueue<Listener>>());
-
+  
   /**
    * The current state of the service.  This should be written with the lock held but can be read
    * without it because it is an immutable object in a volatile field.  This is desirable so that
    * methods like {@link #state}, {@link #failureCause} and notably {@link #toString} can be run
-   * without grabbing the lock.
-   *
-   * <p>To update this field correctly the lock must be held to guarantee that the state is
+   * without grabbing the lock.  
+   * 
+   * <p>To update this field correctly the lock must be held to guarantee that the state is 
    * consistent.
    */
   @GuardedBy("monitor")
@@ -141,15 +170,15 @@ public abstract class AbstractService implements Service {
 
   /** Constructor for use by subclasses. */
   protected AbstractService() {}
-
+  
   /**
-   * This method is called by {@link #startAsync} to initiate service startup. The invocation of
+   * This method is called by {@link #startAsync} to initiate service startup. The invocation of 
    * this method should cause a call to {@link #notifyStarted()}, either during this method's run,
    * or after it has returned. If startup fails, the invocation should cause a call to
    * {@link #notifyFailed(Throwable)} instead.
    *
    * <p>This method should return promptly; prefer to do work on a different thread where it is
-   * convenient. It is invoked exactly once on service startup, even when {@link #startAsync} is
+   * convenient. It is invoked exactly once on service startup, even when {@link #startAsync} is 
    * called multiple times.
    */
   protected abstract void doStart();
@@ -161,7 +190,7 @@ public abstract class AbstractService implements Service {
    * {@link #notifyFailed(Throwable)} instead.
    *
    * <p> This method should return promptly; prefer to do work on a different thread where it is
-   * convenient. It is invoked exactly once on service shutdown, even when {@link #stopAsync} is
+   * convenient. It is invoked exactly once on service shutdown, even when {@link #stopAsync} is 
    * called multiple times.
    */
   protected abstract void doStop();
@@ -172,7 +201,6 @@ public abstract class AbstractService implements Service {
         snapshot = new StateSnapshot(STARTING);
         starting();
         doStart();
-       // TODO(user): justify why we are catching Throwable and not RuntimeException
       } catch (Throwable startupFailure) {
         notifyFailed(startupFailure);
       } finally {
@@ -211,8 +239,6 @@ public abstract class AbstractService implements Service {
           default:
             throw new AssertionError("Unexpected state: " + previous);
         }
-        // TODO(user): justify why we are catching Throwable and not RuntimeException.  Also, we
-        // may inadvertently catch our AssertionErrors.
       } catch (Throwable shutdownFailure) {
         notifyFailed(shutdownFailure);
       } finally {
@@ -231,7 +257,7 @@ public abstract class AbstractService implements Service {
       monitor.leave();
     }
   }
-
+  
   @Override public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
     if (monitor.enterWhenUninterruptibly(hasReachedRunning, timeout, unit)) {
       try {
@@ -240,12 +266,11 @@ public abstract class AbstractService implements Service {
         monitor.leave();
       }
     } else {
-      // It is possible due to races the we are currently in the expected state even though we
+      // It is possible due to races the we are currently in the expected state even though we 
       // timed out. e.g. if we weren't event able to grab the lock within the timeout we would never
       // even check the guard.  I don't think we care too much about this use case but it could lead
       // to a confusing error message.
-      throw new TimeoutException("Timed out waiting for " + this + " to reach the RUNNING state. "
-          + "Current state: " + state());
+      throw new TimeoutException("Timed out waiting for " + this + " to reach the RUNNING state.");
     }
   }
 
@@ -257,7 +282,7 @@ public abstract class AbstractService implements Service {
       monitor.leave();
     }
   }
-
+  
   @Override public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
     if (monitor.enterWhenUninterruptibly(isStopped, timeout, unit)) {
       try {
@@ -266,7 +291,7 @@ public abstract class AbstractService implements Service {
         monitor.leave();
       }
     } else {
-      // It is possible due to races the we are currently in the expected state even though we
+      // It is possible due to races the we are currently in the expected state even though we 
       // timed out. e.g. if we weren't event able to grab the lock within the timeout we would never
       // even check the guard.  I don't think we care too much about this use case but it could lead
       // to a confusing error message.
@@ -274,7 +299,7 @@ public abstract class AbstractService implements Service {
           + "Current state: " + state());
     }
   }
-
+  
   /** Checks that the current state is equal to the expected state. */
   @GuardedBy("monitor")
   private void checkCurrentState(State expected) {
@@ -282,10 +307,10 @@ public abstract class AbstractService implements Service {
     if (actual != expected) {
       if (actual == FAILED) {
         // Handle this specially so that we can include the failureCause, if there is one.
-        throw new IllegalStateException("Expected the service to be " + expected
+        throw new IllegalStateException("Expected the service to be " + expected 
             + ", but the service has FAILED", failureCause());
       }
-      throw new IllegalStateException("Expected the service to be " + expected + ", but was "
+      throw new IllegalStateException("Expected the service to be " + expected + ", but was " 
           + actual);
     }
   }
@@ -299,7 +324,7 @@ public abstract class AbstractService implements Service {
   protected final void notifyStarted() {
     monitor.enter();
     try {
-      // We have to examine the internal state of the snapshot here to properly handle the stop
+      // We have to examine the internal state of the snapshot here to properly handle the stop 
       // while starting case.
       if (snapshot.state != STARTING) {
         IllegalStateException failure = new IllegalStateException(
@@ -310,7 +335,7 @@ public abstract class AbstractService implements Service {
 
       if (snapshot.shutdownWhenStartupFinishes) {
         snapshot = new StateSnapshot(STOPPING);
-        // We don't call listeners here because we already did that when we set the
+        // We don't call listeners here because we already did that when we set the 
         // shutdownWhenStartupFinishes flag.
         doStop();
       } else {
@@ -392,7 +417,7 @@ public abstract class AbstractService implements Service {
   public final State state() {
     return snapshot.externalState();
   }
-
+  
   /**
    * @since 14.0
    */
@@ -400,7 +425,7 @@ public abstract class AbstractService implements Service {
   public final Throwable failureCause() {
     return snapshot.failureCause();
   }
-
+  
   /**
    * @since 13.0
    */
@@ -422,7 +447,7 @@ public abstract class AbstractService implements Service {
     return getClass().getSimpleName() + " [" + state() + "]";
   }
 
-  /**
+  /** 
    * Attempts to execute all the listeners in {@link #listeners} while not holding the
    * {@link #monitor}.
    */
@@ -485,7 +510,7 @@ public abstract class AbstractService implements Service {
       }
     }.enqueueOn(listeners);
   }
-
+  
   /**
    * An immutable snapshot of the current state of the service. This class represents a consistent
    * snapshot of the state and therefore it can be used to answer simple queries without needing to
@@ -504,22 +529,22 @@ public abstract class AbstractService implements Service {
      * up.
      */
     final boolean shutdownWhenStartupFinishes;
-
+    
     /**
      * The exception that caused this service to fail.  This will be {@code null}
      * unless the service has failed.
      */
     @Nullable
     final Throwable failure;
-
+    
     StateSnapshot(State internalState) {
       this(internalState, false, null);
     }
-
+    
     StateSnapshot(
         State internalState, boolean shutdownWhenStartupFinishes, @Nullable Throwable failure) {
-      checkArgument(!shutdownWhenStartupFinishes || internalState == STARTING,
-          "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.",
+      checkArgument(!shutdownWhenStartupFinishes || internalState == STARTING, 
+          "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.", 
           internalState);
       checkArgument(!(failure != null ^ internalState == FAILED),
           "A failure cause should be set if and only if the state is failed.  Got %s and %s "
@@ -528,7 +553,7 @@ public abstract class AbstractService implements Service {
       this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes;
       this.failure = failure;
     }
-
+    
     /** @see Service#state() */
     State externalState() {
       if (shutdownWhenStartupFinishes && state == STARTING) {
@@ -537,10 +562,10 @@ public abstract class AbstractService implements Service {
         return state;
       }
     }
-
+    
     /** @see Service#failureCause() */
     Throwable failureCause() {
-      checkState(state == FAILED,
+      checkState(state == FAILED, 
           "failureCause() is only valid if the service has failed, service is %s", state);
       return failure;
     }
diff --git a/guava/src/com/google/common/util/concurrent/AggregateFuture.java b/guava/src/com/google/common/util/concurrent/AggregateFuture.java
new file mode 100644
index 0000000..28d5dca
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AggregateFuture.java
@@ -0,0 +1,300 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.collect.ImmutableCollection;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+/**
+ * A future made up of a collection of sub-futures.
+ *
+ * @param <InputT> the type of the individual inputs
+ * @param <OutputT> the type of the output (i.e. this) future
+ */
+ at GwtCompatible
+abstract class AggregateFuture<InputT, OutputT> extends AbstractFuture.TrustedFuture<OutputT> {
+  private static final Logger logger =
+      Logger.getLogger(AggregateFuture.class.getName());
+
+  private RunningState runningState;
+
+  @Override final void done() {
+    super.done();
+
+    // Let go of the memory held by the running state
+    this.runningState = null;
+  }
+
+  // TODO(cpovirk): Use maybePropagateCancellation() if the performance is OK and the code is clean.
+  @Override public final boolean cancel(boolean mayInterruptIfRunning) {
+    // Must get a reference to the futures before we cancel, as they'll be cleared out.
+    RunningState localRunningState = runningState;
+    ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures =
+        (localRunningState != null) ? localRunningState.futures : null;
+    // Cancel all the component futures.
+    boolean cancelled = super.cancel(mayInterruptIfRunning);
+    // & is faster than the branch required for &&
+    if (cancelled & futures != null) {
+      for (ListenableFuture<?> future : futures) {
+        future.cancel(mayInterruptIfRunning);
+      }
+    }
+    return cancelled;
+  }
+
+  @GwtIncompatible("Interruption not supported")
+  @Override protected final void interruptTask() {
+    RunningState localRunningState = runningState;
+    if (localRunningState != null) {
+      localRunningState.interruptTask();
+    }
+  }
+
+  /**
+   * Must be called at the end of each sub-class's constructor.
+   */
+  final void init(RunningState runningState) {
+    this.runningState = runningState;
+    runningState.init();
+  }
+
+  @WeakOuter
+  abstract class RunningState extends AggregateFutureState implements Runnable {
+    private ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures;
+    private final boolean allMustSucceed;
+    private final boolean collectsValues;
+
+    RunningState(ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures,
+        boolean allMustSucceed, boolean collectsValues) {
+      super(futures.size());
+      this.futures = checkNotNull(futures);
+      this.allMustSucceed = allMustSucceed;
+      this.collectsValues = collectsValues;
+    }
+
+    /* Used in the !allMustSucceed case so we don't have to instantiate a listener. */
+    @Override public final void run() {
+      decrementCountAndMaybeComplete();
+    }
+
+    /**
+     * The "real" initialization; we can't put this in the constructor because, in the case where
+     * futures are already complete, we would not initialize the subclass before calling
+     * {@link #handleOneInputDone}. As this is called after the subclass is constructed, we're
+     * guaranteed to have properly initialized the subclass.
+     */
+    private void init() {
+      // Corner case: List is empty.
+      if (futures.isEmpty()) {
+        handleAllCompleted();
+        return;
+      }
+
+      // NOTE: If we ever want to use a custom executor here, have a look at
+      // CombinedFuture as we'll need to handle RejectedExecutionException
+
+      if (allMustSucceed) {
+        // We need fail fast, so we have to keep track of which future failed so we can propagate
+        // the exception immediately
+
+        // Register a listener on each Future in the list to update
+        // the state of this future.
+        // Note that if all the futures on the list are done prior to completing
+        // this loop, the last call to addListener() will callback to
+        // setOneValue(), transitively call our cleanup listener, and set
+        // this.futures to null.
+        // This is not actually a problem, since the foreach only needs
+        // this.futures to be non-null at the beginning of the loop.
+        int i = 0;
+        for (final ListenableFuture<? extends InputT> listenable : futures) {
+          final int index = i++;
+          listenable.addListener(new Runnable() {
+            @Override
+            public void run() {
+              try {
+                handleOneInputDone(index, listenable);
+              } finally {
+                decrementCountAndMaybeComplete();
+              }
+            }
+          }, directExecutor());
+        }
+      } else {
+        // We'll only call the callback when all futures complete, regardless of whether some failed
+        // Hold off on calling setOneValue until all complete, so we can share the same listener
+        for (ListenableFuture<? extends InputT> listenable : futures) {
+          listenable.addListener(this, directExecutor());
+        }
+      }
+    }
+
+    /**
+     * Fails this future with the given Throwable if {@link #allMustSucceed} is
+     * true. Also, logs the throwable if it is an {@link Error} or if
+     * {@link #allMustSucceed} is {@code true}, the throwable did not cause
+     * this future to fail, and it is the first time we've seen that particular Throwable.
+     */
+    private void handleException(Throwable throwable) {
+      checkNotNull(throwable);
+
+      boolean completedWithFailure = false;
+      boolean firstTimeSeeingThisException = true;
+      if (allMustSucceed) {
+        // As soon as the first one fails, throw the exception up.
+        // The result of all other inputs is then ignored.
+        completedWithFailure = setException(throwable);
+        if (completedWithFailure) {
+          releaseResourcesAfterFailure();
+        } else {
+          // Go up the causal chain to see if we've already seen this cause; if we have,
+          // even if it's wrapped by a different exception, don't log it.
+          firstTimeSeeingThisException = addCausalChain(getOrInitSeenExceptions(), throwable);
+        }
+      }
+
+      // | and & used because it's faster than the branch required for || and &&
+      if (throwable instanceof Error
+          | (allMustSucceed & !completedWithFailure & firstTimeSeeingThisException)) {
+        String message =
+            (throwable instanceof Error)
+                ? "Input Future failed with Error"
+                : "Got more than one input Future failure. Logging failures after the first";
+        logger.log(Level.SEVERE, message, throwable);
+      }
+    }
+
+    @Override
+    final void addInitialException(Set<Throwable> seen) {
+      if (!isCancelled()) {
+        addCausalChain(seen, trustedGetException());
+      }
+    }
+
+    /**
+     * Handles the input at the given index completing.
+     */
+    private void handleOneInputDone(int index, Future<? extends InputT> future) {
+      // The only cases in which this Future should already be done are (a) if
+      // it was cancelled or (b) if an input failed and we propagated that
+      // immediately because of allMustSucceed.
+      checkState(allMustSucceed || !isDone() || isCancelled(),
+          "Future was done before all dependencies completed");
+
+      try {
+        checkState(future.isDone(),
+            "Tried to set value from future which is not done");
+        if (allMustSucceed) {
+          if (future.isCancelled()) {
+            // this.cancel propagates the cancellation to children; we use super.cancel
+            // to set our own state but let the input futures keep running
+            // as some of them may be used elsewhere.
+            AggregateFuture.super.cancel(false);
+          } else {
+            // We always get the result so that we can have fail-fast, even if we don't collect
+            InputT result = getUninterruptibly(future);
+            if (collectsValues) {
+              collectOneValue(allMustSucceed, index, result);
+            }
+          }
+        } else if (collectsValues && !future.isCancelled()) {
+          collectOneValue(allMustSucceed, index, getUninterruptibly(future));
+        }
+      } catch (ExecutionException e) {
+        handleException(e.getCause());
+      } catch (Throwable t) {
+        handleException(t);
+      }
+    }
+
+    private void decrementCountAndMaybeComplete() {
+      int newRemaining = decrementRemainingAndGet();
+      checkState(newRemaining >= 0, "Less than 0 remaining futures");
+      if (newRemaining == 0) {
+        processCompleted();
+      }
+    }
+
+    private void processCompleted() {
+      // Collect the values if (a) our output requires collecting them and (b) we haven't been
+      // collecting them as we go. (We've collected them as we go only if we needed to fail fast)
+      if (collectsValues & !allMustSucceed) {
+        int i = 0;
+        for (ListenableFuture<? extends InputT> listenable : futures) {
+          handleOneInputDone(i++, listenable);
+        }
+      }
+      handleAllCompleted();
+    }
+
+    /**
+     * Listeners implicitly keep a reference to {@link RunningState} as they're inner classes,
+     * so we free resources here as well for the allMustSucceed=true case (i.e. when a future fails,
+     * we immediately release resources we no longer need); additionally, the future will release
+     * its reference to {@link RunningState}, which should free all associated memory when all the
+     * futures complete & the listeners are released.
+     *
+     * TODO(user): Write tests for memory retention
+     */
+    void releaseResourcesAfterFailure() {
+      this.futures = null;
+    }
+
+    /**
+     * Called only if {@code collectsValues} is true.
+     *
+     * <p>If {@code allMustSucceed} is true, called as each future completes; otherwise,
+     * called for each future when all futures complete.
+     */
+    abstract void collectOneValue(boolean allMustSucceed, int index, @Nullable InputT returnValue);
+
+    abstract void handleAllCompleted();
+
+    void interruptTask() {}
+  }
+
+  /** Adds the chain to the seen set, and returns whether all the chain was new to us. */
+  private static boolean addCausalChain(Set<Throwable> seen, Throwable t) {
+    for (; t != null; t = t.getCause()) {
+      boolean firstTimeSeen = seen.add(t);
+      if (!firstTimeSeen) {
+        /*
+         * We've seen this, so we've seen its causes, too. No need to re-add them. (There's one case
+         * where this isn't true, but we ignore it: If we record an exception, then someone calls
+         * initCause() on it, and then we examine it again, we'll conclude that we've seen the whole
+         * chain before when it fact we haven't. But this should be rare.)
+         */
+        return false;
+      }
+    }
+    return true;
+  }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AggregateFutureState.java b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java
new file mode 100644
index 0000000..393c74a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static com.google.common.collect.Sets.newConcurrentHashSet;
+import static java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater;
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/**
+ * A helper which does some thread-safe operations for aggregate futures, which must be implemented
+ * differently in GWT.  Namely:
+ * <p>Lazily initializes a set of seen exceptions
+ * <p>Decrements a counter atomically
+ */
+ at GwtCompatible(emulated = true)
+abstract class AggregateFutureState {
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static final AtomicReferenceFieldUpdater<AggregateFutureState, Set<Throwable>>
+      SEEN_EXCEPTIONS_UDPATER = newUpdater(
+          AggregateFutureState.class, (Class) Set.class, "seenExceptions");
+
+  private static final AtomicIntegerFieldUpdater<AggregateFutureState>
+      REMAINING_COUNT_UPDATER = newUpdater(AggregateFutureState.class, "remaining");
+
+  // Lazily initialized the first time we see an exception; not released until all the input futures
+  // & this future completes. Released when the future releases the reference to the running state
+  private volatile Set<Throwable> seenExceptions = null;
+  @SuppressWarnings("unused") private volatile int remaining;
+
+  AggregateFutureState(int remainingFutures) {
+    this.remaining = remainingFutures;
+  }
+
+  final Set<Throwable> getOrInitSeenExceptions() {
+    /*
+     * The initialization of seenExceptions has to be more complicated than we'd like. The simple
+     * approach would be for each caller CAS it from null to a Set populated with its exception. But
+     * there's another race: If the first thread fails with an exception and a second thread
+     * immediately fails with the same exception:
+     *
+     * Thread1: calls setException(), which returns true, context switch before it can CAS
+     * seenExceptions to its exception
+     *
+     * Thread2: calls setException(), which returns false, CASes seenExceptions to its exception,
+     * and wrongly believes that its exception is new (leading it to logging it when it shouldn't)
+     *
+     * Our solution is for threads to CAS seenExceptions from null to a Set population with _the
+     * initial exception_, no matter which thread does the work. This ensures that seenExceptions
+     * always contains not just the current thread's exception but also the initial thread's.
+     */
+    Set<Throwable> seenExceptionsLocal = seenExceptions;
+    if (seenExceptionsLocal == null) {
+      seenExceptionsLocal = newConcurrentHashSet();
+      /*
+       * Other handleException() callers may see this as soon as we publish it. We need to populate
+       * it with the initial failure before we do, or else they may think that the initial failure
+       * has never been seen before.
+       */
+      addInitialException(seenExceptionsLocal);
+
+      SEEN_EXCEPTIONS_UDPATER.compareAndSet(this, null, seenExceptionsLocal);
+      /*
+       * If another handleException() caller created the set, we need to use that copy in case yet
+       * other callers have added to it.
+       *
+       * This read is guaranteed to get us the right value because we only set this once (here).
+       */
+      seenExceptionsLocal = seenExceptions;
+    }
+    return seenExceptionsLocal;
+  }
+
+  /** Populates {@code seen} with the exception that was passed to {@code setException}. */
+  abstract void addInitialException(Set<Throwable> seen);
+
+  final int decrementRemainingAndGet() {
+    return REMAINING_COUNT_UPDATER.decrementAndGet(this);
+  }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AsyncFunction.java b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
index cdb1228..c804e91 100644
--- a/guava/src/com/google/common/util/concurrent/AsyncFunction.java
+++ b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
@@ -16,15 +16,21 @@
 
 package com.google.common.util.concurrent;
 
+import com.google.common.annotations.GwtCompatible;
+
 import java.util.concurrent.Future;
 
+import javax.annotation.Nullable;
+
 /**
  * Transforms a value, possibly asynchronously. For an example usage and more
- * information, see {@link Futures#transform(ListenableFuture, AsyncFunction)}.
+ * information, see
+ * {@link Futures#transformAsync(ListenableFuture, AsyncFunction)}.
  *
  * @author Chris Povirk
  * @since 11.0
  */
+ at GwtCompatible
 public interface AsyncFunction<I, O> {
   /**
    * Returns an output {@code Future} to use in place of the given {@code
@@ -34,5 +40,5 @@ public interface AsyncFunction<I, O> {
    * <p>Throwing an exception from this method is equivalent to returning a
    * failing {@code Future}.
    */
-  ListenableFuture<O> apply(I input) throws Exception;
+  ListenableFuture<O> apply(@Nullable I input) throws Exception;
 }
diff --git a/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java b/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java
deleted file mode 100644
index 469cdb9..0000000
--- a/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.util.concurrent;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import javax.annotation.Nullable;
-
-/**
- * A settable future that can be set asynchronously via {@link #setFuture}.
- * A similar effect could be accomplished by adding a listener to the delegate
- * future that sets a normal settable future after the delegate is complete.
- * This approach gains us the ability to keep track of whether a delegate has
- * been set (i.e. so that we can prevent collisions from setting it twice and
- * can know before the computation is done whether it has been set), as well
- * as improved cancellation semantics (i.e. if either future is cancelled,
- * then the other one is too).  This class is thread-safe.
- *
- * @param <V> The result type returned by the Future's {@code get} method.
- *
- * @author Stephen Hicks
- */
-final class AsyncSettableFuture<V> extends ForwardingListenableFuture<V> {
-
-  /** Creates a new asynchronously-settable future. */
-  public static <V> AsyncSettableFuture<V> create() {
-    return new AsyncSettableFuture<V>();
-  }
-
-  private final NestedFuture<V> nested = new NestedFuture<V>();
-  private final ListenableFuture<V> dereferenced = Futures.dereference(nested);
-
-  private AsyncSettableFuture() {}
-
-  @Override protected ListenableFuture<V> delegate() {
-    return dereferenced;
-  }
-
-  /**
-   * Sets this future to forward to the given future.  Returns {@code true}
-   * if the future was able to be set (i.e. it hasn't been set already).
-   */
-  public boolean setFuture(ListenableFuture<? extends V> future) {
-    return nested.setFuture(checkNotNull(future));
-  }
-
-  /**
-   * Convenience method that calls {@link #setFuture} on a {@link
-   * Futures#immediateFuture}.  Returns {@code true} if the future
-   * was able to be set (i.e. it hasn't been set already).
-   */
-  public boolean setValue(@Nullable V value) {
-    return setFuture(Futures.immediateFuture(value));
-  }
-
-  /**
-   * Convenience method that calls {@link #setFuture} on a {@link
-   * Futures#immediateFailedFuture}.  Returns {@code true} if the
-   * future was able to be set (i.e. it hasn't been set already).
-   */
-  public boolean setException(Throwable exception) {
-    return setFuture(Futures.<V>immediateFailedFuture(exception));
-  }
-
-  /**
-   * Returns {@code true} if this future has been (possibly asynchronously) set.
-   * Note that a {@code false} result in no way gaurantees that a later call
-   * to, e.g., {@link #setFuture} will succeed, since another thread could
-   * make the call in between.  This is somewhat analogous to {@link #isDone},
-   * but since setting and completing are not the same event, it is useful to
-   * have this method broken out.
-   */
-  public boolean isSet() {
-    return nested.isDone();
-  }
-
-  private static final class NestedFuture<V> extends AbstractFuture<ListenableFuture<? extends V>> {
-    boolean setFuture(ListenableFuture<? extends V> value) {
-      boolean result = set(value);
-      if (isCancelled()) {
-        value.cancel(wasInterrupted());
-      }
-      return result;
-    }
-  }
-}
diff --git a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
index d0af965..35fafaf 100644
--- a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
+++ b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
@@ -23,6 +23,7 @@ import com.google.common.base.Function;
 import com.google.common.collect.Maps;
 
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
@@ -255,10 +256,12 @@ public final class AtomicLongMap<K> {
    * of the zero values have been removed and others have not.
    */
   public void removeAllZeros() {
-    for (K key : map.keySet()) {
-      AtomicLong atomic = map.get(key);
+    Iterator<Map.Entry<K, AtomicLong>> entryIterator = map.entrySet().iterator();
+    while (entryIterator.hasNext()) {
+      Map.Entry<K, AtomicLong> entry = entryIterator.next();
+      AtomicLong atomic = entry.getValue();
       if (atomic != null && atomic.get() == 0L) {
-        map.remove(key, atomic);
+        entryIterator.remove();
       }
     }
   }
diff --git a/guava/src/com/google/common/util/concurrent/Callables.java b/guava/src/com/google/common/util/concurrent/Callables.java
index 11c67fc..ca0f824 100644
--- a/guava/src/com/google/common/util/concurrent/Callables.java
+++ b/guava/src/com/google/common/util/concurrent/Callables.java
@@ -18,6 +18,8 @@ package com.google.common.util.concurrent;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Supplier;
 
 import java.util.concurrent.Callable;
@@ -30,6 +32,7 @@ import javax.annotation.Nullable;
  * @author Isaac Shum
  * @since 1.0
  */
+ at GwtCompatible(emulated = true)
 public final class Callables {
   private Callables() {}
 
@@ -54,6 +57,7 @@ public final class Callables {
    * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
    *     for each invocation of the wrapped callable.
    */
+  @GwtIncompatible("threads")
   static <T> Callable<T> threadRenaming(final Callable<T> callable,
       final Supplier<String> nameSupplier) {
     checkNotNull(nameSupplier);
@@ -83,6 +87,7 @@ public final class Callables {
    * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
    *     for each invocation of the wrapped callable.
    */
+  @GwtIncompatible("threads")
   static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
     checkNotNull(nameSupplier);
     checkNotNull(task);
@@ -103,6 +108,7 @@ public final class Callables {
   }
 
   /** Tries to set name of the given {@link Thread}, returns true if successful. */
+  @GwtIncompatible("threads")
   private static boolean trySetName(final String threadName, Thread currentThread) {
     // In AppEngine this will always fail, should we test for that explicitly using
     // MoreExecutors.isAppEngine.  More generally, is there a way to see if we have the modifyThread
diff --git a/guava/src/com/google/common/util/concurrent/CheckedFuture.java b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
index e286e2a..70d461e 100644
--- a/guava/src/com/google/common/util/concurrent/CheckedFuture.java
+++ b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
@@ -17,6 +17,7 @@
 package com.google.common.util.concurrent;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
 
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
@@ -29,6 +30,14 @@ import java.util.concurrent.TimeoutException;
  * of the {@code get} methods that can throw a checked exception.  This makes it
  * easier to create a future that executes logic which can throw an exception.
  *
+ * <p><b>Warning:</b> We recommend against using {@code CheckedFuture} in new
+ * projects. {@code CheckedFuture} is difficult to build libraries atop. {@code
+ * CheckedFuture} ports of methods like {@link Futures#transformAsync} have
+ * historically had bugs, and some of these bugs are necessary, unavoidable
+ * consequences of the {@code CheckedFuture} API. Additionally, {@code
+ * CheckedFuture} encourages users to take exceptions from one thread and
+ * rethrow them in another, producing confusing stack traces.
+ *
  * <p>A common implementation is {@link Futures#immediateCheckedFuture}.
  *
  * <p>Implementations of this interface must adapt the exceptions thrown by
@@ -41,14 +50,15 @@ import java.util.concurrent.TimeoutException;
  * {@link Future} or as an asynchronous callback mechanism as needed. This
  * allows multiple callbacks to be registered for a particular task, and the
  * future will guarantee execution of all listeners when the task completes.
- * 
- * <p>For a simpler alternative to CheckedFuture, consider accessing Future 
- * values with {@link Futures#get(Future, Class) Futures.get()}.
+ *
+ * <p>For a simpler alternative to CheckedFuture, consider accessing Future
+ * values with {@link Futures#getChecked(Future, Class) Futures.getChecked()}.
  *
  * @author Sven Mawson
  * @since 1.0
  */
 @Beta
+ at GwtCompatible
 public interface CheckedFuture<V, X extends Exception>
     extends ListenableFuture<V> {
 
diff --git a/guava/src/com/google/common/util/concurrent/CollectionFuture.java b/guava/src/com/google/common/util/concurrent/CollectionFuture.java
new file mode 100644
index 0000000..2bf9320
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/CollectionFuture.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Aggregate future that collects (stores) results of each future.
+ */
+ at GwtCompatible
+abstract class CollectionFuture<V, C> extends AggregateFuture<V, C> {
+
+  @WeakOuter
+  abstract class CollectionFutureRunningState extends RunningState {
+    private List<Optional<V>> values;
+
+    CollectionFutureRunningState(
+        ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+        boolean allMustSucceed) {
+      super(futures, allMustSucceed, true);
+
+      this.values = futures.isEmpty() ? ImmutableList.<Optional<V>>of()
+          : Lists.<Optional<V>>newArrayListWithCapacity(futures.size());
+
+      // Populate the results list with null initially.
+      for (int i = 0; i < futures.size(); ++i) {
+        values.add(null);
+      }
+    }
+
+    @Override
+    final void collectOneValue(boolean allMustSucceed, int index, @Nullable V returnValue) {
+      List<Optional<V>> localValues = values;
+  
+      if (localValues != null) {
+        localValues.set(index, Optional.fromNullable(returnValue));
+      } else {
+        // Some other future failed or has been cancelled, causing this one to
+        // also be cancelled or have an exception set. This should only happen
+        // if allMustSucceed is true or if the output itself has been
+        // cancelled.
+        checkState(allMustSucceed || isCancelled(),
+            "Future was done before all dependencies completed");
+      }
+    }
+  
+    @Override
+    final void handleAllCompleted() {
+      List<Optional<V>> localValues = values;
+      if (localValues != null) {
+        set(combine(localValues));
+      } else {
+        checkState(isDone());
+      }
+    }
+
+    @Override
+    void releaseResourcesAfterFailure() {
+      super.releaseResourcesAfterFailure();
+      this.values = null;
+    }
+
+    abstract C combine(List<Optional<V>> values);
+  }
+}
diff --git a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
index e438cec..7752d19 100644
--- a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
+++ b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
@@ -27,6 +27,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.MapMaker;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -519,7 +520,7 @@ public class CycleDetectingLockFactory {
     static final StackTraceElement[] EMPTY_STACK_TRACE =
         new StackTraceElement[0];
 
-    static Set<String> EXCLUDED_CLASS_NAMES = ImmutableSet.of(
+    static final Set<String> EXCLUDED_CLASS_NAMES = ImmutableSet.of(
         CycleDetectingLockFactory.class.getName(),
         ExampleStackTrace.class.getName(),
         LockGraphNode.class.getName());
@@ -665,10 +666,8 @@ public class CycleDetectingLockFactory {
       // can happen because multiple locks may share the same LockGraphNode. In
       // this situation, throw an IllegalStateException as defined by contract
       // described in the documentation of WithExplicitOrdering.
-      Preconditions.checkState(
-          this != acquiredLock,
-          "Attempted to acquire multiple locks with the same rank " +
-          acquiredLock.getLockName());
+      Preconditions.checkState(this != acquiredLock,
+          "Attempted to acquire multiple locks with the same rank %s", acquiredLock.getLockName());
 
       if (allowedPriorLocks.containsKey(acquiredLock)) {
         // The acquisition ordering from "acquiredLock" to "this" has already
@@ -778,7 +777,7 @@ public class CycleDetectingLockFactory {
       LockGraphNode node = lock.getLockGraphNode();
       // Iterate in reverse because locks are usually locked/unlocked in a
       // LIFO order.
-      for (int i = acquiredLockList.size() - 1; i >=0; i--) {
+      for (int i = acquiredLockList.size() - 1; i >= 0; i--) {
         if (acquiredLockList.get(i) == node) {
           acquiredLockList.remove(i);
           break;
@@ -911,7 +910,7 @@ public class CycleDetectingLockFactory {
   private class CycleDetectingReentrantReadLock
       extends ReentrantReadWriteLock.ReadLock {
 
-    final CycleDetectingReentrantReadWriteLock readWriteLock;
+    @Weak final CycleDetectingReentrantReadWriteLock readWriteLock;
 
     CycleDetectingReentrantReadLock(
         CycleDetectingReentrantReadWriteLock readWriteLock) {
@@ -973,7 +972,7 @@ public class CycleDetectingLockFactory {
   private class CycleDetectingReentrantWriteLock
       extends ReentrantReadWriteLock.WriteLock {
 
-    final CycleDetectingReentrantReadWriteLock readWriteLock;
+    @Weak final CycleDetectingReentrantReadWriteLock readWriteLock;
 
     CycleDetectingReentrantWriteLock(
         CycleDetectingReentrantReadWriteLock readWriteLock) {
diff --git a/guava/src/com/google/common/util/concurrent/ExecutionList.java b/guava/src/com/google/common/util/concurrent/ExecutionList.java
index cb9fc82..0e35048 100644
--- a/guava/src/com/google/common/util/concurrent/ExecutionList.java
+++ b/guava/src/com/google/common/util/concurrent/ExecutionList.java
@@ -16,8 +16,9 @@
 
 package com.google.common.util.concurrent;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Level;
@@ -27,18 +28,16 @@ import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 
 /**
- * <p>A list of listeners, each with an associated {@code Executor}, that
- * guarantees that every {@code Runnable} that is {@linkplain #add added} will
- * be executed after {@link #execute()} is called. Any {@code Runnable} added
- * after the call to {@code execute} is still guaranteed to execute. There is no
- * guarantee, however, that listeners will be executed in the order that they
- * are added.
+ * A support class for {@code ListenableFuture} implementations to manage their listeners. An
+ * instance contains a list of listeners, each with an associated {@code Executor}, and guarantees
+ * that every {@code Runnable} that is {@linkplain #add added} will be executed after {@link
+ * #execute()} is called. Any {@code Runnable} added after the call to {@code execute} is still
+ * guaranteed to execute. There is no guarantee, however, that listeners will be executed in the
+ * order that they are added.
  *
- * <p>Exceptions thrown by a listener will be propagated up to the executor.
- * Any exception thrown during {@code Executor.execute} (e.g., a {@code
- * RejectedExecutionException} or an exception thrown by {@linkplain
- * MoreExecutors#directExecutor direct execution}) will be caught and
- * logged.
+ * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
+ * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception
+ * thrown by {@linkplain MoreExecutors#directExecutor direct execution}) will be caught and logged.
  *
  * @author Nishant Thakkar
  * @author Sven Mawson
@@ -49,8 +48,8 @@ public final class ExecutionList {
   @VisibleForTesting static final Logger log = Logger.getLogger(ExecutionList.class.getName());
 
   /**
-   * The runnable, executor pairs to execute.  This acts as a stack threaded through the 
-   * {@link RunnableExecutorPair#next} field.
+   * The runnable, executor pairs to execute.  This acts as a stack threaded through the {@link
+   * RunnableExecutorPair#next} field.
    */
   @GuardedBy("this")
   private RunnableExecutorPair runnables;
@@ -61,61 +60,49 @@ public final class ExecutionList {
   public ExecutionList() {}
 
   /**
-   * Adds the {@code Runnable} and accompanying {@code Executor} to the list of
-   * listeners to execute. If execution has already begun, the listener is
-   * executed immediately.
+   * Adds the {@code Runnable} and accompanying {@code Executor} to the list of listeners to
+   * execute. If execution has already begun, the listener is executed immediately.
    *
-   * <p>Note: For fast, lightweight listeners that would be safe to execute in
-   * any thread, consider {@link MoreExecutors#directExecutor}. For heavier
-   * listeners, {@code directExecutor()} carries some caveats: First, the
-   * thread that the listener runs in depends on whether the {@code
-   * ExecutionList} has been executed at the time it is added. In particular,
-   * listeners may run in the thread that calls {@code add}. Second, the thread
-   * that calls {@link #execute} may be an internal implementation thread, such
-   * as an RPC network thread, and {@code directExecutor()} listeners may
-   * run in this thread. Finally, during the execution of a {@code
-   * directExecutor} listener, all other registered but unexecuted
-   * listeners are prevented from running, even if those listeners are to run
-   * in other executors.
+   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+   * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation.
    */
   public void add(Runnable runnable, Executor executor) {
-    // Fail fast on a null.  We throw NPE here because the contract of
-    // Executor states that it throws NPE on null listener, so we propagate
-    // that contract up into the add method as well.
-    Preconditions.checkNotNull(runnable, "Runnable was null.");
-    Preconditions.checkNotNull(executor, "Executor was null.");
+    // Fail fast on a null.  We throw NPE here because the contract of Executor states that it
+    // throws NPE on null listener, so we propagate that contract up into the add method as well.
+    checkNotNull(runnable, "Runnable was null.");
+    checkNotNull(executor, "Executor was null.");
 
-    // Lock while we check state.  We must maintain the lock while adding the
-    // new pair so that another thread can't run the list out from under us.
-    // We only add to the list if we have not yet started execution.
+    // Lock while we check state.  We must maintain the lock while adding the new pair so that
+    // another thread can't run the list out from under us. We only add to the list if we have not
+    // yet started execution.
     synchronized (this) {
       if (!executed) {
         runnables = new RunnableExecutorPair(runnable, executor, runnables);
         return;
       }
     }
-    // Execute the runnable immediately. Because of scheduling this may end up
-    // getting called before some of the previously added runnables, but we're
-    // OK with that.  If we want to change the contract to guarantee ordering
-    // among runnables we'd have to modify the logic here to allow it.
+    // Execute the runnable immediately. Because of scheduling this may end up getting called before
+    // some of the previously added runnables, but we're OK with that.  If we want to change the
+    // contract to guarantee ordering among runnables we'd have to modify the logic here to allow
+    // it.
     executeListener(runnable, executor);
   }
 
   /**
-   * Runs this execution list, executing all existing pairs in the order they
-   * were added. However, note that listeners added after this point may be
-   * executed before those previously added, and note that the execution order
-   * of all listeners is ultimately chosen by the implementations of the
-   * supplied executors.
+   * Runs this execution list, executing all existing pairs in the order they were added. However,
+   * note that listeners added after this point may be executed before those previously added, and
+   * note that the execution order of all listeners is ultimately chosen by the implementations of
+   * the supplied executors.
    *
-   * <p>This method is idempotent. Calling it several times in parallel is
-   * semantically equivalent to calling it exactly once.
+   * <p>This method is idempotent. Calling it several times in parallel is semantically equivalent
+   * to calling it exactly once.
    *
    * @since 10.0 (present in 1.0 as {@code run})
    */
   public void execute() {
-    // Lock while we update our state so the add method above will finish adding
-    // any listeners before we start to run them.
+    // Lock while we update our state so the add method above will finish adding any listeners
+    // before we start to run them.
     RunnableExecutorPair list;
     synchronized (this) {
       if (executed) {
@@ -128,11 +115,11 @@ public final class ExecutionList {
     // If we succeeded then list holds all the runnables we to execute.  The pairs in the stack are
     // in the opposite order from how they were added so we need to reverse the list to fulfill our
     // contract.
-    // This is somewhat annoying, but turns out to be very fast in practice.  Alternatively, we 
+    // This is somewhat annoying, but turns out to be very fast in practice.  Alternatively, we
     // could drop the contract on the method that enforces this queue like behavior since depending
     // on it is likely to be a bug anyway.
     
-    // N.B. All writes to the list and the next pointers must have happened before the above 
+    // N.B. All writes to the list and the next pointers must have happened before the above
     // synchronized block, so we can iterate the list without the lock held here.
     RunnableExecutorPair reversedList = null;
     while (list != null) {
@@ -148,16 +135,16 @@ public final class ExecutionList {
   }
 
   /**
-   * Submits the given runnable to the given {@link Executor} catching and logging all 
-   * {@linkplain RuntimeException runtime exceptions} thrown by the executor.
+   * Submits the given runnable to the given {@link Executor} catching and logging all {@linkplain
+   * RuntimeException runtime exceptions} thrown by the executor.
    */
   private static void executeListener(Runnable runnable, Executor executor) {
     try {
       executor.execute(runnable);
     } catch (RuntimeException e) {
-      // Log it and keep going, bad runnable and/or executor.  Don't
-      // punish the other runnables if we're given a bad one.  We only
-      // catch RuntimeException because we want Errors to propagate up.
+      // Log it and keep going, bad runnable and/or executor.  Don't punish the other runnables if
+      // we're given a bad one.  We only catch RuntimeException because we want Errors to propagate
+      // up.
       log.log(Level.SEVERE, "RuntimeException while executing runnable "
           + runnable + " with executor " + executor, e);
     }
diff --git a/guava/src/com/google/common/util/concurrent/FutureCallback.java b/guava/src/com/google/common/util/concurrent/FutureCallback.java
index efab08f..691d5d3 100644
--- a/guava/src/com/google/common/util/concurrent/FutureCallback.java
+++ b/guava/src/com/google/common/util/concurrent/FutureCallback.java
@@ -16,6 +16,8 @@
 
 package com.google.common.util.concurrent;
 
+import com.google.common.annotations.GwtCompatible;
+
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
@@ -30,6 +32,7 @@ import javax.annotation.Nullable;
  * @author Anthony Zana
  * @since 10.0
  */
+ at GwtCompatible
 public interface FutureCallback<V> {
   /**
    * Invoked with the result of the {@code Future} computation when it is
diff --git a/guava/src/com/google/common/util/concurrent/FutureFallback.java b/guava/src/com/google/common/util/concurrent/FutureFallback.java
index 7d03c67..cb7fcc6 100644
--- a/guava/src/com/google/common/util/concurrent/FutureFallback.java
+++ b/guava/src/com/google/common/util/concurrent/FutureFallback.java
@@ -17,32 +17,36 @@
 package com.google.common.util.concurrent;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
 
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 /**
- * Provides a backup {@code Future} to replace an earlier failed {@code Future}.
- * An implementation of this interface can be applied to an input {@code Future}
- * with {@link Futures#withFallback}.
+ * Provides a backup {@code Future} to replace an earlier failed {@code Future}. An implementation
+ * of this interface can be applied to an input {@code Future} with {@link Futures#withFallback}.
  *
  * @param <V> the result type of the provided backup {@code Future}
  *
  * @author Bruno Diniz
  * @since 14.0
+ * @deprecated This interface's main user, {@link Futures#withFallback(ListenableFuture,
+ *     FutureFallback) Futures.withFallback}, has been updated to use {@link AsyncFunction}. We
+ *     recommend that other APIs be updated in the same way. This interface will be removed in Guava
+ *     release 20.0.
  */
 @Beta
+ at Deprecated
+ at GwtCompatible
 public interface FutureFallback<V> {
   /**
-   * Returns a {@code Future} to be used in place of the {@code Future} that
-   * failed with the given exception. The exception is provided so that the
-   * {@code Fallback} implementation can conditionally determine whether to
-   * propagate the exception or to attempt to recover.
+   * Returns a {@code Future} to be used in place of the {@code Future} that failed with the given
+   * exception. The exception is provided so that the {@code Fallback} implementation can
+   * conditionally determine whether to propagate the exception or to attempt to recover.
    *
-   * @param t the exception that made the future fail. If the future's {@link
-   *     Future#get() get} method throws an {@link ExecutionException}, then the
-   *     cause is passed to this method. Any other thrown object is passed
-   *     unaltered.
+   * @param t the exception that made the future fail. If the future's {@link Future#get() get}
+   *     method throws an {@link ExecutionException}, then the cause is passed to this method. Any
+   *     other thrown object is passed unaltered.
    */
   ListenableFuture<V> create(Throwable t) throws Exception;
 }
diff --git a/guava/src/com/google/common/util/concurrent/Futures.java b/guava/src/com/google/common/util/concurrent/Futures.java
index 650ff26..3fb81d0 100644
--- a/guava/src/com/google/common/util/concurrent/Futures.java
+++ b/guava/src/com/google/common/util/concurrent/Futures.java
@@ -16,46 +16,38 @@
 
 package com.google.common.util.concurrent;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Platform.isInstanceOfThrowableClass;
 import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
-import static java.lang.Thread.currentThread;
-import static java.util.Arrays.asList;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Ordering;
 import com.google.common.collect.Queues;
-import com.google.common.collect.Sets;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.UndeclaredThrowableException;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.annotation.CheckReturnValue;
 import javax.annotation.Nullable;
 
 /**
@@ -63,7 +55,7 @@ import javax.annotation.Nullable;
  *
  * <p>Many of these methods use the {@link ListenableFuture} API; consult the
  * Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
  * {@code ListenableFuture}</a>.
  *
  * @author Kevin Bourrillion
@@ -72,13 +64,66 @@ import javax.annotation.Nullable;
  * @since 1.0
  */
 @Beta
-public final class Futures {
+ at GwtCompatible(emulated = true)
+public final class Futures extends GwtFuturesCatchingSpecialization {
+
+  // A note on memory visibility.
+  // Many of the utilities in this class (transform, withFallback, withTimeout, asList, combine)
+  // have two requirements that significantly complicate their design.
+  // 1. Cancellation should propagate from the returned future to the input future(s).
+  // 2. The returned futures shouldn't unnecessarily 'pin' their inputs after completion.
+  //
+  // A consequence of these requirements is that the delegate futures cannot be stored in
+  // final fields.
+  //
+  // For simplicity the rest of this description will discuss Futures.catching since it is the
+  // simplest instance, though very similar descriptions apply to many other classes in this file.
+  //
+  // In the constructor of AbstractCatchingFuture, the delegate future is assigned to a field
+  // 'inputFuture'. That field is non-final and non-volatile.  There are 2 places where the
+  // 'inputFuture' field is read and where we will have to consider visibility of the write
+  // operation in the constructor.
+  //
+  // 1. In the listener that performs the callback.  In this case it is fine since inputFuture is
+  //    assigned prior to calling addListener, and addListener happens-before any invocation of the
+  //    listener. Notably, this means that 'volatile' is unnecessary to make 'inputFuture' visible
+  //    to the listener.
+  //
+  // 2. In done() where we may propagate cancellation to the input.  In this case it is _not_ fine.
+  //    There is currently nothing that enforces that the write to inputFuture in the constructor is
+  //    visible to done().  This is because there is no happens before edge between the write and a
+  //    (hypothetical) unsafe read by our caller. Note: adding 'volatile' does not fix this issue,
+  //    it would just add an edge such that if done() observed non-null, then it would also
+  //    definitely observe all earlier writes, but we still have no guarantee that done() would see
+  //    the inital write (just stronger guarantees if it does).
+  //
+  // See: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013800.html
+  // For a (long) discussion about this specific issue and the general futility of life.
+  //
+  // For the time being we are OK with the problem discussed above since it requires a caller to
+  // introduce a very specific kind of data-race.  And given the other operations performed by these
+  // methods that involve volatile read/write operations, in practice there is no issue.  Also, the
+  // way in such a visibility issue would surface is most likely as a failure of cancel() to
+  // propagate to the input.  Cancellation propagation is fundamentally racy so this is fine.
+  //
+  // Future versions of the JMM may revise safe construction semantics in such a way that we can
+  // safely publish these objects and we won't need this whole discussion.
+  // TODO(user,lukes): consider adding volatile to all these fields since in current known JVMs
+  // that should resolve the issue.  This comes at the cost of adding more write barriers to the
+  // implementations.
+
   private Futures() {}
 
   /**
-   * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture}
-   * and a {@link Function} that maps from {@link Exception} instances into the
-   * appropriate checked type.
+   * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture} and a {@link Function}
+   * that maps from {@link Exception} instances into the appropriate checked type.
+   *
+   * <p><b>Warning:</b> We recommend against using {@code CheckedFuture} in new projects. {@code
+   * CheckedFuture} is difficult to build libraries atop. {@code CheckedFuture} ports of methods
+   * like {@link Futures#transformAsync} have historically had bugs, and some of these bugs are
+   * necessary, unavoidable consequences of the {@code CheckedFuture} API. Additionally, {@code
+   * CheckedFuture} encourages users to take exceptions from one thread and rethrow them in another,
+   * producing confusing stack traces.
    *
    * <p>The given mapping function will be applied to an
    * {@link InterruptedException}, a {@link CancellationException}, or an
@@ -87,6 +132,8 @@ public final class Futures {
    *
    * @since 9.0 (source-compatible since 1.0)
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <V, X extends Exception> CheckedFuture<V, X> makeChecked(
       ListenableFuture<V> future, Function<? super Exception, X> mapper) {
     return new MappingCheckedFuture<V, X>(checkNotNull(future), mapper);
@@ -138,6 +185,8 @@ public final class Futures {
   }
 
   private static class ImmediateSuccessfulFuture<V> extends ImmediateFuture<V> {
+    static final ImmediateSuccessfulFuture<Object> NULL =
+        new ImmediateSuccessfulFuture<Object>(null);
 
     @Nullable private final V value;
 
@@ -151,6 +200,7 @@ public final class Futures {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static class ImmediateSuccessfulCheckedFuture<V, X extends Exception>
       extends ImmediateFuture<V> implements CheckedFuture<V, X> {
 
@@ -191,6 +241,7 @@ public final class Futures {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static class ImmediateCancelledFuture<V> extends ImmediateFuture<V> {
 
     private final CancellationException thrown;
@@ -211,6 +262,7 @@ public final class Futures {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static class ImmediateFailedCheckedFuture<V, X extends Exception>
       extends ImmediateFuture<V> implements CheckedFuture<V, X> {
 
@@ -243,7 +295,14 @@ public final class Futures {
    * be canceled or timed out and its {@code isDone()} method always returns
    * {@code true}.
    */
+  @CheckReturnValue
   public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
+    if (value == null) {
+      // This cast is safe because null is assignable to V for all V (i.e. it is covariant)
+      @SuppressWarnings({"unchecked", "rawtypes"})
+      ListenableFuture<V> typedNull = (ListenableFuture) ImmediateSuccessfulFuture.NULL;
+      return typedNull;
+    }
     return new ImmediateSuccessfulFuture<V>(value);
   }
 
@@ -255,6 +314,8 @@ public final class Futures {
    * method always returns {@code true}. Calling {@code get()} or {@code
    * checkedGet()} will immediately return the provided value.
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <V, X extends Exception> CheckedFuture<V, X>
       immediateCheckedFuture(@Nullable V value) {
     return new ImmediateSuccessfulCheckedFuture<V, X>(value);
@@ -269,6 +330,7 @@ public final class Futures {
    * throw the provided {@code Throwable} wrapped in an {@code
    * ExecutionException}.
    */
+  @CheckReturnValue
   public static <V> ListenableFuture<V> immediateFailedFuture(
       Throwable throwable) {
     checkNotNull(throwable);
@@ -281,6 +343,8 @@ public final class Futures {
    *
    * @since 14.0
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <V> ListenableFuture<V> immediateCancelledFuture() {
     return new ImmediateCancelledFuture<V>();
   }
@@ -295,6 +359,8 @@ public final class Futures {
    * ExecutionException}, and calling {@code checkedGet()} will throw the
    * provided exception itself.
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <V, X extends Exception> CheckedFuture<V, X>
       immediateFailedCheckedFuture(X exception) {
     checkNotNull(exception);
@@ -345,34 +411,25 @@ public final class Futures {
    *         }
    *       });}</pre>
    *
-   * <p>Note: If the derived {@code Future} is slow or heavyweight to create
-   * (whether the {@code Future} itself is slow or heavyweight to complete is
-   * irrelevant), consider {@linkplain #withFallback(ListenableFuture,
-   * FutureFallback, Executor) supplying an executor}. If you do not supply an
-   * executor, {@code withFallback} will use a
-   * {@linkplain MoreExecutors#directExecutor direct executor}, which carries
-   * some caveats for heavier operations. For example, the call to {@code
-   * fallback.create} may run on an unpredictable or undesirable thread:
-   *
-   * <ul>
-   * <li>If the input {@code Future} is done at the time {@code withFallback}
-   * is called, {@code withFallback} will call {@code fallback.create} inline.
-   * <li>If the input {@code Future} is not yet done, {@code withFallback} will
-   * schedule {@code fallback.create} to be run by the thread that completes
-   * the input {@code Future}, which may be an internal system thread such as
-   * an RPC network thread.
-   * </ul>
-   *
-   * <p>Also note that, regardless of which thread executes the {@code
-   * fallback.create}, all other registered but unexecuted listeners are
-   * prevented from running during its execution, even if those listeners are
-   * to run in other executors.
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code FutureFallback.create}, not to
+   * any work done to complete the returned {@code Future}.
    *
    * @param input the primary input {@code Future}
    * @param fallback the {@link FutureFallback} implementation to be called if
    *     {@code input} fails
    * @since 14.0
+   * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+   *     AsyncFunction) catchingAsync(input, Throwable.class,
+   *     fallbackImplementedAsAnAsyncFunction)}, usually replacing {@code
+   *     Throwable.class} with the specific type you want to handle. This method
+   *     will be removed in Guava release 20.0.
    */
+  @Deprecated
+  @CheckReturnValue
   public static <V> ListenableFuture<V> withFallback(
       ListenableFuture<? extends V> input,
       FutureFallback<? extends V> fallback) {
@@ -423,12 +480,12 @@ public final class Futures {
    *         }
    *       }, directExecutor());}</pre>
    *
-   * <p>When the execution of {@code fallback.create} is fast and lightweight
-   * (though the {@code Future} it returns need not meet these criteria),
-   * consider {@linkplain #withFallback(ListenableFuture, FutureFallback)
-   * omitting the executor} or explicitly specifying {@code
-   * directExecutor}. However, be aware of the caveats documented in the
-   * link above.
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code FutureFallback.create}, not to any work done to
+   * complete the returned {@code Future}.
    *
    * @param input the primary input {@code Future}
    * @param fallback the {@link FutureFallback} implementation to be called if
@@ -436,72 +493,476 @@ public final class Futures {
    * @param executor the executor that runs {@code fallback} if {@code input}
    *     fails
    * @since 14.0
+   * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+   *     AsyncFunction, Executor) catchingAsync(input, Throwable.class,
+   *     fallbackImplementedAsAnAsyncFunction, executor)}, usually replacing
+   *     {@code Throwable.class} with the specific type you want to handle. This method
+   *     will be removed in Guava release 20.0.
    */
+  @Deprecated
+  @CheckReturnValue
   public static <V> ListenableFuture<V> withFallback(
       ListenableFuture<? extends V> input,
       FutureFallback<? extends V> fallback, Executor executor) {
+    return catchingAsync(
+        input, Throwable.class, asAsyncFunction(fallback), executor);
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+   * primary input fails with the given {@code exceptionType}, from the result provided by the
+   * {@code fallback}. {@link Function#apply} is not invoked until the primary input has failed, so
+   * if the primary input succeeds, it is never invoked. If, during the invocation of {@code
+   * fallback}, an exception is thrown, this exception is used as the result of the output {@code
+   * Future}.
+   *
+   * <p>Usage example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catching(
+   *       fetchCounterFuture, FetchException.class,
+   *       new Function<FetchException, Integer>() {
+   *         public Integer apply(FetchException e) {
+   *           return 0;
+   *         }
+   *       });}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+   * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+   * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+   * listeners" refer here to the work done during {@code Function.apply}.
+   *
+   * @param input the primary input {@code Future}
+   * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+   *     bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+   *     {@code Throwable.class} in particular.
+   * @param fallback the {@link Function} implementation to be called if {@code input} fails with
+   *     the expected exception type
+   * @since 19.0
+   */
+  @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+  @CheckReturnValue
+  public static <V, X extends Throwable> ListenableFuture<V> catching(
+      ListenableFuture<? extends V> input, Class<X> exceptionType,
+      Function<? super X, ? extends V> fallback) {
+    CatchingFuture<V, X> future = new CatchingFuture<V, X>(input, exceptionType, fallback);
+    input.addListener(future, directExecutor());
+    return future;
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+   * primary input fails with the given {@code exceptionType}, from the result provided by the
+   * {@code fallback}. {@link Function#apply} is not invoked until the primary input has failed, so
+   * if the primary input succeeds, it is never invoked. If, during the invocation of {@code
+   * fallback}, an exception is thrown, this exception is used as the result of the output {@code
+   * Future}.
+   *
+   * <p>Usage example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catching(
+   *       fetchCounterFuture, FetchException.class,
+   *       new Function<FetchException, Integer>() {
+   *         public Integer apply(FetchException e) {
+   *           return 0;
+   *         }
+   *       }, directExecutor());}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+   * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+   * work done during {@code Function.apply}.
+   *
+   * @param input the primary input {@code Future}
+   * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+   *     bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+   *     {@code Throwable.class} in particular.
+   * @param fallback the {@link Function} implementation to be called if {@code input} fails with
+   *     the expected exception type
+   * @param executor the executor that runs {@code fallback} if {@code input} fails
+   * @since 19.0
+   */
+  @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+  @CheckReturnValue
+  public static <V, X extends Throwable> ListenableFuture<V> catching(
+      ListenableFuture<? extends V> input, Class<X> exceptionType,
+      Function<? super X, ? extends V> fallback, Executor executor) {
+    CatchingFuture<V, X> future = new CatchingFuture<V, X>(input, exceptionType, fallback);
+    input.addListener(future, rejectionPropagatingExecutor(executor, future));
+    return future;
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+   * primary input fails with the given {@code exceptionType}, from the result provided by the
+   * {@code fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has
+   * failed, so if the primary input succeeds, it is never invoked. If, during the invocation of
+   * {@code fallback}, an exception is thrown, this exception is used as the result of the output
+   * {@code Future}.
+   *
+   * <p>Usage examples:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+   *       fetchCounterFuture, FetchException.class,
+   *       new AsyncFunction<FetchException, Integer>() {
+   *         public ListenableFuture<Integer> apply(FetchException e) {
+   *           return immediateFuture(0);
+   *         }
+   *       });}</pre>
+   *
+   * <p>The fallback can also choose to propagate the original exception when desired:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter only in case the exception was a
+   *   // TimeoutException.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+   *       fetchCounterFuture, FetchException.class,
+   *       new AsyncFunction<FetchException, Integer>() {
+   *         public ListenableFuture<Integer> apply(FetchException e)
+   *             throws FetchException {
+   *           if (omitDataOnFetchFailure) {
+   *             return immediateFuture(0);
+   *           }
+   *           throw e;
+   *         }
+   *       });}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+   * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+   * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+   * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+   * to complete the returned {@code Future}.
+   *
+   * @param input the primary input {@code Future}
+   * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+   *     bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+   *     {@code Throwable.class} in particular.
+   * @param fallback the {@link AsyncFunction} implementation to be called if {@code input} fails
+   *     with the expected exception type
+   * @since 19.0 (similar functionality in 14.0 as {@code withFallback})
+   */
+  @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+  // TODO(kak): @CheckReturnValue
+  public static <V, X extends Throwable> ListenableFuture<V> catchingAsync(
+      ListenableFuture<? extends V> input, Class<X> exceptionType,
+      AsyncFunction<? super X, ? extends V> fallback) {
+    AsyncCatchingFuture<V, X> future =
+        new AsyncCatchingFuture<V, X>(input, exceptionType, fallback);
+    input.addListener(future, directExecutor());
+    return future;
+  }
+
+  /**
+   * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+   * primary input fails with the given {@code exceptionType}, from the result provided by the
+   * {@code fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has
+   * failed, so if the primary input succeeds, it is never invoked. If, during the invocation of
+   * {@code fallback}, an exception is thrown, this exception is used as the result of the output
+   * {@code Future}.
+   *
+   * <p>Usage examples:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter in case an exception happens when
+   *   // processing the RPC to fetch counters.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+   *       fetchCounterFuture, FetchException.class,
+   *       new AsyncFunction<FetchException, Integer>() {
+   *         public ListenableFuture<Integer> apply(FetchException e) {
+   *           return immediateFuture(0);
+   *         }
+   *       }, directExecutor());}</pre>
+   *
+   * <p>The fallback can also choose to propagate the original exception when desired:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<Integer> fetchCounterFuture = ...;
+   *
+   *   // Falling back to a zero counter only in case the exception was a
+   *   // TimeoutException.
+   *   ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+   *       fetchCounterFuture, FetchException.class,
+   *       new AsyncFunction<FetchException, Integer>() {
+   *         public ListenableFuture<Integer> apply(FetchException e)
+   *             throws FetchException {
+   *           if (omitDataOnFetchFailure) {
+   *             return immediateFuture(0);
+   *           }
+   *           throw e;
+   *         }
+   *       }, directExecutor());}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+   * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+   * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+   * {@code Future}.
+   *
+   * @param input the primary input {@code Future}
+   * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+   *     bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+   *     {@code Throwable.class} in particular.
+   * @param fallback the {@link AsyncFunction} implementation to be called if {@code input} fails
+   *     with the expected exception type
+   * @param executor the executor that runs {@code fallback} if {@code input} fails
+   * @since 19.0 (similar functionality in 14.0 as {@code withFallback})
+   */
+  @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+  // TODO(kak): @CheckReturnValue
+  public static <V, X extends Throwable> ListenableFuture<V> catchingAsync(
+      ListenableFuture<? extends V> input, Class<X> exceptionType,
+      AsyncFunction<? super X, ? extends V> fallback, Executor executor) {
+    AsyncCatchingFuture<V, X> future =
+        new AsyncCatchingFuture<V, X>(input, exceptionType, fallback);
+    input.addListener(future, rejectionPropagatingExecutor(executor, future));
+    return future;
+  }
+
+  @Deprecated
+  static <V> AsyncFunction<Throwable, V> asAsyncFunction(final FutureFallback<V> fallback) {
     checkNotNull(fallback);
-    return new FallbackFuture<V>(input, fallback, executor);
+    return new AsyncFunction<Throwable, V>() {
+      @Override
+      public ListenableFuture<V> apply(Throwable t) throws Exception {
+        return checkNotNull(fallback.create(t), "FutureFallback.create returned null instead of a "
+            + "Future. Did you mean to return immediateFuture(null)?");
+      }
+    };
+  }
+
+  private abstract static class AbstractCatchingFuture<V, X extends Throwable, F>
+      extends AbstractFuture.TrustedFuture<V> implements Runnable {
+    @Nullable ListenableFuture<? extends V> inputFuture;
+    @Nullable Class<X> exceptionType;
+    @Nullable F fallback;
+
+    AbstractCatchingFuture(
+        ListenableFuture<? extends V> inputFuture, Class<X> exceptionType, F fallback) {
+      this.inputFuture = checkNotNull(inputFuture);
+      this.exceptionType = checkNotNull(exceptionType);
+      this.fallback = checkNotNull(fallback);
+    }
+
+    @Override public final void run() {
+      ListenableFuture<? extends V> localInputFuture = inputFuture;
+      Class<X> localExceptionType = exceptionType;
+      F localFallback = fallback;
+      if (localInputFuture == null | localExceptionType == null | localFallback == null
+          | isCancelled()) {
+        return;
+      }
+      inputFuture = null;
+      exceptionType = null;
+      fallback = null;
+
+      Throwable throwable;
+      try {
+        set(getUninterruptibly(localInputFuture));
+        return;
+      } catch (ExecutionException e) {
+        throwable = e.getCause();
+      } catch (Throwable e) {  // this includes cancellation exception
+        throwable = e;
+      }
+      try {
+        if (isInstanceOfThrowableClass(throwable, localExceptionType)) {
+          @SuppressWarnings("unchecked") // verified safe by isInstance
+          X castThrowable = (X) throwable;
+          doFallback(localFallback, castThrowable);
+        } else {
+          setException(throwable);
+        }
+      } catch (Throwable e) {
+        setException(e);
+      }
+    }
+
+    /** Template method for subtypes to actually run the fallback. */
+    abstract void doFallback(F fallback, X throwable) throws Exception;
+
+    @Override final void done() {
+      maybePropagateCancellation(inputFuture);
+      this.inputFuture = null;
+      this.exceptionType = null;
+      this.fallback = null;
+    }
   }
 
   /**
-   * A future that falls back on a second, generated future, in case its
-   * original future fails.
+   * A {@link AbstractCatchingFuture} that delegates to an {@link AsyncFunction}
+   * and {@link #setFuture(ListenableFuture)} to implement {@link #doFallback}
    */
-  private static class FallbackFuture<V> extends AbstractFuture<V> {
-
-    private volatile ListenableFuture<? extends V> running;
-
-    FallbackFuture(ListenableFuture<? extends V> input,
-        final FutureFallback<? extends V> fallback,
-        final Executor executor) {
-      running = input;
-      addCallback(running, new FutureCallback<V>() {
-        @Override
-        public void onSuccess(V value) {
-          set(value);
+  static final class AsyncCatchingFuture<V, X extends Throwable>
+      extends AbstractCatchingFuture<V, X, AsyncFunction<? super X, ? extends V>> {
+
+    AsyncCatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+        AsyncFunction<? super X, ? extends V> fallback) {
+      super(input, exceptionType, fallback);
+    }
+
+    @Override void doFallback(
+        AsyncFunction<? super X, ? extends V> fallback, X cause) throws Exception {
+      ListenableFuture<? extends V> replacement = fallback.apply(cause);
+      checkNotNull(replacement, "AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+      setFuture(replacement);
+    }
+  }
+
+  /**
+   * A {@link AbstractCatchingFuture} that delegates to a {@link Function}
+   * and {@link #set(Object)} to implement {@link #doFallback}
+   */
+  static final class CatchingFuture<V, X extends Throwable>
+      extends AbstractCatchingFuture<V, X, Function<? super X, ? extends V>> {
+    CatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+        Function<? super X, ? extends V> fallback) {
+      super(input, exceptionType, fallback);
+    }
+
+    @Override void doFallback(Function<? super X, ? extends V> fallback, X cause) throws Exception {
+      V replacement = fallback.apply(cause);
+      set(replacement);
+    }
+  }
+
+  /**
+   * Returns a future that delegates to another but will finish early (via a
+   * {@link TimeoutException} wrapped in an {@link ExecutionException}) if the
+   * specified duration expires.
+   *
+   * <p>The delegate future is interrupted and cancelled if it times out.
+   *
+   * @param delegate The future to delegate to.
+   * @param time when to timeout the future
+   * @param unit the time unit of the time parameter
+   * @param scheduledExecutor The executor service to enforce the timeout.
+   *
+   * @since 19.0
+   */
+  @GwtIncompatible("java.util.concurrent.ScheduledExecutorService")
+  @CheckReturnValue
+  public static <V> ListenableFuture<V> withTimeout(ListenableFuture<V> delegate,
+      long time, TimeUnit unit, ScheduledExecutorService scheduledExecutor) {
+    TimeoutFuture<V> result = new TimeoutFuture<V>(delegate);
+    TimeoutFuture.Fire<V> fire = new TimeoutFuture.Fire<V>(result);
+    result.timer = scheduledExecutor.schedule(fire, time, unit);
+    delegate.addListener(fire, directExecutor());
+    return result;
+  }
+
+  /**
+   * Future that delegates to another but will finish early (via a {@link
+   * TimeoutException} wrapped in an {@link ExecutionException}) if the
+   * specified duration expires.
+   * The delegate future is interrupted and cancelled if it times out.
+   */
+  private static final class TimeoutFuture<V> extends AbstractFuture.TrustedFuture<V> {
+    // Memory visibility of these fields.
+    // There are two cases to consider.
+    // 1. visibility of the writes to these fields to Fire.run
+    //    The initial write to delegateRef is made definitely visible via the semantics of
+    //    addListener/SES.schedule.  The later racy write in cancel() is not guaranteed to be
+    //    observed, however that is fine since the correctness is based on the atomic state in
+    //    our base class.
+    //    The initial write to timer is never definitely visible to Fire.run since it is assigned
+    //    after SES.schedule is called. Therefore Fire.run has to check for null.  However, it
+    //    should be visible if Fire.run is called by delegate.addListener since addListener is
+    //    called after the assignment to timer, and importantly this is the main situation in which
+    //    we need to be able to see the write.
+    // 2. visibility of the writes to cancel
+    //    Since these fields are non-final that means that TimeoutFuture is not being 'safely
+    //    published', thus a motivated caller may be able to expose the reference to another thread
+    //    that would then call cancel() and be unable to cancel the delegate.
+    //    There are a number of ways to solve this, none of which are very pretty, and it is
+    //    currently believed to be a purely theoretical problem (since the other actions should
+    //    supply sufficient write-barriers).
+
+    @Nullable ListenableFuture<V> delegateRef;
+    @Nullable Future<?> timer;
+
+    TimeoutFuture(ListenableFuture<V> delegate) {
+      this.delegateRef = Preconditions.checkNotNull(delegate);
+    }
+
+    /** A runnable that is called when the delegate or the timer completes. */
+    private static final class Fire<V> implements Runnable {
+      @Nullable TimeoutFuture<V> timeoutFutureRef;
+
+      Fire(TimeoutFuture<V> timeoutFuture) {
+        this.timeoutFutureRef = timeoutFuture;
+      }
+
+      @Override public void run() {
+        // If either of these reads return null then we must be after a successful cancel
+        // or another call to this method.
+        TimeoutFuture<V> timeoutFuture = timeoutFutureRef;
+        if (timeoutFuture == null) {
+          return;
+        }
+        ListenableFuture<V> delegate = timeoutFuture.delegateRef;
+        if (delegate == null) {
+          return;
         }
 
-        @Override
-        public void onFailure(Throwable t) {
-          if (isCancelled()) {
-            return;
-          }
+        /*
+         * If we're about to complete the TimeoutFuture, we want to release our reference to it.
+         * Otherwise, we'll pin it (and its result) in memory until the timeout task is GCed. (The
+         * need to clear our reference to the TimeoutFuture is the reason we use a *static* nested
+         * class with a manual reference back to the "containing" class.)
+         *
+         * This has the nice-ish side effect of limiting reentrancy: run() calls
+         * timeoutFuture.setException() calls run(). That reentrancy would already be harmless,
+         * since timeoutFuture can be set (and delegate cancelled) only once. (And "set only once"
+         * is important for other reasons: run() can still be invoked concurrently in different
+         * threads, even with the above null checks.)
+         */
+        timeoutFutureRef = null;
+        if (delegate.isDone()) {
+          timeoutFuture.setFuture(delegate);
+        } else {
           try {
-            running = fallback.create(t);
-            if (isCancelled()) { // in case cancel called in the meantime
-              running.cancel(wasInterrupted());
-              return;
-            }
-            addCallback(running, new FutureCallback<V>() {
-              @Override
-              public void onSuccess(V value) {
-                set(value);
-              }
-
-              @Override
-              public void onFailure(Throwable t) {
-                if (running.isCancelled()) {
-                  cancel(false);
-                } else {
-                  setException(t);
-                }
-              }
-            }, directExecutor());
-          } catch (Throwable e) {
-            setException(e);
+            // TODO(lukes): this stack trace is particularly useless (all it does is point at the
+            // scheduledexecutorservice thread), consider eliminating it altogether?
+            timeoutFuture.setException(new TimeoutException("Future timed out: " + delegate));
+          } finally {
+            delegate.cancel(true);
           }
         }
-      }, executor);
+      }
     }
 
-    @Override
-    public boolean cancel(boolean mayInterruptIfRunning) {
-      if (super.cancel(mayInterruptIfRunning)) {
-        running.cancel(mayInterruptIfRunning);
-        return true;
+    @Override void done() {
+      maybePropagateCancellation(delegateRef);
+
+      Future<?> localTimer = timer;
+      // Try to cancel the timer as an optimization
+      // timer may be null if this call to run was by the timer task since there is no
+      // happens-before edge between the assignment to timer and an execution of the timer task.
+      if (localTimer != null) {
+        localTimer.cancel(false);
       }
-      return false;
+
+      delegateRef = null;
+      timer = null;
     }
   }
 
@@ -523,28 +984,12 @@ public final class Futures {
    *   ListenableFuture<QueryResult> queryFuture =
    *       transform(rowKeyFuture, queryFunction);}</pre>
    *
-   * <p>Note: If the derived {@code Future} is slow or heavyweight to create
-   * (whether the {@code Future} itself is slow or heavyweight to complete is
-   * irrelevant), consider {@linkplain #transform(ListenableFuture,
-   * AsyncFunction, Executor) supplying an executor}. If you do not supply an
-   * executor, {@code transform} will use a
-   * {@linkplain MoreExecutors#directExecutor direct executor}, which carries
-   * some caveats for heavier operations. For example, the call to {@code
-   * function.apply} may run on an unpredictable or undesirable thread:
-   *
-   * <ul>
-   * <li>If the input {@code Future} is done at the time {@code transform} is
-   * called, {@code transform} will call {@code function.apply} inline.
-   * <li>If the input {@code Future} is not yet done, {@code transform} will
-   * schedule {@code function.apply} to be run by the thread that completes the
-   * input {@code Future}, which may be an internal system thread such as an
-   * RPC network thread.
-   * </ul>
-   *
-   * <p>Also note that, regardless of which thread executes the {@code
-   * function.apply}, all other registered but unexecuted listeners are
-   * prevented from running during its execution, even if those listeners are
-   * to run in other executors.
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code AsyncFunction.apply}, not to any
+   * work done to complete the returned {@code Future}.
    *
    * <p>The returned {@code Future} attempts to keep its cancellation state in
    * sync with that of the input future and that of the future returned by the
@@ -559,13 +1004,15 @@ public final class Futures {
    * @return A future that holds result of the function (if the input succeeded)
    *     or the original input's failure (if not)
    * @since 11.0
+   * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+   *     being renamed to {@code transformAsync}. (The {@code Function}
+   *     overloads are keeping the "transform" name.) This method will be removed in Guava release
+   *     20.0.
    */
+  @Deprecated
   public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
       AsyncFunction<? super I, ? extends O> function) {
-    ChainingListenableFuture<I, O> output =
-        new ChainingListenableFuture<I, O>(function, input);
-    input.addListener(output, directExecutor());
-    return output;
+    return transformAsync(input, function);
   }
 
   /**
@@ -586,6 +1033,13 @@ public final class Futures {
    *   ListenableFuture<QueryResult> queryFuture =
    *       transform(rowKeyFuture, queryFunction, executor);}</pre>
    *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code AsyncFunction.apply}, not to any work done to
+   * complete the returned {@code Future}.
+   *
    * <p>The returned {@code Future} attempts to keep its cancellation state in
    * sync with that of the input future and that of the future returned by the
    * chain function. That is, if the returned {@code Future} is cancelled, it
@@ -593,12 +1047,6 @@ public final class Futures {
    * cancelled, the returned {@code Future} will receive a callback in which it
    * will attempt to cancel itself.
    *
-   * <p>When the execution of {@code function.apply} is fast and lightweight
-   * (though the {@code Future} it returns need not meet these criteria),
-   * consider {@linkplain #transform(ListenableFuture, AsyncFunction) omitting
-   * the executor} or explicitly specifying {@code directExecutor}.
-   * However, be aware of the caveats documented in the link above.
-   *
    * @param input The future to transform
    * @param function A function to transform the result of the input future
    *     to the result of the output future
@@ -606,39 +1054,133 @@ public final class Futures {
    * @return A future that holds result of the function (if the input succeeded)
    *     or the original input's failure (if not)
    * @since 11.0
+   * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+   *     being renamed to {@code transformAsync}. (The {@code Function}
+   *     overloads are keeping the "transform" name.) This method will be removed in Guava release
+   *     20.0.
    */
+  @Deprecated
   public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
       AsyncFunction<? super I, ? extends O> function,
       Executor executor) {
+    return transformAsync(input, function, executor);
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+   * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+   * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+   * original {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transformAsync(rowKeyFuture, queryFunction);}</pre>
+   *
+   * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+   * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+   * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+   * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+   * to complete the returned {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+   * input future and that of the future returned by the function. That is, if the returned {@code
+   * Future} is cancelled, it will attempt to cancel the other two, and if either of the other two
+   * is cancelled, the returned {@code Future} will receive a callback in which it will attempt to
+   * cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future to the result of the
+   *     output future
+   * @return A future that holds result of the function (if the input succeeded) or the original
+   *     input's failure (if not)
+   * @since 19.0 (in 11.0 as {@code transform})
+   */
+  public static <I, O> ListenableFuture<O> transformAsync(
+      ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function) {
+    AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+    input.addListener(output, directExecutor());
+    return output;
+  }
+
+  /**
+   * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+   * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+   * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+   * original {@code Future}. Example:
+   *
+   * <pre>   {@code
+   *   ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+   *   AsyncFunction<RowKey, QueryResult> queryFunction =
+   *       new AsyncFunction<RowKey, QueryResult>() {
+   *         public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+   *           return dataService.read(rowKey);
+   *         }
+   *       };
+   *   ListenableFuture<QueryResult> queryFuture =
+   *       transformAsync(rowKeyFuture, queryFunction, executor);}</pre>
+   *
+   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+   * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+   * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+   * {@code Future}.
+   *
+   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+   * input future and that of the future returned by the chain function. That is, if the returned
+   * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
+   * other two is cancelled, the returned {@code Future} will receive a callback in which it will
+   * attempt to cancel itself.
+   *
+   * @param input The future to transform
+   * @param function A function to transform the result of the input future to the result of the
+   *     output future
+   * @param executor Executor to run the function in.
+   * @return A future that holds result of the function (if the input succeeded) or the original
+   *     input's failure (if not)
+   * @since 19.0 (in 11.0 as {@code transform})
+   */
+  public static <I, O> ListenableFuture<O> transformAsync(ListenableFuture<I> input,
+      AsyncFunction<? super I, ? extends O> function, Executor executor) {
     checkNotNull(executor);
-    ChainingListenableFuture<I, O> output =
-        new ChainingListenableFuture<I, O>(function, input);
-    input.addListener(rejectionPropagatingRunnable(output, output, executor), directExecutor());
+    AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+    input.addListener(output, rejectionPropagatingExecutor(executor, output));
     return output;
   }
 
   /**
-   * Returns a Runnable that will invoke the delegate Runnable on the delegate executor, but if the
-   * task is rejected, it will propagate that rejection to the output future.
+   * Returns an Executor that will propagate {@link RejectedExecutionException} from the delegate
+   * executor to the given {@code future}.
+   *
+   * <p>Note, the returned executor can only be used once.
    */
-  private static Runnable rejectionPropagatingRunnable(
-      final AbstractFuture<?> outputFuture,
-      final Runnable delegateTask,
-      final Executor delegateExecutor) {
-    return new Runnable() {
-      @Override public void run() {
-        final AtomicBoolean thrownFromDelegate = new AtomicBoolean(true);
+  private static Executor rejectionPropagatingExecutor(
+      final Executor delegate, final AbstractFuture<?> future) {
+    checkNotNull(delegate);
+    if (delegate == directExecutor()) {
+      // directExecutor() cannot throw RejectedExecutionException
+      return delegate;
+    }
+    return new Executor() {
+      volatile boolean thrownFromDelegate = true;
+      @Override public void execute(final Runnable command) {
         try {
-          delegateExecutor.execute(new Runnable() {
+          delegate.execute(new Runnable() {
             @Override public void run() {
-              thrownFromDelegate.set(false);
-              delegateTask.run();
+              thrownFromDelegate = false;
+              command.run();
             }
           });
         } catch (RejectedExecutionException e) {
-          if (thrownFromDelegate.get()) {
+          if (thrownFromDelegate) {
             // wrap exception?
-            outputFuture.setException(e);
+            future.setException(e);
           }
           // otherwise it must have been thrown from a transitive call and the delegate runnable
           // should have handled it.
@@ -663,26 +1205,11 @@ public final class Futures {
    *   ListenableFuture<List<Row>> rowsFuture =
    *       transform(queryFuture, rowsFunction);}</pre>
    *
-   * <p>Note: If the transformation is slow or heavyweight, consider {@linkplain
-   * #transform(ListenableFuture, Function, Executor) supplying an executor}.
-   * If you do not supply an executor, {@code transform} will use an inline
-   * executor, which carries some caveats for heavier operations.  For example,
-   * the call to {@code function.apply} may run on an unpredictable or
-   * undesirable thread:
-   *
-   * <ul>
-   * <li>If the input {@code Future} is done at the time {@code transform} is
-   * called, {@code transform} will call {@code function.apply} inline.
-   * <li>If the input {@code Future} is not yet done, {@code transform} will
-   * schedule {@code function.apply} to be run by the thread that completes the
-   * input {@code Future}, which may be an internal system thread such as an
-   * RPC network thread.
-   * </ul>
-   *
-   * <p>Also note that, regardless of which thread executes the {@code
-   * function.apply}, all other registered but unexecuted listeners are
-   * prevented from running during its execution, even if those listeners are
-   * to run in other executors.
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation. The documentation's warnings about "lightweight listeners"
+   * refer here to the work done during {@code Function.apply}.
    *
    * <p>The returned {@code Future} attempts to keep its cancellation state in
    * sync with that of the input future. That is, if the returned {@code Future}
@@ -703,8 +1230,7 @@ public final class Futures {
   public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
       final Function<? super I, ? extends O> function) {
     checkNotNull(function);
-    ChainingListenableFuture<I, O> output =
-        new ChainingListenableFuture<I, O>(asAsyncFunction(function), input);
+    ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
     input.addListener(output, directExecutor());
     return output;
   }
@@ -725,6 +1251,12 @@ public final class Futures {
    *   ListenableFuture<List<Row>> rowsFuture =
    *       transform(queryFuture, rowsFunction, executor);}</pre>
    *
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+   * The documentation's warnings about "lightweight listeners" refer here to
+   * the work done during {@code Function.apply}.
+   *
    * <p>The returned {@code Future} attempts to keep its cancellation state in
    * sync with that of the input future. That is, if the returned {@code Future}
    * is cancelled, it will attempt to cancel the input, and if the input is
@@ -734,11 +1266,6 @@ public final class Futures {
    * <p>An example use of this method is to convert a serializable object
    * returned from an RPC into a POJO.
    *
-   * <p>When the transformation is fast and lightweight, consider {@linkplain
-   * #transform(ListenableFuture, Function) omitting the executor} or
-   * explicitly specifying {@code directExecutor}. However, be aware of the
-   * caveats documented in the link above.
-   *
    * @param input The future to transform
    * @param function A Function to transform the results of the provided future
    *     to the results of the returned future.
@@ -749,18 +1276,9 @@ public final class Futures {
   public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
       final Function<? super I, ? extends O> function, Executor executor) {
     checkNotNull(function);
-    return transform(input, asAsyncFunction(function), executor);
-  }
-
-  /** Wraps the given function as an AsyncFunction. */
-  private static <I, O> AsyncFunction<I, O> asAsyncFunction(
-      final Function<? super I, ? extends O> function) {
-    return new AsyncFunction<I, O>() {
-      @Override public ListenableFuture<O> apply(I input) {
-        O output = function.apply(input);
-        return immediateFuture(output);
-      }
-    };
+    ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+    input.addListener(output, rejectionPropagatingExecutor(executor, output));
+    return output;
   }
 
   /**
@@ -786,6 +1304,8 @@ public final class Futures {
    * @return A future that returns the result of the transformation.
    * @since 10.0
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <I, O> Future<O> lazyTransform(final Future<I> input,
       final Function<? super I, ? extends O> function) {
     checkNotNull(input);
@@ -848,49 +1368,32 @@ public final class Futures {
    * href="http://code.google.com/p/guava-libraries/issues/detail?id=1548">we
    * should remove the {@code UndeclaredThrowableException} special case</a>.
    */
-  private static class ChainingListenableFuture<I, O>
-      extends AbstractFuture<O> implements Runnable {
-
-    private AsyncFunction<? super I, ? extends O> function;
-    private ListenableFuture<? extends I> inputFuture;
-    private volatile ListenableFuture<? extends O> outputFuture;
-
-    private ChainingListenableFuture(
-        AsyncFunction<? super I, ? extends O> function,
-        ListenableFuture<? extends I> inputFuture) {
-      this.function = checkNotNull(function);
+  private abstract static class AbstractChainingFuture<I, O, F>
+      extends AbstractFuture.TrustedFuture<O> implements Runnable {
+    // In theory, this field might not be visible to a cancel() call in certain circumstances. For
+    // details, see the comments on the fields of TimeoutFuture.
+    @Nullable ListenableFuture<? extends I> inputFuture;
+    @Nullable F function;
+
+    AbstractChainingFuture(ListenableFuture<? extends I> inputFuture, F function) {
       this.inputFuture = checkNotNull(inputFuture);
+      this.function = checkNotNull(function);
     }
 
     @Override
-    public boolean cancel(boolean mayInterruptIfRunning) {
-      /*
-       * Our additional cancellation work needs to occur even if
-       * !mayInterruptIfRunning, so we can't move it into interruptTask().
-       */
-      if (super.cancel(mayInterruptIfRunning)) {
-        // This should never block since only one thread is allowed to cancel
-        // this Future.
-        cancel(inputFuture, mayInterruptIfRunning);
-        cancel(outputFuture, mayInterruptIfRunning);
-        return true;
-      }
-      return false;
-    }
-
-    private void cancel(@Nullable Future<?> future,
-        boolean mayInterruptIfRunning) {
-      if (future != null) {
-        future.cancel(mayInterruptIfRunning);
-      }
-    }
-
-    @Override
-    public void run() {
+    public final void run() {
       try {
+        ListenableFuture<? extends I> localInputFuture = inputFuture;
+        F localFunction = function;
+        if (isCancelled() | localInputFuture == null | localFunction == null) {
+          return;
+        }
+        inputFuture = null;
+        function = null;
+
         I sourceResult;
         try {
-          sourceResult = getUninterruptibly(inputFuture);
+          sourceResult = getUninterruptibly(localInputFuture);
         } catch (CancellationException e) {
           // Cancel this future and return.
           // At this point, inputFuture is cancelled and outputFuture doesn't
@@ -902,35 +1405,7 @@ public final class Futures {
           setException(e.getCause());
           return;
         }
-
-        final ListenableFuture<? extends O> outputFuture = this.outputFuture =
-            Preconditions.checkNotNull(function.apply(sourceResult),
-                "AsyncFunction may not return null.");
-        if (isCancelled()) {
-          outputFuture.cancel(wasInterrupted());
-          this.outputFuture = null;
-          return;
-        }
-        outputFuture.addListener(new Runnable() {
-            @Override
-            public void run() {
-              try {
-                set(getUninterruptibly(outputFuture));
-              } catch (CancellationException e) {
-                // Cancel this future and return.
-                // At this point, inputFuture and outputFuture are done, so the
-                // value of mayInterruptIfRunning is irrelevant.
-                cancel(false);
-                return;
-              } catch (ExecutionException e) {
-                // Set the cause of the exception as this future's exception
-                setException(e.getCause());
-              } finally {
-                // Don't pin inputs beyond completion
-                ChainingListenableFuture.this.outputFuture = null;
-              }
-            }
-          }, directExecutor());
+        doTransform(localFunction, sourceResult);
       } catch (UndeclaredThrowableException e) {
         // Set the cause of the exception as this future's exception
         setException(e.getCause());
@@ -938,12 +1413,56 @@ public final class Futures {
         // This exception is irrelevant in this thread, but useful for the
         // client
         setException(t);
-      } finally {
-        // Don't pin inputs beyond completion
-        function = null;
-        inputFuture = null;
       }
     }
+
+    /** Template method for subtypes to actually run the transform. */
+    abstract void doTransform(F function, I result) throws Exception;
+
+    @Override final void done() {
+      maybePropagateCancellation(inputFuture);
+      this.inputFuture = null;
+      this.function = null;
+    }
+  }
+
+  /**
+   * A {@link AbstractChainingFuture} that delegates to an {@link AsyncFunction} and
+   * {@link #setFuture(ListenableFuture)} to implement {@link #doTransform}.
+   */
+  private static final class AsyncChainingFuture<I, O>
+      extends AbstractChainingFuture<I, O, AsyncFunction<? super I, ? extends O>> {
+    AsyncChainingFuture(ListenableFuture<? extends I> inputFuture,
+        AsyncFunction<? super I, ? extends O> function) {
+      super(inputFuture, function);
+    }
+
+    @Override
+    void doTransform(AsyncFunction<? super I, ? extends O> function, I input) throws Exception {
+      ListenableFuture<? extends O> outputFuture = function.apply(input);
+      checkNotNull(outputFuture, "AsyncFunction.apply returned null instead of a Future. "
+          + "Did you mean to return immediateFuture(null)?");
+      setFuture(outputFuture);
+    }
+  }
+
+  /**
+   * A {@link AbstractChainingFuture} that delegates to a {@link Function} and
+   * {@link #set(Object)} to implement {@link #doTransform}.
+   */
+  private static final class ChainingFuture<I, O>
+      extends AbstractChainingFuture<I, O, Function<? super I, ? extends O>> {
+
+    ChainingFuture(ListenableFuture<? extends I> inputFuture,
+        Function<? super I, ? extends O> function) {
+      super(inputFuture, function);
+    }
+
+    @Override
+    void doTransform(Function<? super I, ? extends O> function, I input) {
+      // TODO(lukes): move the UndeclaredThrowable catch block here?
+      set(function.apply(input));
+    }
   }
 
   /**
@@ -968,9 +1487,10 @@ public final class Futures {
    * @since 13.0
    */
   @SuppressWarnings({"rawtypes", "unchecked"})
+  @CheckReturnValue
   public static <V> ListenableFuture<V> dereference(
       ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
-    return Futures.transform((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
+    return transformAsync((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
   }
 
   /**
@@ -1000,9 +1520,11 @@ public final class Futures {
    * @since 10.0
    */
   @Beta
+  @SafeVarargs
+  @CheckReturnValue
   public static <V> ListenableFuture<List<V>> allAsList(
       ListenableFuture<? extends V>... futures) {
-    return listFuture(ImmutableList.copyOf(futures), true, directExecutor());
+    return new ListFuture<V>(ImmutableList.copyOf(futures), true);
   }
 
   /**
@@ -1022,60 +1544,10 @@ public final class Futures {
    * @since 10.0
    */
   @Beta
+  @CheckReturnValue
   public static <V> ListenableFuture<List<V>> allAsList(
       Iterable<? extends ListenableFuture<? extends V>> futures) {
-    return listFuture(ImmutableList.copyOf(futures), true, directExecutor());
-  }
-
-  private static final class WrappedCombiner<T> implements Callable<T> {
-    final Callable<T> delegate;
-    CombinerFuture<T> outputFuture;
-
-    WrappedCombiner(Callable<T> delegate) {
-      this.delegate = checkNotNull(delegate);
-    }
-
-    @Override public T call() throws Exception {
-      try {
-        return delegate.call();
-      } catch (ExecutionException e) {
-        outputFuture.setException(e.getCause());
-      } catch (CancellationException e) {
-        outputFuture.cancel(false);
-      }
-      // at this point the return value doesn't matter since we already called setException or
-      // cancel so the future is done.
-      return null;
-    }
-  }
-
-  private static final class CombinerFuture<V> extends ListenableFutureTask<V> {
-    ImmutableList<ListenableFuture<?>> futures;
-
-    CombinerFuture(Callable<V> callable, ImmutableList<ListenableFuture<?>> futures) {
-      super(callable);
-      this.futures = futures;
-    }
-
-    @Override public boolean cancel(boolean mayInterruptIfRunning) {
-      ImmutableList<ListenableFuture<?>> futures = this.futures;
-      if (super.cancel(mayInterruptIfRunning)) {
-        for (ListenableFuture<?> future : futures) {
-          future.cancel(mayInterruptIfRunning);
-        }
-        return true;
-      }
-      return false;
-    }
-
-    @Override protected void done() {
-      super.done();
-      futures = null;
-    }
-
-    @Override protected void setException(Throwable t) {
-      super.setException(t);
-    }
+    return new ListFuture<V>(ImmutableList.copyOf(futures), true);
   }
 
   /**
@@ -1086,6 +1558,8 @@ public final class Futures {
    *
    * @since 15.0
    */
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <V> ListenableFuture<V> nonCancellationPropagating(
       ListenableFuture<V> future) {
     return new NonCancellationPropagatingFuture<V>(future);
@@ -1094,23 +1568,15 @@ public final class Futures {
   /**
    * A wrapped future that does not propagate cancellation to its delegate.
    */
-  private static class NonCancellationPropagatingFuture<V>
-      extends AbstractFuture<V> {
+  @GwtIncompatible("TODO")
+  private static final class NonCancellationPropagatingFuture<V>
+      extends AbstractFuture.TrustedFuture<V> {
     NonCancellationPropagatingFuture(final ListenableFuture<V> delegate) {
-      checkNotNull(delegate);
-      addCallback(delegate, new FutureCallback<V>() {
-        @Override
-        public void onSuccess(V result) {
-          set(result);
-        }
-
-        @Override
-        public void onFailure(Throwable t) {
-          if (delegate.isCancelled()) {
-            cancel(false);
-          } else {
-            setException(t);
-          }
+      delegate.addListener(new Runnable() {
+        @Override public void run() {
+          // This prevents cancellation from propagating because we don't assign delegate until
+          // delegate is already done, so calling cancel() on it is a no-op.
+          setFuture(delegate);
         }
       }, directExecutor());
     }
@@ -1132,9 +1598,11 @@ public final class Futures {
    * @since 10.0
    */
   @Beta
+  @SafeVarargs
+  @CheckReturnValue
   public static <V> ListenableFuture<List<V>> successfulAsList(
       ListenableFuture<? extends V>... futures) {
-    return listFuture(ImmutableList.copyOf(futures), false, directExecutor());
+    return new ListFuture<V>(ImmutableList.copyOf(futures), false);
   }
 
   /**
@@ -1153,9 +1621,10 @@ public final class Futures {
    * @since 10.0
    */
   @Beta
+  @CheckReturnValue
   public static <V> ListenableFuture<List<V>> successfulAsList(
       Iterable<? extends ListenableFuture<? extends V>> futures) {
-    return listFuture(ImmutableList.copyOf(futures), false, directExecutor());
+    return new ListFuture<V>(ImmutableList.copyOf(futures), false);
   }
 
   /**
@@ -1172,11 +1641,13 @@ public final class Futures {
    * @since 17.0
    */
   @Beta
+  @GwtIncompatible("TODO")
+  @CheckReturnValue
   public static <T> ImmutableList<ListenableFuture<T>> inCompletionOrder(
       Iterable<? extends ListenableFuture<? extends T>> futures) {
     // A CLQ may be overkill here.  We could save some pointers/memory by synchronizing on an
     // ArrayDeque
-    final ConcurrentLinkedQueue<AsyncSettableFuture<T>> delegates =
+    final ConcurrentLinkedQueue<SettableFuture<T>> delegates =
         Queues.newConcurrentLinkedQueue();
     ImmutableList.Builder<ListenableFuture<T>> listBuilder = ImmutableList.builder();
     // Using SerializingExecutor here will ensure that each CompletionOrderListener executes
@@ -1191,7 +1662,7 @@ public final class Futures {
     //    a directExecutor listener on one of the output futures which is an antipattern anyway.
     SerializingExecutor executor = new SerializingExecutor(directExecutor());
     for (final ListenableFuture<? extends T> future : futures) {
-      AsyncSettableFuture<T> delegate = AsyncSettableFuture.create();
+      SettableFuture<T> delegate = SettableFuture.create();
       // Must make sure to add the delegate to the queue first in case the future is already done
       delegates.add(delegate);
       future.addListener(new Runnable() {
@@ -1225,26 +1696,10 @@ public final class Futures {
    *       }
    *     });}</pre>
    *
-   * <p>Note: If the callback is slow or heavyweight, consider {@linkplain
-   * #addCallback(ListenableFuture, FutureCallback, Executor) supplying an
-   * executor}. If you do not supply an executor, {@code addCallback} will use
-   * a {@linkplain MoreExecutors#directExecutor direct executor}, which carries
-   * some caveats for heavier operations. For example, the callback may run on
-   * an unpredictable or undesirable thread:
-   *
-   * <ul>
-   * <li>If the input {@code Future} is done at the time {@code addCallback} is
-   * called, {@code addCallback} will execute the callback inline.
-   * <li>If the input {@code Future} is not yet done, {@code addCallback} will
-   * schedule the callback to be run by the thread that completes the input
-   * {@code Future}, which may be an internal system thread such as an RPC
-   * network thread.
-   * </ul>
-   *
-   * <p>Also note that, regardless of which thread executes the callback, all
-   * other registered but unexecuted listeners are prevented from running
-   * during its execution, even if those listeners are to run in other
-   * executors.
+   * <p>This overload, which does not accept an executor, uses {@code
+   * directExecutor}, a dangerous choice in some cases. See the discussion in
+   * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+   * documentation.
    *
    * <p>For a more general interface to attach a completion listener to a
    * {@code Future}, see {@link ListenableFuture#addListener addListener}.
@@ -1281,10 +1736,9 @@ public final class Futures {
    *       }
    *     }, e);}</pre>
    *
-   * <p>When the callback is fast and lightweight, consider {@linkplain
-   * #addCallback(ListenableFuture, FutureCallback) omitting the executor} or
-   * explicitly specifying {@code directExecutor}. However, be aware of the
-   * caveats documented in the link above.
+   * <p>When selecting an executor, note that {@code directExecutor} is
+   * dangerous in some cases. See the discussion in the {@link
+   * ListenableFuture#addListener ListenableFuture.addListener} documentation.
    *
    * <p>For a more general interface to attach a completion listener to a
    * {@code Future}, see {@link ListenableFuture#addListener addListener}.
@@ -1368,22 +1822,14 @@ public final class Futures {
    * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
    *         RuntimeException} or does not have a suitable constructor
    * @since 10.0
+   * @deprecated Use {@link #getChecked(Future, Class)}. This method will be
+   *     removed in Guava release 20.0.
    */
+  @Deprecated
+  @GwtIncompatible("reflection")
   public static <V, X extends Exception> V get(
       Future<V> future, Class<X> exceptionClass) throws X {
-    checkNotNull(future);
-    checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
-        "Futures.get exception type (%s) must not be a RuntimeException",
-        exceptionClass);
-    try {
-      return future.get();
-    } catch (InterruptedException e) {
-      currentThread().interrupt();
-      throw newWithCause(exceptionClass, e);
-    } catch (ExecutionException e) {
-      wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
-      throw new AssertionError();
-    }
+    return getChecked(future, exceptionClass);
   }
 
   /**
@@ -1433,37 +1879,124 @@ public final class Futures {
    * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
    *         RuntimeException} or does not have a suitable constructor
    * @since 10.0
+   * @deprecated Use {@link #getChecked(Future, Class, long, TimeUnit)}, noting
+   *     the change in parameter order. This method will be removed in Guava
+   *     release 20.0.
    */
+  @Deprecated
+  @GwtIncompatible("reflection")
   public static <V, X extends Exception> V get(
       Future<V> future, long timeout, TimeUnit unit, Class<X> exceptionClass)
       throws X {
-    checkNotNull(future);
-    checkNotNull(unit);
-    checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
-        "Futures.get exception type (%s) must not be a RuntimeException",
-        exceptionClass);
-    try {
-      return future.get(timeout, unit);
-    } catch (InterruptedException e) {
-      currentThread().interrupt();
-      throw newWithCause(exceptionClass, e);
-    } catch (TimeoutException e) {
-      throw newWithCause(exceptionClass, e);
-    } catch (ExecutionException e) {
-      wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
-      throw new AssertionError();
-    }
+    return getChecked(future, exceptionClass, timeout, unit);
   }
 
-  private static <X extends Exception> void wrapAndThrowExceptionOrError(
-      Throwable cause, Class<X> exceptionClass) throws X {
-    if (cause instanceof Error) {
-      throw new ExecutionError((Error) cause);
-    }
-    if (cause instanceof RuntimeException) {
-      throw new UncheckedExecutionException(cause);
-    }
-    throw newWithCause(exceptionClass, cause);
+  /**
+   * Returns the result of {@link Future#get()}, converting most exceptions to a
+   * new instance of the given checked exception type. This reduces boilerplate
+   * for a common use of {@code Future} in which it is unnecessary to
+   * programmatically distinguish between exception types or to extract other
+   * information from the exception instance.
+   *
+   * <p>Exceptions from {@code Future.get} are treated as follows:
+   * <ul>
+   * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+   *     {@code X} if the cause is a checked exception, an {@link
+   *     UncheckedExecutionException} if the cause is a {@code
+   *     RuntimeException}, or an {@link ExecutionError} if the cause is an
+   *     {@code Error}.
+   * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+   *     restoring the interrupt).
+   * <li>Any {@link CancellationException} is propagated untouched, as is any
+   *     other {@link RuntimeException} (though {@code get} implementations are
+   *     discouraged from throwing such exceptions).
+   * </ul>
+   *
+   * <p>The overall principle is to continue to treat every checked exception as a
+   * checked exception, every unchecked exception as an unchecked exception, and
+   * every error as an error. In addition, the cause of any {@code
+   * ExecutionException} is wrapped in order to ensure that the new stack trace
+   * matches that of the current thread.
+   *
+   * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+   * public constructor that accepts zero or more arguments, all of type {@code
+   * String} or {@code Throwable} (preferring constructors with at least one
+   * {@code String}) and calling the constructor via reflection. If the
+   * exception did not already have a cause, one is set by calling {@link
+   * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+   * {@code IllegalArgumentException} is thrown.
+   *
+   * @throws X if {@code get} throws any checked exception except for an {@code
+   *     ExecutionException} whose cause is not itself a checked exception
+   * @throws UncheckedExecutionException if {@code get} throws an {@code
+   *     ExecutionException} with a {@code RuntimeException} as its cause
+   * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+   *     with an {@code Error} as its cause
+   * @throws CancellationException if {@code get} throws a {@code
+   *     CancellationException}
+   * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+   *     RuntimeException} or does not have a suitable constructor
+   * @since 19.0 (in 10.0 as {@code get})
+   */
+  @GwtIncompatible("reflection")
+  public static <V, X extends Exception> V getChecked(
+      Future<V> future, Class<X> exceptionClass) throws X {
+    return FuturesGetChecked.getChecked(future, exceptionClass);
+  }
+
+  /**
+   * Returns the result of {@link Future#get(long, TimeUnit)}, converting most
+   * exceptions to a new instance of the given checked exception type. This
+   * reduces boilerplate for a common use of {@code Future} in which it is
+   * unnecessary to programmatically distinguish between exception types or to
+   * extract other information from the exception instance.
+   *
+   * <p>Exceptions from {@code Future.get} are treated as follows:
+   * <ul>
+   * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+   *     {@code X} if the cause is a checked exception, an {@link
+   *     UncheckedExecutionException} if the cause is a {@code
+   *     RuntimeException}, or an {@link ExecutionError} if the cause is an
+   *     {@code Error}.
+   * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+   *     restoring the interrupt).
+   * <li>Any {@link TimeoutException} is wrapped in an {@code X}.
+   * <li>Any {@link CancellationException} is propagated untouched, as is any
+   *     other {@link RuntimeException} (though {@code get} implementations are
+   *     discouraged from throwing such exceptions).
+   * </ul>
+   *
+   * <p>The overall principle is to continue to treat every checked exception as a
+   * checked exception, every unchecked exception as an unchecked exception, and
+   * every error as an error. In addition, the cause of any {@code
+   * ExecutionException} is wrapped in order to ensure that the new stack trace
+   * matches that of the current thread.
+   *
+   * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+   * public constructor that accepts zero or more arguments, all of type {@code
+   * String} or {@code Throwable} (preferring constructors with at least one
+   * {@code String}) and calling the constructor via reflection. If the
+   * exception did not already have a cause, one is set by calling {@link
+   * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+   * {@code IllegalArgumentException} is thrown.
+   *
+   * @throws X if {@code get} throws any checked exception except for an {@code
+   *     ExecutionException} whose cause is not itself a checked exception
+   * @throws UncheckedExecutionException if {@code get} throws an {@code
+   *     ExecutionException} with a {@code RuntimeException} as its cause
+   * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+   *     with an {@code Error} as its cause
+   * @throws CancellationException if {@code get} throws a {@code
+   *     CancellationException}
+   * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+   *     RuntimeException} or does not have a suitable constructor
+   * @since 19.0 (in 10.0 as {@code get} and with different parameter order)
+   */
+  @GwtIncompatible("reflection")
+  public static <V, X extends Exception> V getChecked(
+      Future<V> future, Class<X> exceptionClass, long timeout, TimeUnit unit)
+      throws X {
+    return FuturesGetChecked.getChecked(future, exceptionClass, timeout, unit);
   }
 
   /**
@@ -1503,6 +2036,7 @@ public final class Futures {
    *         CancellationException}
    * @since 10.0
    */
+  @GwtIncompatible("TODO")
   public static <V> V getUnchecked(Future<V> future) {
     checkNotNull(future);
     try {
@@ -1513,6 +2047,7 @@ public final class Futures {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static void wrapAndThrowUnchecked(Throwable cause) {
     if (cause instanceof Error) {
       throw new ExecutionError((Error) cause);
@@ -1526,11 +2061,6 @@ public final class Futures {
   }
 
   /*
-   * TODO(user): FutureChecker interface for these to be static methods on? If
-   * so, refer to it in the (static-method) Futures.get documentation
-   */
-
-  /*
    * Arguably we don't need a timed getUnchecked because any operation slow
    * enough to require a timeout is heavyweight enough to throw a checked
    * exception and therefore be inappropriate to use with getUnchecked. Further,
@@ -1539,259 +2069,40 @@ public final class Futures {
    * wasn't thrown by the computation -- makes sense, and if we don't convert
    * it, the user still has to write a try-catch block.
    *
-   * If you think you would use this method, let us know.
+   * If you think you would use this method, let us know. You might also also
+   * look into the Fork-Join framework:
+   * http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
    */
 
-  private static <X extends Exception> X newWithCause(
-      Class<X> exceptionClass, Throwable cause) {
-    // getConstructors() guarantees this as long as we don't modify the array.
-    @SuppressWarnings("unchecked")
-    List<Constructor<X>> constructors =
-        (List) Arrays.asList(exceptionClass.getConstructors());
-    for (Constructor<X> constructor : preferringStrings(constructors)) {
-      @Nullable X instance = newFromConstructor(constructor, cause);
-      if (instance != null) {
-        if (instance.getCause() == null) {
-          instance.initCause(cause);
-        }
-        return instance;
-      }
-    }
-    throw new IllegalArgumentException(
-        "No appropriate constructor for exception of type " + exceptionClass
-            + " in response to chained exception", cause);
-  }
-
-  private static <X extends Exception> List<Constructor<X>>
-      preferringStrings(List<Constructor<X>> constructors) {
-    return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
-  }
-
-  private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST =
-      Ordering.natural().onResultOf(new Function<Constructor<?>, Boolean>() {
-        @Override public Boolean apply(Constructor<?> input) {
-          return asList(input.getParameterTypes()).contains(String.class);
-        }
-      }).reverse();
-
-  @Nullable private static <X> X newFromConstructor(
-      Constructor<X> constructor, Throwable cause) {
-    Class<?>[] paramTypes = constructor.getParameterTypes();
-    Object[] params = new Object[paramTypes.length];
-    for (int i = 0; i < paramTypes.length; i++) {
-      Class<?> paramType = paramTypes[i];
-      if (paramType.equals(String.class)) {
-        params[i] = cause.toString();
-      } else if (paramType.equals(Throwable.class)) {
-        params[i] = cause;
-      } else {
-        return null;
-      }
-    }
-    try {
-      return constructor.newInstance(params);
-    } catch (IllegalArgumentException e) {
-      return null;
-    } catch (InstantiationException e) {
-      return null;
-    } catch (IllegalAccessException e) {
-      return null;
-    } catch (InvocationTargetException e) {
-      return null;
-    }
-  }
-
-  private interface FutureCombiner<V, C> {
-    C combine(List<Optional<V>> values);
-  }
-
-  private static class CombinedFuture<V, C> extends AbstractFuture<C> {
-    private static final Logger logger =
-        Logger.getLogger(CombinedFuture.class.getName());
-
-    ImmutableCollection<? extends ListenableFuture<? extends V>> futures;
-    final boolean allMustSucceed;
-    final AtomicInteger remaining;
-    FutureCombiner<V, C> combiner;
-    List<Optional<V>> values;
-    final Object seenExceptionsLock = new Object();
-    Set<Throwable> seenExceptions;
-
-    CombinedFuture(
-        ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
-        boolean allMustSucceed, Executor listenerExecutor,
-        FutureCombiner<V, C> combiner) {
-      this.futures = futures;
-      this.allMustSucceed = allMustSucceed;
-      this.remaining = new AtomicInteger(futures.size());
-      this.combiner = combiner;
-      this.values = Lists.newArrayListWithCapacity(futures.size());
-      init(listenerExecutor);
-    }
-
-    /**
-     * Must be called at the end of the constructor.
-     */
-    protected void init(final Executor listenerExecutor) {
-      // First, schedule cleanup to execute when the Future is done.
-      addListener(new Runnable() {
-        @Override
-        public void run() {
-          // Cancel all the component futures.
-          if (CombinedFuture.this.isCancelled()) {
-            for (ListenableFuture<?> future : CombinedFuture.this.futures) {
-              future.cancel(CombinedFuture.this.wasInterrupted());
-            }
-          }
-
-          // Let go of the memory held by other futures
-          CombinedFuture.this.futures = null;
-
-          // By now the values array has either been set as the Future's value,
-          // or (in case of failure) is no longer useful.
-          CombinedFuture.this.values = null;
-
-          // The combiner may also hold state, so free that as well
-          CombinedFuture.this.combiner = null;
-        }
-      }, directExecutor());
-
-      // Now begin the "real" initialization.
-
-      // Corner case: List is empty.
-      if (futures.isEmpty()) {
-        set(combiner.combine(ImmutableList.<Optional<V>>of()));
-        return;
-      }
-
-      // Populate the results list with null initially.
-      for (int i = 0; i < futures.size(); ++i) {
-        values.add(null);
-      }
-
-      // Register a listener on each Future in the list to update
-      // the state of this future.
-      // Note that if all the futures on the list are done prior to completing
-      // this loop, the last call to addListener() will callback to
-      // setOneValue(), transitively call our cleanup listener, and set
-      // this.futures to null.
-      // This is not actually a problem, since the foreach only needs
-      // this.futures to be non-null at the beginning of the loop.
-      int i = 0;
-      for (final ListenableFuture<? extends V> listenable : futures) {
-        final int index = i++;
-        listenable.addListener(new Runnable() {
-          @Override
-          public void run() {
-            setOneValue(index, listenable);
-          }
-        }, listenerExecutor);
-      }
-    }
-
-    /**
-     * Fails this future with the given Throwable if {@link #allMustSucceed} is
-     * true. Also, logs the throwable if it is an {@link Error} or if
-     * {@link #allMustSucceed} is {@code true}, the throwable did not cause
-     * this future to fail, and it is the first time we've seen that particular Throwable.
-     */
-    private void setExceptionAndMaybeLog(Throwable throwable) {
-      boolean visibleFromOutputFuture = false;
-      boolean firstTimeSeeingThisException = true;
-      if (allMustSucceed) {
-        // As soon as the first one fails, throw the exception up.
-        // The result of all other inputs is then ignored.
-        visibleFromOutputFuture = super.setException(throwable);
-
-        synchronized (seenExceptionsLock) {
-          if (seenExceptions == null) {
-            seenExceptions = Sets.newHashSet();
-          }
-          firstTimeSeeingThisException = seenExceptions.add(throwable);
-        }
-      }
-
-      if (throwable instanceof Error
-          || (allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException)) {
-        logger.log(Level.SEVERE, "input future failed.", throwable);
-      }
+  /** Used for {@link #allAsList} and {@link #successfulAsList}. */
+  private static final class ListFuture<V> extends CollectionFuture<V, List<V>> {
+    ListFuture(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+        boolean allMustSucceed) {
+      init(new ListFutureRunningState(futures, allMustSucceed));
     }
 
-    /**
-     * Sets the value at the given index to that of the given future.
-     */
-    private void setOneValue(int index, Future<? extends V> future) {
-      List<Optional<V>> localValues = values;
-      // TODO(user): This check appears to be redundant since values is
-      // assigned null only after the future completes.  However, values
-      // is not volatile so it may be possible for us to observe the changes
-      // to these two values in a different order... which I think is why
-      // we need to check both.  Clear up this craziness either by making
-      // values volatile or proving that it doesn't need to be for some other
-      // reason.
-      if (isDone() || localValues == null) {
-        // Some other future failed or has been cancelled, causing this one to
-        // also be cancelled or have an exception set. This should only happen
-        // if allMustSucceed is true or if the output itself has been
-        // cancelled.
-        checkState(allMustSucceed || isCancelled(),
-            "Future was done before all dependencies completed");
+    private final class ListFutureRunningState extends CollectionFutureRunningState {
+      ListFutureRunningState(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+        boolean allMustSucceed) {
+        super(futures, allMustSucceed);
       }
 
-      try {
-        checkState(future.isDone(),
-            "Tried to set value from future which is not done");
-        V returnValue = getUninterruptibly(future);
-        if (localValues != null) {
-          localValues.set(index, Optional.fromNullable(returnValue));
-        }
-      } catch (CancellationException e) {
-        if (allMustSucceed) {
-          // Set ourselves as cancelled. Let the input futures keep running
-          // as some of them may be used elsewhere.
-          cancel(false);
-        }
-      } catch (ExecutionException e) {
-        setExceptionAndMaybeLog(e.getCause());
-      } catch (Throwable t) {
-        setExceptionAndMaybeLog(t);
-      } finally {
-        int newRemaining = remaining.decrementAndGet();
-        checkState(newRemaining >= 0, "Less than 0 remaining futures");
-        if (newRemaining == 0) {
-          FutureCombiner<V, C> localCombiner = combiner;
-          if (localCombiner != null && localValues != null) {
-            set(localCombiner.combine(localValues));
-          } else {
-            checkState(isDone());
-          }
+      @Override
+      public List<V> combine(List<Optional<V>> values) {
+        List<V> result = Lists.newArrayList();
+        for (Optional<V> element : values) {
+          result.add(element != null ? element.orNull() : null);
         }
+        return Collections.unmodifiableList(result);
       }
     }
   }
 
-  /** Used for {@link #allAsList} and {@link #successfulAsList}. */
-  private static <V> ListenableFuture<List<V>> listFuture(
-      ImmutableList<ListenableFuture<? extends V>> futures,
-      boolean allMustSucceed, Executor listenerExecutor) {
-    return new CombinedFuture<V, List<V>>(
-        futures, allMustSucceed, listenerExecutor,
-        new FutureCombiner<V, List<V>>() {
-          @Override
-          public List<V> combine(List<Optional<V>> values) {
-            List<V> result = Lists.newArrayList();
-            for (Optional<V> element : values) {
-              result.add(element != null ? element.orNull() : null);
-            }
-            return Collections.unmodifiableList(result);
-          }
-        });
-  }
-
   /**
    * A checked future that uses a function to map from exceptions to the
    * appropriate checked type.
    */
+  @GwtIncompatible("TODO")
   private static class MappingCheckedFuture<V, X extends Exception> extends
       AbstractCheckedFuture<V, X> {
 
diff --git a/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java
new file mode 100644
index 0000000..99441ea
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java
@@ -0,0 +1,309 @@
+/*
+ * 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.Thread.currentThread;
+import static java.util.Arrays.asList;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Ordering;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
+
+import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nullable;
+
+/**
+ * Static methods used to implement {@link Futures#getChecked(Future, Class)}.
+ */
+final class FuturesGetChecked {
+  static <V, X extends Exception> V getChecked(Future<V> future, Class<X> exceptionClass) throws X {
+    return getChecked(bestGetCheckedTypeValidator(), future, exceptionClass);
+  }
+
+  /**
+   * Implementation of {@link Futures#getChecked(Future, Class)}.
+   */
+  @VisibleForTesting
+  static <V, X extends Exception> V getChecked(
+      GetCheckedTypeValidator validator, Future<V> future, Class<X> exceptionClass) throws X {
+    validator.validateClass(exceptionClass);
+    try {
+      return future.get();
+    } catch (InterruptedException e) {
+      currentThread().interrupt();
+      throw newWithCause(exceptionClass, e);
+    } catch (ExecutionException e) {
+      wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+      throw new AssertionError();
+    }
+  }
+
+  /**
+   * Implementation of {@link Futures#getChecked(Future, Class, long, TimeUnit)}.
+   */
+  static <V, X extends Exception> V getChecked(
+      Future<V> future, Class<X> exceptionClass, long timeout, TimeUnit unit) throws X {
+    // TODO(cpovirk): benchmark a version of this method that accepts a GetCheckedTypeValidator
+    bestGetCheckedTypeValidator().validateClass(exceptionClass);
+    try {
+      return future.get(timeout, unit);
+    } catch (InterruptedException e) {
+      currentThread().interrupt();
+      throw newWithCause(exceptionClass, e);
+    } catch (TimeoutException e) {
+      throw newWithCause(exceptionClass, e);
+    } catch (ExecutionException e) {
+      wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+      throw new AssertionError();
+    }
+  }
+
+  @VisibleForTesting
+  interface GetCheckedTypeValidator {
+    void validateClass(Class<? extends Exception> exceptionClass);
+  }
+
+  private static GetCheckedTypeValidator bestGetCheckedTypeValidator() {
+    return GetCheckedTypeValidatorHolder.BEST_VALIDATOR;
+  }
+
+  @VisibleForTesting
+  static GetCheckedTypeValidator weakSetValidator() {
+    return GetCheckedTypeValidatorHolder.WeakSetValidator.INSTANCE;
+  }
+
+  @J2ObjCIncompatible // ClassValue
+  @VisibleForTesting
+  static GetCheckedTypeValidator classValueValidator() {
+    return GetCheckedTypeValidatorHolder.ClassValueValidator.INSTANCE;
+  }
+
+  /**
+   * Provides a check of whether an exception type is valid for use with
+   * {@link FuturesGetChecked#getChecked(Future, Class)}, possibly using caching.
+   *
+   * <p>Uses reflection to gracefully fall back to when certain implementations aren't available.
+   */
+  @VisibleForTesting
+  static class GetCheckedTypeValidatorHolder {
+    static final String CLASS_VALUE_VALIDATOR_NAME =
+        GetCheckedTypeValidatorHolder.class.getName() + "$ClassValueValidator";
+
+    static final GetCheckedTypeValidator BEST_VALIDATOR = getBestValidator();
+
+    @IgnoreJRERequirement // getChecked falls back to another implementation if necessary
+    @J2ObjCIncompatible // ClassValue
+    enum ClassValueValidator implements GetCheckedTypeValidator {
+      INSTANCE;
+
+      /*
+       * Static final fields are presumed to be fastest, based on our experience with
+       * UnsignedBytesBenchmark. TODO(cpovirk): benchmark this
+       */
+      private static final ClassValue<Boolean> isValidClass =
+          new ClassValue<Boolean>() {
+            @Override
+            protected Boolean computeValue(Class<?> type) {
+              checkExceptionClassValidity(type.asSubclass(Exception.class));
+              return true;
+            }
+          };
+
+      @Override
+      public void validateClass(Class<? extends Exception> exceptionClass) {
+        isValidClass.get(exceptionClass); // throws if invalid; returns safely (and caches) if valid
+      }
+    }
+
+    enum WeakSetValidator implements GetCheckedTypeValidator {
+      INSTANCE;
+
+      /*
+       * Static final fields are presumed to be fastest, based on our experience with
+       * UnsignedBytesBenchmark. TODO(cpovirk): benchmark this
+       */
+      /*
+       * A CopyOnWriteArraySet<WeakReference> is faster than a newSetFromMap of a MapMaker map with
+       * weakKeys() and concurrencyLevel(1), even up to at least 12 cached exception types.
+       */
+      private static final Set<WeakReference<Class<? extends Exception>>> validClasses =
+          new CopyOnWriteArraySet<WeakReference<Class<? extends Exception>>>();
+
+      @Override
+      public void validateClass(Class<? extends Exception> exceptionClass) {
+        for (WeakReference<Class<? extends Exception>> knownGood : validClasses) {
+          if (exceptionClass.equals(knownGood.get())) {
+            return;
+          }
+          // TODO(cpovirk): if reference has been cleared, remove it?
+        }
+        checkExceptionClassValidity(exceptionClass);
+
+        /*
+         * It's very unlikely that any loaded Futures class will see getChecked called with more
+         * than a handful of exceptions. But it seems prudent to set a cap on how many we'll cache.
+         * This avoids out-of-control memory consumption, and it keeps the cache from growing so
+         * large that doing the lookup is noticeably slower than redoing the work would be.
+         *
+         * Ideally we'd have a real eviction policy, but until we see a problem in practice, I hope
+         * that this will suffice. I have not even benchmarked with different size limits.
+         */
+        if (validClasses.size() > 1000) {
+          validClasses.clear();
+        }
+
+        validClasses.add(new WeakReference<Class<? extends Exception>>(exceptionClass));
+      }
+    }
+
+    /**
+     * Returns the ClassValue-using validator, or falls back to the "weak Set" implementation if
+     * unable to do so.
+     */
+    static GetCheckedTypeValidator getBestValidator() {
+      try {
+        Class<?> theClass = Class.forName(CLASS_VALUE_VALIDATOR_NAME);
+        return (GetCheckedTypeValidator) theClass.getEnumConstants()[0];
+      } catch (Throwable t) { // ensure we really catch *everything*
+        return weakSetValidator();
+      }
+    }
+  }
+
+  // TODO(cpovirk): change parameter order to match other helper methods (Class, Throwable)?
+  private static <X extends Exception> void wrapAndThrowExceptionOrError(
+      Throwable cause, Class<X> exceptionClass) throws X {
+    if (cause instanceof Error) {
+      throw new ExecutionError((Error) cause);
+    }
+    if (cause instanceof RuntimeException) {
+      throw new UncheckedExecutionException(cause);
+    }
+    throw newWithCause(exceptionClass, cause);
+  }
+
+  /*
+   * TODO(user): FutureChecker interface for these to be static methods on? If
+   * so, refer to it in the (static-method) Futures.getChecked documentation
+   */
+
+  private static boolean hasConstructorUsableByGetChecked(
+      Class<? extends Exception> exceptionClass) {
+    try {
+      newWithCause(exceptionClass, new Exception());
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private static <X extends Exception> X newWithCause(Class<X> exceptionClass, Throwable cause) {
+    // getConstructors() guarantees this as long as we don't modify the array.
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    List<Constructor<X>> constructors = (List) Arrays.asList(exceptionClass.getConstructors());
+    for (Constructor<X> constructor : preferringStrings(constructors)) {
+      @Nullable X instance = newFromConstructor(constructor, cause);
+      if (instance != null) {
+        if (instance.getCause() == null) {
+          instance.initCause(cause);
+        }
+        return instance;
+      }
+    }
+    throw new IllegalArgumentException(
+        "No appropriate constructor for exception of type "
+            + exceptionClass
+            + " in response to chained exception",
+        cause);
+  }
+
+  private static <X extends Exception> List<Constructor<X>> preferringStrings(
+      List<Constructor<X>> constructors) {
+    return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
+  }
+
+  private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST =
+      Ordering.natural()
+          .onResultOf(
+              new Function<Constructor<?>, Boolean>() {
+                @Override
+                public Boolean apply(Constructor<?> input) {
+                  return asList(input.getParameterTypes()).contains(String.class);
+                }
+              })
+          .reverse();
+
+  @Nullable
+  private static <X> X newFromConstructor(Constructor<X> constructor, Throwable cause) {
+    Class<?>[] paramTypes = constructor.getParameterTypes();
+    Object[] params = new Object[paramTypes.length];
+    for (int i = 0; i < paramTypes.length; i++) {
+      Class<?> paramType = paramTypes[i];
+      if (paramType.equals(String.class)) {
+        params[i] = cause.toString();
+      } else if (paramType.equals(Throwable.class)) {
+        params[i] = cause;
+      } else {
+        return null;
+      }
+    }
+    try {
+      return constructor.newInstance(params);
+    } catch (IllegalArgumentException e) {
+      return null;
+    } catch (InstantiationException e) {
+      return null;
+    } catch (IllegalAccessException e) {
+      return null;
+    } catch (InvocationTargetException e) {
+      return null;
+    }
+  }
+
+  @VisibleForTesting
+  static boolean isCheckedException(Class<? extends Exception> type) {
+    return !RuntimeException.class.isAssignableFrom(type);
+  }
+
+  @VisibleForTesting
+  static void checkExceptionClassValidity(Class<? extends Exception> exceptionClass) {
+    checkArgument(
+        isCheckedException(exceptionClass),
+        "Futures.getChecked exception type (%s) must not be a RuntimeException",
+        exceptionClass);
+    checkArgument(
+        hasConstructorUsableByGetChecked(exceptionClass),
+        "Futures.getChecked exception type (%s) must be an accessible class with an accessible "
+            + "constructor whose parameters (if any) must be of type String and/or Throwable",
+        exceptionClass);
+  }
+
+  private FuturesGetChecked() {}
+}
diff --git a/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java b/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
new file mode 100644
index 0000000..7b08339
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
@@ -0,0 +1,33 @@
+/*
+ * 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.util.concurrent;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Hidden superclass of {@link Futures} that provides us a place to declare special GWT versions of
+ * the {@link Futures#catching(ListenableFuture, Class, com.google.common.base.Function)
+ * Futures.catching} family of methods. Those versions have slightly different signatures.
+ */
+ at GwtCompatible(emulated = true)
+abstract class GwtFuturesCatchingSpecialization {
+  /*
+   * This server copy of the class is empty. The corresponding GWT copy contains alternative
+   * versions of catching() and catchingAsync() with slightly different signatures from the ones
+   * found in Futures.java.
+   */
+}
diff --git a/guava/src/com/google/common/util/concurrent/InterruptibleTask.java b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java
new file mode 100644
index 0000000..36c7167
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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.util.concurrent;
+
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+ at GwtCompatible(emulated = true)
+abstract class InterruptibleTask implements Runnable {
+  private static final AtomicReferenceFieldUpdater<InterruptibleTask, Thread> RUNNER =
+      newUpdater(InterruptibleTask.class, Thread.class, "runner");
+
+  // These two fields are used to interrupt running tasks.  The thread executing the task
+  // publishes itself to the 'runner' field and the thread interrupting sets 'doneInterrupting'
+  // when it has finished interrupting.
+  private volatile Thread runner;
+  private volatile boolean doneInterrupting;
+
+  @Override public final void run() {
+    if (!RUNNER.compareAndSet(this, null, Thread.currentThread())) {
+      return;  // someone else has run or is running.
+    }
+    try {
+      runInterruptibly();
+    } finally {
+      if (wasInterrupted()) {
+        // We were interrupted, it is possible that the interrupted bit hasn't been set yet.  Wait
+        // for the interrupting thread to set 'doneInterrupting' to true. See interruptTask().
+        // We want to wait so that we don't interrupt the _next_ thing run on the thread.
+        // Note. We don't reset the interrupted bit, just wait for it to be set.
+        // If this is a thread pool thread, the thread pool will reset it for us.  Otherwise, the
+        // interrupted bit may have been intended for something else, so don't clear it.
+        while (!doneInterrupting) {
+          Thread.yield();
+        }
+      }
+    }
+  }
+
+  abstract void runInterruptibly();
+
+  abstract boolean wasInterrupted();
+
+  final void interruptTask() {
+    // interruptTask is guaranteed to be called at most once and if runner is non-null when that
+    // happens then it must have been the first thread that entered run().  So there is no risk
+    // that we are interrupting the wrong thread.
+    Thread currentRunner = runner;
+    if (currentRunner != null) {
+      currentRunner.interrupt();
+    }
+    doneInterrupting = true;
+  }
+}
diff --git a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
index 099d0b7..00612d1 100644
--- a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
+++ b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
@@ -157,6 +157,7 @@ public final class JdkFutureAdapters {
           return;
         }
 
+        // TODO(lukes): handle RejectedExecutionException
         adapterExecutor.execute(new Runnable() {
           @Override
           public void run() {
@@ -168,11 +169,9 @@ public final class JdkFutureAdapters {
                * instead of using listenInPoolThread.
                */
               getUninterruptibly(delegate);
-            } catch (Error e) {
-              throw e;
             } catch (Throwable e) {
-              // ExecutionException / CancellationException / RuntimeException
-              // The task is done, run the listeners.
+              // ExecutionException / CancellationException / RuntimeException / Error
+              // The task is presumably done, run the listeners.
             }
             executionList.execute();
           }
diff --git a/guava/src/com/google/common/util/concurrent/ListenableFuture.java b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
index 7d169ec..9f839a1 100644
--- a/guava/src/com/google/common/util/concurrent/ListenableFuture.java
+++ b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -16,6 +16,8 @@
 
 package com.google.common.util.concurrent;
 
+import com.google.common.annotations.GwtCompatible;
+
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
@@ -30,7 +32,7 @@ import java.util.concurrent.RejectedExecutionException;
  * immediately.
  * 
  * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
  * {@code ListenableFuture}</a>.
  *
  * <h3>Purpose</h3>
@@ -60,9 +62,10 @@ import java.util.concurrent.RejectedExecutionException;
  * <h3>How to get an instance</h3>
  *
  * <p>Developers are encouraged to return {@code ListenableFuture} from their
- * methods so that users can take advantages of the utilities built atop the
- * class. The way that they will create {@code ListenableFuture} instances
- * depends on how they currently create {@code Future} instances:
+ * methods so that users can take advantages of the {@linkplain Futures
+ * utilities built atop the class}. The way that they will create {@code
+ * ListenableFuture} instances depends on how they currently create {@code
+ * Future} instances:
  * <ul>
  * <li>If they are returned from an {@code ExecutorService}, convert that
  * service to a {@link ListeningExecutorService}, usually by calling {@link
@@ -83,6 +86,7 @@ import java.util.concurrent.RejectedExecutionException;
  * @author Nishant Thakkar
  * @since 1.0
  */
+ at GwtCompatible
 public interface ListenableFuture<V> extends Future<V> {
   /**
    * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on
@@ -101,29 +105,30 @@ public interface ListenableFuture<V> extends Future<V> {
    * logged.
    *
    * <p>Note: For fast, lightweight listeners that would be safe to execute in
-   * any thread, consider {@link MoreExecutors#directExecutor}. For heavier
-   * listeners, {@code directExecutor()} carries some caveats.  For
-   * example, the listener may run on an unpredictable or undesirable thread:
+   * any thread, consider {@link MoreExecutors#directExecutor}. Otherwise, avoid
+   * it. Heavyweight {@code directExecutor} listeners can cause problems, and
+   * these problems can be difficult to reproduce because they depend on timing.
+   * For example:
    *
    * <ul>
-   * <li>If this {@code Future} is done at the time {@code addListener} is
-   * called, {@code addListener} will execute the listener inline.
-   * <li>If this {@code Future} is not yet done, {@code addListener} will
-   * schedule the listener to be run by the thread that completes this {@code
-   * Future}, which may be an internal system thread such as an RPC network
-   * thread.
+   * <li>The listener may be executed by the caller of {@code addListener}. That
+   * caller may be a UI thread or other latency-sensitive thread. This can harm
+   * UI responsiveness.
+   * <li>The listener may be executed by the thread that completes this {@code
+   * Future}. That thread may be an internal system thread such as an RPC
+   * network thread. Blocking that thread may stall progress of the whole
+   * system. It may even cause a deadlock.
+   * <li>The listener may delay other listeners, even listeners that are not
+   * themselves {@code directExecutor} listeners.
    * </ul>
    *
-   * <p>Also note that, regardless of which thread executes the
-   * {@code directExecutor()} listener, all other registered but unexecuted
-   * listeners are prevented from running during its execution, even if those
-   * listeners are to run in other executors.
-   *
    * <p>This is the most general listener interface. For common operations
-   * performed using listeners, see {@link
-   * com.google.common.util.concurrent.Futures}. For a simplified but general
-   * listener interface, see {@link
-   * com.google.common.util.concurrent.Futures#addCallback addCallback()}.
+   * performed using listeners, see {@link Futures}. For a simplified but
+   * general listener interface, see {@link Futures#addCallback addCallback()}.
+   *
+   * <p>Memory consistency effects: Actions in a thread prior to adding a listener
+   * <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
+   * <i>happen-before</i></a> its execution begins, perhaps in another thread.
    *
    * @param listener the listener to run when the computation is complete
    * @param executor the executor to run the listener in
diff --git a/guava/src/com/google/common/util/concurrent/Monitor.java b/guava/src/com/google/common/util/concurrent/Monitor.java
index 2e15ea8..b242725 100644
--- a/guava/src/com/google/common/util/concurrent/Monitor.java
+++ b/guava/src/com/google/common/util/concurrent/Monitor.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.Weak;
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
@@ -276,6 +277,19 @@ public final class Monitor {
    * participating in the signal-passing game.
    */
 
+  /*
+   * Timeout handling is intricate, especially given our ambitious goals:
+   * - Avoid underflow and overflow of timeout values when specified timeouts are close to
+   *   Long.MIN_VALUE or Long.MAX_VALUE.
+   * - Favor responding to interrupts over timeouts.
+   * - System.nanoTime() is expensive enough that we want to call it the minimum required number of
+   *   times, typically once before invoking a blocking method.  This often requires keeping track
+   *   of the first time in a method that nanoTime() has been invoked, for which the special value
+   *   0L is reserved to mean "uninitialized".  If timeout is non-positive, then nanoTime need
+   *   never be called.
+   * - Keep behavior of fair and non-fair instances consistent.
+   */
+
   /**
    * A boolean condition for which a thread may wait. A {@code Guard} is associated with a single
    * {@code Monitor}. The monitor may check the guard at arbitrary times from any thread occupying
@@ -290,7 +304,7 @@ public final class Monitor {
   @Beta
   public abstract static class Guard {
 
-    final Monitor monitor;
+    @Weak final Monitor monitor;
     final Condition condition;
 
     @GuardedBy("monitor.lock")
@@ -359,6 +373,8 @@ public final class Monitor {
 
   /**
    * Enters this monitor. Blocks indefinitely, but may be interrupted.
+   *
+   * @throws InterruptedException if interrupted while waiting
    */
   public void enterInterruptibly() throws InterruptedException {
     lock.lockInterruptibly();
@@ -370,20 +386,20 @@ public final class Monitor {
    * @return whether the monitor was entered
    */
   public boolean enter(long time, TimeUnit unit) {
-    long timeoutNanos = unit.toNanos(time);
+    final long timeoutNanos = toSafeNanos(time, unit);
     final ReentrantLock lock = this.lock;
     if (!fair && lock.tryLock()) {
       return true;
     }
-    long deadline = System.nanoTime() + timeoutNanos;
     boolean interrupted = Thread.interrupted();
     try {
-      while (true) {
+      final long startTime = System.nanoTime();
+      for (long remainingNanos = timeoutNanos;;) {
         try {
-          return lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
+          return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
         } catch (InterruptedException interrupt) {
           interrupted = true;
-          timeoutNanos = deadline - System.nanoTime();
+          remainingNanos = remainingNanos(startTime, timeoutNanos);
         }
       }
     } finally {
@@ -397,6 +413,7 @@ public final class Monitor {
    * Enters this monitor. Blocks at most the given time, and may be interrupted.
    *
    * @return whether the monitor was entered
+   * @throws InterruptedException if interrupted while waiting
    */
   public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
     return lock.tryLock(time, unit);
@@ -415,6 +432,8 @@ public final class Monitor {
 
   /**
    * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
+   *
+   * @throws InterruptedException if interrupted while waiting
    */
   public void enterWhen(Guard guard) throws InterruptedException {
     if (guard.monitor != this) {
@@ -466,27 +485,43 @@ public final class Monitor {
    * the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
    * interrupted.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
+   * @throws InterruptedException if interrupted while waiting
    */
   public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
-    long timeoutNanos = unit.toNanos(time);
+    final long timeoutNanos = toSafeNanos(time, unit);
     if (guard.monitor != this) {
       throw new IllegalMonitorStateException();
     }
     final ReentrantLock lock = this.lock;
     boolean reentrant = lock.isHeldByCurrentThread();
-    if (fair || !lock.tryLock()) {
-      long deadline = System.nanoTime() + timeoutNanos;
+    long startTime = 0L;
+
+ locked: {
+      if (!fair) {
+        // Check interrupt status to get behavior consistent with fair case.
+        if (Thread.interrupted()) {
+          throw new InterruptedException();
+        }
+        if (lock.tryLock()) {
+          break locked;
+        }
+      }
+      startTime = initNanoTime(timeoutNanos);
       if (!lock.tryLock(time, unit)) {
         return false;
       }
-      timeoutNanos = deadline - System.nanoTime();
     }
 
     boolean satisfied = false;
     boolean threw = true;
     try {
-      satisfied = guard.isSatisfied() || awaitNanos(guard, timeoutNanos, reentrant);
+      satisfied = guard.isSatisfied()
+          || awaitNanos(guard,
+                        (startTime == 0L)
+                            ? timeoutNanos
+                            : remainingNanos(startTime, timeoutNanos),
+                        reentrant);
       threw = false;
       return satisfied;
     } finally {
@@ -507,43 +542,54 @@ public final class Monitor {
    * Enters this monitor when the guard is satisfied. Blocks at most the given time, including
    * both the time to acquire the lock and the time to wait for the guard to be satisfied.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
    */
   public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
-    long timeoutNanos = unit.toNanos(time);
+    final long timeoutNanos = toSafeNanos(time, unit);
     if (guard.monitor != this) {
       throw new IllegalMonitorStateException();
     }
     final ReentrantLock lock = this.lock;
-    long deadline = System.nanoTime() + timeoutNanos;
+    long startTime = 0L;
     boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
     boolean interrupted = Thread.interrupted();
     try {
       if (fair || !lock.tryLock()) {
-        boolean locked = false;
-        do {
+        startTime = initNanoTime(timeoutNanos);
+        for (long remainingNanos = timeoutNanos;;) {
           try {
-            locked = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
-            if (!locked) {
+            if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
+              break;
+            } else {
               return false;
             }
           } catch (InterruptedException interrupt) {
             interrupted = true;
+            remainingNanos = remainingNanos(startTime, timeoutNanos);
           }
-          timeoutNanos = deadline - System.nanoTime();
-        } while (!locked);
+        }
       }
 
       boolean satisfied = false;
       try {
         while (true) {
           try {
-            return satisfied = guard.isSatisfied()
-                || awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
+            if (guard.isSatisfied()) {
+              satisfied = true;
+            } else {
+              final long remainingNanos;
+              if (startTime == 0L) {
+                startTime = initNanoTime(timeoutNanos);
+                remainingNanos = timeoutNanos;
+              } else {
+                remainingNanos = remainingNanos(startTime, timeoutNanos);
+              }
+              satisfied = awaitNanos(guard, remainingNanos, signalBeforeWaiting);
+            }
+            return satisfied;
           } catch (InterruptedException interrupt) {
             interrupted = true;
             signalBeforeWaiting = false;
-            timeoutNanos = deadline - System.nanoTime();
           }
         }
       } finally {
@@ -562,7 +608,7 @@ public final class Monitor {
    * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
    * does not wait for the guard to be satisfied.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
    */
   public boolean enterIf(Guard guard) {
     if (guard.monitor != this) {
@@ -585,7 +631,8 @@ public final class Monitor {
    * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
    * not wait for the guard to be satisfied, and may be interrupted.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
+   * @throws InterruptedException if interrupted while waiting
    */
   public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
     if (guard.monitor != this) {
@@ -608,7 +655,7 @@ public final class Monitor {
    * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
    * lock, but does not wait for the guard to be satisfied.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
    */
   public boolean enterIf(Guard guard, long time, TimeUnit unit) {
     if (guard.monitor != this) {
@@ -632,7 +679,7 @@ public final class Monitor {
    * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
    * lock, but does not wait for the guard to be satisfied, and may be interrupted.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
    */
   public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
       throws InterruptedException {
@@ -660,7 +707,7 @@ public final class Monitor {
    *
    * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
    *
-   * @return whether the monitor was entered with the guard satisfied
+   * @return whether the monitor was entered, which guarantees that the guard is now satisfied
    */
   public boolean tryEnterIf(Guard guard) {
     if (guard.monitor != this) {
@@ -684,6 +731,8 @@ public final class Monitor {
   /**
    * Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
    * called only by a thread currently occupying this monitor.
+   *
+   * @throws InterruptedException if interrupted while waiting
    */
   public void waitFor(Guard guard) throws InterruptedException {
     if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
@@ -712,13 +761,20 @@ public final class Monitor {
    * May be called only by a thread currently occupying this monitor.
    *
    * @return whether the guard is now satisfied
+   * @throws InterruptedException if interrupted while waiting
    */
   public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
-    long timeoutNanos = unit.toNanos(time);
+    final long timeoutNanos = toSafeNanos(time, unit);
     if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
       throw new IllegalMonitorStateException();
     }
-    return guard.isSatisfied() || awaitNanos(guard, timeoutNanos, true);
+    if (guard.isSatisfied()) {
+      return true;
+    }
+    if (Thread.interrupted()) {
+      throw new InterruptedException();
+    }
+    return awaitNanos(guard, timeoutNanos, true);
   }
 
   /**
@@ -728,7 +784,7 @@ public final class Monitor {
    * @return whether the guard is now satisfied
    */
   public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
-    long timeoutNanos = unit.toNanos(time);
+    final long timeoutNanos = toSafeNanos(time, unit);
     if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
       throw new IllegalMonitorStateException();
     }
@@ -736,19 +792,19 @@ public final class Monitor {
       return true;
     }
     boolean signalBeforeWaiting = true;
-    long deadline = System.nanoTime() + timeoutNanos;
+    final long startTime = initNanoTime(timeoutNanos);
     boolean interrupted = Thread.interrupted();
     try {
-      while (true) {
+      for (long remainingNanos = timeoutNanos;;) {
         try {
-          return awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
+          return awaitNanos(guard, remainingNanos, signalBeforeWaiting);
         } catch (InterruptedException interrupt) {
           interrupted = true;
           if (guard.isSatisfied()) {
             return true;
           }
           signalBeforeWaiting = false;
-          timeoutNanos = deadline - System.nanoTime();
+          remainingNanos = remainingNanos(startTime, timeoutNanos);
         }
       }
     } finally {
@@ -863,6 +919,46 @@ public final class Monitor {
   }
 
   /**
+   * Returns unit.toNanos(time), additionally ensuring the returned value is not at risk of
+   * overflowing or underflowing, by bounding the value between 0 and (Long.MAX_VALUE / 4) * 3.
+   * Actually waiting for more than 219 years is not supported!
+   */
+  private static long toSafeNanos(long time, TimeUnit unit) {
+    long timeoutNanos = unit.toNanos(time);
+    return (timeoutNanos <= 0L) ? 0L
+        : (timeoutNanos > (Long.MAX_VALUE / 4) * 3) ? (Long.MAX_VALUE / 4) * 3
+        : timeoutNanos;
+  }
+
+  /**
+   * Returns System.nanoTime() unless the timeout has already elapsed.
+   * Returns 0L if and only if the timeout has already elapsed.
+   */
+  private static long initNanoTime(long timeoutNanos) {
+    if (timeoutNanos <= 0L) {
+      return 0L;
+    } else {
+      long startTime = System.nanoTime();
+      return (startTime == 0L) ? 1L : startTime;
+    }
+  }
+
+  /**
+   * Returns the remaining nanos until the given timeout, or 0L if the timeout has already elapsed.
+   * Caller must have previously sanitized timeoutNanos using toSafeNanos.
+   */
+  private static long remainingNanos(long startTime, long timeoutNanos) {
+    // assert timeoutNanos == 0L || startTime != 0L;
+
+    // TODO : NOT CORRECT, BUT TESTS PASS ANYWAYS!
+    // if (true) return timeoutNanos;
+    // ONLY 2 TESTS FAIL IF WE DO:
+    // if (true) return 0;
+
+    return (timeoutNanos <= 0L) ? 0L : timeoutNanos - (System.nanoTime() - startTime);
+  }
+
+  /**
    * Signals some other thread waiting on a satisfied guard, if one exists.
    *
    * We manage calls to this method carefully, to signal only when necessary, but never losing a
@@ -980,7 +1076,7 @@ public final class Monitor {
    */
 
   @GuardedBy("lock")
-    private void await(Guard guard, boolean signalBeforeWaiting)
+  private void await(Guard guard, boolean signalBeforeWaiting)
       throws InterruptedException {
     if (signalBeforeWaiting) {
       signalNextWaiter();
@@ -1010,23 +1106,32 @@ public final class Monitor {
     }
   }
 
+  /**
+   * Caller should check before calling that guard is not satisfied.
+   */
   @GuardedBy("lock")
   private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting)
       throws InterruptedException {
-    if (signalBeforeWaiting) {
-      signalNextWaiter();
-    }
-    beginWaitingFor(guard);
+    boolean firstTime = true;
     try {
       do {
-        if (nanos < 0L) {
+        if (nanos <= 0L) {
           return false;
         }
+        if (firstTime) {
+          if (signalBeforeWaiting) {
+            signalNextWaiter();
+          }
+          beginWaitingFor(guard);
+          firstTime = false;
+        }
         nanos = guard.condition.awaitNanos(nanos);
       } while (!guard.isSatisfied());
       return true;
     } finally {
-      endWaitingFor(guard);
+      if (!firstTime) {
+        endWaitingFor(guard);
+      }
     }
   }
 
diff --git a/guava/src/com/google/common/util/concurrent/MoreExecutors.java b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
index e0b1045..6549e57 100644
--- a/guava/src/com/google/common/util/concurrent/MoreExecutors.java
+++ b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
@@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Supplier;
 import com.google.common.base.Throwables;
@@ -49,9 +51,8 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+
+import javax.annotation.concurrent.GuardedBy;
 
 /**
  * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
@@ -62,6 +63,7 @@ import java.util.concurrent.locks.ReentrantLock;
  * @author Justin Mahoney
  * @since 3.0
  */
+ at GwtCompatible(emulated = true)
 public final class MoreExecutors {
   private MoreExecutors() {}
 
@@ -81,6 +83,7 @@ public final class MoreExecutors {
    * @return an unmodifiable version of the input which will not hang the JVM
    */
   @Beta
+  @GwtIncompatible("TODO")
   public static ExecutorService getExitingExecutorService(
       ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
     return new Application()
@@ -104,6 +107,7 @@ public final class MoreExecutors {
    * @return an unmodifiable version of the input which will not hang the JVM
    */
   @Beta
+  @GwtIncompatible("TODO")
   public static ScheduledExecutorService getExitingScheduledExecutorService(
       ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
     return new Application()
@@ -122,6 +126,7 @@ public final class MoreExecutors {
    * @param timeUnit unit of time for the time parameter
    */
   @Beta
+  @GwtIncompatible("TODO")
   public static void addDelayedShutdownHook(
       ExecutorService service, long terminationTimeout, TimeUnit timeUnit) {
     new Application()
@@ -144,6 +149,7 @@ public final class MoreExecutors {
    * @return an unmodifiable version of the input which will not hang the JVM
    */
   @Beta
+  @GwtIncompatible("concurrency")
   public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) {
     return new Application().getExitingExecutorService(executor);
   }
@@ -164,13 +170,16 @@ public final class MoreExecutors {
    * @return an unmodifiable version of the input which will not hang the JVM
    */
   @Beta
+  @GwtIncompatible("TODO")
   public static ScheduledExecutorService getExitingScheduledExecutorService(
       ScheduledThreadPoolExecutor executor) {
     return new Application().getExitingScheduledExecutorService(executor);
   }
 
   /** Represents the current application to register shutdown hooks. */
-  @VisibleForTesting static class Application {
+  @GwtIncompatible("TODO")
+  @VisibleForTesting
+  static class Application {
 
     final ExecutorService getExitingExecutorService(
         ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
@@ -224,6 +233,7 @@ public final class MoreExecutors {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static void useDaemonThreadFactory(ThreadPoolExecutor executor) {
     executor.setThreadFactory(new ThreadFactoryBuilder()
         .setDaemon(true)
@@ -233,7 +243,7 @@ public final class MoreExecutors {
 
   /**
    * Creates an executor service that runs each task in the thread
-   * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy}  This
+   * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy}.  This
    * applies both to individually submitted tasks and to collections of tasks
    * submitted via {@code invokeAll} or {@code invokeAny}.  In the latter case,
    * tasks will run serially on the calling thread.  Tasks are run to
@@ -261,26 +271,27 @@ public final class MoreExecutors {
    * RejectedExecutionException, although a subset of the tasks may already
    * have been executed.
    *
-   * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+   * @since 10.0 (<a href="https://github.com/google/guava/wiki/Compatibility"
    *        >mostly source-compatible</a> since 3.0)
    * @deprecated Use {@link #directExecutor()} if you only require an {@link Executor} and
-   *     {@link #newDirectExecutorService()} if you need a {@link ListeningExecutorService}.
+   *     {@link #newDirectExecutorService()} if you need a {@link ListeningExecutorService}. This
+   *     method will be removed in August 2016.
    */
-  @Deprecated public static ListeningExecutorService sameThreadExecutor() {
+  @Deprecated
+  @GwtIncompatible("TODO")
+  public static ListeningExecutorService sameThreadExecutor() {
     return new DirectExecutorService();
   }
 
   // See sameThreadExecutor javadoc for behavioral notes.
-  private static class DirectExecutorService
+  @GwtIncompatible("TODO")
+  private static final class DirectExecutorService
       extends AbstractListeningExecutorService {
     /**
      * Lock used whenever accessing the state variables
-     * (runningTasks, shutdown, terminationCondition) of the executor
+     * (runningTasks, shutdown) of the executor
      */
-    private final Lock lock = new ReentrantLock();
-
-    /** Signaled after the executor is shutdown and running tasks are done */
-    private final Condition termination = lock.newCondition();
+    private final Object lock = new Object();
 
     /*
      * Conceptually, these two variables describe the executor being in
@@ -289,8 +300,8 @@ public final class MoreExecutors {
      *   - Shutdown: runningTasks > 0 and shutdown == true
      *   - Terminated: runningTasks == 0 and shutdown == true
      */
-    private int runningTasks = 0;
-    private boolean shutdown = false;
+    @GuardedBy("lock") private int runningTasks = 0;
+    @GuardedBy("lock") private boolean shutdown = false;
 
     @Override
     public void execute(Runnable command) {
@@ -304,21 +315,18 @@ public final class MoreExecutors {
 
     @Override
     public boolean isShutdown() {
-      lock.lock();
-      try {
+      synchronized (lock) {
         return shutdown;
-      } finally {
-        lock.unlock();
       }
     }
 
     @Override
     public void shutdown() {
-      lock.lock();
-      try {
+      synchronized (lock) {
         shutdown = true;
-      } finally {
-        lock.unlock();
+        if (runningTasks == 0) {
+          lock.notifyAll();
+        }
       }
     }
 
@@ -331,11 +339,8 @@ public final class MoreExecutors {
 
     @Override
     public boolean isTerminated() {
-      lock.lock();
-      try {
+      synchronized (lock) {
         return shutdown && runningTasks == 0;
-      } finally {
-        lock.unlock();
       }
     }
 
@@ -343,19 +348,18 @@ public final class MoreExecutors {
     public boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException {
       long nanos = unit.toNanos(timeout);
-      lock.lock();
-      try {
+      synchronized (lock) {
         for (;;) {
-          if (isTerminated()) {
+          if (shutdown && runningTasks == 0) {
             return true;
           } else if (nanos <= 0) {
             return false;
           } else {
-            nanos = termination.awaitNanos(nanos);
+            long now = System.nanoTime();
+            TimeUnit.NANOSECONDS.timedWait(lock, nanos);
+            nanos -= System.nanoTime() - now;  // subtract the actual time we waited
           }
         }
-      } finally {
-        lock.unlock();
       }
     }
 
@@ -367,14 +371,11 @@ public final class MoreExecutors {
      *         shutdown
      */
     private void startTask() {
-      lock.lock();
-      try {
-        if (isShutdown()) {
+      synchronized (lock) {
+        if (shutdown) {
           throw new RejectedExecutionException("Executor already shutdown");
         }
         runningTasks++;
-      } finally {
-        lock.unlock();
       }
     }
 
@@ -382,14 +383,11 @@ public final class MoreExecutors {
      * Decrements the running task count.
      */
     private void endTask() {
-      lock.lock();
-      try {
-        runningTasks--;
-        if (isTerminated()) {
-          termination.signalAll();
+      synchronized (lock) {
+        int numRunning = --runningTasks;
+        if (numRunning == 0) {
+          lock.notifyAll();
         }
-      } finally {
-        lock.unlock();
       }
     }
   }
@@ -426,6 +424,7 @@ public final class MoreExecutors {
    *
    * @since 18.0 (present as MoreExecutors.sameThreadExecutor() since 10.0)
    */
+  @GwtIncompatible("TODO")
   public static ListeningExecutorService newDirectExecutorService() {
     return new DirectExecutorService();
   }
@@ -456,6 +455,10 @@ public final class MoreExecutors {
     @Override public void execute(Runnable command) {
       command.run();
     }
+
+    @Override public String toString() {
+      return "MoreExecutors.directExecutor()";
+    }
   }
 
   /**
@@ -476,6 +479,7 @@ public final class MoreExecutors {
    *
    * @since 10.0
    */
+  @GwtIncompatible("TODO")
   public static ListeningExecutorService listeningDecorator(
       ExecutorService delegate) {
     return (delegate instanceof ListeningExecutorService)
@@ -504,6 +508,7 @@ public final class MoreExecutors {
    *
    * @since 10.0
    */
+  @GwtIncompatible("TODO")
   public static ListeningScheduledExecutorService listeningDecorator(
       ScheduledExecutorService delegate) {
     return (delegate instanceof ListeningScheduledExecutorService)
@@ -511,6 +516,7 @@ public final class MoreExecutors {
         : new ScheduledListeningDecorator(delegate);
   }
 
+  @GwtIncompatible("TODO")
   private static class ListeningDecorator
       extends AbstractListeningExecutorService {
     private final ExecutorService delegate;
@@ -520,38 +526,39 @@ public final class MoreExecutors {
     }
 
     @Override
-    public boolean awaitTermination(long timeout, TimeUnit unit)
+    public final boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException {
       return delegate.awaitTermination(timeout, unit);
     }
 
     @Override
-    public boolean isShutdown() {
+    public final boolean isShutdown() {
       return delegate.isShutdown();
     }
 
     @Override
-    public boolean isTerminated() {
+    public final boolean isTerminated() {
       return delegate.isTerminated();
     }
 
     @Override
-    public void shutdown() {
+    public final void shutdown() {
       delegate.shutdown();
     }
 
     @Override
-    public List<Runnable> shutdownNow() {
+    public final List<Runnable> shutdownNow() {
       return delegate.shutdownNow();
     }
 
     @Override
-    public void execute(Runnable command) {
+    public final void execute(Runnable command) {
       delegate.execute(command);
     }
   }
 
-  private static class ScheduledListeningDecorator
+  @GwtIncompatible("TODO")
+  private static final class ScheduledListeningDecorator
       extends ListeningDecorator implements ListeningScheduledExecutorService {
     @SuppressWarnings("hiding")
     final ScheduledExecutorService delegate;
@@ -564,8 +571,8 @@ public final class MoreExecutors {
     @Override
     public ListenableScheduledFuture<?> schedule(
         Runnable command, long delay, TimeUnit unit) {
-      ListenableFutureTask<Void> task =
-          ListenableFutureTask.create(command, null);
+      TrustedListenableFutureTask<Void> task =
+          TrustedListenableFutureTask.create(command, null);
       ScheduledFuture<?> scheduled = delegate.schedule(task, delay, unit);
       return new ListenableScheduledTask<Void>(task, scheduled);
     }
@@ -573,7 +580,7 @@ public final class MoreExecutors {
     @Override
     public <V> ListenableScheduledFuture<V> schedule(
         Callable<V> callable, long delay, TimeUnit unit) {
-      ListenableFutureTask<V> task = ListenableFutureTask.create(callable);
+      TrustedListenableFutureTask<V> task = TrustedListenableFutureTask.create(callable);
       ScheduledFuture<?> scheduled = delegate.schedule(task, delay, unit);
       return new ListenableScheduledTask<V>(task, scheduled);
     }
@@ -634,6 +641,7 @@ public final class MoreExecutors {
       }
     }
 
+    @GwtIncompatible("TODO")
     private static final class NeverSuccessfulListenableFutureTask
         extends AbstractFuture<Void>
         implements Runnable {
@@ -742,6 +750,7 @@ public final class MoreExecutors {
   /**
    * Submits the task and adds a listener that adds the future to {@code queue} when it completes.
    */
+  @GwtIncompatible("TODO")
   private static <T> ListenableFuture<T> submitAndAddQueueListener(
       ListeningExecutorService executorService, Callable<T> task,
       final BlockingQueue<Future<T>> queue) {
@@ -763,6 +772,7 @@ public final class MoreExecutors {
    * @since 14.0
    */
   @Beta
+  @GwtIncompatible("concurrency")
   public static ThreadFactory platformThreadFactory() {
     if (!isAppEngine()) {
       return Executors.defaultThreadFactory();
@@ -782,6 +792,7 @@ public final class MoreExecutors {
     }
   }
 
+  @GwtIncompatible("TODO")
   private static boolean isAppEngine() {
     if (System.getProperty("com.google.appengine.runtime.environment") == null) {
       return false;
@@ -810,6 +821,7 @@ public final class MoreExecutors {
    * Creates a thread using {@link #platformThreadFactory}, and sets its name to {@code name}
    * unless changing the name is forbidden by the security manager.
    */
+  @GwtIncompatible("concurrency")
   static Thread newThread(String name, Runnable runnable) {
     checkNotNull(name);
     checkNotNull(runnable);
@@ -822,8 +834,8 @@ public final class MoreExecutors {
     return result;
   }
 
-  // TODO(user): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
-  // TODO(user): provide overloads that take constant strings? Function<Runnable, String>s to
+  // TODO(lukes): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
+  // TODO(lukes): provide overloads that take constant strings? Function<Runnable, String>s to
   // calculate names?
 
   /**
@@ -837,6 +849,7 @@ public final class MoreExecutors {
    * @param executor The executor to decorate
    * @param nameSupplier The source of names for each task
    */
+  @GwtIncompatible("concurrency")
   static Executor renamingDecorator(final Executor executor, final Supplier<String> nameSupplier) {
     checkNotNull(executor);
     checkNotNull(nameSupplier);
@@ -863,6 +876,7 @@ public final class MoreExecutors {
    * @param service The executor to decorate
    * @param nameSupplier The source of names for each task
    */
+  @GwtIncompatible("concurrency")
   static ExecutorService renamingDecorator(final ExecutorService service,
       final Supplier<String> nameSupplier) {
     checkNotNull(service);
@@ -893,6 +907,7 @@ public final class MoreExecutors {
    * @param service The executor to decorate
    * @param nameSupplier The source of names for each task
    */
+  @GwtIncompatible("concurrency")
   static ScheduledExecutorService renamingDecorator(final ScheduledExecutorService service,
       final Supplier<String> nameSupplier) {
     checkNotNull(service);
@@ -924,19 +939,18 @@ public final class MoreExecutors {
    *  <li>waits for the other half of the specified timeout.
    * </ol>
    *
-   * <p>If, at any step of the process, the given executor is terminated or the calling thread is
-   * interrupted, the method calls {@link ExecutorService#shutdownNow()}, cancelling
-   * pending tasks and interrupting running tasks.
+   * <p>If, at any step of the process, the calling thread is interrupted, the method calls {@link
+   * ExecutorService#shutdownNow()} and returns.
    *
    * @param service the {@code ExecutorService} to shut down
    * @param timeout the maximum time to wait for the {@code ExecutorService} to terminate
    * @param unit the time unit of the timeout argument
-   * @return {@code true} if the pool was terminated successfully, {@code false} if the
-   *     {@code ExecutorService} could not terminate <b>or</b> the thread running this method
-   *     is interrupted while waiting for the {@code ExecutorService} to terminate
+   * @return {@code true} if the {@code ExecutorService} was terminated successfully, {@code false}
+   *     the call timed out or was interrupted
    * @since 17.0
    */
   @Beta
+  @GwtIncompatible("concurrency")
   public static boolean shutdownAndAwaitTermination(
       ExecutorService service, long timeout, TimeUnit unit) {
     checkNotNull(unit);
diff --git a/guava/src/com/google/common/collect/FilteredMultimap.java b/guava/src/com/google/common/util/concurrent/Platform.java
similarity index 59%
copy from guava/src/com/google/common/collect/FilteredMultimap.java
copy to guava/src/com/google/common/util/concurrent/Platform.java
index e97cfdb..017a08a 100644
--- a/guava/src/com/google/common/collect/FilteredMultimap.java
+++ b/guava/src/com/google/common/util/concurrent/Platform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 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.
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.google.common.collect;
+package com.google.common.util.concurrent;
 
 import com.google.common.annotations.GwtCompatible;
-import com.google.common.base.Predicate;
 
-import java.util.Map.Entry;
+import javax.annotation.Nullable;
 
 /**
- * An interface for all filtered multimap types.
- * 
- * @author Louis Wasserman
+ * Methods factored out so that they can be emulated differently in GWT.
  */
- at GwtCompatible
-interface FilteredMultimap<K, V> extends Multimap<K, V> {  
-  Multimap<K, V> unfiltered();
+ at GwtCompatible(emulated = true)
+final class Platform {
+  static boolean isInstanceOfThrowableClass(
+      @Nullable Throwable t, Class<? extends Throwable> expectedClass) {
+    return expectedClass.isInstance(t);
+  }
 
-  Predicate<? super Entry<K, V>> entryPredicate();
+  private Platform() {}
 }
diff --git a/guava/src/com/google/common/util/concurrent/RateLimiter.java b/guava/src/com/google/common/util/concurrent/RateLimiter.java
index 74290b0..76b7e73 100644
--- a/guava/src/com/google/common/util/concurrent/RateLimiter.java
+++ b/guava/src/com/google/common/util/concurrent/RateLimiter.java
@@ -28,6 +28,7 @@ import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.SmoothRateLimiter.SmoothBursty;
 import com.google.common.util.concurrent.SmoothRateLimiter.SmoothWarmingUp;
 
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 import javax.annotation.concurrent.ThreadSafe;
@@ -41,7 +42,7 @@ import javax.annotation.concurrent.ThreadSafe;
  * physical or logical resource is accessed. This is in contrast to {@link
  * java.util.concurrent.Semaphore} which restricts the number of concurrent
  * accesses instead of the rate (note though that concurrency and rate are closely related,
- * e.g. see <a href="http://en.wikipedia.org/wiki/Little's_law">Little's Law</a>).
+ * e.g. see <a href="http://en.wikipedia.org/wiki/Little%27s_law">Little's Law</a>).
  *
  * <p>A {@code RateLimiter} is defined primarily by the rate at which permits
  * are issued. Absent additional configuration, permits will be distributed at a
@@ -77,7 +78,7 @@ import javax.annotation.concurrent.ThreadSafe;
  *}</pre>
  *
  * <p>It is important to note that the number of permits requested <i>never</i>
- * affect the throttling of the request itself (an invocation to {@code acquire(1)}
+ * affects the throttling of the request itself (an invocation to {@code acquire(1)}
  * and an invocation to {@code acquire(1000)} will result in exactly the same throttling, if any),
  * but it affects the throttling of the <i>next</i> request. I.e., if an expensive task
  * arrives at an idle RateLimiter, it will be granted immediately, but it is the <i>next</i>
@@ -166,13 +167,15 @@ public abstract class RateLimiter {
    */
   public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
     checkArgument(warmupPeriod >= 0, "warmupPeriod must not be negative: %s", warmupPeriod);
-    return create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit);
+    return create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit,
+                  3.0);
   }
 
   @VisibleForTesting
   static RateLimiter create(
-      SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
-    RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit);
+      SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit,
+      double coldFactor) {
+    RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit, coldFactor);
     rateLimiter.setRate(permitsPerSecond);
     return rateLimiter;
   }
@@ -395,7 +398,7 @@ public abstract class RateLimiter {
 
   @Override
   public String toString() {
-    return String.format("RateLimiter[stableRate=%3.1fqps]", getRate());
+    return String.format(Locale.ROOT, "RateLimiter[stableRate=%3.1fqps]", getRate());
   }
 
   @VisibleForTesting
diff --git a/guava/src/com/google/common/util/concurrent/SerializingExecutor.java b/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
index 47524eb..5407edf 100644
--- a/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
+++ b/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
@@ -19,7 +19,7 @@ package com.google.common.util.concurrent;
 import com.google.common.base.Preconditions;
 
 import java.util.ArrayDeque;
-import java.util.Queue;
+import java.util.Deque;
 import java.util.concurrent.Executor;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -31,17 +31,20 @@ import javax.annotation.concurrent.GuardedBy;
  * using the provided Executor, and serially such that no two will ever
  * be running at the same time.
  *
- * TODO(user): The tasks are given to the underlying executor as a single
- * task, which means the semantics of the executor may be changed, e.g. the
- * executor may have an afterExecute method that runs after every task
+ * <p>Tasks submitted to {@link #execute(Runnable)} are executed in FIFO order.
  *
- * TODO(user): What happens in case of shutdown or shutdownNow?  Should
- * TaskRunner check for interruption?
+ * <p>Tasks can also be prepended to the queue to be executed in LIFO order before any other
+ * submitted tasks. Primarily intended for the currently executing task to be able to schedule a
+ * continuation task.
  *
- * TODO(user): It would be nice to provide a handle to individual task
- * results using Future.  Maybe SerializingExecutorService?
+ * <p>Execution on the queue can be {@linkplain #suspend suspended}, e.g. while waiting for an RPC,
+ * and execution can be {@linkplain #resume resumed} later.
  *
- * @author JJ Furman
+ * <p>The execution of tasks is done by one thread as long as there are tasks left in the queue and
+ * execution has not been suspended. (Even if one task is {@linkplain Thread#interrupt interrupted},
+ * execution of subsequent tasks continues.) {@code RuntimeException}s thrown by tasks are simply
+ * logged and the executor keeps trucking. If an {@code Error} is thrown, the error will propagate
+ * and execution will stop until it is restarted by external calls.
  */
 final class SerializingExecutor implements Executor {
   private static final Logger log =
@@ -50,117 +53,144 @@ final class SerializingExecutor implements Executor {
   /** Underlying executor that all submitted Runnable objects are run on. */
   private final Executor executor;
 
-  /** A list of Runnables to be run in order. */
   @GuardedBy("internalLock")
-  private final Queue<Runnable> waitQueue = new ArrayDeque<Runnable>();
-
-  /**
-   * We explicitly keep track of if the TaskRunner is currently scheduled to
-   * run.  If it isn't, we start it.  We can't just use
-   * waitQueue.isEmpty() as a proxy because we need to ensure that only one
-   * Runnable submitted is running at a time so even if waitQueue is empty
-   * the isThreadScheduled isn't set to false until after the Runnable is
-   * finished.
-   */
+  private final Deque<Runnable> queue = new ArrayDeque<Runnable>();
   @GuardedBy("internalLock")
-  private boolean isThreadScheduled = false;
+  private boolean isWorkerRunning = false;
+  @GuardedBy("internalLock")
+  private int suspensions = 0;
 
-  /** The object that actually runs the Runnables submitted, reused. */
-  private final TaskRunner taskRunner = new TaskRunner();
+  private final Object internalLock = new Object();
+
+  public SerializingExecutor(Executor executor) {
+    this.executor = Preconditions.checkNotNull(executor);
+  }
 
   /**
-   * Creates a SerializingExecutor, running tasks using {@code executor}.
+   * Adds a task to the queue and makes sure a worker thread is running, unless the queue has been
+   * suspended.
    *
-   * @param executor Executor in which tasks should be run. Must not be null.
+   * <p>If this method throws, e.g. a {@code RejectedExecutionException} from the delegate executor,
+   * execution of tasks will stop until a call to this method or to {@link #resume()} is
+   * made.
    */
-  public SerializingExecutor(Executor executor) {
-    Preconditions.checkNotNull(executor, "'executor' must not be null.");
-    this.executor = executor;
+  public void execute(Runnable task) {
+    synchronized (internalLock) {
+      queue.add(task);
+    }
+    startQueueWorker();
   }
 
-  private final Object internalLock = new Object() {
-    @Override public String toString() {
-      return "SerializingExecutor lock: " + super.toString();
+  /**
+   * Prepends a task to the front of the queue and makes sure a worker thread is running, unless the
+   * queue has been suspended.
+   */
+  public void executeFirst(Runnable task) {
+    synchronized (internalLock) {
+      queue.addFirst(task);
+    }
+    startQueueWorker();
+  }
+
+  /**
+   * Suspends the running of tasks until {@link #resume()} is called. This can be called multiple
+   * times to increase the suspensions count and execution will not continue until {@link #resume}
+   * has been called the same number of times as {@code suspend} has been.
+   *
+   * <p>Any task that has already been pulled off the queue for execution will be completed
+   * before execution is suspended.
+   */
+  public void suspend() {
+    synchronized (internalLock) {
+      suspensions++;
     }
-  };
+  }
 
   /**
-   * Runs the given runnable strictly after all Runnables that were submitted
-   * before it, and using the {@code executor} passed to the constructor.     .
+   * Continue execution of tasks after a call to {@link #suspend()}. More accurately, decreases the
+   * suspension counter, as has been incremented by calls to {@link #suspend}, and resumes execution
+   * if the suspension counter is zero.
+   *
+   * <p>If this method throws, e.g. a {@code RejectedExecutionException} from the delegate executor,
+   * execution of tasks will stop until a call to this method or to {@link #execute(Runnable)} or
+   * {@link #executeFirst(Runnable)} is made.
+   *
+   * @throws java.lang.IllegalStateException if this executor is not suspended.
    */
-  @Override
-  public void execute(Runnable r) {
-    Preconditions.checkNotNull(r, "'r' must not be null.");
-    boolean scheduleTaskRunner = false;
+  public void resume() {
     synchronized (internalLock) {
-      waitQueue.add(r);
+      Preconditions.checkState(suspensions > 0);
+      suspensions--;
+    }
+    startQueueWorker();
+  }
 
-      if (!isThreadScheduled) {
-        isThreadScheduled = true;
-        scheduleTaskRunner = true;
+  private void startQueueWorker() {
+    synchronized (internalLock) {
+      // We sometimes try to start a queue worker without knowing if there is any work to do.
+      if (queue.peek() == null) {
+        return;
+      }
+      if (suspensions > 0) {
+        return;
       }
+      if (isWorkerRunning) {
+        return;
+      }
+      isWorkerRunning = true;
     }
-    if (scheduleTaskRunner) {
-      boolean threw = true;
-      try {
-        executor.execute(taskRunner);
-        threw = false;
-      } finally {
-        if (threw) {
-          synchronized (internalLock) {
-            // It is possible that at this point that there are still tasks in
-            // the queue, it would be nice to keep trying but the error may not
-            // be recoverable.  So we update our state and propogate so that if
-            // our caller deems it recoverable we won't be stuck.
-            isThreadScheduled = false;
-          }
+    boolean executionRejected = true;
+    try {
+      executor.execute(new QueueWorker());
+      executionRejected = false;
+    } finally {
+      if (executionRejected) {
+        // The best we can do is to stop executing the queue, but reset the state so that
+        // execution can be resumed later if the caller so wishes.
+        synchronized (internalLock) {
+          isWorkerRunning = false;
         }
       }
     }
   }
 
   /**
-   * Task that actually runs the Runnables.  It takes the Runnables off of the
-   * queue one by one and runs them.  After it is done with all Runnables and
-   * there are no more to run, puts the SerializingExecutor in the state where
-   * isThreadScheduled = false and returns.  This allows the current worker
-   * thread to return to the original pool.
+   * Worker that runs tasks off the queue until it is empty or the queue is suspended.
    */
-  private class TaskRunner implements Runnable {
+  private final class QueueWorker implements Runnable {
     @Override
     public void run() {
-      boolean stillRunning = true;
       try {
-        while (true) {
-          Preconditions.checkState(isThreadScheduled);
-          Runnable nextToRun;
-          synchronized (internalLock) {
-            nextToRun = waitQueue.poll();
-            if (nextToRun == null) {
-              isThreadScheduled = false;
-              stillRunning = false;
-              break;
-            }
-          }
+        workOnQueue();
+      } catch (Error e) {
+        synchronized (internalLock) {
+          isWorkerRunning = false;
+        }
+        throw e;
+        // The execution of a task has ended abnormally.
+        // We could have tasks left in the queue, so should perhaps try to restart a worker,
+        // but then the Error will get delayed if we are using a direct (same thread) executor.
+      }
+    }
 
-          // Always run while not holding the lock, to avoid deadlocks.
-          try {
-            nextToRun.run();
-          } catch (RuntimeException e) {
-            // Log it and keep going.
-            log.log(Level.SEVERE, "Exception while executing runnable "
-                + nextToRun, e);
+    private void workOnQueue() {
+      while (true) {
+        Runnable task = null;
+        synchronized (internalLock) {
+          // TODO(user): How should we handle interrupts and shutdowns?
+          if (suspensions == 0) {
+            task = queue.poll();
           }
-        }
-      } finally {
-        if (stillRunning) {
-          // An Error is bubbling up, we should mark ourselves as no longer
-          // running, that way if anyone tries to keep using us we won't be
-          // corrupted.
-          synchronized (internalLock) {
-            isThreadScheduled = false;
+          if (task == null) {
+            isWorkerRunning = false;
+            return;
           }
         }
+        try {
+          task.run();
+        } catch (RuntimeException e) {
+          log.log(Level.SEVERE, "Exception while executing runnable " + task, e);
+        }
       }
     }
   }
diff --git a/guava/src/com/google/common/util/concurrent/ServiceManager.java b/guava/src/com/google/common/util/concurrent/ServiceManager.java
index 4f7d1d7..f72f199 100644
--- a/guava/src/com/google/common/util/concurrent/ServiceManager.java
+++ b/guava/src/com/google/common/util/concurrent/ServiceManager.java
@@ -35,7 +35,6 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Stopwatch;
-import com.google.common.base.Supplier;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
@@ -45,23 +44,22 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.MultimapBuilder;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.Multiset;
 import com.google.common.collect.Ordering;
 import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.ListenerCallQueue.Callback;
 import com.google.common.util.concurrent.Service.State;
+import com.google.j2objc.annotations.WeakOuter;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.EnumMap;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -402,12 +400,7 @@ public final class ServiceManager {
 
     @GuardedBy("monitor")
     final SetMultimap<State, Service> servicesByState =
-        Multimaps.newSetMultimap(new EnumMap<State, Collection<Service>>(State.class),
-            new Supplier<Set<Service>>() {
-              @Override public Set<Service> get() {
-                return Sets.newLinkedHashSet();
-              }
-            });
+        MultimapBuilder.enumKeys(State.class).linkedHashSetValues().build();
 
     @GuardedBy("monitor")
     final Multiset<State> states = servicesByState.keys();
@@ -438,7 +431,14 @@ public final class ServiceManager {
      * Controls how long to wait for all the services to either become healthy or reach a
      * state from which it is guaranteed that it can never become healthy.
      */
-    final Monitor.Guard awaitHealthGuard = new Monitor.Guard(monitor) {
+    final Monitor.Guard awaitHealthGuard = new AwaitHealthGuard();
+
+    @WeakOuter
+    final class AwaitHealthGuard extends Monitor.Guard {
+      AwaitHealthGuard() {
+        super(ServiceManagerState.this.monitor);
+      }
+
       @Override public boolean isSatisfied() {
         // All services have started or some service has terminated/failed.
         return states.count(RUNNING) == numberOfServices
@@ -446,16 +446,23 @@ public final class ServiceManager {
             || states.contains(TERMINATED)
             || states.contains(FAILED);
       }
-    };
+    }
 
     /**
      * Controls how long to wait for all services to reach a terminal state.
      */
-    final Monitor.Guard stoppedGuard = new Monitor.Guard(monitor) {
+    final Monitor.Guard stoppedGuard = new StoppedGuard();
+
+    @WeakOuter
+    final class StoppedGuard extends Monitor.Guard {
+      StoppedGuard() {
+        super(ServiceManagerState.this.monitor);
+      }
+
       @Override public boolean isSatisfied() {
         return states.count(TERMINATED) + states.count(FAILED) == numberOfServices;
       }
-    };
+    }
 
     /** The listeners to notify during a state transition. */
     @GuardedBy("monitor")
@@ -564,7 +571,7 @@ public final class ServiceManager {
           throw new TimeoutException("Timeout waiting for the services to stop. The following "
               + "services have not stopped: "
               + Multimaps.filterKeys(servicesByState,
-                  not(in(ImmutableSet.of(TERMINATED, FAILED)))));
+                  not(in(EnumSet.of(TERMINATED, FAILED)))));
         }
       } finally {
         monitor.leave();
@@ -577,7 +584,7 @@ public final class ServiceManager {
       try {
         for (Entry<State, Service> entry : servicesByState.entries()) {
           if (!(entry.getValue() instanceof NoOpService)) {
-            builder.put(entry.getKey(), entry.getValue());
+            builder.put(entry);
           }
         }
       } finally {
@@ -602,17 +609,13 @@ public final class ServiceManager {
       } finally {
         monitor.leave();
       }
-      Collections.sort(loadTimes, Ordering.<Long>natural()
+      Collections.sort(loadTimes, Ordering.natural()
           .onResultOf(new Function<Entry<Service, Long>, Long>() {
             @Override public Long apply(Map.Entry<Service, Long> input) {
               return input.getValue();
             }
           }));
-      ImmutableMap.Builder<Service, Long> builder = ImmutableMap.builder();
-      for (Entry<Service, Long> entry : loadTimes) {
-        builder.put(entry);
-      }
-      return builder.build();
+      return ImmutableMap.copyOf(loadTimes);
     }
 
     /**
@@ -771,7 +774,7 @@ public final class ServiceManager {
       if (state != null) {
         // Log before the transition, so that if the process exits in response to server failure,
         // there is a higher likelihood that the cause will be in the logs.
-        if (!(service instanceof NoOpService)) {
+        if (!(service instanceof NoOpService) ) {
           logger.log(Level.SEVERE, "Service " + service + " has failed in the " + from + " state.",
               failure);
         }
diff --git a/guava/src/com/google/common/util/concurrent/SettableFuture.java b/guava/src/com/google/common/util/concurrent/SettableFuture.java
index 23e14f9..bc3f905 100644
--- a/guava/src/com/google/common/util/concurrent/SettableFuture.java
+++ b/guava/src/com/google/common/util/concurrent/SettableFuture.java
@@ -16,16 +16,21 @@
 
 package com.google.common.util.concurrent;
 
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
 import javax.annotation.Nullable;
 
 /**
- * A {@link ListenableFuture} whose result may be set by a {@link #set(Object)}
- * or {@link #setException(Throwable)} call. It may also be cancelled.
+ * A {@link ListenableFuture} whose result may be set by a {@link #set(Object)},
+ * {@link #setException(Throwable)} or {@link #setFuture(ListenableFuture)} call. 
+ * It may also be cancelled.
  *
  * @author Sven Mawson
  * @since 9.0 (in 1.0 as {@code ValueFuture})
  */
-public final class SettableFuture<V> extends AbstractFuture<V> {
+ at GwtCompatible
+public final class SettableFuture<V> extends AbstractFuture.TrustedFuture<V> {
 
   /**
    * Creates a new {@code SettableFuture} in the default state.
@@ -40,31 +45,17 @@ public final class SettableFuture<V> extends AbstractFuture<V> {
    */
   private SettableFuture() {}
 
-  /**
-   * Sets the value of this future.  This method will return {@code true} if
-   * the value was successfully set, or {@code false} if the future has already
-   * been set or cancelled.
-   *
-   * @param value the value the future should hold.
-   * @return true if the value was successfully set.
-   */
-  @Override
-  public boolean set(@Nullable V value) {
+  @Override public boolean set(@Nullable V value) {
     return super.set(value);
   }
 
-  /**
-   * Sets the future to having failed with the given exception. This exception
-   * will be wrapped in an {@code ExecutionException} and thrown from the {@code
-   * get} methods. This method will return {@code true} if the exception was
-   * successfully set, or {@code false} if the future has already been set or
-   * cancelled.
-   *
-   * @param throwable the exception the future should hold.
-   * @return true if the exception was successfully set.
-   */
-  @Override
-  public boolean setException(Throwable throwable) {
+  @Override public boolean setException(Throwable throwable) {
     return super.setException(throwable);
   }
+
+  @Beta
+  @Override
+  public boolean setFuture(ListenableFuture<? extends V> future) {
+    return super.setFuture(future);
+  }
 }
diff --git a/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java b/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
index 0d426cf..d934c78 100644
--- a/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
+++ b/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
 import static java.lang.Math.min;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import com.google.common.math.LongMath;
+
 import java.util.concurrent.TimeUnit;
 
 abstract class SmoothRateLimiter extends RateLimiter {
@@ -144,79 +146,58 @@ abstract class SmoothRateLimiter extends RateLimiter {
    */
 
   /**
-   * This implements the following function:
+   * This implements the following function where coldInterval = coldFactor * stableInterval.
    *
    *          ^ throttling
    *          |
-   * 3*stable +                  /
+   *    cold  +                  /
    * interval |                 /.
-   *  (cold)  |                / .
+   *          |                / .
    *          |               /  .   <-- "warmup period" is the area of the trapezoid between
-   * 2*stable +              /   .       halfPermits and maxPermits
-   * interval |             /    .
+   *          |              /   .       thresholdPermits and maxPermits
+   *          |             /    .
    *          |            /     .
    *          |           /      .
-   *   stable +----------/  WARM . }
-   * interval |          .   UP  . } <-- this rectangle (from 0 to maxPermits, and
-   *          |          . PERIOD. }     height == stableInterval) defines the cooldown period,
-   *          |          .       . }     and we want cooldownPeriod == warmupPeriod
-   *          |---------------------------------> storedPermits
-   *              (halfPermits) (maxPermits)
-   *
+   *   stable +----------/  WARM .
+   * interval |          .   UP  .
+   *          |          . PERIOD.
+   *          |          .       .
+   *        0 +----------+-------+--------------> storedPermits
+   *          0 thresholdPermits maxPermits
    * Before going into the details of this particular function, let's keep in mind the basics:
    * 1) The state of the RateLimiter (storedPermits) is a vertical line in this figure.
    * 2) When the RateLimiter is not used, this goes right (up to maxPermits)
    * 3) When the RateLimiter is used, this goes left (down to zero), since if we have storedPermits,
    *    we serve from those first
-   * 4) When _unused_, we go right at the same speed (rate)! I.e., if our rate is
-   *    2 permits per second, and 3 unused seconds pass, we will always save 6 permits
-   *    (no matter what our initial position was), up to maxPermits.
-   *    If we invert the rate, we get the "stableInterval" (interval between two requests
-   *    in a perfectly spaced out sequence of requests of the given rate). Thus, if you
-   *    want to see "how much time it will take to go from X storedPermits to X+K storedPermits?",
-   *    the answer is always stableInterval * K. In the same example, for 2 permits per second,
-   *    stableInterval is 500ms. Thus to go from X storedPermits to X+6 storedPermits, we
-   *    require 6 * 500ms = 3 seconds.
-   *
-   *    In short, the time it takes to move to the right (save K permits) is equal to the
-   *    rectangle of width == K and height == stableInterval.
-   * 4) When _used_, the time it takes, as explained in the introductory class note, is
+   * 4) When _unused_, we go right at a constant rate! The rate at which we move to
+   *    the right is chosen as maxPermits / warmupPeriod.  This ensures that the time it takes to
+   *    go from 0 to maxPermits is equal to warmupPeriod.
+   * 5) When _used_, the time it takes, as explained in the introductory class note, is
    *    equal to the integral of our function, between X permits and X-K permits, assuming
    *    we want to spend K saved permits.
    *
    *    In summary, the time it takes to move to the left (spend K permits), is equal to the
    *    area of the function of width == K.
    *
-   * Let's dive into this function now:
+   *    Assuming we have saturated demand, the time to go from maxPermits to thresholdPermits is
+   *    equal to warmupPeriod.  And the time to go from thresholdPermits to 0 is
+   *    warmupPeriod/2.  (The reason that this is warmupPeriod/2 is to maintain the behavior of
+   *    the original implementation where coldFactor was hard coded as 3.)
    *
-   * When we have storedPermits <= halfPermits (the left portion of the function), then
-   * we spend them at the exact same rate that
-   * fresh permits would be generated anyway (that rate is 1/stableInterval). We size
-   * this area to be equal to _half_ the specified warmup period. Why we need this?
-   * And why half? We'll explain shortly below (after explaining the second part).
+   *  It remains to calculate thresholdsPermits and maxPermits.
    *
-   * Stored permits that are beyond halfPermits, are mapped to an ascending line, that goes
-   * from stableInterval to 3 * stableInterval. The average height for that part is
-   * 2 * stableInterval, and is sized appropriately to have an area _equal_ to the
-   * specified warmup period. Thus, by point (4) above, it takes "warmupPeriod" amount of time
-   * to go from maxPermits to halfPermits.
+   *  - The time to go from thresholdPermits to 0 is equal to the integral of the function between
+   *    0 and thresholdPermits.  This is thresholdPermits * stableIntervals.  By (5) it is also
+   *    equal to warmupPeriod/2.  Therefore
    *
-   * BUT, by point (3) above, it only takes "warmupPeriod / 2" amount of time to return back
-   * to maxPermits, from halfPermits! (Because the trapezoid has double the area of the rectangle
-   * of height stableInterval and equivalent width). We decided that the "cooldown period"
-   * time should be equivalent to "warmup period", thus a fully saturated RateLimiter
-   * (with zero stored permits, serving only fresh ones) can go to a fully unsaturated
-   * (with storedPermits == maxPermits) in the same amount of time it takes for a fully
-   * unsaturated RateLimiter to return to the stableInterval -- which happens in halfPermits,
-   * since beyond that point, we use a horizontal line of "stableInterval" height, simulating
-   * the regular rate.
+   *        thresholdPermits = 0.5 * warmupPeriod / stableInterval.
    *
-   * Thus, we have figured all dimensions of this shape, to give all the desired
-   * properties:
-   * - the width is warmupPeriod / stableInterval, to make cooldownPeriod == warmupPeriod
-   * - the slope starts at the middle, and goes from stableInterval to 3*stableInterval so
-   *   to have halfPermits being spend in double the usual time (half the rate), while their
-   *   respective rate is steadily ramping up
+   *  - The time to go from maxPermits to thresholdPermits is equal to the integral of the function
+   *    between thresholdPermits and maxPermits.  This is the area of the pictured trapezoid, and it
+   *    is equal to 0.5 * (stableInterval + coldInterval) * (maxPermits - thresholdPermits).  It is
+   *    also equal to warmupPeriod, so
+   *
+   *        maxPermits = thresholdPermits + 2 * warmupPeriod / (stableInterval + coldInterval).
    */
   static final class SmoothWarmingUp extends SmoothRateLimiter {
     private final long warmupPeriodMicros;
@@ -225,21 +206,24 @@ abstract class SmoothRateLimiter extends RateLimiter {
      * (when permits == maxPermits)
      */
     private double slope;
-    private double halfPermits;
-  
-    SmoothWarmingUp(SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit) {
+    private double thresholdPermits;
+    private double coldFactor;
+
+    SmoothWarmingUp(
+        SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit, double coldFactor) {
       super(stopwatch);
       this.warmupPeriodMicros = timeUnit.toMicros(warmupPeriod);
+      this.coldFactor = coldFactor;
     }
-  
+
     @Override
     void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
       double oldMaxPermits = maxPermits;
-      maxPermits = warmupPeriodMicros / stableIntervalMicros;
-      halfPermits = maxPermits / 2.0;
-      // Stable interval is x, cold is 3x, so on average it's 2x. Double the time -> halve the rate
-      double coldIntervalMicros = stableIntervalMicros * 3.0;
-      slope = (coldIntervalMicros - stableIntervalMicros) / halfPermits;
+      double coldIntervalMicros = stableIntervalMicros * coldFactor;
+      thresholdPermits = 0.5 * warmupPeriodMicros / stableIntervalMicros;
+      maxPermits = thresholdPermits
+          + 2.0 * warmupPeriodMicros / (stableIntervalMicros + coldIntervalMicros);
+      slope = (coldIntervalMicros - stableIntervalMicros) / (maxPermits - thresholdPermits);
       if (oldMaxPermits == Double.POSITIVE_INFINITY) {
         // if we don't special-case this, we would get storedPermits == NaN, below
         storedPermits = 0.0;
@@ -249,43 +233,49 @@ abstract class SmoothRateLimiter extends RateLimiter {
             : storedPermits * maxPermits / oldMaxPermits;
       }
     }
-  
+
     @Override
     long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
-      double availablePermitsAboveHalf = storedPermits - halfPermits;
+      double availablePermitsAboveThreshold = storedPermits - thresholdPermits;
       long micros = 0;
       // measuring the integral on the right part of the function (the climbing line)
-      if (availablePermitsAboveHalf > 0.0) {
-        double permitsAboveHalfToTake = min(availablePermitsAboveHalf, permitsToTake);
-        micros = (long) (permitsAboveHalfToTake * (permitsToTime(availablePermitsAboveHalf)
-            + permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0);
-        permitsToTake -= permitsAboveHalfToTake;
+      if (availablePermitsAboveThreshold > 0.0) {
+        double permitsAboveThresholdToTake = min(availablePermitsAboveThreshold, permitsToTake);
+        micros = (long) (permitsAboveThresholdToTake
+            * (permitsToTime(availablePermitsAboveThreshold)
+            + permitsToTime(availablePermitsAboveThreshold - permitsAboveThresholdToTake)) / 2.0);
+        permitsToTake -= permitsAboveThresholdToTake;
       }
       // measuring the integral on the left part of the function (the horizontal line)
       micros += (stableIntervalMicros * permitsToTake);
       return micros;
     }
-  
+
     private double permitsToTime(double permits) {
       return stableIntervalMicros + permits * slope;
     }
+
+    @Override
+    double coolDownIntervalMicros() {
+      return warmupPeriodMicros / maxPermits;
+    }
   }
 
   /**
    * This implements a "bursty" RateLimiter, where storedPermits are translated to
    * zero throttling. The maximum number of permits that can be saved (when the RateLimiter is
    * unused) is defined in terms of time, in this sense: if a RateLimiter is 2qps, and this
-   * time is specified as 10 seconds, we can save up to 2 * 10 = 20 permits. 
+   * time is specified as 10 seconds, we can save up to 2 * 10 = 20 permits.
    */
   static final class SmoothBursty extends SmoothRateLimiter {
     /** The work (permits) of how many seconds can be saved up if this RateLimiter is unused? */
-    final double maxBurstSeconds; 
-    
+    final double maxBurstSeconds;
+
     SmoothBursty(SleepingStopwatch stopwatch, double maxBurstSeconds) {
       super(stopwatch);
       this.maxBurstSeconds = maxBurstSeconds;
     }
-  
+
     @Override
     void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
       double oldMaxPermits = this.maxPermits;
@@ -299,11 +289,16 @@ abstract class SmoothRateLimiter extends RateLimiter {
             : storedPermits * maxPermits / oldMaxPermits;
       }
     }
-  
+
     @Override
     long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
       return 0L;
     }
+
+    @Override
+    double coolDownIntervalMicros() {
+      return stableIntervalMicros;
+    }
   }
 
   /**
@@ -359,11 +354,14 @@ abstract class SmoothRateLimiter extends RateLimiter {
     long returnValue = nextFreeTicketMicros;
     double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
     double freshPermits = requiredPermits - storedPermitsToSpend;
-
     long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
         + (long) (freshPermits * stableIntervalMicros);
 
-    this.nextFreeTicketMicros = nextFreeTicketMicros + waitMicros;
+    try {
+      this.nextFreeTicketMicros = LongMath.checkedAdd(nextFreeTicketMicros, waitMicros);
+    } catch (ArithmeticException e) {
+      this.nextFreeTicketMicros = Long.MAX_VALUE;
+    }
     this.storedPermits -= storedPermitsToSpend;
     return returnValue;
   }
@@ -378,11 +376,20 @@ abstract class SmoothRateLimiter extends RateLimiter {
    */
   abstract long storedPermitsToWaitTime(double storedPermits, double permitsToTake);
 
-  private void resync(long nowMicros) {
+  /**
+   * Returns the number of microseconds during cool down that we have to wait to get a new permit.
+   */
+  abstract double coolDownIntervalMicros();
+
+  /**
+   * Updates {@code storedPermits} and {@code nextFreeTicketMicros} based on the current time.
+   */
+  void resync(long nowMicros) {
     // if nextFreeTicket is in the past, resync to now
     if (nowMicros > nextFreeTicketMicros) {
       storedPermits = min(maxPermits,
-          storedPermits + (nowMicros - nextFreeTicketMicros) / stableIntervalMicros);
+          storedPermits
+            + (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros());
       nextFreeTicketMicros = nowMicros;
     }
   }
diff --git a/guava/src/com/google/common/util/concurrent/Striped.java b/guava/src/com/google/common/util/concurrent/Striped.java
index a8bc379..1ca01b5 100644
--- a/guava/src/com/google/common/util/concurrent/Striped.java
+++ b/guava/src/com/google/common/util/concurrent/Striped.java
@@ -466,8 +466,9 @@ public abstract class Striped<L> {
      * a fourth long here, to minimize chance of interference between consecutive locks,
      * but I couldn't observe any benefit from that.
      */
-    @SuppressWarnings("unused")
-    long q1, q2, q3;
+    long unused1;
+    long unused2;
+    long unused3;
 
     PaddedLock() {
       super(false);
@@ -476,8 +477,9 @@ public abstract class Striped<L> {
 
   private static class PaddedSemaphore extends Semaphore {
     // See PaddedReentrantLock comment
-    @SuppressWarnings("unused")
-    long q1, q2, q3;
+    long unused1;
+    long unused2;
+    long unused3;
 
     PaddedSemaphore(int permits) {
       super(permits, false);
diff --git a/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
index 47f20cc..5fc283c 100644
--- a/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
+++ b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicLong;
@@ -66,9 +67,8 @@ public final class ThreadFactoryBuilder {
    *     {@code "rpc-pool-0"}, {@code "rpc-pool-1"}, {@code "rpc-pool-2"}, etc.
    * @return this for the builder pattern
    */
-  @SuppressWarnings("ReturnValueIgnored")
   public ThreadFactoryBuilder setNameFormat(String nameFormat) {
-    String.format(nameFormat, 0); // fail fast if the format is bad or null
+    String unused = format(nameFormat, 0); // fail fast if the format is bad or null
     this.nameFormat = nameFormat;
     return this;
   }
@@ -161,7 +161,7 @@ public final class ThreadFactoryBuilder {
       @Override public Thread newThread(Runnable runnable) {
         Thread thread = backingThreadFactory.newThread(runnable);
         if (nameFormat != null) {
-          thread.setName(String.format(nameFormat, count.getAndIncrement()));
+          thread.setName(format(nameFormat, count.getAndIncrement()));
         }
         if (daemon != null) {
           thread.setDaemon(daemon);
@@ -176,4 +176,8 @@ public final class ThreadFactoryBuilder {
       }
     };
   }
+
+  private static String format(String format, Object... args) {
+    return String.format(Locale.ROOT, format, args);
+  }
 }
diff --git a/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java b/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java
new file mode 100644
index 0000000..07b93bc
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 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.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RunnableFuture;
+
+import javax.annotation.Nullable;
+
+/**
+ * A {@link RunnableFuture} that also implements the {@link ListenableFuture}
+ * interface.
+ * 
+ * <p>This should be used in preference to {@link ListenableFutureTask} when possible for 
+ * performance reasons.
+ */
+ at GwtCompatible
+class TrustedListenableFutureTask<V> extends AbstractFuture.TrustedFuture<V>
+    implements RunnableFuture<V> {
+
+  /**
+   * Creates a {@code ListenableFutureTask} that will upon running, execute the
+   * given {@code Callable}.
+   *
+   * @param callable the callable task
+   */
+  static <V> TrustedListenableFutureTask<V> create(Callable<V> callable) {
+    return new TrustedListenableFutureTask<V>(callable);
+  }
+
+  /**
+   * Creates a {@code ListenableFutureTask} that will upon running, execute the
+   * given {@code Runnable}, and arrange that {@code get} will return the
+   * given result on successful completion.
+   *
+   * @param runnable the runnable task
+   * @param result the result to return on successful completion. If you don't
+   *     need a particular result, consider using constructions of the form:
+   *     {@code ListenableFuture<?> f = ListenableFutureTask.create(runnable,
+   *     null)}
+   */
+  static <V> TrustedListenableFutureTask<V> create(
+      Runnable runnable, @Nullable V result) {
+    return new TrustedListenableFutureTask<V>(Executors.callable(runnable, result));
+  }
+
+  private TrustedFutureInterruptibleTask task;
+
+  TrustedListenableFutureTask(Callable<V> callable) {
+    this.task = new TrustedFutureInterruptibleTask(callable);
+  }
+
+  @Override public void run() {
+    TrustedFutureInterruptibleTask localTask = task;
+    if (localTask != null) {
+      localTask.run();
+    }
+  }
+
+  @Override final void done() {
+    super.done();
+
+    // Free all resources associated with the running task
+    this.task = null;
+  }
+
+  @GwtIncompatible("Interruption not supported")
+  @Override protected final void interruptTask() {
+    TrustedFutureInterruptibleTask localTask = task;
+    if (localTask != null) {
+      localTask.interruptTask();
+    }
+  }
+
+  @WeakOuter
+  private final class TrustedFutureInterruptibleTask extends InterruptibleTask {
+    private final Callable<V> callable;
+
+    TrustedFutureInterruptibleTask(Callable<V> callable) {
+      this.callable = checkNotNull(callable);
+    }
+
+    @Override void runInterruptibly() {
+      // Ensure we haven't been cancelled or already run.
+      if (!isDone()) {
+        try {
+          set(callable.call());
+        } catch (Throwable t) {
+          setException(t);
+        } 
+      }
+    }
+
+    @Override boolean wasInterrupted() {
+      return TrustedListenableFutureTask.this.wasInterrupted();
+    }
+  }
+}
diff --git a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
index 19b91f2..3d19c4c 100644
--- a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
+++ b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
@@ -21,6 +21,7 @@ import static java.util.logging.Level.SEVERE;
 import com.google.common.annotations.VisibleForTesting;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
 import java.util.logging.Logger;
 
 /**
@@ -62,7 +63,8 @@ public final class UncaughtExceptionHandlers {
     @Override public void uncaughtException(Thread t, Throwable e) {
       try {
         // cannot use FormattingLogger due to a dependency loop
-        logger.log(SEVERE, String.format("Caught an exception in %s.  Shutting down.", t), e);
+        logger.log(SEVERE,
+            String.format(Locale.ROOT, "Caught an exception in %s.  Shutting down.", t), e);
       } catch (Throwable errorInLogging) {
         // If logging fails, e.g. due to missing memory, at least try to log the
         // message and the cause for the failed logging.
diff --git a/guava/src/com/google/common/util/concurrent/Uninterruptibles.java b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
index d0f80d7..521a655 100644
--- a/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
+++ b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
 import com.google.common.base.Preconditions;
 
 import java.util.concurrent.BlockingQueue;
@@ -40,6 +42,7 @@ import java.util.concurrent.TimeoutException;
  * @since 10.0
  */
 @Beta
+ at GwtCompatible(emulated = true)
 public final class Uninterruptibles {
 
   // Implementation Note: As of 3-7-11, the logic for each blocking/timeout
@@ -49,6 +52,7 @@ public final class Uninterruptibles {
    * Invokes {@code latch.}{@link CountDownLatch#await() await()}
    * uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static void awaitUninterruptibly(CountDownLatch latch) {
     boolean interrupted = false;
     try {
@@ -72,6 +76,7 @@ public final class Uninterruptibles {
    * {@code latch.}{@link CountDownLatch#await(long, TimeUnit)
    * await(timeout, unit)} uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static boolean awaitUninterruptibly(CountDownLatch latch,
       long timeout, TimeUnit unit) {
     boolean interrupted = false;
@@ -98,6 +103,7 @@ public final class Uninterruptibles {
   /**
    * Invokes {@code toJoin.}{@link Thread#join() join()} uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static void joinUninterruptibly(Thread toJoin) {
     boolean interrupted = false;
     try {
@@ -122,8 +128,8 @@ public final class Uninterruptibles {
    * {@link Futures#getUnchecked}.
    *
    * <p>If instead, you wish to treat {@link InterruptedException} uniformly
-   * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
-   * or {@link Futures#makeChecked}.
+   * with other exceptions, see {@link Futures#getChecked(Future, Class)
+   * Futures.getChecked}.
    *
    * @throws ExecutionException if the computation threw an exception
    * @throws CancellationException if the computation was cancelled
@@ -152,15 +158,16 @@ public final class Uninterruptibles {
    * uninterruptibly.
    *
    * <p>If instead, you wish to treat {@link InterruptedException} uniformly
-   * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
-   * or {@link Futures#makeChecked}.
+   * with other exceptions, see {@link Futures#getChecked(Future, Class)
+   * Futures.getChecked}.
    *
    * @throws ExecutionException if the computation threw an exception
    * @throws CancellationException if the computation was cancelled
    * @throws TimeoutException if the wait timed out
    */
+  @GwtIncompatible("TODO")
   public static <V> V getUninterruptibly(
-      Future<V> future, long timeout,  TimeUnit unit)
+      Future<V> future, long timeout, TimeUnit unit)
           throws ExecutionException, TimeoutException {
     boolean interrupted = false;
     try {
@@ -188,6 +195,7 @@ public final class Uninterruptibles {
    * {@code unit.}{@link TimeUnit#timedJoin(Thread, long)
    * timedJoin(toJoin, timeout)} uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static void joinUninterruptibly(Thread toJoin,
       long timeout, TimeUnit unit) {
     Preconditions.checkNotNull(toJoin);
@@ -215,6 +223,7 @@ public final class Uninterruptibles {
   /**
    * Invokes {@code queue.}{@link BlockingQueue#take() take()} uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static <E> E takeUninterruptibly(BlockingQueue<E> queue) {
     boolean interrupted = false;
     try {
@@ -241,6 +250,7 @@ public final class Uninterruptibles {
    * @throws IllegalArgumentException if some property of the specified element
    *     prevents it from being added to the given queue
    */
+  @GwtIncompatible("concurrency")
   public static <E> void putUninterruptibly(BlockingQueue<E> queue, E element) {
     boolean interrupted = false;
     try {
@@ -264,6 +274,7 @@ public final class Uninterruptibles {
    * Invokes {@code unit.}{@link TimeUnit#sleep(long) sleep(sleepFor)}
    * uninterruptibly.
    */
+  @GwtIncompatible("concurrency")
   public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
     boolean interrupted = false;
     try {
@@ -292,6 +303,7 @@ public final class Uninterruptibles {
    *
    * @since 18.0
    */
+  @GwtIncompatible("concurrency")
   public static boolean tryAcquireUninterruptibly(
       Semaphore semaphore, long timeout, TimeUnit unit) {
     return tryAcquireUninterruptibly(semaphore, 1, timeout, unit);
@@ -303,6 +315,7 @@ public final class Uninterruptibles {
    *
    * @since 18.0
    */
+  @GwtIncompatible("concurrency")
   public static boolean tryAcquireUninterruptibly(
       Semaphore semaphore, int permits, long timeout, TimeUnit unit) {
     boolean interrupted = false;
diff --git a/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java b/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
index 9417c69..e6a324b 100644
--- a/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
+++ b/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
@@ -53,7 +53,7 @@ abstract class WrappingExecutorService implements ExecutorService {
   /**
    * Wraps a {@code Callable} for submission to the underlying executor. This
    * method is also applied to any {@code Runnable} passed to the default
-   * implementation of {@link #wrapTest(Runnable)}.
+   * implementation of {@link #wrapTask(Runnable)}.
    */
   protected abstract <T> Callable<T> wrapTask(Callable<T> callable);
 
diff --git a/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java b/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
index b12c150..f218158 100644
--- a/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
+++ b/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
@@ -42,7 +42,7 @@ public final class PublicSuffixPatterns {
 
   /** If a hostname is contained as a key in this map, it is a public suffix. */
   public static final ImmutableMap<String, PublicSuffixType> EXACT =
-      TrieParser.parseTrie("a&027qjf--nx?12oa08--nx?2eyh3la2ckx--nx?32wqq1--nx?6&1f4a3abgm--nx?lbgw--nx??883xnn--nx?b!.&asnu?gro?ibnu?lim?moc?oc?sr?ten?ude?vog??ihsot??c!.&b&a?m?n??c&b?g?q??ep?fn?k&s?y??ln?no?oc,sn?t&n?opsgolb,?un??irfa?s??d&neit?om?tl??g!oy??hskihs?i&dem?sa??jnin?k&dov?usto??l!.&c,gro?moc?ofni?rep?t&en?ni??ude?vog??lenisiuc??m!.&ca?gro?oc?sserp?ten?vog??ahokoy?e00sf7vqn--nx??n!.&ac?cc?eman?gro?ibom?loohcs?moc?ni?o&c?fni?rp??r&d?o??s&u?w??vt?xm???p!.&bog?ca?d&em?ls??g&ni [...]
+      TrieParser.parseTrie("a&0&0trk9--nx?27qjf--nx?e9ebgn--nx?nbb0c7abgm--nx??12oa08--nx?2&eyh3la2ckx--nx?qbd9--nx??3&2wqq1--nx?60a0y8--nx??4x1d77xrck--nx?6&1f4a3abgm--nx?2yqyn--nx?3np8lv81qo3--nx?5b06t--nx?lbgw--nx??883xnn--nx?9d2c24--nx?a&a?it??b!.&asnu?gro?ibnu?lim?moc?oc?sr?t&en?opsgolb,?ude?vog??abila?c?ihsot?m?n??c!.&b&a?m?n??c&b?g?q??ep?fn?k&s?y??ln?no?oc,sn?t&n?opsgolb,?un??i&ma?nofelet?r&emarp?fa??sroc??naiva?s??d&ats?n&eit?oh??om?sa?tl??eg?f&c?ob??g!emo?naripi?oy??h&od?skihs?? [...]
 
   /**
    * If a hostname is not a key in the EXCLUDE map, and if removing its
@@ -50,7 +50,7 @@ public final class PublicSuffixPatterns {
    * public suffix.
    */
   public static final ImmutableMap<String, PublicSuffixType> UNDER =
-      TrieParser.parseTrie("az?db?e&k?y??gp?hk?in?jf?k&c?f?u.hcs??li?m&j?m?z??nb?p&j.&a&mahokoy?yogan??ebok?i&adnes?kasawak??oroppas?uhsuykatik??n??r&e?t??ug?w&k?z??yc?zm??");
+      TrieParser.parseTrie("db?e&k?y??gp?h&k?s.mroftalp,?in?jf?k&c?f?u.hcs??li?m&j?m?z??nb?p&j.&a&mahokoy?yogan??ebok?i&adnes?kasawak??oroppas?uhsuykatik??n??r&b.mon?e??ug?w&k?z??zm??");
 
   /**
    * The elements in this map would pass the UNDER test, but are known not to
@@ -59,5 +59,5 @@ public final class PublicSuffixPatterns {
    * important here. The map is simply used for consistency reasons.
    */
   public static final ImmutableMap<String, PublicSuffixType> EXCLUDED =
-      TrieParser.parseTrie("kc.www?pj.&a&mahokoy.ytic?yogan.ytic??ebok.ytic?i&adnes.ytic?kasawak.ytic??oroppas.ytic?uhsuykatik.ytic??rt.cin?zm.atadelet??");
+      TrieParser.parseTrie("kc.www?pj.&a&mahokoy.ytic?yogan.ytic??ebok.ytic?i&adnes.ytic?kasawak.ytic??oroppas.ytic?uhsuykatik.ytic??zm.atadelet??");
 }
diff --git a/mvn-deploy.sh b/mvn-deploy.sh
deleted file mode 100644
index 4c8a5f7..0000000
--- a/mvn-deploy.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-#
-# This script checks the java version and bails if it's less
-# than Java6 (because we use @Override annotations on interface
-# overriding methods.  It then proceeds to do a maven build that
-# first cleans, then builds the normal lifecycle through compilation
-# unit testing (if available) up to packaging.  It then packages
-# the source, javadocs, and maven site.  It then signs the 
-# artifacts with whatever pgp signature is the default of the 
-# user executing it, and then deploys to the repository contained
-# in the distributionManagement section of the pom.
-#
-# author: cgruber at google.com (Christian Edward Gruber)
-#
-if [[ -n ${JAVA_HOME} ]] ; then 
-  JAVA_CMD=${JAVA_HOME}/bin/java
-else
-  JAVA_CMD=java
-fi
-java_version="$(${JAVA_CMD} -version 2>&1 | grep -e 'java version' | awk '{ print $3 }')"
-
-# This test sucks, but it's short term
-# TODO(cgruber) strip the quotes and patch version and do version comparison. 
-greater_than_java5="$(echo ${java_version} | grep -e '^"1.[67]')"
-
-if [[ -z ${greater_than_java5} ]] ; then
-  echo "Your java version is ${java_version}."
-  echo "You must use at least a java 6 JVM to build and deploy this software."
-  exit 1
-else
-  echo "Building with java ${java_version}"
-fi
-
-if [[ $# > 0 ]]; then
-  params+=" -Dgpg.keyname=${1}"
-  gpg_sign_plugin=" gpg:sign"
-fi
-cmd="mvn clean package source:jar site:jar javadoc:jar ${gpg_sign_plugin} deploy ${params}"
-echo "Executing ${cmd}"
-${cmd}
diff --git a/pom.xml b/pom.xml
index dac208f..8c7a2d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,19 +11,20 @@
   </parent>
   <groupId>com.google.guava</groupId>
   <artifactId>guava-parent</artifactId>
-  <version>18.0</version>
+  <version>19.0</version>
   <packaging>pom</packaging>
   <name>Guava Maven Parent</name>
-  <url>http://code.google.com/p/guava-libraries</url>
+  <url>https://github.com/google/guava</url>
   <properties>
     <gpg.skip>true</gpg.skip>
     <!-- Override this with -Dtest.include="**/SomeTest.java" on the CLI -->
     <test.include>**/*Test.java</test.include>
-    <truth.version>0.23</truth.version>
+    <truth.version>0.25</truth.version>
+    <animal.sniffer.version>1.14</animal.sniffer.version>
   </properties>
   <issueManagement>
-    <system>code.google.com</system>
-    <url>http://code.google.com/p/guava-libraries/issues</url>
+    <system>GitHub Issues</system>
+    <url>https://github.com/google/guava/issues</url>
   </issueManagement>
   <inceptionYear>2010</inceptionYear>
   <licenses>
@@ -37,9 +38,9 @@
     <maven>3.0.3</maven>
   </prerequisites>
   <scm>
-    <connection>scm:git:https://code.google.com/p/guava-libraries/</connection>
-    <developerConnection>scm:git:https://code.google.com/p/guava-libraries/</developerConnection>
-    <url>http://code.google.com/p/guava-libraries/source/browse</url>
+    <connection>scm:git:https://github.com/google/guava.git</connection>
+    <developerConnection>scm:git:git at github.com:google/guava.git</developerConnection>
+    <url>https://github.com/google/guava</url>
   </scm>
   <developers>
     <developer>
@@ -55,6 +56,10 @@
       <timezone>-8</timezone>
     </developer>
   </developers>
+  <ciManagement>
+    <system>Travis CI</system>
+    <url>https://travis-ci.org/google/guava</url>
+  </ciManagement>
   <modules>
     <module>guava</module>
     <module>guava-gwt</module>
@@ -133,12 +138,12 @@
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>animal-sniffer-maven-plugin</artifactId>
-          <version>1.7</version>
+          <version>${animal.sniffer.version}</version>
           <configuration>
             <signature>
               <groupId>org.codehaus.mojo.signature</groupId>
               <artifactId>java16-sun</artifactId>
-              <version>1.0</version>
+              <version>1.10</version>
             </signature>
           </configuration>
           <executions>
@@ -155,7 +160,7 @@
           <artifactId>maven-javadoc-plugin</artifactId>
           <version>2.8</version>
           <configuration>
-            <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+            <notimestamp>true</notimestamp>
           </configuration>
           <executions>
             <execution>
@@ -200,6 +205,16 @@
         <version>1.3.9</version>
       </dependency>
       <dependency>
+        <groupId>com.google.errorprone</groupId>
+        <artifactId>error_prone_annotations</artifactId>
+        <version>2.0.2</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.j2objc</groupId>
+        <artifactId>j2objc-annotations</artifactId>
+        <version>0.1</version>
+      </dependency>
+      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.8.2</version>
@@ -233,7 +248,7 @@
       <dependency>
         <groupId>com.google.caliper</groupId>
         <artifactId>caliper</artifactId>
-        <version>0.5-rc1</version>
+        <version>1.0-beta-2</version>
         <scope>test</scope>
         <exclusions>
           <exclusion>
@@ -245,4 +260,64 @@
       </dependency>
     </dependencies>
   </dependencyManagement>
+  <profiles>
+    <profile>
+      <id>jdk7</id>
+      <activation>
+        <jdk>1.7</jdk>
+      </activation>
+      <!-- Set custom stylesheet under JDK7 -->
+      <reporting>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+            </configuration>
+          </plugin>
+        </plugins>
+      </reporting>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>jdk8</id>
+      <activation>
+        <jdk>[1.8,)</jdk>
+      </activation>
+      <!-- Disable doclint under JDK 8 -->
+      <reporting>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </reporting>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>
diff --git a/util/deploy_snapshot.sh b/util/deploy_snapshot.sh
new file mode 100755
index 0000000..0883b76
--- /dev/null
+++ b/util/deploy_snapshot.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# see https://coderwall.com/p/9b_lfq
+
+set -e -u
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guava" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
+  echo "Publishing Maven snapshot..."
+
+  mvn clean source:jar javadoc:jar deploy --settings="util/settings.xml" -DskipTests=true
+
+  echo "Maven snapshot published."
+fi
diff --git a/util/settings.xml b/util/settings.xml
new file mode 100644
index 0000000..306d14a
--- /dev/null
+++ b/util/settings.xml
@@ -0,0 +1,11 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+  <servers>
+    <server>
+      <id>sonatype-nexus-snapshots</id>
+      <username>${env.CI_DEPLOY_USERNAME}</username>
+      <password>${env.CI_DEPLOY_PASSWORD}</password>
+    </server>
+  </servers>
+</settings>
diff --git a/util/update_snapshot_docs.sh b/util/update_snapshot_docs.sh
new file mode 100755
index 0000000..99e8210
--- /dev/null
+++ b/util/update_snapshot_docs.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# see http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ for details
+
+set -e -u
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guava" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
+  echo "Publishing Javadoc and JDiff..."
+
+  cd $HOME
+  git clone -q -b gh-pages https://${GH_TOKEN}@github.com/google/guava gh-pages > /dev/null
+  cd gh-pages
+
+  git config --global user.email "travis at travis-ci.org"
+  git config --global user.name "travis-ci"
+
+  ./updaterelease.sh snapshot
+
+  git push -fq origin gh-pages > /dev/null
+
+  echo "Javadoc and JDiff published to gh-pages."
+fi

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/guava-libraries.git



More information about the pkg-java-commits mailing list