So, I have two Sets with elements of my class Capability.
public class Capability {
private String name;
public Capability(){
//
}
public Capability(String name){
this.name = name;
//this.id = count.getAndIncrement();
}
public String getName(){
return name;
}
#Override
public String toString(){
return "Capability: "+name+".";
}
}
Please disregard the value of this class over a String, this is for future expansion.
I'm trying to compare two sets that I've gotten from importing a json file, so they are not the same object, nor contain the same object, just have the same content.
public boolean allCapabilitiesMet(){
int count = 0;
for(Capability taskCap : this.getReqCapabilities()){
for(Capability primCap : this.getPrimitive().getCapabilities())
{
System.out.println(taskCap.equals(primCap));
System.out.println(taskCap.getName().equals(primCap.getName()));
if(taskCap.equals(primCap)){
count++;
}
}
}
return count == this.getReqCapabilities().size();
//return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());
}
The goal is to see if one set is a subset of the other, which I could do with the commented return before I switched to importing from the json file.
The thing is, I could fix this right now by simply changing the if clause to the string comparison, because that does indeed work. This would be terrible once I start adding other fields to the main class.
Is there anything I can do to compare the sets content without manually checking their content?
So I just replaced the equals() and hashCode() methods in Capability after adding an id field.
#Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null || obj.getClass() != this.getClass())
return false;
Capability cap = (Capability) obj;
return (cap.getName().equals(this.getName()) && cap.getId() == this.getId());
}
#Override
public int hashCode()
{
return (int) this.id;
}
With this, I can use the solution that I'd originally planned for the comparison
public boolean allCapabilitiesMet(){
return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());
}
Is there any issue with this implementation? Sadly, I'll have to add a term to the if statement everytime I want to add a field to Capability. Is there any other way?
I have a SmsClass:
public class SmsClass {
private String numberInside;
private String name;
public SmsClass( String numberInside ,String name) {
this.numberInside = numberInside;
this.name = name;
}
and I try to make two same ArrayList of this class:
SmsClass SmsClass3 = new SmsClass("name" , "19");
SmsClass SmsClass4 = new SmsClass("name" , "19" );
ArrayList<SmsClass> c1 = new ArrayList<>();
ArrayList<SmsClass> c2 = new ArrayList<>();
c1.add(SmsClass1);
c1.add(SmsClass2);
c2.add(SmsClass3);
c2.add(SmsClass4);
I have problem with .contains method . When I run this code :
for(int i = 0 ; i < c1.size() ; i++){
if (c1.contains(c2.get(i))) {
System.out.println("victory");
}
}
I have same arrays but nothing found.
You should override this equals method like this in SmsClass;
public class SmsClass {
private String numberInside;
private String name;
public SmsClass(String numberInside, String name) {
this.numberInside = numberInside;
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SmsClass)) return false;
SmsClass smsClass = (SmsClass) o;
if (numberInside != null ? !numberInside.equals(smsClass.numberInside) : smsClass.numberInside != null)
return false;
return name != null ? name.equals(smsClass.name) : smsClass.name == null;
}
}
Just an idea, you can check easily without a for loop equations of two list .
c1.removeAll(c2);
if (c1.isEmpty()) {
System.out.println("victory!");
}
You must define equals in your Object.
Something like this:
public class SmsClass {
private String numberInside;
private String name;
public SmsClass( String numberInside ,String name){
this.numberInside = numberInside;
this.name = name; }
public boolean equals(Object obj) {
if(obj instanceof SmsClass ) {
SmsClass smsObj = (SmsClass)obj;
if(smsObj.getNumberInside() == this.getNumberInside() &&
smsObj.getName() == this.getName())
return true;
}
return false;
}
}
You have not defined equals (and implicitly hashCode), thus contains can not compare your Objects. In case you do not override those both method: Object::equals will be used (which just uses reference comparison, via ==) and hashCode (in java-8) will be computed as a pseudo-random number (based on Marsaglia XOR shift algorithm).
Variable names should not start with capital letter as recommendation.
Also, you added SmsClass1, and SmsClass2 to c1 list, while adding SmsClass3, and SmsClass4 to c2 list. Although, smsClass1 and smsClass3 have same values in their fields, they are stored on different part of memory. ArrayList.contains() method check equality according to elements' references(where they placed in memory).
SmsClass SmsClass3 = new SmsClass("name" , "19");
SmsClass SmsClass4 = new SmsClass("name" , "19" );
ArrayList<SmsClass> c1 = new ArrayList<>();
ArrayList<SmsClass> c2 = new ArrayList<>();
c1.add(SmsClass1);
c1.add(SmsClass2);
c2.add(SmsClass3);
c2.add(SmsClass4);
I have a class named SampleEntity i.e a POJO which will help me create my dynamoDB table.The hash key and range key have been defined clearly in POJO object but still i get an exception that the hash key is not being defined
#DynamoDBTable(tableName = "sampletable1")
public class SampleEntity {
public static final String HASH_KEY = "f1_hash";
public static final String RANGE_KEY = "f2_range";
#DynamoDBAttribute(attributeName = HASH_KEY)
#DynamoDBHashKey
private Integer feild1;
#DynamoDBAttribute(attributeName = RANGE_KEY)
#DynamoDBRangeKey
private String field2;
#DynamoDBAttribute(attributeName = "f3")
private String feild3;
#DynamoDBAttribute(attributeName = "f4")
private String feild4;
#DynamoDBAttribute(attributeName = "f5")
private String feild5;
public Integer getFeild1() {
return feild1;
}
public void setFeild1(Integer feild1) {
this.feild1 = feild1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
public String getFeild3() {
return feild3;
}
public void setFeild3(String feild3) {
this.feild3 = feild3;
}
public String getFeild4() {
return feild4;
}
public void setFeild4(String feild4) {
this.feild4 = feild4;
}
public String getFeild5() {
return feild5;
}
public void setFeild5(String feild5) {
this.feild5 = feild5;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SampleEntity)) return false;
SampleEntity that = (SampleEntity) o;
if (!getFeild1().equals(that.getFeild1())) return false;
if (!getField2().equals(that.getField2())) return false;
if (!getFeild3().equals(that.getFeild3())) return false;
if (!getFeild4().equals(that.getFeild4())) return false;
return getFeild5().equals(that.getFeild5());
}
#Override
public int hashCode() {
int result = getFeild1().hashCode();
result = 31 * result + getField2().hashCode();
result = 31 * result + getFeild3().hashCode();
result = 31 * result + getFeild4().hashCode();
result = 31 * result + getFeild5().hashCode();
return result;
}
}
This my class and i am issuing a create table request on this class but i got DynamoDBMappingException that is no HASH key value present.
server = ServerRunner.createServerFromCommandLineArgs(new String[]{"-inMemory", "-port", "8005"});
server.start();
dynamoDBClient = new AmazonDynamoDBClient(new BasicAWSCredentials("any", "thing")).withEndpoint("http://localhost:8005");
dbMapper = new DynamoDBMapper(dynamoDBClient);
CreateTableRequest createTableRequest = ddbMapper.generateCreateTableRequest(SampleEntity.class);
createTableRequest.setProvisionedThroughput(new ProvisionedThroughput(5L, 5L));
dynamoDBClient.createTable(createTableRequest);
SampleLoginEntity data= new SampleLoginEntity();
data.setLogin(123);
data.setField2("range");
data.setFeild3("abc");
dbMapper.save(data);
There are two possible issues I can see (one that I ran into recently), but your setup is a little different than mine.
You're using both #DynamoDBAttribute and #DynamoDBHashKey on a single item - that's not necessary, and might be messing it up, though I don't have time to test it right now. You should be able to just do, #DynamoDBHashKey(attributeName=HASH_KEY) and you'll be fine. I think as is, you might be declaring an attribute as "f1_hash", and a hash key named as "field1", both mapping to the same internal value (though I could be wrong).
The issue I was having though is actually a result of this error message being really poorly worded - it will throw this exception when you call dbMapper.save() with an object with the hash key value set to null, though if your setLogin() was supposed to be setField1() that shouldn't be the issue here.
I got the same exeption when tried to get the record by the null hashCode:
myClassMapper.load(MyClass.class, null))
Try to set:
data.setField1("some_hash");
I have two classes that represent two different database entities. Their relationship is 1:m in db and it is represented in class structures something like this:
public class Company {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
public class Employee {
private Company company;
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
Now I want to override equals/hashCode on these classes. Eclipse generates the following code for me:
public class Company {
private List<Employee> employees;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((employees == null) ? 0 : employees.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;
Company other = (Company) obj;
if (employees == null) {
if (other.employees != null)
return false;
} else if (!employees.equals(other.employees))
return false;
return true;
}
}
public class Employee {
private Company company;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((company == null) ? 0 : company.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;
Employee other = (Employee) obj;
if (company == null) {
if (other.company != null)
return false;
} else if (!company.equals(other.company))
return false;
return true;
}
}
If I run the following test:
public class EqualsTest {
#Test
public void testEquals() {
Company company1 = new Company();
Employee employee1 = new Employee();
employee1.setCompany(company1);
company1.setEmployees(Arrays.asList(employee1));
Company company2 = new Company();
Employee employee2 = new Employee();
employee2.setCompany(company2);
company2.setEmployees(Arrays.asList(employee2));
assertThat(company1, is(company2));
}
}
I expect it to pass because both company1 and company2 have equal lists of employees, but it fails with StackOverflowError:
java.lang.StackOverflowError
at java.util.AbstractList$Itr.<init>(AbstractList.java:318)
at java.util.AbstractList$Itr.<init>(AbstractList.java:318)
at java.util.AbstractList$ListItr.<init>(AbstractList.java:377)
at java.util.AbstractList.listIterator(AbstractList.java:315)
at java.util.AbstractList.listIterator(AbstractList.java:284)
at java.util.AbstractList.equals(AbstractList.java:502)
at com.test.Company.equals(Company.java:37)
at com.test.Employee.equals(Employee.java:35)
at java.util.AbstractList.equals(AbstractList.java:507)
at com.test.Company.equals(Company.java:37)
at com.test.Employee.equals(Employee.java:35)
at java.util.AbstractList.equals(AbstractList.java:507)
at com.test.Company.equals(Company.java:37)
at com.test.Employee.equals(Employee.java:35)
...
I understand that the reason for this failure is cross reference in classes and thus equals/hashCode methods. But how should I implement equals/hashCode to avoid infinitive recursion?
As it is now, the identity of a company is defined solely by its employees. Likewise, the identity of an employee is defined solely by its company. Do you see how that leads to a mutual logical dependency?
You need to break that logical dependency in your code. How would you logically uniquely identify a company and an employee? Typically you'd do this with some sort of meaningful unique identifier: a name (string), a number (int/long), or some similar combination of primitive fields.
Imho there are 2 versions available. I assume company should be the "leading" class, storing the employees.
version: In the employee equals, use the "==" to check for object equality on company (not very nice)
version: assign your company a unique ID and compare that only that company ID in employee equals
hth
Do not compare the list of employees within the Company.equals method. Are there other attributes of Company that are meaningful and could be used to perform the comparison within equals, like a name? Or Stock Symbol?
You have inadvertently set up a recursive dependency between Company and Employee. The Company#hashCode() method needs to compute the individual hashcodes of every Employee, and the Employee#hashCode() method depends on the Company's hashcode, leading to an infinite recursion.
A company object's hashcode should not depend on the employees in it. The hash code is in some sense the "identity" of the object, which shouldn't change when a new employee is added to it. Same for Employee. The Employee's identity shouldn't change just because he/she moves to a different company.
You'll have to redefine those methods in terms of some meaningful identity attribute. Your code doesn't show it, but both Company and Employee must have some other member variables, such as a name. Base the hashCode and equals implementations on that attribute.
I have these 4 hashmaps and use them in code so I can show the comparison in an excel sheet.
HashMap 1 - is with a key of unique id and value as another hashmap containing tagid as key and description of fields to compare.
[343, ((id_1,Plan Features),(a, Deductible),(b,Individual),(c,Family),(id_4,Individual Out-of-network),(id_2, Out-of-pocket Annual Maximum),(d,Individual),(e,Family),(u, Life Time Maximum))]
HashMap 2 - is with a key of unique id same as Hashmap 1 and value as another hashmap containing tagid as key and value of description used in Hashmap 1.
[343, ((id_1,""),(a, Calendar Year),(b,5000),(c,10000)(id_4,15000),(id_2,""),(d,5000),(e,10000),(u,"Unlimited"))]
Same is the case with HashMap 3 and HashMap 4
[347, ((id_1,Plan Features),(a, Deductible),(b,Individual),(id_5, Individual Out-of-network),(c,Family),(id_4,Family Out-of-network),(id_2, Out-of-pocket Annual Maximum),(d,Individual),(e,Family),(u, Life Time Maximum))]
[347, ((id_1,""),(a, Calendar Year),(b,7000),(id_5, 9000),(c,12000),(id_4,14000),(id_2, ""),(d,6000),(e,15000),(u, "Unlimited"))]
I want to show the comparison in an excel sheet by showing all descriptions in one column and respective values in another 2 columns.
I'd first suggest you to normalize your suboptimal data representation to something like below. Then you just need to maintain TWO Maps. Then is is easy to iterate between them and display whichever way you want.
If you can use google-guava library then it is even easier to group then by id using Multiset.
Below are highlevel details on my approach. You can use the return type of "reportBuilder.build(plan1, plan2)" and use Apache POI as suggested by others to create the excel
A Carrier offers 1 or more Plan's
Each Plan has and id and 1 or more Features
Each Feature has id, decsription, value
public class Main
{
private static Map> plan1Map;
private static Map> plan1AdditionalDetailsMap;
private static Map> plan2Map;
private static Map> plan2AdditionalDetailsMap;
private static Plan plan1;
private static Plan plan2;
public static void main(final String[] args)
{
initiaizeData();
normalizeData();
System.out.println(plan1);
System.out.println(plan2);
PlanComaprisionReportBuilder reportBuilder = new PlanComaprisionReportBuilder();
System.out.println(reportBuilder.build(plan1, plan2));
}
private static void normalizeData()
{
plan1 = buildPlan(plan1Map, plan1AdditionalDetailsMap);
plan2 = buildPlan(plan2Map, plan2AdditionalDetailsMap);
}
private static Plan buildPlan(final Map<String, Map<String, String>> planMap,
final Map<String, Map<String, String>> planAdditionalDetailsMap)
{
String planId = Iterables.getOnlyElement(planMap.keySet());
Plan plan = new Plan(planId);
Map<String, String> planDetails = planMap.get(planId);
Iterator<Entry<String, String>> features = planDetails.entrySet().iterator();
Map<String, String> additionalDetails = planAdditionalDetailsMap.get(planId);
while (features.hasNext())
{
Entry<String, String> entry = features.next();
String tagId = entry.getKey();
String tagDescription = entry.getValue();
String tagValue = additionalDetails.get(tagId);
plan.addFeature(new Feature(tagId, tagDescription, tagValue));
}
return plan;
}
private static void initiaizeData()
{
plan1Map = Maps.newHashMap();
Map map1Value = Maps.newTreeMap();
map1Value.put("id_1", "Plan Features");
map1Value.put("a", "Deductible");
map1Value.put("b", "Individual");
map1Value.put("c", "Family");
map1Value.put("id_4", "Individual Out-of-network");
map1Value.put("id_2", "Out-of-pocket Annual Maximum");
map1Value.put("d", "Individual");
map1Value.put("e", "Family");
map1Value.put("u", "Life Time Maximum");
plan1Map.put("343", map1Value);
plan1AdditionalDetailsMap = Maps.newHashMap();
Map<String, String> policy1ExtensionValue = Maps.newTreeMap();
policy1ExtensionValue.put("id_1", "");
policy1ExtensionValue.put("a", "Calendar Year");
policy1ExtensionValue.put("b", "5000");
policy1ExtensionValue.put("c", "10000");
policy1ExtensionValue.put("id_4", "15000");
policy1ExtensionValue.put("id_2", "");
policy1ExtensionValue.put("d", "5000");
policy1ExtensionValue.put("e", "10000");
policy1ExtensionValue.put("u", "Unlimited");
plan1AdditionalDetailsMap.put("343", policy1ExtensionValue);
plan2Map = Maps.newHashMap();
Map<String, String> policy2Value = Maps.newTreeMap();
policy2Value.put("id_1", "Plan Features");
policy2Value.put("a", "Deductible");
policy2Value.put("b", "Individual");
policy2Value.put("id_5", "Individual Out-of-network");
policy2Value.put("c", "Family");
policy2Value.put("id_4", "Family Out-of-network");
policy2Value.put("id_2", "Out-of-pocket Annual Maximum");
policy2Value.put("d", "Individual");
policy2Value.put("e", "Family");
policy2Value.put("u", "Life Time Maximum");
plan2Map.put("347", policy2Value);
plan2AdditionalDetailsMap = Maps.newHashMap();
Map<String, String> policy2ExtensionValue = Maps.newTreeMap();
policy2ExtensionValue.put("id_1", "");
policy2ExtensionValue.put("a", "Calendar Year");
policy2ExtensionValue.put("b", "7000");
policy2ExtensionValue.put("id_5", "9000");
policy2ExtensionValue.put("c", "12000");
policy2ExtensionValue.put("id_4", "14000");
policy2ExtensionValue.put("id_2", "");
policy2ExtensionValue.put("d", "6000");
policy2ExtensionValue.put("e", "15000");
policy2ExtensionValue.put("u", "Unlimited");
plan2AdditionalDetailsMap.put("347", policy2ExtensionValue);
}
}
public class Plan
{
private final String id;
private final Set<Feature> features = Sets.newHashSet();
public Plan(final String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void addFeature(final Feature f)
{
features.add(f);
}
public Set<Feature> getFeatures()
{
return Collections.unmodifiableSet(features);
}
#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(final Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
Plan other = (Plan) obj;
if (id == null)
{
if (other.id != null)
{
return false;
}
}
else if (!id.equals(other.id))
{
return false;
}
return true;
}
#Override
public String toString()
{
return "Plan [features=" + features + ", id=" + id + "]";
}
}
public class Feature
{
private final String id;
private final String description;
private final String value;
public Feature(final String id, final String description, final String value)
{
this.id = id;
this.description = description;
this.value = value;
}
public String getId()
{
return id;
}
public String getDescription()
{
return description;
}
public String getValue()
{
return value;
}
#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(final Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
Feature other = (Feature) obj;
if (id == null)
{
if (other.id != null)
{
return false;
}
}
else if (!id.equals(other.id))
{
return false;
}
return true;
}
#Override
public String toString()
{
return "Attribute [description=" + description + ", id=" + id + ", value=" + value + "]";
}
}
public class PlanComaprisionReportBuilder
{
Multimap<String, String> build(final Plan... plans)
{
Multimap<String, String> rows = ArrayListMultimap.create(100, plans.length);
for (Plan p : plans)
{
for (Feature f : p.getFeatures())
{
rows.put(f.getDescription(), f.getValue() != null ? f.getValue() : "");
// if (!rows.containsKey(f.getDescription()))
// {
// }
// else
// {
// existing row needs separate handling
// }
}
}
return rows;
}
}
So you have two sets of hashmaps you want to compare in an excel file and both sets might or might not have the same informations in it... (and lets assume that if they have the same information, they might or not have the same keys in the maps)
I'm not sure I get what is the problem you're stuck on exactly, but here is how I would quickly go about this.
I would have a small class holding the row label ("Plan Features", for example), and holding the values of both maps you want to compare (valA, valB, for example), so something like this:
class ThisIsARow {
String label, valA, valB;
}
I would combine both sets of hashmaps in a resulting one HashMap<String, ThisIsARow> for which the key would be the label itself.
I would then loop through the first set of hashmaps, creating new instances of ThisIsARow, setting their label and valA values for each.
Then I would loop through the second set of hashmaps, looking first if there is already a ThisIsARow instance in the resulting HashMap<String, ThisIsARow> for each label, creating and adding a new one (setting its label and valB) if there's none yet for this label, or else just set the valB of the existing ThisIsARow instance.
Then I'd use Apache POI to write everything down in an Excel file. (You then only have to loop through the resulting hashmap, printing one instance of ThisIsARow per row.)
label valA valB
label valA valB
label valA valB
label valA valB
...
I hope this helps. Let me know if you need clarifications or if I'm offtrack!