replace removeAll/retainAll implementation with one a removeIf based
The algorithms for removeAll, retainAll and removeIf were almost identical. The main difference was, that removeIf calls a lambda, whereas removeAll and retainAll executed the check directly. Both methods call indexOf on an IntList, which easily outweighs the extra cost of the lambda. It makes sense to consolidate and remove the duplicated code. I ran a few benchmarks with different list sizes before the replacement. The results are not as clear as I would have liked. In some cases, especially for short lists, the special implementations of removeAll/retainAll were up to 10% faster. In other situations I saw 50% difference the one day, but could not reproduce those results a day later. This leads me to believe, that my test setup is not trustworthy. That means I stay with what I now. The code is identical with one tiny difference. And that difference shouldn't matter, because indexOf is much more expensive.
This commit is contained in:
@@ -342,6 +342,11 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* <p>
|
||||
* This method does not release any memory. Call {@link #trim()} to free unused
|
||||
* memory.
|
||||
* <p>
|
||||
* If {@code retain} is sorted, then the algorithm has a complexity of
|
||||
* O(n*log(m)), where n is the length of {@code this} and m the length of
|
||||
* {@code retain}. If {@code retain} is not sorted, then the complexity is
|
||||
* O(n*m).
|
||||
*
|
||||
* @param remove
|
||||
* the elements to remove
|
||||
@@ -350,19 +355,7 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* @see #trim()
|
||||
*/
|
||||
public void removeAll(final IntList remove) {
|
||||
|
||||
int insertPosition = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int current = data[i];
|
||||
if (remove.indexOf(current) < 0) {
|
||||
// keep current element
|
||||
data[insertPosition] = current;
|
||||
insertPosition++;
|
||||
}
|
||||
}
|
||||
size = insertPosition;
|
||||
|
||||
sorted = size() <= 1 ? true : sorted; // lists of size 1 or smaller are always sorted
|
||||
removeIf((val, index) -> remove.indexOf(val) >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,8 +396,10 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* For a method that computes the intersection of two lists and also removes
|
||||
* duplicate values, see {@link #intersection(IntList, IntList)}.
|
||||
* <p>
|
||||
* The algorithm has a complexity of O(n*log(m)), where n is the length of
|
||||
* {@code this} and m the length of {@code retain}.
|
||||
* If {@code retain} is sorted, then the algorithm has a complexity of
|
||||
* O(n*log(m)), where n is the length of {@code this} and m the length of
|
||||
* {@code retain}. If {@code retain} is not sorted, then the complexity is
|
||||
* O(n*m).
|
||||
*
|
||||
* @param retain
|
||||
* the elements to retain
|
||||
@@ -414,17 +409,7 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* @see #intersection(IntList, IntList)
|
||||
*/
|
||||
public void retainAll(final IntList retain) {
|
||||
|
||||
int insertPosition = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int current = data[i];
|
||||
if (retain.indexOf(current) >= 0) {
|
||||
// keep current element
|
||||
data[insertPosition] = current;
|
||||
insertPosition++;
|
||||
}
|
||||
}
|
||||
size = insertPosition;
|
||||
removeIf((val, index) -> retain.indexOf(val) < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user