Hello,

I've updated the PR [1] with the following changes:
- made the Map.Entry instance returned by PointMap.getEntry() support
the setValue() method for all spaces and dimensions
- created an abstract base class to share code between the 1D PointMap
implementations
- fixed a bug in the 1D spherical point map remove() method
- added additional unit tests

Supporting setValue() in the multidimensional cases was trivial since
I simply returned the actual SimpleEntry instance stored in the map
instead of an immutable wrapper instance. For the 1D cases, I made
getEntry() return a wrapper instance that calls Map.replace() on the
underlying TreeMap when the value is changed. This forces another key
look up but I believe that the small overhead is worth it in order to
provide a consistent PointMap API. In any case,  the overall
performance is not affected since calling put() or replace() is the
only method available to modify a TreeMap entry (outside of using the
entrySet).

Let me know what you think.

Regards,
Matt

[1] https://github.com/apache/commons-geometry/pull/194

On Wed, Mar 16, 2022 at 12:30 PM Gilles Sadowski <gillese...@gmail.com> wrote:
>
> Hi.
>
> Le mer. 16 mars 2022 à 15:42, Matt Juntunen
> <matt.a.juntu...@gmail.com> a écrit :
> >
> > Hello,
> >
> > > I suggest to carefully consider whether to return a "SimpleEntry"
> > (and prominently note that any sort of concurrent modification is
> > a caller responsibility).
> >
> > I see what you mean and I think that would be a good idea. However,
> > the sticking point is that the 1D implementations for both Euclidean
> > and spherical space internally use the JDK's TreeMap class to store
> > entries, due to its superior performance when compared to the
> > AbstractBucketPointMap class used for other dimensions. TreeMap
> > returns immutable Map.Entry instances from its entry-access methods
> > (e.g., ceilingEntry, floorEntry),
>
> The apidocs[1] state:
> ---CUT---
> Map.Entry<K,V> ceilingEntry(K key)
>    Returns a key-value mapping associated with the least key greater
> than or equal to the given key, or null if there is no such key.
> ---CUT---
>
> > so there is not a straightforward
> > way for us to implement the behavior you propose for these dimensions.
>
> AFAICT, (im)mutability of the returned entry is not part of the
> JDK-mandated API.
> So, assuming that the behaviour is implementation-dependent,
> it can be chosen to be different for different dimensions on the
> basis of which behaviour is most "natural" for applications.
>
> > The options I see are:
> > 1. Have all returned entries be immutable (the current behavior).
> > 2. Return specialized Map.Entry implementations for the 1D cases that
> > call the "put" method on the underlying map when "setValue" is called.
> >
> > Option #2 seems less than ideal so unless there is another approach
> > that I'm missing, I vote for #1.
>
> I agree that the situation is somewhat unsatisfying.  But, as said, I'd
> favour #1 only if there were an actual security promise.  Otherwise,
> immutability is a false claim.
> Unless I'm mistaken, calling "put" in order to update the "value" is
> necessarily less performant than calling "setValue" (map search in
> the former, no-op in the latter).
>
> Regards,
> Gilles
>
> [1] 
> https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#ceilingEntry-K-
>
> > Regards,
> > Matt
> >
> >
> > On Wed, Mar 16, 2022 at 9:48 AM Gilles Sadowski <gillese...@gmail.com> 
> > wrote:
> > >
> > > Hi.
> > >
> > > Le mer. 16 mars 2022 à 03:17, Matt Juntunen
> > > <matt.a.juntu...@gmail.com> a écrit :
> > > >
> > > > Hello,
> > > >
> > > > I've made the following changes to the PR:
> > > > - removed the "resolveKey" method from PointMap
> > > > - renamed PointMap.resolveEntry to PointMap.getEntry and
> > > > PointSet.resolve to PointSet.get
> > > > - added an entry on PointMap/PointSet to the user guide
> > > > - addressed Github comments (thanks, Bruno!)
> > > >
> > > > I ran some performance tests regarding the immutable entry instance
> > > > created in the PointMap.getEntry method and there seems to be no
> > > > impact.
> > > >
> > > > > Furthermore, what is actually meant here by "immutable
> > > > instance" (since the "value" could be mutable without the
> > > > map being aware of the fact)?
> > > >
> > > > It is immutable in that the object reference used as the entry value
> > > > cannot be changed. This reference could point to a mutable object.
> > > > This is the same behavior as other Map implementations.
> > >
> > > I don't see that "reference immutability" is mandated by the
> > > "Map" interface (see e.g. [1]).
> > >
> > > I've noted many times that I generally favour (true) immutability:
> > > It makes much sense for "small" data-structures (e.g. for future
> > > potential optimizations[2]).
> > >
> > > However, the "cloud of points" data-structure is at the opposite
> > > of the spectrum from this POV:  It is intended to contain a large
> > > number of points whose "key" should indeed be (truly) immutable
> > > but whose value would likely need to be mutable for many actual
> > > use cases.
> > > If a "SimpleImmutableEntry" is returned, then in order to modify
> > > the map's "value" contents, one has to (IIUC)
> > >  * retrieve the entry,
> > >  * create a new value,
> > >  * call "put" (on the map)
> > > rather than
> > >  * retrieve the entry
> > >  * call "setValue" (on the entry).
> > > So we have a somewhat crippled API that does not bring any
> > > advantage since reference immutability doesn't provide any
> > > security to the map's user (any other caller who is being passed
> > > the same map, is able to change its contents anyways).
> > >
> > > I suggest to carefully consider whether to return a "SimpleEntry"
> > > (and prominently note that any sort of concurrent modification is
> > > a caller responsibility).
> > >
> > > Regards,
> > > Gilles
> > >
> > > [1] 
> > > https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#entrySet--
> > > [2] 
> > > https://cr.openjdk.java.net/~briangoetz/valhalla/sov/02-object-model.html
> > >
> > > >>> [...]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to