Implementing bidirectional relations between objects of the same class - java

I have to implement a class whose instances have a bidirectional relation to each other. For example I have the class FooBar which should offer the method sameAs(FooBar x) and maintain a Set for each instances containing its equivalent instances. So if I call foo.sameAs(bar), the Set in foo should contain bar and vice versa. Invoking bar.sameAs(foo) doesn't work, of course.
For clarifiction: the instances of this class are only semantically equal. equals should still return false.
The solutions I've come up with is either to implement a private method internalSameAs(FooBar x) which is invoked from sameAs(FooBar x) or to use a static method sameAs(FooBar x, FooBar y).
Solution 1:
class FooBar {
Set<FooBar> sameAs = new HashSet<FooBar>();
public void sameAs(FooBar x) {
this.internalSameAs(x);
x.internalSameAs(this);
}
public void internalSameAs(FooBar x) {
sameAs.add(x);
}
}
Solution 2:
class FooBar {
Set<FooBar> sameAs = new HashSet<FooBar>();
public static void sameAs(FooBar x, FooBar y) {
x.sameAs.add(y);
y.sameAs.add(x);
}
}
Which one would you prefer and why? Or is there another way I didn't think about?

The naming you've used is confusing. sameAs sounds as though it's a test which should return a boolean, but from your code it seems it would be more appropriately named declareSameAs. When you call foo.sameAs(bar), you're declaring that foo and bar are the same, not doing a test, correct?
The problem is that with your code you can declare
x.sameAs(y);
y.sameAs(z);
but it won't be the case that x is the same as z, which is presumably not what you want (and if it is what you want, you definitely need to change the method name).
It seems to me you want to divide your instances into sets, and have each instance keep a reference to the set it's in (not to a separate set internal to the instance). When you make a new declaration that two instances are the same, you need to combine the sets, and ensure all affected instances have a reference to the combined set.

are you flexible with the data structures to be used? If so you could use a Multimap (from Guava Collections) that is static amongst all the instances of the class FooBar. In that Multimap you can have the keys as FooBar references (or a unique id if you have one) and the values would be the references (or id.s) of the FooBars that have the sameAs relation.

Maybe there's a different way: sameAs sounds pretty similiar to equals. If we do not need equals for something else, then I'd simply implement the equals method on FooBar so that we simply do a
if (foo.equals(bar))
System.out.println("We're equal (aka: 'equivalent/the same')");
In this case, we do not need any set - just a rule to determine, if two instances are equal.
You could store the sameness information in a separate datastructure outside of those classes. A central map could do the job:
HashMap<FooBar, Set<FooBar>> sameFooBars;
If you have "same" objects, simply add them to the map:
public static void addSameObjects(FooBar foo1, FooBar foo2) {
Set<FooBar> set = getMap().get(foo1);
if (set == null) {
set = new HashSet<FooBar>();
getMap().put(foo1, set);
}
set.add(foo2);
// serious implementation avoid code duplication...
set = getMap().get(foo2);
if (set == null) {
set = new HashSet<FooBar>();
getMap().put(foo2, set);
}
set.add(foo1);
}
And the test:
public static boolean isSame(FooBar foo1, FooBar foo2) {
if (getMap().get(foo1) == null)
return false;
return getMap().get(foo1).contains(foo2);
}

Do you really need to maintain a list of equivalences in ALL objects? If possible I would separate the set of equivalences from the objects themselves. This will be easier to maintain.
Then you can use the multimap of #posdef or more simply a Map> to stay with standard JAVA API.

Your "bidirectional" samesAs(...) method sounds like Object.equals(...), which, according to javadoc is a "an equivalence relation on non-null object references". If this is what you want, then you just have to override equals in your class.
I'm a bit lost when you say that "FooBar shouldmaintain a Set for each instances containing its equivalent instances". If you want to build equivalent classes for FooBar objects, then I think it's a good idea to use a java Collection to represent them, and more precisely a Set.
Here is a quickly hacked example:
public class FooBar {
#Override
public boolean equals(Object other) {
// do whatever fancy computation to determine if
// the object other is equal to this object
}
}
and for the equivalent class:
#SuppressWarnings("serial")
public class FooBarEquivalentClass extends HashSet<FooBar> {
#Override
public boolean add(FooBar e) {
if (isEmpty())
return super.add(e);
else if (e.equals(iterator().next()))
return super.add(e);
else
return false;
}
}

