What is the correct way to use the compareTo inside for loop? I'd like to sort the Course objects in ascending order inside the array. I'm worried about the correct syntax for compareTo inside a loop in my insert() method.
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0) - is giving me error.
public class Courses implements Comparable{
private String title;
private int courseNumber;
private Courses[] array;
private int size;
public Courses(String title, int courseNumber){
this.title = title;
this.courseNumber = courseNumber;
this.array = new Courses[10];
this.size = 0;
}
public void insert(String title, int courseNumber){
Courses object = new Courses(title, courseNumber);
if(size == 0){
array[0] = object;
}
else{
int i;
for(i = 0; i < size; i++){
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
//do STUFF
}
}
}
#Override
public int compareTo(Object o) {
if(o instanceof Courses){
Courses obj1 = (Courses)o;
return this.courseNumber - obj1.courseNumber;
}
return -1;
}
}
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
Is giving you an error because courseNumber is a primitive (not an object), so there is no compareTo method defined on it.
If you would like to use that syntax to compare integers, you can use the static Integer.compare method.
if(Integer.compare(array[i].courseNumber, object.courseNumber) <= 0)
If you want to use your defined compareTo method then do
if(array[i].compareTo(object) <= 0))
Hint : You are not passing the object as parameter.
How does this compare two objects ?
for(i = 0; i < size; i++){
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
//do STUFF
}
You should look at Arrays.sort(Object[]) which will take care about ordering it using the Comparable interface.
Related
I'm trying to apply insertion sort to an array of objects but my else if never compiles and says "bad operand types".
Just wondering if I need to make a very specific compareTo method or if there's a better way of comparing arrays of objects in an insertion sort method.
EDIT:
So here's me trying to use my compareTo method and it compiles but I get a null pointer exception on the else if. Why?
public static void insertElement(WordClass[] Words, int next)
{
WordClass value = Words[next];
int i = next;
while(true)
{
//
if(i == 0)
{
Words[0] = value;
break;
}
else if(Words[i-1].getStr().compareTo(value.getStr()) <= 0)
{
Words[i] = value;
break;
}
else
{
Words[i] = Words[i-1];
i--;
}
}
}
public static void insertionSort(WordClass[] Words)
{
for(int i = 1; i< Words.length; i++)
{
insertElement(Words, i);
}
}
//in WordClass
public int compareTo(WordClass w) //makes WordClass comparable
{
return getStr().compareTo(w.getStr());
}
You should always use campareTo instead of == or <= operators for object types, unless you want to campare two object variables to see if both refers to same object.
Also your WordClass class must implement the Camparable interface in order for this to work.
Here i have create a delete method that will search through the Object array and remove the selected object.
public class DogList {
private int numItems;
private DogItem[] dogListArray;
private int position;
private String name;
DogList () {
numItems=0;
position = 0;
dogListArray = new DogItem[20];
}
DogList(String name) {
this.name = name;
}
public void deleteItem(DogList gi) {
int i = 0;
while( (i < numItems) && (gi != dogListArray[i]) ) {
i++;
}
if(i == numItems) {
// Throw exception if there is not matching Item
throw new NoSuchElementException("That item does not exists");
}
int pos = i;
while(pos < numItems -1 ) {
dogListArray[pos] = dogListArray[pos + 1];
pos++;
}
numItems --;
}
I cant wrap my head around why in the first while loop the (gi != dogListArray[i]) is throwing an error:"Incompatible operand types DogList and DogItem"
Any help would be wonderful.
The code is pretty long so if you want to see any part i will edit and show what is needed.
I am assuming that dogListArray is a DogItem[], making dogListArray[i] a DogItem. I assume that gi is meant to be a DogItem as well rather than a DogList?
On a separate but still relevant note, you should use the equals method, rather than == or !=, to compare objects. See here an explanation of this aspect.
public static ArrayList<ArrayList<HSSFCell>> newTogether(ArrayList<ArrayList<HSSFCell>> sheetData) {
ArrayList<ArrayList<HSSFCell>> temporary = new ArrayList<ArrayList<HSSFCell>>();
for(int i = 0; i < sheetData.size(); i++) {
ArrayList<HSSFCell> list = sheetData.get(i);
if (list.get(3).getCellType() == Cell.CELL_TYPE_NUMERIC) {
if(Integer.parseInt(list.get(3).getStringCellValue()) > 100) {
temporary.add(list);
sheetData.remove(i);
i--;
}
}
}
for(int i = 0; i < sheetData.size(); i++) {
ArrayList<HSSFCell> list = sheetData.get(i);
temporary.add(list);
}
return temporary;
}
What I am trying to do with my code is have the 2D ArrayList take out any numbers greater than 100 and put them in the beginning of the ArrayList, while preserving the order of the remaining elements. However, this code just returns an ArrayList in the original order, and if I add a println to either if, I get nothing. Could someone point out what it is I'm doing wrong?
Have you tried putting a println in front of the first if to check what getStringCellValue() returns?
btw. since Collections.sort is guaranteed to be stable according to the API documentation, you could use that. Should be faster than your way of doing it.
That could look like this
private static boolean biggerThan100(ArrayList<HSSFCell> list) {
return list.get(3).getCellType() == Cell.CELL_TYPE_NUMERIC &&
(Integer.parseInt(list.get(3).getStringCellValue()) > 100);
}
public static ArrayList<ArrayList<HSSFCell>> newTogether(ArrayList<ArrayList<HSSFCell>> sheetData) {
ArrayList<ArrayList<HSSFCell>> temp = new ArrayList<>(sheetData);
Collections.sort(temp, new Comparator<ArrayList<HSSFCell>>() {
public int compare(ArrayList<HSSFCell> a, ArrayList<HSSFCell> b) {
if(biggerThan100(a) && !biggerThan100(b)) return -1;
else if(biggerThan100(b) && !biggerThan100(a)) return 1;
else return 0;
}
});
return temp;
}
I created an object Student using Comparable with getters/setters as well as a method that overrides compareTo. In a separate file an arraylist of objects is populated from a text file. Now I need to compare the values in the arraylist to another Student object.
The file was used to create an arraylist as below:
try {
private static ArrayList<Student> array = new ArrayList<Student>();
File file = new File("students.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String inline = scanner.nextLine();
String[] split = inline.split(":");
Student myStudent = new Student();
myStudent.setUsername(split[0]);
myStudent.setPassword(split[1]);
array.add(myStudent);
}
scanner.close();
}
catch (FileNotFoundException e)
{
System.out.println("ERROR.");
}
The text file looks like this:
John:password1
Jane:password2
Jack:password3
(One on each line, no blank lines in between.)
And in a separate method a created Student object is compared to the elements in the arraylist:
Student aStudent = new Student();
aStudent.setUsername("student");
aStudent.setPassword("password");
boolean found = false;
for (int i = 0; i < array.size(); i++)
{
if (array.get(i).compareTo(aStudent) == 0)
{
System.out.println(aStudent.equals(array.get(i)));
found = true;
break;
}
else
{
System.out.println("No such records found!");
found = false;
break;
}
System.out.println(found);
}
The problem is that the object aStudent is not being compared with the objects in the arraylist. It does not print out anything (a -1, 0, or 1) for the call to compareTo, but it always shows that found is true, even though it should be false when there are no matches for aStudent in the file (which there aren't any matches to the username "student" or the password "password").
All together my code complies and works - it just works incorrectly.
Sorry if this sounds confusing. In short, my question is how can I compare the objects of an arraylist to another object using the Comparable interface and compareTo? A plus is if you can tell me what I'm doing wrong.
Thank you in advance.
EDIT
Here is the overriding of the compareTo method:
public int compareTo(Student obj){
int result = 1;
if ((this.Username.compareToIgnoreCase(object.Username) < 0) || (this.Password.compareTo(object.Password) < 0))
{
result = -1;
}
else if ((this.Username.compareToIgnoreCase(object.Username) == 0) && (this.Password.compareTo(object.Password) == 0))
{
result = 0;
}
return result;
}
More context would be useful, but your for-loop looks wrong...
for (int i = 0; i < array.size(); i++)
{
if (array.get(i).compareTo(aStudent) == 0)
{
System.out.println(aStudent.equals(array.get(i)));
found = true;
break; // out of loop
}
else
{
System.out.println("No such records found!");
found = false;
break; // break out loop
}
System.out.println(found);
}
The break statement is used to break out of the loop, meaning that you will only ever compare the first element in the list.
The entire else branch isn't required (or at least I don't think it is ;)), for example...
for (int i = 0; i < array.size(); i++)
{
if (array.get(i).compareTo(aStudent) == 0)
{
System.out.println(aStudent.equals(array.get(i)));
found = true;
break; // out of loop
}
}
System.out.println(found);
Updated
Based on you new compareTo code snippet, this...
if ((this.Username.compareToIgnoreCase(object.Username) < 0) || (this.Password.compareTo(object.Password) < 0))
{
result = -1;
}
else if ((this.Username.compareToIgnoreCase(object.Username) < 0) && (this.Password.compareTo(object.Password) < 0))
{
result = 0;
}
seems wrong to me...the else if should be more like
else if ((this.Username.compareToIgnoreCase(object.Username) == 0) && (this.Password.compareTo(object.Password) == 0))
if the contract for the Comparable interface is to be met, where 0 is equal...
For example...
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
private static ArrayList<Student> array = new ArrayList<Student>();
public static void main(String[] args) {
array.add(new Student("John", "password1"));
array.add(new Student("Jane", "password2"));
array.add(new Student("Jack", "password3"));
Student aStudent = new Student("Jack", "password3");
boolean found = false;
for (int i = 0; i < array.size(); i++) {
if (array.get(i).compareTo(aStudent) == 0) {
System.out.println(aStudent.equals(array.get(i)));
found = true;
break;
}
}
System.out.println(found);
}
public static class Student implements Comparable<Student> {
private String name;
private String password;
public Student(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public int compareTo(Student object) {
int result = 1;
if ((this.getName().compareToIgnoreCase(object.getName()) < 0) || (this.getPassword().compareTo(object.getPassword()) < 0)) {
result = -1;
} else if ((this.getName().compareToIgnoreCase(object.getName()) == 0) && (this.getPassword().compareTo(object.getPassword()) == 0)) {
result = 0;
}
return result;
}
}
}
Which will print out...
false
true
Where the objects are not equal but where they are comparable...which is kind of weird...to me ;)
Your problem may lie in the compareTo function that you overrode, you need to include that code otherwise no one can determine why certain values are being returned
EDIT:
Note that when objects are created, they are not necessarily equal solely because their contained values are equal. They are separate instances of the object and treated as such.
You will need to override the equals function as well, not just the compareTo function, in order to get the result that you seek.
I have an arrayList of Students in my main class called S... of objects type student. In "s", i need to sort my Students in my arrayList "S" by the registrationNumber they have, smaller to higher.
I tried many ways, but cannot get it to work...
public static void sort(){
int small;
for (int i=0; i < s.size() -1;i++){
small = i;
for (int ind = i + 1; ind< s.size(); ind++ ){
if( stud.get(ind).getRegNum() < s.get(small).getRegNum() ){
small = ind;
swap(i, small);
}
}
}
}
public static void swap(int one,int two){
}
You should check out java collections.
see http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
I assume that your student class has a public variable registrationNumber
public class StudentComparator implements Comparator<Student>{
#Override
public int compare(Student o1, Student o2) {
return (o1.registrationNumber>o2.registrationNumber);
}
}
somewhere call:
Collections.sort(students, new StudentComparator ());
Call Collections.sort(yourStudentList);
Your student class have to implement the interface Comparable
Override the comparteTo() method of the interface.
That's it!
Example for a comparator(assume registrationNumber is an integer):
#Override
public int compareTo(Student o) {
if(null== o)
return 1;
if(registrationNumber == 0 && o.registrationNumber==0)
return 0;
if(registrationNumber == 0 && o.registrationNumber!=0)
return -1;
if(registrationNumber != 0 && o.registrationNumber==0)
return 1;
return o.registrationNumber.compareTo(registrationNumber);
}
return 1 //when o is less than this
return -1 //when o is bigger than this
return 0 //when they are equal
EDIT If you need to use selectionsort, than you need this comparator too and the interface compareable. But then you only have so creat a custom sort() function which implements the selectionsort algorithm.