clone object in java - java

I have a class X:
public class X implements Cloneable {
private int a;
private int b;
#Override
public X clone() throws CloneNotSupportedException {
return (X) super.clone();
}
}
I want to remember its initial state. Therefore get his clone:
try {
old = new X();
old = x.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
x - an object of class X, a and b installed.
For example i do with old:
old.setA(7)
How do I now compare the old and the new object, find out whether there were changes. I do so but does not work:
//if object is changed
if (!old.equals(x)){
}
How to check the object has changed or not?

Add below code in your X class
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + a;
result = prime * result + b;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
X other = (X) obj;
if (a != other.a)
return false;
if (b != other.b)
return false;
return true;
}

public boolean equals(Object object2) {
return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}

Related

Java - Compare two fields using only comparable interface

I'm trying to compare two fields (string and integer) using only the Comparable interface. It was my first time using this and I've no idea where to put the second field to compare the values.
public int compareTo(Object o) throws ClassCastException
{
int count = 0;
int compareName = this.lastName.compareTo(((SalePerson) o).getLastName());
int compareSales = Integer.compare(this.totalSales, ((SalePerson) o).getTotalSales());
if(!(o instanceof SalePerson))
{
throw new ClassCastException("A SalePerson object expected.");
}
if((this.totalSales < ((SalePerson) o).getTotalSales()))
{
count = -1;
}
else if((this.totalSales > ((SalePerson) o).getTotalSales()))
{
count = 1;
}
return count;
}
If you want to implement Comparable interface, it is unecassary to throw ClassCastException since o has to be SalePerson, otherwise you will get a compile error.
You can do it this way:
public class SalePerson implements Comparable<SalePerson>{
#Override
public int compareTo(SalePerson o) {
int totalSalesCompare = Integer.compare(this.totalSales, o.getTotalSales());
return totalSalesCompare == 0 ? this.lastName.compareTo(o.getLastName())
: totalSalesCompare;
}
}
Also, the compareTo is suggested to work with equals and hashCode:
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof SalePerson)) {
return false;
}
return Integer.compare(Integer.compare(this.totalSales, o.getTotalSales())) == 0
&& this.lastName.equals(o.getLastName());
}
#Override
public int hashCode() {
return this.lastName.hashCode() * 31 + this.totalSales;
}

Backup of HashMap's Maps in Java