"same as" but not "equal to" sounds like you should be using Comparable.
I think it makes more sense to implement compareTo() or sameAs() as an instance method rather than a static since you will always need two real instances to do any comparison.

Sounds like what you want are to separate the equivalence groups from the object instances.
Make a Map<FooBar, Set<FooBar>> and note that when you lookup an object the set will include itself.

Related

How to use an object that was called from a method in Java?

I'm trying to figure out what the syntax is for calling an object inside a method..
Pseudocode:
boolean check(Object someObject) {
return someObject == theOtherObject;
}
public static void main(String args[]) {
someClass one = new someClass();
someClass two = new someClass();
one.check(two);
}
So the check method is supposed to check whether the two objects are equal, but how would I specify the other object (theOtherObject should be one)?
Thanks in advance!
One word answer: this
boolean check(Object someObject) {
return someObject == this;
}
which will test object identity only. You should override equals and use that.
if (one.equals(two)) {
// ...
}
You can have the boolean check(Object o) method inside SomeClass and check
boolean check(Object o) {
this == (SomeClass) o;
}
This would work only if both reference variables are pointing to same object. Moreover the right way to check if two objects are meaningfully equal would be to use the inherited equals and hashCode method.
Override equals and hashCode method.
Why do I need to override the equals and hashCode methods in Java?
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
So what you're asking for there is actually already a command in java.lang.Objects class to compare to objects.
one.equals(two)
the comparison this does is called a shallow comparison. So if that's what you're looking to do then this would work. For reference, the definitions of shallow comparison defined by geeksforgeeks.org is
Shallow comparison: The default implementation of equals method is defined in Java.lang.Object class which simply checks if two Object references (say x and y) refer to the same Object. i.e. It checks if x == y. Since Object class has no data members that define its state, it is also known as a shallow comparison.
if you're looking to do a more complicated comparison you're the best bet would be to actually override the equals command in the one class file
this article would be a good place to start to learn more about this topic.
https://www.geeksforgeeks.org/equals-hashcode-methods-java/

Custom equals outside of the class definition

Is there a way to write a custom equals method compactly when trying to compare two objects but not relying on those objects' internal equals() method? For example, if I had two Foo objects like so:
public class Foo {
int id;
String name;
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Foo item = (Foo) o;
return id == item.id && listId == item.name;
}
}
But, in a use case for the foo objects, lets say I just want them equated by their id. Keep in mind this is a toy example and the real use case has many more fields so I may have an object with 6 fields all being used in the overridden equals method but may want to only use 3 of them to do an equals outside the class when comparing two objects.
List<Foo> objType1;
List<Foo> objType2;
Compare the two lists and assert each Foo object is equal but only use a subset of the fields of Foo in the comparison. I dont want to touch the actual Foo object in any way. How can i do this outside of asserting by handing that each field I am interested in is equal?
The complexity of the solution really depends on the use case. Universally - no, one cannot do it without direct bytecode manipulation.
A lot of Java APIs allow using custom Comparator as an option. E.g. if you want to compare two lists of Foo's with custom comparator:
List<Foo> list1 = ...
List<Foo> list2 = ...
Comparator<Foo> c = Comparator.comparing(Foo::getId);
boolean equal = list1.size() == list2.size() &&
IntStream.range(0, list1.size())
.allMatch(i -> c.compare(list1.get(i), list2.get(i)) == 0);
Note, this solution does not check for list1 or list2 being null's and assumes your Foo has standard getters like getId(). Also, if you don't deal with lists but with abstract iterable collections, you might want to look into zip implementations. Comparator.comapring() is chainable like this Comparator.comparing(Foo::getId).thenComparing(Foo::getAttrX).thenComparing(Foo:getAttrY)...; which is fairly convenient and readable.
Another option you might want to look at to customize equals() for a variety of cases is to use Proxy.newProxyInstance() with your custom equals override, i.e. auto-create proxy wrapper around your instances when filling collections etc.
UPDATE
Using Comparator.comparing().thenComparing()... chain might seem to be tricky. It helps to understand that lambdas for these functions need to extract either primitives or Comparable descendants (i.e. implements Comparable and has compareTo() method) from the given top level object reference - in our case, Foo. If Foo would have a Bar getBar() accessor that has to be included into comparison, then either go down to the primitive - .thenComparing(f -> f.getBar().getName()) or make Bar implement Comparable. Don't forget to treat nulls properly, if you go the route of custom lambda functions - which is, sometimes, a challenge on it's own.
The positive of an approach in this answer is that Comparator defines a total order over the set of objects stored in the lists. The negative of this approach is, this total order is not really needed for simple comparison - if it is really all you need. In some cases, writing a good old for loop and doing all the comparisons "manually" might be less confusing. From experience, in most cases having an order is beneficial, if not now, then in the next release.
You could add some extra field(s) to your Foo class that will be used in your overriden equals method to specify which fields should be used to deteremine whether two instances are equal. You could then set those fields before comparing. Then your equals method might contain:
if ( useFiledA ) {
if ( this.a != item.a ) return false;
}
if ( useFiledB ) {
if ( this.b != item.b ) return false;
}
// etc.
return true;
implements Comparable from your classes. then write the compareTo method. iterate ocer the first list and call colpareTo over all the elements of the second list

