Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #36822 > unrolled thread

no easy way to do a reverse pointer?

Started byEric Douglas <e.d.programmer@gmail.com>
First post2017-07-07 11:56 -0700
Last post2017-07-14 14:32 -0700
Articles 6 — 4 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  no easy way to do a reverse pointer? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 11:56 -0700
    Re: no easy way to do a reverse pointer? Martin Gregorie <martin@address-in-sig.invalid> - 2017-07-07 19:48 +0000
      Re: no easy way to do a reverse pointer? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 13:28 -0700
        Re: no easy way to do a reverse pointer? Martin Gregorie <martin@address-in-sig.invalid> - 2017-07-07 21:47 +0000
        Re: no easy way to do a reverse pointer? Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 18:06 -0400
          Re: no easy way to do a reverse pointer? lewbloch@gmail.com - 2017-07-14 14:32 -0700

#36822 — no easy way to do a reverse pointer?

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-07 11:56 -0700
Subjectno easy way to do a reverse pointer?
Message-ID<6c91c2b4-7d8f-42ba-8a51-eaef43635f49@googlegroups.com>
public class A {
  private B fld;
  public void setFld(B value) {
    fld = value;
  }
}

So field fld is an object, which means it's a pointer to an instance of type B, and I can have multiple instances of A referencing a single instance of B.
So the easiest way for an instance of B to tell you which instances of A hold a reference?

public class A {
  private B fld;
  public void setFld(B value) {
    if (fld != null) {
      fld.dropRef(this);
    }
    value.refer(this);
    fld = value;
  }
}
public class B {
  private HashSet<A> refs = new HashSet();
  public void refer(A value) {
    refs.add(value);
  }
  public HashSet getRefs() {
    return refs;
  }
  public void dropRef(A value) {
    refs.remove(value);
  }
}

[toc] | [next] | [standalone]


#36826

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2017-07-07 19:48 +0000
Message-ID<ojooib$v3s$1@dont-email.me>
In reply to#36822
On Fri, 07 Jul 2017 11:56:34 -0700, Eric Douglas wrote:

> public class A {
>   private B fld;
>   public void setFld(B value) {
>     fld = value;
>   }
> }
> 
> So field fld is an object, which means it's a pointer to an instance of
> type B, and I can have multiple instances of A referencing a single
> instance of B.
> So the easiest way for an instance of B to tell you which instances of A
> hold a reference?
> 
> public class A {
>   private B fld;
>   public void setFld(B value) {
>     if (fld != null) {
>       fld.dropRef(this);
>     } value.refer(this); fld = value;
>   }
> }
> public class B {
>   private HashSet<A> refs = new HashSet();
>   public void refer(A value) {
>     refs.add(value);
>   }
>   public HashSet getRefs() {
>     return refs;
>   }
>   public void dropRef(A value) {
>     refs.remove(value);
>   }
> }

Thats actually backwards: the A instance needs to hold a list of all the 
B instances it owns while each B instance holds a reference to its owning 
A instance. It has to be that way round or you can't easily find all the 
Bs that belong to a selected A. The fun and games comes when you want to 
find all the As that reference a given B. At first glance you just keep a 
list of As in each B but that would be hell on wheels to maintain. 

Its OK to use the array of references once, I've done exactly that for a 
set of rosters I maintain: each Roster header has a list of references to 
the roster Members and they in turn have a list of potential Duty slots. 
This allows a Member to be on more than one Roster. 

Working in reverse is different. Theres another structure with an entry 
per rostered date and each of these has a reference to all the Duty slots 
on that day. 

Another way to tackle this is the use the RDBMS model of insisting that 
each class instance has a unique key. Each list of classes is linked to a 
TreeMap instance which allows all access to by managed by using the keys 
in the TreeMaps. For youe example the ERD looks like this:

      (  A* )
         |
         |
        /|\
      (  B  )

and the list of TreeMaps is:

TreeMap Akey  - holds A's unique prime key and a reference to each A
                instance
TreeMap Bkey  - holds B's unique prime key and a reference to each B
                instance
TreeMap Balt1 - holds alternate key 1 for B and a reference to the B
                instance. The Alternate key is  Bkey.Akey
TreeMap Balt2 - holds alternate key 2 for B and a reference to the B
                instance. The Alternate key is  Bkey.Akey

Using this arrangement you can:
 
- find all B instances belonging to an A instance by using Balt1: 
  they are all linked to the keys whose first part is the A instance
  prime key.

- find all the A instances that are linked to a B instance by using Balt2:
  they are all the keys whose first part is the B prime key  

