Thoughts on a new method for equality on java.util.Objects?
Holo The Sage Wolf
holo3146 at gmail.com
Sun Feb 11 08:25:57 UTC 2024
How beneficial is it to extend equality method without appropriate hashing?
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:
var foo = new Point3D(0,0,0);
var bar = new Point3D(0,0,1);
var set = new HashSet<>(Arrays.asList(foo, bar));
assert set.size() == 1 \\ assertion failure :(
The idea is fine, but you need to wrap a lot of Java's Standard Library to
respect the new semantics.
I think that the idea can work nicely as a library, but not inside java.*
On Sun, 11 Feb 2024, 07:41 David Alayachew, <davidalayachew at gmail.com>
wrote:
> Hello Core Libs Dev Team,
>
> 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.
>
> 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.
>
> Here is my basic idea. (Special thanks to @liach for guidance in creating
> this!)
>
> ```java
> import java.util.*;
> import java.util.function.*;
>
> import static java.util.Objects.*;
>
> public class Objects2
> {
>
> public static <T> BiPredicate<T, T> equalsBy(final List<Function<T, ?>>
> functions)
> {
>
> requireNonNull(functions, "Objects.equalsBy cannot execute because
> the parameter is null!");
>
> return
> (final T o1, final T o2) ->
> {
>
> requireNonNull(o1, "Cannot check for equality because the
> first object is null!");
> requireNonNull(o2, "Cannot check for equality because the
> second object is null!");
>
> for (final var function : functions)
> {
>
> requireNonNull(function, "Cannot check for equality because
> the function is null!");
>
> final var r1 = function.apply(o1);
> final var r2 = function.apply(o2);
>
> final boolean theyAreEqual = Objects.equals(r1, r2);
>
> if (!theyAreEqual)
> {
>
> return false;
>
> }
>
> }
>
> return true;
>
> }
> ;
>
> }
>
> public static void main(final String[] args)
> {
>
> record Point3D(int x, String y, int z) {}
>
> final Point3D a = new Point3D(1, "2", 3);
> final Point3D b = new Point3D(1, "2", 4);
>
> final BiPredicate<Point3D,Point3D> equalsByXY =
> equalsBy(List.of(Point3D::x, Point3D::y));
> final BiPredicate<Point3D,Point3D> equalsByXYZ =
> equalsBy(List.of(Point3D::x, Point3D::y, Point3D::z));
>
> System.out.println(equalsByXY.test(a, b)); //true
> System.out.println(equalsByXYZ.test(a, b)); //false
>
> }
>
> }
> ```
>
> The concept is simple -- I want to make it easy to create ad-hoc equals
> methods.
>
> 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.
>
> 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.
>
> 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.
>
> Any thoughts?
>
> Thank you all for your time and help!
> David Alayachew
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240211/7c3bb681/attachment.htm>
More information about the core-libs-dev
mailing list