How to remove a value from a hashmap? - java

The thing is, I have an ExpandableListView with 2 groups, inside of each group I have some users and when I click on these users I get their ids and add to a HashMap of strings, now I'm trying to remove these ids when I click on them for the second time, but the ids of the second group are not being deleted. here is what I'm trying to do:
aMap = new HashMap < String, GPSEscolas > ();
TextView idAluno = (TextView) v.findViewById(R.id.idcrianca);
TextView idEscola = (TextView) v.findViewById(R.id.idescola);
IdEscola = String.valueOf(idEscola.getText());
IdAluno = String.valueOf(idAluno.getText());
mGpsEscolas = aMap.get(IdEscola);
if (mGpsEscolas == null) {
mGpsEscolas = new GPSEscolas();
aMap.put(IdEscola, mGpsEscolas);
mGpsEscolas.getIds_alunos().add(String.valueOf(IdAluno));
mGpsEscolas.setAlunos(IdAluno);
} else {
Set < String > ia = mGpsEscolas.getIds_alunos();
if (!ia.contains(IdAluno)) {
ia.add(String.valueOf(IdAluno));
} else {
alunos = aMap.get(IdEscola).getAlunos();
ia.remove(IdAluno);
aMap.remove(alunos);
}
stringArray = new String[ia.size()];
out = "";
if (ia.size() > 0) {
for (String str: ia.toArray(stringArray)) {
out += ";" + str;
}
aMap.get(IdEscola).setAlunos(out.substring(1));
}
}
MOdel:
public class GPSEscolas implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id_escola;
private Set<String> ids_alunos = new TreeSet<String>();
private String Alunos;
private double distancia;
private Float latitude;
private Float longitude;
public String getAlunos() {
return Alunos;
}
public void setAlunos(String alunos) {
Alunos = alunos;
}
public Integer getId_escola() {
return id_escola;
}
public void setId_escola(Integer id_escola) {
this.id_escola = id_escola;
}
public Set<String> getIds_alunos() {
return ids_alunos;
}
public void setIds_alunos(Set<String> ids_alunos) {
this.ids_alunos = ids_alunos;
}
public double getDistancia() {
return distancia;
}
public void setDistancia(double distancia) {
this.distancia = distancia;
}
public Float getLatitude() {
return latitude;
}
public void setLatitude(Float latitude) {
this.latitude = latitude;
}
public Float getLongitude() {
return longitude;
}
public void setLongitude(Float longitude) {
this.longitude = longitude;
}
}

I assume you are referring to this line:
aMap.remove(alunos);
... which is the only place where you are trying to remove from a HashMap.
If that's the case, the problem is that you are not passing the right parameter value to aMap.remove(). That method expects you to pass a key value, such as whatever IdEscola is, which is the key value you used to do a put in the HashMap.
But instead, you are passing in alunos, which I can't quite be sure what that is, but it looks like a list of students.
So I think that what you wanted to do was to simply do aMap.remove(IdEscola).
EDIT: I now realize that your hashmap is keyed by school, so I changed my answer.
EDIT 2: And if the above is not what you want, then you probably don't want to remove anything from that HashMap.

If your key objects are different while putting(aMap.put(IdEscola, mGpsEscolas)) and getting (aMap.get(IdEscola).getAlunos()) are two different objects then hashmap will return null even when they are logically same values.
Read about object class in java and it's equals() and hashcode() functions , hashmap class uses it.
Student A= new Student ("ram");
Student B= new Student ("ram");
map.put(A,"10");
map.get(B) will return null.
If you use object A as a key to put some element in map then you cant use object B to retrieve it , even when they are logically same .

Related

Java array list returning 0 value

