1

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
  • Your code doesn’t compile. Please post the exact code that produced that output – cpp beginner Mar 31 '18 at 23:26
  • Regardless of the output: Using an `int[]` array as a key in a `Map` will almost certainly **not** work as you imagine. For a quick, simple solution, consider using `java.awt.Point` instead of these 2-element arrays. – Marco13 Mar 31 '18 at 23:49
  • @cppbeginner I have updated the code, it should produce the same output as my actual output. –  Apr 01 '18 at 00:59
  • @Marco13 Thank you for the suggestion. Actually, these are given coordinate of a 2D plane and I have to find the distance of each coordinate with the origin and store the coordinate as key and respective distance as the value on the map. –  Apr 01 '18 at 01:04

3 Answers3

3

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)

Marco13
  • 53,703
  • 9
  • 80
  • 159
0

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());
  • This worked for me. Thank you so much. I am wondering if we can directly print the set rather than converting into the List. –  Apr 01 '18 at 01:07
  • @praveen If I help you please mark answer as correct) – Svichkarev Anatoly Apr 01 '18 at 08:34
  • 1
    @Svicharev I have already marked the answer correct, but because of less than 15 reputations, it is not publishing in your account. Again Thank you so much for the help. –  Apr 01 '18 at 16:34
0

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.

Jan Černý
  • 1,268
  • 2
  • 17
  • 31
  • Use [`Arrays#toString`](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#toString-int:A-) instead. – Marco13 Apr 01 '18 at 11:51