I am overriding equals method of a class to compare two objects since I want to compare all the fields of it. If two objects are unequal, is there a way to find out which of the fields were unequal due to which the objects are unequal?
You could write a method in the class that returns an object of the same type with either the difference or null for each data member. Or you can find a library that does it for you. Try http://javers.org
Create class to strore fields information like this (or use Map):
class FieldsContainer<F,V>{
private F field;
private V value;
public FieldsContainer(F field, V value) {
this.field = field;
this.value = value;
}
public FieldsContainer(){}
public F getField() {
return field;
}
public void setField(F field) {
this.field = field;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
and then in equals():
public boolean equals(Object obj) {
...
} else if (!field1.equals(other.field1)){
fieldsContainer=new FieldsContainer("fieldName1", field1);
return false;
}
if (field2 != other.field2){
fieldsContainer=new FieldsContainer("fieldName2", field2);
return false;
}
fieldsContainer=null;
return true;
}
and in main:
if(!obj1.equals(obj2)){
fieldsContainer.getField();
fieldsContainer.getValue();
//Your stuff
}
Related
for example, I want to create a parent class Node, and subclasses IntegerNode and CharacterNode.
and try to find if a value already exists in a list without knowing what the type of values are.
for that, I will send my Node object and during runtime, I want to get the appropriate value.
there is a way to do that without using an instance of?
public class CharNode extends Node {
private Character charNode;
CharNode(char digit){
this.charNode = digit;
}
Character getValue(){
return charNode;
}
}
public class IntegerNode extends Node {
private Integer integerNode;
IntegerNode(int number){
this.integerNode = number;
}
Integer getValue(){
return integerNode;
}
}
public class Node {
Node getNode();
}
boolean isExists(List<Node> list, Node value){
///// Here I want to check if the value inside the node already exists in that list without checking the type. It can be Lists of characters or a list of integers.
}
I've changed your classes a bit, so it's easier to work with them.
public abstract class Node<T> {
public abstract T getValue();
// I guess you implemented this method, but didn't copy it in your example.
//Node getNode();
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> otherNode = (Node<?>) o;
T value = getValue();
if (value == null) return otherNode.getValue() == null;
return getValue().equals(otherNode.getValue());
}
// If you implement eqauls you should also always implement hashCode.
public int hashCode() {
T value = getValue();
return value != null ? value.hashCode() : 0;
}
}
public class CharNode extends Node<Character> {
private Character value;
public CharNode(char value){
this.value = value;
}
#Override
public Character getValue(){
return value;
}
}
public class IntegerNode extends Node<Integer> {
private Integer value;
public IntegerNode(int value){
this.value = value;
}
#Override
public Integer getValue(){
return value;
}
}
Node is now abstract and has a abstract method getValue added to it. Any class that inherits from Node is now forced to implement getValue. Additionally I added simple implementations of equals & hashCode. In your case you would probably only need equals, but not implementing hashCode when implemeneting equals is very bad practice and can break classes that rely on a working implementation.
Now just iterate over the list and check equals every time.
public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
for (Node<?> node : list) {
if (node.equals(value)) {
return true;
}
}
return false;
}
Or use List.contains which does the same for us.
public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
return list.contains(value);
}
Here is an example for using a list of CharNodes.
CharNode sNode = new CharNode('s');
CharNode cNode = new CharNode('c');
IntegerNode oneNode = new IntegerNode(1);
IntegerNode twoNode = new IntegerNode(2);
List<CharNode> charNodes = Arrays.asList(sNode, cNode);
System.out.println(isExists(charNodes, new CharNode('s'))); // true
System.out.println(isExists(charNodes, new CharNode('x'))); // false
You can also create a list of nodes with mixed types.
List<Node<?>> allNodes = Arrays.asList(sNode, cNode, oneNode, twoNode);
System.out.println(isExists(allNodes, new CharNode('s'))); // true
System.out.println(isExists(allNodes, new IntegerNode(1))); // true
System.out.println(isExists(allNodes, new CharNode('x'))); // false
You can use Node.getValue() to get the value, but without knowing the type of getValue() there is only so much you can do.
Object nodeValue = allNodes.get(3).getValue();
System.out.println(nodeValue); // 2
As you mentioned you can use instanceof to get the type and write codefor each instanceof check, but there is a much better solution: Add another method in your Node class and implement appropriate behavior for this method in your children.
The easiest way to do that is to implement the equals method for both classes:
// equals for the CharNode class
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
// add here the logic specific to each class
return this.charNode.equals(((CharNode)o).charNode);
}
// equals for the IntegerNode class
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
// add here the logic specific to each class
return this.integerNode.equals(((IntegerNode)o).integerNode);
}
After that you'll be able to use the list.contains(node) method
Try this.
static abstract class Node {
protected Object value;
public Node(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
}
static class CharacterNode extends Node {
public CharacterNode(char value) {
super(value);
}
}
static class IntegerNode extends Node {
public IntegerNode(int value) {
super(value);
}
}
public static void main(String[] args) {
List<Node> nodes = List.of(new CharacterNode('a'), new IntegerNode(3));
for (Node node : nodes)
if (node.getValue().equals(3))
System.out.println("found value 3");
}
output:
found value 3
I have use TreeMap to store key value.
For key using custom object.
But once I have faced very strange issue, I am not able to get value which I have set earlier(with same key).
below is my code
public final class TestOptions implements Cloneable {
private Map<StorageSystemOptionKey, Object> options = new TreeMap<StorageSystemOptionKey, Object>();
private static final class StorageSystemOptionKey implements Comparable<StorageSystemOptionKey> {
/** Constant used to create hashcode */
private static final int HASH = 31;
private final Class<? extends StorageRepository> storageRepositoryClass;
/** The option name */
private final String name;
private StorageSystemOptionKey(Class<? extends StorageRepository> storageRepositoryClass, String name) {
this.storageRepositoryClass = storageRepositoryClass;
this.name = name;
}
public int compareTo(StorageSystemOptionKey o) {
int ret = storageRepositoryClass.getName().compareTo(o.storageRepositoryClass.getName());
if (ret != 0) {
return ret;
}
return name.compareTo(o.name);
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final StorageSystemOptionKey that = (StorageSystemOptionKey) o;
if (!storageRepositoryClass.equals(that.storageRepositoryClass)) {
return false;
}
if (!name.equals(that.name)) {
return false;
}
return true;
}
#Override
public int hashCode() {
int result;
result = storageRepositoryClass.hashCode();
result = HASH * result + name.hashCode();
return result;
}
}
void setOption(Class<? extends StorageRepository> fileSystemClass, String name, Object value) {
options.put(new StorageSystemOptionKey(fileSystemClass, name), value);
}
Object getOption(Class<? extends StorageRepository> fileSystemClass, String name) {
StorageSystemOptionKey key = new StorageSystemOptionKey(fileSystemClass, name);
return options.get(key);
}
boolean hasOption(Class<? extends StorageRepository> fileSystemClass, String name) {
StorageSystemOptionKey key = new StorageSystemOptionKey(fileSystemClass, name);
return options.containsKey(key);
}
public int compareTo(TestOptions other) {
if (this == other) {
return 0;
}
int propsSz = options == null ? 0 : options.size();
int propsFkSz = other.options == null ? 0 : other.options.size();
if (propsSz < propsFkSz) {
return -1;
}
if (propsSz > propsFkSz) {
return 1;
}
if (propsSz == 0) {
return 0;
}
int hash = options.hashCode();
int hashFk = other.options.hashCode();
if (hash < hashFk) {
return -1;
}
if (hash > hashFk) {
return 1;
}
return 0;
}
#Override
public Object clone() {
TestOptions clone = new TestOptions();
clone.options = new TreeMap<StorageSystemOptionKey, Object>(options);
return clone;
}
}
calling method to set and get like
public abstract Class<? extends StorageRepository> getStorageRepositoryClass();
public Class<? extends StorageRepository> getStorageRepositoryClass() {
return MyImpl.class;
}
TestOptions opt =new TestOptions(); // shared accross all Threads
Object getProperty(String name) {
return opt.getOption(getStorageRepositoryClass(), name);
}
void setProperty(String name, Object value) {
opt.setOption(getStorageRepositoryClass(), name, value);
}
Using set and get method in multi-threaded application.
queries:
I am calling set/get in multiple time then also I was not able to get value which was set earlier(same key)
Is this due to Treeset implementation is not synchronized
or problem with hashCode, equals or compareTo method implementation?
On a quick glance your compareTo(), equals() and hashCode() look fine. Note that TreeMap will mostly use compareTo() to find elements so that method needs to be correct (your's looks technically correct).
However, TreeMap and TreeSet (as well as other basic collections and maps) are not thread-safe and thus concurrent modifications can cause all kinds of unexpected behavior. We once had a case where 2 threads were trying to add a single element to a hashmap and the threads ended up in an endless loop because the internal list to resolve clashes produced a cycle (due to the concurrent put).
So either use the ConcurrentXxxx maps and collections or synchronize access to yours.
TreeSet is not synchronized. I belive ConcurrentSkipListMap might be better.
Check also your hashCode, equals implementation
My program loads information from a text file and creates an array of an object with the information whether it is a integer or a string.
I then want the object to return either a String or an Integer depending on whether the object is holding a integer value or a string value.
edit...
So here is my type class that holds either a int if the field in the text file is a number, or a string if the field is a word, and this is held in a Type array.
public class Type {
private String name;
private int value;
public Type(String name) {
this.name = name;
}
public Type(int value) {
this.value = value;
}
public String getName() {
return this.name;
}
public int getValue() {
return this.value;
}
public boolean isInt() {
boolean isInt = false;
if (this.value != 0) {
isInt = true;
return isInt;
}
return isInt;
}
}
So in my array could be either a Int or a String, i want to return the datatype without any long statements in my main class.
If you strictly want only to get the specific values, you could add a method to your Type class and get the values from this method, ugly but does what you want:
public <T> T getDynamicValue(Type t) {
if (isInt()) {
return (T) ((Integer) t.getValue());
} else {
return (T) t.getName();
}
}
use of it:
List<Type> dynamicList = Arrays.asList(new Type[]{new Type(1), new Type(2), new Type("dog")});
for (Type t : dynamicList) {
System.out.println("T -> " + t.getDynamicValue(t));
}
If you want to perform some manipulation with this data, you have to make an instanceof check and Cast it, for instance some splitting (or String methods) with the name value...
You can't choose the type of object to return at runtime. Your only option is to return an Object. You can check if it's a String or an int using this code, for example:
if(object instanceof String) {
//... it's a string
}
else {
//...otherwise it's an int
}
If you are reading all inputs into String instances, you will need to test the values against Integer.parseString(value) to find out if it is actually an Integer.
You could try to cast the object into an Integer and catch the ClassCastException:
try {
int i = (Integer) object;
}
catch (ClassCastException e){
String s = (String) object;
}
When I have this type of problem, I sometimes solve it by turning the problem around and using a callback-style solution.
For example:
for ( Type t : array ) {
t.process( callback );
}
Where the callback looks like this:
interface Callback {
public void processInt(....);
public void processString(....);
}
You can then either implement the process method either with an if (isInt()) callback.processInt() else callback.processString(), or if you change the definition of Type you can use the inheritance tree to do it for you.
For example:
interface Type {
public void process( Callback cb );
}
class IntType implements Type {
public void process( Callback cb ) {
cb.processInt(...);
}
}
class StringType implements Type {
public void process( Callback cb ) {
cb.processString(...);
}
}
I want to make the class below immutable. Can anyone provide a simple example of creating an immutable class in java?
class Emp implements Comparable
{
String name,job;
int salary;
public Emp(String n,String j,int sal)
{
name=n;
job=j;
salary=sal;
}
public void display()
{
System.out.println(name+"\t"+job+"\t"+salary);
}
public boolean equals(Object o)
{
// use a shortcut comparison for slightly better performance; not really required
if (this == o)
{
return true;
}
// make sure o can be cast to this class
if (o == null || o.getClass() != getClass())
{
// cannot cast
return false;
}
// can now safely cast
Emp p=(Emp)o;
return this.name.equals(p.name)&&this.job.equals(p.job) &&this.salary==p.salary;
}
public int hashCode()
{
return name.hashCode()+job.hashCode()+salary;
}
public int compareTo(Object o)
{
Emp e=(Emp)o;
return this.name.compareTo(e.name);
//return this.job.compareTo(e.job);
// return this.salary-e.salary;
}
}
Just label all fields of your class as final, and don't assign to them anywhere but the constructor for your class.
Also, it's good to make the class final, or to only provide private constructors, and static factory methods. This means people cannot subclass your class and override you methods.
for example:
public class Immutable {
private final String value;
private Immutable(String value) {
this.value = value;
}
public static Immutable create(String value) { return new Immutable(value); }
public String getValue() { return value; }
}
public Object getValue()
{
ValueItem valueItem = null;
Object returnValue = null;
if(this.value instanceof StringValueImpl)
{
valueItem = (StringValueImpl) this.value;
}
else if(this.value instanceof ListValueImpl)
{
valueItem = (ListValueImpl) this.value;
}
else if(this.value instanceof MapValueImpl)
{
valueItem = (MapValueImpl) this.value;
}
if(valueItem!=null)
returnValue = valueItem.getValue();
return returnValue;
}
ValueItem is an interface which is implemented by ListValueImpl, MapValueImpl etc .. I want return value which is an object. The code works fine but i was wondering if this can be improved in any way ?
What is the type of this.value? If it is ValueItem then you don't need to do any of this and can replace the method with this:
public Object getValue()
{
Object returnValue = null;
if(this.value!=null)
returnValue = this.value.getValue();
return returnValue;
}
Or even shorter:
public Object getValue()
{
return this.value!=null ? this.value.getValue() : null;
}
If this.value is not of type ValueItem but it has to contain a ValueItem, then you have a design problem at your hand.
My inclination is that your getValue() isn't doing anything for you at all. You're detecting what class it is, casting it to that class, then shoving it into an Object again. ...so you'll have to do the same kind of detection on the caller's side of getValue() anyways!
Personally, I'd do it like this:
public boolean isaStringValueImpl() {
return (this.value instanceof StringValueImpl);
}
public boolean isaListValueImpl() {
return (this.value instanceof ListValueImpl);
}
public boolean isaMapValueImpl() {
return (this.value instanceof MapValueImpl);
}
public StringValueImpl getAsaStringValueImpl() {
return (StringValueImpl)this.value;
}
public ListValueImpl getAsaListValueImpl() {
return (ListValueImpl)this.value;
}
public MapValueImpl getAsaMapValueImpl() {
return (MapValueImpl)this.value;
}
In addition to the regular getter:
public ValueItem getValueItem() {
return this.value;
}
But even with all this, I'd say that you might have a larger design issue that could be cleaned up.
How about a generics based type safe version.
public abstract class ValueItem<T> {
public abstract T getValue();
public class StringValueImpl extends ValueItem<String> {
private String value;
public String getValue() {
return value;
}
}
public class ListValueImpl extends ValueItem<List<?>> {
private List<?> value;
public List<?> getValue() {
return value;
}
}
public class MapValueImpl extends ValueItem<Map<?, ?>> {
private Map<?, ?> value;
public Map<?, ?> getValue() {
return value;
}
}
}