3

I have some objects, lets just call them Person objects. I also have some other objects, lets call them Relationship objects.

I want to be able to assign a Relationship object between two Person objects, but I'm not really sure what a good way to go about this is.

I was thinking of maybe giving each Person object an ID and then creating a 2D array of Relationship objects using the Person object ID as the key values.

I'm not sure if that's the best approach though as the array would have a lot of null values wherever there isn't a relationship between two Person objects.

user11406
  • 1,208
  • 1
  • 13
  • 25
  • 1
    You could have each Person contain a list of all the Relationships it's in. If you want to store them externally, you can use a nested map (or Guava's Table). – Jeffrey Bosboom Apr 25 '15 at 19:24
  • If I understand correctly, you want to be able, given two persons, to know if a relationship exists between them. Create a Key class containing two persons, or two person IDs, and use a Map. Make sure to properly implement hashCode() and equals(). – JB Nizet Apr 25 '15 at 19:27
  • If you are open to using 3rd party libraries, then I **HIGHLY** recommend Neo4j. It maps this type of stuff using graphs and you can use it's query language to efficiently reason over the structure. –  Apr 25 '15 at 19:41

4 Answers4

2

@Makoto's a good idea. Alternatively, what sounds to me a litte bit more natural is to have Relationship object hold two Person objects passed e.g. as constructor arguments. You'll then need to track only the Relationship objects because they'll have knowledge about both Persons that are the parts of it.

class Relationship {
Person firstPerson;
Person secondPerson;

  public Relationship(Person firstPerson, Person secondPerson) {
    this.firstPerson = firstPerson;
    this.secondPerson = secondPerson;
}

Alternatively you can use a public method to pass the reference to the Person objects if you don't want them to be passed via constructor:

public void setPersons(Person firstPerson, Person secondPerson) {
  this.firstPerson = firstPerson;
  this.secondPerson = secondPerson;
}
ttarczynski
  • 949
  • 1
  • 10
  • 19
1

What you describe are three instances: two Person instances and one Relationship instance.

The most straightforward approach is, in the Person class, allow for a Relationship instance to exist, and to wire up the relationships of a Relationship between these two Persons.

class Person {
    Relationship relationship;

    public void createRelationship(Person person) {
        relationship = new Relationship(this, person);
    }
}

If you wanted the Relationship instance back to keep in a collection or array, you could modify that to simply return a new Relationship as the result of two Persons.

 class Relationship {

    public static Relationship createRelationshipFrom(Person firstPerson, Person secondPerson) {
        return new Relationship(firstPerson, secondPerson);
    }
}
Makoto
  • 104,088
  • 27
  • 192
  • 230
  • "If you wanted the Relationship instance back to keep in a collection or array, you could modify that to simply return a new Relationship as the result of two Persons." Yes, this is what I'm asking. How would I best do that? A 2D array with the keys being a Person ID? Is there some kind of Java object which can use accept two objects as a key? – user11406 Apr 25 '15 at 19:54
  • You're overcomplicating things here. All you'd need to do is store the new `Relationship` instance as a result of calling the method above. If you wanted to see if a `Person` was in a particular `Relationship`, you'd have to define an `equals` method for `Person`, and expose an `inRelationship(Person person)` method in `Relationship`. – Makoto Apr 25 '15 at 19:57
  • This is bad OOP style! The two classes are too tightly coupled. `Person` class doesn't need a `Relationship` member. Only `Relationship` should keep two references to `Person`. – mike Apr 25 '15 at 20:03
  • @mike: Hence my revision. I don't think that we'd need a field to `Relationship` either. – Makoto Apr 25 '15 at 20:27
  • @Makoto ...but you still have a member of type `Relationship` in class `Person`. – mike Apr 25 '15 at 22:14
0

In the natural world, a person can be a part of a relationship, but a relationship can not be part of a person. Therefore, having Relationship as a member of Person is undesirable. Such a setup prevents a Person from having more than one Relationship :) and also prevents a Person from having no Relationship :(

If we can define a Relationship as being between 2 people, and 2 people only, then one possible setup would be to have the Relationship class contain 2 Person members. If a Relationship can be between 3 or more people :), then a single List<Person> member may be more helpful.

I want to be able to assign a Relationship object between two Person objects

If you are trying to discretely ask for dating advice, you have come to the wrong place.

Edit:

If you are trying to get a Relationship that any given two people are involved in, create a method like this

public Relationship find(List<Relationship> relationships, Person person1, Person person2) {
    for (Relationship relationship : relationships) {
        if (relationship.getPerson1().equals(person1) && relationship.getPerson2().equals(person2) {
            return relationship;
        }
        if (relationship.getPerson1().equals(person2) && relationship.getPerson2().equals(person1) {
            return relationship;
        }
    }
}

If performance is a concern, use Set<Relationship> and override the equals() and hashCode() methods of Relationship so that two Relationship objects containing the same people will be considered equal. Then you can do this

Set<Relationship> relationships = new HashSet<Relationship>();
// populate relationships

Relationship delegate = new Relationship(person1, person2);
int hasRelationship = relationships.contains(delegate);
pathfinderelite
  • 3,047
  • 1
  • 27
  • 30
  • Thanks for the reply. I understand how to store the Relationship I'm just confused on how to best retrieve it after it's created. Would I use a 2D array of Person or something? What would the keys be, the objects? – user11406 Apr 25 '15 at 19:56
  • @user11406 It depends. How do you want to retrieve it? Are you looking to get a list of `Relationship` that a `Person` is involved in? `Map>` would work. Do you want to list the people involved in all relationships? Just use `List`. It really all depends on how you plan on using that information. – pathfinderelite Apr 25 '15 at 20:02
  • Neither. I have two people and I want to get their relationship. I want something like, relationship = relationships[person1][person2]; I just doubt using a 2D array would be a good approach and I'm not even sure how to create a 2D ArrayList. Plus, even if I do it either of those ways I'd need to assign a ID for each Person to use as a key. – user11406 Apr 25 '15 at 20:18
  • there could be thousands of relationships and speed is important as this will make part of search algorithm. Is this the best way? – user11406 Apr 25 '15 at 20:31
  • @user11406 Updated answer to include a HashSet implementation for performance. – pathfinderelite Apr 25 '15 at 20:41
0

What you need is an implementation of a Tree in Java, where the nodes are the Person objects, and the edges (the lines that connect two nodes) are the connections. This is the most efficient data model available for the type of storage you need.

Someone posted a basic tree class structure on SO in the past: Java tree data-structure?

Community
  • 1
  • 1
mittelmania
  • 3,393
  • 4
  • 23
  • 48