Java Puzzler on Arrays

  • submit to reddit

Today, while working with arrays I came accross a Java puzzle which made me wonder WHY IS THIS PIECE OF CODE NOT WORKING?

Java Puzzle

Can you guess whether this Junit test case will pass?

@Test
public void testMapOfArray() {

Map<String[], String[]> map = new HashMap<String[], String[]>();
map.put(new String[] { "shekhar" },
new String[] { "I am Java Developer" });
map.put(new String[] { "rahul" }, new String[] { "I am C# Developer" });

String[] description = map.get(new String[] { "shekhar" });
assertThat(description[0], IsEqual.equalTo("I am Java Developer"));
}


Everytime I ran this test it failed with NullPointerException.

What's the reason for this unexpected behavior?

The problem is that String[] uses object identity for equals and hashcode methodsz. So,

String[] arr1 = new String[] { "shekhar" };
String[] arr2 = new String[] { "shekhar" };

 will not match with eachother in a HashMap. 

Advice
Don't use arrays as HashMap keys. If you want to use an array as a key, then write a wrapper arround an array and override equals and the hashcode method.

 

 

2.5
Your rating: None Average: 2.5 (4 votes)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Eric Jablow replied on Fri, 2010/08/06 - 4:41pm

More to the point, never use mutable objects as keys of HashMaps or elements of HashSets. Arrays are always mutable. Sadly, so are Dates. As a horrible example, take a typical Name JavaBean class with givenName and surName members and the obvious getters, setters, and equals, and hashCode methods.
HashMap<Name, Integer> ages = new HashMap<Name, Integer>();
Name me = new Name("Eric", "Jablow");
ageMap.put(me, 48);
me.setGivenName("Ricky");
System.out.println(ages.get(me)); // Probably prints null.
Why? Because it will look in the wrong hash bucket.

Marco Rietveld replied on Fri, 2010/08/06 - 4:45pm

First there was a String constant pool.. and then a Long, and an Integer and probably even a Double constant pool, et cetera. 

But there has never been an "array" constant pool because 1. Array's can't be autoboxed and 2.  Even if you could, why would you autobox a collection? It's the content of the collection that counts! 

 

Chad Retz replied on Fri, 2010/08/06 - 5:35pm

Um...I think it's pretty commonly known that

new String[] { "bob" }.hashCode() != new String[] { "bob" }.hashCode()

Just use eclipse's auto-generated hashCode and equals on a POJO containing your array and it will be fine (Arrays.hashCode, Arrays.equals, etc). Or just use a List or Set as your key which guarantee the equals and hashCode on common elements

Thomas J. Clancy replied on Sat, 2010/08/07 - 12:17pm

Who would do this anyway?

Cosmin Mutu replied on Mon, 2010/08/09 - 12:48am

who said SCJP exams are worthless? :)

Pradeep Arumalla replied on Mon, 2010/08/09 - 10:22am


     Try the below code,when ever you do a "new Somthing()", is a new object 

 

Map<String[], String[]> map = new HashMap<String[], String[]>();
      
      String[] key=new String[] { "shekhar" };
      map.put(key,
              new String[] { "I am Java Developer" });
      map.put(new String[] { "rahul" }, new String[] { "I am C# Developer" });

      String[] description = map.get(key);
      //assertThat(description[0], "I am Java Developer".equals("I am Java Developer"));
    
      System.out.println(description[0].toString());

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.