Java tutorial
/////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2001, Eric D. Friedman All Rights Reserved. // Copyright (c) 2009, Rob Eden All Rights Reserved. // Copyright (c) 2009, Jeff Randall All Rights Reserved. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /////////////////////////////////////////////////////////////////////////////// package gnu.trove.map.custom_hash; import gnu.trove.TDoubleCollection; import gnu.trove.function.TDoubleFunction; import gnu.trove.impl.Constants; import gnu.trove.impl.HashFunctions; import gnu.trove.impl.hash.TCustomObjectHash; import gnu.trove.impl.hash.THash; import gnu.trove.iterator.TDoubleIterator; import gnu.trove.iterator.TObjectDoubleIterator; import gnu.trove.iterator.hash.TObjectHashIterator; import gnu.trove.map.TObjectDoubleMap; import gnu.trove.procedure.TDoubleProcedure; import gnu.trove.procedure.TObjectDoubleProcedure; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.strategy.HashingStrategy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.*; import java.util.*; ////////////////////////////////////////////////// // THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // ////////////////////////////////////////////////// /** * An open addressed Map implementation for Object keys and double values. * * @author Rob Eden */ public class TObjectDoubleCustomHashMap<K> extends TCustomObjectHash<K> implements TObjectDoubleMap<K>, Externalizable { private static final Log logger = LogFactory.getLog(TObjectDoubleCustomHashMap.class); static final long serialVersionUID = 1L; private final TObjectDoubleProcedure<K> PUT_ALL_PROC = new TObjectDoubleProcedure<K>() { public boolean execute(K key, double value) { put(key, value); return true; } }; /** the values of the map */ protected transient double[] _values; /** the value that represents null */ protected double no_entry_value; /** FOR EXTERNALIZATION ONLY!!! */ public TObjectDoubleCustomHashMap() { } /** * Creates a new <code>TObjectDoubleHashMap</code> instance with the default * capacity and load factor. */ public TObjectDoubleCustomHashMap(HashingStrategy<K> strategy) { super(strategy); } /** * Creates a new <code>TObjectDoubleHashMap</code> instance with a prime * capacity equal to or greater than <tt>initialCapacity</tt> and * with the default load factor. * * @param initialCapacity an <code>int</code> value */ public TObjectDoubleCustomHashMap(HashingStrategy<K> strategy, int initialCapacity) { super(strategy, initialCapacity); no_entry_value = Constants.DEFAULT_DOUBLE_NO_ENTRY_VALUE; } /** * Creates a new <code>TObjectDoubleHashMap</code> instance with a prime * capacity equal to or greater than <tt>initialCapacity</tt> and * with the specified load factor. * * @param initialCapacity an <code>int</code> value * @param loadFactor a <code>float</code> value */ public TObjectDoubleCustomHashMap(HashingStrategy<K> strategy, int initialCapacity, float loadFactor) { super(strategy, initialCapacity, loadFactor); no_entry_value = Constants.DEFAULT_DOUBLE_NO_ENTRY_VALUE; } /** * Creates a new <code>TObjectDoubleHashMap</code> instance with a prime * value at or near the specified capacity and load factor. * * @param initialCapacity used to find a prime capacity for the table. * @param loadFactor used to calculate the threshold over which * rehashing takes place. * @param noEntryValue the value used to represent null. */ public TObjectDoubleCustomHashMap(HashingStrategy<K> strategy, int initialCapacity, float loadFactor, double noEntryValue) { super(strategy, initialCapacity, loadFactor); no_entry_value = noEntryValue; //noinspection RedundantCast if (no_entry_value != (double) 0) { Arrays.fill(_values, no_entry_value); } } /** * Creates a new <code>TObjectDoubleCustomHashMap</code> that contains the entries * in the map passed to it. * * @param map the <tt>TObjectDoubleMap</tt> to be copied. */ public TObjectDoubleCustomHashMap(HashingStrategy<K> strategy, TObjectDoubleMap<K> map) { this(strategy, map.size(), 0.5f, map.getNoEntryValue()); if (map instanceof TObjectDoubleCustomHashMap) { TObjectDoubleCustomHashMap hashmap = (TObjectDoubleCustomHashMap) map; this._loadFactor = hashmap._loadFactor; this.no_entry_value = hashmap.no_entry_value; this.strategy = hashmap.strategy; //noinspection RedundantCast if (this.no_entry_value != (double) 0) { Arrays.fill(_values, this.no_entry_value); } setUp((int) Math.ceil(DEFAULT_CAPACITY / _loadFactor)); } putAll(map); } /** * initializes the hashtable to a prime capacity which is at least * <tt>initialCapacity + 1</tt>. * * @param initialCapacity an <code>int</code> value * @return the actual capacity chosen */ public int setUp(int initialCapacity) { int capacity; capacity = super.setUp(initialCapacity); _values = new double[capacity]; return capacity; } /** * rehashes the map to the new capacity. * * @param newCapacity an <code>int</code> value */ protected void rehash(int newCapacity) { int oldCapacity = _set.length; //noinspection unchecked K oldKeys[] = (K[]) _set; double oldVals[] = _values; _set = new Object[newCapacity]; Arrays.fill(_set, FREE); _values = new double[newCapacity]; Arrays.fill(_values, no_entry_value); for (int i = oldCapacity; i-- > 0;) { if (oldKeys[i] != FREE && oldKeys[i] != REMOVED) { K o = oldKeys[i]; int index = insertionIndex(o); if (index < 0) { throwObjectContractViolation(_set[(-index - 1)], o); } _set[index] = o; _values[index] = oldVals[i]; } } } // Query Operations /** {@inheritDoc} */ public double getNoEntryValue() { return no_entry_value; } /** {@inheritDoc} */ public boolean containsKey(Object key) { return contains(key); } /** {@inheritDoc} */ public boolean containsValue(double val) { Object[] keys = _set; double[] vals = _values; for (int i = vals.length; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED && val == vals[i]) { return true; } } return false; } /** {@inheritDoc} */ public double get(Object key) { int index = index(key); return index < 0 ? no_entry_value : _values[index]; } // Modification Operations /** {@inheritDoc} */ public double put(K key, double value) { int index = insertionIndex(key); return doPut(key, value, index); } /** {@inheritDoc} */ public double putIfAbsent(K key, double value) { int index = insertionIndex(key); if (index < 0) return _values[-index - 1]; return doPut(key, value, index); } private double doPut(K key, double value, int index) { double previous = no_entry_value; boolean isNewMapping = true; if (index < 0) { index = -index - 1; previous = _values[index]; isNewMapping = false; } //noinspection unchecked K oldKey = (K) _set[index]; _set[index] = key; _values[index] = value; if (isNewMapping) { postInsertHook(oldKey == FREE); } return previous; } /** {@inheritDoc} */ public double remove(Object key) { double prev = no_entry_value; int index = index(key); if (index >= 0) { prev = _values[index]; removeAt(index); // clear key,state; adjust size } return prev; } /** * Removes the mapping at <tt>index</tt> from the map. * This method is used internally and public mainly because * of packaging reasons. Caveat Programmer. * * @param index an <code>int</code> value */ protected void removeAt(int index) { _values[index] = no_entry_value; super.removeAt(index); // clear key, state; adjust size } // Bulk Operations /** {@inheritDoc} */ public void putAll(Map<? extends K, ? extends Double> map) { Set<? extends Map.Entry<? extends K, ? extends Double>> set = map.entrySet(); for (Map.Entry<? extends K, ? extends Double> entry : set) { put(entry.getKey(), entry.getValue()); } } /** {@inheritDoc} */ public void putAll(TObjectDoubleMap<K> map) { map.forEachEntry(PUT_ALL_PROC); } /** {@inheritDoc} */ public void clear() { super.clear(); Arrays.fill(_set, 0, _set.length, FREE); Arrays.fill(_values, 0, _values.length, no_entry_value); } // Views /** {@inheritDoc} */ public Set<K> keySet() { return new KeyView(); } /** {@inheritDoc} */ public Object[] keys() { //noinspection unchecked K[] keys = (K[]) new Object[size()]; Object[] k = _set; for (int i = k.length, j = 0; i-- > 0;) { if (k[i] != FREE && k[i] != REMOVED) { //noinspection unchecked keys[j++] = (K) k[i]; } } return keys; } /** {@inheritDoc} */ public K[] keys(K[] a) { int size = size(); if (a.length < size) { //noinspection unchecked a = (K[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); } Object[] k = _set; for (int i = k.length, j = 0; i-- > 0;) { if (k[i] != FREE && k[i] != REMOVED) { //noinspection unchecked a[j++] = (K) k[i]; } } return a; } /** {@inheritDoc} */ public TDoubleCollection valueCollection() { return new TDoubleValueCollection(); } /** {@inheritDoc} */ public double[] values() { double[] vals = new double[size()]; double[] v = _values; Object[] keys = _set; for (int i = v.length, j = 0; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED) { vals[j++] = v[i]; } } return vals; } /** {@inheritDoc} */ public double[] values(double[] array) { int size = size(); if (array.length < size) { array = new double[size]; } double[] v = _values; Object[] keys = _set; for (int i = v.length, j = 0; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED) { array[j++] = v[i]; } } if (array.length > size) { array[size] = no_entry_value; } return array; } /** * @return an iterator over the entries in this map */ public TObjectDoubleIterator<K> iterator() { return new TObjectDoubleHashIterator<K>(this); } /** {@inheritDoc} */ @SuppressWarnings({ "RedundantCast" }) public boolean increment(K key) { //noinspection RedundantCast return adjustValue(key, (double) 1); } /** {@inheritDoc} */ public boolean adjustValue(K key, double amount) { int index = index(key); if (index < 0) { return false; } else { _values[index] += amount; return true; } } /** {@inheritDoc} */ public double adjustOrPutValue(final K key, final double adjust_amount, final double put_amount) { int index = insertionIndex(key); final boolean isNewMapping; final double newValue; if (index < 0) { index = -index - 1; newValue = (_values[index] += adjust_amount); isNewMapping = false; } else { newValue = (_values[index] = put_amount); isNewMapping = true; } //noinspection unchecked K oldKey = (K) _set[index]; _set[index] = key; if (isNewMapping) { postInsertHook(oldKey == FREE); } return newValue; } /** * Executes <tt>procedure</tt> for each key in the map. * * @param procedure a <code>TObjectProcedure</code> value * @return false if the loop over the keys terminated because * the procedure returned false for some key. */ public boolean forEachKey(TObjectProcedure<K> procedure) { return forEach(procedure); } /** * Executes <tt>procedure</tt> for each value in the map. * * @param procedure a <code>TDoubleProcedure</code> value * @return false if the loop over the values terminated because * the procedure returned false for some value. */ public boolean forEachValue(TDoubleProcedure procedure) { Object[] keys = _set; double[] values = _values; for (int i = values.length; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED && !procedure.execute(values[i])) { return false; } } return true; } /** * Executes <tt>procedure</tt> for each key/value entry in the * map. * * @param procedure a <code>TOObjectDoubleProcedure</code> value * @return false if the loop over the entries terminated because * the procedure returned false for some entry. */ @SuppressWarnings({ "unchecked" }) public boolean forEachEntry(TObjectDoubleProcedure<K> procedure) { Object[] keys = _set; double[] values = _values; for (int i = keys.length; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED && !procedure.execute((K) keys[i], values[i])) { return false; } } return true; } /** * Retains only those entries in the map for which the procedure * returns a true value. * * @param procedure determines which entries to keep * @return true if the map was modified. */ public boolean retainEntries(TObjectDoubleProcedure<K> procedure) { boolean modified = false; //noinspection unchecked K[] keys = (K[]) _set; double[] values = _values; // Temporarily disable compaction. This is a fix for bug #1738760 tempDisableAutoCompaction(); try { for (int i = keys.length; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED && !procedure.execute(keys[i], values[i])) { removeAt(i); modified = true; } } } finally { reenableAutoCompaction(true); } return modified; } /** * Transform the values in this map using <tt>function</tt>. * * @param function a <code>TDoubleFunction</code> value */ public void transformValues(TDoubleFunction function) { Object[] keys = _set; double[] values = _values; for (int i = values.length; i-- > 0;) { if (keys[i] != null && keys[i] != REMOVED) { values[i] = function.execute(values[i]); } } } // Comparison and hashing /** * Compares this map with another map for equality of their stored * entries. * * @param other an <code>Object</code> value * @return a <code>boolean</code> value */ public boolean equals(Object other) { if (!(other instanceof TObjectDoubleMap)) { return false; } TObjectDoubleMap that = (TObjectDoubleMap) other; if (that.size() != this.size()) { return false; } try { TObjectDoubleIterator iter = this.iterator(); while (iter.hasNext()) { iter.advance(); Object key = iter.key(); double value = iter.value(); if (value == no_entry_value) { if (!(that.get(key) == that.getNoEntryValue() && that.containsKey(key))) { return false; } } else { if (value != that.get(key)) { return false; } } } } catch (ClassCastException ex) { // unused. logger.warn("An error occurred!", ex); } return true; } /** {@inheritDoc} */ public int hashCode() { int hashcode = 0; Object[] keys = _set; double[] values = _values; for (int i = values.length; i-- > 0;) { if (keys[i] != FREE && keys[i] != REMOVED) { hashcode += HashFunctions.hash(values[i]) ^ (keys[i] == null ? 0 : keys[i].hashCode()); } } return hashcode; } /** a view onto the keys of the map. */ protected class KeyView extends MapBackedView<K> { @SuppressWarnings({ "unchecked" }) public Iterator<K> iterator() { return new TObjectHashIterator(TObjectDoubleCustomHashMap.this); } public boolean removeElement(K key) { return no_entry_value != TObjectDoubleCustomHashMap.this.remove(key); } public boolean containsElement(K key) { return TObjectDoubleCustomHashMap.this.contains(key); } } private abstract class MapBackedView<E> extends AbstractSet<E> implements Set<E>, Iterable<E> { public abstract boolean removeElement(E key); public abstract boolean containsElement(E key); @SuppressWarnings({ "unchecked" }) public boolean contains(Object key) { return containsElement((E) key); } @SuppressWarnings({ "unchecked" }) public boolean remove(Object o) { return removeElement((E) o); } public void clear() { TObjectDoubleCustomHashMap.this.clear(); } public boolean add(E obj) { throw new UnsupportedOperationException(); } public int size() { return TObjectDoubleCustomHashMap.this.size(); } public Object[] toArray() { Object[] result = new Object[size()]; Iterator<E> e = iterator(); for (int i = 0; e.hasNext(); i++) { result[i] = e.next(); } return result; } public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) { //noinspection unchecked a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); } Iterator<E> it = iterator(); Object[] result = a; for (int i = 0; i < size; i++) { result[i] = it.next(); } if (a.length > size) { a[size] = null; } return a; } public boolean isEmpty() { return TObjectDoubleCustomHashMap.this.isEmpty(); } public boolean addAll(Collection<? extends E> collection) { throw new UnsupportedOperationException(); } @SuppressWarnings({ "SuspiciousMethodCalls" }) public boolean retainAll(Collection<?> collection) { boolean changed = false; Iterator<E> i = iterator(); while (i.hasNext()) { if (!collection.contains(i.next())) { i.remove(); changed = true; } } return changed; } } class TDoubleValueCollection implements TDoubleCollection { /** {@inheritDoc} */ public TDoubleIterator iterator() { return new TObjectDoubleValueHashIterator(); } /** {@inheritDoc} */ public double getNoEntryValue() { return no_entry_value; } /** {@inheritDoc} */ public int size() { return _size; } /** {@inheritDoc} */ public boolean isEmpty() { return 0 == _size; } /** {@inheritDoc} */ public boolean contains(double entry) { return TObjectDoubleCustomHashMap.this.containsValue(entry); } /** {@inheritDoc} */ public double[] toArray() { return TObjectDoubleCustomHashMap.this.values(); } /** {@inheritDoc} */ public double[] toArray(double[] dest) { return TObjectDoubleCustomHashMap.this.values(dest); } public boolean add(double entry) { throw new UnsupportedOperationException(); } /** {@inheritDoc} */ public boolean remove(double entry) { double[] values = _values; Object[] set = _set; for (int i = values.length; i-- > 0;) { if ((set[i] != FREE && set[i] != REMOVED) && entry == values[i]) { removeAt(i); return true; } } return false; } /** {@inheritDoc} */ public boolean containsAll(Collection<?> collection) { for (Object element : collection) { if (element instanceof Double) { double ele = ((Double) element).doubleValue(); if (!TObjectDoubleCustomHashMap.this.containsValue(ele)) { return false; } } else { return false; } } return true; } /** {@inheritDoc} */ public boolean containsAll(TDoubleCollection collection) { TDoubleIterator iter = collection.iterator(); while (iter.hasNext()) { if (!TObjectDoubleCustomHashMap.this.containsValue(iter.next())) { return false; } } return true; } /** {@inheritDoc} */ public boolean containsAll(double[] array) { for (double element : array) { if (!TObjectDoubleCustomHashMap.this.containsValue(element)) { return false; } } return true; } /** {@inheritDoc} */ public boolean addAll(Collection<? extends Double> collection) { throw new UnsupportedOperationException(); } /** {@inheritDoc} */ public boolean addAll(TDoubleCollection collection) { throw new UnsupportedOperationException(); } /** {@inheritDoc} */ public boolean addAll(double[] array) { throw new UnsupportedOperationException(); } /** {@inheritDoc} */ @SuppressWarnings({ "SuspiciousMethodCalls" }) public boolean retainAll(Collection<?> collection) { boolean modified = false; TDoubleIterator iter = iterator(); while (iter.hasNext()) { if (!collection.contains(Double.valueOf(iter.next()))) { iter.remove(); modified = true; } } return modified; } /** {@inheritDoc} */ public boolean retainAll(TDoubleCollection collection) { if (this == collection) { return false; } boolean modified = false; TDoubleIterator iter = iterator(); while (iter.hasNext()) { if (!collection.contains(iter.next())) { iter.remove(); modified = true; } } return modified; } /** {@inheritDoc} */ public boolean retainAll(double[] array) { boolean changed = false; Arrays.sort(array); double[] values = _values; Object[] set = _set; for (int i = set.length; i-- > 0;) { if (set[i] != FREE && set[i] != REMOVED && (Arrays.binarySearch(array, values[i]) < 0)) { removeAt(i); changed = true; } } return changed; } /** {@inheritDoc} */ public boolean removeAll(Collection<?> collection) { boolean changed = false; for (Object element : collection) { if (element instanceof Double) { double c = ((Double) element).doubleValue(); if (remove(c)) { changed = true; } } } return changed; } /** {@inheritDoc} */ public boolean removeAll(TDoubleCollection collection) { if (this == collection) { clear(); return true; } boolean changed = false; TDoubleIterator iter = collection.iterator(); while (iter.hasNext()) { double element = iter.next(); if (remove(element)) { changed = true; } } return changed; } /** {@inheritDoc} */ public boolean removeAll(double[] array) { boolean changed = false; for (int i = array.length; i-- > 0;) { if (remove(array[i])) { changed = true; } } return changed; } /** {@inheritDoc} */ public void clear() { TObjectDoubleCustomHashMap.this.clear(); } /** {@inheritDoc} */ public boolean forEach(TDoubleProcedure procedure) { return TObjectDoubleCustomHashMap.this.forEachValue(procedure); } @Override public String toString() { final StringBuilder buf = new StringBuilder("{"); forEachValue(new TDoubleProcedure() { private boolean first = true; public boolean execute(double value) { if (first) { first = false; } else { buf.append(", "); } buf.append(value); return true; } }); buf.append("}"); return buf.toString(); } class TObjectDoubleValueHashIterator implements TDoubleIterator { protected THash _hash = TObjectDoubleCustomHashMap.this; /** * the number of elements this iterator believes are in the * data structure it accesses. */ protected int _expectedSize; /** the index used for iteration. */ protected int _index; /** Creates an iterator over the specified map */ TObjectDoubleValueHashIterator() { _expectedSize = _hash.size(); _index = _hash.capacity(); } /** {@inheritDoc} */ public boolean hasNext() { return nextIndex() >= 0; } /** {@inheritDoc} */ public double next() { moveToNextIndex(); return _values[_index]; } /** @{inheritDoc} */ public void remove() { if (_expectedSize != _hash.size()) { throw new ConcurrentModificationException(); } // Disable auto compaction during the remove. This is a workaround for bug 1642768. try { _hash.tempDisableAutoCompaction(); TObjectDoubleCustomHashMap.this.removeAt(_index); } finally { _hash.reenableAutoCompaction(false); } _expectedSize--; } /** * Sets the internal <tt>index</tt> so that the `next' object * can be returned. */ protected final void moveToNextIndex() { // doing the assignment && < 0 in one line shaves // 3 opcodes... if ((_index = nextIndex()) < 0) { throw new NoSuchElementException(); } } /** * Returns the index of the next value in the data structure * or a negative value if the iterator is exhausted. * * @return an <code>int</code> value * @throws java.util.ConcurrentModificationException * if the underlying * collection's size has been modified since the iterator was * created. */ protected final int nextIndex() { if (_expectedSize != _hash.size()) { throw new ConcurrentModificationException(); } Object[] set = TObjectDoubleCustomHashMap.this._set; int i = _index; while (i-- > 0 && (set[i] == TCustomObjectHash.FREE || set[i] == TCustomObjectHash.REMOVED)) { ; } return i; } } } class TObjectDoubleHashIterator<K> extends TObjectHashIterator<K> implements TObjectDoubleIterator<K> { /** the collection being iterated over */ private final TObjectDoubleCustomHashMap<K> _map; public TObjectDoubleHashIterator(TObjectDoubleCustomHashMap<K> map) { super(map); this._map = map; } /** {@inheritDoc} */ public void advance() { moveToNextIndex(); } /** {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) public K key() { return (K) _map._set[_index]; } /** {@inheritDoc} */ public double value() { return _map._values[_index]; } /** {@inheritDoc} */ public double setValue(double val) { double old = value(); _map._values[_index] = val; return old; } } // Externalization public void writeExternal(ObjectOutput out) throws IOException { // VERSION out.writeByte(0); // SUPER super.writeExternal(out); // STRATEGY out.writeObject(strategy); // NO_ENTRY_VALUE out.writeDouble(no_entry_value); // NUMBER OF ENTRIES out.writeInt(_size); // ENTRIES for (int i = _set.length; i-- > 0;) { if (_set[i] != REMOVED && _set[i] != FREE) { out.writeObject(_set[i]); out.writeDouble(_values[i]); } } } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // VERSION in.readByte(); // SUPER super.readExternal(in); // STRATEGY strategy = (HashingStrategy<K>) in.readObject(); // NO_ENTRY_VALUE no_entry_value = in.readDouble(); // NUMBER OF ENTRIES int size = in.readInt(); setUp(size); // ENTRIES while (size-- > 0) { //noinspection unchecked K key = (K) in.readObject(); double val = in.readDouble(); put(key, val); } } /** {@inheritDoc} */ public String toString() { final StringBuilder buf = new StringBuilder("{"); forEachEntry(new TObjectDoubleProcedure<K>() { private boolean first = true; public boolean execute(K key, double value) { if (first) first = false; else buf.append(","); buf.append(key).append("=").append(value); return true; } }); buf.append("}"); return buf.toString(); } }