In practise I used both approaches in the rostering application: 
references are used to build the list of members in each roster and the 
list of possible duty slots for each member, but almost all the cross 
references etc are managed by key access via appropriately ordered 
TreeMaps.


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#36829

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-07 13:28 -0700
Message-ID<1d4174af-ff17-433c-bb32-23e17388e9ff@googlegroups.com>
In reply to#36826
On Friday, July 7, 2017 at 3:52:32 PM UTC-4, Martin Gregorie wrote:
> Thats actually backwards: the A instance needs to hold a list of all the 
> B instances it owns while each B instance holds a reference to its owning 
> A instance. It has to be that way round or you can't easily find all the 
> Bs that belong to a selected A. The fun and games comes when you want to 
> find all the As that reference a given B. At first glance you just keep a 
> list of As in each B but that would be hell on wheels to maintain. 
> 
> Its OK to use the array of references once, I've done exactly that for a 
> set of rosters I maintain: each Roster header has a list of references to 
> the roster Members and they in turn have a list of potential Duty slots. 
> This allows a Member to be on more than one Roster. 
> 
> Working in reverse is different. Theres another structure with an entry 
> per rostered date and each of these has a reference to all the Duty slots 
> on that day. 
> 
> Another way to tackle this is the use the RDBMS model of insisting that 
> each class instance has a unique key. Each list of classes is linked to a 
> TreeMap instance which allows all access to by managed by using the keys 
> in the TreeMaps. For youe example the ERD looks like this:
> 
>       (  A* )
>          |
>          |
>         /|\
>       (  B  )
> 
> and the list of TreeMaps is:
> 
> TreeMap Akey  - holds A's unique prime key and a reference to each A
>                 instance
> TreeMap Bkey  - holds B's unique prime key and a reference to each B
>                 instance
> TreeMap Balt1 - holds alternate key 1 for B and a reference to the B
>                 instance. The Alternate key is  Bkey.Akey
> TreeMap Balt2 - holds alternate key 2 for B and a reference to the B
>                 instance. The Alternate key is  Bkey.Akey
> 
> Using this arrangement you can:
>  
> - find all B instances belonging to an A instance by using Balt1: 
>   they are all linked to the keys whose first part is the A instance
>   prime key.
> 
> - find all the A instances that are linked to a B instance by using Balt2:
>   they are all the keys whose first part is the B prime key  
> 
> In practise I used both approaches in the rostering application: 
> references are used to build the list of members in each roster and the 
> list of possible duty slots for each member, but almost all the cross 
> references etc are managed by key access via appropriately ordered 
> TreeMaps.
> 

Exactly, I think, but where to put the maps?

Instead of A and B maybe it's easier to see a practical model.

public class KitchenDuty {
}

public class NightWatchDuty {
}

public class Soldier {
}

Now, the easiest way to set and get a soldier's duties?
Any one soldier may be assigned multiple duties.
Any duty may have multiple soldiers.
We need to be able to list which soldiers are on any given duty.
We need to be able to list which duties are assigned to any given soldier.

Either each of these classes has a HashSet field and maintains a list of duties/soldiers as they're added/removed, or our independent class holds HashSets and maintains as it adds and removes.

public class MyApplication {
  static public void main(String[] args) {
    KitchenDuty kd = new KitchenDuty();
    Soldier s1 = new Soldier();
    Soldier s1 = new Soldier();
    HashSet kds = new HashSet();
    s1.assignDuty(kd);
    kds.add(s1);
    s2.assignDuty(kd);
    kds.add(s2);
  }
}

This ^^ independent method sounds ugly.  I just want to be able to say kd.listSolders() and s1.listDuties(), so adding a pointer to one should automatically add back a pointer to the other?

[toc] | [prev] | [next] | [standalone]


#36832

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2017-07-07 21:47 +0000
Message-ID<ojovht$qok$1@dont-email.me>
In reply to#36829
On Fri, 07 Jul 2017 13:28:05 -0700, Eric Douglas wrote:

> On Friday, July 7, 2017 at 3:52:32 PM UTC-4, Martin Gregorie wrote:
>> Thats actually backwards: the A instance needs to hold a list of all
>> the B instances it owns while each B instance holds a reference to its
>> owning A instance. It has to be that way round or you can't easily find
>> all the Bs that belong to a selected A. The fun and games comes when
>> you want to find all the As that reference a given B. At first glance
>> you just keep a list of As in each B but that would be hell on wheels
>> to maintain.
>> 
>> Its OK to use the array of references once, I've done exactly that for
>> a set of rosters I maintain: each Roster header has a list of
>> references to the roster Members and they in turn have a list of
>> potential Duty slots. This allows a Member to be on more than one
>> Roster.
>> 
>> Working in reverse is different. Theres another structure with an entry
>> per rostered date and each of these has a reference to all the Duty
>> slots on that day.
>> 
>> Another way to tackle this is the use the RDBMS model of insisting that
>> each class instance has a unique key. Each list of classes is linked to
>> a TreeMap instance which allows all access to by managed by using the
>> keys in the TreeMaps. For youe example the ERD looks like this:
>> 
>>       (  A* )
>>          |
>>          |
>>         /|\
>>       (  B  )
>> 
>> and the list of TreeMaps is:
>> 
>> TreeMap Akey  - holds A's unique prime key and a reference to each A
>>                 instance
>> TreeMap Bkey  - holds B's unique prime key and a reference to each B
>>                 instance
>> TreeMap Balt1 - holds alternate key 1 for B and a reference to the B
>>                 instance. The Alternate key is  Bkey.Akey
>> TreeMap Balt2 - holds alternate key 2 for B and a reference to the B
>>                 instance. The Alternate key is  Bkey.Akey
>> 
>> Using this arrangement you can:
>>  
>> - find all B instances belonging to an A instance by using Balt1:
>>   they are all linked to the keys whose first part is the A instance
>>   prime key.
>> 
>> - find all the A instances that are linked to a B instance by using
>> Balt2:
>>   they are all the keys whose first part is the B prime key
>> 
>> In practise I used both approaches in the rostering application:
>> references are used to build the list of members in each roster and the
>> list of possible duty slots for each member, but almost all the cross
>> references etc are managed by key access via appropriately ordered
>> TreeMaps.
>> 
>> 
> Exactly, I think, but where to put the maps?
> 
> Instead of A and B maybe it's easier to see a practical model.
> 
> public class KitchenDuty {
> }
> 
> public class NightWatchDuty {
> }
> 
> public class Soldier {
> }
> 
> Now, the easiest way to set and get a soldier's duties?
> Any one soldier may be assigned multiple duties.
>
Yes, that's OK, but there's almost certainly more structure that needs to 
be there to understand the problem. For starteds you need some sort of 
duty diary. The days in this would be initially populated with the 
appropriate number of unassigned duties of each type.

