Specific compare/equals for List.contains(obj) - java

Hi#all and thx in advance,
i currently wondering if there is a great best practice for my situation.
Consider u have an object. Let's say an object of type Customer.
Within a Customer object u have (n-1) fields.
Now u are implementing the hashCode and equals method via eclipse context menu >> Sources >> Generate hashCode() and equals()...
It uses all (n-1) fields to do so. Which is actually not really a bad in the general case.
Additional in a seperate service class within a specific method u have a list of Customers >> List myCustomers.
In this method u implement an if-else case with the condition myCustomers.contains(specificCustomer).
if (myCustomer.contains(specificCustomer)) {
// todo
} else {
// todo
}
So the list.contains(obj) uses internally the equals method of the object. This is the general way to check if a list contains an object.
BUT
In my case i've the standard hashCode and equals allready implemented with all (n-1) fields. And what i want, is to use a/the .contains(obj) method, which checks only specific fields of the object, for example (n-5) fields.
I don't want to adapt the existing hashCode and equals, because other parts of the code allready using this. And if i do so, i can not predict the behavior afterwards.
Also i don't want to write a seperate method within the Customer class and use it only in the if-else-condition.
So, does anyone has an idea, best practice or great pattern to get this done?

You want a specific piece of business logic (the n-5 field equals) to be used so you will have to wrte a specific piece of code somewhere. The simplest which comes to mind is to replace the standard contains call with a custom method which iterates over the list and checks if there is an item which matches using the custom equals logic. If you need this version of equals in more places you could extract it into a separate utility or service class.

Related

Comparing objects where almost all fields are same

In unit tests I usually use something like
assertThat(someObject).isEqualTo(someOtherObject);
to make sure these two objects have identical content. But what to do in case objects have identical content except certain fields?
Normally it would be like that:
assertThat(someObject.getFirstField()).isNotEqualTo(someOtherObject.getFirstField());
assertThat(someObject.getLastField()).isNotEqualTo(someOtherObject.getLastFieldd());
// and then gazilion fields that should be equal
assertThat(someObject.getNthField()).isEqualTo(someOtherObject.getNthField());
// ...
For obvious reasons, it is very unwieldy for bigger classes with a lot of fields. Is there way to specify that you expect certain fields to be not equal, but rest equal?
Both someObject and someOtherObject are same class that is Lomboked, so equals() is automatically handled.
If you are open to using assertJ then there is a very simple solution to your problem. Use
assertThat(someObject).isEqualToIgnoringGivenFields(someObjectOther, "firstField", "lastField")
Bear in mind that this uses reflection internally and failures can happen if you change the name of your fields inside the class which you want to ignore.
More on this Field by field comparisons

Sorting rest get request results by field passed as a parameter

I am currently working on a Rest API, in a get method which suppose to return an Array of objects in json format I now have the requirement to sort the result by a field passed as a parameter to the method. Consider for example the object to be
public class ExampleType {
int firstField ;
String secondField ;
}
Now according to the requirements the Rest API user should be able to pass as a parameter among other things either "firstField" or "secondField" and I should be sorting the array containing the result objects using this field.
Apparently my model is not so simplistic as the example, I do have more than 15 fields which could potentially be the one that I need to sort by, so an else if statement is not a choice at this point. My question is does anybody had a similar requirement for a rest api and if so how did you tackle it ? Or any recommendation on what could potentially by an elegant solution to my problem would be greatly appreciated.
You should create a Comparator and then use this to sort your data.
The comparators could be stored in a static map to avoid a switch/case if/else:
map.put("fieldName", Comparator.comparing(ExampleType::getFirstField));
You can combine two or more comparators using the thenComparing method.
The only other option is to create the appropriate comparators using reflection.
Note: requirements of API consumers often are not requirements that should be implemented in the API itself. You may also consider that sorting output is in fact a display problem and not something that an API needs to be concerned with.
It depends on the situation though, if data needs to be paginated then you may have no option other than to sort at the API level.

Should I compare all fields in my class's "equals" method?

