I have a class as below.
public class Employee{
int EmployeeDepartmentId;
int EmplyoyeeId;
int Salary;
}
I an creating an ArrayList as Below.
ArrayList<Employee> arrEmployee = new ArrayList<Employee>;
Now, I want to find out List of employees from every department with minimum salary.
How can this be achieved. I tried using Collections.Min(), but that will give me the minimum salary from whole list. I want it to be grouped by department.
Any suggestions?
Do two runs. The first to group the employees by department, perhaps using a map:
Map<Integer,List<Employee>>
Then loop over this map grabbing the minimum of each list.
Using the idea by Jim, something like this should work:
Map<Integer, List<Employee>> hmap = new HashMap<Integer, List<Employee>>();
int i = 0;
int size = arrEmployee.size();
for(i = 0; i < size; i++)
{
Employee emp = arrEmployee.get(i);
List<Employee> list = hmap.get(emp.EmployeeDepartmentId);
if (list == null)
{
list = new ArrayList<Employee>();
}
list.add(emp);
hmap.put(emp.EmployeeDepartmentId, list);
}
You should make your own comparator :
Collections.min(list,new Comparator<Employee>() {
public int compare(Employee e1, Employee e2) {
return e2.getSalary().compareTo(e1.getSalary());
}
});
I Hope this help.
This will only get the minimum salary.
every logic is in Comparator they will be grouped by department and sorted by salary:
public class Employee {
Integer EmployeeDepartmentId;
Integer EmplyoyeeId;
Integer Salary;
public Employee(Integer employeeDepartmentId, Integer emplyoyeeId, Integer salary) {
EmployeeDepartmentId = employeeDepartmentId;
EmplyoyeeId = emplyoyeeId;
Salary = salary;
}
public Integer getEmployeeDepartmentId() {
return EmployeeDepartmentId;
}
public void setEmployeeDepartmentId(Integer employeeDepartmentId) {
EmployeeDepartmentId = employeeDepartmentId;
}
public Integer getEmplyoyeeId() {
return EmplyoyeeId;
}
public void setEmplyoyeeId(Integer emplyoyeeId) {
EmplyoyeeId = emplyoyeeId;
}
public Integer getSalary() {
return Salary;
}
public void setSalary(Integer salary) {
Salary = salary;
}
public static void main(String[] args) {
List<Employee> employees=new ArrayList<Employee>();
employees.add(new Employee(3, 3, 50));
employees.add(new Employee(2, 4, 2500));
employees.add(new Employee(1, 1, 100));
employees.add(new Employee(2, 5, 1100));
employees.add(new Employee(1, 2, 20));
for(Employee e:employees)
System.out.println(e.getEmployeeDepartmentId()+" "+e.getEmplyoyeeId()+" "+e.getSalary());
Collections.sort(employees,new Comparator<Employee>() {
#Override
public int compare(Employee e, Employee e1) {
if(e.getEmployeeDepartmentId()==e1.getEmployeeDepartmentId()){
return e.getSalary().compareTo(e1.getSalary());
}else
return e.getEmployeeDepartmentId().compareTo(e1.getEmployeeDepartmentId());
}
});
for(Employee e:employees)
System.out.println(e.getEmployeeDepartmentId()+" "+e.getEmplyoyeeId()+" "+e.getSalary());
}
}
You'll have to do it youself:
Map<Integer, Employee> minSalary = new HashMap<Integer, Employee>();
for(Employee emp : employeeList) {
Integer depId = emp.getDepartmentId();
if(minSalary.containsKey(depId )) {
if(emp.getSalary() < minSalary.get(depId).getSalary()) {
minSalary.put(depId, emp);
}
}
else {
minSalary.put(depId, emp);
}
}
Note that only one Employee is stored with minimal salary, but it is sufficient when you only want to know the salary. If you really need all employees with the minimal salary, you need a Map<Integer, List<Employee>>.
In that case i'd recommend to store the Employees redundantly in a List<Employee> and a `Map<Integer, List<Employee>> (per departmentID, as suggested by other answers.
Related
I am trying to sort the Person reverse alphabetically by name and then sorting in ascending order by age
I could sort in reverse order of name, but unable to sort again in ascending order of age.
PerId Name Age
--------------
7 Simpson 8
3 Michel 10
9 Mark 35
2 Mark 30
8 Lee 40
1 Jorge 19
5 Frank 28
6 Bill 34
4 Bill 16
My Code
class Util {
public static List<Person> getPersons() {
List<Person> col = new ArrayList<Person>();
col.add(new Person(5, "Frank", 28));
col.add(new Person(1, "Jorge", 19));
col.add(new Person(6, "Bill", 34));
col.add(new Person(3, "Michel", 10));
col.add(new Person(7, "Simpson", 8));
col.add(new Person(4, "Bill",16 ));
col.add(new Person(8, "Lee", 40));
col.add(new Person(9, "Mark", 35));
col.add(new Person(2, "Mark", 30));
return col;
}
}
class Person implements Comparator<Person> {
private int perId;
private String name;
private int age;
public Person(){}
public Person(int perId, String name, int age) {
this.perId = perId;
this.name = name;
this.age = age;
}
//.... getters/setters
#Override
public int compare(Person e1, Person e2) {
return e2.getName().compareTo(e1.getName());
}
}
class PersonId implements Comparable<Person>{
private Integer perId;
#Override
public int compareTo(Person o) {
return this.perId.compareTo(o.getPerId());
}
//...getter
}
public class TestPersonSort {
public static void main(String[] args) {
List<Person> coll = Util.getPersons();
Collections.sort(coll, new Person());
// sort method
printList(coll);
//problem here ***********************************************
//Collections.sort(coll);
}
private static void printList(List<Person> list) {
System.out.println("PerId\tName\tAge");
for (Person e: list) {
System.out.println(e.getPerId() + "\t" + e.getName() + "\t" + e.getAge());
}
}
}
Have a Comparator class first compare the person's name. If the comparison is not 0, return it. If it is 0, then move on to compare the person's age.
public int compare(Person e1, Person e2) {
int comp = e2.getName().compareTo(e1.getName()); // desc
if (comp != 0) return comp;
return e1.getAge() - e2.getAge(); // asc
}
Another option, a bit more complicated, but more flexible, is to have a Comparator that uses other Comparators. Then you can supply Comparator<Person>s that compare one attribute each, in a List, to combine their effects.
public class FlexiblePersonComparator implements Comparator<Person>
{
private List<Comparator<Person>> comparators;
public FlexiblePersonComparator(List<Comparator<Person>> comparators)
{
this.comparators = comparators;
}
#Override
public int compare(Person p1, Person p2)
{
int comp;
for (Comparator<Person> comparator : comparators)
{
comp = comparator.compare(p1, p2);
if (comp != 0)
return comp;
}
return 0;
}
}
An easy way is to have Person implement Comparable<Person>. main() can then use Collections.sort(coll);
class Person implements Comparable<Person> {
private int perId;
private String name;
private int age;
public Person(){}
public Person(int perId, String name, int age) {
this.perId = perId;
this.name = name;
this.age = age;
}
//.... getters/setters
#Override
public int compareTo(Person other) {
int result;
if (other == null)
return(0);
if (other == this)
return(0);
result = name.compareTo(other.name);
if (result != 0)
return(-result); // Sort names in reverse
return(age - other.age); // Sort age ascending
}
}
I hava below task. I stuck on the problem a).
Create classes, which describe employees with hourly wage and fixed payment. Give your suggestions
about relations between classes. Implement method for calculating the average monthly salary. For
employees with hourly wage use next formula: “average monthly salary= 20.8*8* hourly rate”, for employees
with fixed payment – “average monthly salary= fixed monthly payment”. Write well commented code for
solving next problems
a) Sort the collection of employees in descending order by the average monthly salary. In the case of
equal salary – by the name. Write ID, name and monthly salary for all employees from collection.
b) Write information about first five employees from collection (problem a).
c) Write ID of three last employees from collection (problem b).
d) Write code for reading and writing collection of these objects from (into) file.
e) Write code for handling the incorrect format of incoming file.
I have created below classes, but I have no idea how to sort different objects from different classes. Please help me!!!!
import java.util.*;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<EmployeeFixedPayment> coll = new ArrayList<Employee>();
EmployeeHourlyWage a = new EmployeeHourlyWage("Edd", "Goo", 23, 4);
EmployeeHourlyWage b = new EmployeeHourlyWage("Tedd", "Foo", 2, 5);
EmployeeHourlyWage c = new EmployeeHourlyWage("Bob", "Bee", 4, 2);
EmployeeHourlyWage d = new EmployeeHourlyWage("Kate", "See", 2, 5);
EmployeeFixedPayment e = new EmployeeFixedPayment("Lisa", "Lee", 7, 500);
EmployeeFixedPayment f = new EmployeeFixedPayment("Mike", "Ree", 10,
450);
EmployeeFixedPayment g = new EmployeeFixedPayment("Izia", "Kurz", 13,
1000);
EmployeeFixedPayment j = new EmployeeFixedPayment("Aisha", "Moore", 20,
800);
coll.add(a);
coll.add(b);
coll.add(c);
coll.add(d);
coll.add(e);
coll.add(f);
coll.add(g);
coll.add(j);
Collections.sort(coll);
// System.out.println(coll.size());
for (Employee i : coll) {
System.out.print(i.secondName + " ");
}
}
}
public class Employee {
String firstName;
String secondName;
int id;
public Employee(String firstName, String secondName,int id){
this.firstName = firstName;
this.secondName = secondName;
this.id = id;
}
public void printEmployee(){
System.out.println(firstName+" "+secondName+" "+id);
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
}
public class EmployeeFixedPayment extends Employee {
double fixedPayment;
public EmployeeFixedPayment(String firstName, String secondName, int id,
double salary) {
super(firstName, secondName, id);
fixedPayment = salary;
}
public double getSalary() {
return fixedPayment;
}
public void setSalary(double salary) {
fixedPayment = salary;
}
}
public class EmployeeHourlyWage extends Employee {
Double hourlyWage;
public EmployeeHourlyWage(String firstName, String secondName, int id, double hourlyRate) {
super(firstName, secondName, id);
hourlyWage = 20.8*8*hourlyRate;
}
public double getWage(){
return hourlyWage;
}
public void setWage(double rate) {
hourlyWage = 20.8*8*rate;
}
}
Implement the Comparable interface for Employee. This way they get sortet the right way when you call Collections.sort(coll) .
Personally I find the CompareToBuilder class helpfull for this.
The trick here is to pull the relevant information (i.e., the monthly salary) up to a base class (Employee), so you can write a Comparator for it.
So first, let's pull the relevant method up to Employee. Since Employee does not contain the logic to calculate its salary, that'd make the class abstract:
public abstract class Employee {
public abstract double getMonthlySalary();
// Rest of the members and methods you declared
}
public class EmployeeFixedPayment extends Employee {
double fixedPayment;
#Override
public double getMonthlySalary() {
return fixedPayment;
}
// Rest of the members, ctots, etc. you declared
}
public class EmployeeHourlyWage extends Employee {
double hourlyWage;
#Override
public double getMonthlySalary() {
return hourlyWage * 20.8 * 8;
}
// Rest of the members, ctots, etc. you declared
}
Now that all Employees expose their salary in a coherent interface, they can be sorted by implementing a Comparator:
public class EmployeeComparator implements Comparator<Employee> {
#Override
public int compare (Employee e1, Employee e2) {
// Note we're comparing e2 to e1 to get a descneding effect
int salaryCompare = Double.compare(e2.getMonthlySalary(), e1.getMonthlySalary());
if (salaryCompare != 0) {
return salaryCompare;
}
// If the salaries are equal, compare names
return e1.getName().compareTo(e2.getName());
}
}
Now, to put it all together, we just sort the List with our custom Comparator:
List<Employee> coll = new ArrayList<>();
Collections.sort(coll, new EmployeeComparator());
I am getting the error Exception in thread "main" java.lang.ClassCastException
: com.genous.Employee cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Arrays.java:1157)
at java.util.Arrays.sort(Arrays.java:1092)
at java.util.Collections.sort(Collections.java:134)
at com.genious.Employee.main(Employee.java:54)//
public class Employee implements Comparator
{
String firstname;
String lastname;
int mobileno;
public Employee(String firstname,String lastname,int mobileno)
{
this.firstname=firstname;
this.lastname=lastname;
this.mobileno=mobileno;
}
#Override
public String toString() {
return firstname;
}
#Override
public int compare(Object o1, Object o2) {
Employee e2=(Employee)o1;
Employee e3=(Employee)o2;
int i=e2.firstname.compareTo(e3.firstname);
if(i!=0)
return i;
return i;
}
/**
* #param args
*/
public static void main(String[] args) {
ArrayList list=new ArrayList();
Employee e=new Employee("anand","pandey",93456666);
Employee e1=new Employee("sheel","nidhi",678956344);
Employee e5=new Employee("shumit", "Kumar", 97390267);
Employee e6=new Employee("Kamal", "Kumar", 97390267);
list.add(e);
list.add(e1);
list.add(e5);
list.add(e6);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
You can Override the equals() method in your employee class and add all your employee objects to a set instead of List you will get the list of unique employee objects.And if you want the count of duplicate entries you can subtract set size() from List size()
//Provided you have overriden the equals() method
List<Employee> employeeList = new ArrayList<Employee>();
Set<Employee> employeeSet = new HashSet<Employee>(employeeList);
int dupEntries = employeeList.size() - employeeSet.size();
System.out.println("Dup Entries : "+dupEntries);
Implement the Comparable interface
public class Empl implemnents Comparable{
public int compareTo(Empl o){
if(.... your check if duplicate ....)
return 0;
return -1;
};
}
and try this
ArrayList<Empl> yourlist = ...;
TreeSet ts = new TreeSet();
ts.addAll(yourlist);
yourlist.removeAll(ts);
now yourlist has all duplicates.
To override equals() is too low-level and offensive for myself.
I'm trying to sort a list of objects by its id. Here is my code:
List<Employee> employee = getEmployeeList();
Collections.sort(employee, new Comparator<Employee>(){
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getEmployeeId().compareTo(employee2.getEmployeeId());
}
});
But nothing happens after the sort, it still shows the original employee list. Am I doing something wrong? I've searched everywhere but they all just do this and it works for them. Here is a hard coded set of Employee Ids:
public class Employee{
private String employeeId = "";
private String employeeName = "";
private String contactNbr = "";
//getters and setters
}
List<Employee> empList = new ArrayList<Employee>();
Employee emp1 = new Employee();
emp1.setEmployeeId("A1B1");
empList.add(emp1);
Employee emp2 = new Employee();
emp2.setEmployeeId("A2B1");
empList.add(emp2);
Employee emp3 = new Employee();
emp3.setEmployeeId("A3B1");
empList.add(emp3);
Collections.sort(empList, new Comparator<Employee>(){
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getEmployeeId().compareTo(employee2.getEmployeeId());
}
});
Check the results of the employeeId compareTo method.
If it always returns 0, the sort will think all the elements are equal. Collections does a stable sort, so if all the elements are equal it will leave the order unchanged.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
public class MainTest {
public static void main(String[] arg)
{
List<Employee> empList = new ArrayList<Employee>();
Employee emp1 = new Employee();
emp1.setEmployeeId("A2B1");
empList.add(emp1);
Employee emp2 = new Employee();
emp2.setEmployeeId("A1B1");
empList.add(emp2);
Employee emp3 = new Employee();
emp3.setEmployeeId("A3B1");
empList.add(emp3);
Collections.sort(empList, new Comparator<Employee>(){
public int compare(Employee employee1, Employee employee2) {
return employee1.getEmployeeId().compareTo(employee2.getEmployeeId());
}
});
Iterator i = empList.iterator();
while(i.hasNext()){
System.out.println(((Employee)i.next()).getEmployeeId());
}
}
}
class Employee{
private String employeeId = "";
private String employeeName = "";
private String contactNbr = "";
public String getContactNbr() {
return contactNbr;
}
public void setContactNbr(String contactNbr) {
this.contactNbr = contactNbr;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
//getters and setters
}
This is printing correctly output:
A1B1
A2B1
A3B1
You are adding the list in the sorted order that's why you are under the impression that your list is not getting the updated. As far as your source is concerned there is no issues you are doing it right. The issue is your input. You are giving the following input in the sorted order as follows.
emp1.setEmployeeId("A1B1");
empList.add(emp1);
emp1.setEmployeeId("A2B1");
empList.add(emp2);
emp1.setEmployeeId("A3B1");
empList.add(emp3);
Your output will be as below
Before sorting: [A1B1, A2B1, A3B1]
After sorting: [A1B1, A2B1, A3B1]
Try modifying the source as below and check
emp1.setEmployeeId("A3B1");
empList.add(emp3);
emp1.setEmployeeId("A2B1");
empList.add(emp2);
emp1.setEmployeeId("A1B1");
empList.add(emp1);
You will get the result as below
Before sorting: [A3B1, A2B1, A1B1]
After sorting: [A1B1, A2B1, A3B1]
If I have the following class:
public class Employee {
private int empId;
private String name;
private int age;
public Employee(int empId, String name, int age) {
// set values on attributes
}
// getters & setters
}
How can I use comparator that compares by name, then age, then id?
You need to implement it so that it orders by preferred elements. That is, you need to compare by name, then if that comparison is equal, compare by age, etc. An example is listed below:
public class EmployeeComparator implements Comparator<Employee> {
#Override
public int compare(Employee e1, Employee e2) {
int nameDiff = e1.getName().compareTo(e2.getName());
if(nameDiff != 0) {
return nameDiff;
}
int ageDiff = e1.getAge() - e2.getAge();
if(ageDiff != 0) {
return ageDiff;
}
int idDiff = e1.getEmpId() - e2.getEmpId();
return idDiff;
}
}
Update
Came across this a moment ago: How to compare objects by multiple fields One of the answers linked to ComparatorChain which will invoke multiple comparators in sequence until a non-zero result is received from a comparator or all comparators are invoked. This should probably be your preferred solution.
Perhaps this (untested) implementation of Comparator#compare() will do the trick.
int compare(Employee e, Employee f)
{
int val = e.name.compareTo(f.name);
if(val == 0)
{
val = e.age - f.age;
if(val == 0)
{
val = e.empId - f.empId;
}
}
return val;
}
You can also implement the Comparable Interface in your class.
for example, something like this:
public class Employee implements Comparable<Employee>{
private int empId;
private String name;
private int age;
public Employee(int empId, String name, int age) {
// set values on attributes
}
// getters & setters
public int compareTo(Employee o) {
int ret = this.name.compareTo(o.name);
if(ret == 0)
ret = this.age - o.age;
if(ret == 0)
ret = this.empId - o.empId;
return ret;
}
}
so you don't have to implement a extra class to compare your Employees.
Implement it
public class Employee {
private int empId;
private String name;
private int age;
/**
* #param empId
* #param name
* #param age
*/
public Employee(int empId, String name, int age) {
super();
this.empId = empId;
this.name = name;
this.age = age;
}
/**
*
*/
public Employee() {
super();
// TODO Auto-generated constructor stub
}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
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;
}
//Compare by name, age and then id
public static Comparator<Employee> COMPARE_EMPLOYEE = new Comparator<Employee>() {
public int compare(Employee one, Employee other) {
//Compare Name
if (one.getName().compareToIgnoreCase(other.getName()) == 0) {
//Compare age
if((one.getAge() - other.getAge()) == 0) {
// Now check with id is useless
// So directly return result of compare by id
return one.getEmpId() - other.getEmpId();
} else { //If age Not equal
return one.getAge() - other.getAge();
}
} else { //If name not equal
return one.getName().compareToIgnoreCase(other.getName());
}
}
};
}
Use :
List<Employee> contacts = new ArrayList<Employee>();
//Fill it.
//Sort by address.
Collections.sort(contacts, Employee.COMPARE_EMPLOYEE);
Read Sorting an ArrayList of Contacts , this must help you and you will get more ideas and different different types of use of Comparator.
guava ComparisonChain:
List<Employee> list = new ArrayList<Employee>();
//...
Collections.sort(list, new Comparator<Employee>(){
#Override
public int compare(Employee e1, Employee e2) {
return ComparisonChain.start()
.compare(e1.empId, e2.empId)
.compare(e1.name, e2.name)
.compare(e1.age, e2.age).result();
}});
Use this:
public class Test
{
public static void main(String[] args)
{
Employee emp1 = new Employee(2, "Tom", 20);
Employee emp2 = new Employee(1, "Tom", 20);
Employee emp3 = new Employee(3, "Hank", 21);
List<Employee> list = new ArrayList<>();
list.add(emp1);
list.add(emp2);
list.add(emp3);
Collections.sort(list, new Employee().new MyComparator());
System.out.println(list);
}
}
class Employee
{
private int empId;
private String name;
private int age;
public Employee()
{}
public Employee(int empId, String name, int age)
{
this.empId = empId;
this.name = name;
this.age = age;
}
class MyComparator implements Comparator<Employee>
{
#Override
public int compare(Employee e1, Employee e2)
{
if(e1.name.compareTo(e2.name) == 0)
{
if(((Integer)e1.age).compareTo(e2.age) == 0)
{
return ((Integer)e1.empId).compareTo(e2.empId);
}
else
{
return ((Integer)e1.age).compareTo(e2.age);
}
}
return e1.name.compareTo(e2.name);
}
}
#Override
public String toString()
{
return "Employee [empId=" + empId + ", name=" + name + ", age=" + age + "]";
}
}
The Comparator interface defines two methods: compare() and equals().
The compare() method, compares two elements for order:
int compare(Object obj1, Object obj2)
obj1 and obj2 are the objects to be compared. This method returns zero if the objects are equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned.
By overriding compare(), you can alter the way that objects are ordered. For example, to sort in a reverse order, you can create a comparator that reverses the outcome of a comparison.
The equals() method, tests whether an object equals the invoking comparator: boolean equals(Object obj)
obj is the object to be tested for equality. The method returns true if obj and the invoking object are both Comparator objects and use the same ordering. Otherwise, it returns false.
Example:
import java.util.*;
class Dog implements Comparator<Dog>, Comparable<Dog> {
private String name;
private int age;
Dog() {
}
Dog(String n, int a) {
name = n;
age = a;
}
public String getDogName() {
return name;
}
public int getDogAge() {
return age;
}
// Overriding the compareTo method
public int compareTo(Dog d) {
return (this.name).compareTo(d.name);
}
// Overriding the compare method to sort the age
public int compare(Dog d, Dog d1) {
return d.age - d1.age;
}
}
public class Example {
public static void main(String args[]) {
// Takes a list o Dog objects
List<Dog> list = new ArrayList<Dog>();
list.add(new Dog("Shaggy", 3));
list.add(new Dog("Lacy", 2));
list.add(new Dog("Roger", 10));
list.add(new Dog("Tommy", 4));
list.add(new Dog("Tammy", 1));
Collections.sort(list); // Sorts the array list
for(Dog a: list) // printing the sorted list of names
System.out.print(a.getDogName() + ", ");
// Sorts the array list using comparator
Collections.sort(list, new Dog());
System.out.println(" ");
for(Dog a: list) // printing the sorted list of ages
System.out.print(a.getDogName() +" : "+ a.getDogAge() + ", ");
}
}
Check it out for more Java Comparator examples.