I have following Groovy script:
mymap = ['key': 'value']
println mymap
v = mymap.get('notexistkey', 'default')
println v
println mymap
When I run it I get following console output:
[key:value]
default
[key:value, notexistkey:default]
I'm surprised that after calling mymap.get('notexistkey', 'default') where second parameter is a default value returned when given key does not exist, the key notexistkey is added to the map I've called the method on. Why? Is that expected behaviour? How can I prevent this mutation?
Use Java's Map.getOrDefault(key, value) instead:
mymap = ['key': 'value']
println mymap
v = mymap.getOrDefault('notexistingkey', 'default')
println v
println mymap
Output:
[key:value]
default
[key:value]
Groovy SDK adds Map.get(key, default) via DefaultGroovyMethods.get(map, key, default) and if you take a look what Javadoc says you will understand that this behaviour is expected:
Looks up an item in a Map for the given key and returns the value - unless there is no entry for the given key in which case add the default value to the map and return that.
And this is what implementation of this method looks like:
/**
* Looks up an item in a Map for the given key and returns the value - unless
* there is no entry for the given key in which case add the default value
* to the map and return that.
* <pre class="groovyTestCase">def map=[:]
* map.get("a", []) << 5
* assert map == [a:[5]]</pre>
*
* #param map a Map
* #param key the key to lookup the value of
* #param defaultValue the value to return and add to the map for this key if
* there is no entry for the given key
* #return the value of the given key or the default value, added to the map if the
* key did not exist
* #since 1.0
*/
public static <K, V> V get(Map<K, V> map, K key, V defaultValue) {
if (!map.containsKey(key)) {
map.put(key, defaultValue);
}
return map.get(key);
}
it's pretty old concept (since Groovy 1.0). However I would recommend not using it - this .get(key, default) operation is neither atomic, nor synchronized. And problems start when you use it on ConcurrentMap which is designed for concurrent access - this method breaks its contract, because there is no synchronization between containsKey, put and final get call.
Related
I've read the documentation of Hazelcast Jet.
I've seen it is possible to add/update entries in an IMap sink.
But I've seen nowhere how it is possible to remove entries from the IMap.
Is there a way for this ?
See Sinks.mapWithMerging, from JavaDoc :
/**
* Returns a sink that uses the supplied functions to extract the key
* and value with which to update a Hazelcast {#code IMap}. If the map
* already contains the key, it applies the given {#code mergeFn} to
* resolve the existing and the proposed value into the value to use. If
* the value comes out as {#code null}, it removes the key from the map.
* Expressed as code, the sink performs the equivalent of the following for
* each item:
* <pre>
* K key = toKeyFn.apply(item);
* V oldValue = map.get(key);
* V newValue = toValueFn.apply(item);
* V resolved = (oldValue == null)
* ? newValue
: mergeFn.apply(oldValue, newValue);
* if (value == null)
* map.remove(key);
* else
* map.put(key, value);
* </pre>
...
I am new to Kotlin and tried to google it, but I don't get it.
Example here:
https://try.kotlinlang.org/#/UserProjects/q4c23aofcl7lb155oc307cnc5i/sgjm2olo277atiubhu2nn0ikb8
Code:
fun main(args: Array<String>) {
val foo = mutableMapOf('A' to 0, 'C' to 0, 'G' to 0, 'T' to 0)
foo['A'] = foo['A'] + 1
println("$foo['A']")
}
I don't get it; why does the indexing operator return the nullable type? The map in the example is defined as Map<Char, Int>, not Map<Char, Int?>.
I can override it via non-null assertion, so this works:
foo['A'] = foo['A']!!.plus(1)
Is there a cleaner way?
You can use the index operator with arbitrary chars, even those that are not part of the map, as in not an existing key. There are two obvious solutions to this, either throw an exception or return null. As you can see in the documentation, the standard library returns null in the operator fun get, which the index operator translates to:
/**
* Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.
*/
public operator fun get(key: K): V?
The alternative is getValue which is described like this:
Returns the value for the given [key] or throws an exception if there is no such key in the map.
Used like this: val v: Int = foo.getValue('A')
I am writing closure externs for WebAssembly.
For function WebAssembly.instantiate, it has 2 function signatures.
Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}>
instantiate(BufferSource bytes [, importObject])
Promise<WebAssembly.Instance> instantiate(moduleObject [, importObject])
How to declare both rules in closure externs?
Reference:
https://github.com/WebAssembly/design/blob/master/JS.md#webassemblyinstantiate
You can specify that argument and result are union of two different types. See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler about how to specify types.
Here is a simple example of such a function:
/**
* #param {string|number} value
* #return {string|number}
*/
ambiguous = function(value) {
if (typeof value == 'string') {
return value+' is string';
} else if (typeof value == 'number') {
return value+1;
} else throw new Error();
};
For your WebAssembly.instantiate function you will of course have more complex types than string and number. I don't know how you would specify the Promise types, I don't recognize the syntax shown for those, and I doubt closure compiler will parse that as-is. The extern then looks something like this (with bogus types for the Promises).
/**
#param (!BufferSource|!WebAssembly.Module) arg1 either a BufferSource or a module
#param Object= importObject optional object to import
#return (!PromiseType1|!PromiseType2)
*/
WebAssembly.instantiate = function(arg1, importObject) {};
The ! symbol is used to indicate a non-null object. If these can be null then leave that out. The = symbol after Object= means it can be undefined.
When using the results of this function you will need to test what type of thing you got using instanceof or some other method. Otherwise the compiler only knows the result is one of the two possible types. If not using instanceof, you can use type casting to tell the compiler that you know what the type is, see end of that page referenced above.
An example of a function from closure-library that has a union type in both its argument and its result is goog.array.find. The source for goog.array.find is available. Note that the angle brackets <> are used for the template type feature of the compiler.
HashMap objHashMap = new HashMap();
objHashMap.put("key1", "Value1");
objHashMap.put("key1", "Value2");
System.out.println(objHashMap.get("key1"));
Above code displaying "Value2" how and why
check this
/**
* Associates the specified value with the specified key in this map. If the
* map previously contained a mapping for the key, the old value is
* replaced.
*
* #param key
* key with which the specified value is to be associated
* #param value
* value to be associated with the specified key
* #return the previous value associated with <tt>key</tt>, or <tt>null</tt>
* if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
* can also indicate that the map previously associated
* <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K , V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
Lets note down the steps one by one:
1) First of all, key object is checked for null. If key is null, value is stored in table[0] position. Because hash code for null is always 0.
2) Then on next step, a hash value is calculated using key’s hash code by calling its hashCode() method. This hash value is used to calculate index in array for storing Entry object. JDK designers well assumed that there might be some poorly written hashCode() functions that can return very high or low hash code value. To solve this issue, they introduced another hash() function, and passed the object’s hash code to this hash() function to bring hash value in range of array index size.
3) Now indexFor(hash, table.length) function is called to calculate exact index position for storing the Entry object.
4) Here comes the main part. Now, as we know that two unequal objects can have same hash code value, how two different objects will be stored in same array location [called bucket].
Answer is LinkedList. If you remember, Entry class had an attribute “next”. This attribute always points to next object in chain. This is exactly the behavior of LinkedList.
So, in case of collision, Entry objects are stored in LinkedList form. When an Entry object needs to be stored in particular index, HashMap checks whether there is already an entry?? If there is no entry already present, Entry object is stored in this location.
If there is already an object sitting on calculated index, its next attribute is checked. If it is null, and current Entry object becomes next node in LinkedList. If next variable is not null, procedure is followed until next is evaluated as null.
What if we add the another value object with same key as entered before. Logically, it should replace the old value. How it is done? Well, after determining the index position of Entry object, while iterating over LinkedList on calculated index, HashMap calls equals method on key object for each Entry object. All these Entry objects in LinkedList will have similar hash code but equals() method will test for true equality. If key.equals(k) will be true then both keys are treated as same key object. This will cause the replacing of value object inside Entry object only.
In this way, HashMap ensure the uniqueness of keys.
Because Hash maps store only unique keys for each value, this means that you can't put 2 keys with the same name in it, when you do you will overwrite the value for that key, so if you want to store 2 different values you need to store two different keys in it.
HashMap objHashMap = new HashMap();
objHashMap.put("key1", "Value1");
objHashMap.put("key2", "Value2"); //CHANGED THIS KEY to "key2"
System.out.println(objHashMap.get("key1"));
Both of the reflect.Type interface and reflect.Value type implement the same Kind() method signature, suppose that we have some value object v := reflect.ValueOf(x)
Is v.Kind() just call v.Type().Kind() ?
They contain the same value, but do not seem to refer to the same thing:
type.go source
value.go source
A Type is usually implemented by unexported struct rtype (via TypeOf), while the Value contains a *rtype and extends flag, which is itself a reduced form of the Kind:
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagRO: obtained via unexported field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
// The next five bits give the Kind of the value.
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
// If typ.size > ptrSize, code can assume that flagIndir is set.
When getting the ValueOf something:
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value {
[...]
// For an interface value with the noAddr bit set,
// the representation is identical to an empty interface.
eface := *(*emptyInterface)(unsafe.Pointer(&i))
typ := eface.typ
/** Flag is built from the type, then kept separate (my comment) */
fl := flag(typ.Kind()) << flagKindShift
if typ.size > ptrSize {
fl |= flagIndir
}
return Value{typ, unsafe.Pointer(eface.word), fl}
}
And so when you get the kind of a Value (remember it extends its flag):
func (v Value) Kind() Kind {
return v.kind()
}
func (f flag) kind() Kind {
return Kind((f >> flagKindShift) & flagKindMask)
}
While getting the kind of a type: (Type is an interface, usually implemented by *rtype)
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
So although they seem to be equal in most of the cases, v.Kind() is not v.Type().Kind()
The file reflect/value.go states that the relevant field in the implementation of reflect.Value "repeats typ.Kind() except for method values". So, unless the value is a method, value.Kind() and value.Type().Kind() return the same number.