I'm working on an application that allows the user to manage accounts. So, suppose I have an Account class, representing one of the user's accounts:
class Account
{
public int id;
public String accountName;
public String accountIdentifier;
public String server;
public String notes;
}
My equals method looks like this:
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || !(o instanceof Account))
return false;
Account other = (Account) o;
if (!accountIdentifier.equals(other.accountIdentifier))
return false;
if (!server.equals(other.server))
return false;
return true;
}
As you can see, I'm only comparing the accountIdentifier and the server, but not the other fields. There are several reasons why I chose this approach.
I keep the accounts in a List. When the user updates an account, by changing the account name (which is just a name specified by the user to identify the account) or the notes, I can do accountList.set(accountList.indexOf(account), account); to update the account in the list. If equals compared all properties, this approach wouldn't work, and I'd have to work around it (for example by iterating over the list and checking for these properties manually).
This might actually be more important, but it only came to my mind after thinking about it for a while. An Account is uniquely identified by the accountIdentifier and the server it belongs to. The user might decide to rename the account, or change the notes, but it's still the same account. But if the server is changed, I think I would consider it a different account. The id is just an internal ID since the accounts are stored in a database. Even if that changed, the account is still considered the same account if the accountIdentifier and the server stayed the same.
What I'm trying to say is that I basically implemented equals this way to allow for shorter, more concise code in the rest of the application. But I'm not sure if I'm breaking some rules here, or if I'm doing something that might cause other developers headaches if it ever happens that someone is working with my application's API.
Is it okay to only compare some fields in the equals method, or should I compare all fields?
Yes, it's definitely okay to do this. You get to decide what equality means for your class, and you should use it in a way that makes the most sense for your application's logic — in particular, for collections and other such classes that make use of equality. It sounds like you have thought about that and decided that the (server, identifier) pair is what uniquely distinguishes instances.
This would mean, for instance, that two instances with the same (server, identifier) pair but a different accountName are different versions of the same Account, and that the difference might need to be resolved somehow; that's a perfectly reasonable semantic.
It may make sense to define a separate boolean allFieldsEqual(Account other) method to cover the "extended" definition, depending on whether you need it (or would find it useful for testing).
And, of course, you should override hashCode to make it consistent with whatever definition of equals you go with.
You should compare all of the fields that are necessary to determine equality. If the accountIdentifier and server fields are enough to determine if two objects are equal, then that is perfectly fine. No need to include any of the other fields that don't matter in terms of equality.
For the key normally you should use the business key, this key can be simple or composite key and not necessary need to include all the fields in the entity. So... depends of each case to select what identify an entity. If possible should be the minimum number of field fully and unique identify the entity.
Some people prefer (and is a good practice) to create a surrogate key that will identity the object, this is very useful when you want to persist your objects using any ORM due you don’t need to export the keys to the child entities in 1:M or M:N relations. For example the ID in your sample can be considered as surrogate key if you create it as internal unique identifier.
Also may want to take into consideration:
Always you override equals you must override hashCode too, this is important to work properly with classes like Collections, Maps etc
Apache provide a really nice API to help in the implementation of equals and hashCode. Those classes are EqualsBuilder and HashCodeBuilder. Both allow you to concatenate the fields you want to use in your comparison and have a way also to use reflection.
The answer is "it depends depends on the semantics of your data".
For example, you might internally store a field that can be derived (calculated) from the other fields. In which case, you don't need to compare the calculated value.
As a gross generalisation, anything that cannot be derived from other fields should be included.
This is fine - and probably a good thing to do. If you've identified equality as the accountIdentifier and the server being distinct and unique, then that's perfectly valid for your use case.
You don't want to use more fields than you need to since that would produce false positives in your code. This approach is perfectly suitable to your needs.

4 Key Value HashMap? Array? Best Approach?

I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.

what is the best way to compare two complex java object and generate event depending upon comparision

I have a requirement to compare two complex object, e:g
Policy{
Private Vehicle-information info1;
private Driver-information info2;
...
}
I have two populated instance of this class. I want to compare those instance and depending upon difference I need to show them in UI marked in colors using some flag.
What is the best way to compare these objects. Can we achieve it using XML because java code will be complex.
Override the equals() and hashCode() method in your Policy class. Then you can check for equality like:
if(object1.equals(object2)) {
// do something
}
Implement Comparable and override the compareTo() method if you need to order the objects.
One solution: use Jackson to serialize your objects as JSON, then use this: it is a Java implementation of JSON Patch which also can generate differences between two JSONs as JSON Patches.
Which means you can know what has changed and where. And since this is JSON, you can send the result to your browser and have it handled by some JavaScript code easily. Unlike XML!

Categories

Resources