Java의 HashMap에서 key값으로 primitive type은 올 수 없다.

그래서 int가 key값으로 필요하다면 Integer를 대신 사용하게 된다.


그런데 여기에서 짚고 넘어가야 할 점이 하나 있다.

HashMap에서는 key의 hashCode()값을 기준으로 entry를 찾기 때문에

처음 HashMap에 entry를 넣을 때의 key의 hashCode()값과

entry를 불러 올 때의 key의 hashCode()값이 같아야 한다.

그래서 HashMap에 entry를 넣을 때의 Integer의 reference를 유지해야,

나중에 HashMap에서 entry를 불러 올 때 사용할 수 있다라고 생각하기 쉽다.



위의 경우 과연 Integer value는 null일까?

단순히 생각해 봤을때 처음 entry를 넣을 때 Integer 객체를 하나 생성했고

entry를 찾을 때 새로운 Integer 객체를 생성했기 때문에 null값이 나올 것이라고 생각할 수도 있다.

하지만 실제로 해보면 null값이 아니라 30을 값으로 지니는 Integer가 반환된다.


그렇다면 왜 그런 것일까?

이는 Java API의 Integer의 hashCode() 부분을 보면 쉽게 알 수 있다.


hashCode

public int hashCode()
Returns a hash code for this Integer.

Overrides:
hashCode in class Object
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.


즉, Integer의 hashCode()를 호출하면 Integer가 표현하고 있는 primitive int 값을 리턴한다.

Integer를 언제 어디서 얼마나 많이 생성하던지간에, Integer가 표현하는 primitive int값이 같다면 모두 같은 instance를 공유하는것이 된다.

따라서 HashMap에서 Integer를 사용할 때 쓸데없이 많은 생각을 하지 않아도 된다.



위와 같은 HashMap의 사용이 가능한 것도 모두 같은 원리로써 설명이 가능하다.

  

HashTable vs HashMap vs ConcurrentHashMap

Posted by epicdev Archive : 2012. 8. 23. 19:41

출처: http://apurvagnihotri.blogspot.kr/2010/06/hashmap-vs-hashtable.html


HashMap and HashTable both provide key-value access to data.


The Hashtable is among the original collection classes in Java.Hashtable extends the Dictionary class, which as the Javadocs state, is obsolete and has been replaced by the Map interface. HashMap is part of the new Collections Framework, added with Java 2.


The key difference between the two is that access to the Hashtable is synchronized on the table while access to the HashMap is not synchronized.This makes HashMap better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones


HashMap has a more complex hashing algorithm then Hashtable. It takes the hash value from the key and then hashes it again (double hashing). This can improve the distribution of the keys and hence the performance of the Map.


Another difference is that iterator in the HashMap is fail-safe while the enumerator for the Hashtable isn't. If we change the map while iterating, it will throw exception. 


Third difference is that HashMap permits null values in it, while Hashtable doesn't.Also note that only one NULL value is allowed as a key in HashMap. HashMap does not allow multiple keys to be NULL. Nevertheless, it can have multiple NULL values.


Using ConcurrentHashmap: for having a thread safe map we can use ConcurrenthashMap(from java5 onwards) as well instead of Hashtable which has become obsolete.


private Map myConcMap = new ConcurrentHashMap();


Now The question arises why ConcurrentHashMap and not HashTable or just have a synchronised access to HasMap.


So the major advantage of using ConcurrentHashMap is "performance" as the lock is not applied on wholeMap as is the case with a Synchronised access to hashmap or Hashtable.


As we know that hash maps store their data in a series of separate buckets, it is possible to lock only the portion of the map that is being accessed.ConcurrentHashMap uses this to provide us a highly optimized synchronised way of accessing HashMap.ConcurrentHash hash map follows following to provide a concurrent access:


1. Writing to a ConcurrentHashMap locks only a portion of the map

2. Reads can occur without locking.


Some disadvantges of ConcurrentHashMap:

