HashMap con comportamiento extraño

Este es el código problemático:

public GetPlaces(Context context, GoogleMap map, Location loc, int radius,
        String userId) {
    this.context = context;
    this.userId = userId;
    this.loc = loc;
    this.mMap = map;
    this.radius = radius;
    this.placesInfo = null;
}
@Override
protected void onPostExecute(ArrayList<Place> result) {

    super.onPostExecute(result);
    // Should be great centralize that

    Marker myMarker = null;
    placesInfo = new HashMap<String, Place>();
    LatLng myPos = new LatLng(loc.getLatitude(), loc.getLongitude());
    new MapCircle(mMap, myPos, radius);

    if (dialog.isShowing()) {
        dialog.dismiss();
    }
    // If 1st Loading, Move camera to initial location.
    SharedPreferences preferences = PreferenceManager
            .getDefaultSharedPreferences(context);
    boolean isFirstLoad = preferences.getBoolean("isFirstLoad", true);
    if (isFirstLoad) {
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(loc.getLatitude(), loc.getLongitude()), 4));
    }
    MarkerOptions marker;
    if (result.size() > 0) {
        for (Place myPlace : result){
            marker = new MarkerOptions();
            myMarker = null;
            // No hay rating general, pero hay rating individual, hay que
            // hacer el promedio
            if (myPlace.getRating() == null) {
                if (myPlace.getNumReviews() > 0) {
                    float average_rating = Place.calcRatAvrg(myPlace);
                    myPlace.setRating(average_rating);
                }

            }

            marker.title(myPlace.getName());
            marker.position(new LatLng(myPlace.getLatitude(), myPlace
                    .getLongitude()));
            if (myPlace.getRating() == null) {
                if (myPlace.getNumReviews() == 0)
                    marker.icon(BitmapDescriptorFactory
                            .fromResource(R.drawable.gris));
            }

            else if (myPlace.getRating() < 4)
                marker.icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.rojo));
            else
                marker.icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.verde));
            // marker.snippet(myPlace.getVicinity());
            // result.get
            myMarker = mMap.addMarker(marker);
            String markerId = myMarker.getId();
            placesInfo.put(markerId, myPlace);

        }

        int zoom = getZoom();

        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(myPos) // Sets the center of the map to
                .zoom(zoom) // Sets the zoom
                .tilt(30) // Sets the tilt of the camera to 30 degrees
                .build(); // Creates a CameraPosition from the builder
        mMap.animateCamera(CameraUpdateFactory
                .newCameraPosition(cameraPosition));
    } else {
        Toast.makeText(
                context,
                "No se encontró ninguna gasolinera en el radius, Sube el radio en los ajustes",
                Toast.LENGTH_LONG).show();
    }

}

result is an ArrayList which contains Places from google:

