4

I have a Map<String, Object> in which I store "test" and ArrayList<Integer>. I then try to display the whole array testMap.get("test") which works fine, but when I try to display not the whole array but rather its 1st element, it fails with error: cannot find symbol: method get(int).

public class Test  {
    public static void main(String[] args) {
        Map<String, Object> testMap = new HashMap<>();
        ArrayList<Integer> testArray = new ArrayList<>();
        testArray.add(1);
        testArray.add(2);
        testArray.add(3);

        testMap.put("test", testArray);

        //works fine, output: [1, 2, 3]
        System.out.println(testMap.get("test"));
        //get 1st element of testArray, error
        System.out.println(testMap.get("test").get(0));
    }
}

Why does this happen and how to fix it?

My guess was the type Object in the Map causes it, but I can't change it to ArrayList because the Map is supposed to store other types (like String, Integer) as well. So I tried:

System.out.println((ArrayList) testMap.get("test").get(0));

System.out.println(((List<Integer>) testMap.get("test")).get(0)) didn't work too.

which still resulted in the error.

Ans
  • 1,212
  • 1
  • 23
  • 51
  • What do you mean by `System.out.println(((List) testMap.get("test")).get(0)) didn't work too.`? Works fine for me (but ofc now you have an unchecked cast warning). – m0skit0 Feb 08 '18 at 10:34
  • 2
    Btw using `Map` is a [code smell](https://en.wikipedia.org/wiki/Code_smell). – m0skit0 Feb 08 '18 at 10:39
  • @m0skit0 valid point again, but it might be homework assignment, who knows... – Betlista Feb 08 '18 at 11:01
  • @m0skit0 Don't know. `List` doesn't work, but `ArrayList` works. What's so wrong about wanting a dictionary that can store different types of values? If there is a better way to do it, I would gladly use it then. In python such dictionaries is a built-in function, why wouldn't one want to use them in java too? – Ans Feb 08 '18 at 11:04
  • 1
    @m0skit0 Figured out, the `List` wasn't imported, while the `ArrayList` was, that's why it didn't work. – Ans Feb 08 '18 at 11:13
  • 1
    Pro tip: Use an IDE, not a text editor, it will save you a lot of time. – m0skit0 Feb 08 '18 at 11:46

7 Answers7

7

Since Map holding a type of Object, you need to cast that result from Object to List.

 ArrayList<Integer> list =  (ArrayList<Integer>)testMap.get("test");
 System.out.println(list.get(0));

And it is bad practise to have Object as a value. Choose most specific type if possible.

Map<String, ArrayList<Integer>> testMap = new HashMap<>();

So that you can avoid casts. With the above declaration you can directly do

System.out.println(testMap.get("test").get(0));

If you have no option but have to use your map with Object type, instanceof is your friend. That helps you to have a check before doing any cast. So that you can avoid ClassCastException's.

    Map<String, Object> testMap = new HashMap<>();
    ArrayList<Integer> testArray = new ArrayList<>();
    testArray.add(1);
    testArray.add(2);
    testArray.add(3);

    testMap.put("test", testArray);

    // works fine, output: [1, 2, 3]
    System.out.println(testMap.get("test"));
    // get 1st element of testArray, error
    if (testMap.get("test") instanceof ArrayList) {
        System.out.println(((ArrayList<Integer>) testMap.get("test")).get(0));
    }
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
3

I'd recommend to define your map as

Map<String, ArrayList<Integer>> testMap = new HashMap<>();

if you are ok with ArrayLists to be values...

Betlista
  • 10,327
  • 13
  • 69
  • 110
  • 2
    Or even better `Map>` – m0skit0 Feb 08 '18 at 10:31
  • Depends, but I kind of agree, more can be found at https://stackoverflow.com/questions/1992384/program-to-an-interface-what-does-it-mean – Betlista Feb 08 '18 at 10:35
  • How "depends", can you elaborate? The link you provided doesn't provide any argument on "depends" :) – m0skit0 Feb 08 '18 at 10:37
  • @m0skit0 Your point is valid, but I wouldn't ovecomplicate it for a beginner, that's what I meant... – Betlista Feb 08 '18 at 10:42
  • 1
    @Betlista If you think using the interface is over-complicating it, why are you using `Map`? – Michael Feb 08 '18 at 10:46
  • He's already using HashMap to Map, so I guess he already understands that ;) – m0skit0 Feb 08 '18 at 10:52
  • I just think, OP copied the code from some tutorial... OP is not consistent, he used `Map... testMap`, but `ArrayList... testArray` instead of `List testArray`. I believe, just because someone is more experienced, do not need to criticize everythink, especially if the code is working. I like [KISS](https://en.wikipedia.org/wiki/KISS_principle) idea. Also changing whole code might be scary - the relation inbetween original one and new might be lost (which I mean in general, not in this specific case). – Betlista Feb 08 '18 at 10:54
3

If you are storing mixed-type objects in the map, you circumvent Java's internal type checking system and have to make sure on your own that everything is ok.

For the compiler, testMap.get("test") is an Object. So you have to cast:

((ArrayList<Integer>)testMap.get("test")).get(0)
                     ^-----------------^   This is an Object
^---------------------------------------^  We have to cast this into an ArrayList.

Note the correct use of ()s, as explained by the comments. Only then we can use its .get().

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
glglgl
  • 89,107
  • 13
  • 149
  • 217
2

You need to declare your Map to hold ArrayList<Integer> instead of Object type as shown below, otherwise, you need to go for the typecasting (which I don't recommend)

Map<String, ArrayList<Integer>> testMap = new HashMap<>();
Vasu
  • 21,832
  • 11
  • 51
  • 67
1
public class Test  {
        public static void main(String[] args) {
            Map<String, ArrayList<Integer>> testMap = new HashMap<>();
            ArrayList<Integer> testArray = new ArrayList<>();
            testArray.add(1);
            testArray.add(2);
            testArray.add(3);

            testMap.put("test", testArray);

            //works fine, output: [1, 2, 3]
            System.out.println(testMap.get("test"));
            //get 1st element of testArray, error

            System.out.println(testMap.get("test").get(0));
        }
    }

This will work

got the result

[1, 2, 3]
1
Sumesh TG
  • 2,557
  • 2
  • 15
  • 29
1
System.out.println(((List<Integer>) testMap.get("test")).get(0));

Here you have casted your object to List which is an interface. You should use an Arraylist object to make this work.

System.out.println(((ArrayList<Integer>) testMap.get("test")).get(0));

This will work.

0
   Map<String, ArrayList<Integer>> testMap = new 
   HashMap<String,ArrayList<Integer>>();

Highlighted change alone is the only thing that you need. Making the generics as Object is always considered as Bad coding, because the output from that would be a Object and hence need typecasting again.

System.out.println(testMap.get("test").get(0));

Reason for the error is, Object method does not have a method of get() method. As i told you earlier, object is returned here.

So, going forward, make use of generics, which is a good coding practice and also they help you to resolve these errors in future.

    ArrayList<Integer> testArray = new ArrayList<Integer>();
    testArray.add(1);
    testArray.add(2);
    testArray.add(3);

    testMap.put("test", testArray);

    //works fine, output: [1, 2, 3]
    System.out.println(testMap.get("test"));
    //get 1st element of testArray, error
    System.out.println(testMap.get("test").get(0));
Jayanth
  • 746
  • 6
  • 17