JS: improve performance of Hashtable-based collections
This commit is contained in:
@@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
### Compiler
|
### Compiler
|
||||||
|
|
||||||
|
### JS
|
||||||
|
|
||||||
|
- Improve performance of maps and sets
|
||||||
|
|
||||||
#### Analysis & diagnostics
|
#### Analysis & diagnostics
|
||||||
|
|
||||||
- Combination of 'open' and 'override' is no longer a warning
|
- Combination of 'open' and 'override' is no longer a warning
|
||||||
|
|||||||
@@ -78,4 +78,8 @@ public final class StandardClassesTest extends SingleFileTranslationTest {
|
|||||||
public void ignore_testThrowableImpl() throws Exception {
|
public void ignore_testThrowableImpl() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMutableMapRemoveWithCollision() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+257
-271
@@ -272,241 +272,247 @@
|
|||||||
* @param {(function(Key, Key): boolean)=} equalityFunctionParam
|
* @param {(function(Key, Key): boolean)=} equalityFunctionParam
|
||||||
* @template Key, Value
|
* @template Key, Value
|
||||||
*/
|
*/
|
||||||
var Hashtable = function (hashingFunctionParam, equalityFunctionParam) {
|
function Hashtable(hashingFunctionParam, equalityFunctionParam) {
|
||||||
var that = this;
|
this.buckets = [];
|
||||||
var buckets = [];
|
this.bucketsByHash = {};
|
||||||
var bucketsByHash = {};
|
|
||||||
|
|
||||||
var hashingFunction = (typeof hashingFunctionParam == FUNCTION) ? hashingFunctionParam : hashObject;
|
this.hashingFunction = (typeof hashingFunctionParam == FUNCTION) ? hashingFunctionParam : hashObject;
|
||||||
var equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null;
|
this.equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null;
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.put_wn2jw4$ = function (key, value) {
|
Hashtable.prototype.put_wn2jw4$ = function (key, value) {
|
||||||
var hash = hashingFunction(key), bucket, bucketEntry, oldValue = null;
|
var hash = this.hashingFunction(key), bucket, bucketEntry, oldValue = null;
|
||||||
|
|
||||||
// Check if a bucket exists for the bucket key
|
// Check if a bucket exists for the bucket key
|
||||||
bucket = getBucketForHash(bucketsByHash, hash);
|
bucket = getBucketForHash(this.bucketsByHash, hash);
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
// Check this bucket to see if it already contains this key
|
// Check this bucket to see if it already contains this key
|
||||||
bucketEntry = bucket.getEntryForKey(key);
|
bucketEntry = bucket.getEntryForKey(key);
|
||||||
if (bucketEntry) {
|
if (bucketEntry) {
|
||||||
// This bucket entry is the current mapping of key to value, so replace old value and we're done.
|
// This bucket entry is the current mapping of key to value, so replace old value and we're done.
|
||||||
oldValue = bucketEntry[1];
|
oldValue = bucketEntry[1];
|
||||||
bucketEntry[1] = value;
|
bucketEntry[1] = value;
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The bucket does not contain an entry for this key, so add one
|
|
||||||
bucket.addEntry(key, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No bucket exists for the key, so create one and put our key/value mapping in
|
// The bucket does not contain an entry for this key, so add one
|
||||||
bucket = new Bucket(hash, key, value, equalityFunction);
|
bucket.addEntry(key, value);
|
||||||
buckets[buckets.length] = bucket;
|
this._size++;
|
||||||
bucketsByHash[hash] = bucket;
|
|
||||||
}
|
}
|
||||||
return oldValue;
|
}
|
||||||
};
|
else {
|
||||||
|
// No bucket exists for the key, so create one and put our key/value mapping in
|
||||||
|
bucket = new Bucket(hash, key, value, this.equalityFunction);
|
||||||
|
this.buckets[this.buckets.length] = bucket;
|
||||||
|
this.bucketsByHash[hash] = bucket;
|
||||||
|
this._size++;
|
||||||
|
}
|
||||||
|
return oldValue;
|
||||||
|
};
|
||||||
|
|
||||||
this.get_za3rmp$ = function (key) {
|
Hashtable.prototype.get_za3rmp$ = function (key) {
|
||||||
var hash = hashingFunction(key);
|
var hash = this.hashingFunction(key);
|
||||||
|
|
||||||
// Check if a bucket exists for the bucket key
|
// Check if a bucket exists for the bucket key
|
||||||
var bucket = getBucketForHash(bucketsByHash, hash);
|
var bucket = getBucketForHash(this.bucketsByHash, hash);
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
// Check this bucket to see if it contains this key
|
// Check this bucket to see if it contains this key
|
||||||
var bucketEntry = bucket.getEntryForKey(key);
|
var bucketEntry = bucket.getEntryForKey(key);
|
||||||
if (bucketEntry) {
|
if (bucketEntry) {
|
||||||
// This bucket entry is the current mapping of key to value, so return the value.
|
// This bucket entry is the current mapping of key to value, so return the value.
|
||||||
return bucketEntry[1];
|
return bucketEntry[1];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
};
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
this.containsKey_za3rmp$ = function (key) {
|
Hashtable.prototype.containsKey_za3rmp$ = function (key) {
|
||||||
var bucketKey = hashingFunction(key);
|
var bucketKey = this.hashingFunction(key);
|
||||||
|
|
||||||
// Check if a bucket exists for the bucket key
|
// Check if a bucket exists for the bucket key
|
||||||
var bucket = getBucketForHash(bucketsByHash, bucketKey);
|
var bucket = getBucketForHash(this.bucketsByHash, bucketKey);
|
||||||
|
|
||||||
return bucket ? bucket.containsKey_za3rmp$(key) : false;
|
return bucket ? bucket.containsKey_za3rmp$(key) : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.containsValue_za3rmp$ = function (value) {
|
Hashtable.prototype.containsValue_za3rmp$ = function (value) {
|
||||||
var i = buckets.length;
|
var i = this.buckets.length;
|
||||||
|
while (i--) {
|
||||||
|
if (this.buckets[i].containsValue_za3rmp$(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hashtable.prototype.clear = function () {
|
||||||
|
this.buckets.length = 0;
|
||||||
|
this.bucketsByHash = {};
|
||||||
|
this._size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hashtable.prototype.isEmpty = function () {
|
||||||
|
return !this.buckets.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hashtable.prototype._keys = function () {
|
||||||
|
var aggregated = [], i = this.buckets.length;
|
||||||
|
while (i--) {
|
||||||
|
this.buckets[i].keys(aggregated);
|
||||||
|
}
|
||||||
|
return aggregated;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hashtable.prototype._values = function () {
|
||||||
|
var aggregated = [], i = this.buckets.length;
|
||||||
|
while (i--) {
|
||||||
|
this.buckets[i].values(aggregated);
|
||||||
|
}
|
||||||
|
return aggregated;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hashtable.prototype._entries = function () {
|
||||||
|
var aggregated = [], i = this.buckets.length;
|
||||||
|
while (i--) {
|
||||||
|
this.buckets[i].getEntries(aggregated);
|
||||||
|
}
|
||||||
|
return aggregated;
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Hashtable.prototype, "values", {
|
||||||
|
get: function () {
|
||||||
|
var values = this._values();
|
||||||
|
var i = values.length;
|
||||||
|
var result = new Kotlin.ArrayList();
|
||||||
while (i--) {
|
while (i--) {
|
||||||
if (buckets[i].containsValue_za3rmp$(value)) {
|
result.add_za3rmp$(values[i]);
|
||||||
return true;
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Hashtable.prototype.remove_za3rmp$ = function (key) {
|
||||||
|
var hash = this.hashingFunction(key), bucketIndex, oldValue = null, result = null;
|
||||||
|
|
||||||
|
// Check if a bucket exists for the bucket key
|
||||||
|
var bucket = getBucketForHash(this.bucketsByHash, hash);
|
||||||
|
|
||||||
|
if (bucket) {
|
||||||
|
// Remove entry from this bucket for this key
|
||||||
|
result = bucket.removeEntryForKey(key);
|
||||||
|
if (result !== null) {
|
||||||
|
this._size--;
|
||||||
|
oldValue = result[1];
|
||||||
|
|
||||||
|
// Entry was removed, so check if bucket is empty
|
||||||
|
if (!bucket.entries.length) {
|
||||||
|
// Bucket is empty, so remove it from the bucket collections
|
||||||
|
bucketIndex = searchBuckets(this.buckets, hash);
|
||||||
|
arrayRemoveAt(this.buckets, bucketIndex);
|
||||||
|
delete this.bucketsByHash[hash];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
};
|
return oldValue;
|
||||||
|
};
|
||||||
|
|
||||||
this.clear = function () {
|
Object.defineProperty(Hashtable.prototype, "size", {
|
||||||
buckets.length = 0;
|
get: function () {
|
||||||
bucketsByHash = {};
|
return this._size;
|
||||||
};
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.isEmpty = function () {
|
Hashtable.prototype.each = function (callback) {
|
||||||
return !buckets.length;
|
var entries = this._entries(), i = entries.length, entry;
|
||||||
};
|
while (i--) {
|
||||||
|
entry = entries[i];
|
||||||
|
callback(entry[0], entry[1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var createBucketAggregator = function (bucketFuncName) {
|
Hashtable.prototype.putAll_r12sna$ = hashMapPutAll;
|
||||||
return function () {
|
|
||||||
var aggregated = [], i = buckets.length;
|
|
||||||
while (i--) {
|
|
||||||
buckets[i][bucketFuncName](aggregated);
|
|
||||||
}
|
|
||||||
return aggregated;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
this._keys = createBucketAggregator("keys");
|
Hashtable.prototype.clone = function () {
|
||||||
this._values = createBucketAggregator("values");
|
var clone = new Hashtable(this.hashingFunction, this.equalityFunction);
|
||||||
this._entries = createBucketAggregator("getEntries");
|
clone.putAll_r12sna$(this);
|
||||||
|
return clone;
|
||||||
|
};
|
||||||
|
|
||||||
Object.defineProperty(this, "values", {
|
Object.defineProperty(Hashtable.prototype, "keys", {
|
||||||
get: function () {
|
get: function () {
|
||||||
var values = this._values();
|
var res = new Kotlin.ComplexHashSet();
|
||||||
var i = values.length;
|
var keys = this._keys();
|
||||||
var result = new Kotlin.ArrayList();
|
var i = keys.length;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
result.add_za3rmp$(values[i]);
|
res.add_za3rmp$(keys[i]);
|
||||||
}
|
}
|
||||||
return result;
|
return res;
|
||||||
},
|
},
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Hashtable.prototype, "entries", {
|
||||||
|
get: function () {
|
||||||
|
var result = new Kotlin.ComplexHashSet();
|
||||||
|
var entries = this._entries();
|
||||||
|
var i = entries.length;
|
||||||
|
while (i--) {
|
||||||
|
var entry = entries[i];
|
||||||
|
result.add_za3rmp$(new Entry(entry[0], entry[1]));
|
||||||
|
}
|
||||||
|
|
||||||
this.remove_za3rmp$ = function (key) {
|
return result;
|
||||||
var hash = hashingFunction(key), bucketIndex, oldValue = null, result = null;
|
},
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
// Check if a bucket exists for the bucket key
|
Hashtable.prototype.hashCode = function() {
|
||||||
var bucket = getBucketForHash(bucketsByHash, hash);
|
var h = 0;
|
||||||
|
var entries = this._entries();
|
||||||
|
var i = entries.length;
|
||||||
|
while (i--) {
|
||||||
|
var entry = entries[i];
|
||||||
|
h += mapEntryHashCode(entry[0], entry[1]);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
};
|
||||||
|
|
||||||
if (bucket) {
|
Hashtable.prototype.equals_za3rmp$ = function(o) {
|
||||||
// Remove entry from this bucket for this key
|
if (o == null || this.size !== o.size) return false;
|
||||||
result = bucket.removeEntryForKey(key);
|
|
||||||
if (result !== null) {
|
|
||||||
oldValue = result[1];
|
|
||||||
|
|
||||||
// Entry was removed, so check if bucket is empty
|
var entries = this._entries();
|
||||||
if (!bucket.entries.length) {
|
var i = entries.length;
|
||||||
// Bucket is empty, so remove it from the bucket collections
|
while (i--) {
|
||||||
bucketIndex = searchBuckets(buckets, hash);
|
var entry = entries[i];
|
||||||
arrayRemoveAt(buckets, bucketIndex);
|
var key = entry[0];
|
||||||
delete bucketsByHash[hash];
|
var value = entry[1];
|
||||||
}
|
if (value == null) {
|
||||||
}
|
if (!(o.get_za3rmp$(key) == null && o.contains_za3rmp$(key))) return false;
|
||||||
}
|
}
|
||||||
return oldValue;
|
else {
|
||||||
};
|
if (!Kotlin.equals(value, o.get_za3rmp$(key))) return false;
|
||||||
|
|
||||||
Object.defineProperty(this, "size", {
|
|
||||||
get: function () {
|
|
||||||
var total = 0, i = buckets.length;
|
|
||||||
while (i--) {
|
|
||||||
total += buckets[i].entries.length;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
this.each = function (callback) {
|
Hashtable.prototype.toString = function() {
|
||||||
var entries = that._entries(), i = entries.length, entry;
|
var entries = this._entries();
|
||||||
while (i--) {
|
var length = entries.length;
|
||||||
entry = entries[i];
|
if (length === 0) return "{}";
|
||||||
callback(entry[0], entry[1]);
|
var builder = "{";
|
||||||
}
|
for (var i = 0;;) {
|
||||||
};
|
var entry = entries[i];
|
||||||
|
var key = entry[0];
|
||||||
/**
|
var value = entry[1];
|
||||||
* @param {Hashtable.<Key, Value>} hashtable
|
builder +=
|
||||||
*/
|
(key === this ? "(this Map)" : Kotlin.toString(key)) +
|
||||||
this.putAll_r12sna$ = hashMapPutAll;
|
"=" +
|
||||||
|
(value === this ? "(this Map)" : Kotlin.toString(value));
|
||||||
this.clone = function () {
|
if (++i >= length) return builder + "}";
|
||||||
var clone = new Hashtable(hashingFunctionParam, equalityFunctionParam);
|
builder += ", "
|
||||||
clone.putAll_r12sna$(that);
|
}
|
||||||
return clone;
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(this, "keys", {
|
|
||||||
get: function () {
|
|
||||||
var res = new Kotlin.ComplexHashSet();
|
|
||||||
var keys = this._keys();
|
|
||||||
var i = keys.length;
|
|
||||||
while (i--) {
|
|
||||||
res.add_za3rmp$(keys[i]);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, "entries", {
|
|
||||||
get: function () {
|
|
||||||
var result = new Kotlin.ComplexHashSet();
|
|
||||||
var entries = this._entries();
|
|
||||||
var i = entries.length;
|
|
||||||
while (i--) {
|
|
||||||
var entry = entries[i];
|
|
||||||
result.add_za3rmp$(new Entry(entry[0], entry[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
this.hashCode = function() {
|
|
||||||
var h = 0;
|
|
||||||
var entries = this._entries();
|
|
||||||
var i = entries.length;
|
|
||||||
while (i--) {
|
|
||||||
var entry = entries[i];
|
|
||||||
h += mapEntryHashCode(entry[0], entry[1]);
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.equals_za3rmp$ = function(o) {
|
|
||||||
if (o == null || this.size !== o.size) return false;
|
|
||||||
|
|
||||||
var entries = this._entries();
|
|
||||||
var i = entries.length;
|
|
||||||
while (i--) {
|
|
||||||
var entry = entries[i];
|
|
||||||
var key = entry[0];
|
|
||||||
var value = entry[1];
|
|
||||||
if (value == null) {
|
|
||||||
if (!(o.get_za3rmp$(key) == null && o.contains_za3rmp$(key))) return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!Kotlin.equals(value, o.get_za3rmp$(key))) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.toString = function() {
|
|
||||||
var entries = this._entries();
|
|
||||||
var length = entries.length;
|
|
||||||
if (length === 0) return "{}";
|
|
||||||
var builder = "{";
|
|
||||||
for (var i = 0;;) {
|
|
||||||
var entry = entries[i];
|
|
||||||
var key = entry[0];
|
|
||||||
var value = entry[1];
|
|
||||||
builder +=
|
|
||||||
(key === this ? "(this Map)" : Kotlin.toString(key)) +
|
|
||||||
"=" +
|
|
||||||
(value === this ? "(this Map)" : Kotlin.toString(value));
|
|
||||||
if (++i >= length) return builder + "}";
|
|
||||||
builder += ", "
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Kotlin.HashTable = Hashtable;
|
Kotlin.HashTable = Hashtable;
|
||||||
@@ -515,7 +521,7 @@
|
|||||||
|
|
||||||
lazyInitClasses.HashMap = Kotlin.createClass(
|
lazyInitClasses.HashMap = Kotlin.createClass(
|
||||||
function () {
|
function () {
|
||||||
return [Kotlin.modules['builtins'].kotlin.collections.MutableMap];
|
return [Kotlin.HashTable, Kotlin.modules['builtins'].kotlin.collections.MutableMap];
|
||||||
},
|
},
|
||||||
function () {
|
function () {
|
||||||
Kotlin.HashTable.call(this);
|
Kotlin.HashTable.call(this);
|
||||||
@@ -766,75 +772,55 @@
|
|||||||
convertKeyToKeyType: convertKeyToBoolean
|
convertKeyToKeyType: convertKeyToBoolean
|
||||||
});
|
});
|
||||||
|
|
||||||
function LinkedHashMap() {
|
|
||||||
Kotlin.ComplexHashMap.call(this);
|
|
||||||
this.orderedKeys = [];
|
|
||||||
|
|
||||||
this.super_put_wn2jw4$ = this.put_wn2jw4$;
|
|
||||||
this.put_wn2jw4$ = function(key, value) {
|
|
||||||
if (!this.containsKey_za3rmp$(key)) {
|
|
||||||
this.orderedKeys.push(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.super_put_wn2jw4$(key, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.super_remove_za3rmp$ = this.remove_za3rmp$;
|
|
||||||
this.remove_za3rmp$ = function(key) {
|
|
||||||
var i = this.orderedKeys.indexOf(key);
|
|
||||||
if (i != -1) {
|
|
||||||
this.orderedKeys.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.super_remove_za3rmp$(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.super_clear = this.clear;
|
|
||||||
this.clear = function() {
|
|
||||||
this.super_clear();
|
|
||||||
this.orderedKeys = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(this, "keys", {
|
|
||||||
get: function () {
|
|
||||||
// TODO return special Set which unsupported adding
|
|
||||||
var set = new Kotlin.LinkedHashSet();
|
|
||||||
set.map = this;
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, "entries", {
|
|
||||||
get: function () {
|
|
||||||
var result = new Kotlin.ArrayList();
|
|
||||||
|
|
||||||
for (var i = 0, c = this.orderedKeys, l = c.length; i < l; i++) {
|
|
||||||
result.add_za3rmp$(this.get_za3rmp$(c[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, "entries", {
|
|
||||||
get: function () {
|
|
||||||
var set = new Kotlin.LinkedHashSet();
|
|
||||||
|
|
||||||
for (var i = 0, c = this.orderedKeys, l = c.length; i < l; i++) {
|
|
||||||
set.add_za3rmp$(new Entry(c[i], this.get_za3rmp$(c[i])));
|
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
lazyInitClasses.LinkedHashMap = Kotlin.createClass(
|
lazyInitClasses.LinkedHashMap = Kotlin.createClass(
|
||||||
function () {
|
function () {
|
||||||
return [Kotlin.ComplexHashMap];
|
return [Kotlin.ComplexHashMap];
|
||||||
},
|
},
|
||||||
|
/** @constructs */
|
||||||
function () {
|
function () {
|
||||||
LinkedHashMap.call(this);
|
Kotlin.ComplexHashMap.call(this);
|
||||||
|
this.orderedKeys = [];
|
||||||
|
},
|
||||||
|
/** @lends {Kotlin.LinkedHashMap.prototype} */
|
||||||
|
{
|
||||||
|
put_wn2jw4$: function (key, value) {
|
||||||
|
if (!this.containsKey_za3rmp$(key)) {
|
||||||
|
this.orderedKeys.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Kotlin.ComplexHashMap.prototype.put_wn2jw4$.call(this, key, value);
|
||||||
|
},
|
||||||
|
remove_za3rmp$: function (key) {
|
||||||
|
var i = this.orderedKeys.indexOf(key);
|
||||||
|
if (i != -1) {
|
||||||
|
this.orderedKeys.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Kotlin.ComplexHashMap.prototype.remove_za3rmp$.call(this, key);
|
||||||
|
},
|
||||||
|
clear: function () {
|
||||||
|
Kotlin.ComplexHashMap.prototype.clear.call(this);
|
||||||
|
this.orderedKeys = [];
|
||||||
|
},
|
||||||
|
keys: {
|
||||||
|
get: function () {
|
||||||
|
// TODO return special Set which unsupported adding
|
||||||
|
var set = new Kotlin.LinkedHashSet();
|
||||||
|
set.map = this;
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
get: function () {
|
||||||
|
var set = new Kotlin.LinkedHashSet();
|
||||||
|
|
||||||
|
for (var i = 0, c = this.orderedKeys, l = c.length; i < l; i++) {
|
||||||
|
set.add_za3rmp$(new Entry(c[i], this.get_za3rmp$(c[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
override fun hashCode() = 23456
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val x = A()
|
||||||
|
val y = A()
|
||||||
|
|
||||||
|
val map = mutableMapOf<A, Int>()
|
||||||
|
map[x] = 1
|
||||||
|
assertEquals(1, map.size)
|
||||||
|
|
||||||
|
map.remove(y)
|
||||||
|
assertEquals(1, map.size)
|
||||||
|
|
||||||
|
map.remove(x)
|
||||||
|
assertEquals(0, map.size)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user