Run equal method defined by parent class from outside the class

If I have a complex hierachy of inheritance and I want to do an equality check that depends on a specific equality is there a way to ensure I run using that equality check and not a version overridden by a child class that may behave different then I want?
To give an example lets say I have a foo with it's own equality class, and then I have something like boo with an equals class sort of like below sudocode (too lazy to right it out in full)
class Foo {
int id;
int otherId;
int count;
public boolean equals(Object other){
//check other instance of foo and re-cast
return (id==other.id && otherId==other.otherId)
}
}
class Bar extends Foo{
private someObject uniqueValue;
public boolean equals(Object other){
//check other instance of foo and re-cast
return super.equals(other) && other.getUniqueValue.equals(this.getUniqueValue);
{
}
Then I have some method which takes too foo objects which reference the same foo and add up the counts for them
public combineFoos(Foo foo1, Foo foo2){
if(! foo1.equals(foo2))
throw IllegalArgumentException("no match");
Foo combinedFoo=new Foo(foo1.id, foo1.otherId, (foo1.count + foo2.count))
return combinedFoo
}
}
In theory this all works, until the bar value comes in. Now if I call combineFoo and pass in a bar to foo1 it fails, because bars equal method checks foo2 is an instanceOf bar. I really don't care if foo2 is a bar, the information I need is available for any foo. For that matter if I pass in two unequal bars that both are equal as defined by foo's equality method (ie only the uniqueValue fields are different) I would want the combineFoo to still accept them as equal Foo's, even if not equal by Bar's definition.
The problem is that I want to do an equality check on exactly what a FOO considers as equal, but I don't know what bizarre inherited class I may actually receive. Is there a way to work around this, to basically say in my combineFoo to always use a FOOs definition of equals, even if it is overridden by a child class?
Related, would this be a far worse idea then I imagine it be even if doable, or is there some other way to handle something like the above example, short of effectively re-writing foo's equal method within the combineFoo?
Your equals methods fail the symmetry test, if a.equals(b) then b.equals(a). The obvious way to fix it would be to check the class like so:
public boolean equals(Object other){
if(other.getClass() != this.getClass()) return false;
return (id==other.id && otherId==other.otherId)
}
Having said that you may wish to allow some pairs of subclasses to be considered equal to each other - in which case I suggest you check out this question:
Java - equals method in base class and in subclasses

Make an object read only in Java [duplicate]

If an object reference is passed to a method, is it possible to make the object "Read Only" to the method?
Not strictly speaking. That is, a reference that can mutate an object can not be turned into a reference that can not mutate an object. Also, there is not way to express that a type is immutable or mutable, other than using conventions.
The only feature that ensure some form of immutability would be final fields - once written they can not be modified.
That said, there are ways to design classes so that unwanted mutation are prevented. Here are some techniques:
Defensive Copying. Pass a copy of the object, so that if it is mutated it doesn't break your internal invariants.
Use access modifiers and/or interface to expose only read-only methods. You can use access modifieres (public/private/protected), possibly combined with interface, so that only certain methods are visible to the other object. If the methods that are exposed are read-only by nature, you are safe.
Make your object immutable by default. Any operation on the object returns actually a copy of the object.
Also, note that the API in the SDK have sometimes methods that return an immutable version of an object, e.g. Collections.unmodifiableList. An attempt to mutate an immutable list will throw an exception. This does not enforce immutability statically (at compile-time with the static type system), but is is a cheap and effective way to enforce it dynamically (at run-time).
There has been many research proposals of Java extension to better control of aliasing, and accessibility. For instance, addition of a readonly keyword. None of them is as far as I know planned for inclusion in future version of Java. You can have a look at these pointers if you're interested:
Why We Should Not Add ''Read-Only'' to Java (yet) -- it lists and compare most of the proposals
The Checker Framework: Custom pluggable types for Java -- a non intrusive way to extend the type system, notably with immutable types.
The Checker Framework is very interesting. In the Checker Framework, look at Generic Universe Types checker, IGJ immutability checker, and Javari immutability checker. The framework works using annotations, so it is not intrusive.
No, not without decorating, compositing, cloning, etc.
There's no general mechanism for that. You'll need to write special-case code to achieve it, like writing an immutable wrapper (see Collections.unmodifiableList).
You could achieve a similar thing in most cases by cloning the Object as the first statement of the method, such as this...
public void readOnlyMethod(Object test){
test = test.clone();
// other code here
}
So if you called readOnlyMethod() and pass in any Object, a clone of the Object will be taken. The clone uses the same name as the parameter of the method, so there's no risk of accidentally changing the original Object.
No. But you could try to clone the object before passing it, so any changes made by the method won't affect the original object.
making it implement a interface which has only read only methods (no setter methods) this gives a copy of an object (road-only copy) and returning the read only instance of interface instead of returning the instance of an object itself
You could define all parameters of the objects as final but that makes the object read only to everyone.
I believe your real question is about avoiding escape references.
As pointed out in some answers to extract an Interface from class and expose only get methods. It will prevent modification by accident but it is again not a foolproof solution to avoid above problem.
Consider below example:
Customer.java:
public class Customer implements CustomerReadOnly {
private String name;
private ArrayList<String> list;
public Customer(String name) {
this.name=name;
this.list = new ArrayList<>();
this.list.add("First");
this.list.add("Second");
}
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public ArrayList<String> getList() {
return list;
}
public void setList(ArrayList<String> list) {
this.list = list;
}
}
CustomerReadOnly.java:
public interface CustomerReadOnly {
String getName();
ArrayList<String> getList();
}
Main.java:
public class Test {
public static void main(String[] args) {
CustomerReadOnly c1 = new Customer("John");
System.out.println("printing list of class before modification");
for(String s : c1.getList()) {
System.out.println(s);
}
ArrayList<String> list = c1.getList();
list.set(0, "Not first");
System.out.println("printing list created here");
for(String s : list) {
System.out.println(s);
}
System.out.println("printing list of class after modification");
for(String s : c1.getList()) {
System.out.println(s);
}
}
}
Ouput:
printing list of class before modification
First
Second
printing list created here
Not first
Second
printing list of class after modification
Not first
Second
So, as you can see extracting interface and exposing only get methods works only if you don't have any mutable member variable.
If you have a collection as a member variable whose reference you don't want to get escape from class, you can use Collections.unmodifiableList() as pointed out in ewernli's answer.
With this no external code can modify the underlying collection and your data is fully read only.
But again when it comes to custom objects for doing the same, I am aware of the Interface method only as well which can prevent modification by accident but not sure about the foolproof way to avoid reference escape.
Depending on where you want the rule enforced. If you are working collaboratively on a project, use final with a comment telling the next person they are not meant to modify this value. Otherwise wouldn't you simply write the method to not touch the object?
public static void main(String[] args) {
cantTouchThis("Cant touch this");
}
/**
*
* #param value - break it down
*/
public static void cantTouchThis(final String value) {
System.out.println("Value: " + value);
value = "Nah nah nah nah"; //Compile time error
}
So specifically to this method, the value will never be written to, and it is enforced at compile time making the solution extremely robust. Outside the scope of this method, the object remains unaltered without having to create any sort of wrapper.
private boolean isExecuteWriteQueue = false;
public boolean isWriting(){
final boolean b = isExecuteWriteQueue;
return b;
}
Expanding on ewernli's answer...
If you own the classes, you can use read-only interfaces so that methods using a read-only reference of the object can only get read-only copies of the children; while the main class returns the writable versions.
example
public interface ReadOnlyA {
public ReadOnlyA getA();
}
public class A implements ReadOnlyA {
#Override
public A getA() {
return this;
}
public static void main(String[] cheese) {
ReadOnlyA test= new A();
ReadOnlyA b1 = test.getA();
A b2 = test.getA(); //compile error
}
}
If you don't own the classes, you could extend the class, overriding the setters to throw an error or no-op, and use separate setters. This would effectively make the base class reference the read-only one, however this can easily lead to confusion and hard to understand bugs, so make sure it is well documented.

Is there a standard class which wraps a reference and provides a getter and setter?

Sorry for the stupid question.
I'm very sure, that the Java API provides a class which wraps a reference,
and provides a getter and a setter to it.
class SomeWrapperClass<T> {
private T obj;
public T get(){ return obj; }
public void set(T obj){ this.obj=obj; }
}
Am I right? Is there something like this in the Java API?
Thank you.
Yes, I could write it y myself, but why should I mimic existing functionality?
EDIT: I wanted to use it for reference
parameters (like the ref keyword in C#), or more specific,
to be able to "write to method parameters" ;)
There is the AtomicReference class, which provides this. It exists mostly to ensure atomicity, especially with the getAndSet() and compareAndSet() methods, but I guess it does what you want.
When I started programming in Java after years of writing C++, I was concerned with the fact that I could not return multiple objects from a function.
It turned out that not only was it possible but it was also improving the design of my programs.
However, Java's implementation of CORBA uses single-element arrays to pass things by reference. This also works with basic types.
I'm not clear what this would be for, but you could use one of the subclasses of the Reference type. They set the reference in the constructor rather than setter.
It' worth pointing out that the Reference subclasses are primarily intended to facilitate garbage collection, for example when used in conjunction with WeakHashMap.
I'm tempted to ask why you'd want one of these, but I assume it's so you can return multiple objects from a function...
Whenever I've wanted to do that, I've used an array or a container object...
bool doStuff(int params, ... , SomeObject[] returnedObject)
{
returnedObject[0] = new SomeObject();
return true;
}
void main(String[] args)
{
SomeObject myObject;
SomeObject[1] myObjectRef = new SomeObject[1];
if(doStuff(..., myObjectRef))
{
myObject = myObjectRef[0];
//handle stuff
}
//could not initialize.
}
... good question, but have not come across it. I'd vote no.
.... hm, after some reflection, reflection might be what comes close to it:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
there is java.lang.ref.Reference, but it is immutable (setter is missing). The java.lang.ref documentation says:
Every reference object provides methods for getting and clearing the reference. Aside from the clearing operation reference objects are otherwise immutable, so no set operation is provided. A program may further subclass these subclasses, adding whatever fields and methods are required for its purposes, or it may use these subclasses without change.
EDIT
void refDemo(MyReference<String> changeMe) {
changeMe.set("I like changing!");
...
the caller:
String iWantToChange = "I'm like a woman";
Reference<String> ref = new MyReference<String>(iWantToChange)
refDemo(myRef);
ref.get();
I don't like it however, too much code. This kind of features must be supported at language level as in C#.
If you are trying to return multiple values from a function, I would create a Pair, Triple, &c class that acts like a tuple.
class Pair<A,B> {
A a;
B b;
public void Pair() { }
public void Pair(A a,B b) {
this.a=a;
this.b=b;
}
public void Pair( Pair<? extends A,? extends B> p) {
this.a=p.a;
this.b=p.b;
}
public void setFirst(A a) { this.a=a; }
public A getFirst() { return a; }
public void setSecond(B b) { this.b=b; }
public B getSecond() { return b; }
}
This would allow you to return 2 (techically infinite) return values
/* Reads a line from the provided input stream and returns the number of
* characters read and the line read.*/
public Pair<Integer,String> read(System.in) {
...
}
I think there is no Java API Class designed for your intent, i would also prefer your example (the Wrapper Class) then using this "array-trick" because you could insert later some guards or can check several thinks via aspects or reflection and you're able to add features which are cross-cutting-concerns functionality.
But be sure that's what you want to do! Maybe you could redesign and come to another solutions?

Categories

Resources