I iterate an HashMap with this method:
public void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue() + " " + mp.get("objectId"));
}
it.remove(); // avoids a ConcurrentModificationException
}
The result is:
Key1 = Value1 objectIDValue
Key2 = Value2 objectIDValue
objectId = objectIDValue objectIDValue
Key4 = Value4 null
Key5 = Value5 null
...
Why is mp.get("objectId") becomes null once the key is passed?
It does not look possible unless the pair is deleted by another thread. Is this method called concurrently? If so, pair might be deleted by it.remove() since insertion order and iteration order is not guaranteed to be same for HashMap.
This is most likely a concurrency problem. I would try to use a thread-safe map implementation such as ConcurrentHashMap. Also, your method removes the last entry in the iteration, which might change depending on the map implementation you choose.
Related
Is there any way to check a HashMap if it contains a certain set of keys which keys are given in an array. When I try something like the code below it returns false.
map.containsKey(arrayOf("2018-01-16"))
If I try the following code it works but I need to check for the keys and the numbers of keys that I need to search is not fixed.
map.containsKey("2018-01-16")
You can start from the keys themselves, and use the all function from the standard library:
val map = hashMapOf(...)
val keys = arrayOf("2018-01-16", "2018-01-17", "2018-01-18")
val containsAllKeys = keys.all { map.containsKey(it) }
If you do this a lot and want to have this functionality on the Map type, you can always add it as an extension:
fun <K, V> Map<K, V>.containsKeys(keys: Array<K>) = keys.all { this.containsKey(it) }
val containsAllKeys = map.containsKeys(arrayOf("2018-01-16", "2018-01-17"))
You might also want to overload the extension with another function that takes an Iterable<K> as the parameter.
Map has keys collection, which as every collection implements containsAll method, so you can use it to check whether the keys collection contains all of the keys:
map.keys.containsAll(keysArray.asList())
You could use ArrayList<T> as a key, since it's equals is different as the Array<T> one. Let's see this test:
class ExampleUnitTest {
#Test
fun arrayAsKeyTest() {
val hashMapOne = HashMap<Array<String>, Int>()
val stringKeysOne1 = arrayOf("a", "b")
hashMapOne.set(stringKeysOne1, 2)
val stringKeysOne2 = arrayOf("a", "b")
// NOT MATCH! As stringKeysOne1 == stringKeysOne2 is false
assertFalse(hashMapOne.containsKey(stringKeysOne2)) // NOT MATCH
val hashMapTwo = HashMap<ArrayList<String>, Int>()
val stringKeysTwo1 = arrayListOf("a", "b")
hashMapTwo.set(stringKeysTwo1, 2)
val stringKeysTwo2 = arrayListOf("a", "b")
// MATCH! As stringKeysTwo1 == stringKeysTwo2 is true (although stringKeysTwo1 === stringKeysTwo2 is false)
assertTrue(hashMapTwo.containsKey(stringKeysTwo2)) // MATCH
}
}
The "C# 4.0 IN A NUTSHELL" 4th edition book by the Albaharis states on page 249:
". . . calling object.ReferenceEquals guarantees normal referential equality."
So, I decided to test this out.
First I tried value types like this.
int aa1 = 5;
int aa2 = aa1;
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And just as I expected, the result was false:
object.ReferenceEquals(aa1, aa2) is: False
Life was good.
Then I tried a mutable reference type like this.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And just as I expected, the result was true
object.ReferenceEquals(sblr1, sblr2) is: True
Life was still good.
Then I figured that since it is a mutable reference type, then if I change one variable to null, then both should be null.
So I tried the following.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr1 = null;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And I expected them to both be null.
But the result I got was False:
object.ReferenceEquals(sblr1, sblr2) is: False
Now life was not so good.
I thought that if it overrode the memory location of sblr1, then it would be overriding the memory location of sblr2 also.
Then I thought that maybe they were pointing to two different nulls, so I tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr2 = null;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2);
But here, only one was pointing to a null like this.
sblr1 == aaa and sblr2 ==
Only one was null.
It was displaying the behavior I'd expect from an immutable reference type like a string object.
With a string object, I can do something like this:
string aa1 = "aaX";
string aa2 = "aaX";
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And they will both reference the same thing like this.
object.ReferenceEquals(aa1, aa2) is: True
because "aaX" only gets written to the assembly once.
But if I do this:
string aa1 = "aaX";
string aa2 = "aaX";
aa1 = null;
MessageBox.Show("After aa1 is null(" + aa1 + "), then aa2 is: " + aa2);
Then they point to different things like this:
After aa1 is null (), then aa2 is: aaX
That's because string objects are immutable. The memory location doesn't get overriden. Rather, the variable points to a different location in Heap memory where the new value exists.
Changing aa1 to null in the above example means that aa1 will point to a different location on the Heap memory.
Why then is the mutable reference type behaving just the same as the immutable reference type?
Edit 4:03PM and 4:08
I've recently tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
// sblr1 and sblr2 should now both point to the same location on the Heap that has "aaa".
System.Text.StringBuilder sblr2 = sblr1;
System.Text.StringBuilder sblr3 = new System.Text.StringBuilder();
sblr3.Append("bbb");
sblr1 = sblr3;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2 + " and sblr3 == " + sblr3);
Which gave me:
sblr1 == bbb and sblr2 == aaa and sblr3 == bbb
That's more like the result I was expecting.
I see now, thanks to the comments, that I abscent mindedly expected null to act like a memory location.
I thought that if it overrode the memory location of sblr1, then it would be overriding the memory location of sblr2 also.
This is your misunderstanding.
When you write this:
System.Text.StringBuilder sblr2 = sblr1;
You're assigning the sblr2 variable to be a reference to the same instance of StringBuilder as the one pointed to by sblr1. The two variables now point to the same reference.
You then write:
sblr1 = null;
This changes the sblr1 variable to now be a null reference. You didn't change the instance in memory at all.
This has nothing to do with whether the reference is a mutable type or not. You're changing the variables, not the instance which they are referencing.
As for your string example:
That's because string objects are immutable. The memory location doesn't get overridden
This actually is not true. The fact that you're setting one string variable to null doesn't really have anything to do with the string being immutable. That's a separate concern.
Why then is the mutable reference type behaving just the same as the immutable reference type?
The behavior you're seeing has nothing to do with mutability. It is the standard behavior for all reference types (whether immutable or mutable). Mutability is a different issue.
The main issue with mutability is this:
Suppose you have a class, like so:
class Foo
{
public int Bar { get; set; }
}
If you write this:
Foo a = new Foo();
a.Bar = 42;
Foo b = a;
b.Bar = 54;
Console.WriteLine(a.Bar); // Will print 54, since you've changed the same mutable object
With immutable types, this can't happen, since you can't change Bar - instead, if you make an immutable class:
class Baz
{
public Baz(int bar) { this.Bar = bar; }
public int Bar { get; private set; }
}
You would need to write:
Baz a = new Baz(42);
Baz b = a;
// This isn't legal now:
// b.Bar = 54;
// So you'd write:
b = new Baz(54); // Creates a new reference
Alternatively, you could make the class return a new reference on a "change" operation, ie:
class Baz
{
public Baz(int bar) { this.Bar = bar; }
public int Bar { get; private set; }
public Baz Alter(int newValue) { return new Baz(newValue); } // May copy other data from "this"
}
Then when you'd write:
Baz a = new Baz(42);
Baz b = a.Alter(54); // b is now a new instance
This is what happens with string - all of the methods return a new instance, since a string is immutable, so you can never "change" the existing copy.
This has nothing to do with mutability. The rules involved here are the same for all reference types. A non-ref non-out variable (or member, or slot in a collection) of a reference type is a reference (duh). That means it refers to some object. It does not refer to another reference, or to a location where another reference is (e.g. to a variable). When you assign to a variable (or member, or slot in a collection), you change what reference is in that place; you do not overwrite any part of any object (except, of course, the member you assign to, if it's a member).
In your code, there are two variables srbl1 and srbl2, each of which stores a reference to the same string builder object. Assigning to either changes overwrites one of those reference (e.g. with null, or with a reference to a different object).
Changing a reference is just changing what something refers to. It doesn't change the object itself.
One way to look at it is to imagine an array of integers:
int[] foo = new int[] {0, 1, 2, 3, 4, 5};
You can create two indexes that refer to items in the array:
int ix = 1;
int iy = ix;
And then foo[ix] == foo[iy].
If you then write foo[ix] = 42, then foo[ix] == foo[iy] is still true because you changed the value that the indexes referred to.
But if you change the index so that ix = 3, then ix and iy are referring to different things.
Reference types work exactly the same way.
When you write sblr1 = new StringBuilder(), you've created a new StringBuilder object instance and made sblr1 point to it. If you then write sblr2 = sblr1, you're just making sblr2 point to the same thing. And then sblr1 = null just says, "sblr1 isn't pointing to anything anymore." It doesn't actually affect the item it refers to, just as changing the index to an array doesn't affect the value of the item being indexed.
When I want a unique key for documents I'm partial to using #Unique(). I like that it's based on username and time.
Is there a way to get that from inside a Java bean?
If not, what's the best way to get a unique number in Java that would not repeat?
Thanks
This is what I use whenever I need a unique number:
String controlNumber = UUID.randomUUID().toString();
Yes you can. When you get a handle to Session call evaluate. You can evaluate any formula expressions with this method.
String ID = (String)session.evaluate("#Unique").elementAt(0);
Russell's answer is correct. But if you need a shorter unique key, you can also try this alternative:
public static String getUnique() {
String CHARLIST = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
long number=System.currentTimeMillis();
int base=CHARLIST.length();
String result="";
while (number > 0){
result = CHARLIST.charAt((int)(number%base))+result;
number = number/base;
}
return result;
}
This is basically converts the number of milliseconds from 1970 to 62-base number. You can even shorten this by getting time since 2012/12/31 or so.
What about this:
public String getUnique() {
try {
return (String) getCurrentSession().evaluate("#Unique").elementAt(0);
} catch (NotesException e) {
return "";
}
}
// retrieve handle to a Notes-Domino object in the bean class
public static Session getCurrentSession() {
FacesContext context = FacesContext.getCurrentInstance();
return (Session) context.getApplication().getVariableResolver()
.resolveVariable(context, "session");
}
It will return a familiar Unique string. Unfortunately with the signature of your server, not the current username when it runs in a browser. I the client it will work as intended.
The following is the LotusScript code I developed a long time ago as part of my .DominoFramework to reproduce the behavior of #Unique(). You should be able to convert this to Java to get a set of values similar to what you are used to.
Function unique() As String
Dim Index As Integer
Try:
On Error GoTo Catch
Randomize
Unique = ""
For Index% = 1 To 4
Unique$ = Unique$ + Chr$(CInt(Rnd(Index%)*26)+65)
Next Index%
Unique$ = Unique$ + "-"
For Index% = 6 To 11
Unique$ = Unique$ + Chr$(CInt(Rnd(Index%)*26)+65)
Next Index%
Exit Function
Catch:
Stop
DominoException.throw Me, Nothing
Exit Function
End Function
I have got a List of strings like:
String1
String1.String2
String1.String2.String3
Other1
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB
Folder1.Folder2.FolderB.FolderC
Now I would like to group this into:
String1.String2.String3
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB.FolderC
If
"String1" is in the next item "String1.String2" I will ignore the first one
and if the second item is in the third I will only take the third "String1.String2.String3"
and so on (n items). The string is structured like a node/path and could be split by a dot.
As you can see for the Folder example Folder2 has got two different Subfolder items so I would need both strings.
Do you know how to handle this with Linq? I would prefer VB.Net but C# is also ok.
Regards Athu
Dim r = input.Where(Function(e, i) i = input.Count - 1 OrElse Not input(i + 1).StartsWith(e + ".")).ToList()
Condition within Where method checks if element is last from input or is not followed by element, that contains current one.
That solution uses the fact, that input is List(Of String), so Count and input(i+1) are available on O(1) time.
LINQ isn't really the correct approach here, because you need to access more than one item at a time.
I would go with something like this:
public static IEnumerable<string> Filter(this IEnumerable<string> source)
{
string previous = null;
foreach(var current in source)
{
if(previous != null && !current.Contains(previous))
yield return previous;
previous = current;
}
yield return previous;
}
Usage:
var result = strings.Filter();
Pretty simple one. Try this:
var lst = new List<string> { /*...*/ };
var sorted =
from item in lst
where lst.Last() == item || !lst[lst.IndexOf(item) + 1].Contains(item)
select item;
the following simple line can do the trick, I'm not sure about the performance cost through
List<string> someStuff = new List<string>();
//Code to the strings here, code not added for brewity
IEnumerable<string> result = someStuff.Where(s => someStuff.Count(x => x.StartsWith(s)) == 1);
I'm creating a map like this:
def myMap = [:]
The map is basically an object for a key and an int for a value. When I iterate over the map, I decret the value, and if it's 0, I remove it. I already tried myMap.remove(), but I get a ConcurrentModificationError - which is fair enough. So I move on to using it.remove(), which is giving me weird results.
Basically, my code is this:
myMap.each {
it.value--;
if( it.value <= 0 )
it.remove();
}
Simple enough. My problem is, if I print myMap.size() before and after the remove, they're the same. If I call myMap.containsKey( key ), it gives me true, the key is still in there.
But, if I print out the map like this:
myMap.each { System.out.println( "$it.key: $it.value" ); }
I get nothing, and calling myMap.keySet() and myMap.values() return empty.
Anyone know what's going on?
This should be a bit more efficient than Tim's answer (because you only need to iterate over the map once). Unfortunately, it is also pretty verbose
def map = [2:1, 3:4]
def iterator = map.entrySet().iterator()
while (iterator.hasNext()) {
if (iterator.next().value - 1 <= 0) {
iterator.remove()
}
}
// test that it worked
assert map == [3:4]
Can you do something like this:
myMap = myMap.each { it.value-- }.findAll { it.value > 0 }
That will subtract one from every value, then return you a new map of only those entries where the value is greater than zero.
You shouldn't call the remove method on a Map Entry, it is supposed to be a private method used internally by the Map (see line 325 for the Java 7 implementation), so you calling it yourself is getting the enclosing Map into all sorts of bother (it doesn't know that it is losing entries)
Groovy lets you call private methods, so you can do this sort of trickery behind the back of the Java classes
Edit -- Iterator method
Another way would be:
myMap.iterator().with { iterator ->
iterator.each { entry ->
entry.value--
if( entry.value <= 0 ) iterator.remove()
}
}