<div dir="auto"><div dir="auto">How beneficial is it to extend equality method without appropriate hashing?</div><div dir="auto"><br></div><div dir="auto">Specifically, given you are working in a domain specific world, e.g. projection of Point3D into XY with equality semantics of equalsByXY, Java does not know how to treat semantically equal objects as equal:</div><div dir="auto"><br></div><div dir="auto">var foo = new Point3D(0,0,0);</div><div dir="auto">var bar = new Point3D(0,0,1);</div><div dir="auto">var set = new HashSet<>(Arrays.asList(foo, bar));</div><div dir="auto">assert set.size() == 1 \\ assertion failure :(</div><div dir="auto"><br></div><div dir="auto">The idea is fine, but you need to wrap a lot of Java's Standard Library to respect the new semantics.</div><div dir="auto"><br></div><div dir="auto">I think that the idea can work nicely as a library, but not inside java.*</div><br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Sun, 11 Feb 2024, 07:41 David Alayachew, <<a href="mailto:davidalayachew@gmail.com">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:monospace">Hello Core Libs Dev Team,</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">I jumped the gun a bit and made a PR for this first. Alan Bateman kindly informed me of my faux pas, and now I'm trying to redo things correctly.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">I am looking to add a new method to java.util.Objects to facilitate equality checks, something that I hope fits well in place with the other methods in this class.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Here is my basic idea. (Special thanks to @liach for guidance in creating this!)</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">```java<br>import java.util.*;<br>import java.util.function.*;<br><br>import static java.util.Objects.*;<br><br>public class Objects2<br>{<br><br> public static <T> BiPredicate<T, T> equalsBy(final List<Function<T, ?>> functions)<br> {<br> <br> requireNonNull(functions, "Objects.equalsBy cannot execute because the parameter is null!");<br> <br> return<br> (final T o1, final T o2) -><br> {<br> <br> requireNonNull(o1, "Cannot check for equality because the first object is null!");<br> requireNonNull(o2, "Cannot check for equality because the second object is null!");<br> <br> for (final var function : functions)<br> {<br> <br> requireNonNull(function, "Cannot check for equality because the
function
is null!");<br> <br> final var r1 = function.apply(o1);<br> final var r2 =
function.apply(o2);<br> <br> final boolean theyAreEqual = Objects.equals(r1, r2);<br> <br> if (!theyAreEqual)<br> {<br> <br> return false;<br> <br> }<br> <br> }<br> <br> return true;<br> <br> }<br> ;<br> <br> }<br><br> public static void main(final String[] args)<br> {</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace"> record Point3D(int x, String y, int z) {}<br> <br> final Point3D a = new Point3D(1, "2", 3);<br> final Point3D b = new Point3D(1, "2", 4);<br> <br> final BiPredicate<Point3D,Point3D> equalsByXY = equalsBy(List.of(Point3D::x, Point3D::y));<br> final BiPredicate<Point3D,Point3D> equalsByXYZ = equalsBy(List.of(Point3D::x, Point3D::y, Point3D::z));<br> <br> System.out.println(equalsByXY.test(a, b)); //true<br> System.out.println(equalsByXYZ.test(a, b)); //false<br> <br> }<br><br>}<br></div><div class="gmail_default" style="font-family:monospace">```</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">The concept is simple -- I want to make it easy to create ad-hoc equals methods.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Object equality is domain-specific -- in some domains, 2 objects are equal, but in another, they are not. The object's equals method is not always a good spot to put this logic into, largely because we don't always know what domain we are in. The object's equals method is where a good default should be placed, not logic for every domain. And even if we tried, it's difficult, if not impossible, to apply equality for the correct domain if both objects are of the same type.<br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">So, for domain-specific contexts, I would like to introduce this method. This method (which should be constant-foldable, thanks again for the help @liach!) lets you clearly say that you are taking 2 objects and comparing them by the following methods that apply to both. And due to the nature of lambdas, developers are not constrained to just the getters of the object in question -- any function that takes in T is fair game. This allows flexibility, and lets developers keep their objects simple, thus facilitating things like DOP.<br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Now, perhaps this makes more sense on the BiPredicate interface instead. However, since this was more equality focused, I figured Objects was a better fit.<br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Any thoughts? <br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Thank you all for your time and help!</div><div class="gmail_default" style="font-family:monospace">David Alayachew<br></div></div>
</blockquote></div></div>