Hierarchical Data to arrayList using recursion. (Java) - java

I have hierarchical data in MySQL of employees and their subordinates as shown here There is a joining column 'managerID' which references to the employee ID in the same column.
My objective is to recursively go through this data and add it all to an arrayList which would end up looking like this:
[Tom [Hanna [George [Chris], Rachel]]]
But there is a logic problem in my java function:
public void getList(String employeeName, ArrayList<Object> arrayList) {
// Initialise the arrayList the first time
if (arrayList == null) {
arrayList = new ArrayList<>();
}
// Using the string provided, I have found the employee
Employee employee = employeeRepository.findByName(employeeName);
// adding employee to the list
arrayList.add(employee);
// Getting list of employee's subordinates
List<Employee> subordinates = employee.getSubordinates();
// Checking if employee has subordinates
if (subordinates != null) {
// Iterate through each of their subordinates and call recursive function
for (int i = 0; i < subordinates.size(); i++) {
ArrayList<Object> subOrdinateDetails = new ArrayList<>();
// If the subordinate has subordinates, use recursion
if (subordinates.get(i).getSubordinates() != null) {
getList(subordinates.get(i).getName(), subordinatesDetails);
}
// Adding this list to the original arrayList
arrayList.add(subOrdinateDetails);
}
System.out.println(arrayList.toString());
}
}
The toString method at the end of the method does not print what I wanted above, instead it prints:
[Chris]
[George, [Chris]]
[Rachel]
[Hanna, [George, [Chris]], [Rachel]]
[Tom, [Hanna, [George, [Chris]], [Rachel]]]
While trying to debug it, I tried to get the first index of the arrayList, to understand what it was here is what it printed:
Chris
George
Rachel
Hanna
Tom
As you can tell, I am new to java, and I have failed debugging my code. If you could point out my mistake, I will be very grateful.

You can simply do it like this.
public class Employee {
private final String name;
private final List<Employee> subordinates;
public Employee(String name, List<Employee> subordinates) {
super();
this.name = name;
this.subordinates = subordinates;
}
public String getName() {
return name;
}
public List<Employee> getSubordinates() {
return subordinates;
}
public void print() {
System.out.println(this.name);
this.subordinates.forEach(emp -> {
emp.print();
});
}
}
public class EmployeeTest {
public static void main(String[] args) {
Employee chris = new Employee("chris", new ArrayList<>());
Employee george = new Employee("george", Arrays.asList(chris));
Employee rachell = new Employee("rachell", new ArrayList<>());
Employee hannah = new Employee("hannan", Arrays.asList(george, rachell));
Employee tom= new Employee("tom",Arrays.asList(hannah));
tom.print();
}
}
The trick in the recursion is each time it prints out the current employee, before printing any of it's subordinates as you can see in the method. I'll leave it to you to come up with the brackets if needed.

Related

Java: Finding friendship chains via recursion

