Reputation:
There is a 2d array with contains set and I want to put it on a map as key. Please, someone, suggest how to do it correctly. Expected and actual outputs are attached below.
public class trysome
{
static int[][] points = {{1,2}, {1,1},{5,7}};
public static void some()
{
HashMap<int[], Integer> map= new HashMap<int[], Integer>();
for(int i =0;i<points.length;i++)
{
map.put(points[i], 1);
}
for(Entry<int[], Integer> entry : map.entrySet())
{
System.out.println(entry.getKey() + " "+entry.getValue());
}
}
public static void main(String[] args)
{
trysome.some();
}
}
Actual Output:
[I@16b4a017 1
[I@8807e25 1
[I@2a3046da 1
Expected Output:
{1,2} 1
{1,1} 1
{5,7} 1
Upvotes: 1
Views: 1811
Reputation: 1386
This method can help you:
private static String intArrayToString(int[] inputArray) {
StringBuilder output = new StringBuilder().append('{');
for (int i = 0; i < inputArray.length - 1; i++) {
output.append(inputArray[i]);
output.append(',');
}
output.append(inputArray[inputArray.length - 1]);
return output.append('}').toString();
}
}
You can use it like this:
System.out.println(intArrayToString(entry.getKey()) + " " + entry.getValue());
Benefits of this solution are that you can customize it as you wish.
Upvotes: 0
Reputation: 54679
The reason for the output that you are observing is explained in What's the simplest way to print a Java array?. The bottom line is: The output [I@16b4a017
is basically the "memory location" of the array, and just not the contents of the array.
The reason why I'm not closing this as a duplicate is that the output here is just an irrelevant symptom of a much greater flaw: Your approach is conceptually wrong.
You cannot use an int[]
array as the key in a hash-based datastructure!
One might argue that it would work if one relied on the identity of the arrays. But that's rarely the case.
The reason for that is that the equals
and hashCode
methods are not implemented on arrays in the way that would be necessary for this to work. Omitting some technical details that can be read elsewhere.
If your code is supposed to handle 2D points in a plane, then you should use a proper class to represent these points. This class could then include proper implementations of hashCode
, equals
and toString
.
Fortunately, there already is such a class in the Java standard API, namely, java.awt.Point
.
The following shows why your original implementation would not work as expected, in the usingArraysAsKeys
method, and how it could be implemented properly in the usingPointsAsKeys
method:
import java.awt.Point;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class PointsAsKeys
{
public static void main(String[] args)
{
usingArraysAsKeys();
usingPointsAsKeys();
}
public static void usingPointsAsKeys()
{
Point points[] =
{
new Point(1, 2),
new Point(1, 1),
new Point(5, 7)
};
Map<Point, Integer> map = new HashMap<Point, Integer>();
for (int i = 0; i < points.length; i++)
{
map.put(points[i], 1);
}
for (Entry<Point, Integer> entry : map.entrySet())
{
Point p = entry.getKey();
String s = "{" + p.x + ", " + p.y + "}";
System.out.println(s + " " + entry.getValue());
}
//=====================================================================
// Important: This shows that it WILL work as expected!
Point somePoint = new Point(1, 2);
Integer value = map.get(somePoint);
System.out.println("Value for " + somePoint + " is " + value);
}
public static void usingArraysAsKeys()
{
int[][] points =
{
{ 1, 2 },
{ 1, 1 },
{ 5, 7 }
};
HashMap<int[], Integer> map = new HashMap<int[], Integer>();
for (int i = 0; i < points.length; i++)
{
map.put(points[i], 1);
}
for (Entry<int[], Integer> entry : map.entrySet())
{
// This would print the arrays as "[I@139a55"
//System.out.println(entry.getKey() + " " + entry.getValue());
// This will print the arrays as [1, 2]:
System.out.println(
Arrays.toString(entry.getKey()) + " " + entry.getValue());
}
//=====================================================================
// Important: This shows that it will NOT work as expected!
int somePoint[] = { 1, 2 };
Integer value = map.get(somePoint);
System.out.println(
"Value for " + Arrays.toString(somePoint) + " is " + value);
}
}
Another advantage of using the Point
class is that it already has several convenient methods - most importantly, a Point2D#distance
method that allows you to compute the distance of a point to another one:
// Computes the distance of the point to the point at (0,0) (i.e. the origin)
double distanceToOrigin = point.distance(new Point(0,0));
(By the way: If the map is supposed to store distances, then its value type should probably be Double
and not Integer
)
Upvotes: 3
Reputation: 739
Try this:
System.out.println(Arrays.toString(entry.getKey()) + " "+entry.getValue());
Output (for example):
[1, 2] 1
Or if you want to exact as Expected Output:
System.out.println(String.format("{%d,%d}", entry.getKey()[0], entry.getKey()[1]) +
" " + entry.getValue());
Upvotes: 0