[Place{id=0c130dc7e8661def2807993911c60af6d87f401f, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Gasofacil Estación 7640, latitude=19.286464, longitude=-99.149204}, 
Place{id=9c3ece23658da5a1325faab62ee792526975b151, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Gasofacil Estación 5240, latitude=19.303008, longitude=-99.146746}, 
Place{id=ba261a363d621730ac1270c8f3d5f1d050b9068d, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Servicio Santa Úrsula, latitude=19.305874, longitude=-99.144426}, 
Place{id=b738dbfcdc2914428d2c95595fa45aca996574c2, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Gasolinera Pemex, latitude=19.293018, longitude=-99.125251}, 
Place{id=a125eaec620874ccf21dd3b97490ee9213b6eaa0, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Dangases, latitude=19.299829, longitude=-99.150671}, 
Place{id=5f4ecc0f7f1e9da577a0b3d3126b5775efcb926d, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Operadora Sisgo S.A. de C.V. ., latitude=19.284062, longitude=-99.129679}, 
Place{id=ca37e566f0c661764318247b8615a0f0e762b2fa, icon=http://maps.gstatic.com/mapfiles/place_api/icons/gas_station-71.png, name=Super Servicio Coapa S.A. de C.V., latitude=19.290221, longitude=-99.119116}]

markerId takes the values : m7,m8,m9,m10,m11,m12,m13

The weird thing is how is filled the hashmap in the line :

placesInfo.put(markerId, myPlace);

With the debug, here is the way it is filled :

placeInfos :

[0]:null
[1]:null
[2]:m7->place1
[3]:null

[0]:null
[1]:null
[2]:m7->place1
[3]:m8->place2

[0]:m9->place3
[1]:null
[2]:m7->place1
[3]:m8->place2

[0]:m9->place3
[1]:null
[2]:m10->place4 ( It erased m7, I check everything, I don't understand it)
[3]:m8->place2

[0]:m9->place3
[1]:null
[2]:null
[3]:null
[4]:null
[5]:null
[6]:m10->place4
[7]:m11->place5

[0]:m9->place3
[1]:null
[2]:null
[3]:null
[4]:m12->place6
[5]:null
[6]:m10->place4
[7]:m11->place5

[0]:m9->place3
[1]:null
[2]:null
[3]:null
[4]:m12->place6
[5]:m13->place7
[6]:m10->place4
[7]:m11->place5 ( At the end, I lost place1 and place2)

EDIT 1: I put all the onPostExecute Method EDIT 2: I've now implemented Equals() ans hashCode() methods in Place Class, but it still doesn't work, I have a nullPointerException trying to access to hmInfos.get("m7") ( I removed all getters and setters and other methods for easier reading)

public class Place {
private String id;
private String icon;
private String name;
private String vicinity;
private Double latitude;
private Double longitude;
private ArrayList<Review> reviews;
private Float rating;
private String reference;
private int numReviews;

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Place))
          return false;
        if (obj == this)
          return true;
        return  (this.id == ((Place) obj).getId());

}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * (getId().hashCode());
    return result;
}
}

preguntado el 27 de noviembre de 13 a las 00:11

You just aren't looking at the full bucket list. -

¿Cómo son HashCode y Equals implementado en Place? -

How are you getting this debug output? Have you tried to get con las llaves m7 y m8? -

@JeroenVannevel there is no implementation of HashCode and Equals in Place -

@JuliatzindelToro: winner winner chicken dinner. You'll probably have hash collision (which you can also see in Sotirios' and Jim's) replies. When you add custom objects to a HashMap you have to override these methods in order to avoid situations like this. You'll find a lot of info by just googling 'java override equals hashcode'. -

1 Respuestas

Consider this section of your debug output:

[0]:m9->place3
[1]:null
[2]:m10->place4 ( It erased m7, I check everything, I don't understand it)
[3]:m8->place2

Asumiendo placesInfo es un estándar HashMap then when there is a collision (m10 hashed to the same slot as m7), the entry for m7 se encadenado del uno para m10. Es realmente

[0]:m9->place3
[1]:null
[2]:m10->place4,  m7->place1
[3]:m8->place2

respondido 27 nov., 13:00

@Jim Garrison I don't understand that : the entry for m7 gets chained from the one for m10. How can happen a collision??? and how should I do to avoid it ??? tx for the help - juliatzin

@JuliatzindelToro Why do you want to avoid it? It just means two key objects fall in the same bucket in the HashMap, a very common state of affairs. - patricia shanahan

@PatriciaShanahan The thing is when I try to do: Place myPlace = hmInfos.get("m7"), I get a null exception. I also checked the hashcode, and they are not equals. I admit I don't know anything about hascodes, so I will see how can I implement HashCode and Equals in my class - juliatzin

¿Está utilizando java.util.HashMap<K,V>? Or some other 3rd party library? - Jim Garrison

Yes, java.util.HashMap<String,Place>. I'm trying to implement equals and HashCode is Place. - juliatzin

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.