HashMap change Values Object - java

I have a set with String and i want to create hash map with String key and Node Object value.
and this is my code
Set<String> cities = new HashSet<>();
Map<String, Node> allCity = new HashMap<>();
Iterator<String> c = cities.iterator();
while(c.hasNext()){
String name = c.next();
Node cit = new Node(name);
allCity.put(name, cit);
}
my problem is when i read first from c iterator and correctly make new object and put it to hash map but when second object was create in my hash map the previous object value was change like this
first read
key = "New York"
Value = Node (and the value of node is New York)
second read
Key = "Los Angles"
Value = Node (and the value of node is Los Angles)
and my first read Value with New York key was change to Los Angles.
myNode class
public class Node{
private static String city;
private static double pathCost;
private ArrayList<Edge> neighbours;
private Node parent;
public Node(String cityName){
city = cityName;
neighbours = new ArrayList<>();
}
public static String getValue() {
return city;
}
public static void setValue(String city) {
Node.city = city;
}
public static double getPathCost() {
return pathCost;
}
public static void setPathCost(double pathCost) {
Node.pathCost = pathCost;
}
public static String getCity() {
return city;
}
public static void setCity(String city) {
Node.city = city;
}
public ArrayList<Edge> getNeighbours() {
return neighbours;
}
public void setNeighbours(ArrayList<Edge> neighbours) {
this.neighbours = neighbours;
}
public void addNeighbours(Edge n){
this.neighbours.add(n);
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
#Override
public String toString() {
return city;
}
}
Please help me.

That's because you made the city (and pathCost) fields static. A static field belongs to the class, not to a specific instance of this class. Each node has a specific city, so you want to mek the city field an instance field, and not a static field.
Read the Java tutorial about class members.

The city member in your Node class is static. This means all the Nodes share the same city, and when one instance updates it (e.g., in the constructor), the change applies for all of them.
To resolve this issue, you could change city to be an instance member:
public class Node{
private String city;
...

Without looking thoroughly there is a major mistake here:
private static String city;
city is node (i.e. instance) data and should not be static.
Since it is static in your case, all nodes share one value for city, which most probably isn't what you want. The same applies to pathCost.

Related

Java Vector: Each element contains three objects. How to operate based on the value of one of them?

For example, I have vector(object1, object2, price). How can I print elements where price > 100?
All the tutorials and documents (concerning operating in such way) I have seen only handle vectors where each element contains only one object.
So how can I get a handle on one specific object inside element? Or is this even possible?
A side question: what are those called? That is, if a single element is comprised of several items, what are those items called? Like in databases, a record is comprised of fields. Hard to google stuff you do not know the name of.
Main:
import java.util.Vector;
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String type;
String location;
double value;
System.out.print("type->");
type=sc.nextLine();
System.out.print("location->");
location=sc.nextLine();
Property prop=new Property(type,location);
System.out.print("value->");
value=sc.nextDouble();
InsuranceInfo insu=new InsuranceInfo(prop,value);
container.addInsuranceInfo(insu);
}
InsInfoContainer class:
public class InsInfoContainer {
private Vector<InsuranceInfo> container;
public InsInfoContainer() {
container = new Vector<>(3, 1);
}
public void addInsuranceInfo(InsuranceInfo insu) {
container.addElement(insu);
}
public void print() {
Iterator<InsuranceInfo> iter = container.iterator();
while (iter.hasNext()) {System.out.println(iter.next());}
}
InsuranceInfo class:
public class InsuranceInfo {
public InsuranceInfo(Property prop, double value) {
this.prop = prop;
this.value = value;
}
private Property prop;
private double value;
public Property getProp() {return prop;}
public void setProp(Property prop) {this.prop = prop;}
public double getValue() {return value;}
public void setValue(double value) {this.value= value;}
}
Property class:
public class Property {
private String type;
private String location;
public Property(final String type, final String location) {
this.type = type;
this.location = location;
}
public String getType() {return this.type;}
public void setType(final String type) {this.type = type;}
public String getLocation() {return this.location;}
public void setLocation(final String sijainti) {this.location = location;}
}
You have a container to store your InsuranceInfo:
private Vector<InsuranceInfo> container;
Your container is called Collection
Your InsuranceInfo instances inside your container are called element
Your "items" inside InsuranceInfo (Property, value) are called property or field of element
To iterate over your container collection, the usual ways are using for loop or foreach loop:
public void print() {
for (InsuranceInfo element: container) {
if (element.getValue() > 100) { // Here is your condition to filter elements
// Process your elements here
}
}
}
You can also use Iterator, Stream to do that.

Need to Remove Duplicate from List

I have a list of objects in ArrayList.I want to remove the duplicate object in the list based on old paymentDate.For an Example, if the member (Vishal) repeated two times I need to remove the Vishal object based on old paymnetDate from the list.
[{CreditCardNum,name,Amount,DueDate,PaymentDate}]
masterlist = [{4123456789123456,Vishal,80000,03/06/2015,07/06/2015},
{4123456789123456,Vivek,80000,07/06/2015,11/06/2015},
{4123456789123456,Vishal,80000,03/06/2015,09/06/2015}];
Removable Object from List =
{4123456789123456,Vishal,80000,03/06/2015,07/06/2015}
List<CreditcardVo> masterlist =new ArrayList<CreditcardVo>();
public class CreditCardVO {
public String creditNumber;
public String name;
public int amount;
public Date dueDate;
public Date paymentDate;
public String getCreditNumber() {
return creditNumber;
}
public void setCreditNumber(String creditNumber) {
this.creditNumber = creditNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public Date getDueDate() {
return dueDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
public Date getPaymentDate() {
return paymentDate;
}
public void setPaymentDate(Date paymentDate) {
this.paymentDate = paymentDate;``
}
}
Here is the algorithm that you can use to do that:
First You need a unique identifier for each of the object in the ArrayList. The identifier can me the name if you are sure that the name does not repeat.
Step 1: Create an empty map where the key is the object identifier and the value will be the object itself
Step 2: For each element, in ArrayList :
Check if the map contains the identifier of the object
If yes then get the value val associated to that identifier in the map and compare it its date with the date of your current object curr:
if val has the latest date then do nothing
if curr has the latest date then call map.put(identifier, curr) to update the value in the map
If no, then map.put(identifier, curr) to add the current object to the map
At the end, the result will be the values of the map. And you can get that by using map.values()
You can create a method as such:
List<CreditCardVO> getDistinctObjectsByName(List<CreditCardVO> cardVOS){
Collection<CreditCardVO> resultSet =
cardVOS.stream()
.collect(Collectors.toMap(CreditCardVO::getName, Function.identity(),
(left, right) ->
left.getPaymentDate().after(right.getPaymentDate()) ?
left : right
)).values();
return new ArrayList<>(resultSet);
}
which given a list of CreditCardVO will return a new list with distinct objects with the latest payment date.

Object to string delimited format

I have set of objects of different types.
Ex : Employee emp, adress adr
These two classes have list of properties
public class Employee{
private Stringname;
private int age;
}
public class Adress {
private String HouseNo;
private string Street;
private string pin;
}
Each attribute is assigned with some 2 character value
Name (NA), age (AG), HouseNo(HN),Street(ST), pin(PN)
I need to construct a string with these data and delimit with a %
Output:
NA%Vidhya%AG%30%HN%80%ST%1st cross%PN%100100
Each class knows it own data best so I would let each class be responsible for generating the string. As I understand it the two char codes for each field are unique for each class and member and only used when generating the string so only the class would need them.
interface AttributeDescription {
String generateDescription();
}
public class Employee implements AttributeDescription {
//members...
public String generateDescription() {
return String.format(“NA%%%s%%AG%%%d”, name, age)
}
Then simply call this method for all objects implementing the interface.
AttributeDescription object = ...
String attr = object.generateDescription();
I don't think it can be generalized more than this given the requirements.
Update
It might be better to have a builder class for building the string to get a more unified behavior between classes. Here is an example
public class AttributeBuilder {
private builder = new StringBuilder();
public String getAttribute() {
return builder.toString();
}
public void add(String code, String value) {
if (value == null) {
return;
}
builder.append(code);
builder.append(‘%’);
builder.append(value);
builder.append(‘%’);
}
}
And then you would also have to implement add(...) methods for other data types in a similar fashion. The builder could then be used like
public String generateDescription() {
AttributeBuilder builder = new AttributeBuilder();
builder.add(“NA”, name);
builder.add(“AG”, age);
return builder.getAttribute();
}

Is there a way to share elements of overlapping maps?

This a little something I stumbled upon while programming and I wonder whether anyone could provide me with some insights here.
Imagine you have some enum-like classes, i.e. classes with loads of instances defined as constants of the class. As an example consider something like
public class ChildName {
private static final Map<String, ChildName> LUT = new TreeMap<>();
private final String name;
private ChildName(String name) {
this.name = name.toLowerCase();
LUT.put(name, this);
}
public static Collection<ChildName> getNames() {
return LUT.values();
}
public static ChildName fromValue(String name) {
return LUT.get(name);
}
public static final ChildName SARAH = new ChildName("Sarah");
public static final ChildName MEGAN = new ChildName("Megan");
public static final ChildName SANDY = new ChildName("Sandy");
public static final ChildName JOHN = new ChildName("John");
public static final ChildName BORIS = new ChildName("Boris");
// etc...
}
Now, one could argue that it might be necessary to split up between boy's names and girl's names (or consider names from different countries or whatever, you get the idea). The idea would be that you can still list all of the possible names, but also all the names for boys or all the names for girls. This could be done with something like
public class ChildName {
private static final Map<String, ChildName> LUT = new TreeMap<>();
private final String name;
protected ChildName(String name) {
this.name = name.toLowerCase();
LUT.put(name, this);
}
public static Collection<ChildName> getNames() {
return LUT.values();
}
public static ChildName fromValue(String name) {
return LUT.get(name);
}
// maybe here there are some gender-neutral names as constants left
public static final ChildName ALEX = new ChildName("Alex");
}
public class GirlsName {
private static final Map<String, ChildName> LUT = new TreeMap<>();
private GirlsName(String name) {
super(name);
LUT.put(name, this);
}
public static Collection<ChildName> getNames() {
return LUT.values();
}
public static final ChildName SARAH = new ChildName("Sarah");
public static final ChildName MEGAN = new ChildName("Megan");
public static final ChildName SANDY = new ChildName("Sandy");
// etc...
}
public class BoysName {
private static final Map<String, ChildName> LUT = new TreeMap<>();
private BoysName(String name) {
super(name);
LUT.put(name, this);
}
public static Collection<ChildName> getNames() {
return LUT.values();
}
public static final ChildName JOHN = new ChildName("John");
public static final ChildName BORIS = new ChildName("Boris");
// etc...
}
which could lead to huge Maps in each of the classes with massive overlaps.
There is probably not that much of a problem concerning efficiency or memory in this case, but despite that, it is still quite redundant and does not feel pretty.
It can be argued that the Map in the upper class could be omitted (assume the gender-neutral names are just duplicated in the subclasses or so) and the collection of all results could be retrieved from combining the collections of the subclasses. However, I would like to avoid this approach from a design point of view (imagine how messy that might get in case of a subclass for each country on this planet).
A more elegant solution (in my eyes) would be to keep a Map in every class, but in such a way that they share entries. Now I was wondering whether someone would now if this could be possible using a basic Map implementation. Other suggestions to solve this kind of problem are of course also welcome.
PS: I am aware that my proposal for an elegant solution is in fact not that much better, but I just can't come up with a better idea and I can't stop wondering how such kind of map could be implemented
Go one step further than enum-like, and make them enums:
interface ChildName {}
enum GirlsName implements ChildName {
Sarah, Megan, Sandy
}
enum BoysName implements ChildName {
John, Boris
}
Now look up map is not needed:
ChildName name = BoysName.valueOf("Boris");
I'll let you write the code to find either boy's or girl's name.
I would suggest using an actual enum, and instead of grouping them into distinct classes, storing attributes such as country and gender on the ChildName class, then filtering and grouping as necessary.
public enum Gender {
MALE, FEMALE
}
public enum Country {
USA, CA, UK
}
public enum ChildName {
SARAH(FEMALE, USA),
MEGAN(FEMALE, CA),
SANDY(FEMALE, UK),
JOHN(MALE, USA),
BORIS(MALE, UK);
private static final Map<String, ChildName> LUT;
static {
LUT = Array.stream(values())
.collect(Collectors.groupingBy(c -> c.name().toLowerCase()));
}
public static Collection<ChildName> getNames() {
return Arrays.asList(values());
}
public static ChildName fromValue(String name) {
return LUT.get(name.toLowerCase());
}
// some examples of filtering and grouping
// if necessary, they can be cached statically (like LUT)
public static List<String> getMaleNames() {
return Arrays.stream(values())
.filter(c -> c.getGender() == MALE)
.map(ChildName::name)
.collect(Collectors.toList());
}
public static Map<Gender, List<ChildName>> getGenderMapForCountry(Country country) {
return Arrays.stream(values())
.filter(c -> c.getCountry() == country)
.collect(Collectors.groupingBy(ChildName::getGender));
}
private final Gender gender;
private final Country country;
ChildName(Gender gender, Country country) {
this.gender = gender;
this.country = country;
}
public Gender getGender() {
return gender;
}
public Country getCountry() {
return country;
}
}

Collection with multiple values in key

I'm looking for a Collection type data structure to implement the following. Say I have a class like this:
class Person() {
String homeTown; // key
String sex; // key
String eyeColour; // key
String name;
long height;
// other stuff....
}
I am processing multiple Person objects. I want to organise them into sets whereby each set contains Person objects with the same homeTown, sex and eyeColour. At the moment I am implementing something like this:
Map<String, HashSet<Person>> = new HashMap<String, HashSet<Person>>;
where the key is a concatanation of the homeTown, sex and eyeColour. This works but seems a bit untidy - can anyone suggest a more elegant solution or a better data structure to use, thanks?
You could restructure your class to make the key explicit. This is more robust than simply concatenating the key values and avoids any additional object creation overhead at the point when you wish to store your Person instance in a Map, because you've eagerly created the key in advance.
public class Person {
public class Key {
private final String homeTown;
private final String sex;
private final String eyeColour;
public Key(String homeTown, String sex, String eyeColour) { ... }
public boolean equals(Object o) { /* Override to perform deep equals. */ }
public int hashCode() { /* Could pre-compute in advance if the key elements never change. */ }
}
private final Key key;
private final String name;
private final long height;
public Person(String homeTown, String sex, String eyeColour, String name, long height) {
this.key = new Key(homeTown, sex, eyeColour);
this.name = name;
this.height = height;
}
public Key getKey() {
return key;
}
public String getName() { return name; }
public long getHeight() { return height; }
}
Create an object to model your key. For example class PersonKey { String homeTown, sex, eyeColour } (getters and setters omitted for brevity)
Implement the equals and hashCode method for this object.
Use this object as the key in your Map.
Either remove the attributes from your Person object or replace them with a reference to your PersonKey object.
In addition, consider making the type of your map the following i.e. you don't need to specify what type of Set you are using as the key to your map.
Map<String, Set<Person>> = new HashMap<String, Set<Person>>();
And, if you are using a Set<Person> then you'll need to override equals and hashCode for the Person as well, otherwise the Set cannot correctly determine if two Person objects represent the same person or not, which is needed to make sure the collection contains only unique elements.
org.apache.commons.collections.map.MultiValueMap
You can use guava's Sets.filter method to filter the person objects.
Example:
Person class:
public class Person {
String name;
String hometown;
int age;
public Person(String name, String hometown, int age) {
this.name = name;
this.age = age;
this.hometown = hometown;
}
#Override
public int hashCode() {
int hash = 17;
hash = 37 * hash + name.hashCode();
hash = 37 * hash + hometown.hashCode();
hash = 37 * hash + age;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
Person p;
if (obj instanceof Person)
p = (Person) obj;
else
return false;
if (this.name.equals(p.name) && this.hometown.equals(p.hometown)
&& this.age == p.age)
return true;
return false;
}
#Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append("[name = ").append(name).append("\n");
b.append("home town = ").append(hometown).append("\n");
b.append("age = ").append(age).append("]");
return b.toString();
}
}
TestGuavaFilter class:
public class TestGuavaFilter {
public static void main(String[] args) {
Set<Person> set = new HashSet<Person>();
set.add(new Person("emil", "NY", 24));
set.add(new Person("Sam", "NY", 50));
set.add(new Person("george", "LA", 90));
System.out.println(Sets.filter(set, new FilterHomeTown("NY")));
}
}
class FilterHomeTown implements Predicate<Person> {
String home;
public FilterHomeTown(String home) {
this.home = home;
}
#Override
public boolean apply(Person arg0) {
if (arg0.hometown.equals(this.home))
return true;
return false;
}
}
The advantage of using a filter is that you can filter Person object in any way ,suppose you want to filter only using home-town and not the other 2 attributes this will helpful.More over since guava's filter only produces a view of the the real Set,you can save memory.

Categories