I have created a class like this, which contains a bunch of arraylist as you can see. I've been setting the array with the methods add.. and then retrieving it with get.., when i tried to System.out.println numberofcitizen for example it is returning 0. Note that i have instantiated the class in another class to set the values.
public int numberOfCitizen;
private final ArrayList<Integer> citizenid = new ArrayList<>();
private final ArrayList<String> citizenName = new ArrayList<>();
private final ArrayList<Integer> citizenWaste = new ArrayList<>();
private final ArrayList<Float> longitude = new ArrayList<>();
private final ArrayList<Float> latitude = new ArrayList<>();
private final ArrayList<String> address = new ArrayList<>();
public void working() {
System.out.println("executing fine");
}
public void setnoOfcit(int number) {
this.numberOfCitizen = number;
}
public int getnumber() {
return this.numberOfCitizen;
}
public void addCitizenId(int citizen) {
citizenid.add(citizen);
}
public int getCitizenid(int i) {
int citId = citizenid.get(i);
return citId;
}
public void addCitizenName(String citizenname) {
citizenName.add(citizenname);
}
public String getCitizenName(int i) {
return citizenName.get(i);
}
public void addCitizenWaste(int waste) {
citizenWaste.add(waste);
}
public int getCitizenWaste(int i) {
return citizenWaste.get(i);
}
public void addLatitude(float lat) {
latitude.add(lat);
}
public float getLat(int i) {
return latitude.get(i);
}
public void addlng(float lng) {
longitude.add(lng);
}
public float getlng(int i) {
return longitude.get(i);
}
com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder vrpBuilder = com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder.newInstance();
public void runVPRSolver() {
System.out.println(numberOfCitizen);
System.out.println(getCitizenName(0));
//create a loop to fill parameters
Probable source of problem :
numberOfCitizen is a member attribute that you seem to never change. If you want it to represent the number of elements in your lists, either use citizenName.size() or increment the value of numberOfCitizen in one of the add methods.
Design flaw :
Your design takes for granted that your other class always use that one properly. Anytime you or someone uses that class, he must make sure that he add every single element manually. This adds code that could be grouped inside your class, which would be cleaner and easier to maintain.
So instead of several add method like this :
addCitizenid();
addCitizenName();
addCitizenWaste();
addLongitude();
addLatitude();
addAddress();
Design an other Citizen class which will contain those elements, and use a single list of instances of that class. That way you can use only one method :
private List<Citizen> citizenList = new ArrayList<>();
public void addCitizen(Citizen c) {
/*Add element in your list*/
citizenList.add(c);
}
This programming methodology is called "Encapsulation" which you can read about here
You need to increment numberOfCitizen in your add methods. For example:
public void addCitizenId(int citizen){
citizenid.add(citizen);
numberOfCitizen++;
}
I would also suggest encapsulating your variables into Objects, so create a citizen class:
public class Citizen {
private Integer id;
private Integer name;
private Integer waste;
}
And change your variable to an ArrayList of objects:
ArrayList<Citizen> citizens;

How to access what appears to be JSONObject, in JSONObject, in a JSONArray? Java/Android

I have this JSON file which I would like to use for my mobile application for my university project, however I'm having issues accessing the "fields" section of it and I'm not sure the best way to access it.
{"total_hits":47287,"max_score":11.854574,
"hits":[
{"_index":"f762ef22-e660-434f-9071-a10ea6691c27",
"_type":"item",
"_id":"513fceb375b8dbbc21000022",
"_score":11.854574,
"fields":{
"item_id":"513fceb375b8dbbc21000022",
"item_name":"Cheese, cheddar - 1 cup, diced",
"brand_name":"USDA",
"nf_calories":533.28,
"nf_total_fat":43.97,
"nf_cholesterol":130.68,
"nf_sodium":861.96,
"nf_serving_size_qty":1,
"nf_serving_size_unit":"serving"}},
{"_index":"f762ef22-e660-434f-9071-a10ea6691c27",
"_type":"item",
"_id":"513fceb375b8dbbc21000021",
"_score":11.800501,
"fields":{"item_id":"513fceb375b8dbbc21000021",
"item_name":"Cheese, cheddar - 1 cup, melted",
"brand_name":"USDA",
"nf_calories":985.76,
"nf_total_fat":81.28,
"nf_cholesterol":241.56,
"nf_sodium":1593.32,
"nf_serving_size_qty":1,
"nf_serving_size_unit":"serving"}}, ... etc.
I can access the _Score value in the first section however, I am looking to access items like item_name, and nf_calories, however I'm not sure on the syntax. I believe I understand what I need to do, but I can't visualise it in my head.
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("hits");
List<NutritionModel> nutModelList = new ArrayList<>();
for(int i=0; i<parentArray.length(); i++) {
hitsObject = parentArray.getJSONObject(i);
NutritionModel nutModel = new NutritionModel();
nutModel.set_score(hitsObject.getDouble("_score"));
//Adding final object in the list
nutModelList.add(nutModel);
This is what I currently have in my ViewNutrition.java file.
public class NutritionModel {
private Double _score;
public Array getFieldarray() {
return fieldarray;
}
public void setFieldarray(Array fieldarray) {
this.fieldarray = fieldarray;
}
private Array fieldarray;
private String item_name;
private Double nf_calories;
private Double nf_total_fat;
private Double nf_protein;
private Double nf_cholesterol;
private Double nf_sodium;
private Double nf_serving_size_qty;
public Double get_score() {
return _score;
}
public void set_score(Double _score) {
this._score = _score;
}
public String getItem_name() {
return item_name;
}
public void setItem_name(String item_name) {
this.item_name = item_name;
}
public Double getNf_calories() {
return nf_calories;
}
public void setNf_calories(Double nf_calories) {
this.nf_calories = nf_calories;
}
public Double getNf_total_fat() {
return nf_total_fat;
}
public void setNf_total_fat(Double nf_total_fat) {
this.nf_total_fat = nf_total_fat;
}
public Double getNf_protein() {
return nf_protein;
}
public void setNf_protein(Double nf_protein) {
this.nf_protein = nf_protein;
}
public Double getNf_cholesterol() {
return nf_cholesterol;
}
public void setNf_cholesterol(Double nf_cholesterol) {
this.nf_cholesterol = nf_cholesterol;
}
public Double getNf_sodium() {
return nf_sodium;
}
public void setNf_sodium(Double nf_sodium) {
this.nf_sodium = nf_sodium;
}
public Double getNf_serving_size_qty() {
return nf_serving_size_qty;
}
public void setNf_serving_size_qty(Double nf_serving_size_qty) {
this.nf_serving_size_qty = nf_serving_size_qty;
}
}
This is what's currently in my custom class for using the JSON data.
I've tried cycling through a JSONObject with a for statement, searching for a JSONObject called "fields" however it still just returns null results. Been stuck for a couple of days now and really struggling, any help or direction would be appreciated! Thanks.
In order to access items like item_name, and nf_calories use need to go to access the inner array. So, how to do-
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("hits");
Suppose you need to access the elements(item_name etc.) of "hits" at index i then, you need to go to the inner JSONObject named "fields" and then you need to access the key named "item_name"
for that do-
for(int i=0;i<parentArray.length();i++) {
JSONObject obj1=parentArray.getJSONObject(i);
JSONObject obj2= obj1.getJSONObject("fields");
String item_name=obj2.getString("item_name");
}
Anyways even if you get confused in the explanation then for better JSON visualization access this website - http://jsonviewer.stack.hu/
The Field object isn't an Array it's an object. I suggest you create a FieldModel class and have the NutritionModel class contain an instance of the FieldModel class.
// In parser class
nutModel.setFields(hitsObject.getJSONObject("fields"));
// In NutritionModel class
public void setFields(JSONObject obj) {
this.fields.item_name = obj.getString("item_name");
// etc
}

Parsing weather data and sort it in collection

Got stuck at the following: I'm parsing xml weather data containing info about 3 different
weather stations:
<station>
<station_id>TAPA</station_id>
<latitude>17.117</latitude>
<longitude>-61.783</longitude>
<xml_url>http://weather.gov/xml/current_obs/TAPA.xml</xml_url>
</station>
<station>
<station_id>TKPN</station_id>
<latitude>17.2</latitude>
<longitude>-62.583</longitude>
<xml_url>http://weather.gov/xml/current_obs/TKPN.xml</xml_url>
</station>
<station>
<station_name>Blackburne/Plymouth</station_name>
<latitude>16.75</latitude>
<longitude>-62.167</longitude>
<xml_url>http://weather.gov/xml/current_obs/TRPM.xml</xml_url>
</station>
Next, i'm getting their distances to my device and getting the following data set:
Distance(Double): Corresponding XML(String)
3495.3 http://weather.gov/xml/current_obs/TAPA.xml
1234.4 http://weather.gov/xml/current_obs/TKPN.xml
5678.7 http://weather.gov/xml/current_obs/TRPM.xml
What's the best way to put them in some kind of a sorted collection in ascending order and get the lowest distance to obtain corresponding xml file? I mean, the Distance would be Key and Corresponding XML would be its value. After sorting I would get the lowest distance(which is the first Key) and access my url to perform some other work on it. The distances may change because there may be other stations nearby so somehow I need to access the very first Key-Value pair. Could you please give me a hint on that.
Ok. This is how it works:
To be able to sort objects by a property in java, you have to implement the Comparable interface. Then, you need to override the method called compareTo() which uses the current instance (this) and an additional one to sort them in the proper order. So, to be able to sort by the distance between the stations, you need to do something like this:
class Data implements Comparable<Data>{
String url;
double distance;
#Override
public int compareTo(Data other){
// compareTo should return < 0 if this is supposed to be
// less than other, > 0 if this is supposed to be greater than
// other and 0 if they are supposed to be equal
int result = this.distance <= other.distance ? -1 : 1;
return result;
}
}
After doing this, you are going to be able to call:
Collections.sort(dataList);
And, you'll have your objects sorted by the distance property.
well I would like to add few things as #Luis Lavierim has covered necessary things.
given xml needs root element as it is invalid now because of multiple root elements
I have written a test code assuming a root element <root></root>
you may use simple framework library to parse the data which is quite easy.
Serializer serializer_Read = new Persister();
File source = new File(path);
Response response = serializer_Read.read(Response.class, source);
Collections.sort(response.getStations());
System.out.println("" + response.getStations().size());
for (Station station : response.getStations()) {
System.out.println("" + station.getStation_id());
}
well you will require some type to do the sort against it, you check this model class for the response. the code is also available on Github and it's been tested
#Root(name = "root", strict = false)
class Response {
#ElementList(name = "station", inline = true)
List<Station> stations;
public List<Station> getStations() {
return stations;
}
}
#Root(name = "station", strict = false)
class Station implements Comparable<Station> {
#Element(name = "station_id", required = false)
private String station_id;
#Element(name = "latitude", required = false)
private String latitude;
#Element(name = "longitude", required = false)
private String longitude;
#Element(name = "xml_url", required = false)
private String xml_url;
#Element(name = "distance", required = true)
private int distance;
public Station() {
}
public Station(String station_id, String latitude, String longitude, String xml_url) {
this.station_id = station_id;
this.latitude = latitude;
this.longitude = longitude;
this.xml_url = xml_url;
}
public String getStation_id() {
return station_id;
}
public String getLatitude() {
return latitude;
}
public String getLongitude() {
return longitude;
}
public String getXml_url() {
return xml_url;
}
public void setDistance(int distance) {
this.distance = distance;
}
public int getDistance() {
return distance;
}
#Override
public int compareTo(Station o) {
Station station = (Station) o;
return this.distance - station.getDistance();
}
}

Sorting ArrayList Hashmap

I have an ArrayList<HashMap<String,String>> and I want to sort it. My ArrayList output in Logcat is like this:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km}]
I want to sort the list based on "diff" value by ascending order so that Logcat has to be like:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km}]
I have read many similar topics and tried something like
Collections.sort(final_itinList, new Comparator<HashMap< String,String >>() {
#Override
public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
// Do your comparison logic here and retrn accordingly.
return lhs.get("diff").compareTo(rhs.get("diff"));
}
});
with no success. Any help would be appreciated
Currently, you are trying to compare two String Objects:
return lhs.get("diff").compareTo(rhs.get("diff"));
What you really want to do is comparing the returned Integers, so you would need to do something like this:
return (Integer.parseInt(lhs.get("diff")) - Integer.parseInt(rhs.get("diff")));
Your Comparator is comparing two Strings. That's probably why the list is not sorted correctly. The "diff" string should be parsed as an integer (or float) to compare it.
If your objects always have the same structure, I would advise to create a List of a custom object (where the diff is an integer representing the number of kilometers) instead of using a List of Maps. In that case, you could make your custom object implement Comparable.
Something like :
public class MyCustomObject implements Comparable<MyCustomObject> {
private String mNum;
private String mUsername;
private String mStartPoliPro;
private String mFinalPoliPro;
private int mDiff;
#Override
public int compareTo(MyCustomObject another) {
return mDiff - another.getDiff();
}
public String getNum() {
return mNum;
}
public void setNum(String num) {
mNum = num;
}
public String getUsername() {
return mUsername;
}
public void setUsername(String username) {
mUsername = username;
}
public String getStartPoliPro() {
return mStartPoliPro;
}
public void setStartPoliPro(String startPoliPro) {
mStartPoliPro = startPoliPro;
}
public String getFinalPoliPro() {
return mFinalPoliPro;
}
public void setFinalPoliPro(String finalPoliPro) {
mFinalPoliPro = finalPoliPro;
}
public int getDiff() {
return mDiff;
}
public void setDiff(int diff) {
mDiff = diff;
}
}
and then simply call
List<MyCustomObject> myList = // create your object list
Collections.sort(myList);

