What is the best implementation of a state toggle in Java? [closed] - java

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is the best (in terms of flexibility) object-oriented implementation for an alternating state toggle in Java? The implementations I have listed are only what I have come up with and are not exhaustive.
Note: The answer to this question is not subjective. By the principles of object-oriented programming, the context of usage for this implementation should be irrelevant.
[Edit] The focus here is on the structure of the code. Obviously the actual functionality is so simple as to not even warrant the effort of a dedicated implementation.
public class ImpureToggle<T> implements Supplier<T> {
//false represents state a, true represents state b
private boolean state;
private final T a;
private final T b;
public ImpureToggle(T a, T b) {
this.a = a;
this.b = b;
}
// returns a different reference depending on internal state
#Override
public T get() {
return state ? b : a;
}
public void toggle() {
state = !state;
}
}
public class ConsumerToggle<T> implements Consumer<Consumer<T>> {
private final T a;
private final T b;
//false represents state a, true represents state b
private boolean state;
public ConsumerToggle(T a, T b) {
this.a = a;
this.b = b;
}
#Override
public void accept(Consumer<T> t) {
t.accept(state ? b : a);
}
public void toggle() {
state = !state;
}
}
public interface ImpureStaticToggle {
// reassigns parameter 'state'
static <T> void toggle(T state, T a, T b) {
state = state == a ? b : a;
}
}
public interface PureStaticToggle {
// returns a different reference depending exclusively on external input
static <T> T toggle(boolean state, T a, T b) {
//false represents state a, true represents state b
return state ? b : a;
}
}
/*
Just as an example of an unarguably bad implementation:
*/
public class MutableToggle<T> implements Supplier<T> {
private T state;
private final T a;
private final T b;
public MutableToggle(T a, T b) {
state = a;
this.a = a;
this.b = b;
}
// exposes a mutable reference, which could completely break the logic of this
// object and others
#Override
public T get() {
return state;
}
public void toggle() {
state = state == a ? b : a;
}
}
[Edit] ternary for inverting boolean (was done for consistency) replaced with logical complement operator as per #gargkshitiz.

