0

I did look at Accessing ArrayList<ArrayList<SomeObject>> elements but was thinking there's a more simple answer in my case. Also looked at Why does Java ArrayList use per-element casting instead of per-array casting? which seems to explain the underlying cast issue but doesn't help me know the best approach here. Thanks for your time reading this!

Ultimately I am a newb Java student just trying to implement a Map class with a text-based 2-d map read into some data structure. As I don't know the map size before I read it, I tried Vectors but moved to ArrayLists.

EDIT here's the "map"

12 12
MwwwppppffffMMMM
MMwwppppfffffMMM
MMMwwwwwppppffff
ffffMMMMMwwwpppp
ffffMMMMMwwwpppM
MwwwppfMMMMppfff
MwwwpffffMMMMppp
MwwwppppffffMMMM
wwppppffffMMMMMw
wppppffffMMMMMww
ppppffffMMMMMwww
pppffffMMMMMwwwp

I have this outside of methods, just under the class declaration:

// we have this vector here to be accessible to all methods
// the inner vector will be built in the readMapFile method
static private ArrayList mapList = new ArrayList();

Then in the readMapFile method I have (the whole method is at the end):

        for ( int i = 0; i < mapRows ; ++i)
            {
                // read each subsequent line in the file
                mapFileLine = fileIn.nextLine();

                ArrayList mapRowList = new ArrayList();

                for ( int j = 0 ; j < mapCols ; ++j )
                {
                    // read each character on the line
                    mapRowList.add(mapFileLine.charAt(j));
                }

                // now put mapRowVector as an element of mapVector
                mapList.add(mapRowList); 

                System.out.println(mapList.get(i));

            }

Then I get in trouble trying to access the elements in the inner ArrayList. With this I get "Object cannot be converted into ArrayList:

public static char getTerrainAtLocation( int row, int column )
{

    ArrayList innerList = mapList.get(row);
    return innerList[column];
}

This doesn't give errors until I try to run it:

public static char getTerrainAtLocation( int row, int column )
{

    char[] innerList = (char[])mapList.get(row);
    return innerList[column];
}

I obviously need some help! What's your best advice here, I just want to return the char at row x and column y from a "map." I get this error:

Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to [C
at adventure2.Map.getTerrainAtLocation(Map.java:144)
at adventure2.Map.printMapList(Map.java:154)
at adventure2.Map.main(Map.java:56)
Java Result: 1

Here's my complete readMapFile:

public static void readMapFile( String arg )
{
    if ( arg != "")
    {
        try
        {
            // open a path to the file given in arg 0, this won't throw
            // an exception
            Scanner fileIn = new Scanner(Paths.get(arg));

            // need to clear mapVector for the new file, if it already
            // has data in it
            mapList.clear();

            // this is the line that will throw the exception
            // try to read the file, see if it throws IOException
            mapRows = fileIn.nextInt();
            mapCols = fileIn.nextInt();

            // read to the end of line
            String mapFileLine = fileIn.nextLine();

            // now we have the first line read, with rows and columns
            // need a 2-D char array to hold the map
            //char[][] mapArray = new char [mapRows][mapCols];

            // make up the row vectors row by row, when a row is complete,
            // add that to the full Vector, making a Vector of Vectors

            for ( int i = 0; i < mapRows ; ++i)
            {
                // read each subsequent line in the file
                mapFileLine = fileIn.nextLine();

                ArrayList mapRowList = new ArrayList();

                for ( int j = 0 ; j < mapCols ; ++j )
                {
                    // read each character on the line
                    mapRowList.add(mapFileLine.charAt(j));
                }

                // now put mapRowVector as an element of mapVector
                mapList.add(mapRowList); 

                System.out.println(mapList.get(i));

            }
        }
        catch ( IOException e )
        {
            System.out.println("There was an error reading the file sorry!");
        }
    }
    else
    {
        // arg length was 0 or negative
        System.out.println("Must call readMapFile with a filename as argument");
    } 
} // end readMapFile

Thanks!

Community
  • 1
  • 1
JimLohse
  • 1,209
  • 4
  • 19
  • 44
  • FWIW I put the map text above – JimLohse Oct 14 '14 at 22:48
  • 4
    You're using raw types all over the place, you should use type parameters. – August Oct 14 '14 at 22:49
  • August, I barely understand that, are you referring to what happens when the ArrayList template is called? I know some C++ but new to Java. – JimLohse Oct 14 '14 at 22:49
  • 1) Raw types with generics are going to lead you down this rabbit hole every time. Specifically type your `ArrayList`. 2) Are you trying to do an `ArrayList>`? – Makoto Oct 14 '14 at 22:51
  • `mapList.get(row)` does not return an `ArrayList`. It returns the element of the `ArrayList` stored at that index. – TNT Oct 14 '14 at 22:53
  • Ah thanks between Makoto and August this is starting to make sense. – JimLohse Oct 14 '14 at 22:53
  • TNT I thought that element would be another ArrayList wrapped inside the outer ArrayList, no? – JimLohse Oct 14 '14 at 22:54
  • Why are you reading the file into an `ArrayList` of `ArrayList`? Is `String[]`, and `String.toCharArray()` not good enough? – Elliott Frisch Oct 14 '14 at 22:57
  • Elliott, good point, I am making this too complicated, I can just read an array of Strings and then parse later. THANKS!!!! and thanks to all, very helpful introducing me to raw types. Awesome stuff! – JimLohse Oct 14 '14 at 23:00
  • Yeah, you're right. But you really should consider using generic type parameters. For example you might use `ArrayList>` like @Makoto suggested. Also, instead of casting to a `char[]`, I'd recommend using the `toArray` method, maybe via `(Character[]) mapList.toArray()`. – TNT Oct 14 '14 at 23:00
  • Sweet this is very helpful too, thanks! – JimLohse Oct 14 '14 at 23:32

1 Answers1

1

Java's data structures are great, but you gotta remember the basics :)

class Terrain {

    private byte[] terrainData;
    private int terrainSizeX;
    private int terrainSizeY;

    public void init() {
        terrainData = new byte[terrainSizeX * terrainSizeY];
    }

    private int getIndex(int row, int column) {
        return terrainSizeX * column + row;
    }

    public byte getTerrainAtLocation(int row, int column) {
        return terrainData[getIndex(row, column)];
    }

    public void setTerrainAtLocation(int row, int column, byte value) {
        terrainData[getIndex(row, column)] = value;
    }
}
schuttek
  • 156
  • 1
  • 10
  • Thanks I am too new to upvote this. Very cool, it's supposed to be an advanced programming class in Java (post C# and C++) but I didn't ever think to use the byte array, that is cool! :) – JimLohse Oct 14 '14 at 23:12