How can I sort a collection of custom entities?

I have a list of custom entities which I need to sort in this order: valueOne, valueTwo, and valueThree.
Here is my code
public class AppRunner {
public static void main(String[] args) {
Detail d1 = new Detail("valueOne");
Detail d2 = new Detail("valueTwo");
Detail d3 = new Detail("valueFive");
Detail d4 = new Detail("valueTen");
Detail d5 = new Detail("valueOne");
Detail d6 = new Detail("valueOne");
List<Detail> details = new ArrayList<Detail>(Arrays.asList(d1, d2, d3, d4, d5, d6));
Collections.sort(details);
System.out.println(details);
}
}
My entity class
public class Detail implements Comparable<Detail> {
private String value; // there are three options: valueOne, valueTwo, and some other value
public Detail(String value) {
this.value = value;
}
#Override
public int compareTo(Detail detail) {
String val = detail.getValue();
if (val.equals(this.value) && val.equals("valueOne")) {
return 1;
} else if (val.equals(this.value) && val.equals("valueTwo")) {
return -1;
} else {
return 0;
}
}
// getter, setters, toString
}
I think that need help with compareTo method. In the end I need to get list in this order:
valueOne
valueOne
valueOne
valueTwo
valueFive
Use an Enum and compare ordinals:
enum ValidValues { valueOne, valueTwo, valueThree }
... and then:
public int compareTo(Object detail) {
return Integer.compare(ValidValues.valueOf(this.value).ordinal(),
ValidValues.valueOf(((Detail)detail).value).ordinal());
}
For a larger number of values it might be worth it to do this with a collection or map, rather than an enum.
You can have a simple getter that return a numeric value based on your String value and simply return the difference of both numeric values in your compare() method (remember that compare() should return 0 if the two objects are equals, see Comparable javadoc.
public static class Detail implements Comparable<Detail> {
private String value; // there are three options: valueOne, valueTwo, and some other value
public Detail(String value) {
this.value = value;
}
#Override
public int compareTo(Detail detail) {
return this.getNumericValue() - detail.getNumericValue();
}
private int getNumericValue() {
switch (this.value) {
case "valueOne": return 1;
case "valueTwo": return 2;
default: return 3;
}
}
}
See note at the end on possible better designs.
I suggest adding another field to the Detail class, populating that baeed on the desired sort order and value, and using this to sort.
public class Detail implements Comparable<Detail> {
private String value;
private int sortOrder;
public Detail(String value) {
this.value = value;
if(value.equals("valueOne") {
sortOrder = 1;
}
if(value.equals("valueTwo") {
sortOrder = 2;
}
...
...
}
This makes compareTo simple:
public int compareTo(Detail detail) {
if(this.sortOrder < detail.sortOrder) {
return -1;
}
if(this.sortOrder == detail.sortOrder) {
return 0;
}
if(this.sortOrder > detail.sortOrder) {
return 1;
}
}
Note:
The above is solution to your problem as it stands. However, you may have better options. If you are using Detail to represnet a fixed set of values, look at Enums. Enums in Java are very powerful and versatile. You can have a enum repsesenting a fixed set of values and use the enum in your Detail class.
If you may have a large set of values that are not predefined, you can have a Map that maps the sort order with the value.
private static Map<Int, String> sortOrder = new HashMap<Int, String>();
sortOrder.put(1, "valueOne");
...
And use this map sorting. Depending on your situation, you can popuklate this map from a database, a file on initialization or just dueing runtime.

Categories

Resources