Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Can ThreadLocal be used as Key in HashMap?
If so, how does it work and is it generally a bad idea? What should I look out for and be aware of?
You can use ThreadLocal as a HashMap key like any other object. Whether it has any meaning is a different topic.
Basically you can have problems if you use a mutable object as a key for things like HashMap, HashSet and so on, because those classes usually use hashCode() (hence the name) to put stuff in buckets and retrieve it. So if you use a mutable object as a key, then change the object (in a way the hashCode changes) and then try to retrieve the entry by key, you will not find the entry anymore as the map will look in the wrong bucket for the entry.
In the case of ThreadLocal this would not be a problem, as it does not override equals() and hashCode() and thus the hashCode() will not change if you change the object, so you could safely use the ThreadLocal as key.
As Jaroslaw Pawlak commented, since ThreadLocal doesn't implement hashCode() and equals() it is not suitable for the key in HashMap, at least if you expect it to be well behaved.
Even if it did, it would be useless. Considering the use-case of ThreadLocal, it would be far clearer to use the contained object as the key.
Having a map with one ThreadLocal (with thread specific contents) mapping just ends up with having the internal map of ThreadLocal (the one that maps the thread to the value) being used for the actual mappings.
Not to mention that ThreadLocal instances are somewhat recommended against. The common use cases they have are solved by introducing "native" threadlocal classes, such as java.util.concurrent.ThreadSafeRandom.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
That is, I get the object through the get-method. And then change the value. Thus, I do not create a copy of this object, but change the value of the original.
Example with List:
getMyListFromPojo().addAll(additionalList);
This code will change the value in the field myListFromPojo! Is this a normal practice?
Is it a bad practice to change the value of an object, bypassing the setter?
A good API won't allow you to change the value. getMyListFromPojo() would return an unmodifiable collection, no one from the outside would be able to alter the value returned.
On the other hand, a POJO class is supposed to be a very simple class. I rarely see POJO methods return something more complex (for instance, a copy or an immutable object) than a reference to a corresponding field.
It depends on what you want to achieve with your object, if you need your object to be immutable(except by using some methods provided), then you would need to show a copy of that object(or make it immutable by using methods like Collections.Immutable).
To answer your question: it's perfectly fine to modify a list returned by a method(if that is what you want).
I would instead write two methods:
one for adding a single object to the list
public void addToListFromPojo(Object object) {
this.myListFromPojo.add(object);
}
and another one for adding a list of objects to it
public void addAllToListOfPojo(List<Object> objectList) {
this.myListFromPojo.addAll(objectList);
}
That would result in more (theoretically unnecessary) code, but it would support readability and
keep the responsibility of changing the fields inside the class.
If you don't care for responsibilities of units of your code, then just use less code ==> your example
This code will change the value in the field myListFromPojo! Is this a normal practice?
It is your code, thus your decision.
If you want to allow for such things, nicely document that in JavaDoc, and ensure that the underlying List is an ArrayList for example that allows any kind of modification.
If, on the other hand, you do not want such changes to take place, then nicely document that in JavaDoc, to then ensure that your APIs do not allow for it to happen. For example by making sure that the List instance is actually some sort of ImmutableList.
And note that both ways can be legit. It is really up to the person defining the APIs here what is acceptable and what not. Of course, the first premise would be that all things in your API behave in the same way.
Beyond that, such DTOs/Beans are typically meant to only contain values, so updating them is often allowed. But of course, it can lead to problems when multiple threads come into play. From a consistency point of view, you are always better off to forbid modifications (instead: changes create new objects with new content). But sometimes the performance penalty for doing that might be considered too high.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I know the underlying difference between the remove() method of the traditional collection like hashMap and concurrent collection like concurrentHashMap. In concurrentHashmap, JVM will match the key and the value both before removing the key value object which is required for the multithreading environment.
Is there any other difference between them?
I think you are asking why is there a second remove method in the concurrent map.
Map has:
V remove(Object key)
ConcurrentMap has an additional method:
boolean remove(Object key, Object value)
(In fact, Map has this as a default method since 1.8.)
In a non-concurrent Map, the two-arg form can easily written by composing a get followed by remove, at the cost of two lookups. Concurrent operations, however, do not compose. For concurrent maps you may see remove used in a loop similar to how compareAndSet is typically used.
You could perform the remove operation in a single operation through the normal collections interfaces if you first used entrySet. It's just not very convenient or obvious.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In java,We can use Object.hashCode() to get the object's hashcode, that, in turn, can we use the hashcode to get the object? But how? Is there any existing method to solve this problem?
Hashcode do not work that way. They are meant to be a hint whether two objects are equal. From Object javadoc :
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
As different object may have same hashcode, there cannot exist a way to get an object from its hashcode. If you have such a need, do use a Map and store objects with a key. But even there a Map will have only one value per key (still from javadoc : A map cannot contain duplicate keys; each key can map to at most one value)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Suppose I need to create a multi-set data structure with operations such as intersect and union of two sets. With c# or java.
In both cases I need create a copy of every object of both sets, otherwise changing one of it could break other sets.
I see one solution: specify generic type, for example
class MultiSet<T, U> where T : struct, where U : ICloneable
or something like this in java.
Are there another ways to solve this?
In both cases I need create a copy of every object of both sets, otherwise changing one of it could break other sets
If you want an intersect of two collections of objects, you will want references to those that "match" as a result, rather than copies of them. The latter makes no sense.
To check wether two objects are the same (in set 1 and set 2), just compare them in a meaningful way (i.e. overriding their hash code and compare methods).
The structure of your result collection will also depend on wether or not the objects can be equal to each other without their reference being equal. In that case, the resulting collection will need to hold two references (two for each "match"), one for each set.
As for the union, just simply create one collection that holds references to all the objects in both collections.
Complete side note
Union and intersect are data operations, and so I assume your collections will hold data. It's not the best idea to do such operations in a programming language. There are other tools that are much more up to the task, such as SQL.
Other than the recommended ICloneable? (I say the recommended way, however cloning is usually seen as bad)
I suppose if the objects are Serializable you could serialize and de-serialise as a new object.
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, yourObject);
stream.Seek(0, SeekOrigin.Begin);
return (YourObjectType)formatter.Deserialize(stream);
}
Add a null check and it would make a nice extension method for serialisable objects.
Once again though, cloning probably is not a good solution for your problem, but I don't know enough about your use-case to recommend anything.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Are immutable objects (other than String like Integer and other wrapper classes etc.) good for hashmap keys?
Can anybody explain how?
If immutable, the object's hashcode wont change and it allows caching the hashcode of different keys which makes the overall retrieval process very fast.
Also for mutable objects ,the hashCode() might be dependent on fields that could change, if this happens you wont be able to find the key (and its value) in the HashMap since hashCode() returns different value.
You can find the answer here: How HashMap works in Java
String, Integer and other wrapper classes are natural candidates of HashMap key, and String is most frequently used key as well because String is immutable and final,and overrides equals and hashcode() method. Other wrapper class also shares similar property. Immutabiility is required, in order to prevent changes on fields used to calculate hashCode() because if key object return different hashCode during insertion and retrieval than it won't be possible to get object from HashMap. Immutability is best as it offers other advantages as well like thread-safety, If you can keep your hashCode same by only making certain fields final, then you go for that as well. Since equals() and hashCode() method is used during retrieval of value object from HashMap, its important that key object correctly override these methods and follow contact. If unequal object return different hashcode than chances of collision will be less which subsequently improve performance of HashMap.
There is also another stack for the discussion: Why are immutable objects in hashmaps so effective
Both hashcode and equals method are used in put and get method of HashMap. You need to make sure you can always get the value object from the map after you put it with the key object. No matter you change the key object or not. But Immutable object is good enough to achieve that.
yes because it is unchangeable.
Lets assume that i am having one class
MyKey key = new MyKey("shreyansh"); //assume hashCode=1234
myHashMap.put(key, "value");
// Below code will change the key hashCode() and equals()
// but it's location is not changed.
key.setName("jogi"); //assume new hashCode=7890
//below will return null, because HashMap will try to look for key
//in the same index as it was stored but since key is mutated,
//there will be no match and it will return null.
myHashMap.get(new MyKey("shreyansh"));
here while accessing that using key "Shreyansh" it will return nulll
If you object is immutable and implements hashcode/equals correctly, you are fine to use them as keys in a hashmap.