title: Most efficient Java data structure to frequently find values in 3-dimensions?
body: <p>I've never worked with 3 dimensional data until now, I'm trying to implement a structure which allows me to store objects in positions relative to each other in a structure which allows me to find the coordinates (x,y,z) of any given object, to find any objects adjacent to it and to get a list of all values (rooms).</p>
  
  <p>The data will be read frequently but changed infrequently and I'm targetting Android so memory efficiency is important. Currently the bounds for all 3 axis are 0-11 but in the future it must scale for axis 0-250 (so 250^3).</p>
  
  <p>Below is my current code, I've read a lot of related questions but not found a definitive answer. Is there a better data structure / way to do this in java?</p>
  
  <pre><code>public class Building {
  
      private int mStartX;
      private int mStartZ;
      private Bounds mBounds;
      private Map&lt;XYPair, Map&lt;Integer, Room&gt;&gt; mRooms;
  
      public Building(Bounds b) {
          mBounds = b;
          mRooms = new HashMap&lt;&gt;();
          mStartX = Math.round(b.getMaxWidth() / 2f) -1;
          mStartZ = Math.round(b.getMaxHeight() / 2f) -1;
          Map&lt;Integer, Room&gt; zMap = new HashMap&lt;&gt;();
          zMap.put(mStartZ, new StartRoom());
          mRooms.put(new XYPair(mStartX, 0), zMap);
      }
  
      public Room roomAt(int x, int y, int z) {
          Room room = null;
          Map&lt;Integer, Room&gt; zMap = mRooms.get(new XYPair(x, y));
          if (zMap != null) {
              room = zMap.get(z);
          }
          return room;
      }
  
      //FIXME: There must me a more efficient structure
      public List&lt;Room&gt; getAdjacentRooms(Room l) {
          List&lt;Room&gt; adjacent = null;
          if (l != null) {
              for (int y = 0; y &lt; mBounds.getMaxLength(); y++) {
                  for (int x = 0; x &lt; mBounds.getMaxWidth(); x++) {
                      for (int z = 0; z &lt; mBounds.getMaxHeight(); z++) {
                          if (l.equals(roomAt(x, y, z))) {
                              adjacent = getAdjacentRooms(x, y, z);
                          }
                      }
                  }
              }
          }
          return adjacent;
      }
  
      public List&lt;Room&gt; getAdjacentRooms(int x, int y, int z) {
          List&lt;Room&gt; adjacent = new ArrayList&lt;&gt;();
          if (x &gt; 0) {
              Room room = roomAt(x-1, y, z);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          if (x &lt; mBounds.getMaxWidth()) {
              Room room = roomAt(x+1, y, z);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          if (y &gt; 0) {
              Room room = roomAt(x, y-1, z);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          if (y &lt; mBounds.getMaxLength()) {
              Room room = roomAt(x, y+1, z);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          if (z &gt; 0) {
              Room room = roomAt(x, y, z-1);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          if (z &lt; mBounds.getMaxHeight()) {
              Room room = roomAt(x, y, z+1);
              if (room != null) {
                  adjacent.add(room);
              }
          }
          return adjacent;
      }
  
      public List&lt;Room&gt; getAllRooms() {
          List&lt;Room&gt; rooms = new ArrayList&lt;&gt;();
          for (Map&lt;Integer, Room&gt; zMap : mRooms.values()) {
              rooms.addAll( zMap.values() );   
          }
          return rooms;
      }
  
      private final class XYPair {
  
          private final int mX, mY;
  
          public XYPair(int x, int y) {
              mX = x;
              mY = y;
          }
  
          public int getX() {
              return mX;
          }
  
          public int getY() {
              return mY;
          }
  
          public int hashCode() {
              return (mX * 31) ^ mY;
          }
  
          public boolean equals(Object o) {
              if (o instanceof XYPair) {
                  XYPair other = (XYPair) o;
                  return (mX == other.getX() &amp;&amp; mY == other.getY());
              }
              return false;
          }
  
      }
  
  }
  </code></pre>