com.google.common.collect.NpeThrowingAbstractMap Maven / Gradle / Ivy
Show all versions of google-collections Show documentation
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* {@code AbstractMap} extension whose views have {@code removeAll} and
* {@code retainAll} methods that always throw an exception when given a null
* collection. It provides a workaround for Sun bug
* 4802647. It also 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.
*
* @author Jared Levy
*/
abstract class NpeThrowingAbstractMap extends AbstractMap {
/**
* Supplies an entry set, a wrapped version of which is returned by
* {@code entrySet()}. That way, {@link #entrySet} retrieves an entry set
* whose {@link Set#retainAll} method always throws an exception.
*
* This method is invoked at most once on a given map, at the time when
* {@code entrySet()} is first called.
*/
protected abstract Set> createEntrySet();
private transient Set> entrySet;
@Override public synchronized Set> entrySet() {
if (entrySet == null) {
final Set> delegate = createEntrySet();
entrySet = new ForwardingSet>() {
@Override protected Set> delegate() {
return delegate;
}
};
}
return entrySet;
}
private transient Set keySet;
@Override public synchronized Set keySet() {
if (keySet == null) {
final Set delegate = super.keySet();
keySet = new ForwardingSet() {
@Override protected Set delegate() {
return delegate;
}
@Override public boolean isEmpty() {
return NpeThrowingAbstractMap.this.isEmpty();
}
};
}
return keySet;
}
private transient Collection values;
@Override public synchronized Collection values() {
if (values == null) {
final Collection delegate = super.values();
values = new ForwardingCollection() {
@Override protected Collection delegate() {
return delegate;
}
@Override public boolean isEmpty() {
return NpeThrowingAbstractMap.this.isEmpty();
}
};
}
return values;
}
/**
* Returns {@code true} if this map contains no key-value mappings.
*
* The implementation returns {@code entrySet().isEmpty()}.
*
* @return {@code true} if this map contains no key-value mappings
*/
@Override public boolean isEmpty() {
return entrySet().isEmpty();
}
}