i am trying to sort the employee object based on salary using the junit test case.
it is my employee sort class
package day4;
import day4.Employee;
public class EmployeesInfoWithSalary {
private Employee[] employee;
private int numberOfEmployees;
public EmployeesInfoWithSalary(Employee[] employee, int numberOfEmployees) {
super();
this.employee = employee;
this.numberOfEmployees = numberOfEmployees;
}
public Employee[] getSortBasedOnSalary() {
String temp;
for (int iterator = 0; iterator < numberOfEmployees; iterator++) {
int minSalary = employee[iterator].getSalary();
int index = iterator;
for (int comparator = iterator; comparator < numberOfEmployees; comparator++) {
if (employee[comparator].getSalary() < minSalary) {
index = comparator;
minSalary = employee[comparator].getSalary();
}
}
employee[index].setSalary(employee[iterator].getSalary());
employee[iterator].setSalary(minSalary);
temp = employee[index].getId();
employee[index].setId(employee[iterator].getId());
employee[iterator].setId(temp);
temp = employee[index].getName();
employee[index].setName(employee[iterator].getName());
employee[iterator].setName(temp);
}
return employee;
}
}
employee object class is as follows
package day4;
public class Employee {
private String id;
private String name;
private int salary;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
testemployee salary class for junit test case is as follows
package day4;
import static org.junit.Assert.*;
import day4.Employee;
import org.junit.Test;
public class TestEmployeeInfoWithSalary {
#Test
public void testGetSortBasedOnSalary() {
Employee[] employee = new Employee[5];
employee[0].setName("pratap");
employee[1].setName("aruna");
employee[2].setName("satyam");
employee[3].setName("krishna");
employee[4].setName("siva");
employee[0].setId("k0100");
employee[1].setId("k0101");
employee[2].setId("k0102");
employee[3].setId("k0103");
employee[4].setId("k0104");
employee[0].setSalary(10000);
employee[1].setSalary(1000);
employee[2].setSalary(8000);
employee[3].setSalary(6000);
employee[4].setSalary(9000);
EmployeesInfoWithSalary employeeInfoWithSalary= new EmployeesInfoWithSalary(employee, 5);
employee[4].setName("pratap");
employee[0].setName("aruna");
employee[2].setName("satyam");
employee[1].setName("krishna");
employee[3].setName("siva");
employee[4].setId("k0100");
employee[0].setId("k0101");
employee[2].setId("k0102");
employee[1].setId("k0103");
employee[3].setId("k0104");
employee[4].setSalary(10000);
employee[0].setSalary(1000);
employee[2].setSalary(8000);
employee[1].setSalary(6000);
employee[3].setSalary(9000);
assertArrayEquals(employee,employeeInfoWithSalary.getSortBasedOnSalary());
}
}
the log is showing the error that null point expression..
can any body help me..
thanks..
I suspect this is the line of the NPE.
// creates an array full of null values.
Employee[] employee = new Employee[5];
employee[0].setName("pratap");
You need to add Employee objects to each element in the array.
A better approach is to use a constructor which takes all the needed fields.
Employee[] employee = {
new Employee("pratap", "k0100", 10000),
new Employee("aruna", "k0101", 1000),
new Employee("satyam", "k0102", 8000),
new Employee("krishna","k0103", 6000),
new Employee("siva", "k0104", 9000) };
After
Employee[] employee = new Employee[5];
for each index in array you need to initialize Employee object.
employee[0] = new Employee(); etc
Related
I need to find and display the the employee who has the maximum salary from the Farm.
this is what I got so far
public class Employee implements Comparable<Employee> {
private String name;
private Integer salary;
public Employee (String name , Integer salary) {
this.name = name;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public Integer getSalary() {
return salary;
}
public String toString() {
return name + " " + salary;
}
public int compareTo(Employee emp) {
return this.salary.compareTo(emp.getSalary());
}
}
Employee class
public class Farm {
private String name;
private Integer surface;
List<Employee> emp = new ArrayList<Employee>();
public Farm(String name , Integer surface) {
this.name = name;
this.surface = surface;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSurface(Integer surface) {
this.surface = surface;
}
public int getSurface () {
return surface;
}
public String toString() {
return name + " " + surface;
}
public void makeList(String ename , Integer esalary) {
this.emp.add(new Employee(ename,esalary));
}
public void getList() {
for(Employee el : emp)
System.out.println(el);
}
}
And the last one is the main. The thing is that I don't know how can I have more farms and get the max from every single one of them. Can you guys help me?
And this is my mainapp
public class Mainapp {
public static void main(String args[])
{
List <Farm> FarmList = new ArrayList<Farm>();
FarmList.add(new Farm("unirea pizdii", 890030));
FarmList.add(new Farm("pseudo autsm",78594));
FarmList.add(new Farm("haha hihi",854856099));
Farm farm1 = new Farm("Tiguana" , 700);
farm1.makeList("Mihai", 30000);
farm1.makeList("Vladimir", 4000);
farm1.makeList("Tusnic", 3000);
farm1.getList();
Employee emp1 = new Employee(" mihai", 3000);
System.out.println(emp1);
}
}
To get employee with max salary for each farm you can use stream api:
import static java.util.stream.Collectors.*;
Map<Farm, Optional<Employee>> collect =
farmList.stream().collect(groupingBy(Function.identity(),
flatMapping(farm -> farm.getEmployes().stream(),
maxBy(Employee::compareTo))));
Result map has Farm as a key and Employee with max salary as a value
Note: flatMapping method is from java9
There are multiple ways to sort a List in Java, one of them being Collections.sort(List), but in this case it looks like you are trying to retrieve the maximum value from the list, so there's no need to add the extra overhead.
EDIT: JB Nizet suggested using Collections.max(List):
public Employee getMostPaidEmployee() {
return Collections.max(emp);
}
One way to get the most paid employee from the list would be to loop through them and compare each one to the previously "saved" most paid employee:
// Farm.java
public Employee getMostPaidEmployee() {
Employee mostPaid = null;
// Initialize maximum to the lowest possible value.
// If salaries can only be positive you could also initialize this to `0`.
int maximumSalary = Integer.MIN_VALUE;
for (Employee employee : emp) {
if (employee.getSalary() > maximumSalary) {
// Reset the most paid fields
mostPaid = employee;
maximumSalary = employee.getSalary();
}
}
return mostPaid;
}
You can declare this method on the Farm class, so you will be able to call it even if you have multiple instances of Farm:
List<Farm> farms = new ArrayList<>();
// TODO Add farms
// Get the most paid employee in first farm
Employee mostPaid = farms.get(0).getMostPaidEmployee();
In terms of performance, this method is linear, i.e. O(n).
We have a ArrayList. It contains duplicate employee objects with only difference in their age, but name and id will be same. So while removing the duplicates, we have to keep the employee with maximum age and remove all other duplicates. This is one of the questions asked by an interviewer in one of the interviews.
I tried solving this. It is giving me correct result, but I am not sure with my approach as I am changing the state of the object in equals method. Is there any other approach to solve this problem?
Code Snippet below: -
package practice;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Employee {
private int id;
private String name;
private int age;
Employee(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public int hashCode() {
return (31*(name.hashCode()) + 31);
}
#Override
public boolean equals(Object obj) {
if ((obj instanceof Employee)) {
if (((Employee)obj).getId() == this.id && (((Employee)obj).getName().equalsIgnoreCase(this.name))) {
if(this.age > ((Employee)obj).getAge()) {
((Employee)obj).setAge(this.age);
}
return true;
} else
return false;
} else
return false;
}
}
public class ListDuplicateRemoval {
public static List<Employee> removeDuplicates(List<Employee> employees) {
Set<Employee> set = new HashSet<>();
for (int i = 0; i < employees.size(); i++) {
set.add(employees.get(i));
}
/*for (int i = 0; i < set.size(); i++) {
System.out.println(set.iterator().next().getAge());
}*/
employees.removeAll(employees);
employees.addAll(set);
return employees;
}
public static void main(String[] args) {
Employee e1 = new Employee(1, "Mike", 20);
Employee e2 = new Employee(1, "Mike", 21);
List <Employee> list = new ArrayList<>();
list.add(e1);
list.add(e2);
removeDuplicates(list);
System.out.println(list.size());
System.out.println(list.get(0).getAge());
}
}
No this solution is really awful. equals should never, ever, modify the state of the objects it's comparing.
Create a class containing the information that identifies employees uniquely, and which properly override equal() and hashCode(). Then use a Map containing these identication info as key, and the employee with the largest age as value. Then get the values and make it a list:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
class Employee {
private int id;
private String name;
private int age;
Employee(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
int getId() {
return id;
}
String getName() {
return name;
}
int getAge() {
return age;
}
#Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
class DuplicateRemoval {
public static void main(String[] args) {
List<Employee> employeeList = Arrays.asList(
new Employee(1, "Joe", 23),
new Employee(2, "Joe", 23),
new Employee(1, "Joe", 21),
new Employee(1, "Jane", 22),
new Employee(1, "Jane", 20)
);
Map<EmployeeKey, Employee> map = employeeList.stream().collect(
Collectors.toMap(e -> new EmployeeKey(e.getId(), e.getName()),
Function.identity(),
(e1, e2) -> e1.getAge() > e2.getAge() ? e1 : e2)
);
List<Employee> result = new ArrayList<>(map.values());
System.out.println("result = " + result);
}
private static class EmployeeKey {
private int id;
private String name;
EmployeeKey(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EmployeeKey that = (EmployeeKey) o;
return id == that.id &&
Objects.equals(name, that.name);
}
#Override
public int hashCode() {
return Objects.hash(id, name);
}
}
}
Implement a Comparator<Employee>
Have the compare method take into account age.
Have the equals method ignore age.
use equals to identify duplicates.
use compare to determine which duplicate to keep.
Can we make the class immutable which has collection as one of the fields?
public class Student implements Comparable<Student> {
private int rollNumber;
private String name;
private Set<String> subjects;
private List<Integer> marks ;
public Student(int rollNumber, String name, Set<String> subjects,
List<Integer> marks) {
this.rollNumber = rollNumber;
this.name = name;
this.subjects = Collections.unmodifiableSet(subjects);
this.marks = Collections.unmodifiableList(marks);
setPercentage();
}
private float percentage;
public int getRollNumber() {
return rollNumber;
}
public String getName() {
return name;
}
public Set<String> getSubjects() {
return new HashSet<>(subjects);
}
public List<Integer> getMarks() {
return new ArrayList<>(marks);
}
public float getPercentage() {
return percentage;
}
private void setPercentage() {
float sum = 0;
for (Integer i : marks)
sum = sum + i;
if (!marks.isEmpty())
percentage = sum / marks.size();
}
}
I am not able to achieve it.
I tried:
Set<String> subjects= new HashSet<>();
subjects.add("Maths");
subjects.add("Science");
subjects.add("English");
List<Integer> marks1= new LinkedList<Integer>();
marks1.add(45);
marks1.add(36);
marks1.add(98);
Student student1= new Student(1, "Payal", subjects, marks1);
//student1.getSubjects().add("History");
subjects.add("History");
System.out.println(student1);
But subjects.add is changing the state of the object.
Please help.
You're making a copy of both collections before returning them from your getters. This is unnecessary, since the collections are unmodifiable (unless you want the caller to get mutable collections and not unmodifiable ones).
What is necessary is to make copies of the collections that are passed from the outside in the contructor. Otherwise, the caller can still modify the collections after they've been stored in your object:
this.subjects = Collections.unmodifiableSet(new HashSet<>(subjects));
this.marks = Collections.unmodifiableList(new ArrayList<>(marks));
To be truly immutable, the class and its fields should also be final.
public class Student implements Comparable<Student> {
private int rollNumber;
private String name;
private Set<String> subjects;
private List<Integer> marks ;
public Student(int rollNumber, String name, Set<String> subjects,
List<Integer> marks) {
this.rollNumber = rollNumber;
this.name = name;
this.subjects = new HashSet<>(subjects);
this.marks = new ArrayList<>(marks);
setPercentage();
}
private float percentage;
public int getRollNumber() {
return rollNumber;
}
public String getName() {
return name;
}
public Set<String> getSubjects() {
return new HashSet<>(subjects);
}
public List<Integer> getMarks() {
return new ArrayList<>(marks);
}
public float getPercentage() {
return percentage;
}
private void setPercentage() {
float sum = 0;
for (Integer i : marks)
sum = sum + i;
if (!marks.isEmpty())
percentage = sum / marks.size();
}
}
I did this. It worked. If I try these 2 operations now, no problem.
Set<String> subjects= new HashSet<>();
subjects.add("Maths");
subjects.add("Science");
subjects.add("English");
List<Integer> marks1= new LinkedList<Integer>();
marks1.add(45);
marks1.add(36);
marks1.add(98);
Student student1= new Student(1, "Payal", subjects, marks1);
student1.getSubjects().add("History");
subjects.add("History");
System.out.println(student1);
Here is the answer
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Student implements Comparable<Student> {
private final int rollNumber;
private final String name;
private final Set<String> subjects;
private final List<Integer> marks;
public Student(int rollNumber, String name, Set<String> subjects, List<Integer> marks) {
this.rollNumber = rollNumber;
this.name = name;
this.subjects = new HashSet<>(subjects);
this.marks = new ArrayList<>(marks);
setPercentage();
}
private float percentage;
public int getRollNumber() {
return rollNumber;
}
public String getName() {
return name;
}
public Set<String> getSubjects() {
return Collections.unmodifiableSet(subjects);
}
public List<Integer> getMarks() {
return new ArrayList<>(marks);
}
public float getPercentage() {
return percentage;
}
private void setPercentage() {
float sum = 0;
for (Integer i : marks) {
sum = sum + i;
}
if (!marks.isEmpty()) {
percentage = sum / marks.size();
}
}
#Override
public String toString() {
return subjects.toString();
}
#Override
public int compareTo(Student o) {
return -1;
}
}
Main Method :
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class NewClass {
public static void main(String[] args) {
Set<String> sub = new HashSet<>();
sub.add("Maths");
sub.add("Science");
sub.add("English");
List<Integer> marks1 = new LinkedList<Integer>();
marks1.add(45);
marks1.add(36);
marks1.add(98);
Student student1 = new Student(1, "Payal", sub, marks1);
sub.add("History");
System.out.println(student1);
}
}
1 : Reason why other code is not working is they make collection unmodifiableSet and unmodifiableList but to the local object while we just need to create new object instead of pointing old reference.
2 : And Second prevent modification of return value, for that just make instance variable to final or you can create new collection object and return it, but if you do that then it create new object each time you call getXXXX method while actually you don't need that object.
I am trying to store a collection of objects on the list employ. But I am getting an error on employ.addAll(), I have tried to employ.add() but I still get the error.
import java.util.ArrayList;
public class Employee {
public String FullName;
public float wage;
public int ID;
ArrayList<Employee> employ = new ArrayList<Employee>();
Employee(String name, float wage, int ID){
this.FullName = name;
this.wage = wage;
this.ID = ID;
}
Employee e = new Employee("Tony", 1245, 2222);
employ.addAll(e); //here is where I a getting the error
}
You are adding a single Employee, so use add, not addAll :
Employee e = new Employee("Tony", 1245, 2222);
employ.add(e);
Beside that, employ.add(e); should be inside some method.
employ.addAll() expects a collection, for adding single element use employ.add().
import java.util.ArrayList;
public class Employee {
public String FullName;
public float wage;
public int ID;
Employee(String name, float wage, int ID){
this.FullName = name;
this.wage = wage;
this.ID = ID;
}
public static void main(String[] args) {
ArrayList<Employee> employ = new ArrayList<Employee>();
Employee e = new Employee("Tony", 1245, 2222);
employ.add(e);
}
}
I have these two classes:
class Student
{
String name;
String age ;
}
class Person
{
String name;
String age ;
String grade ;
}
In the code below, I am creating Student objects and setting them inside the ArrayList. Once the data is set in the ArrayList, I need to parse that ArrayList and set the values in another object:
public class Work {
public static void main(String args[]) {
List StudentItems = new ArrayList();
Student stud1 = new Student();
Student stud2 = new Student();
stud1.name = "ABC";
stud1.age = "28";
stud2.name = "XYZ";
stud2.age = "38";
StudentItems.add(stud1);
StudentItems.add(stud2);
Person[] pers = new Person[StudentItems.size()];
for (int i = 0; i < StudentItems.size(); i++) {
pers[i] = new Person();
// I am confused here , could anyone please help
}
}
}
Try it out. This will do the work
Your Person class should be something like this:
package com.student.person.work;
/**
*
* #author sarath_sivan
*/
public class Person {
private String name;
private int age;
private String grade;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getGrade() {
return this.grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
Your Student class should be something like this:
package com.student.person.work;
/**
*
* #author sarath_sivan
*/
public class Student {
private String name;
private int age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
And finally, the Work class:
package com.student.person.work;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author sarath_sivan
*/
public class Work {
public static String calculateGrade() {
String grade = "";
// Your code to find the grade.
//............
return grade;
}
public static void doWork() {
List<Student> studentList = new ArrayList<Student>();
Student student = new Student();
student.setName("ABC");
student.setAge(24);
studentList.add(student);
student = new Student();
student.setName("DEF");
student.setAge(28);
studentList.add(student);
student = new Student();
student.setName("GHI");
student.setAge(21);
studentList.add(student);
List<Person> personList = new ArrayList<Person>();
for(Student students : studentList) {
Person person = new Person();
person.setName(students.getName());
person.setAge(students.getAge());
person.setGrade(Work.calculateGrade());// Setting the grade
}
}
public static void main(String[] args) {
Work.doWork();
}
}
Hope this will be helpful.
Thank you!
Something like this:
List<Student> studentItems = new ArrayList<Student>();
Student stud1 = new Student();
Student stud2 = new Student();
stud1.name = "ABC";
stud1.age = "28";
stud2.name = "XYZ";
stud2.age = "38";
studentItems.add(stud1);
studentItems.add(stud2);
for (int i = 0; i < studentItems.size(); i++) {
Student student = studentItems.get(i);
Person person = new Person();
person.name = student.name;
person.age = student.age;
// person.grade = something - set grade here
pers[i] = person;
}
But be avare that you shouldn't use public fields... so it should look like this:
for (int i = 0; i < studentItems.size(); i++) {
Student student = studentItems.get(i);
Person person = new Person();
person.setName(student.getName());
person.setAge(student.getAge());
// person.setGrade(computeGradeSomehow()); - set grade here
persons[i] = person;
}
If you are frequently converting from student object to Person object, add following like constructor and setter/getter method
class Person {
String name;
String age;
String grade;
public Person() {
}
Person(Student student) {
this.name = student.getName();
this.age = student.getAge();
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
class Student {
private String name;
private String age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
And in Work class, create Person object like,
List<Student> studentItems = new ArrayList<Student>();
List<Person> personItems = new ArrayList<Person>();
for (int i = 0; i < studentItems.size(); i++) {
Student student = studentItems.get(i);
Person person = new Person(student);
person.setGrade(your_formula_for grade);
personItems.add(person);
}
You can do it as follow:
pers[i].name = StudentItems.get(i).name;
Grade should be in the Student class. If you to this, your classes should look like this:
class Person {
private String name;
private int age;
//getters and setters
}
class Student extends Person { // here you have name and age from Person
private String grade;
//getters and setters
}
Now, you want the list of persons from the list of students? You can do this:
for (int i = 0; i < listOfStudents.size(); i++){
arrayOfPersons[i] = (Person)listOfStudents.get(i);
}
Given, that your classes are really properly layouted (see my comment), you could write a constructor for person which takes an Student as input:
pers[i] = new Person (StudentItems[i]);
note, that I would rename the variables:
persons [i] = new Person (students[i]);
Your Person with the new CTor would look like this:
class Person
{
String name;
String age ;
String grade ;
public Person () {}
public Person (s Student) {
name = s.name;
age = s.age;
}
}
More probably, you want to change the name of Student and Person, and derive Student from Person. Then, every Student is a person, and in your loop, it is justs:
persons [i] = students[i];