ConcurrentHashMap will generally take up more memory.

it cannot take null as a key.

  

HashMap 과 Hashtable의 차이

Posted by epicdev Archive : 2011. 9. 21. 03:06
출처: http://stackoverflow.com/questions/40471/java-hashmap-vs-hashtable

 There are several differences between HashMap and Hashtable in Java:
  1. Hashtable is synchronized, whereas HashMap is not. This makes HashMap better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.
  2. Hashtable does not allow null keys or values. HashMap allows one null key and any number of null values.
  3. One of HashMap's subclasses is LinkedHashMap, so in the event that you'd want predictable iteration order (which is insertion order by default), you could easily swap out the HashMap for a LinkedHashMap. This wouldn't be as easy if you were using Hashtable.

'Archive' 카테고리의 다른 글

표준 Java 코드 스타일  (0) 2011.09.21
Static 메소드에서 Synchronized 사용하는 방법  (0) 2011.09.21
Fail-Fast란?  (0) 2011.09.21
안드로이드에서의 Multithreading 예제  (0) 2011.09.21
Java Heap에 대한 10가지 사항  (0) 2011.09.20
  

Weak reference와 Weak hashmap에 관하여

Posted by epicdev Archive : 2011. 9. 8. 00:42

Most any Java Developer will be familiar with the concepts of references, as in pass-by-reference vs. pass-by-value. (Pointers, now that’s another thing…)

When calling methods, primitive data types are passed by value, while objects and arrays are passed by reference. This means when you call a method with an object as a parameter, you are merely providing that method a way to access/manipulate the same object via a reference; no copy is made. Contrast that with primitives: When calling a method that requires them, a copy of that value is put on the call stack before invoking the method.

In that way, references are somewhat like pointers, though they obviously cannot be manipulated by pointer arithmetic. But what about weak references? What are they, and how do they contrast with strong references?

Weakly understood

Based on my experience, the concept of weak references, or more generally reachability, is not one that is well-understood in the Java world. At least I did not have a good grasp of them until stumbling upon some sample code one day. It may be that the need to utilize them is outside the confines of most day-to-day programming tasks, as the concept is fairly low-level. Nonetheless, it’s an important concept to understand.

Basically, Java specifies five levels of reachability for objects that reflect which state the object is in, in relation to being marked as finalizable, being finalized and being reclaimed. They are, in order of strongest-to-weakest:

  1. Strongly Reachable
  2. Softly Reachable
  3. Weakly Reachable
  4. Phantom Reachable
  5. Unreachable

An object’s normal state, as soon as it has been instantiated and assigned to a variable/field is strongly reachable. Chances are, these are the only types of objects you’ve worked with. We’ll first cover the concept of weakly reachableobjects, as I believe it provides a good base for understanding the remainder.

Cleaning out the trash

Going by the API reference, a weakly reachable object is one that can be reached by traversing (i.e. going through) a weak reference. That’s a succinct definition to be sure, but it just raises the next question: What is a weak reference?

Simply put, if an object can only be reached by traversing a weak reference, the garbage collector will not attempt to keep the object in memory any more than it would an object with no references to it, i.e. an object that cannot be accessed. Thus, from the garbage collector’s point-of-view, a weakly-referenced object will eventually be cleaned from memory the same as an object no references to it.

So, if weakly-referenced objects are treated the same as completely non-referenced ones, what is the purpose of the weak reference? A good example is the WeakHashMap, a class provided by Java.

WeakHashMap

Unfortunately, WeakHashMap may also be poorly understood, probably as a result of weak references not being well known. WeakHashMap may at times be described as a “cache” of sorts, where objects/entries that are not used will be removed to decrease memory usage. This is not how WeakHashMap works at all.

The best way to describe a WeakHashMap is one where the entries (key-to-value mappings) will be removed when it is no longer possible to retrieve them from the map. For example, say you’ve added an object to the WeakHashMap using a key k1. If you now set k1 to null, there should be no way to retrieve the object from the map, since you don’t have the key object around any more to call get() with. This behaviour is possible because WeakHashMap only has weak references to the keys, not strong references like the other Map classes.

