Parsing weather data and sort it in collection - java

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();
}
}

Related

LiveData<String>To Float Parse Replace

I'm using the Google purchase library and I'm using the price via a LiveData. Price tag: It looks like $20.99. I have to parse this data and print only 20.99. For this, I think I need to convert the LiveData String data to float or integer. How can I do that?
static public class SkuDetails {
final public String sku;
final public LiveData<String> title;
final public LiveData<String> description;
final public LiveData<String> price;
final public int iconDrawableId;
SkuDetails(#NonNull String sku, TrivialDriveRepository tdr) {
this.sku = sku;
title = tdr.getSkuTitle(sku);
description = tdr.getSkuDescription(sku);
price = tdr.getSkuPrice(sku);
iconDrawableId = skuToResourceIdMap.get(sku);
}
}
BillingClient;
public final LiveData<String> getSkuPrice(String sku) {
LiveData<SkuDetails> skuDetailsLiveData = skuDetailsLiveDataMap.get(sku);
assert skuDetailsLiveData != null;
return Transformations.map(skuDetailsLiveData, SkuDetails::getPrice);
}
EDIT: Sorry, I forgot to add the line of code that prints the price information correctly. I have shared the code I need to parse below.
public LiveData<String> getSkuPrice(Subscription var1) {
return getSkuDetails(var1.getSku()).price;
}
Activity.xml;
android:text="#{viewModel.getSkuPrice(subscription)}"
You can do something like this once you've price LiveData assigned.
// get the string value from "price" LiveData
String strPrice = price.getValue();
//remove dollar sign from this price
String priceWithoutDollarSign = strPrice.replaceAll("[^\\d.]", "");
//convert/parse it as float just in-case needed otherwise priceWithoutDollarSign will be enough
float resultPrice = Float.parseFloat(priceWithoutDollarSign);

Access existing objects in another class Java

