The following issues were found

guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
6 issues
JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 38

              @GwtCompatible
@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class SetAddAllTester<E> extends AbstractSetTester<E> {
  @CollectionFeature.Require(SUPPORTS_ADD)
  @CollectionSize.Require(absent = ZERO)
  public void testAddAll_supportedSomePresent() {
    assertTrue(
        "add(somePresent) should return true", getSet().addAll(MinimalCollection.of(e3(), e0())));
    expectAdded(e3());

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 42

                @CollectionSize.Require(absent = ZERO)
  public void testAddAll_supportedSomePresent() {
    assertTrue(
        "add(somePresent) should return true", getSet().addAll(MinimalCollection.of(e3(), e0())));
    expectAdded(e3());
  }

  @CollectionFeature.Require(SUPPORTS_ADD)
  public void testAddAll_withDuplicates() {

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 46

                  expectAdded(e3());
  }

  @CollectionFeature.Require(SUPPORTS_ADD)
  public void testAddAll_withDuplicates() {
    MinimalCollection<E> elementsToAdd = MinimalCollection.of(e3(), e4(), e3(), e4());
    assertTrue("add(hasDuplicates) should return true", getSet().addAll(elementsToAdd));
    expectAdded(e3(), e4());
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 49

                @CollectionFeature.Require(SUPPORTS_ADD)
  public void testAddAll_withDuplicates() {
    MinimalCollection<E> elementsToAdd = MinimalCollection.of(e3(), e4(), e3(), e4());
    assertTrue("add(hasDuplicates) should return true", getSet().addAll(elementsToAdd));
    expectAdded(e3(), e4());
  }

  @CollectionFeature.Require(SUPPORTS_ADD)
  @CollectionSize.Require(absent = ZERO)

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 53

                  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(e0())));
    expectUnchanged();
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 56

                @CollectionFeature.Require(SUPPORTS_ADD)
  @CollectionSize.Require(absent = ZERO)
  public void testAddAll_supportedAllPresent() {
    assertFalse("add(allPresent) should return false", getSet().addAll(MinimalCollection.of(e0())));
    expectUnchanged();
  }
}

            

Reported by PMD.

guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
6 issues
JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 41

              @GwtCompatible
@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class QueueRemoveTester<E> extends AbstractQueueTester<E> {
  @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ZERO)
  public void testRemove_empty() {
    try {
      getQueue().remove();
      fail("emptyQueue.remove() should throw");

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 45

                @CollectionSize.Require(ZERO)
  public void testRemove_empty() {
    try {
      getQueue().remove();
      fail("emptyQueue.remove() should throw");
    } catch (NoSuchElementException expected) {
    }
    expectUnchanged();
  }

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 52

                  expectUnchanged();
  }

  @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ONE)
  public void testRemove_size1() {
    assertEquals("size1Queue.remove() should return first element", e0(), getQueue().remove());
    expectMissing(e0());
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 55

                @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ONE)
  public void testRemove_size1() {
    assertEquals("size1Queue.remove() should return first element", e0(), getQueue().remove());
    expectMissing(e0());
  }

  @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 59

                  expectMissing(e0());
  }

  @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)
  public void testRemove_sizeMany() {
    assertEquals("sizeManyQueue.remove() should return first element", e0(), getQueue().remove());
    expectMissing(e0());
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 62

                @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)
  public void testRemove_sizeMany() {
    assertEquals("sizeManyQueue.remove() should return first element", e0(), getQueue().remove());
    expectMissing(e0());
  }
}

            

Reported by PMD.

guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
6 issues
JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 40

              @GwtCompatible
@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class QueuePollTester<E> extends AbstractQueueTester<E> {
  @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ZERO)
  public void testPoll_empty() {
    assertNull("emptyQueue.poll() should return null", getQueue().poll());
    expectUnchanged();
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 43

                @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ZERO)
  public void testPoll_empty() {
    assertNull("emptyQueue.poll() should return null", getQueue().poll());
    expectUnchanged();
  }

  @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ONE)

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 47

                  expectUnchanged();
  }

  @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ONE)
  public void testPoll_size1() {
    assertEquals("size1Queue.poll() should return first element", e0(), getQueue().poll());
    expectMissing(e0());
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 50

                @CollectionFeature.Require(SUPPORTS_REMOVE)
  @CollectionSize.Require(ONE)
  public void testPoll_size1() {
    assertEquals("size1Queue.poll() should return first element", e0(), getQueue().poll());
    expectMissing(e0());
  }

  @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 54

                  expectMissing(e0());
  }

  @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)
  public void testPoll_sizeMany() {
    assertEquals("sizeManyQueue.poll() should return first element", e0(), getQueue().poll());
    expectMissing(e0());
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 57

                @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
  @CollectionSize.Require(SEVERAL)
  public void testPoll_sizeMany() {
    assertEquals("sizeManyQueue.poll() should return first element", e0(), getQueue().poll());
    expectMissing(e0());
  }
}

            

