HashMap con comportamiento extraño
Frecuentes
Visto 99 veces
-1
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;
}
}
1 Respuestas
1
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 java hashmap or haz tu propia pregunta.
You just aren't looking at the full bucket list. - Sotirios Delimanolis
¿Cómo son
HashCode
yEquals
implementado enPlace
? - Jeroen VannevelHow are you getting this debug output? Have you tried to
get
con las llavesm7
ym8
? - rgettman@JeroenVannevel there is no implementation of HashCode and Equals in Place - Juliatzin
@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'. - Jeroen Vannevel