# Sorting a Vector by Fields of Objects Stored in it

• 06-09-2013, 08:37 AM
Willriker
Sorting a Vector by Fields of Objects Stored in it
Hello all!

I am going back to relearn Java. I never really got it in college. So, I am going back through my old texts, doing the exercises to get back into it. The good news is that, this time through, things are making much more sense. Until now...

I have a vector filled with objects of type Address. Each of the address objects contains three fields: Name, Date of Birth, and Address. I want to provide three methods. Each of these methods will order the vector by a field. But, I am stuck.

My initial thought was to perform a bubble sort. Well, that is what i found people call what i wanted to do during my unsuccessful attempts to research an answer to my own question. Apparently, bubble sorts are frowned upon... everywhere I look, people talk about implementing comparable and comparator. These are new to me. Despite that, i tried to implement them to sort my vector. The operative word being 'Tried'.

I will include the code I am using below, starting with the class that I am using to construct the Vector of addresses. This is also the class that i was attempting to put my comparable/comparator. At first, I am trying to sort by the Date of Birth (dob). That segment is at the bottom of this segment of code.

Code:

package Learning;
import java.util.*;

private Vector <Address>v;//cast the vector so its elements are of type <Address>

/* Constructor requires an object of type Address
* make a vector object, all elements are of type <Address>
* initial capacity is 1, increments by 2 as needed
*/
v = new Vector <Address> (1,2);

}

//add an element to the vector, at v.size()+1, its capacity will automatically increment by 2 if needed.
}

//getter Methods
public String getName(int index) {
return a.getName();
}

public String getDOB(int index) {
return a.getDOB();
}

}

public int getSize() {
return v.size();
}

//toString Method
public String toString(int index) {
return getName(index) + " " + getDOB(index) + " lives at "+ getAddress(index);
}

//sorts by DOB
@Override
return this.dob.compareTo(other.getDOB());
}

}//end of class

in this class I define the objects that I insert into the vector (above):
package Learning;

Code:

import java.util.Date;

private Name obj;
private String name;
private Date obj2;
private String dob;

//Constructor
public Address(String first, String middle, String middleInitial, String last, String address, int yearDOB, int monthDOB, int dayDOB) {
obj = new Name(first, middle, middleInitial, last);
name=obj.toString();
obj2= new Date(yearDOB, monthDOB, dayDOB);
dob= "(" + Integer.toString(obj2.getMonth()) + " " + Integer.toString(obj2.getDate())+ ", "
+ Integer.toString(obj2.getYear()) + ")";
}

//getter methods
public String getName() {
return name;
}

public String getDOB() {
return dob;
}

}

//setter methods
//either middle or middle initial must be a null value
public void setName(String first, String middle, String middleInitial, String last) {
obj.setFirst(first);
obj.setMiddle(middle);
obj.setMiddleInitial(middleInitial);
obj.setLast(last);
name=obj.toString();
}

public void setDOB(int yearDOB, int monthDOB, int dayDOB) {
obj2.setYear(yearDOB);
obj2.setMonth(monthDOB);
obj2.setDate(dayDOB);
dob="(" + Integer.toString(obj2.getMonth()) + " " + Integer.toString(obj2.getDate()) + ", "
+ Integer.toString(obj2.getYear()) + ")";
}

}

//toString method
public String toString() {
return getName() + ", " + getDOB() + " lives at " + getAddress();
}

}//end of class

The name field in the Address object uses Class Name that I wrote before:

Code:

package Learning;
// Testing of this Class is in Chapter3Exercises.java

public class Name {
private String first;
private String middle;
private String middleInitial;
private String last;
private boolean surnameFirst = false;

//constructor for instances, objects, of type Name
public Name(String a, String b, String c, String d) {
first = a;
middle = b;
middleInitial = c;
last = d;
}

//getter methods
public String getFirst() {
return first;
}

public String getMiddle() {
return middle;
}

public String getMiddleInitial() {
return middleInitial;
}

public String getLast() {
return last;
}

public boolean getSurnameFirst() {
return surnameFirst;
}

//setter methods
public void setFirst(String e) {
first = e;
}

public void setMiddle(String f) {
middle = f;
}

public void setLast(String g) {
last = g;
}

public void setMiddleInitial(String h) {
middleInitial = h;
}

public void setSurnameFirst(boolean i) {
surnameFirst = i;
}

//toString method
public String toString() {
if (middle==null && middleInitial==null && surnameFirst==false) {
return getFirst() + " " + getLast();
}
if (middle==null && middleInitial==null && surnameFirst==true) {
return getLast() + ", " + getFirst();
}
if (middle==null && middleInitial!=null && surnameFirst==false) {
return getFirst() + " " + getMiddleInitial() + ". " + getLast();
}
if (middle==null && middleInitial!=null && surnameFirst==true) {
return getLast() + ", " + getFirst() + " " + getMiddleInitial() + ".";
}
if (middle!=null && middleInitial==null && surnameFirst==false) {
return getFirst() + " " + getMiddle() + " " + getLast();
}
if (middle!=null && middleInitial==null && surnameFirst==true) {
return getLast() + ", " + getFirst() + " " + getMiddle();
} else {
return "You must enter at least a first name and a surname.";
}
}
}