I'm currently working on a problem where I have to find friendship chains via recursion in Java. Statistically, a person knows another person over about 6 waypoints - which is the chain I am trying to find.
I've got a class "Person", which defines a name and direct friends:
public class Person
{
private Person[] friendChain;
private String name;
public Person(String name, Person[] friendChain)
{
this.friendChain = friendChain;
this.name = name;
}
public Person[] getFriends()
{
return this.friendChain;
}
public String getName()
{
return this.name;
}
public boolean isFriendWith(Person person)
{
for(Person p: this.friendChain)
{
if(p != null && person != null && p.getName().equals(person.getName()))
return true;
}
return false;
}
public boolean equals (Person person)
{
return this.name.equals(person.getName());
}
public String toString()
{
return this.getName();
}
}
A diagram was given that gives an example chain, where arrows indicate a one-way or two-way relationship (as in Thomas knows Theresa, but Theresa doesn't know Thomas):
So basically my outcome should look similiar to something like this:
result = getFriendshipChain(adam, theresa);
result[0].getName(); // "Michael"
result[1].getName(); // "Kerstin"
result[2].getName(); // "Thomas"
result[3].getName(); // "Theresa"
result[4].getName(); // null
result[5].getName(); // null
I've done a lot of recursive programming in the past, but I just can't get my head into this right now - I'd appreciate any help!
Here is an example but beware, this will only work if your graph has only one path like in your sample image
In case this isn't broad enough to suit your needs, at least the first and second steps (maybe the third also) should be helpful :
1) You only accept friendsChain in the constructor of Person, but how can you pass a chain of Person objects that haven't yet been created ?
This is a cyclic creation dependency; I suggest to remove the problem with a lighter constructor, along with a setter for friendChain .
public Person(final String name) {
this.name = name;
}
public void setFriendChain(final Person[] friendChain) {
this.friendChain = friendChain;
}
2) Let's build Person objects and populate their friend chains
Person adam = new Person("Adam");
Person michael = new Person("Michael");
Person kerstin = new Person("Kerstin");
Person thomas = new Person("Thomas");
Person theresa = new Person("Theresa");
Person[] adamsFriends = { michael, kerstin };
adam.setFriendChain(adamsFriends);
Person[] michaelsFriends = { adam, kerstin };
michael.setFriendChain(michaelsFriends);
Person[] kerstinsFriends = { thomas, adam, michael };
kerstin.setFriendChain(kerstinsFriends);
Person[] thomasFriends = { kerstin, theresa };
thomas.setFriendChain(thomasFriends);
Person[] theresasFriends = { thomas };
theresa.setFriendChain(theresasFriends);
3) Let's build a recursive method to follow the friend chain (note that we use a List, because we don't know the final size of the chain) :
public void getFriendshipChain(final Person from, final Person to, final List<Person> friendshipChain) {
friendshipChain.add(from);
// We have found the target person, return
if (from.equals(to)) {
return;
}
// For every friend from that person
for (Person friend : from.getFriendChain()) {
// If we don't already have it in the list
if (!friendshipChain.contains(friend)) {
// follow this friend's chain
getFriendshipChain(friend, to, friendshipChain);
}
}
}
4) Call it :
List<Person> result = new ArrayList<Person>();
getFriendshipChain(adam, theresa, result);
System.out.println(result);

Multiple NULL addition into a List in Java

