Refactoring code to be Generics and functional interface - java

I have two interfaces one can be used to find some statistics by Key and Value and the other is used to visit an object and iterate over it, the first one has the following methods:
public interface Statistic {
public String getKey();
public Object getValue();
public String getDetails();
}
And here is the implementation for it:
public class Collector implements Statistic {
private String key;
private int val;
public Collector(String key, int val) {
this.key = key;
this.val = val;
}
public void setValue(int val) {
this.val = val;
}
#Override
public String getKey() {
return key;
}
#Override
public Integer getValue() {
return val;
}
#Override
public String getDetails() {
return null;
}
}
And the other one has the following:
public interface StatisticsCollector<T extends Object, S extends Statistic> {
public String getName();
public void visit(T object);
public Iterator<S> calculatedStatistics();
}
And here is the implementation for it:
public class CalculateFromObject<K, V> implements StatisticsCollector<Object, Collector> {
EmployeeValidator empValidator = new EmployeeValidator();
StringValidator strValidator = new StringValidator();
#Override
public String getName() {
return null;
}
#Override
public void visit(Object object) {
if (object instanceof String) {
String str = object.toString();
int upperCaseCount = strValidator.upperCaseFreq(str);
strValidator.set.add(new Collector("Upper Case Letters: ", upperCaseCount));
int lowerCaseCount = strValidator.lowerCaseFreq(str);
strValidator.set.add(new Collector("Lower Case Letters: ", lowerCaseCount));
int digitsCount = strValidator.digitFreq(str);
strValidator.set.add(new Collector("Digits Count: ", digitsCount));
int wordCount = strValidator.wordFreq(str);
strValidator.set.add(new Collector("Words Count: ", wordCount));
int nonWordCount = strValidator.nonWordFreq(str);
strValidator.set.add(new Collector("Non Word Count: ", nonWordCount));
} else if (object instanceof Employee) {
Employee emp = (Employee) object;
empValidator.salaryValidator(emp);
empValidator.birthDateValidator(emp);
empValidator.birthPlaceValidator(emp);
empValidator.resignationDateValidator(emp);
empValidator.positionValidator(emp);
}
}
#Override
public Iterator<Collector> calculatedStatistics() {
return empValidator.set.iterator();
}
}
And in my package I have a bean for Employee which has few properties like firstName, lastName, salary and position with their setters and getters.
I would like to do some validations like get me the number of employees which has a salary of x and been born in 1990 and did the following class for these validations:
public class EmployeeValidator {
public Set<Collector> set = new HashSet<>();
public void salaryValidator(Employee emp) {
int count = 0;
// each collector consist of a condition (function), key, value (always incremented)
if (emp.getSalary() < 350) {
set.add(new Collector("Employee with salaries less than 350JD: ", ++count));
} else if (emp.getSalary() >= 350 && emp.getSalary() < 600) {
set.add(new Collector("Employee with salaries between 350JD And 600JD: ", ++count));
} else if (emp.getSalary() >= 600 && emp.getSalary() < 1200) {
set.add(new Collector("Employee with salaries between 600JD And 1200JD ", ++count));
} else if (emp.getSalary() >= 1200) {
set.add(new Collector("Employee with salaries more than 1200JD: ", ++count));
}
}
public void birthDateValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where born in " + emp.getBirthDate().getYear() + " = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where born in " + emp.getBirthDate().getYear() + " = ", 1));
}
public void birthPlaceValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where born in " + emp.getBirthPlace() + " = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where born in " + emp.getBirthPlace() + " = ", 1));
}
public void resignationDateValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ").equals(
stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ", 1));
}
public void positionValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that occupy the " + emp.getPosition() + " position = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that occupy the " + emp.getPosition() + " position = ", 1));
}
private void count(Collector stats) {
int counter = stats.getValue() + 1;
stats.setValue(counter);
}
}
And I have another class to validate strings and see how many uppercase letters a string has, how many lower case it has...etc
As you can see in the visit method in the CalculateFromObject class im calling all my methods to do the validations, everything is working fine and I am getting the expected results, but my code is not very efficient as I would like to make it generic and make it accept any type of object, I have done few tries but im stuck.
I have tried to write a functional interface called Conditions that has one method that I can pass a condition and check it like the following:
public interface Conditions {
boolean checkCondition(Object obj);
}
So can someone suggest what is the best way to change my code to be generic and accept any type of objects like Student for example and to be as clean as possible maybe by applying a design pattern?