I am hoping someone can point out how to do this one. Actually, I'm really hoping someone can take the time to explain how to sort by dob. Then i can go and try to sort by the other fields using what i learned.
• 06-09-2013, 10:03 AM
JosAH
Re: Sorting a Vector by Fields of Objects Stored in it
Normally the interface Comparable<X> is only implemented by a class X (or subclasses thereof); use the Comparator<X> instead, so any class can compare objects X. You have to have three implementations, one for each sort criterium.

kind regards,

Jos
• 06-09-2013, 06:03 PM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it
Thank you for taking the time to reply, but I must be misunderstanding your advice. When I replace implements Comparable (in class AddressBook) it wants a compare() method instead of compareTo(). And since I am dealing with strings, dont I need to use the compareTo() method?
• 06-09-2013, 06:34 PM
JosAH
Re: Sorting a Vector by Fields of Objects Stored in it
Quote:

Originally Posted by Willriker
Thank you for taking the time to reply, but I must be misunderstanding your advice. When I replace implements Comparable (in class AddressBook) it wants a compare() method instead of compareTo(). And since I am dealing with strings, dont I need to use the compareTo() method?

Yep, if you want your class to implement the Comparator<X> interface, your class has to implement the compare(X a, X b) method; don't ask me why those names are different, but who cares? If you want to compare two Addresses by their name, say, all you have to do is create a small class like this:

Code:

return a.getName().compareTo(b.getName());
}
}

Similar reasoning applies with small classes that compare Adresses by other fields. Note that this little class uses the compareTo( ... ) method of the String class to do the actual comparison.

kind regards,

Jos
• 06-11-2013, 10:02 PM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it
Sorry I have not gotten back to you. I have been trying to get this to work. I got rid of the comparator stuff from class AddressBook (above) and created a new class to hold them, along with the corresponding getter methods. I am putting it below this line:

Code:

package Learning;

import java.util.Comparator;

/* setting up comparators
* these comparators will compare each argument to the next one in the series.
* the comparator will continue to loop until all comparisons return 0 or less
* if o1<o2 a value of -1 is returned
* if o1=o2 a value of 0 is returned
* if o1>o2 a value of 1 is returned
*/

public class CompareByName implements Comparator<Address> {
@Override
return o1.getName().compareToIgnoreCase(o2.getName());
}
}

public class CompareByDOB implements Comparator<Address> {

@Override
return o1.getDOB().compareTo(o2.getDOB());
}
}

@Override
}
}

//getter methods
return new CompareByName();
}

return new CompareByDOB();
}

}

}//End of Class

So, now I try to call this in my main method. But, it wont compile.

Code:

package Learning;

import java.util.Collections;
import java.util.List;

public class Chapter3Exercises {

/**
* @param args
*/
public static void main(String[] args) {                //testing instances, objects, of type AddressBook
Address obj14 = new Address("M", null, "L", "Capo", "3 Wood Avenue", 1760, 1, 30);
for (int index=0; index<obj16.getSize(); index++) {
System.out.println(obj16.toString(index));
}
Collections.sort(obj16.getName(0), comparers.getCompareByName());
for (int index=0; index<obj16.getSize(); index++) {
System.out.println(obj16.toString(index));
}

}//End of Class

I think the Collections.sort line is giving me an issue. If I enter obj16.getName(), for the first parameter, I am asked for an index. That isn't much of a surprise because the getter function i wrote required an input. I guess I should start at 0. So, I place 0 as the index. Once i do this, then the word sort gets red lined. with the error message

"The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (String, Comparator<Address>)"

I don't know.. I think i am heading in the correct direction though.

Its my understanding that while comparator will give the 1, 0, or -1 value, the Collections.sort is the line that will actually put things into the correct order.
• 06-12-2013, 11:35 PM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it
• 06-14-2013, 01:45 AM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it
this is becoming very frustrating :/

i cant get rid of this error message:
Quote:

The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (String, Comparator<Address>)
I have a red squiggle under the word sort in my main (line 22)
• 06-14-2013, 06:32 AM
DarrylBurke
Re: Sorting a Vector by Fields of Objects Stored in it
If you're human, please use meaningful variable names. Names like obj13 / 14 / 15 / 16 may be fine for a discussion between bots.

Have you read the API for Collections#sort(...)? what is the Type of the first parameter to that method? Is the parameter you provide of that Type?

db
• 06-15-2013, 01:20 AM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it
I thought that vectors implement the list interface. Thus making it a part of the collections group. And, sort requires a List. Now I dont know why there is an issue.
• 06-15-2013, 09:59 AM
JosAH
Re: Sorting a Vector by Fields of Objects Stored in it
Yep, a Vector implements the List interface but an obj16.getName(0) doesn't and that's what you're passing to the sort method.

kind regards,

Jos
• 06-15-2013, 04:18 PM
Willriker
Re: Sorting a Vector by Fields of Objects Stored in it

Ill post the code below for people who want to search before asking. Thank you, once again, for pointing me in the right direction.

Including this class, just for reference, so anyone can see what each individual address entry into the vector looks like.
Code:

package Learning;

import java.util.Date;

private Name obj;
private String name;
private Date obj2;
private String dob;

/*Constructor*/
public Address(String first, String middle, String middleInitial, String last, String address, int yearDOB, int monthDOB, int dayDOB) {
obj = new Name(first, middle, middleInitial, last);
name=obj.toString();
obj2= new Date(yearDOB, monthDOB, dayDOB);
dob= "(" + Integer.toString(obj2.getMonth()) + " " + Integer.toString(obj2.getDate())+ ", "
+ Integer.toString(obj2.getYear()) + ")";
}

//getter methods
public String getName() {
return name;
}

public String getDOB() {
return dob;
}

}