Reported by PMD.

guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
6 issues
JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 38

              @GwtCompatible
@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class QueuePeekTester<E> extends AbstractQueueTester<E> {
  @CollectionSize.Require(ZERO)
  public void testPeek_empty() {
    assertNull("emptyQueue.peek() should return null", getQueue().peek());
    expectUnchanged();
  }


            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 40

              public class QueuePeekTester<E> extends AbstractQueueTester<E> {
  @CollectionSize.Require(ZERO)
  public void testPeek_empty() {
    assertNull("emptyQueue.peek() should return null", getQueue().peek());
    expectUnchanged();
  }

  @CollectionSize.Require(ONE)
  public void testPeek_size1() {

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 44

                  expectUnchanged();
  }

  @CollectionSize.Require(ONE)
  public void testPeek_size1() {
    assertEquals("size1Queue.peek() should return first element", e0(), getQueue().peek());
    expectUnchanged();
  }


            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 46

              
  @CollectionSize.Require(ONE)
  public void testPeek_size1() {
    assertEquals("size1Queue.peek() should return first element", e0(), getQueue().peek());
    expectUnchanged();
  }

  @CollectionFeature.Require(KNOWN_ORDER)
  @CollectionSize.Require(SEVERAL)

            

Reported by PMD.

JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 50

                  expectUnchanged();
  }

  @CollectionFeature.Require(KNOWN_ORDER)
  @CollectionSize.Require(SEVERAL)
  public void testPeek_sizeMany() {
    assertEquals("sizeManyQueue.peek() should return first element", e0(), getQueue().peek());
    expectUnchanged();
  }

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 53

                @CollectionFeature.Require(KNOWN_ORDER)
  @CollectionSize.Require(SEVERAL)
  public void testPeek_sizeMany() {
    assertEquals("sizeManyQueue.peek() should return first element", e0(), getQueue().peek());
    expectUnchanged();
  }
}

            

Reported by PMD.

android/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
6 issues
Field delegate has the same name as a method
Error

