src.it.unimi.dsi.fastutil.bytes.Byte2LongArrayMap Maven / Gradle / Ivy
/* Generic definitions */
/* Assertions (useful to generate conditional code) */
/* Current type and class (and size, if applicable) */
/* Value methods */
/* Interfaces (keys) */
/* Interfaces (values) */
/* Abstract implementations (keys) */
/* Abstract implementations (values) */
/* Static containers (keys) */
/* Static containers (values) */
/* Implementations */
/* Synchronized wrappers */
/* Unmodifiable wrappers */
/* Other wrappers */
/* Methods (keys) */
/* Methods (values) */
/* Methods (keys/values) */
/* Methods that have special names depending on keys (but the special names depend on values) */
/* Equality */
/* Object/Reference-only definitions (keys) */
/* Primitive-type-only definitions (keys) */
/* Object/Reference-only definitions (values) */
/* Primitive-type-only definitions (values) */
/*
* Copyright (C) 2007-2013 Sebastiano Vigna
*
* 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 it.unimi.dsi.fastutil.bytes;
import java.util.Map;
import java.util.NoSuchElementException;
import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.longs.LongCollection;
import it.unimi.dsi.fastutil.longs.LongCollections;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongArrays;
/** A simple, brute-force implementation of a map based on two parallel backing arrays.
*
* The main purpose of this
* implementation is that of wrapping cleanly the brute-force approach to the storage of a very
* small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
*/
public class Byte2LongArrayMap extends AbstractByte2LongMap implements java.io.Serializable, Cloneable {
private static final long serialVersionUID = 1L;
/** The keys (valid up to {@link #size}, excluded). */
private transient byte[] key;
/** The values (parallel to {@link #key}). */
private transient long[] value;
/** The number of valid entries in {@link #key} and {@link #value}. */
private int size;
/** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
*
*
It is responsibility of the caller that the elements of key
are distinct.
*
* @param key the key array.
* @param value the value array (it must have the same length as key
).
*/
public Byte2LongArrayMap( final byte[] key, final long[] value ) {
this.key = key;
this.value = value;
size = key.length;
if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
}
/** Creates a new empty array map.
*/
public Byte2LongArrayMap() {
this.key = ByteArrays.EMPTY_ARRAY;
this.value = LongArrays.EMPTY_ARRAY;
}
/** Creates a new empty array map of given capacity.
*
* @param capacity the initial capacity.
*/
public Byte2LongArrayMap( final int capacity ) {
this.key = new byte[ capacity ];
this.value = new long[ capacity ];
}
/** Creates a new empty array map copying the entries of a given map.
*
* @param m a map.
*/
public Byte2LongArrayMap( final Byte2LongMap m ) {
this( m.size() );
putAll( m );
}
/** Creates a new empty array map copying the entries of a given map.
*
* @param m a map.
*/
public Byte2LongArrayMap( final Map extends Byte, ? extends Long> m ) {
this( m.size() );
putAll( m );
}
/** Creates a new array map with given key and value backing arrays, using the given number of elements.
*
*
It is responsibility of the caller that the first size
elements of key
are distinct.
*
* @param key the key array.
* @param value the value array (it must have the same length as key
).
* @param size the number of valid elements in key
and value
.
*/
public Byte2LongArrayMap( final byte[] key, final long[] value, final int size ) {
this.key = key;
this.value = value;
this.size = size;
if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
}
private final class EntrySet extends AbstractObjectSet implements FastEntrySet {
@Override
public ObjectIterator iterator() {
return new AbstractObjectIterator() {
int next = 0;
public boolean hasNext() {
return next < size;
}
@SuppressWarnings("unchecked")
public Entry next() {
if ( ! hasNext() ) throw new NoSuchElementException();
return new AbstractByte2LongMap.BasicEntry ( key[ next ], value[ next++ ] );
}
};
}
public ObjectIterator fastIterator() {
return new AbstractObjectIterator() {
int next = 0;
final BasicEntry entry = new BasicEntry ( ((byte)0), (0) );
public boolean hasNext() {
return next < size;
}
@SuppressWarnings("unchecked")
public Entry next() {
if ( ! hasNext() ) throw new NoSuchElementException();
entry.key = key[ next ];
entry.value = value[ next++ ];
return entry;
}
};
}
public int size() {
return size;
}
@SuppressWarnings("unchecked")
public boolean contains( Object o ) {
if ( ! ( o instanceof Map.Entry ) ) return false;
final Map.Entry e = (Map.Entry)o;
final byte k = ((e.getKey()).byteValue());
return Byte2LongArrayMap.this.containsKey( k ) && ( (Byte2LongArrayMap.this.get( k )) == (((e.getValue()).longValue())) );
}
}
public FastEntrySet byte2LongEntrySet() {
return new EntrySet();
}
private int findKey( final byte k ) {
final byte[] key = this.key;
for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
return -1;
}
@SuppressWarnings("unchecked")
public long get( final byte k ) {
final byte[] key = this.key;
for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return value[ i ];
return defRetValue;
}
public int size() {
return size;
}
@Override
public void clear() {
size = 0;
}
@Override
public boolean containsKey( final byte k ) {
return findKey( k ) != -1;
}
@Override
@SuppressWarnings("unchecked")
public boolean containsValue( long v ) {
for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == (v) ) ) return true;
return false;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
@SuppressWarnings("unchecked")
public long put( byte k, long v ) {
final int oldKey = findKey( k );
if ( oldKey != -1 ) {
final long oldValue = value[ oldKey ];
value[ oldKey ] = v;
return oldValue;
}
if ( size == key.length ) {
final byte[] newKey = new byte[ size == 0 ? 2 : size * 2 ];
final long[] newValue = new long[ size == 0 ? 2 : size * 2 ];
for( int i = size; i-- != 0; ) {
newKey[ i ] = key[ i ];
newValue[ i ] = value[ i ];
}
key = newKey;
value = newValue;
}
key[ size ] = k;
value[ size ] = v;
size++;
return defRetValue;
}
@Override
@SuppressWarnings("unchecked")
public long remove( final byte k ) {
final int oldPos = findKey( k );
if ( oldPos == -1 ) return defRetValue;
final long oldValue = value[ oldPos ];
final int tail = size - oldPos - 1;
for( int i = 0; i < tail; i++ ) {
key[ oldPos + i ] = key[ oldPos + i + 1 ];
value[ oldPos + i ] = value[ oldPos + i + 1 ];
}
size--;
return oldValue;
}
@Override
@SuppressWarnings("unchecked")
public ByteSet keySet() {
return new ByteArraySet ( key, size );
}
@Override
public LongCollection values() {
return LongCollections.unmodifiable( new LongArraySet ( value, size ) );
}
/** Returns a deep copy of this map.
*
* This method performs a deep copy of this hash map; the data stored in the
* map, however, is not cloned. Note that this makes a difference only for object keys.
*
* @return a deep copy of this map.
*/
@SuppressWarnings("unchecked")
public Byte2LongArrayMap clone() {
Byte2LongArrayMap c;
try {
c = (Byte2LongArrayMap )super.clone();
}
catch(CloneNotSupportedException cantHappen) {
throw new InternalError();
}
c.key = key.clone();
c.value = value.clone();
return c;
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
s.defaultWriteObject();
for( int i = 0; i < size; i++ ) {
s.writeByte( key[ i ] );
s.writeLong( value[ i ] );
}
}
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
key = new byte[ size ];
value = new long[ size ];
for( int i = 0; i < size; i++ ) {
key[ i ] = s.readByte();
value[ i ] = s.readLong();
}
}
}