Linkend List copy constructor - java

I am having problems with the copy constructor of a Linkend List in Java.
The list I am trying to copy has a size of 3, when I use the copy constructor the list is empty.
When I try this with the clone method everything works great.
I have look a this for a quite a while and I get the feeling it is so obvious. I just
dont see it, here is the code.
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary){
this.name = name;
this.salary = salary;
}
public void setname(String name){
this.name = name;
}
public void setsalary(double salary){
this.salary = salary;
}
public String getname(){
return this.name;
}
public double getsalary(){
return this.salary;
}
}
public class Main {
public static void main(String[] args) {
Employees employees = new Employees();
employees.add(new Employee("Employee1", 2500.00));
employees.add(new Employee("Employee2", 2400.00));
employees.add(new Employee("Employee3", 2000.00));
Employees employeesCopy2 = new Employees(employees);
Employees employeesCopy = (Employees) employees.clone();
System.out.println(employees.size());
System.out.println(employeesCopy2.size());
System.out.println(employeesCopy.size());
}
}
import java.util.LinkedList;
public class Employees extends LinkedList<Employee> {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void addWerknemer(Employee w){
employees.add(w);
}
}
EDIT
This is homework, but when I wanted to add the tag is showed that the tag was no longer is use.

I think this:
public class Employees extends LinkedList<Employee> {
private LinkedList<Employee> employees;
will create a world of confusion. You're both extending a list, and within that class you're maintaining a separate list. When you call addWerknemer() you add to the inner list. What happens when you call get() ? Since you've not overridden this, you're calling get() on the base class, and that's a different list!
Without inspecting the rest of your code, I suspect this is a fundamental source of problems.
You have two choices:
Employees extends List
Employees contains a List
I would prefer the second. You can change the underlying collection (e.g. a Set, perhaps a Map for better lookup performance) and not change the exposed interface.

You are extending LinkedList, but also have a LinkedList inside that extension. Initially you use the add method to add Employee instances, so they get added to the Employees list itself, but when you use the copy constructor, you copy those employees to the employees field inside your Employees class.
When you call the size() method, it will use the LinkedList of the Employees object itself, so in the first list it is 3, but on the second it is 0 as now the employees are in the contained list and not in the object itself.
In this case you probably should not extend LinkedList. Or if you do, then don't use a separate field like employees which also contains a LinkedList.

Your confusion comes from the fact, that Employees both is a list and contains a list. When you use
employees.add(new Employee("Employee1", 2500.00));
you add the employee to the outer list. When you use
employees.addWerknemer(new Employee("Employee1", 2500.00));
you add the employee to the inner list. Since you have overwritten the constructor Employees(Employees es), this will not clone the outer list, but only the inner. And since you haven't overwritten clone(), it will clone the outer list, but not the inner. This is rather messy and also most probably not intended by you. I therefore propose one of the following changes:
1. [Preferred] Employees only contains a list and not extends one
Skip the extends LinkedList<Employee> and only work with an internal list. You will have to use your method addWerknemer(Employee emp) to add to your list (or change it's name to add). You will have to implement size and clone as well as other methods that you wish to use. If you want to be really clean about this, you can even make the class implement List or implement Collection or so. This way you can still treat your class as a java.util.Collection. I don't think that this would be neccessary in your case though. Also you would need to implement all of the interfaces methods (there are many). An example implementation would look like this. You still have to implement size, etc.
public class Employees /*implements List<Employees>*/ {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void add(Employee w){
employees.add(w);
}
public Employees clone() {
return employees.clone();
}
// add more methods as you need them (like remove, get, size, etc)
}
2. Employees only extends LinkedList and doesn't contain one
Throw away your methods addWerknemer(Employee emp) and the copy constructor Employees(Employees) as well as your internal list. This way you will not overwrite the existing implementations of LinkedList. This approach is more or less useless because you basically just rename LinkedList to Employees and add/change nothing. Therefore I wouldn't recommend this approach.

Related

ArrayList getter and setter in a class java

public class Employee
{
private String name;
private String department;
private ArrayList<Employee>job= new ArrayList();
// just want to add getter and setter for this ArrayList
public void setJob(Employee j)
{
job.add(j);
// this is my setter
I want to be able to add later on as many 'job' as I want by extending the arraylist
While you can have setters and getter of List type, you should think carefully about their implementation, because most lists are mutable.
For instance, assume that you want to validate that the jobs list is not empty.
public void setJob(List<Employee> jobs) {
if (jobs.isEmpty()) throw new RuntimeException();
this.job = jobs;
}
Now the following code produces an employee without jobs:
Employee e = ...;
e.setJobs(jobs);
jobs.clear();
//the employee now has no jobs :-(
You can avoid this issue by making a defensive copy
public void setJob(List<Employee> j) {
this.job = new ArrayList<>(j);
}
The same applies to the getter. If you implement it as:
public List<Employee> getJobs() {
return this.jobs;
}
you are allowing the caller to modify the private job list without invoking the corresponding setter: myEmployee.getJobs().clear().
In this case, you may return an unmodifiable list instead of returning the inner object.
public List<Employee> getJobs() {
return java.util.Collections.unmodifiableList(this.jobs);
}
Ordinarily for a collection or array you would use addJob, removeJob and getJobs instead of a get/set pair.

Set<T> within a Map<K,V> in Java

I was wondering if it is possible to have a Set member added as a member variable of a class, the object of which can then be put as a value into a Map.
My idea is to use HashSet<T> projects as a member variable for my employee class. But, I would like to have a query performed on a database that will return query results as a Map> item where int will be the employeeId and Set will be the projects. is it doable at all?
This is definitely doable. It looks like you are implementing a many-to-many relationship between employees and projects. This would correspond to a pair of tables with a junction table to connect them.
Your would read your employees and your projects, and then add projects to each employee set.
I should mention that it's not a good idea to expose a set as a member variable, because sets are mutable. You could make the variable private, and expose methods to add/query projects from your object.
Try something like this
class Project{
int pid;
int name;
//Getter and setter
}
Create Employee class
public class Employee {
int employeeId;
String name;
Set<Project> projects;
//getter , setter or add methods
}
Now you can use above two classes in DAO
public class EmployeesDao{
/* Get multiple employee-projects */
public Map<Integer, Set<Project>> getManyEmployeeAndProjects(){
Map<Integer, Set<Project>> emps = new HashMap<Integer, Set<Project>>();
//query and populate
return emps;
}
/**
* Get single employee
*/
public Employee getEmployee(){
//Query and return Employee
return new Employee();
}
}
That being said, I think you may only need return list of employees because Employee will have employee id and projects
public List<Employee> getEmployees(){
//create list of Employee object
}

Aggregation with 1:m between objects

I have member.objects that are painters, carpenters and TeamLeads which can have other TeamLeads, painters or carpenters under them. Is there a way to connect them so that I can getTeamLeads.team and also have the ability to see who is working under their TeamLeads.team. I understand how to do it with a database but wanted to see if composition or aggregation would handle a 1:m relationship and if there is an example somewhere that I could see. Would it require maybe a Team.class to link everyone or can it be handled by local references and I just can't find any examples.
As i see it you can do this with a private collection that can be managed by modifiers which also mantain reverse relationship something like this:
public class TeamMember {
private TeamMember leader;
private Set<TeamMember> teamMembers= new HashSet<TeamMember>();
public Set<TeamMember> getTeamMembers(){
return new HashSet<TeamMember>(teamMembers);
}
public void addTeamMember(TeamMember member){
if(member.leader!=null){
member.leader.removeTeamMember(member);
}
member.leader=this;
teamMembers.add(member);
}
public void removeTeamMember(TeamMember member){
member.leader=null;
teamMembers.remove(member);
}
public TeamMember getLeader(){
return leader;
}
}
Since you dont have public setters for teamMembers or leader the only way to change leader or teamMembers is by using the addTeamMember and removeTeamMember methods so you have the bidirectional relationship mantained by these methods.
I wish this may help.
So it sounds like you have some a method with this sort of signature to retrieve the list of TeamLead:
public List<TeamLead> getTeamLeads()
And from there, you want to get the members of each team, your TeamLead class would look something like this:
public class TeamLead {
private final List<Person> team = new ArrayList<Person> ();
// You can of course populate this list however is best for your code
public void addTeamMember(Person p) {
team.add(p);
}
public List<Person> getTeam() {
return team;
}
// more code...
}
Where Person is the base class for Painter, Carpenter, and TeamLead - there are other ways to do this without a class hierarchy, but I'll stick to this for easier explanation for now.

Filter ArrayList that has similar data

I have the following classes:
public class School{
List<ClassRoom> classRooms;
}
public class ClassRoom{
List<Student> students;
}
public class Student{
String name;
long typeId;
}
I need to get the whole students within the given class roomS that has typeID=123
Expected result:
List filteredStudent=classRoomList.filterByStudentTypeID(typeIdToSearchFor)
I don't need to write some dirty code and loops.
I need to take advantage of existing libraries.
I found out Google Guava.
I found out a method at guava that searches by the the whole reference ... instead I need to search using the attribute, typeId
Collection<Student> filtered =Collections2.filter(students, Predicates.equalTo(s1));
Any ideas!
Since you are using Guava, you can use a custom predicate:
final long typeIdToSearchFor = ...;
Collection<Student> filtered = Collections2.filter(students,
new Predicate<Student>() {
#Override
public boolean apply(Student s) {
return s.typeId == typeIdToSearchFor;
}
}
);
Note that typeIdToSearchFor must be final in the scope of the call to filter because it is being referenced by the (anonymous) Predicate subclass.

Java Linked List How to create a node that holds a string and an int?

I have been at this literally all day. I can create linked lists no problem and display/delete the data in them. My problem is though that I am not sure how to create a linked list of flights with each node including a reference to a linked list of passengers? This is an assignment in my advanced Algorithms class. I am drawing a blank here?
Create an object that holds a Passenger:
public class Passenger
{
private String name;
private int id;
}
Then give Flight a List of Passengers:
public class Flight
{
private List<Passenger> passengers;
}
Now you can have a List of Flights:
public class Schedule
{
private List<Flight> flights;
}
You needs lots more code in each. Be sure to override equals and hashCode for Passenger and Flight to make sure that they work properly.
Well, can't you just create a Flight class and a Passenger class?
class Flight {
private LinkedList<Passenger> passengers;
...
}
class Passenger {
...
}
LinkedList<Flight> flights = ...

Categories

Resources