Note that for the WeakHashMap to work this way, as it was intended, the key objects must only be considered equal if they are actually the same object – i.e. object identity instead of mere equality. This is the default behaviour forObject.equals() and Object.hashCode(), so if these methods have not been overridden, the object is OK to be used as a key in WeakHashMap. Objects like Integer are not suitable for use in WeakHashMap, because it is possible to create two separate (non-identical) objects that are both equal:

final Integer i1 = new Integer(4);
final Integer i2 = new Integer(4);
LOGGER.debug("i1.equals(i2): " + i1.equals(i2)); // True.
LOGGER.debug("i1 == i2: " + (i1 == i2)); // False.

Another point of importance is that String is not a suitable key for a WeakHashMap as well. In addition to its overriding of equals() andhashCode(), String objects in Java are also interned (i.e. stored) in a pool by the JVM when created. This means that they may remain strongly referenced even after you have apparently gotten rid of your reference to them. Because of this, entries that you add to a WeakHashMap using String keys may never get dropped, even after you have apparently lost reference to the keys, since the Strings may remain strongly referenced in the string intern pool.

An example of String interning:

final String s1 = "The only thing we have to fear is fear itself.";
final String s2 = "The only thing we have to fear is fear itself.";
LOGGER.debug("s1.equals(s2): " + s1.equals(s2)); // True.
LOGGER.debug("s1 == s2: " + (s1 == s2)); // May also return true!

String objects are interned for performance reasons, so when you are going to create a new String, Java first checks if there is a String in the pool that is “equal” to the one you are creating. If such a String exists, the existing object is just returned instead of having to instantiate a new object. This is possible because Strings in Java are immutable, i.e. operations that appear to modify a String (such as concatenation, toUpperCase(), etc.) really return a new String object while preserving the original.

The last usage note is that even though the keys are weakly-referenced by WeakHashMap, the values remain strongly-referenced. Thus, you must take care to not use value objects that strongly reference the keys themselves, as if this happens, the keys/entries will no longer be automatically dropped because a strong reference may always exist to the keys. (This can be avoided by wrapping the value object in a WeakReference, so that both keys and values are weakly-referenced when in the WeakHashMap)

Example use of WeakHashMap

Here is a brief, albeit contrived example of WeakHashMap at work:

// SampleKey is just an object that holds a single int. (Use instead of
// Integer, since Integer overrides equals() and hashcode())
SampleKey key = new SampleKey(42);
SampleObject value = new SampleObject("Sample Value");

final WeakHashMap<SampleKey, SampleObject> weakHashMap = new WeakHashMap<SampleKey, SampleObject>();
weakHashMap.put(key, value);

// At this point, we still have a strong reference to the key. Thus, even
// though the key is weakly-referenced by the WeakHashMap, nothing will
// be automatically removed even if we give a hint to the GC.
System.gc();

LOGGER.debug(weakHashMap.size()); // Will still be '1'.
LOGGER.debug(weakHashMap.get(key)); // Will still be 'Sample Value'.

// Now, we if set the key to null, the entry in weakHashMap will eventually
// disappear. Note that the number of times we have to 'kick' the GC
// before the entry disappears may be different on each run depending
// on the JVM load, memory usage, etc.
key = null;
int count = 0;
while(0 != weakHashMap.size())
{
  ++count;
  System.gc();
}
LOGGER.debug("Took " + count + " calls to System.gc() to result in weakHashMap size of : " + weakHashMap.size());

Finishing up

In an upcoming article, I plan on covering the other types of references (soft and phantom) as well as the associated Reference classes in Java. I wanted to keep this post brief so that it provided a basic understanding of the situation.

출처: http://unitstep.net/blog/2011/03/26/java-weak-references-and-weakhashmap/ 
  
 «이전 1  다음»