I'm using Bluej to create a basic Java project which I'm not supposed to use Arrays or collections and I'm having difficulty to understand how I can display a specific existing object from another class.
Here's my Class Listing:
public class Listing
{
//name of the listing
private String listingName;
//number of the listing
private int listingNumb = 0;
//price of the listing
private double price;
//checks if the listing is for sale
private boolean isForSale;
//House data of the listing
private HouseData housedata;
private boolean isSold;
/**
* Constructor for objects of class Listing
*/
public Listing(String newListing, double newPrice, HouseData housedata)
{
listingName = newListing;
listingNumb++;
price = newPrice;
isForSale = false;
this.housedata = housedata;
isSold = false;
}
//Returns if the listing is sold or not
public boolean getIsSold(){
return isSold;
}
//Set the listing as sold or not
public boolean setIsSold(){
isSold = true;
return isSold;
}
//returns if the listing is for sale or not
public boolean getIsForSale(){
return isForSale;
}
//set the listing for sale or not
public boolean setIsForSale(boolean sale){
isForSale = sale;
return isForSale;
}
//Return the price of the listing
public double getPrice(){
return price;
}
//Return the listing name
public String getListingName(){
return listingName;
}
//Return the listing number
public int getListingNumb(){
return listingNumb;
}
//checks if the listing is located at a specific city
public boolean isLocatedAt(String city){
if(housedata.city() == city){
return true;
}else{
return false;}}
public double getSurface(){
return housedata.getSurface();
}
}
Here's my Class RealEstateAgency where I want to call the objects from class Listing:
public class RealEstateAgency
{
//the name of the agency
private String agency;
//the amount of profit from property sales
private double profit;
//identifies the seller of the property
private String agent;
private boolean isOnSale;
//the name of the property
private Listing listing;
private Listings lists;
/**
* Constructor for objects of class RealEstateAgency
*/
public RealEstateAgency()
{
profit = 0;
}
//Returns total profit from agency
public double getProfit(){
return profit;
}
//Display listing that is on sale with the name of one city
//This is the method where I want to retrieve all listing existing objects that have a specific city
public void displayListingsLocatedAt(String city){
System.out.println("The available listings for this city are: " + ;
}
}
And this is the main class where I initialize the objects:
public class AppStart
{
public static void main(String[] args)
{
Address address1 = new Address("street", "postalcode", "city");
HouseData house1 = new HouseData(2, true, address1);
Listing list1 = new Listing("Imóvel1", 9000, house1);
Listing list2 = new Listing("Imóvel2", 9000, house1);
Listing list3 = new Listing("Imóvel3", 8000, house1);
RealEstateAgency real1 = new RealEstateAgency();
}
}
Thing is, you are creating these Listing classes that are not part of any class. After your initialization of RealEstateAgency, there should be a call something like this:
real1.listing = list1;
(I think it will work, altough it's set to private...)
It will add your list1 into your real1 object, then able to call it's getters like
real1.listing.getPrice();
Or something like this.
Thing is, you can reach the class variables by the dot selector, even if that variable is an another class, in that case you can use your selectors as a chain.
However, with your current setup, you can hold only 1 Listing in each RealEstateAgency, plus I don't think "Listings lists" works. Either that's an errorenous code, or part of your code is missing that explains that line.
An another note, your listingNumb currently does nothing, since it's held by the Listing class, so after calling the constructor of a Listing, it will be just set to 1 all the time.

How to remove a value from a hashmap?

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 .

Only Allow Objects with Unique Name - Java

I am making an inventory system.
I want to ensure that objects I am creating (Ingredients) all have unique names. In other words, I want to make sure that there are never two Ingredients that have the same name in the whole program. Currently I have the following class:
package ingredient;
import java.util.HashSet;
public class Ingredient {
private final String name;
private final double price;
private static HashSet<String> names = new HashSet<String> ();
private Ingredient(String ingr_name, double ingr_price) {
name = ingr_name;
price = ingr_price;
}
public static Ingredient createIngredient(String ingr_name, double ingr_price) {
if (names.contains(ingr_name)) {
return null;
} else {
names.add(ingr_name);
return new Ingredient(ingr_name, ingr_price);
}
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Then, when I go to actually make new ingredients, I make statements such as :
Ingredient egg = Ingredient.createIngredient("egg", 1);
Is this okay design? I suppose I am concerned because returning "NULL" might not be the best practice here.
I cant comment, but whatever...
I would go about this by storing all of the Ingredients in a different class, then you wouldn't need all this static nonsense. In the class where you actually create a new Ingredient (Ingredient egg = Ingredient.createIngredient("egg", 1);) you could maybe create an ArrayList of ingredients like so:
ArrayList<Ingredient> ingredients = new ArrayList<>();
Then when you make a new Ingredient you would just have to make sure you add it to the ArrayListand when you do so, check that none of the ingredients are already there, maybe something like this:
createIngredient("egg", 1);
or
Ingredient egg = createIngredient("egg", 1);
...
private Ingredient createIngredient(String ingr_name, double ingr_price){
for(Ingredient i : ingredients){
if(i.getName().equals(ingr_name)){
return null;
}
}
Ingredient newing = new Ingredient(ingr_name, ingr_price);
ingredients.add(newing);
return newing;
}
Then the Ingredient class could be cut down to something like this:
package ingredient;
public class Ingredient {
private final String name;
private final double price;
public Ingredient(String ingr_name, double ingr_price) {
name = ingr_name;
price = ingr_price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
And then you could access each individual Ingredientwith a method to run through the ArrayList and find the Ingredient with the name your looking for:
public Ingredient findIngredient(String name){
for(Ingredient i : ingredients){
if(i.getName().equals(name)){
return i;
}
}
return null;
}
I would recommend either
A) returning the already created ingredient
Or if that would confuse the caller,
B) throwing an exception
This can be a simple IllegalArgumentsException, or depending on your needs, a custom exception class.

What's good practice of creating input validation method in Java?

If I want to validate my input, should I make validation code as private helper methods or create a separate static helper class? Does the validation code increase the size of the object?
More Information
Let's say I have a class
import java.util.Vector;
public class Place {
private final double longitude;
private final double latitude;
private final String id;
private String address;
private String name;
private String types;
private String icon;
private String phoneNumber;
private String websiteUrl;
private int rating;
private Vector<Integer> challenges;
public static class Builder {
// required parameter
private final double longitude;
private final double latitude;
private final String id;
// optional parameter
private String address = "n/a";
private String name = "n/a";
private String icon = "n/a";
private String phoneNumber = "n/a";
private String websiteUrl = "n/a";
private String types = "n/a";
private Vector<Integer> challenges = new Vector<Integer>();
private int rating = 0;
public Builder(double longitude, double latitude, String id) {
assert(longitude >= -180.0 && longitude <= 180.0);
assert(latitude >= -90.0 && longitude <= 90.0);
this.longitude = longitude;
this.latitude = latitude;
this.id = id;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder types(String types) {
this.types = types;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder icon(String icon) {
this.icon = icon;
return this;
}
public Builder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Builder websiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
return this;
}
public Builder builder(int rating) {
this.rating = rating;
return this;
}
public Place build() {
return new Place(this);
}
}
public Place(Builder builder) {
// required parameters
longitude = builder.longitude;
latitude = builder.latitude;
id = builder.id;
// optional parameters
address = builder.address;
types = builder.types;
name = builder.name;
icon = builder.icon;
phoneNumber = builder.phoneNumber;
websiteUrl = builder.websiteUrl;
rating = builder.rating;
challenges = builder.challenges;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
public String getId() {
return id;
}
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public String getTypes() {
return types;
}
public void setTypes(String types) {
this.types = types;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setIconUrl(String icon) {
this.icon = icon;
}
public String getIcon() {
return icon;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setWebsiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
}
public String getWebsiteUrl() {
return websiteUrl;
}
public void setRating(int rating) {
this.rating = rating;
}
public int getRating() {
return rating;
}
#Override
public String toString() {
return "(" + Double.toString(longitude) + ", " + Double.toString(latitude) + ")";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Place other = (Place) obj;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public Vector<Integer> getChallenges() {
return new Vector<Integer>(challenges);
}
public void addChallenges(Integer i) {
this.challenges.add(i);
}
public void showChallenges() {
for (Integer i : challenges) {
System.out.print(i + ", ");
}
}
}
If I have to validate address argument before setting it, where should I put the code for validating address in this case?
If you are talking just seeing if the entered String is formatted correctly or if the length is right, then you would use a private method. If you would on the other hand check if the address is correct (look it up on a map) or any more advanced stuff, it would make sense to create a AddressValidator interface and call it from that private method.
The reason for the private method being that you call this both from a constructor, setter or any other method that could suppy an address. The reason for the interface being that you might want to have e.g. an online / offline AddressValidator (MockAddressValidator, or one that calls a different class for each country etc).
As an AddressValidator could be reused in other classes, and to keep your code clean, I would create it as a top level interface + OnlineAddressValidator. This makes your class better readable as well. For full configurability, you might want to think about how you are going to supply the AddressValidator instance, e.g. through the constructor or one defined as a static final validator.
public interface AddressValidator {
static class AddressValidatorResult {
// some results, you might want to return some useful feedback (if not valid)
boolean isValid() {
throw new IllegalStateException("Method not implemented yet");
}
}
public static class AddressValidationException extends Exception {
private AddressValidationException(AddressValidatorResult result) {
// add some implementation
}
}
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
AddressValidatorResult validateAddress(String address);
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
}
public class DefaultAddressValidator implements AddressValidator {
public static class Params {
// some parameters for this specific validator
}
private final Params params;
public DefaultAddressValidator(Params params) {
// creates this validator
this.params = params;
}
#Override
public AddressValidatorResult validateAddress(String address) {
// perform your code here
// I don't like "return null" as it may lead to bugs
throw new IllegalStateException("Method not implemented yet");
}
}
// and use it like this
private void validateAddress(String address) throws AddressValidationException {
// e.g. field AddressValidator set in constructor
AddressValidatorResult result = addressValidator.validateAddress(address);
if (!result.isValid()) {
throw new AddressValidationException(result);
}
}
Should I make validation code as private helper methods or create a separate static helper class?
This totally depends on your context. It's impossible to say what should be the best design, without knowing what you are trying to realise.
After you edit: IMO, it is still not easy to tell you. If you only have to validate the address in one single point of your application (id: the setter method), I would validate it inside the setter method. If the input was invalid, I whould throw an IllegalArgumentException.
Does the validation code increase the size of the object?
However, the answer to your second question is No. To understand why, you have to know what Object Oriented Programming is.
Some references:
http://en.wikipedia.org/wiki/Object-oriented_programming
http://en.wikipedia.org/wiki/Class_(computer_science)
Should I make validation code as private helper methods or create a
separate static helper class?
It depends if you think that you'll need to reuse the same method also in another class for the same purpose(input validation) it is better write the method in a separate static helper class so you can reuse the method and maintain it easily.
If you write the same private helper method in several class each time that you need to make a changes you have to edit each method in each class, with a static helper class you change the code in one place only ...
Read about PropertyChangeListener and Bean Validation.
I tend to validate within the get() and set() methods wherever possible - calling external static methods for common tasks such as checking dates or cleaning input (i.e. to avoid sql injection)
If you only use (and are only ever going to use) the validation within one class, keep it as a private helper method. If in doubt, I tend to pull the functionality out into a static helper class. It makes very little difference to the amount of code, is no more effort to implement, and is much more flexible.
The short answer is: you should implement your validation code the way that your framework tells you to. Typically, this is a public method or an annotation. An interface could work too. If you add code, your class size will increase.
Data validation should be automatically called by your software's infrastructure. This helps to prevent programmers from forgetting to call the appropriate code. So, the methods should be public (an interface would work too).
Frameworks like Struts, Spring, Hibernate and have their own validation systems. Java EE leverages bean validation.
I recommend bean validation, because it performs validation regardless of the input source. When most people think of input validation, they think of data coming from the user e.g. HTTP Request, command console, Swing text field. Spring and Struts validation is often fine for those situations. But in long lived programs developed for enterprises, other data feeds often get introduced e.g. SQL database updates from another programs, database restoration after a crash, enterprise service bus, JMS.
That is why I prefer bean validation. The downside is that "safe sources" (data that you know is untainted) are validated unnecessarily. But with today's processing power, that should rarely be a significant concern.
Java EE Tutorial

Categories

Resources