> Any duty may have multiple soldiers.
>
Probably not, but that depends on the representation: the 'Duty Rota' of 
a specific type will have a bunch of soldiers (one per duty slot), but if 
you consider that a Duty is might be defined as "Main Gate duty on the 
morning of 13 August 2017, then it quickly becomes obvious that a Duty 
instance has one soldier assigned to do it.

> We need to be able to list which soldiers are on any given duty.
> We need to be able to list which duties are assigned to any given
> soldier.
> 
Yes, indeed, and the lists are quite different because of how they'll be 
used and by whom. 

The list of who has what duty needs to show the soldier doing each duty 
on every day: it is probably a matrix with date and time down the side, 
duty type across the top and a soldier's name in each cell.

OTOH a soldier's list only needs to show, ordered by date and time, what 
type of duty each is, when he'll be on it and where it is (assuming the 
duty slot's name doesn't indicate where it will be performed.
 
> Either each of these classes has a HashSet field and maintains a list of
> duties/soldiers as they're added/removed, or our independent class holds
> HashSets and maintains as it adds and removes.
> 
> public class MyApplication {
>   static public void main(String[] args) {
>     KitchenDuty kd = new KitchenDuty();
>     Soldier s1 = new Soldier(); Soldier s1 = new Soldier(); HashSet kds
>     = new HashSet(); s1.assignDuty(kd);
>     kds.add(s1);
>     s2.assignDuty(kd);
>     kds.add(s2);
>   }
> }
> 
> This ^^ independent method sounds ugly.  I just want to be able to say
> kd.listSolders() and s1.listDuties(), so adding a pointer to one should
> automatically add back a pointer to the other?
>
Agreed. It looks as though Duty may be a good candidate for subtyping, 
though it may work equally well as a single class with its type being 
either a class attribute or derived from the column its linked to in the 
duty rota. This is something that should only be decided when the problem 
is completely understood and (preferably) after data analysis has 
generated an ERD linking the various entities (classes) and listed the 
main attributes of each entity.
 

-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#36833

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2017-07-07 18:06 -0400
Message-ID<ojp0ea$7l6$1@dont-email.me>
In reply to#36829
On 7/7/2017 4:28 PM, Eric Douglas wrote:
> [...]
> 
> public class KitchenDuty {
> }
> 
> public class NightWatchDuty {
> }
> 
> public class Soldier {
> }
> 
> Now, the easiest way to set and get a soldier's duties?
> Any one soldier may be assigned multiple duties.
> Any duty may have multiple soldiers.
> We need to be able to list which soldiers are on any given duty.
> We need to be able to list which duties are assigned to any given soldier.

     Maybe a single central Set<Assignment> would suffice, where
each Assignment associates one Soldier with one Duty.  (It might
also record the Officer who made the Assignment, so you can check
whether some other Officer has sufficient rank to overrule it ...)

-- 
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.

[toc] | [prev] | [next] | [standalone]


#36940

Fromlewbloch@gmail.com
Date2017-07-14 14:32 -0700
Message-ID<ee84dcfb-e9e9-470e-ad0a-08a46908493d@googlegroups.com>
In reply to#36833
This type of cross-reference is common in JPA, with its `@OneToMany`, `@ManyToOne`, and `@ManyToMany` relationships. These are modeled as contained collections. 

One to many is something like:

    public class Manager {
      Set<Employee> underlings;
      ...
    }

Many to one is like:

    public class Employee {
      Manager manager;
      ...
    }

Many to many:

    public class Employee {
      Set<Project> projects;
      ...
    }

    public class Project {
      Set<Employee> members;
      ...
    }

It's a pretty standard, long-standing, and well documented approach.

--
Lew

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web