//setter methods
//either middle or middle initial must be a null value
public void setName(String first, String middle, String middleInitial, String last) {
obj.setFirst(first);
obj.setMiddle(middle);
obj.setMiddleInitial(middleInitial);
obj.setLast(last);
name=obj.toString();
}

public void setDOB(int yearDOB, int monthDOB, int dayDOB) {
obj2.setYear(yearDOB);
obj2.setMonth(monthDOB);
obj2.setDate(dayDOB);
dob="(" + Integer.toString(obj2.getMonth()) + " " + Integer.toString(obj2.getDate()) + ", "
+ Integer.toString(obj2.getYear()) + ")";
}

}

//toString method
public String toString() {
return getName() + ", " + getDOB() + " lives at " + getAddress();
}

}//end of class

This class holds ALL of my comparators, one comparator for each sort I want to perform. It also holds a getter method for each comparator.
Code:

package Learning;

import java.util.Comparator;

/* setting up comparators
* these comparators will compare each argument to the next one in the series.
* the comparator will continue to loop until all comparisons return 0 or less
* if o1<o2 a value of -1 is returned
* if o1=o2 a value of 0 is returned
* if o1>o2 a value of 1 is returned
*/

public class CompareByName implements Comparator<Address> {
@Override
return o1.getName().compareToIgnoreCase(o2.getName());
}
}

public class CompareByDOB implements Comparator<Address> {

@Override
return o1.getDOB().compareTo(o2.getDOB());
}
}

@Override
}
}

//getter methods
return new CompareByName();
}

return new CompareByDOB();
}

}

}//End of Class

This is the class that holds the vector of address's. It holds getter/add/ToString/ and now the sort procedures for each type of sort I want to have available to the main method.
Code:

package Learning;
import java.util.*;

private Vector <Address>v;//cast the vector so its elements are of type <Address>

/* Constructor requires an object of type Address
* make a vector object, all elements are of type <Address>
* initial capacity is 1, increments by 2 as needed
*/
v = new Vector <Address> (1,2);

}

//add an element to the vector, at v.size()+1, its capacity will automatically increment by 2 if needed.
}

//getter Methods
public String getName(int index) {
return a.getName();
}

public String getDOB(int index) {
return a.getDOB();
}

}

public int getSize() {
return v.size();
}

//toString Method
public String toString(int index) {
return getName(index) + " " + getDOB(index) + " lives at "+ getAddress(index);
}

//sorting procedure methods
public void sortByName() {
Collections.sort(v, comparators.getCompareByName());
}

public void sortByDOB() {
Collections.sort(v, comparators.getCompareByDOB());
}

}

}//end of class

Here is just an excerpt of the main method I use to create addresses, add them to the vector, sort the vector by field, then print out the results to the console window.
Main:
Code:

//testing instances, objects, of type AddressBook
Address obj14 = new Address("M", null, "L", "Capo", "3 Wood Avenue", 1760, 1, 30);
for (int index=0; index<obj16.getSize(); index++) {
System.out.println(obj16.toString(index));
}
obj16.sortByName();
for (int index=0; index<obj16.getSize(); index++) {
System.out.println(obj16.toString(index));
}
obj16.sortByDOB();
for (int index=0; index<obj16.getSize(); index++) {
System.out.println(obj16.toString(index));
}