There's a lot of overhead in your classes and misunderstanding of interfaces against POJO's (simple classes). On a high level you should do the following:
1). Remove interface Statistic and class Collectors. They are just incapsulating data. Instead - create a POJO Employee with necessary fields + getters + setters. Don't use 'key-value`, give those fields meaningful names:
public class Employee
{
private String name;
private int id;
private double salary;
...
public String getName() {...}
public void setName(..) {...}
// other getters / setters
}
Create constructor if needed
2) Looks like your Employee class is also redundant, remove it. Use new Employee instead
3) Use Collections framework to store collections of your employee's instances.
`List<Employee> employees = new ArrayList<>();
employees.add(new Employee(.... )); `
4). Create interface EmployeeValidator with validating methods and implement it:
public interface EmployeeValidator {
void validate(List<Employee> employees);
}
5) If you want to operate some statistics data, create a separate Statistics class which will operate on collections of employees, e.g.
public class Statistics {
public double getAvgSalary(List<Employee> employees)
{
double avgSalary = 0;
for (Employee e : employees) {
....
}
}
}

Related

How can I use the indexOf() function to find an object with a certain property

I have an object, Pet, and one of the functions is to retrieve its name.
public class pet{
private String petName;
private int petAge;
public pet(String name, int age){
petName = name;
petAge = age;
}
public String getName(){
return petName;
}
public int getAge(){
return petAge;
}
}
I then have an ArrayList which holds a collection of pets as shown in the code below:
import java.util.ArrayList;
pet Dog = new pet("Orio", 2);
pet Cat = new pet("Kathy", 4);
pet Lion = new pet("Usumba", 6);
ArrayList<pet> pets = new ArrayList<>();
pets.add(Dog);
pets.add(Cat);
pets.add(Lion;
I was wondering how I could retrieve the index in the ArrayList or the object that has the name I need. So if I wanted to find out how old Usumba was, how would I do this?
Note: This is not my actual piece of code, it's just used so that I can better explain my problem.
Edit 1
So far, I have the following but I was wondering if there was a better or more efficient way
public int getPetAge(String petName){
int petAge= 0;
for (pet currentPet : pets) {
if (currentPet.getName() == petName){
petAge = currentPet.getAge();
break;
}
}
return petAge;
}
You can't use indexOf() for this purpose, unless you abuse the purpose of the equals() method.
Use a for loop over an int variable that iterates from 0 to the length of the List.
Inside the loop, compare the name if the ith element, and if it's equal to you search term, you've found it.
Something like this:
int index = -1;
for (int i = 0; i < pets.length; i++) {
if (pets.get(i).getName().equals(searchName)) {
index = i;
break;
}
}
// index now holds the found index, or -1 if not found
If you just want to find the object, you don't need the index:
pet found = null;
for (pet p : pets) {
if (p.getName().equals(searchName)) {
found = p;
break;
}
}
// found is now something or null if not found
As the others already stated, you cannot use indexOf() for this directly. It would be possible in certain situations (lambdas, rewriting hashCode/equals etc), but that is usually a bad idea because it would abuse another concept.
Here's a few examples of how we can do that in modern Java:
(as the index topic has already been answered quite well, this only handles direct Object return)
package stackoverflow.filterstuff;
import java.util.ArrayList;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
public class FilterStuff {
public static void main(final String[] args) {
final Pet dog = new Pet("Orio", 2); // again, naming conventions: variable names start with lowercase letters
final Pet cat = new Pet("Kathy", 4);
final Pet lion = new Pet("Usumba", 6);
final ArrayList<Pet> pets = new ArrayList<>();
pets.add(dog);
pets.add(cat);
pets.add(lion);
try {
simpleOldLoop(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
simpleLoopWithLambda(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
filterStreams(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
filterStreamsWithLambda(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
}
private static void simpleOldLoop(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.simpleOldLoop()");
System.out.println("Pet named 'Kathy': " + filterPet_simpleOldLoop(pPets, "Kathy"));
System.out.println("Pet named 'Hans': " + filterPet_simpleOldLoop(pPets, "Hans"));
}
private static Pet filterPet_simpleOldLoop(final ArrayList<Pet> pPets, final String pName) {
if (pPets == null) return null;
for (final Pet pet : pPets) {
if (pet == null) continue;
if (Objects.equals(pet.getName(), pName)) return pet;
}
return null;
}
private static void simpleLoopWithLambda(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.simpleLoopWithLambda()");
System.out.println("Pet named 'Kathy': " + filterPet_simpleLoopWithLambda(pPets, (pet) -> Boolean.valueOf(Objects.equals(pet.getName(), "Kathy"))));
System.out.println("Pet named 'Hans': " + filterPet_simpleLoopWithLambda(pPets, (pet) -> Boolean.valueOf(Objects.equals(pet.getName(), "Hans"))));
}
private static Pet filterPet_simpleLoopWithLambda(final ArrayList<Pet> pPets, final Function<Pet, Boolean> pLambda) {
if (pPets == null) return null;
for (final Pet pet : pPets) {
if (pet == null) continue;
final Boolean result = pLambda.apply(pet);
if (result == Boolean.TRUE) return pet;
}
return null;
}
private static void filterStreams(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.filterStreams()");
System.out.println("Pet named 'Kathy': " + filterPet_filterStreams(pPets, "Kathy"));
System.out.println("Pet named 'Hans': " + filterPet_filterStreams(pPets, "Hans"));
}
private static Pet filterPet_filterStreams(final ArrayList<Pet> pPets, final String pName) {
return pPets.stream().filter(p -> Objects.equals(p.getName(), pName)).findAny().get();
}
private static void filterStreamsWithLambda(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.filterStreamsWithLambda()");
System.out.println("Pet named 'Kathy': " + filterPet_filterStreams(pPets, p -> Objects.equals(p.getName(), "Kathy")));
final Predicate<Pet> pdctHans = p -> Objects.equals(p.getName(), "Hans"); // we can also have 'lambda expressions' stored in variables
System.out.println("Pet named 'Hans': " + filterPet_filterStreams(pPets, pdctHans));
}
private static Pet filterPet_filterStreams(final ArrayList<Pet> pPets, final Predicate<Pet> pLambdaPredicate) {
return pPets.stream().filter(pLambdaPredicate).findAny().get();
}
}
Along with your Pet class, extended by toString():
package stackoverflow.filterstuff;
public class Pet { // please stick to naming conventions: classes start with uppercase letters!
private final String petName;
private final int petAge;
public Pet(final String name, final int age) {
petName = name;
petAge = age;
}
public String getName() {
return petName;
}
public int getAge() {
return petAge;
}
#Override public String toString() {
return "Pet [Name=" + petName + ", Age=" + petAge + "]";
}
}

Removing an specific object from an arraylist

I need help removing a specific object from an arraylist. I'm creating objects with a unique ID and grade for each object.I'm trying to use this unique ID to remove an object from the arraylist, but am having trouble figuring out why my code isn't working. I have my main Driver class, a superclass, and a subclass.
The subclass is where the object information is passed from and extends the superclass. I thought that since the subclass is extended, it would be able to be defined from there.
The problem that is occurring is line 49 of the superclasss. Eclipse says that getStudentID isn't defined in the class.
I am trying to modify code that my instructor provided in order to locate this unique ID that an object in the arraylist has. I believe I did everything correctly, but the method "locationPerson" doesn't seem to see the getStudentID() method in the subclass.
Here is the code. Any help would be appreciated!
Subclass
public class StudentEnrollee extends ClassSection{
private int grade;
private String studentID;
StudentEnrollee() {
setStudentID("000-000");
setGrade(0);
}
StudentEnrollee(String ID, int theGrade) {
setStudentID(ID);
setGrade(0);
}
//STUDENT ID
public String getStudentID() {
return studentID;
}
public void setStudentID(String theStudentID) {
this.studentID = theStudentID;
}
//STUDENT GRADE
public int getGrade() {
return grade;
}
public void setGrade(int studentGrade) {
this.grade = studentGrade;
}
public String toString() {
return("Student ID : " + studentID + "\n" +
"Student Grade: " + grade);
}
}
Superclass
import java.util.ArrayList;
import java.util.List;
public class ClassSection {
private int crn, courseNumber, capacity, enrollment, ID, student;
private String departmentCode, courseMode, meetingDay, meetingTime;
//CONSTRUCTOR
ClassSection() {
setCrn(0);
setDepartmentCode("");
setCourseNumber(0);
setCourseMode("");
setMeetingDay("");
setMeetingTime("");
setCapacity(0);
setEnrollment(0);
setID(0);
}
ClassSection(int crn, String departmentCode, int courseNumber, String courseMode, String meetingDay, String meetingTime, int capacity, int enrollment, int ID) {
setCrn(crn);
setDepartmentCode(departmentCode);
setCourseNumber(courseNumber);
setCourseMode(courseMode);
setMeetingDay(meetingDay);
setMeetingTime(meetingTime);
setCapacity(capacity);
setEnrollment(enrollment);
setID(ID);
}
//STUDENT ENROLL ARRAY
List < StudentEnrollee > studentList = new ArrayList < StudentEnrollee > ();
public int getStudent() {
return student;
}
public void addStudent(StudentEnrollee studentObject) {
studentList.add(studentObject);
}
//LOCATING PERSON
public ClassSection locatePerson(String getStudentID) {
for (ClassSection personObject: studentList) {
if (personObject.getStudentID().equals(getStudentID)) {
return personObject;
}
}
return null;
}
//Delete person
public void deletePerson(String studentID) {
ClassSection personObject = locatePerson(studentID); // we'll use our locatePerson method find the index of a Person with a given socSecNum.
if (personObject != null) studentList.remove(personObject); // if element i contains the target SSN, remove it.
}
//DISPLAY LIST OF ENROLLEE
public void displayListV1() {
for (int i = 0; i < studentList.size(); i++) // the old way
{
System.out.println(studentList.get(i) + "\n");
}
}
//CRN
public int getCrn() {
return crn;
}
void setCrn(int classCrn) {
this.crn = classCrn;
}
//DEPARTMENT CODE
public String getDepartmentCode() {
return departmentCode;
}
void setDepartmentCode(String classDepartmentCode) {
this.departmentCode = classDepartmentCode;
}
//COURSE NUMBER
public int getCourseNumber() {
return courseNumber;
}
void setCourseNumber(int classCourseNumber) {
this.courseNumber = classCourseNumber;
}
//COURSE LOCATION
public String getCourseMode() {
return courseMode;
}
public void setCourseMode(String classCourseMode) {
this.courseMode = classCourseMode;
}
//MEETING DAY
public String getMeetingDay() {
return meetingDay;
}
public void setMeetingDay(String classMeetingDay) {
this.meetingDay = classMeetingDay;
}
//MEETING TIMES
public String getMeetingTime() {
return meetingTime;
}
public void setMeetingTime(String classMeetingTime) {
this.meetingTime = classMeetingTime;
}
//CAPACITY
public int getCapacity() {
return capacity;
}
public void setCapacity(int classCapacity) {
this.capacity = classCapacity;
}
//ENROLLMENT
public int getEnrollment() {
return enrollment;
}
public void setEnrollment(int classEnrollment) {
this.enrollment = classEnrollment;
}
//INSTRUCTOR ID
public int getID() {
return ID;
}
public void setID(int instructorID) {
this.ID = instructorID;
}
//TO STRING METHOD
public String toString() {
return ("CRN :" + crn + "\n" +
"Department :" + departmentCode + "\n" +
"Course Number :" + courseNumber + "\n" +
"Instructional mode :" + courseMode + "\n" +
"Meeting days :" + meetingDay + "\n" +
"Meeting times :" + meetingTime + "\n" +
"Capacity :" + capacity + "\n" +
"Enrollment :" + enrollment + "\n" +
"Instructor’s ID :" + ID + "\n");
}
}
Driver
public class ClassDriver {
public static void main(String[] args) {
ClassSection firstInstance = new ClassSection(20008, "CHM", 000, "Online", "N/A", "N/A", 30, 21, 231);
ClassSection secondInstance = new ClassSection();
ClassSection addToList = new ClassSection();
StudentEnrollee studentObj1 = new StudentEnrollee();
StudentEnrollee studentObj2 = new StudentEnrollee();
StudentEnrollee studentObj3 = new StudentEnrollee();
studentObj1.setGrade(5);
studentObj1.setID(230);
studentObj2.setGrade(76);
studentObj2.setID(45);
studentObj3.setGrade(2);
studentObj3.setID(34);
addToList.addStudent(studentObj1);
addToList.addStudent(studentObj2);
addToList.addStudent(studentObj3);
addToList.deletePerson("45");
addToList.displayListV1();
System.out.println(firstInstance.toString());
System.out.println(secondInstance.toString());
}
}
I think it should be:
public StudentEnrollee locatePerson(String getStudentID) {
for (StudentEnrollee personObject: studentList) {
if (personObject.getStudentID().equals(getStudentID)) {
return personObject;
}
}
return null;
}
You are trying to use a method from subclass in superclass, so you got the error that this method is not defined. You can use all method of superclass in subclasses, but it doesn't work another way.
The getStudentID() method is declared in class StudentEnrollee. In the code below, personObject, which is defined as a ClassSection object, does not have access to it.
public ClassSection locatePerson(String getStudentID) {
for (ClassSection personObject: studentList) {
if (personObject.getStudentID().equals(getStudentID)) {
return personObject;
}
}
return null;
}
The solution can vary based on your program logic, but the straightforward way is to replace ClassSection with StudentEnrollee:
public StudentEnrollee locatePerson(String getStudentID) {
for (StudentEnrollee personObject: studentList) {
if (personObject.getStudentID().equals(getStudentID)) {
return personObject;
}
}
return null;
}

Trying to make a 2d array program to store a list of Car objects

Struggling with a little project I've set myself to learn Java. My goal is to create a program to store a list of Car objects. Then to allow the user to search for a particular car and output all of them if they exist. The car object should contain model name, registration number, vin and colour. Here is what I have so far:
package carObjects;
public class cars {
public static int length;
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public cars(String string, String string2, int i) {
}
public String toString() {
return "Model Name: " + modelName + "Registration Number: " + regNumber
+ "Vin" + vin + "Car Colour: " + carColour;
}
public String getLast() {
return modelName;
}
}
for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
for (cars p : cars) {
System.out.println(p.getLast());
}
}
}
Here are some of the things you would need to do:
Since you want to allow searching, you will need to expose accessors to the properties which you would like the user to search for. For instance, if you want to allow users to search by model, you will need to expose the model property. You seem to be doing this through the getLast() method, however, the name is confusing.*
The problem with this code: for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
Is that it is creating a series of identical objects. You could use the value of i to provide some dummy, changing values. This will allow you to test that your search is indeed working.
Constructor names should start with an upper case, just like class names.
cars(String string, String string2, int i): Please provide meaningful names to your variables. This will make your code easier to read.
You will need to assign the variables you are getting through your constructor. As is, at the moment your fields will not be initialized to what you are providing.
To create a 2D array, you will need to use the following syntax: Car[][] carArr = new Car[5][5]. This will create a 5x5 array of type car. To iterate over it, you will need to use a nested loop:
for(int i = 0; i < carrArr.length; i++) {
for (int j = 0; j < carrArr[i].lenght;j++) {
...
}
}
* The usage of getters and setters allow you to control which object properties are exposed and how can users interact with them.
The best would be to separate your exercise in two different classes:
class Car {
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public int getVin() {
return vin;
}
public void setVin(int vin) {
this.vin = vin;
}
// other getter/setter
#Override
public String toString() {
return "Car: " + getVin();
}
#Override
public int hashCode() {
return vin;
}
#Override
public boolean equals(Object obj) {
return (obj != null)
&& (obj instanceof Car)
&& ((Car) obj).getVin() == this.getVin();
}
}
CarSet class has the searching methods:
class CarList extends HashSet<Car> {
public Car serarchByVin(int vin) {
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getVin() == vin) {
return c;
}
}
return null;
}
public CarSet searchByModel(String model) {
CarSet result = new CarSet();
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getModelName()== model) {
result.add(c);
}
}
return result;
}
#Override
public String toString() {
String result = "carList: ";
for (Car c : this) {
result += c;
}
return result;
}
}

How do I create an instance of another class, load an object with data and print it out?

I am a complete noob (5th day programming) which explains why I have spent countless head-aching hours trying to solve this problem and still have not figured it out yet:
How do you create an instance of CarAndBikes, load it with information of 3 cars and print it out?
Here's my incomplete code to give you an idea of the problem:
public class Vehicle {
String manufacturer, model;
int numberOfWheels;
public Vehicle(String manufacturer, String model, int numberOfWheels) {
this.manufacturer = manufacturer;
this.model = model;
this.numberOfWheels = numberOfWheels;
}
public String getManufacturer() {
return manufacturer;
}
public String getModel() {
return model;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
public String toString() {
return "(" + numberOfWheels +") '" + manufacturer + ", " + model + "'";
}
}
public class CarAndBikes {
private Vehicle[] items;
private int nextFreeItem = 0;
CarAndBikes (int size) {
items = new Vehicle[size];
for(int i = 0; i < size; i++)
items[i] = new Vehicle(manufacturer, model, numberOfWheels);
}
void addVehicle(String man, String mdl, int wheels) {
items[nextFreeItem++].addVehicle(man, mdl, wheels);
}
public String toString() {
return "(" + items + ")";
}
}
public class TestProgram extends CarAndBikes{
TestProgram(int size) {
super(size);
}
public static void main(String[] args) {
Vehicle vehicle1 = new Vehicle("Seat", "Ibiza", 4);
Vehicle vehicle2 = new Vehicle("Reliant", "Robin", 3);
Vehicle vehicle3 = new Vehicle("Honda", "Fireblade", 2);
System.out.println(vehicle1);
System.out.println(vehicle2);
System.out.println(vehicle3);
}
}
In my opinion you'd be better off separating cars and bikes into separating cars and bikes into two seperate classes 'Car' and 'Bike' and then create a 3rd class to house a collection of those objects, that way you can use an List or ArrayList to store them and have a method to just print them out.
import java.util.ArrayList;
Public Class Garage
{
private ArrayList<Vehicle> vehicles;
Public Garage()
{
vehicles = new ArrayList<Vehicle>();
}
public void addVehicle(Vehicle v)
{
vehicles.add(v);
}
public void getVehicles()
{
for(Vehicle v : vehicles)
{
System.out.Println(v.getModel());
}
}
}
You'll notice that the ArrayList accepts objects of type vehicle, well both cars and bikes extend vehicle so they will be accepted.
I notice the toString() method in CarAndBikes is using toString() on an array reference (and arrays don't override toString()). You could use Arrays.toString(Object[]) like
public String toString() {
// return "(" + items + ")";
return Arrays.toString(items);
}
The Object.toString() that you're getting is documented as,
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())

Sort array of object by particular member inside the object/class

Say I have a class that looks like this (get/set omited):
class InfoClass{
String name;
String place;
double distance;
}
And I create an array of my class from within my main activity that looks like this:
InfoClass[3] myInfoClass;
myInfoClass[0].name = "venue one";
myInfoClass[0].place = "place one";
myInfoClass[0].distance = 11.23234;
myInfoClass[1].name = "venue two";
myInfoClass[1].place = "place two";
myInfoClass[1].distance = 9.2345643;
myInfoClass[2].name = "venue three";
myInfoClass[2].place = "place three";
myInfoClass[2].distance = 5.23432;
How can I sort my array (myInfoClass[]) so that it is ordered by the distance member?
i.e in the above example the array would be reversed because element [2] has the smallest distance and element [0] has the greatest distance?
Is there some function I can add to my class to do this or some other way?
this should work ..
public static void main(String[] args){
InfoClass[] dd = new InfoClass[3];
Arrays.sort(dd, new Comparator<InfoClass>(){
#Override
public int compare(InfoClass arg0, InfoClass arg1) {
// TODO Auto-generated method stub
if(arg0.distance == arg1.distance){
return 0;
}else if(arg0.distance < arg1.distance){
return -1;
}else{
return 1;
}
}
});
}
Modify your class and implement Comparable interface if you don't want to use Comparator its also preferable when by default you want to provide sorting to array/collection of your objects then go for Comparable
class InfoClass implements Comparable<InfoClass> {
String name;
String place;
double distance;
#Override
public int compareTo(InfoClass o) {
return new Double(this.distance).compareTo(new Double(o.distance));
}
and then you can sort them
Arrays.sort(myInfoClass)
You can use Arrays.Sort with a custom comparator like so:
Arrays.Sort(myInfoClass, new Comparator<InfoClass>() {
#Override
public int compare(InfoClass o1, InfoClass o2){
if (o1==null && o2==null) return 0;
if (o1 == null) return -1;
if (o2 == null) return 1;
return o1.distance.compareTo(o2.distance);
}
});
EDIT: null checking for the win.
Use java.util.Arrays.sort() and specify your own Comparator:
InfoClass[] myInfoClass = new InfoClass[3];
myInfoClass[0] = new InfoClass();
myInfoClass[1] = new InfoClass();
myInfoClass[2] = new InfoClass();
myInfoClass[0].name = "venue one";
myInfoClass[0].place = "place one";
myInfoClass[0].distance = 11.23234;
myInfoClass[1].name = "venue two";
myInfoClass[1].place = "place two";
myInfoClass[1].distance = 9.2345643;
myInfoClass[2].name = "venue three";
myInfoClass[2].place = "place three";
myInfoClass[2].distance = 5.23432;
Arrays.sort(myInfoClass,
new Comparator<InfoClass>()
{
public int compare(InfoClass o1, InfoClass o2)
{
if (o1.distance == o2.distance)
{
return 0;
}
else if (o1.distance < o2.distance)
{
return -1;
}
return 1;
}
});
Arrays.sort(myInfoClass, new Comparator<InfoClass>() {
#Override
public int compare(InfoClass o1, InfoClass o2) {
return Double.valueOf(o1.distance).compareTo(o2.distance);
}
});
Convert array to ArrayList, then using Collection.sort method to sort the ArrayList.
Also sorting in descending order
Arrays.sort(aStudents, Collections.reverseOrder());
Internally Collections define method calls
`public static <T> Comparator<T> reverseOrder() {
return (Comparator<T>) REVERSE_ORDER;
}
public int compare(Comparable c1, Comparable c2) {
return c2.compareTo(c1);
}`
Hope , This example will help you sort class object base on various fields
import java.util.*;
import java.lang.*;
import java.io.*;
public class Main
{
public static void main ( String [] args) throws IOException
{
Employee empList[] = new Employee [4];
empList[0] = new Employee (8,"Kiran","Developer",15000);
empList[1] = new Employee (18,"Krishna","DBA",35000);
empList[2] = new Employee (3,"Pradeep","Tester",25000);
empList[3] = new Employee (7,"Mithun","Admin",20000);
Arrays.sort(empList);
System.out.println("\nAfter Sorting Base On ID");
for (Employee emp : empList)
System.out.println(emp);
Arrays.sort( empList , new EmployeeByDept() );
System.out.println("\nAfter Sorting Base On Department");
for (Employee emp : empList)
System.out.println(emp);
Arrays.sort( empList , new EmployeeByName() );
System.out.println("\nAfter Sorting Base On Name");
for (Employee emp : empList)
System.out.println(emp);
Arrays.sort( empList , new EmployeeBySalary() );
System.out.println("\nAfter Sorting Base On Salary");
for (Employee emp : empList)
System.out.println(emp);
}
}
class EmployeeByDept implements Comparator<Employee>
{
//compare() is mathod of Comparable Interface
// Use When we want to sort on other field like Department
#Override
public int compare(Employee emp1, Employee emp2)
{
return emp1.getDept().compareTo(emp2.getDept());
}
}
class EmployeeByName implements Comparator<Employee>
{
//compare() is mathod of Comparable Interface
// Use When we want to sort on other field like Department
#Override
public int compare(Employee emp1, Employee emp2)
{
return emp1.getName().compareTo(emp2.getName() );
}
}
class EmployeeBySalary implements Comparator<Employee>
{
//compare() is mathod of Comparable Interface
// Use When we want to sort on other field like Department
#Override
public int compare(Employee emp1, Employee emp2)
{
return ( emp1.getSalary() - emp2.getSalary());
}
}
class Employee implements Comparable<Employee>
{
int $id ;
String $name ;
String $dept ;
int $salary ;
public Employee(int id , String name , String dept , int salary)
{
this.$id = id;
this.$name = name ;
this.$dept = dept ;
this.$salary = salary ;
}
public int getID () { return this.$id ; }
public String getName () { return this.$name ; }
public String getDept () { return this.$dept ; }
public int getSalary () { return this.$salary ; }
public String toString()
{
return "[ "
+ "ID :: " + $id
+ " Name :: " + $name
+ " Department :: " + $dept
+ " Salary :: " + $salary
+ " ]";
}
//compareTo() is mathod of Comparable Interface
//Use when you want natural sorting base on ID , Salary
#Override
public int compareTo(Employee emp)
{
return (this.$id - emp.$id);
}
}

Categories

Resources