Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.collections4.map;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableMap;
import org.apache.commons.collections4.KeyValue;
import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.iterators.EmptyIterator;
import org.apache.commons.collections4.iterators.EmptyMapIterator;
/**
* An abstract implementation of a hash-based map which provides numerous points for
* subclasses to override.
*
* This class implements all the features necessary for a subclass hash-based map.
* Key-value entries are stored in instances of the {@code HashEntry} class,
* which can be overridden and replaced. The iterators can similarly be replaced,
* without the need to replace the KeySet, EntrySet and Values view classes.
*
*
* Overridable methods are provided to change the default hashing behavior, and
* to change how entries are added to and removed from the map. Hopefully, all you
* need for unusual subclasses is here.
*
*
* NOTE: From Commons Collections 3.1 this class extends AbstractMap.
* This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1.
* This extends clause will be removed in v5.0.
*
*
* @param the type of the keys in this map
* @param the type of the values in this map
* @since 3.0
*/
public class AbstractHashedMap extends AbstractMap implements IterableMap {
/**
* EntrySet implementation.
*
* @param the type of the keys in the map
* @param the type of the values in the map
*/
protected static class EntrySet extends AbstractSet> {
/** The parent map */
private final AbstractHashedMap parent;
/**
* Constructs a new instance.
*
* @param parent The parent map.
*/
protected EntrySet(final AbstractHashedMap parent) {
this.parent = parent;
}
@Override
public void clear() {
parent.clear();
}
@Override
public boolean contains(final Object entry) {
if (entry instanceof Map.Entry) {
final Map.Entry, ?> e = (Map.Entry, ?>) entry;
final Entry match = parent.getEntry(e.getKey());
return match != null && match.equals(e);
}
return false;
}
@Override
public Iterator> iterator() {
return parent.createEntrySetIterator();
}
@Override
public boolean remove(final Object obj) {
if (!(obj instanceof Map.Entry)) {
return false;
}
if (!contains(obj)) {
return false;
}
final Map.Entry, ?> entry = (Map.Entry, ?>) obj;
parent.remove(entry.getKey());
return true;
}
@Override
public int size() {
return parent.size();
}
}
/**
* EntrySet iterator.
*
* @param the type of the keys in the map
* @param the type of the values in the map
*/
protected static class EntrySetIterator extends HashIterator implements Iterator> {
/**
* Constructs a new instance.
*
* @param parent The parent map.
*/
protected EntrySetIterator(final AbstractHashedMap parent) {
super(parent);
}
@Override
public Map.Entry next() {
return super.nextEntry();
}
}
/**
* HashEntry used to store the data.
*
* If you subclass {@code AbstractHashedMap} but not {@code HashEntry}
* then you will not be able to access the protected fields.
* The {@code entryXxx()} methods on {@code AbstractHashedMap} exist
* to provide the necessary access.
*
*
* @param the type of the keys
* @param the type of the values
*/
protected static class HashEntry implements Map.Entry, KeyValue {
/** The next entry in the hash chain */
protected HashEntry next;
/** The hash code of the key */
protected int hashCode;
/** The key */
protected Object key;
/** The value */
protected Object value;
/**
* Constructs a new instance.
*
* @param next next.
* @param hashCode hash code.
* @param key key.
* @param value value.
*/
protected HashEntry(final HashEntry next, final int hashCode, final Object key, final V value) {
this.next = next;
this.hashCode = hashCode;
this.key = key;
this.value = value;
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Map.Entry)) {
return false;
}
final Map.Entry, ?> other = (Map.Entry, ?>) obj;
return
Objects.equals(getKey(), other.getKey()) &&
Objects.equals(getValue(), other.getValue());
}
@Override
@SuppressWarnings("unchecked")
public K getKey() {
if (key == NULL) {
return null;
}
return (K) key;
}
@Override
@SuppressWarnings("unchecked")
public V getValue() {
return (V) value;
}
@Override
public int hashCode() {
return (getKey() == null ? 0 : getKey().hashCode()) ^
(getValue() == null ? 0 : getValue().hashCode());
}
@Override
@SuppressWarnings("unchecked")
public V setValue(final V value) {
final Object old = this.value;
this.value = value;
return (V) old;
}
@Override
public String toString() {
return new StringBuilder().append(getKey()).append('=').append(getValue()).toString();
}
}
/**
* Base Iterator.
*
* @param the type of the keys in the map
* @param the type of the values in the map
*/
protected abstract static class HashIterator {
/** The parent map */
private final AbstractHashedMap parent;
/** The current index into the array of buckets */
private int hashIndex;
/** The last returned entry */
private HashEntry last;
/** The next entry */
private HashEntry next;
/** The modification count expected */
private int expectedModCount;
/**
* Constructs a new instance.
*
* @param parent The parent AbstractHashedMap.
*/
protected HashIterator(final AbstractHashedMap parent) {
this.parent = parent;
final HashEntry[] data = parent.data;
int i = data.length;
HashEntry next = null;
while (i > 0 && next == null) {
next = data[--i];
}
this.next = next;
this.hashIndex = i;
this.expectedModCount = parent.modCount;
}
/**
* Gets the current entry.
*
* @return the current entry.
*/
protected HashEntry currentEntry() {
return last;
}
/**
* Tests whether there is a next entry.
*
* @return whether there is a next entry.
*/
public boolean hasNext() {
return next != null;
}
/**
* Gets the next entry.
*
* @return the next entry.
*/
protected HashEntry nextEntry() {
if (parent.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
final HashEntry newCurrent = next;
if (newCurrent == null) {
throw new NoSuchElementException(NO_NEXT_ENTRY);
}
final HashEntry[] data = parent.data;
int i = hashIndex;
HashEntry n = newCurrent.next;
while (n == null && i > 0) {
n = data[--i];
}
next = n;
hashIndex = i;
last = newCurrent;
return newCurrent;
}
/**
* Removes the current element.
*/
public void remove() {
if (last == null) {
throw new IllegalStateException(REMOVE_INVALID);
}
if (parent.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
parent.remove(last.getKey());
last = null;
expectedModCount = parent.modCount;
}
@Override
public String toString() {
if (last != null) {
return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
}
return "Iterator[]";
}
}
/**
* MapIterator implementation.
*
* @param the type of the keys in the map
* @param the type of the values in the map
*/
protected static class HashMapIterator extends HashIterator implements MapIterator {
/**
* Constructs a new instance.
*
* @param parent The parent AbstractHashedMap.
*/
protected HashMapIterator(final AbstractHashedMap parent) {
super(parent);
}
@Override
public K getKey() {
final HashEntry current = currentEntry();
if (current == null) {
throw new IllegalStateException(GETKEY_INVALID);
}
return current.getKey();
}
@Override
public V getValue() {
final HashEntry current = currentEntry();
if (current == null) {
throw new IllegalStateException(GETVALUE_INVALID);
}
return current.getValue();
}
@Override
public K next() {
return super.nextEntry().getKey();
}
@Override
public V setValue(final V value) {
final HashEntry current = currentEntry();
if (current == null) {
throw new IllegalStateException(SETVALUE_INVALID);
}
return current.setValue(value);
}
}
/**
* KeySet implementation.
*
* @param the type of elements maintained by this set
*/
protected static class KeySet extends AbstractSet {
/** The parent map */
private final AbstractHashedMap parent;
/**
* Constructs a new instance.
*
* @param parent The parent AbstractHashedMap.
*/
protected KeySet(final AbstractHashedMap parent) {
this.parent = parent;
}
@Override
public void clear() {
parent.clear();
}
@Override
public boolean contains(final Object key) {
return parent.containsKey(key);
}
@Override
public Iterator iterator() {
return parent.createKeySetIterator();
}
@Override
public boolean remove(final Object key) {
final boolean result = parent.containsKey(key);
parent.remove(key);
return result;
}
@Override
public int size() {
return parent.size();
}
}
/**
* KeySet iterator.
*
* @param the type of elements maintained by this set
*/
protected static class KeySetIterator extends HashIterator implements Iterator {
/**
* Constructs a new instance.
*
* @param parent The parent AbstractHashedMap.
*/
@SuppressWarnings("unchecked")
protected KeySetIterator(final AbstractHashedMap parent) {
super((AbstractHashedMap) parent);
}
@Override
public K next() {
return super.nextEntry().getKey();
}
}
/**
* Values implementation.
*
* @param the type of elements maintained by this collection
*/
protected static class Values extends AbstractCollection {
/** The parent map */
private final AbstractHashedMap, V> parent;
/**
* Constructs a new instance.
*
* @param parent The parent AbstractHashedMap.
*/
protected Values(final AbstractHashedMap, V> parent) {
this.parent = parent;
}
@Override
public void clear() {
parent.clear();
}
@Override
public boolean contains(final Object value) {
return parent.containsValue(value);
}
@Override
public Iterator iterator() {
return parent.createValuesIterator();
}
@Override
public int size() {
return parent.size();
}
}
/**
* Values iterator.
*
* @param the type of elements maintained by this collection
*/
protected static class ValuesIterator extends HashIterator