By the principles of object-oriented programming, the context of usage for this implementation should be irrelevant.
Not sure what this means, and you seem firm on not giving context, but I'll try my best to give deeper insight into why I feel what you're doing doesn't make much sense.
Don't pass booleans as arguments1
broadly speaking if there is a parameter passed into a function that selects specific behaviour to be executed then further step-wise refinement is required; Breaking up this function in to smaller functions will produce more highly cohesive ones
The problem with a parameter passed in as you describe, is that the function is doing more than two things; it may or may not check the users access rights depending on the state of the Boolean parameter, then depending on that decision tree it will carry out a piece of functionality.
It would be better to separate the concerns of Access Control from the concerns of Task, Action or Command.
Take, for example, String#regionMatches. It has an overload for ignoring case.
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
if (!ignoreCase) {
return regionMatches(toffset, other, ooffset, len);
}
// Note: toffset, ooffset, or len might be near -1>>>1.
if ((ooffset < 0) || (toffset < 0)
|| (toffset > (long)length() - len)
|| (ooffset > (long)other.length() - len)) {
return false;
}
byte tv[] = value;
byte ov[] = other.value;
if (coder() == other.coder()) {
return isLatin1()
? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
: StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
}
return isLatin1()
? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
: StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
}
This is a clear example, from the standard library, of why you should avoid boolean parameters for your behaviors.
Notice how the boolean determines which implementation should be used: one which ignores casing, or one which doesn't.
This is a cheap trick typically used to make choosing an implementation less verbose:
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = text.regionMatches(even, ...);
// use matches
}
However, at a glance, it's not clear exactly what that condition is determining. We're forced to open the documentation (or worse: the implementation).
Compare that to:
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = false;
if(even)
matches = text.regionMatchesIgnoreCase(...);
else
matches = text.regionMatches(...);
// use matches
}
Or
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = even ? text.regionMatchesIgnoreCase(...) : text.regionMatches(...);
// use matches
}
It's more verbose, but it's clearer as to what the condition is for: determining whether casing should be ignored.
regionMatchesIgnoreCase would be easier to comprehend at a glance, rather than needing to read the documentation to determine what the boolean represents.
Comprehension is important for avoiding time waste when fixing critical bugs. Assuming you want to blindly apply principles, this knocks out PureStaticToggle.
Don't use interfaces as utility classes1 (easy fix)
This seems to me to cut against the grain of interfaces. One would have to look around the API to determine that there are no classes that implement this interface, and that there are no producers or consumers of this interface
If you look at the new Java 8 APIs, you'll see that the final class idiom is still used despite the ability to add static methods on interfaces.
This would remove both interface alternatives. It can be easily worked around: You can ignore this principle, or use a regular class.
But, what would this utility type be for? What other methods would be in the utility type? 1 type per utility implementation seems excessive, bloats the namespace.
Using an interface doesn't make your code OOP. Interfaces in general are not an OOP concept. However, their initial/primary function (before static and private methods) were OOP. Java supports multiple paradigms, hence the exposure of static methods in interfaces.
Design by contract1
Software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, postconditions and invariants.
Assuming you want sturdy interfaces for your implementations, you should expose contracts.
If you aren't familiar with contracts, they're a set of rules followed by both the client of the code & the code itself. If the code doesn't work based on what it states in the contract, it's considered to be bugged.
In Java, they're typically defined by JavaDocs. However, no matter how you choose to expose your contracts to users, the point here is that clients should know what that piece of code will and won't do, and code should define how the user should use the code.
How would your contract look for the types you've proposed?
Contracts are built based off requirements. From the code shown, the requirements aren't clear. In fact, the interface approaches
In terms of OOP, getters violate encapsulation1
It is not encapsulation and [using] Lombok [to generate getters & setters] is just making to work with procedural code less painful
And data structure is not an object
You should encapsulate state and implementation details so that object has full control on that. Logic will be focused inside object and will not be spread all over the codebase
Getters are procedural, not object oriented.
In OOP, objects communicate via behaviors. When you expose getters, you are exposing properties of the object.
The reason why OOP prefers hidding the properties of objects can vary, with some being obvious: Properties are eventually used in logic somewhere, and the logic/behavior which relies on that property won't be easily apparent if exposed.
Using a call-back to handle the logic of the property, especially how you're doing it in ConsumerToggle, is not much different from exposing a getter.
ImpureStaticToggle won't work as it is (easy fix)
Java is pass by value.
String s = "first";
toggle(s, "second", "third");
System.out.println(s); // prints "first"
The value of s will remain unchanged. It can be fixed with a return statement & assignment when calling the function:
<T> T toggle(T state, T a, T b) {
return state == a ? b : a;
}
T value = toggle(value, a, b);
However, this approach is still flawed for reasons mentioned in some of the sections above.
Last notes
ImpureStaticToggle and PureStaticToggle are different.
The former determines a return value based on the type of a reference
The latter determines a return value based on the result of any condition.
You can use PureStaticToggle to achieve what ImpureStaticToggle does. But, you cannot use ImpureStaticToggle to do what PureStaticToggle can do. They aren't completely interchangable, and those details should impact your choice.
What you are ultimately doing with the code you've shown is changing the implementation based on a condition. That's all that's going on here.
I hate to say it, but if your goal is to follow OOP principles by "tossing the book" at your code, then all your alternatives violate commonly practiced OOP principles.
Don't overcomplicate things. I don't see any benefit in encapsulating/hiding the use of a ternary. Use the ternary as is, when needed. Invest the time you would have invested in this design into something important.
Also, for your interfaces, toggle isn't the best name either, since the behavior isn't actually toggling anything - a better name would be chooseValue or determineValue, as that's what the method is actually doing.