Line: 64

                  return new MutableClassToInstanceMap<B>(backingMap);
  }

  private final Map<Class<? extends B>, B> delegate;

  private MutableClassToInstanceMap(Map<Class<? extends B>, B> delegate) {
    this.delegate = checkNotNull(delegate);
  }


            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 95

              
      @Override
      protected Set<Entry<Class<? extends B>, B>> delegate() {
        return MutableClassToInstanceMap.this.delegate().entrySet();
      }

      @Override
      public Iterator<Entry<Class<? extends B>, B>> iterator() {
        return new TransformedIterator<Entry<Class<? extends B>, B>, Entry<Class<? extends B>, B>>(

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 95

              
      @Override
      protected Set<Entry<Class<? extends B>, B>> delegate() {
        return MutableClassToInstanceMap.this.delegate().entrySet();
      }

      @Override
      public Iterator<Entry<Class<? extends B>, B>> iterator() {
        return new TransformedIterator<Entry<Class<? extends B>, B>, Entry<Class<? extends B>, B>>(

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 95

              
      @Override
      protected Set<Entry<Class<? extends B>, B>> delegate() {
        return MutableClassToInstanceMap.this.delegate().entrySet();
      }

      @Override
      public Iterator<Entry<Class<? extends B>, B>> iterator() {
        return new TransformedIterator<Entry<Class<? extends B>, B>, Entry<Class<? extends B>, B>>(

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 101

                    @Override
      public Iterator<Entry<Class<? extends B>, B>> iterator() {
        return new TransformedIterator<Entry<Class<? extends B>, B>, Entry<Class<? extends B>, B>>(
            delegate().iterator()) {
          @Override
          Entry<Class<? extends B>, B> transform(Entry<Class<? extends B>, B> from) {
            return checkedEntry(from);
          }
        };

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 149

              
  @CanIgnoreReturnValue
  private static <B, T extends B> T cast(Class<T> type, B value) {
    return Primitives.wrap(type).cast(value);
  }

  private Object writeReplace() {
    return new SerializedForm(delegate());
  }

            

Reported by PMD.

android/guava/src/com/google/common/collect/ImmutableMapKeySet.java
6 issues
Classes implementing Serializable should set a serialVersionUID
Error

Line: 32

               */
@GwtCompatible(emulated = true)
@ElementTypesAreNonnullByDefault
final class ImmutableMapKeySet<K, V> extends IndexedImmutableSet<K> {
  private final ImmutableMap<K, V> map;

  ImmutableMapKeySet(ImmutableMap<K, V> map) {
    this.map = map;
  }

            

Reported by PMD.

Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 33

              @GwtCompatible(emulated = true)
@ElementTypesAreNonnullByDefault
final class ImmutableMapKeySet<K, V> extends IndexedImmutableSet<K> {
  private final ImmutableMap<K, V> map;

  ImmutableMapKeySet(ImmutableMap<K, V> map) {
    this.map = map;
  }


            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 56

              
  @Override
  K get(int index) {
    return map.entrySet().asList().get(index).getKey();
  }

  @Override
  boolean isPartialView() {
    return true;

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 56

              
  @Override
  K get(int index) {
    return map.entrySet().asList().get(index).getKey();
  }

  @Override
  boolean isPartialView() {
    return true;

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 56

              
  @Override
  K get(int index) {
    return map.entrySet().asList().get(index).getKey();
  }

  @Override
  boolean isPartialView() {
    return true;

            

Reported by PMD.

Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 72

              
  @GwtIncompatible // serialization
  private static class KeySetSerializedForm<K> implements Serializable {
    final ImmutableMap<K, ?> map;

    KeySetSerializedForm(ImmutableMap<K, ?> map) {
      this.map = map;
    }


            

Reported by PMD.

guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
6 issues
JUnit 4 tests that execute tests should use the @Test annotation, JUnit 5 tests should use @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest
Design

Line: 35

              @GwtCompatible
@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class ListMultimapPutAllTester<K, V> extends AbstractListMultimapTester<K, V> {
  @MapFeature.Require(SUPPORTS_PUT)
  public void testPutAllAddsAtEndInOrder() {
    @SuppressWarnings("unchecked")
    List<V> values = Arrays.asList(v3(), v1(), v4());

    for (K k : sampleKeys()) {

            

Reported by PMD.

Unit tests should not contain more than 1 assert(s).
Design

Line: 36

              @Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
public class ListMultimapPutAllTester<K, V> extends AbstractListMultimapTester<K, V> {
  @MapFeature.Require(SUPPORTS_PUT)
  public void testPutAllAddsAtEndInOrder() {
    @SuppressWarnings("unchecked")
    List<V> values = Arrays.asList(v3(), v1(), v4());

    for (K k : sampleKeys()) {
      resetContainer();

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 43

                  for (K k : sampleKeys()) {
      resetContainer();

      List<V> expectedValues = copyToList(multimap().get(k));

      assertTrue(multimap().putAll(k, values));
      expectedValues.addAll(values);

      assertGet(k, expectedValues);

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 45

              
      List<V> expectedValues = copyToList(multimap().get(k));

      assertTrue(multimap().putAll(k, values));
      expectedValues.addAll(values);

      assertGet(k, expectedValues);
    }
  }

            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 46

                    List<V> expectedValues = copyToList(multimap().get(k));

      assertTrue(multimap().putAll(k, values));
      expectedValues.addAll(values);

      assertGet(k, expectedValues);
    }
  }
}

            

Reported by PMD.

Found 'DU'-anomaly for variable 'values' (lines '38'-'50').
Error

Line: 38

                @MapFeature.Require(SUPPORTS_PUT)
  public void testPutAllAddsAtEndInOrder() {
    @SuppressWarnings("unchecked")
    List<V> values = Arrays.asList(v3(), v1(), v4());

    for (K k : sampleKeys()) {
      resetContainer();

      List<V> expectedValues = copyToList(multimap().get(k));

            

Reported by PMD.

android/guava/src/com/google/common/net/HostSpecifier.java
6 issues
Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 49

              @ElementTypesAreNonnullByDefault
public final class HostSpecifier {

  private final String canonicalForm;

  private HostSpecifier(String canonicalForm) {
    this.canonicalForm = canonicalForm;
  }


            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 75

                  // Verify that no port was specified, and strip optional brackets from
    // IPv6 literals.
    final HostAndPort parsedHost = HostAndPort.fromString(specifier);
    Preconditions.checkArgument(!parsedHost.hasPort());
    final String host = parsedHost.getHost();

    // Try to interpret the specifier as an IP address. Note we build
    // the address rather than using the .is* methods because we want to
    // use InetAddresses.toUriString to convert the result to a string in

            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 76

                  // IPv6 literals.
    final HostAndPort parsedHost = HostAndPort.fromString(specifier);
    Preconditions.checkArgument(!parsedHost.hasPort());
    final String host = parsedHost.getHost();

    // Try to interpret the specifier as an IP address. Note we build
    // the address rather than using the .is* methods because we want to
    // use InetAddresses.toUriString to convert the result to a string in
    // canonical form.

            

Reported by PMD.

Avoid empty catch blocks
Error

Line: 85

                  InetAddress addr = null;
    try {
      addr = InetAddresses.forString(host);
    } catch (IllegalArgumentException e) {
      // It is not an IPv4 or IPv6 literal
    }

    if (addr != null) {
      return new HostSpecifier(InetAddresses.toUriString(addr));

            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 98

                  // TODO(user): different versions of this for different factories?
    final InternetDomainName domain = InternetDomainName.from(host);

    if (domain.hasPublicSuffix()) {
      return new HostSpecifier(domain.toString());
    }

    throw new IllegalArgumentException(
        "Domain name does not have a recognized public suffix: " + host);

            

Reported by PMD.

Found 'DD'-anomaly for variable 'addr' (lines '82'-'84').
Error

Line: 82

                  // the address rather than using the .is* methods because we want to
    // use InetAddresses.toUriString to convert the result to a string in
    // canonical form.
    InetAddress addr = null;
    try {
      addr = InetAddresses.forString(host);
    } catch (IllegalArgumentException e) {
      // It is not an IPv4 or IPv6 literal
    }

            

Reported by PMD.

android/guava/src/com/google/common/graph/MapRetrievalCache.java
6 issues
Use equals() to compare object references.
Error

Line: 73

              
    // Check cache. We use == on purpose because it's cheaper and a cache miss is ok.
    entry = cacheEntry1;
    if (entry != null && entry.key == key) {
      return entry.value;
    }
    entry = cacheEntry2;
    if (entry != null && entry.key == key) {
      // Promote second cache entry to first so the access pattern

            

Reported by PMD.

Use equals() to compare object references.
Error

Line: 77

                    return entry.value;
    }
    entry = cacheEntry2;
    if (entry != null && entry.key == key) {
      // Promote second cache entry to first so the access pattern
      // [K1, K2, K1, K3, K1, K4...] still hits the cache half the time.
      addToCache(entry);
      return entry.value;
    }

            

Reported by PMD.

Assigning an Object to null is a code smell. Consider refactoring.
Error

Line: 89

                @Override
  void clearCache() {
    super.clearCache();
    cacheEntry1 = null;
    cacheEntry2 = null;
  }

  private void addToCache(K key, V value) {
    addToCache(new CacheEntry<K, V>(key, value));

            

Reported by PMD.

Assigning an Object to null is a code smell. Consider refactoring.
Error

Line: 90

                void clearCache() {
    super.clearCache();
    cacheEntry1 = null;
    cacheEntry2 = null;
  }

  private void addToCache(K key, V value) {
    addToCache(new CacheEntry<K, V>(key, value));
  }

            

Reported by PMD.

Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 104

                }

  private static final class CacheEntry<K, V> {
    final K key;
    final V value;

    CacheEntry(K key, V value) {
      this.key = key;
      this.value = value;

            

Reported by PMD.

Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 105

              
  private static final class CacheEntry<K, V> {
    final K key;
    final V value;

    CacheEntry(K key, V value) {
      this.key = key;
      this.value = value;
    }

            

Reported by PMD.

android/guava/src/com/google/common/graph/MapIteratorCache.java
6 issues
Found non-transient, non-static member. Please mark as transient or provide accessors.
Error

Line: 46

               */
@ElementTypesAreNonnullByDefault
class MapIteratorCache<K, V> {
  private final Map<K, V> backingMap;

  /*
   * Per JDK: "the behavior of a map entry is undefined if the backing map has been modified after
   * the entry was returned by the iterator, except through the setValue operation on the map entry"
   * As such, this field must be cleared before every map mutation.

            

Reported by PMD.

Potential violation of Law of Demeter (method chain calls)
Design

Line: 111

                  return new AbstractSet<K>() {
      @Override
      public UnmodifiableIterator<K> iterator() {
        final Iterator<Entry<K, V>> entryIterator = backingMap.entrySet().iterator();

        return new UnmodifiableIterator<K>() {
          @Override
          public boolean hasNext() {
            return entryIterator.hasNext();

            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 123

                        public K next() {
            Entry<K, V> entry = entryIterator.next(); // store local reference for thread-safety
            cacheEntry = entry;
            return entry.getKey();
          }
        };
      }

      @Override

            

Reported by PMD.

Potential violation of Law of Demeter (object not created locally)
Design

Line: 147

                  Entry<K, V> entry = cacheEntry; // store local reference for thread-safety

    // Check cache. We use == on purpose because it's cheaper and a cache miss is ok.
    if (entry != null && entry.getKey() == key) {
      return entry.getValue();
    }
    return null;
  }


            

Reported by PMD.

Use equals() to compare object references.
Error

Line: 147

                  Entry<K, V> entry = cacheEntry; // store local reference for thread-safety

    // Check cache. We use == on purpose because it's cheaper and a cache miss is ok.
    if (entry != null && entry.getKey() == key) {
      return entry.getValue();
    }
    return null;
  }


            

Reported by PMD.

Assigning an Object to null is a code smell. Consider refactoring.
Error

Line: 154

                }

  void clearCache() {
    cacheEntry = null;
  }
}

            

Reported by PMD.