I want to do a backup copy of a Map (that contains other Maps).
I have something like this:
Map<TYPE1, Map<TYPE2, TYPE3>>
TYPE1, TYPE2 and TYPE3 are objects from 3 different classes created by me (e.g the components of that classes are: String, Integer, Double,....)
I tried
Map<TYPE1, Map<TYPE2, TYPE3>> Map2= new HashMap<TYPE1, Map<TYPE2, TYPE3>>(Map1)
[....make some changings in Map1...]
Map1 = new HashMap<TYPE1, Map<TYPE2, TYPE3>>(Map2)
Map1 is the original Map I want to make a copy of.
I also tried PutAll method but it didn't work (the content of the Map isn't the same of the original one).
Do you know other methods? Thank you.
Since the key and value in your collection are your self define class.
Those content int the map are not really copied but share the same instance of your "TYPE".
You need to do something like this to copy the value from all the content.
This is just a very simple example, so there's no any encapsulation.
public class Foo1 {
public Integer a = 0;
public Foo1() {
}
public Foo1(Integer a) {
this.a = a;
}
public Foo1 clone() {
return new Foo1();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.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;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
public class Foo2 {
public Integer a = 0;
public Foo2() {
}
public Foo2(Integer a) {
this.a = a;
}
public Foo2 clone() {
return new Foo2();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.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;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
public class Foo3 {
public Integer a = 0;
public Foo3() {
}
public Foo3(Integer a) {
this.a = a;
}
public Foo3 clone() {
return new Foo3();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.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;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
Copy your value by your own.
Map<Foo1, Map<Foo2, Foo3>> map1 = new HashMap<Foo1, Map<Foo2, Foo3>>();
Map<Foo1, Map<Foo2, Foo3>> map2 = new HashMap<Foo1, Map<Foo2, Foo3>>();
Map<Foo2, Foo3> tmp = new HashMap<Foo2, Foo3>();
tmp.put(foo.new Foo2(), foo.new Foo3());
map1.put(foo.new Foo1(), tmp);
for (Foo1 key : map1.keySet()) {
Map<Foo2, Foo3> tmp2 = new HashMap<>();
for (Foo2 key2 : map1.get(key).keySet()) {
tmp2.put(key2.clone(), map1.get(key).get(key2).clone());
}
map2.put(key, tmp2);
}
for (Foo1 key : map1.keySet()) {
for (Foo2 key2 : map1.get(key).keySet()) {
map1.get(key).get(key2).a = 10;//change map1's value
}
}
for (Foo1 key : map2.keySet()) {
for (Foo2 key2 : map2.get(key).keySet()) {
System.out.println(map2.get(key).get(key2).a);// the value in map2 still 0
}
}
very interesting article about deep copy:
How do you make a deep copy of an object in Java?
with serialization/deserialization, you dont need to go inside your classes,
and you dont forget some variable.
it gives:
Map<Integer, Map<String,String>> mimss =new HashMap<Integer, Map<String,String>>();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(mimss);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
Map<Integer, Map<String,String>> mimss_copy=(Map<Integer, Map<String,String>>) new ObjectInputStream(bais).readObject();
You can also convert to B64 in the middle if you want to save it in text:
String serial= DatatypeConverter.printBase64Binary(byteData);
byte[] byteData_reverse=DatatypeConverter.parseBase64Binary(serial);
REQUIREMENT: TYPE1, TYPE2, TYPE3 must be serializable
to be serializable, your class must be like that
public class myclass implements Serializable
and you should (not mandatory) declare inside
private static final long serialVersionUID = 6569838532917408380L;
If anything inside in serializable too, it's OK (standard types are, collections, ...)

Recognizing duplicates in HashSet

So, I have this code written in Java:
import java.util.HashSet;
class Interval{
long from;
long to;
public Interval(long from, long to) {
this.from = from;
this.to = to;
}
public boolean equals(Interval other) {
return from == other.from && to == other.to;
}
}
public class Test {
public static void main(String[] args) {
HashSet<Interval> mySet = new HashSet<Interval>();
mySet.add(new Interval(1,2));
mySet.add(new Interval(1,2));
for(Interval in : mySet) {
System.out.println(in.from + " " + in.to);
}
}
}
The problem is that the set doesn't recognize that there is already an interval from 1 to 2. I defined the function equals, but still it doesn't work. I tried implementing the Comparable interface and overloading the compareTo function, but again nothing. Can somebody tell me how can I solve this problem?
Thank you!
You need to override equals from java.lang.Object.
You did not as yours does not accept Object as parameter.
public boolean equals(Object obj) {
if (obj == null)
return false;
else if (this.getClass() != obj.getClass())
return false;
else {
Interval other = (Interval) obj;
return from == other.from && to == other.to;
}
}
For hashCode, you can do this for example.
public int hashCode() {
return new Long(this.from).hashCode();
}
So overall you get this code.
import java.util.HashSet;
class Interval {
long from;
long to;
public Interval(long from, long to) {
this.from = from;
this.to = to;
}
public boolean equals(Object obj) {
if (obj == null)
return false;
else if (this.getClass() != obj.getClass())
return false;
else {
Interval other = (Interval) obj;
return from == other.from && to == other.to;
}
}
public int hashCode() {
return new Long(this.from).hashCode();
}
}
public class Test003 {
public static void main(String[] args) {
HashSet<Interval> mySet = new HashSet<Interval>();
mySet.add(new Interval(1, 2));
mySet.add(new Interval2(1, 2));
for (Interval in : mySet) {
System.out.println(in.from + " " + in.to);
}
}
}
Use equals and hashCode methods like below it will work perfectly alright
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (from ^ from >>> 32);
result = prime * result + (int) (to ^ to >>> 32);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Interval other = (Interval) obj;
if (from != other.from) {
return false;
}
if (to != other.to) {
return false;
}
return true;
}

ConcurrentHashMap - Odd behaviour

Can anyone let me know what goes wrong in this piece of code? I'm pulling my hair out!
There isn't any problem if I use HashMap instead of ConcurrentHashMap. The code is compiled with JDK 5.0
public class MapTest {
public Map<DummyKey, DummyValue> testMap = new ConcurrentHashMap<DummyKey, DummyValue>();
public MapTest() {
DummyKey k1 = new DummyKey("A");
DummyValue v1 = new DummyValue("1");
DummyKey k2 = new DummyKey("B");
DummyValue v2 = new DummyValue("2");
testMap.put(k1, v1);
testMap.put(k2, v2);
}
public void printMap() {
for(DummyKey key : testMap.keySet()){
System.out.println(key.getKeyName());
DummyValue val = testMap.get(key);
System.out.println(val.getValue());
}
}
public static void main(String[] args){
MapTest main = new MapTest();
main.printMap();
}
private static class DummyKey {
private String keyName = "";
public DummyKey(String keyName){
this.keyName = keyName;
}
public String getKeyName() {
return keyName;
}
#Override
public int hashCode() {
return keyName.hashCode();
}
#Override
public boolean equals(Object o) {
return keyName.equals(o);
}
}
private static class DummyValue {
private String value = "";
public DummyValue(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
}
This is the output:
B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
DummyKey.equals method implementation is incorrect, due to that testMap.get(key) always returns null. Try this
public boolean equals(Object o) {
if (o instanceof DummyKey) {
DummyKey other = (DummyKey) o;
return keyName == null ? other.keyName == null : keyName.equals(other.keyName);
}
return false;
}
hashCode also needs a little change to be consistent with equals
public int hashCode() {
return keyName == null ? 0 : keyName.hashCode();
}
The problem comes from your equals in DummyKey.
When you call DummyValue val = testMap.get(key);, the hashcode function finds a match (both keyname of k1 and key are the same and so are their hashcode). Yet equals returns false because k1.keyname is equal to "A" which is not equal to key itself, which is actually of type DummyValue: you are not comparing properly!
Therefore, you need to modify your equals function:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
Please note that if you change hashCode(), then you must change equals() as well. Otherwise, you will run into problems. If equals() returns true for two items, then their hashCode() value must be equal! The opposite is not required but preferable for better hashing performance. Here is an implementation of equals() and hashCode().
HINT: if you are using eclipse, you can utilize its source generation capability to create the correct hashCode() and equals() method for you. The only thing you need to do is to pick the instance variables that identify the object. To do so in eclipse, while your source code is open, go to the tabs in the top and choose "source", then choose "Generate hashCode() and equals()..."
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
Override
public boolean equals(Object other) {
if(this == other) return true; //for optimization
if(! other instanceof this) return false; //also covers for when other == null
return this.keyName == null ? other.keyName == null : this.keyName.equals(other.keyName);
}
As others have pointed, the problem lies in the way you override hashcode and equals.
Two options : 1) Just remove the hashcode and equals and it works fine
2) I let eclipse generate the source for hashcode and equals and it works fine. This is what my eclipse belted out for me :
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((keyName == null) ? 0 : keyName.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;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}

HashSet.contains does not behave as expected with hashCode and equals

I have a class called MyClass:
public class MyClass extends abstractClass implements
someInterface {
Set<VNode> relation_;
Set<VNode> x_;
Set<VNode> y_;
#Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MyClass)) {
return false;
}
MyClass other = (MyClass) obj;
if (relation_ == null) {
if (other.relation_ != null) {
return false;
}
} else if (!relation_.equals(other.relation_)) {
return false;
}
if (x_ == null) {
if (other.x_ != null) {
return false;
}
} else if (!x_.equals(other.x_)) {
return false;
}
if (y_ == null) {
if (other.y_ != null) {
return false;
}
} else if (!y_.equals(other.y_)) {
return false;
}
return true;
}
#Override
public int hashCode() {
int res = new HashCodeBuilder(17, 37).append(relation_).append(x_)
.append(y_).append(getWeight()).toHashCode();
return res;
}
}
The abstract class is as follows:
public abstract class abstractClass {
double weight_;
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof abstractClass)) {
return false;
}
abstractClass other = (abstractClass) obj;
if (Double.doubleToLongBits(weight_) != Double
.doubleToLongBits(other.weight_)) {
return false;
}
return true;
}
public double getWeight() {
return weight_;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(weight_);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
}
Now, if I have HashSet<MyClass> s1 and an MyClass i1, even if s1 has an element s1i whith s1i.equals(i1)=true and s1i.hashCode()=i1.hashCode(), s1.contains(i1) gives me false.
Any explanations?
Other classes:
public class VNode {
Mention mention_;
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof VNode)) {
return false;
}
VNode other = (VNode) obj;
if (mention_ == null) {
if (other.mention_ != null) {
return false;
}
} else if (!mention_.equals(other.mention_)) {
return false;
}
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((mention_ == null) ? 0 : mention_.hashCode());
return result;
}
}
public class Mention extends Range {
private final int id_;
public Mention(final int start, final int end) {
super(start, end);
id_ = getNextMentionID();
}
}
public class Range {
private final int start_;
private final int end_;
/**
* Contr.
*
* #param start
* #param end
*/
public Range(final int start, final int end) {
start_ = start;
end_ = end;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Range)) {
return false;
}
Range other = (Range) obj;
if (end_ != other.end_) {
return false;
}
if (start_ != other.start_) {
return false;
}
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + end_;
result = prime * result + start_;
return result;
}
}
Your equals() method is not readable at all. Since you are using HashCodeBuilder in hashCode(), why not use EqualsBuilder as well?
Version a)
public boolean equals(Object obj){
if(obj == null || obj.getClass()!=getClass()){
return false;
}
MyClass other = (MyClass) obj;
return new EqualsBuilder()
// check parent properties first
.append(this.getWeight(), other.getWeight())
.append(this.relation_, other.relation_)
.append(this.x_, other.x_)
.append(this.y_, other.y_)
.isEquals();
}
Version b)
public boolean equals(Object obj){
// delegate to parent equals first
if(!super.equals(obj)){
return false;
}
MyClass other = (MyClass) obj;
return new EqualsBuilder()
.append(this.relation_, other.relation_)
.append(this.x_, other.x_)
.append(this.y_, other.y_)
.isEquals();
}
Each class should only be concerned with its own variables when calculating equals and hashcode. So, in your MyClass instead of calling getWeight() you should be using the hashcode of the super class. Like you are with equals()!. In this case the effect will be the same.
public int hashCode() {
int res = new HashCodeBuilder(super.hashcode(), 37).append(relation_).append(x_)
.append(y_);
return res;
}
This means any changes to the base class that may affect equals and hashcode are confined to the class and you don't have to update the sub classes.
(Not really an answer, more an observation but its too big for a comment)

Categories

Resources