Your first implementation (ImpureToggle) looks okay. Just change the toggle method to be:
state = !state
But having such a Toggler with a public toggle method looks like an overkill. Either use the whole class with proper access modifiers OR instead use a local method to limit the scope and the potential bugs.

Related

How can I implement a comparator to compare two numbers?

I have a class OffbyOne where I declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
Here is my code so far:
public static class OffbyOne {
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
return true;
} else if ((y-x)==1) {
return true;
}
return false
public boolean equalChars(char x, char y); {
if (Compare(x,y) == true) {
return true;
}
return false;
}
I'm struggling to understand how comparators work in Java and what do I have to do. If anyone can please help me with this and then provide explanations for how it is supposed to be done, it would be great for me.
Thank you.
Comparator already exists in java - java.util.Comparator. It is something completely different from what you describe: Java's own comparator is a thing that you give 2 objects, and the comparator tells you which of the two 'comes earlier' in a sorting. Such an oracle is all you need to efficiently sort stuff.
It's allowed, but a bad idea, to name types the same as core java types. You can make your own String, which is different from java's own String in all ways (your String does not in any way replace java's string), it's just a confusing name, is all. You're doing the same thing with Comparator here. Bad idea. I'd call it OffByOne or similar.
declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
This makes no sense whatsoever. You must have misunderstood the assignment. An interface describes the what and does not describe the how, whereas what you just said is describing the how. That's just not what interfaces do - they don't get to define the how. They only define the what. You're describing an implementation, not an interface.
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
You can't stick code in types like this. You can stick only methods, fields, constructors, and other types in there. You can stick code in a method and then stick the method in a type, if you want. In addition, given that it is an interface, you can't stick code in one at all - interfaces define what a class can do, not how it does it (there is the default mechanism. That's definitely not what this assignments wants you to do so, so it doesn't apply here).
This would be an interface:
public interface DifferenceOfOne<T> {
public boolean isDifferenceOfOne(T a, T B);
}
This says: There is such a thing as a 'DifferenceOfOne' implementation for any given type. Such a class would implement the method isDifferenceOfOne, which takes in 2 parameters, both of that given type, and which then returns a boolean.
You can then make an implementation for the Integer type:
class IntDiffOfOne implements DifferenceOfOne<Integer> {
public boolean isDifferenceOfOne(Integer a, Integer b) {
return (a - 1 == b || b - 1 == a);
}
}
DifferenceOfOne<Integer> intDiffOfOne = new IntDiffOfOne();
Or in more common, modern java syntax:
DifferenceOfOne<Integer> intDiffOfOne = (a, b) -> (a - 1 == b || b - 1 == a);
And someone else can write a DiffOfOne implementation that, I dunno, tells you if any 2 LocalDate instances differ by exactly 1 day, perhaps, that would be a DifferenceOfOne<LocalDate>.
If this all sounds confusing to you - go back to whomever gave you this assignment, as either the assignment makes no sense, or you misheard/misunderstood it.

How do I define a method once and use it as a "building plan" for other methods?

I'm new to Java and have the following question:
Is there an easier way of making methods for each variable?
The meaning behind the question is:
Do I have to define a method that does the exact same thing as other methods except that they use different variable names and types?
I think the most common methods with the same problem are the get- and set-accessors:
They share the same structure, the only difference are the variable types and names.
In my following example, you need to know:
Variables varA-varD just represent the existance of multiple variables with various types and names.
The variable "inheritor" is special. I do NOT implement inheritance, but I DO have to verify that somewhere, maybe in the inheritor of the inheritor of the inheritor the same variable
has a value ("!= null"; in case of Lists, HashMaps, Enumerations, etc.)
or
has a value other than -2 (because 0 means nothing and -1 indicates "infinite" in my system, so I thought using -2 for indicating that the variable hasn't been set yet is a good idea; in case of Integers, Floats, Doubles, etc.).
I have verification methods...
...to check whether the variables have already been set (or not)
and for this reason the code is located
...outside of the setter because I have to check the variables even when they have not been set yet.
public class ExampleClass {
private int varA;
private String varB;
private ExampleEnum varC;
private List<OtherClass> varD;
//there are more variables here...
private ExampleClass inheritor;
public int getVarA() {
return varA;
}
public void setVarA(int varA) {
this.varA = varA;
}
public boolean validateVarA() {
//-2 is "not set" for Integers
if (varA == -2 && inheritor != null) {
return inheritor.getVarA() != -2;
} else {
return varA != -2;
}
}
//Do I have to define three methods for each variable?
//What if I had like 20 variables?!?
//I would need 60 methods altough every third one
//shares the same structure.
}
I needed some sort of "building plan" for a method:
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
public boolean verifyVar() {
//How would I get the invalid value for each type?
T invalidValue = ?;
if (var == invalidValue && inheritor != null) {
return inheritor.getVar() != invalidValue;
} else {
return var != invalidValue;
}
}
In the example above:
"Var" or "var" would be the variable name
and
"T" would be the type of var
I have no idea how I would get the invalid value...
Sorry in case I think too complicated and there is a simple answer to my question. Furthermore, I apologize for any grammar mistakes that may occur.
For generic getters and setters, there's always Map<String, Object>, but I'm pretty sure that's not what you want, so you should stick to the JavaBean conventions (as mentioned in the comments, any IDE would generate those for you and it makes total sense to have them according to OOP recommendations).
Any attempt to implement generic accessors would sooner or later become some java.util.Map with tones of reflection around it. If that's what you want, perhaps you should reconsider your model and switch your type-safe beans to some free-form types like map.
For validation, there's the javax.validation package (JSR-303).

Is it a bad practice to use arrays as parameter(s) to return multiple values

I sometimes (actually, often) find myself using a one-element array to return multiple values from a method. Something like this:
public static int foo(int param1, int param2[], String param3[])
{
// method body
....
// set return values
param2[0] = <some value>;
param3[0] = <some value>;
return <some value>;
}
Is this a bad practice? (It seems like it is because some of my friends said they didn't know what it was doing for 2 seconds!)
But the reason I used this in the first place was because this looked closest to what is know as pass-by-reference in C++. And the practice wasn't discouraged in C++, so ...
But if this is really a wrong way of doing things, any idea how to rewrite this in the clean way?
Thanks
Create an object that contains the data you want to return.
Then you can return an instance of that object.
class FooData {
private int someInt;
private int anotherInt;
private String someString;
public FooData(int a, int b, String c) {
someInt = a;
anotherInt = b;
someString = c;
}
}
public FooData foo() {
// do stuff
FooData fd = new FooData(blah, blahh, blahhh);
return fd;
}
While I agree with the general opinion here that using arrays for such a purpose is bad practice, I'd like to add a few things.
Are you sure that "pass by reference" really is what you need in the first place?
Many have said that your code is bad style, but now let me tell you why that is IMHO.
"Pass by reference" is mostly a synonym for "programming by side effect" which is a thing you always want to avoid. It makes code much harder to debug and understand, and in a multi-threaded environment, the bad effects of this attitude really can hit you hard.
To write scalable and thread-safe code in Java, you should make objects "read-only" as much as possible, i.e. ideally, you create an object and initialize it at the same time, then use it with this unmodifiable state throughout your application. Logical changes to the state can almost always be considered a "creation" of new state, i.e. creation of a new instance initialized to a state then needed. Many modern scripting languages only let you work in this way, and it makes things much easier to understand.
As opposed to C++, Java is much more efficient in allocating and releasing short-lived objects, so there is actually nothing wrong with what others here have suggested: To create an instance of a special class to hold the function result, just for the purpose of returning the result. Even if you do that in a loop, the JVM will be smart enough to deal with that efficiently. Java will only allocate memory from the OS in very large chunks when needed, and will deal with object creation and release internally without the overhead involved in languages like C/C++. "Pass by reference" really doesn't help you very much in Java.
EDIT: I suggest you search this forum or the net for the terms "side-effect", "functional programming" or "immutability". This will most likely open a new perspective to your question.
I believe that it is bad practice to "return" values using one-element arrays that are parameters to your method.
Here's another SO question about this topic. In short, it's very bad for readability.
There is an easy workaround: Wrap all values that you wish to return in a class you define specifically for this purpose, and return an instance of that class.
return new ValueHolder(someValue1, someValue2, someValue3);
That's not very idiomatic java. There are usually better approaches to software design.
What you're really doing with the "one-element array" is creating a mutable object (since String is immutable, as are primitives like int) and passing it by reference. Modifying this mutable object is called a "side effect" of the method. In general, you should minimize mutability (Effective Java Item 15) and your methods should be side-effect free. There are a couple approaches here.
1. Split the method into two (or three) methods that all take the same params:
public static int foo1(int param1)
{
// method body
....
return <some value>;
}
Similarly, you might have
public static int foo2(int param1) { ... }
and
public static String foo3(int param1) { ... }.
2. Return a composite object.
public Container {
private final int originalReturn;
private final int param2;
private final String param3;
public Container(int originalReturn, int param2, String param3) {
this.originalReturn = originalReturn;
this.param2 = param2;
this.param3 = param3;
}
// getters
}
public static Container foo(int param1, int param2[], String param3[])
{
// method body
....
// set return values
return new Container(<some value>, <some value>, <some value>);
}
This is indeed bad practice if the values are unrelated. This is usually an indicator that you can split that function into two, with each returning one of the values.
EDIT:
I am assuming that you are returning two values calculated in the method in an array. Is this not the case?
e.g.
public int[] getStatistics(int[] nums)
{
//code
int[] returns = new int[2];
returns[0] = mean;
returns[1] = mode;
return returns;
}
The above function could be split into getMean() and getMode().
Passing variables by reference allows the function to "legally" change their value. See this article to clear up the confusion of when this is possible in Java, and when it's not...
This is bad practice if the values are of different type and different entities, e.g. name and address, etc. It is fine with create an array with same data type, e.g list of addresses.

Java Best Practices: Performance with method parameters

Which is faster and/or less resources consuming:
class Foo()
{
public int value;
}
This way?
public int doSomeStuff(Foo f)
{
return (f.value + 1);
}
public int doOtherStuff()
{
...
Foo f = new Foo();
int x = doSomeStuff(f);
...
)
or this way?
public int doSomeStuff(int v)
{
return (v + 1);
}
public int doOtherStuff()
{
...
Foo f = new Foo();
int x = doSomeStuff(f.value);
...
)
In both cases, "doSomeStuff" will not change nothing in foo class. It just needs to know the "value".
They both perform the same, the same sequence of operations occurs. Your main concern is maintainability and sensible design here. Think carefully about which methods need which data and design it properly.
If you do have issues, you can optimise later. But you should always optimise last.
In terms of resource consuming, it is exactly the same.
But the second option is clearly better in terms of programming because if doSomeStuff only needs value, then there is no point to passing f.
I don't think there is any performance difference at all. And Java compiler will optimize to the best one anyway...
Depends how often you're going to call doSomeStuff without calling doOtherStuff, but generally performance difference is negligible and if you only call doOtherStuff then they'll be equally performant.
Probably even better:
Decalre doSomeStuff() as a method of foo, and invoke: f.doSomeStuff()
It is much more readable and will be easier to maintain doing it so, since if you have a
sub class of foo: Bar, and you want to calculate things a bit different - all you have to do is override doSomeStuff() in Bar
You should prefer readability over micro optimizations - let the compiler take care of those for you.
code snap:
class foo() {
public int value;
public int doSomeStuff() {
return value + 1;
}
}
and:
public int doOtherStuff() {
...
foo f = new foo();
int x = f.doSomeStuff();
...
}
The difference between doing:
object.intvariable + 1
and
int + 1
is so negligible as to be irrelevant for real world apps. It's probably one or two more JVM opcodes to look up foo and find its value variable which is not worth mentioning. You'd never notice that unless you were trying to create a pseudo real-time app in Java (which is all but an exercise in futility).
However, that said, the way you are doing it is very bad. You should not be exposing value directly, but be using proper data encapsulation via getter and setter methods.
It does not matter from performance perspective.
The recommendation is: do not think about pre-mature optimization. Think about correctness and good design of your code.
For example your code
Does not follow naming conventions: class names must start with capital letter
Contains public fields. It is forbidden. Use bean notation (getters and setters).
Cannot be compiled (there is no type integer. Choose among int and Integer

Is there a Java utility to do a deep comparison of two objects? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
How to "deep"-compare two objects that do not implement the equals method based on their field values in a test?
Original Question (closed because lack of precision and thus not fulfilling SO standards), kept for documentation purposes:
I'm trying to write unit tests for a variety of clone() operations inside a large project and I'm wondering if there is an existing class somewhere that is capable of taking two objects of the same type, doing a deep comparison, and saying if they're identical or not?
Unitils has this functionality:
Equality assertion through reflection, with different options like ignoring Java default/null values and ignoring order of collections
I love this question! Mainly because it is hardly ever answered or answered badly. It's like nobody has figured it out yet. Virgin territory :)
First off, don't even think about using equals. The contract of equals, as defined in the javadoc, is an equivalence relation (reflexive, symmetric, and transitive), not an equality relation. For that, it would also have to be antisymmetric. The only implementation of equals that is (or ever could be) a true equality relation is the one in java.lang.Object. Even if you did use equals to compare everything in the graph, the risk of breaking the contract is quite high. As Josh Bloch pointed out in Effective Java, the contract of equals is very easy to break:
"There is simply no way to extend an instantiable class and add an aspect while preserving the equals contract"
Besides what good does a boolean method really do you anyway? It'd be nice to actually encapsulate all the differences between the original and the clone, don't you think? Also, I'll assume here that you don't want to be bothered with writing/maintaining comparison code for each object in the graph, but rather you're looking for something that will scale with the source as it changes over time.
Soooo, what you really want is some kind of state comparison tool. How that tool is implemented is really dependent on the nature of your domain model and your performance restrictions. In my experience, there is no generic magic bullet. And it will be slow over a large number of iterations. But for testing the completeness of a clone operation, it'll do the job pretty well. Your two best options are serialization and reflection.
Some issues you will encounter:
Collection order: Should two collections be considered similar if they hold the same objects, but in a different order?
Which fields to ignore: Transient? Static?
Type equivalence: Should field values be of exactly the same type? Or is it ok for one to extend the other?
There's more, but I forget...
XStream is pretty fast and combined with XMLUnit will do the job in just a few lines of code. XMLUnit is nice because it can report all the differences, or just stop at the first one it finds. And its output includes the xpath to the differing nodes, which is nice. By default it doesn't allow unordered collections, but it can be configured to do so. Injecting a special difference handler (Called a DifferenceListener) allows you to specify the way you want to deal with differences, including ignoring order. However, as soon as you want to do anything beyond the simplest customization, it becomes difficult to write and the details tend to be tied down to a specific domain object.
My personal preference is to use reflection to cycle through all the declared fields and drill down into each one, tracking differences as I go. Word of warning: Don't use recursion unless you like stack overflow exceptions. Keep things in scope with a stack (use a LinkedList or something). I usually ignore transient and static fields, and I skip object pairs that I've already compared, so I don't end up in infinite loops if someone decided to write self-referential code (However, I always compare primitive wrappers no matter what, since the same object refs are often reused). You can configure things up front to ignore collection ordering and to ignore special types or fields, but I like to define my state comparison policies on the fields themselves via annotations. This, IMHO, is exactly what annotations were meant for, to make meta data about the class available at runtime. Something like:
#StatePolicy(unordered=true, ignore=false, exactTypesOnly=true)
private List<StringyThing> _mylist;
I think this is actually a really hard problem, but totally solvable! And once you have something that works for you, it is really, really, handy :)
So, good luck. And if you come up with something that's just pure genius, don't forget to share!
In AssertJ, you can do:
Assertions.assertThat(expectedObject).isEqualToComparingFieldByFieldRecursively(actualObject);
Probably it won't work in all cases, however it will work in more cases that you'd think.
Here's what the documentation says:
Assert that the object under test (actual) is equal to the given
object based on recursive a property/field by property/field
comparison (including inherited ones). This can be useful if actual's
equals implementation does not suit you. The recursive property/field
comparison is not applied on fields having a custom equals
implementation, i.e. the overridden equals method will be used instead
of a field by field comparison.
The recursive comparison handles cycles. By default floats are
compared with a precision of 1.0E-6 and doubles with 1.0E-15.
You can specify a custom comparator per (nested) fields or type with
respectively usingComparatorForFields(Comparator, String...) and
usingComparatorForType(Comparator, Class).
The objects to compare can be of different types but must have the
same properties/fields. For example if actual object has a name String
field, it is expected the other object to also have one. If an object
has a field and a property with the same name, the property value will
be used over the field.
Override The equals() Method
You can simply override the equals() method of the class using the EqualsBuilder.reflectionEquals() as explained here:
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
Just had to implement comparison of two entity instances revised by Hibernate Envers. I started writing my own differ but then found the following framework.
https://github.com/SQiShER/java-object-diff
You can compare two objects of the same type and it will show changes, additions and removals. If there are no changes, then the objects are equal (in theory). Annotations are provided for getters that should be ignored during the check. The frame work has far wider applications than equality checking, i.e. I am using to generate a change-log.
Its performance is OK, when comparing JPA entities, be sure to detach them from the entity manager first.
I am usin XStream:
/**
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object o) {
XStream xstream = new XStream();
String oxml = xstream.toXML(o);
String myxml = xstream.toXML(this);
return myxml.equals(oxml);
}
/**
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
XStream xstream = new XStream();
String myxml = xstream.toXML(this);
return myxml.hashCode();
}
http://www.unitils.org/tutorial-reflectionassert.html
public class User {
private long id;
private String first;
private String last;
public User(long id, String first, String last) {
this.id = id;
this.first = first;
this.last = last;
}
}
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);
Hamcrest has the Matcher samePropertyValuesAs. But it relies on the JavaBeans Convention (uses getters and setters). Should the objects that are to be compared not have getters and setters for their attributes, this will not work.
import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
import static org.junit.Assert.assertThat;
import org.junit.Test;
public class UserTest {
#Test
public void asfd() {
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertThat(user1, samePropertyValuesAs(user2)); // all good
user2 = new User(1, "John", "Do");
assertThat(user1, samePropertyValuesAs(user2)); // will fail
}
}
The user bean - with getters and setters
public class User {
private long id;
private String first;
private String last;
public User(long id, String first, String last) {
this.id = id;
this.first = first;
this.last = last;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
}
If your objects implement Serializable you can use this:
public static boolean deepCompare(Object o1, Object o2) {
try {
ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
ObjectOutputStream oos1 = new ObjectOutputStream(baos1);
oos1.writeObject(o1);
oos1.close();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos2);
oos2.writeObject(o2);
oos2.close();
return Arrays.equals(baos1.toByteArray(), baos2.toByteArray());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Your Linked List example is not that difficult to handle. As the code traverses the two object graphs, it places visited objects in a Set or Map. Before traversing into another object reference, this set is tested to see if the object has already been traversed. If so, no need to go further.
I agree with the person above who said use a LinkedList (like a Stack but without synchronized methods on it, so it is faster). Traversing the object graph using a Stack, while using reflection to get each field, is the ideal solution. Written once, this "external" equals() and "external" hashCode() is what all equals() and hashCode() methods should call. Never again do you need a customer equals() method.
I wrote a bit of code that traverses a complete object graph, listed over at Google Code. See json-io (http://code.google.com/p/json-io/). It serializes a Java object graph into JSON and deserialized from it. It handles all Java objects, with or without public constructors, Serializeable or not Serializable, etc. This same traversal code will be the basis for the external "equals()" and external "hashcode()" implementation. Btw, the JsonReader / JsonWriter (json-io) is usually faster than the built-in ObjectInputStream / ObjectOutputStream.
This JsonReader / JsonWriter could be used for comparison, but it will not help with hashcode. If you want a universal hashcode() and equals(), it needs it's own code. I may be able to pull this off with a generic graph visitor. We'll see.
Other considerations - static fields - that's easy - they can be skipped because all equals() instances would have the same value for static fields, as the static fields is shared across all instances.
As for transient fields - that will be a selectable option. Sometimes you may want transients to count other times not. "Sometimes you feel like a nut, sometimes you don't."
Check back to the json-io project (for my other projects) and you will find the external equals() / hashcode() project. I don't have a name for it yet, but it will be obvious.
I think the easiest solution inspired by Ray Hulha solution is to serialize the object and then deep compare the raw result.
The serialization could be either byte, json, xml or simple toString etc. ToString seems to be cheaper. Lombok generates free easy customizable ToSTring for us. See example below.
#ToString #Getter #Setter
class foo{
boolean foo1;
String foo2;
public boolean deepCompare(Object other) { //for cohesiveness
return other != null && this.toString().equals(other.toString());
}
}
I guess you know this, but In theory, you're supposed to always override .equals to assert that two objects are truly equal. This would imply that they check the overridden .equals methods on their members.
This kind of thing is why .equals is defined in Object.
If this were done consistently you wouldn't have a problem.
A halting guarantee for such a deep comparison might be a problem. What should the following do? (If you implement such a comparator, this would make a good unit test.)
LinkedListNode a = new LinkedListNode();
a.next = a;
LinkedListNode b = new LinkedListNode();
b.next = b;
System.out.println(DeepCompare(a, b));
Here's another:
LinkedListNode c = new LinkedListNode();
LinkedListNode d = new LinkedListNode();
c.next = d;
d.next = c;
System.out.println(DeepCompare(c, d));
Apache gives you something, convert both objects to string and compare strings, but you have to Override toString()
obj1.toString().equals(obj2.toString())
Override toString()
If all fields are primitive types :
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
#Override
public String toString() {return
ReflectionToStringBuilder.toString(this);}
If you have non primitive fields and/or collection and/or map :
// Within class
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
#Override
public String toString() {return
ReflectionToStringBuilder.toString(this,new
MultipleRecursiveToStringStyle());}
// New class extended from Apache ToStringStyle
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.*;
public class MultipleRecursiveToStringStyle extends ToStringStyle {
private static final int INFINITE_DEPTH = -1;
private int maxDepth;
private int depth;
public MultipleRecursiveToStringStyle() {
this(INFINITE_DEPTH);
}
public MultipleRecursiveToStringStyle(int maxDepth) {
setUseShortClassName(true);
setUseIdentityHashCode(false);
this.maxDepth = maxDepth;
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName,
Collection<?> coll) {
for(Object value: coll){
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName, Map<?, ?> map) {
for(Map.Entry<?,?> kvEntry: map.entrySet()){
Object value = kvEntry.getKey();
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
value = kvEntry.getValue();
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
}}

Categories

Resources