I have 2 lists and want to copy some element from one to another, i.e. there are old and new employees list I need to union 2 lists and delete the elements that include to the old list but not include in the new one.
I could solve the part of getting the union and intersection by using TreeSet and override the equals and hashcode functions of the Employees class....
Now, I want to exclude the elements that are in the old but not in the new and add them to the "deletedList"....which I got "ConcurrentModificationException"
I tried this instead of "iterator" but the same result: for(Employees e : employeesListDB)
Also I tried "CopyOnWriteArrayList" instead of "ArrayList" but no change!!
but the problem now that at the initialization of the empty list "deletedList" it is filled with multiple null elements before the add function!
Here is the code:
List<Employees> employeesListDB = this.findAll();
Set<Employees> empSet = new TreeSet<Employees>(new EmployeeComparator());
empSet.addAll(employeesList);
List<Employees> deletedList = new ArrayList<Employees>();
Employees e = new Employees();
ListIterator<Employees> itr = employeesListDB.listIterator();
for(itr.hasNext()) {
e = (Employees)itr.next();
if(!empSet.contains(e)) {
deletedList.add(e);
}
}
A counter Example:
The oldlist "employeesListDB" the employees list from the database:
[
{
"email":"mariam.moustafa#x.com"
},
{
"email":"sara.ahmed#x.com"
},
{
"email":"ali.hassan#x.com"
},
{
"email":"hoosen.imam-ally#x.com"
},
{
"email":"allan.randall#x.com"
},
{
"email":"nishaan.maharaj#x.com"
}
]
The new list to be added:
[
{
"email":"ali.moustafa#x.com"
},
{
"email":"sara.ahmed#x.com"
},
{
"email":"emad.hamed#x.com"
}
]
The deleted list that I want:
[
{
"email":"mariam.moustafa#x.com"
},
{
"email":"ali.hassan#x.com"
},
{
"email":"hoosen.imam-ally#x.com"
},
{
"email":"allan.randall#x.com"
},
{
"email":"nishaan.maharaj#x.com"
}
]
Sara mail will be updated...
Employee class has two fields {id,email} the new list (the list to be added to the db) is a list of only emails, id field are not recognized yet but the old list has the complete bean fields ...to compare between these 2 list I should override the Comparator to ignore the id field; Finding duplicates in a List ignoring a field
JUST I need to know, why when I use set.add operation, it adds the unique emails only! the original size of the list was 36 elements after adding it into a set it becomes only 16!!
Set<Employees> oldSet = new TreeSet<Employees>(new EmployeeComparator());
oldSet.addAll(employeesListDB);
Set<Employees> newSet = new TreeSet<Employees>(new EmployeeComparator());
newSet.addAll(employeesList);
Set<Employees> deleted = Sets.difference(oldSet, newSet);
As I understand, you need all elements that are contained by old set and not contained by new set.
For this purpose you can use Guava Sets#difference method:
Set<Employees> deleted = Sets.difference(oldSet, newSet);
Test with your data:
Set<String> oldEmployees = Sets.newHashSet("mariam.moustafa#x.com", "sara.ahmed#x.com", "ali.hassan#x.com", "hoosen.imam-ally#x.com", "allan.randall#x.com", "nishaan.maharaj#x.com");
Set<String> newEmployees = Sets.newHashSet("ali.moustafa#x.com", "sara.ahmed#x.com", "emad.hamed#x.com");
Set<String> diff = Sets.difference(oldEmployees, newEmployees);
System.out.println(diff);
Result:
[nishaan.maharaj#x.com, mariam.moustafa#x.com, ali.hassan#x.com, allan.randall#x.com, hoosen.imam-ally#x.com]
Here is a core Java solution using 2 simple steps:
[1] - Create a set setOld which contains the first set of emails
[2] - Subtract from setOld a new set of emails setNew
Set oldSet<String> = new HashSet<String>(); // original set of email addresses
oldSet.add("mariam.moustafa#x.com");
oldSet.add("sara.ahmed#x.com");
oldSet.add("ali.hassan#x.com");
oldSet.add("hoosen.imam-ally#x.com");
oldSet.add("allan.randall#x.com");
oldSet.add("nishaan.maharaj#x.com");
Set newSet<String> = new HashSet<String>(); // new set of email addresses
newSet.add("ali.moustafa#x.com");
newSet.add("sara.ahmed#x.com");
newSet.add("emad.hamed#x.com");
for (String s : newSet) {
oldSet.remove(s); // this will only remove the element if found
}
// display new contents of oldSet
for (String s : oldSet) {
System.out.println(s);
}
Output:
mariam.moustafa#x.com
ali.hassan#x.com
hoosen.imam-ally#x.com
allan.randall#x.com
nishaan.maharaj#x.com
Try it this way (Made a small TestCase):
private static Employee createEmployee(String string) {
Employee employee = new Employee();
employee.setEmail(string);
return employee;
}
public static void main(String[] args) {
List<String> newMails = new ArrayList<>();
List<Employee> oldList = new ArrayList<>();
oldList.add(createEmployee("mariam.moustafa#x.com"));
oldList.add(createEmployee("sara.ahmed#x.com"));
oldList.add(createEmployee("ali.hassan#x.com"));
oldList.add(createEmployee("hoosen.imam-ally#x.com"));
oldList.add(createEmployee("allan.randall#x.com"));
oldList.add(createEmployee("nishaan.maharaj#x.com"));
newMails.add("ali.moustafa#x.com");
newMails.add("sara.ahmed#x.com");
newMails.add("emad.hamed#x.com");
List<Employee> delete = new ArrayList<>();
Set<String> removedMails = new HashSet<>();
for (Employee emp : oldList) {
if (!newMails.contains(emp.getEmail())) {
delete.add(emp);
}
removedMails.add(emp.getEmail());
}
newMails.removeAll(removedMails);
// remove emploeyees in delete
oldList.removeAll(delete);
// Create employee for left MAils
for (String newMail : newMails) {
oldList.add(createEmployee(newMail));
}
//Old and new Employees
for (Employee emp : oldList) {
System.out.println(emp.getEmail());
}
}
simple Employee class:
class Employee {
String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
output:
sara.ahmed#x.com
ali.moustafa#x.com
emad.hamed#x.com
the empty list filled with multiple null elements before the add
function!
This is becuase you're using the ArrayList which contains the following constant:
private static final int DEFAULT_CAPACITY = 10;
Which mean when you create the ArrayList<T> with the new operator you actually create an Array of T which contains 10 nulls (It's contained as private transient Object[] elementData field).
The JLS said:
Every variable in a program must have a value before its value is
used:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):
[...]
For all reference types (§4.3), the default value is null.
Use List removeAll method. You will need to override equals method in your Employees class. PFB sample snippet based on employee id, you will need to modify it to fit based on email id:
import java.util.*;
public class StringArray {
public static void main(String args[]) {
List<Employee> oldList = new ArrayList<Employee>();
oldList.add(new Employee(1));
oldList.add(new Employee(2));
oldList.add(new Employee(3));
oldList.add(new Employee(4));
List<Employee> newList = new ArrayList<Employee>();
newList.add(new Employee(3));
newList.add(new Employee(4));
newList.add(new Employee(5));
newList.add(new Employee(6));
oldList.removeAll(newList);
System.out.println("Printing delete list");
for (Employee employee : oldList)
System.out.println(employee);
System.out.println("Printing updated list");
for (Employee employee : newList)
System.out.println(employee);
}
}
public class Employee {
private int id;
public Employee(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Override
public String toString() {
return "Employee [id=" + this.id + "]";
}
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Employee))
return false;
Employee c = (Employee) o;
return this.id == c.id;
}
}

