I'm having a difficult time creating a compareTo() method for my program. My program reads 5 pairs of String/Integers from the commandline. They will represent names and ages for a Person object.
For instance my commandline arguments are: Asia 19 Java 20 Html 25 CSS 18 Ruby 10
My goal is to display them in a dialog box rearranged from smallest to biggest number.
*The problem I need help with is with my compareTo() method. I'm kinda of stuck at this point, as I just don't think I understand the concept of using this method. If someone can give me a informative explanation that would be awesome!
My code:
// To display dialog box(s)
import javax.swing.JOptionPane;
//An interface used to compare two objects.
import java.lang.Comparable;
public class searchSort{
public static void main(String[] args){
if (args.length != 10){
System.out.println("Please enter 5 String/Intger pairs " +
"on the commandline");
}
else{
int age1 = new Integer(0);
int age2 = new Integer(0);
int age3 = new Integer(0);
int age4 = new Integer(0);
int age5 = new Integer(0);
try{
age1 = Integer.parseInt(args[1]);
age2 = Integer.parseInt(args[3]);
age3 = Integer.parseInt(args[5]);
age4 = Integer.parseInt(args[7]);
age5 = Integer.parseInt(args[9]);
}
catch (NumberFormatException exception) {
System.out.println("Error: Commandline arguments 2,4,6,8,10 must be a positive integer.");
System.exit(0); // end program
}
Person[] arr = new Person[5];
arr[0] = new Person(args[0], age1);
arr[1] = new Person(args[2], age2);
arr[2] = new Person(args[4], age3);
arr[3] = new Person(args[6], age4);
arr[4] = new Person(args[8], age5);
JOptionPane.showMessageDialog(null, arr[0]+ "\n" +arr[1]+ "\n"+arr[2]+ "\n"+
arr[3] + "\n" + arr[4]);
//
}
}
}
class Person implements Comparable{
// Data Fields
protected String name;
protected int age;
// Constructor
public Person(String n1, int a1){
name = n1;
age = a1;
}
//toString() method
public String toString(){
String output = name + " is " + age + " years old.";
return output;
}
//getAge() method
public int getAge(){
return age;
}
// compareTo() method
public int compareTo(Object object) throws ClassCastException{
int person1 = this.getAge();
int person2 = object.getAge();
int result = this.getAge() - object.getAge();
return result;
}
}
Your code won't compile, because you're using an Object as a Person. You need to cast it:
public int compareTo(Object object) throws ClassCastException{
return age - ((Person)object).age;
}
And you only need one line, and you can access fields directly.
The contract for the compareTo(Object obj) method demands that you return:
n < 0 if this is to be considered less than obj
0 if this is equal to obj
n > 0 if this is greater than obj
This way you can define sorting behavior for your class.
Arrays.sort(people);
Note that you can sort your objects backwards by just inverting the sign of the return value.
As a side note, some sorting methods allow you to pass a Comparator along with the collection you want to sort, which enables you to define a different sort criterion other than the default one.
Arrays.sort(people, new Comparator<Person>() { ... });
What the Comparable enables is for you to sort Person objects when they're in a container object like a List or an Array.
I suggest looking at the Arrays and Collections classes for how to do this.
Related
I'm trying to make a program with three class files, two Objects files and one Main that accesses both and runs operations. The first object file creates objects with one parameter, and then assigns attributes to itself based on said parameter, for example.
public class People {
private int height, weight;
private String specificPerson;
public People(String person){
this.specificPerson = person;
this.height = person.length * 12;
this.weight = person.length * 40;
}
public int getHeight(){return height;}
public int getWeight() {return weight;}
}
These objects are then stored within the array of another object which has a capacity and an array:
public class peopleIndexer {
private int pcapacity, size;
private String[] peopleArray;
public peopleIndexer(int capacity){
this.pcapacity = capacity;
this.peopleArray = new String [capacity];
}
public int getCapacity(){
return pcapacity;
}
public int[] getInfo(String person){
int[] getInfo = new int[2];
int found = Arrays.binarySearch(peopleArray,person);
getInfo[0] = ?.getHeight();
getInfo[1] = ?.getWeight();//I dont know the object name yet so I put "?" for I am not sure
System.out.println("Person" + person + "is " + getInfo[0] + "tall and " + getInfo[1] + " pounds.");
}
}
What I need to know is how to allow the user to make multiple people in the list with input that I can then allow them to retrieve later, for example:
String user_input;
People user_input = new People("user_input");
So that if the users input were to be jack, ryan, and nick, I would have three objects placed in the peopleIndexer as such:
People jack = new People(jack);
People ryan = new People(ryan);
People nick = new People(nick);
Your People constructor takes only one argument and creates a People object..You do not have setters for some of your private variables in the peopleIndexer class, so best to have your main method as part of the peopleIndexer class.
Your "length" attribute in the People constructor is not initialized or declared anywhere, so let's assume it's not there. You must change your "private String[] peopleArray;" to be "private People[] peopleArray;" in order to have people in the array.
public static void main(String args[]){
Scanner input = new Scanner(System.in);
int capacity;
int peopleCount = 0; //used to keep track of people we have in our array
String person = "";
// get the capacity from the user
System.out.println("Enter the number of people you want to capture: ");
capacity = Integer.parseInt(input.nextLine());
//create peopleIndexer object using the given capacity
peopleIndexer pIndexer = new peopleIndexer(capacity);
while(peopleCount < capacity){
//prompt the user for the "People" name, this is the only attibute we need according to your constructor.
System.out.println("Enter person "+(peopleCount + 1)+" name: ");
person = input.nextLine();
//add a new person into the array
peopleArray[peopleCount] = new People(person);
//increase the number of people captured
peopleCount += 1;
}
}
So I had a delimited file that I read into an array.
array[0] is the boxID (double)
and
array[1] is the movieID (double)
I have no clue how I'd be able to sort my array by these two doubles. Any comments? I've tried looking at other questions on this website but I just got confused by them. I'm currently in my first programming class.
Movies[] newMasterMovies = new Movies[200];
int newMasterCount = 0;
int masterCount = 0;
int updateCount = 0;
while (updateCount < updateTotalCounter || masterCount < masterTotalCounter) {
String updateCompare = updateMovies[updateCount].getBoxID() + updateMovies[updateCount].getMovieID();
String masterCompare = masterMovies[masterCount].getBoxID() + masterMovies[masterCount].getMovieID();
int compare = updateCompare.compareTo(masterCompare);
if (compare > 0) {
newMasterMovies[newMasterCount] = masterMovies[masterCount];
masterCount++;
newMasterCount++;
}
if (updateMovies[updateCount].getActionCode() == "A") {
newMasterMovies[newMasterCount] = updateMovies[updateCount];
updateCount++;
newMasterCount++;
}
if (updateMovies[updateCount].getActionCode() == "D") {
updateCount++;
masterCount++;
}
if (updateMovies[updateCount].getActionCode() == "C") {
newMasterMovies[newMasterCount] = updateMovies[updateCount];
updateCount++;
newMasterCount++;
masterCount++;
}
}
That is what my array looks like that I am trying to sort. I tried to do a selection sort but got confused since I want to sort by two properties, not just one.
This guy here does a wonders
Arrays.sort(iArr);
Here is what it can do:
Here is an example code
public class ArrayDemo {
public static void main(String[] args) {
// initializing unsorted int array
int iArr[] = {2, 1, 9, 6, 4};
// let us print all the elements available in list
for (int number : iArr) {
System.out.println("Number = " + number);
}
// sorting array
Arrays.sort(iArr);
// let us print all the elements available in list
System.out.println("The sorted int array is:");
for (int number : iArr) {
System.out.println("Number = " + number);
}
}
}
And the results should be like this
Number = 2
Number = 1
Number = 9
Number = 6
Number = 4
The sorted int array is:
Number = 1
Number = 2
Number = 4
Number = 6
Number = 9
Hopes this helps some
To simply sort your Movies[] you can use Arrays.sort and use a custom Comparator. Like this:
Arrays.sort(masterMovies, new Comparator<Movies>() {
#Override
public int compare(Movies o1, Movies o2) {
// compare boxID
// compare movieID
return 0; // return result
}
});
Arrays.sort use merge sort or binary insertion sort which are both more stable and faster than selection sort.
If you insist to do your selection sort, try to edit yor class Movies to implement Comparable interface, like this: class Movies implements Comparable<Movies>. And implement compareTo method like this:
#Override
public int compareTo(Movies o) {
// compare boxID
// compare movieID
return 0; // return result
}
And change your old compare code int compare = updateCompare.compareTo(masterCompare); to int compare=updateMovies[updateCount].compareTo(masterMovies[masterCount]);, then go on.
I have been trying to compare objects in an Array by one if its properties so that I can sort the objects in the Array into a descending order. Here is the sample code: The array is Candidate[][]
System.out.println("How many positions for this election? > ");
numberOfPositions = sc.nextInt();
Candidate Candidate[][] = new Candidate[numberOfPositions][];
PoliticalParty Parties[][] = new PoliticalParty[numberOfPositions][];
for(int i=0;i<numberOfPositions;i++){
String name;
String politicalParty;
System.out.println("Enter position name > ");
position = sc.next();
System.out.println("How many seats? > ");
numberOfSeats = sc.nextInt();
System.out.println("How many candidates? > ");
numberOfCandidates = sc.nextInt();
Candidate[i] = new Candidate[numberOfCandidates+1];
Candidate[i].sort(votes); //<--------------------------This is what im trying//
Wherein (votes) is an int derived from a text file using this code:
System.out.println("Enter file name > ");
filename = sc.next();
try {
filescan = new Scanner(new File(filename));
} catch (FileNotFoundException ex) {
//Logger.getLogger(Election.class.getName()).log(Level.SEVERE, null, ex);
}
String L = System.lineSeparator();
filescan.useDelimiter(L);
while (filescan.hasNext()) {
numberOfVoters++;
line = filescan.next();
for(int x=0,j=0;j<line.length();j++){
switch(line.charAt(j)){
case ',':
x++;
break;
case ' ':
break;
default:
int y = line.charAt(j)-48;
//Integer.parseInt(line.charAt(j).toString());
Candidate[x][y].addVote();
break;
}
}
Wherein (vote) is encapsulated in another Class:
public class Candidate{
int votes = 0;
String politicalParty;
public Candidate(String name, String politicalParty) {
super(name);
this.politicalParty = politicalParty;
}
public void addVote() {
this.votes++;
//return votes;
}
public int getVotes() {
return votes;
}
#Override
public String getName() {
return getName();
}
public void displayFields(){
System.out.println(this.getName() + " (" + getPoliticalParty() + ") - " + votes);
}
public String getPoliticalParty() {
return politicalParty;
}
public void setPoliticalParty(String politicalParty) {
this.politicalParty = politicalParty;
}
}
Arrays have a premade sort method. The Javadoc for Arrays.sort(Object[] a) mentions a "natural ordering". The Comparable interface exists to provide the natural order.
Step 1
Apply the interface to your class.
public class Candidate implements Comparable<Candidate> {
Step 2
Implement the compareTo(Candidate c) {} method in your class.
Read the Javadoc for compareTo() contract. In general, it must return a positive, zero, or negative number if this.property is greater than, equal to, or less than c.property, respectively. property is the field upon which you are comparing.
Tip: If property is a String, you can simply reuse String's compareTo()
return this.property.compareto(c.property);
Tip: If property is an integer (like votes), you can cleverly create a positive, zero, or negative number by taking the difference.
return this.votes - c.votes;
Step 3
Sort your array.
Now that your object is comparable, call Collections.sort(list) if you have a Collection or Arrays.sort(list) you have an Array of objects.
I recommend you to use an ArrayList to store the elements to be sorted and then you'll have 2 options: make your items Comparable (interface) or create a Comparator (interface):
public class Candidate implements Comparable<Candidate> {
...
public int compareTo(Candidate c) {
... //compare here the attributes of this and c
}
}
Quick question, short answer: java.util.Arrays.sort()
Why your variable starts from capital letter? It should be like all variables from small.
You should use collections for storing custom data types, then you can easy sort it using Collections.sort(List<T> list, Comparator<? super T> c) and define your own Comparator whatever you want.
I have a franchise class with owner(owner of franchise's name), state(2-character string for the state where the franchise is located), and sales (total sales for the day)
public class Franchise implements Comparable <Franchise> {
final String owner;
final String state;
final double sales;
protected Franchise(String owner, String state, double sales ) {
this.owner = owner;
this.state = state;
this.sales = sales;
}
public String toString() {
String str = state + ", " + sales + ", " + owner;
return str;
}
public String getState() {
return state;
}
public double getSales() {
return sales;
}
public int compareTo(Franchise that) {
double thatSales = that.getSales();
if (this.getState().compareTo(that.getState()) < 0)
return -1;
else if (this.getSales() > thatSales)
return -1;
else if (this.getSales() < thatSales)
return 1;
else
return 0;
}
}
the compareTo is based on state ASCENDING and sales DESCENDING
import java.util.ArrayList;
import java.util.Collections;
public class FranchiseTester {
public static void main(String[] args) {
ArrayList<Franchise> franchises = new ArrayList<Franchise>();
Franchise a = new Franchise("Andrew Luck", "IN", 1270.5);
Franchise b = new Franchise("Ray Rice", "MD", 1210);
Franchise c = new Franchise("Alfred Morris", "WA", 980.5);
Franchise d = new Franchise("Roddy White", "GA", 670);
Franchise e = new Franchise("Greg Olsen", "SC", 740);
Franchise f = new Franchise("T.Y. Hilton", "IN", 950);
Franchise g = new Franchise("Julio Jones", "GA", 560);
franchises.add(a);
franchises.add(b);
franchises.add(c);
franchises.add(d);
franchises.add(e);
franchises.add(f);
franchises.add(g);
Collections.sort(franchises);
for(int i = 0; i < franchises.size(); i++) {
System.out.print(franchises.get(i) + "\n");
}
}
}
when I compare these franchise objects without the Collections.sort they compare correctly, However when I test using the Collections.sort like I have here I get an output like this:
GA, 670.0, Roddy White
GA, 560.0, Julio Jones
IN, 1270.5, Andrew Luck
IN, 950.0, T.Y. Hilton
MD, 1210.0, Ray Rice
SC, 740.0, Greg Olsen
WA, 980.5, Alfred Morris
The state's are still being compared correctly but it's not comparing by sales properly (lower sales for particular stat should come first)
I think that the .sort compares string by default is the reason that states are still correct, my question is how do I implement it to compare based on sales too?
In your problem statement you are saying that "compareTo is based on state ASCENDING and sales DESCENDING". Based on this your results are valid. States are in ascending order and for each state the sale is in descending order. In the very next statement you are saying (lower sales for particular stat should come first). So basically you have two conflicting requirement. Both can not be done simultaneously.
In other words do you want your program to do something else like both should be ascending or both descending or some other order. If yes then you have to modify your compareTo method accordingly.
You have to modify your compareTo method. Cause you are returning after comparing the state. So you have to compare state but sales too.
For example:
public int compareTo(Franchise that) {
int stateComparition = this.getState().compareTo(that.getState());
Double sales = Double.valueOf(this.getSales());
Double thatSales = Double.valueOf(that.getSales());
int salesComparition = sales.compareTo(thatSales);
if(stateComparition == 0){
if(salesComparition > 0)
return -1;
else if(salesComparition < 0)
return 1;
else
return 0;
}
return stateComparition;
}
It is because at first comparision condition you are comparing on the basis of state. If the state of current object is not small, then only comparision based on sales will take place. According to your code, in state you want the state of current object to be less than the comparing state, however in sales comparision you want the sales of current object to be greater than the comparing object. This is why you are getting different results. States are being compared in ascending order and sales in descending order. It is all dependent on what you return from compareTo function.
public int compareTo(Franchise that) {
double thatSales = that.getSales();
if (this.getState().compareTo(that.getState()) < 0)
return -1;
else if (this.getSales() < thatSales)
return -1;
else if (this.getSales() > thatSales)
return 1;
else
return 0;
}
Hope this code will help you. You can find good explanation over here
Comparable will give only one way of comparision. This can be done using Comparator interface too.
Collections.sort(list, new Comparator<Franchise>() {
#Override
public int compare(Franchise obj1, Franchise obj2) {
if(obj1.getState().compareTo(obj2.getState()) == 0)
{
Double a1 =obj1.getSales();
Double a2 = obj2.getSales();
return a2.compareTo(a1);
}
return obj1.getName().compareTo(obj2.getName());
}
}
I have three arrays in my proggramme Surname, Forename and result and need to create a sort array
Surname: Chris Forename: Charleton: Result: 54
Surname: Annett: forename: Lyle: result 67
If I wanted to sort it by alphabetical of last name, i need all the fields to move, instead of just the surname. This is the bubble sort code i'm working off
int swap;
boolean swapflag = true;
//outer loop
while (swapflag == true)
{
swapflag = false;
//inner loop
for (int index=0; index < (nums.length - 1); index++)
{
//swap routine
if (nums[index]> nums[index + 1])
{ //swap routine
swap = nums[index];
nums[index] = nums[index + 1];
nums[index + 1] = swap;
swapflag = true;
}
}//end inner
}//end outer
System.out.println ("\nArray Contents after sorting"
+ "\n*************");
for (int index=0; index < nums.length; index ++)
{
System.out.println("Array element "
+ index + ": " + nums[index]);
}
}
}
` package projStudent;
import java.util.Scanner;
public class UnitResults
{
//delcare Scanner as keyb
static Scanner keyb = new Scanner (System.in);
//declare fields
static String studentForename [];
static String studentSurname [];
static int [] studentResult;
static int pointer;
//constructor
UnitResults(int sizeofclass)
{//start of constructor
studentForename = new String [sizeofclass];
studentSurname = new String [sizeofclass];
studentResult = new int [sizeofclass];
pointer = 0;
}//end of constructor
public boolean add(String studentForename[], String studentSurname[],
int studentResult[])
{//start of add method
if (pointer == studentResult.length )
{//start of if statement
System.out.println("Sorry Array is full");
return false;
studentResult[pointer] = studentResult[];
pointer ++;
}//end of if statement
}//end of add method
public boolean delete(int element)
{//start of delete method
element = element - 1;
if ((element >= 0) && ( element < pointer))
{//start of if statement
for(int index = (element + 1); index < pointer; index++)
{//start of for statement
studentResult[index - 1] = studentResult[index];
}//end of for statement
pointer--;
return true;
}//end of if statement
else
{//start of else statement
return false;
}//end of else statement
}//end of delete method
public String find()
{//start of display
String strOutput="";
strOutput = strOutput + "Students";
if (pointer==0)
{//start of if statement
strOutput = strOutput + "There are no records in this Array";
return strOutput;
}//end of if statement
for (int index=0; index < pointer; index++)
{//start of for method
strOutput = strOutput + "Student Name" + studentSurname[index] + studentForename +
"Student Result" + studentResult +"\n";
}//end of for method
return strOutput;
}//display
public int sort (int UnitResults)
{//start of sort
int sort;
boolean swapflag = true;
while (swapflag == true)
{//start of while loop
swapflag = false;
for (int index=0; index < (UnitResults - 1); index++)
{
if (studentResult[index]> studentResult[index + 1])
{ //swap routine
sort = studentResult[index];
studentResult[index] = studentResult[index + 1];
studentResult[index + 1] = sort;
swapflag = true;
}
}
}//end of while loop
}//end of sort
}`
Unfortunately, your post is confusing as you don't include some things, like just what is the current array you are sorting. Still, if I understand your question correctly...
Regardless of the language, your strategy would involve changes to how you swap the elements. If your array consists of composite data, then simply assigning in a swap is fine. If your data is scattered, then your swap needs to swap each variable. You can always just sort the indices of the array into another array, then use that array to indirectly reference the first, for sorted access.
I would suggest you use an List for this purpose.
First create an object. For example "Person" containing members for "Forname","Surename","Result". Then fill the list with these objects, implement the Interface Compareable and use the Collection.sort() methode.
class Person implements Comparable<Person>
{
private String forname;
private String surname;
private int rating;
public Person(String forename, String surname, int rating)
{
this.forname = forename;
this.surname = surname;
this.rating = rating
}
public int compareTo(Person p) {
if(p.rating == this.rating)
return 0;
else if(p.rating < this.rating)
return -1;
return 1;
}
}
class Test{
public static void main(String[] args){
List<Person> personList = new ArrayList<Person>();
Person p1 = new Person("John","Smith",10);
Person p2 = new Person("Max","Muster",20);
Person p3 = new Person("Sarah","Clark",15);
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.sort();
}
}
There are a number of features of the Java programming languages that can help you resolve the problem that you are having, the first of which is inclusion of appropriate data structures and methods with which to manipulate objects within those data structures.
First and foremost, I'd recommend using a java class to represent a single person entity... think about it, when you look up a person's information, you don't consult three separate books, or computer screens, or what have you, when all that information can be organized into one place. For your person above, for example, you could use something like this:
public class Person implements Comparable<Person> {
public String firstName;
public String lastName;
public int result;
public Person(String fn, String ln, int r) {
firstName = fn;
lastName = ln;
result = r;
}
public int compareTo(Person otherPerson) {
return lastName.compareTo(otherPerson.lastName);
}
}
This will give you an object that will store all of your person information, and by default will be easily sortable by last name (you can change this behavior with a comparator, which I won't cover here.)
Now instead of having three different arrays of first names, last names, and results, you can have a single array of Persons. There ARE actually sorting mechanisms within the java language for arrays already, which you can research and use if you choose, but if you'd like to use your own sort, you would just need to replace your swap conditional with something like this:
if(persons[index].compareTo(persons[index+1]) > 0) {
...
}
i just want ask you
why instead creating class student ie
class Student{
private String studentForename;
private String studentSurname;
private int studentResult;
//setters and getters
}
and put them in some collection ie List
you are putting them into 3 different arrays?
do you realize, if you have them nicely in the list, you can sort them just by using Collections.sort() ?
Can't understand properly the question: are you looking for a way to manually implement a sorting algorithm (bubble, quick or whatever) or you would like to simply sort them the best you can? Generally speaking you should never implement your own sort 'cause Java provides itself a very efficient lot... or is this an exercise? Probably :)
Best way I can imagine is, provided the 3 arrays in their original form are linked by index, create a surname/index map, load it form surname array, sort the Map.Entry by key and then you will have the array indexes sorted the way you wanted. Check here for more details: how to sort Map values by key in Java
PS The solutions provided by the others are correct and preferrable if you are NOT doing an exercise :) Better deal with a structured object than with 3 separated data.