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);
|
final RealMatrix out = new SparseRealMatrix(this);
|
||||||
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
||||||
final OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
iterator.advance();
|
||||||
final int row = entry.key() / columnDimension;
|
final int row = iterator.key() / columnDimension;
|
||||||
final int col = entry.key() - row * columnDimension;
|
final int col = iterator.key() - row * columnDimension;
|
||||||
out.setEntry(row, col, getEntry(row, col) + entry.value());
|
out.setEntry(row, col, getEntry(row, col) + iterator.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -138,10 +138,10 @@ public class SparseRealMatrix extends AbstractRealMatrix {
|
||||||
|
|
||||||
final RealMatrix out = new SparseRealMatrix(this);
|
final RealMatrix out = new SparseRealMatrix(this);
|
||||||
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
|
||||||
final OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
iterator.advance();
|
||||||
final int row = entry.key() / columnDimension;
|
final int row = iterator.key() / columnDimension;
|
||||||
final int col = entry.key() - row * columnDimension;
|
final int col = iterator.key() - row * columnDimension;
|
||||||
out.setEntry(row, col, getEntry(row, col) - entry.value());
|
out.setEntry(row, col, getEntry(row, col) - iterator.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -456,16 +456,28 @@ public class OpenIntToDoubleHashMap implements Serializable {
|
||||||
/** Reference modification count. */
|
/** Reference modification count. */
|
||||||
final int referenceCount;
|
final int referenceCount;
|
||||||
|
|
||||||
|
/** Index of curent element. */
|
||||||
|
private int current;
|
||||||
|
|
||||||
/** Index of next element. */
|
/** Index of next element. */
|
||||||
private int index;
|
private int next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple constructor.
|
* Simple constructor.
|
||||||
*/
|
*/
|
||||||
private Iterator() {
|
private Iterator() {
|
||||||
|
|
||||||
|
// preserve the modification count of the map to detect concurrent modifications later
|
||||||
referenceCount = count;
|
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
|
* @return true if there is a next element
|
||||||
*/
|
*/
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return index >= 0;
|
return next >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next entry.
|
* Get the key of current entry.
|
||||||
* @return next entry
|
* @return key of current entry
|
||||||
* @exception ConcurrentModificationException if the map is modified during iteration
|
* @exception ConcurrentModificationException if the map is modified during iteration
|
||||||
* @exception NoSuchElementException if there is no element left in the map
|
* @exception NoSuchElementException if there is no element left in the map
|
||||||
*/
|
*/
|
||||||
public Entry next()
|
public int key()
|
||||||
throws ConcurrentModificationException, NoSuchElementException {
|
throws ConcurrentModificationException, NoSuchElementException {
|
||||||
if (referenceCount != count) {
|
if (referenceCount != count) {
|
||||||
throw MathRuntimeException.createConcurrentModificationException("map has been modified while iterating",
|
throw MathRuntimeException.createConcurrentModificationException("map has been modified while iterating",
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
if (index < 0) {
|
if (current < 0) {
|
||||||
throw MathRuntimeException.createNoSuchElementException("iterator exhausted", null);
|
throw MathRuntimeException.createNoSuchElementException("iterator exhausted", null);
|
||||||
}
|
}
|
||||||
final Entry entry = new Entry(keys[index], values[index]);
|
return keys[current];
|
||||||
goToNext();
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {
|
try {
|
||||||
while (states[++index] != FULL) {
|
while (states[++next] != FULL) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
} 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();
|
OpenIntToDoubleHashMap.Iterator iterator = map.iterator();
|
||||||
for (int i = 0; i < map.size(); ++i) {
|
for (int i = 0; i < map.size(); ++i) {
|
||||||
assertTrue(iterator.hasNext());
|
assertTrue(iterator.hasNext());
|
||||||
OpenIntToDoubleHashMap.Entry entry = iterator.next();
|
iterator.advance();
|
||||||
int key = entry.key();
|
int key = iterator.key();
|
||||||
assertTrue(map.containsKey(key));
|
assertTrue(map.containsKey(key));
|
||||||
assertEquals(javaMap.get(key), map.get(key), 0);
|
assertEquals(javaMap.get(key), map.get(key), 0);
|
||||||
|
assertEquals(javaMap.get(key), iterator.value(), 0);
|
||||||
assertTrue(javaMap.containsKey(key));
|
assertTrue(javaMap.containsKey(key));
|
||||||
}
|
}
|
||||||
assertFalse(iterator.hasNext());
|
assertFalse(iterator.hasNext());
|
||||||
try {
|
try {
|
||||||
iterator.next();
|
iterator.advance();
|
||||||
|
fail("an exception should have been thrown");
|
||||||
} catch (NoSuchElementException nsee) {
|
} catch (NoSuchElementException nsee) {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
|
@ -247,7 +249,8 @@ public class OpenIntToDoubleHashMapTest extends TestCase {
|
||||||
OpenIntToDoubleHashMap.Iterator iterator = map.iterator();
|
OpenIntToDoubleHashMap.Iterator iterator = map.iterator();
|
||||||
map.put(3, 3);
|
map.put(3, 3);
|
||||||
try {
|
try {
|
||||||
iterator.next();
|
iterator.advance();
|
||||||
|
fail("an exception should have been thrown");
|
||||||
} catch (ConcurrentModificationException cme) {
|
} catch (ConcurrentModificationException cme) {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue