removed overhead of Entry object allocation during OpenIntToDoubleHashMap iteration
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@726490 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
11d8f0ec5f
commit
da40b8373a
|
@ -104,10 +104,10 @@ public class SparseRealMatrix extends AbstractRealMatrix {
|
|||
|
||||
final RealMatrix out = new SparseRealMatrix(this);
|
||||
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
||||
final OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
||||
final int row = entry.key() / columnDimension;
|
||||
final int col = entry.key() - row * columnDimension;
|
||||
out.setEntry(row, col, getEntry(row, col) + entry.value());
|
||||
iterator.advance();
|
||||
final int row = iterator.key() / columnDimension;
|
||||
final int col = iterator.key() - row * columnDimension;
|
||||
out.setEntry(row, col, getEntry(row, col) + iterator.value());
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -138,10 +138,10 @@ public class SparseRealMatrix extends AbstractRealMatrix {
|
|||
|
||||
final RealMatrix out = new SparseRealMatrix(this);
|
||||
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
||||
final OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
||||
final int row = entry.key() / columnDimension;
|
||||
final int col = entry.key() - row * columnDimension;
|
||||
out.setEntry(row, col, getEntry(row, col) - entry.value());
|
||||
iterator.advance();
|
||||
final int row = iterator.key() / columnDimension;
|
||||
final int col = iterator.key() - row * columnDimension;
|
||||
out.setEntry(row, col, getEntry(row, col) - iterator.value());
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
|
@ -456,16 +456,28 @@ public class OpenIntToDoubleHashMap implements Serializable {
|
|||
/** Reference modification count. */
|
||||
final int referenceCount;
|
||||
|
||||
/** Index of curent element. */
|
||||
private int current;
|
||||
|
||||
/** Index of next element. */
|
||||
private int index;
|
||||
private int next;
|
||||
|
||||
/**
|
||||
* Simple constructor.
|
||||
*/
|
||||
private Iterator() {
|
||||
|
||||
// preserve the modification count of the map to detect concurrent modifications later
|
||||
referenceCount = count;
|
||||
index = -1;
|
||||
goToNext();
|
||||
|
||||
// initialize current index
|
||||
next = -1;
|
||||
try {
|
||||
advance();
|
||||
} catch (NoSuchElementException nsee) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -473,81 +485,73 @@ public class OpenIntToDoubleHashMap implements Serializable {
|
|||
* @return true if there is a next element
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return index >= 0;
|
||||
return next >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next entry.
|
||||
* @return next entry
|
||||
* Get the key of current entry.
|
||||
* @return key of current entry
|
||||
* @exception ConcurrentModificationException if the map is modified during iteration
|
||||
* @exception NoSuchElementException if there is no element left in the map
|
||||
*/
|
||||
public Entry next()
|
||||
public int key()
|
||||
throws ConcurrentModificationException, NoSuchElementException {
|
||||
if (referenceCount != count) {
|
||||
throw MathRuntimeException.createConcurrentModificationException("map has been modified while iterating",
|
||||
null);
|
||||
}
|
||||
if (index < 0) {
|
||||
if (current < 0) {
|
||||
throw MathRuntimeException.createNoSuchElementException("iterator exhausted", null);
|
||||
}
|
||||
final Entry entry = new Entry(keys[index], values[index]);
|
||||
goToNext();
|
||||
return entry;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find next index.
|
||||
* Get the value of current entry.
|
||||
* @return value of current entry
|
||||
* @exception ConcurrentModificationException if the map is modified during iteration
|
||||
* @exception NoSuchElementException if there is no element left in the map
|
||||
*/
|
||||
private void goToNext() {
|
||||
public double value()
|
||||
throws ConcurrentModificationException, NoSuchElementException {
|
||||
if (referenceCount != count) {
|
||||
throw MathRuntimeException.createConcurrentModificationException("map has been modified while iterating",
|
||||
null);
|
||||
}
|
||||
if (current < 0) {
|
||||
throw MathRuntimeException.createNoSuchElementException("iterator exhausted", null);
|
||||
}
|
||||
return values[current];
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance iterator one step further.
|
||||
* @exception ConcurrentModificationException if the map is modified during iteration
|
||||
* @exception NoSuchElementException if there is no element left in the map
|
||||
*/
|
||||
public void advance()
|
||||
throws ConcurrentModificationException, NoSuchElementException {
|
||||
|
||||
if (referenceCount != count) {
|
||||
throw MathRuntimeException.createConcurrentModificationException("map has been modified while iterating",
|
||||
null);
|
||||
}
|
||||
|
||||
// advance on step
|
||||
current = next;
|
||||
|
||||
// prepare next step
|
||||
try {
|
||||
while (states[++index] != FULL) {
|
||||
while (states[++next] != FULL) {
|
||||
// nothing to do
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
index = -1;
|
||||
next = -2;
|
||||
if (current < 0) {
|
||||
throw MathRuntimeException.createNoSuchElementException("iterator exhausted", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Entry class for the map.
|
||||
* <p>Entry elements are built on the fly only during iteration,
|
||||
* copying values. So changes in the map are <strong>not</strong>
|
||||
* reflected on already built entries.</p>
|
||||
*/
|
||||
public static class Entry {
|
||||
|
||||
/** Key. */
|
||||
private final int key;
|
||||
|
||||
/** Value. */
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Simple constructor.
|
||||
* @param key entry key
|
||||
* @param value entry value
|
||||
*/
|
||||
private Entry(final int key, final double value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key.
|
||||
* @return entry key
|
||||
*/
|
||||
public int key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value.
|
||||
* @return entry value
|
||||
*/
|
||||
public double value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -228,15 +228,17 @@ public class OpenIntToDoubleHashMapTest extends TestCase {
|
|||
OpenIntToDoubleHashMap.Iterator iterator = map.iterator();
|
||||
for (int i = 0; i < map.size(); ++i) {
|
||||
assertTrue(iterator.hasNext());
|
||||
OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
||||
int key = entry.key();
|
||||
iterator.advance();
|
||||
int key = iterator.key();
|
||||
assertTrue(map.containsKey(key));
|
||||
assertEquals(javaMap.get(key), map.get(key), 0);
|
||||
assertEquals(javaMap.get(key), iterator.value(), 0);
|
||||
assertTrue(javaMap.containsKey(key));
|
||||
}
|
||||
assertFalse(iterator.hasNext());
|
||||
try {
|
||||
iterator.next();
|
||||
iterator.advance();
|
||||
fail("an exception should have been thrown");
|
||||
} catch (NoSuchElementException nsee) {
|
||||
// expected
|
||||
}
|
||||
|
@ -247,7 +249,8 @@ public class OpenIntToDoubleHashMapTest extends TestCase {
|
|||
OpenIntToDoubleHashMap.Iterator iterator = map.iterator();
|
||||
map.put(3, 3);
|
||||
try {
|
||||
iterator.next();
|
||||
iterator.advance();
|
||||
fail("an exception should have been thrown");
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
// expected
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue