-1

I know that the question sound weird but an example will clarify my thoughts.

Suppose I have 2 classes Employee and Department. Department has an Arraylist of employees. This way I can access employees in a specific department.

What do I have to do if I also need to access the employee department from the Employee object?I think that also adding the department to employee object is a bad practice?

M.ES
  • 920
  • 14
  • 30

2 Answers2

1

This is the problem of navigability, and is a big concern in database design. There's a couple of ways to achieve this:

  1. Brute force. If you have an Employee, scan the Departments to find which (if any) it belongs to. Obviously this is quite inefficient, and assumes you have a list of all the Departments available.
  2. Indexing. Alongside your Department and Employee objects, maintain a map of Employees to Departments, and use this map to find the reverse look-ups. Of course this has some overheads, but the big worries are transactionality (an update may change the index, then fail before updating the Department) and consistency (what happens if a client tries to read the data after you've updated the Department but before you've updated the index?)
  3. Double-linking. Require that the Department and Employee classes each have a reference to the other. This is tricky because it's fiddly constructing the references, and has the same transactionality and consistency problems. Also makes it extremely hard to make the references final (although I don't think you want that in this case anyway).

So, there are issues to consider before doing this, but it's not insurmountable - just make sure you've thought about thread-safety and fault-tolerance before you do it. Doubly-linked lists are a pretty common data structure which uses this pattern.

Community
  • 1
  • 1
hugh
  • 2,237
  • 1
  • 12
  • 25
-1

You can initialize like the following but it is considered bad practice in multi-threading applications but sometimes acceptable for specific use cases in single thread applications. One important thing to consider is if you pass the Department object as this to the Employee object technically the object is not fully constructed. Another thing to consider is how garbage collection will function in such a pattern.

public class Department {
  List<Employee> myEmployeeList;

  public Department() {
    int size = 5;
    myEmployeeList.add(new Employee(this));
  }
}

public class Employee {
  Department myDepartment;

  public Employee(Department department) {
    myDepartment = department;
  }
}

You could also have a class that holds references to both Department and Employee and give Employee that reference. Or initialize Department in a method from Employee.

Xtrinity
  • 125
  • 1
  • 5
  • yes this is bad practice but the reason it is bad has nothing to do with multithreading or concurrency. –  Aug 08 '15 at 14:08
  • Garbage collection will handle this ok - the rule is an object is eligible for GC if it is reachable from any live thread. This means that "islands" of objects with circular references can be GC'd without any trouble when they are no longer reachable. – hugh Aug 08 '15 at 14:46
  • @JarrodRoberson please take a look at this answer, http://stackoverflow.com/a/9851843/5085407 – Xtrinity Aug 08 '15 at 21:54
  • @hugh the garbage collection will handle this right if the objects are only ever used in a single thread in a singleton manner. However, if you dereference the root they will all still be GCed. If for example, the main thread holds a reference to Department and another thread also holds a reference to the same Department this would become an issue. What OP needs to be asking himself is whether or not he will be using these two objects in a multi-threaded application. Also you have a typo in your comment, "the rule is an object is eligible for GC if it is unreachable*" – Xtrinity Aug 08 '15 at 22:49
  • Typo: Yes, you're right. Multithreading: I don't think that's true. If two threads hold a reference to a `Department`, it will only be GC'd after both threads deference it (or terminate). At this point it cannot be reached from any live thread, so this will not cause any issues. – hugh Aug 09 '15 at 08:01
  • Right. Perhaps there is a misunderstanding :) What I meant by the last sentence in the firs paragraph is that if you're doing multi-threading then you should definitely consider when and where your objects are being dereferenced if both threads hold references. If you only dereference in one thread the object would not be GCed. I'd actually use some the other answers if the objects are being used in multi-threading. As for whether or not there would be an issue with passing the `this` keyword in multi-threaded environments, I suspect it has to do with `interleaving`. – Xtrinity Aug 09 '15 at 08:26