getting ConcurrentModificationException error while using iterator and remove

I am getting a java.util.ConcurrentModificationException from following code and I can find the reason. I could successfully read data form a csv file and make an arraylist called course list of it. then I need to sort my in to an array list that each of its cell contains an arraylist of identical courses (courses that have similar name).
But when I run it generates ConcurrentModificationException and I do not understand why...
public class CourseLister {
private static final String DATA = "data\\data.csv";
File file;
ArrayList<Course> courseList ;
public CourseLister(String filepath) {
file = new File(filepath);
courseList = new ArrayList<>();
}
public void readFromCsv(){
// in this method a Csv file is written line by line , create a new object of course with some attribute such as name , number, instructor,... and is added to courseList //}
}
public Iterator<Course> getCourseIterator(){
return courseList.iterator();
}
public ArrayList<Course> getCourseList(){
return courseList;
}
public static void main(String [ ] args){
CourseLister courseLister = new CourseLister(DATA);
courseLister.readFromCsv();
CourseFileSorter coursefilesoreter = new CourseFileSorter(courseLister.getCourseIterator());
ArrayList<Course> curseList = courseLister.getCourseList();
for (Course course : curseList) {
System.out.println(course.getSemester());
}
System.out.println(curseList.size());
coursefilesoreter.displayCategorizedList();
}
}
here is my CourefileSorterclass:
public class CourseFileSorter {
Iterator<Course> courseItr ;
public CourseFileSorter(Iterator<Course> courseItr) {
this.courseItr = courseItr;
}
public ArrayList<ArrayList<Course>> getSourtedLists(){
Iterator<Course> dissimilarCourseItr = null;
ArrayList<Course> identicalCourseList = new ArrayList<Course>();
ArrayList<Course> dissimilarCourseList = new ArrayList<Course>();
ArrayList<ArrayList<Course>> categorizedCourseList = new ArrayList<ArrayList<Course>>();
Course firstCourse = null;
Course currentCourse ;
if(courseItr.hasNext()){
while(courseItr.hasNext()){
firstCourse = courseItr.next();
identicalCourseList.add(firstCourse);
while(courseItr.hasNext()){
currentCourse = courseItr.next();
if(currentCourse.getCourseName().equals(firstCourse.getCourseName())){
identicalCourseList.add(currentCourse);
courseItr.remove();
}
else{
dissimilarCourseList.add(currentCourse);
}
}
dissimilarCourseItr = dissimilarCourseList.iterator();
courseItr = dissimilarCourseItr;
categorizedCourseList.add(identicalCourseList);
}
return categorizedCourseList;
}
else{
return null;
}
}
}
It would be much easier to sort them into a different data structure. I see that course has a getCourseName() method, which I assume would return a String object. Try using a Map<String, List<Course>> instead.
The sorting method would look like this:
public Map<String, List<Course>> getSourtedLists(){
Map<String, List<Course>> result = new HashMap<String, List<Course>>();
while(courseItr.hasNext()) {
course next = courseItr.next();
if (!result.containsKey(next.getCourseName())) {
result.put(next.getCourseName(), new ArrayList<Course>());
}
result.get(next.getCourseName()).add(next);
}
Also, you REALLY don't want to call courseItr.remove(); This removes the course object from the underlying Collection, meaning that the way you were planning to do it would empty out the courseList from your CourseLister object.
1 . You get ConcurrentModificationException because:
dissimilarCourseList.add(currentCourse);
courseItr = dissimilarCourseItr;
2 . It's not a good idea to use iterators when you have arraylists.

Copying contents of file into array of linked list and sort it

I have a comma separated file that contains
Employee name,company,years.
An employee may be affiliated to multiple companies.
For eg,
John,Google,2
John,Microsoft,1
James,Tesla,1
James,Apple,5
I have retrieved the information using the java scanner
scanner.useDelimiter(",|\\n");
while (scanner.hasNext()) {
String line = scanner.next()
I am new to Java and I am trying to insert the above in a sorted order (using experience as sorting criteria) using an array of linked lists or array of array. So
employee -> Company1 -> Company2.... (ordered by employee experience)
So in the above example, it would be:
John->Microsoft->google
James->Tesla->Apple
Can someone point me to the right direction?
NOTE: If the experience is same, it doesnt matter which company comes first.
Use this class for Person
public class Person {
#Getter #Setter
private String name;
#Getter #Setter
private TreeMap<String, String> companyExperience;
public Person(){
companyExperience = new TreeMap<String, String>();
}
}
Using the experience as key in a TreeMap will automatically sort the companies for a Person in ascending order.
Your main class shoud look like this
public class App
{
public static void main( String[] args )
{
HashMap<String, Person> persons = new HashMap<String, Person>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:\\Users\\Public Administrator\\test.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String line = null;
try {
while ((line = br.readLine()) != null) {
String[] fields = line.split(",");
String personName = fields[0];
Person existingPerson = persons.get(personName);
if (existingPerson==null){
Person newPerson = new Person();
newPerson.setName(personName);
newPerson.getCompanyExperience().put(Integer.parseInt(fields[2])+fields[1], fields[1]);
persons.put(personName, newPerson);
} else{
existingPerson.getCompanyExperience().put(Integer.parseInt(fields[2])+fields[1], fields[1]);
}
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//output
Iterator<Map.Entry<String, Person>> entries = persons.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, Person> entry = entries.next();
Person _person = entry.getValue();
System.out.print(_person.getName());
Iterator<Map.Entry<String, String>> companyExperiences = _person.getCompanyExperience().entrySet().iterator();
while (companyExperiences.hasNext()) {
Map.Entry<String, String> companyExperience = companyExperiences.next();
System.out.print(" > "+companyExperience.getValue());
}
System.out.println();
}
}
}
I've tested it and looks pretty, pretty good to me.
By the way, the #Getter and #Setter annotations are from the Lombok project. You can either use it or create your own getters/setters.
read your file with readLine() and use split to get each field of your data, e.g.:
BufferedReader br = new BufferedReader(new FileReader("FileName"));
String line = null;
ArrayList<Person> list = new ArrayList<Person>();
while ((line = br.readLine()) != null) {
String[] fields = line.split(",");
list.add(new Person(fields[0], fields[1], Integer.parseInt(fields[2])));
}
You can then save your data in ArrayList that takes a custom class e.g. Person that stores the person's information and implements Comparable where you do the sorting logic.
If you need to group your data by the person name, you might consider having a Hashtable where the key is the person name and the value is ArrayList of experience.
You can define a class for your data, e.g.
class Person implements Comparable<Person> {
private String name;
private String company;
private int experience;
public Person(String name, String company, int experience) {
this.name = name;
this.company = company;
this.experience = experience;
}
public int getExperience() {
return experience;
}
#Override
public int compareTo(Person person) {
return new Integer(experience).compareTo(person.getExperience());
}
}
The to sort your list just call Collections.sort(list);; however this list will contain all the data so modify the code to group the data by the employee name and have a list per each employee
For your purposes, it sounds like you really want an object to represent a Person, who has some amount of Experience. Since your input source has the data denormalized, easiest way to do that is to populate a Map<String,Person> as you parse your file:
scanner.useDelimiter(",|\\n");
while (scanner.hasNext()) {
String line = scanner.next();
String[] fields = line.split(",");
String name = fields[0];
Person person = map.get(name);
if (person == null) {
person = new Person(name);
map.put(name, person);
}
person.addJob(fields[1], Integer.parseInt(fields[2]));
}
List<Person> people = new ArrayList<Person>(map.values());
After this process, you'll end up with a List of People, in no particular order. For each Person, since you want to keep their job's in order sorted by experience, you'd need to implement Person.addJob in such a way as to keep it ordered. A SortedSet is a really nice way to do this, but you can't insert duplicates, and since you want to sort by experience, and a person could've been at two jobs the same amount of time you need to use an alternate approach. There's several ways to do this, but without making assumptions about your data I'd suggest keeping a sorted List of Job objects:
class Person {
private final List<Job> jobs = new LinkedList<Job>();
// Constructor, etc...
public void addJob(String companyName, int yearsOfExperience) {
Job newJob = new Job(companyName, yearsOfExperience);
int insertionIndex = Collections.binarySearch(jobs, newJob);
if (insertionIndex < 0) {
insertionIndex = (-(insertionIndex) - 1);
}
jobs.add(insertionIndex, newJob);
}
}
and finally, a Job should implement Comparable<Job>, so that you can look it up:
class Job implements Comparable<Job> {
private final String companyName;
private final int yearsOfExperience;
// Constructor, etc...
public int compareTo(Job otherJob) {
return Integer.compare(yearsOfExperience,otherJob.yearsOfExperience);
}
}
That bit of trickery in Person.addJob will keep the List always sorted by the 'natural order' of Job. (see Collections.binarySearch).

How to insert Java object into an ArrayList?

I have a problem trying to insert a calculated result into an ArrayList of Student's list of results.
It goes like this.
An ArrayList (called FullList) holds a list of Student objects.
A Student object has a name (as a String) and a resultslist (as an ArrayList).
When i receive a Result object, it comes with a name (as a String) and result (as a Integer).
I want to insert this Result object into the Student object's resultlist.
However, the student names are not defined upfront but deduced upon the receipt of a Results object.
That is to say, if there is no Student object in FullList, the Result object will trigger the creation of a Student object and insert itself into the Student object's resultslist.
Then the created Student object will be inserted into FullList.
I have written the code below but I'm getting multiple insertions of the same tag into FullList instead of insertion of multiple results into each tag.
Q1: I can't figure out what's wrong! Need a mind prick from the Gurus!
Q2: I will be using the following code for up to 90,000 students. Is this a feasible way of housing student results?
class Result {
String name;
int result;
public Result(String name, int result) {
this.name = name;
this.result = result;
}
/* start - Getting hungup over this method
* Something is wrong here and i don't know what it is
*/
public void setResult(ArrayList <Student> fullList) {
for (Student s : fullList) {
if (s.getName().equalsIgnoreCase(this.name)) {
s.setResult(this);
}
else { /* enters here if Student does not exist in fullList */
Student s = new Student(this.name); /* create new student */
s.setResult(this); /* insert result into Student's resultslist */
fullList.add(s); /* add Student into fullList */
}
}
}
/* end */
public String getName() {
return this.name;
}
}
class Student {
String name;
ArrayList <Result> resultslist;
public Student(String name) {
this.name = name;
resultslist = new ArrayList <Result> ();
}
public void setResult(Result result) {
this.resultslist.add(result);
}
public String getName() {
return this.name;
}
}
class StudentResults {
public static void main (String [] args) {
ArrayList <Student> FullList = new ArrayList <Student> ();
Result r1 = new Result("John", 12);
Result r2 = new Result("Jamie", 99);
Result r3 = new Result("John", 69);
Result r4 = new Result("Jacque", 56);
Result r5 = new Result("Jacque", 100);
Result r6 = new Result("Jamie", 100);
r1.setResult(FullList);
r2.setResult(FullList);
r3.setResult(FullList);
r4.setResult(FullList);
r5.setResult(FullList);
r6.setResult(FullList);
}
}
For each student in the list, you're inserting a new student if this student doesn't have the same name as the result to insert:
for (Student s : fullList) {
if (s.getName().equalsIgnoreCase(this.name)) { // current student has same name as result
s.setResult(this);
}
else { // current student doesn't have the same name as result
Student s = new Student(this.name);
s.setResult(this);
fullList.add(s);
}
}
The above should be written as:
Student s = findStudentWithName(fullList, this.name);
if (s == null) {
Student s = new Student(this.name);
s.setResult(this);
fullList.add(s);
}
else {
s.setResult(this);
}
And the findStudentWithName method would look like this:
private Student findStudentWithName(List<Student> students, String name) {
for (Student s : students) {
if (s.getName().equalsIgnoreCase(name)) {
return s;
}
}
// no student found.
return null;
}
Use Map/HashMap in place of List as:
Map<String, Student> fullStudents= new HashMap<Student>();
and use it as:
public void setResult(Map<String, Student> fullMap) {
Student s = fullMap.get(this.name.toLowerCase());
if(s == null){
s = new Student(this.name);
fullMap.put(this.name.toLowerCase(), s);
}
s.setResult(this);
}
Its much simpler and cleaner.
Also to get the list of Students any time, you can simply do:
List<Student> fullList = fullMap.values();

Categories