I am intrigued by the fact I noticed today
that for comparision in java
Integer provides compare method
Integer.compare(student1.age, student2.age);
String provides compareTo Method
Student1.firstName.compareTo(student2.firstName);
Just want to understand why so :/
Please refer example class here:
String firstName;
String lastName;
int age;
long studentId;
Student(){}
Student(String firstName, String lastName, int age, long studentId){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.studentId = studentId;
}
}
Camparator Implementations -
public class StudentFirstNameComparator implements Comparator<Student> {
#Override
public int compare(Student student1, Student student2) {
return student1.firstName.compareTo(student2.firstName);
}
}
public class StudentAgeComparator implements Comparator<Student> {
#Override
public int compare(Student student1, Student student2) {
return Integer.compare(student1.age, student2.age);
// either of the lines can be used.
// if(student1.age == student2.age)
// return 0;
// else if (student1.age>student2.age) {
// return 1;
// }else {
// return -1;
// }
}
}
The Integer class also provides a compareTo method, because it's Comparable like String is.
Take a look at Integer class's compare method, and notice that it has 2 int arguments and it's static. This way, one can compare two primitive ints safely without boxing them into Integers, which is what would occur with compareTo.
Related
i have a class called Student has two variables:
String lastName;
String firstName;
public Student(String lastName,String firstName){
this.lastName = lastName;
this.firstName = firstName;
}
public Student(String lastName){
this.lastName = lastName;
}
#Override
public int hashCode() {
return super.hashCode();
}
#Override
public boolean equals(Object obj) {
String getLastName = ((Student) obj).getLastName();
return lastName.equalsIgnoreCase(getLastName);
}
in the Main class i have created an ArrayList
private static ArrayList<Student> listOfStudents = new ArrayList<>();
and i have created this method to get the students from ArrayList
public void findStudent(String lastName){
for (int i=0;i<listOfStudents.size();i++){
if (listOfStudents.get(i).equals(new Student(lastName))){
System.out.println(listOfStudents.get(i));
}
}
}
I have overridden equals() to check by last name.
Now everything is well, but when i add duplicate last name like below:
listOfStudents.add(new Student("Tamoussat","Abdelillah"));
listOfStudents.add(new Student("Tamoussat","Fatima"));
listOfStudents.add(new Student("Soussi","Ahlam"));
I get only the first element, i want the way of how to get more than one element if they have the same last name?
Best Regards
public class Student {
private String lastName;
private String firstName;
public Student(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
#Override
public String toString() {
return firstName + " " + lastName;
}
}
You can filter your list with the java stream api:
public static void findStudent(List<Student> listOfStudents, String lastName){
listOfStudents.stream().filter(s -> s.getLastName().equals(lastName)).forEach(student -> {
// for each student with the lastName
System.out.println(student);
});
}
The mistake will be in your equals() method, as running the code above works as expected with my own implementation of equals() which just compares lastName of this with the object argument.
But still, try to improve this method
public void
findStudent(String lastName)
{
for (Student student : listOfStudents)
{
if (student.lastName().equals(lastName))
{
System.out.println(student);
}
}
}
or any other version like #CodingSamples 's
Your equals() and hashCode() should work, despite they are not canonical. I would write it in a more better way:
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
return Objects.equals(lastName, student.lastName);
}
#Override
public int hashCode() {
return Objects.hash(lastName);
}
But this does not explain why your code returns only one item from the array. You can try my implementation or post more precisely code you execute with data you use and the result of execution.
Thanks for helping, finally i found the problem was in my code, i have a method to add students to array, in that method i used
if(!listOfStudents.contains(new Student(lastName,firstName)){}
So the problem was in other method, when it found duplicate element it doesn't add it to the ArrayList, when i deleted this if statement from that method, code worked good, Best Regard
I have an ArrayList composed of Student objects. These objects contain first name, last name, lab grade, project grade, exam grade, and total grade. I am trying to write a function that sorts the Student objects in the ArrayList based on their total grade.
Here's my Student class:
public class Student {
// fields
private String firstname;
private String lastname;
private int labgrade;
private int projectgrade;
private int examgrade;
private int totalgrade;
// constructor
public Student(String firstname, String lastname, int labgrade,
int projectgrade, int examgrade) {
this.firstname = firstname;
this.lastname = lastname;
this.labgrade = labgrade;
this.examgrade = examgrade;
this.totalgrade = labgrade + projectgrade + examgrade;
}
// method
public String toString() {
String s = firstname + " " + lastname + " has a total grade of "
+ totalgrade;
return s;
}
public int compareTo(Student s) {
return (totalgrade = s.totalgrade);
}
And here's what I tried to do to sort:
private ArrayList<Student> arraylist = new ArrayList<Student>();
public void SortStudent() {
Collections.sort(arraylist);
}
But that doesn't work because it says it can only work on List not ArrayList. Any help to fix my SortStudent method?
ArrayList is a List, the problem is that Student does not implement Comparable, and you didn't define the compareTo method, which you need to do to use the sort method from Collections.
You could do something similar to this:
public class Student implements Comparable<Student> {
//... the rest of the class
public int compareTo(Student s) {
return Integer.compare(this.grade, s.grade);
}
}
Another option would be to use lambda expressions with the method Collections.sort(List<T>, Comparator<? super T> c), where you don't need to implement Comparable:
public void sortStudent() {
Collections.sort(arraylist, (s1, s2) -> Integer.compare(s1.grade, s2.grade));
}
Collections.sort only works for types that implement Comparable:
public static <T extends Comparable<? super T>> void sort(List<T> list) {...}
Implementing Comparable<...> with Student is a bad choice in this case, since the sorting criteria are likely to change. e.g. sometimes you want to sort by first name, and sometimes by last name.
List<...> has a sort method that takes a Comparator, you could use that:
private ArrayList<Student> arraylist = new ArrayList<Student>();
...
public void SortStudent() {
arraylist.sort((x, y) -> Integer.compare(x.totalgrade, y.totalgrade));
}
class Student implements Comparable{
int rollno;
String name;
int grade;
Student(int rollno,String name,int grade){
this.rollno=rollno;
this.name=name;
this.grade=grade;
}
public int compareTo(Object obj){
Student st=(Student)obj;
if(grade==st.grade)
return 0;
else if(grade>st.grade)
return 1;
else
return -1;
}
I have been reading on how to program Java 8 Polymorphism.
I have this code:
public class Person
{
// instance variables - replace the example below with your own
private String lastname;
private String firstname;
private int age;
private boolean married;
private float salary;
/**
* Constructor for objects of class Person
*/
public Person(String lastname, String firstname, int age, boolean married, float salary)
{
// initialise instance variables
this.lastname = new String(lastname);
this.firstname = new String(firstname);
this.age = age;
this.married = married;
this.salary = salary;
}
public String getLastName() {return lastname;}
public String getFirstName() {return firstname;}
public int getAge() {return age;}
public boolean isMarried() {return married;}
public float getSalary() {return salary;}
}
public class MarriedPerson extends Person
{
// instance variables - replace the example below with your own
private int children;
/**
* Constructor for objects of class MarriedPerson
*/
public MarriedPerson(String lastname, String firstname, int age, float salary, int children)
{
// initialise instance variables
super(lastname, firstname, age, true, salary);
this.children = children;
}
public int getNoOfChildren()
{
// put your code here
return children;
}
}
abstract class MyTester
{
public static void main(String[] args) {
Person p1 = new Person("Kings", "Paul", 22, true, 1200f);
MarriedPerson mp1 = new MarriedPerson("Tront", "Betty", 31, 980.5f, 3);
System.out.print(p1.getFirstName()+" "+p1.getLastName()+" is "
+p1.getAge()+" years old, gets a "+p1.getSalary()
+" Euros salary and is");
if (p1.isMarried() == false)
System.out.print(" not");
System.out.println(" married.");
System.out.print(mp1.getFirstName()+" "+mp1.getLastName()
+" is " +mp1.getAge()+ " years old, gets a " + mp1.getSalary()
+" Euros salary and is" + " married with ");
if (mp1.getNoOfChildren() > 0)
System.out.print(mp1.getNoOfChildren());
else System.out.print("no");
System.out.println(" children.");
}
}
Reading from a book, I have not seen an abstract class that contains the main function so I am a bit confused.
Why have we declared MyTester class as abstract? Is this necessary?
I have now created a printInfo method in class Person. See following code:
public class Person
{
// instance variables - replace the example below with your own
private String lastname;
private String firstname;
private int age;
private boolean married;
private float salary;
/**
* Constructor for objects of class Person
*/
public Person(String lastname, String firstname, int age, boolean married, float salary)
{
// initialise instance variables
this.lastname = new String(lastname);
this.firstname = new String(firstname);
this.age = age;
this.married = married;
this.salary = salary;
}
public String getLastName() {return lastname;}
public String getFirstName() {return firstname;}
public int getAge() {return age;}
public boolean isMarried() {return married;}
public float getSalary() {return salary;}
public void printInfo(){
System.out.print(p1.getFirstName()+" "+p1.getLastName()+" is "
+p1.getAge()+" years old, gets a "+p1.getSalary()
+" Euros salary and is");
if (p1.isMarried() == false)
System.out.print(" not");
System.out.println(" married.");
}
}
abstract class MyTester
{
public static void main(String[] args) {
Person p1 = new Person("Kings", "Paul", 22, true, 1200f);
MarriedPerson mp1 = new MarriedPerson("Tront", "Betty", 31, 980.5f, 3);
p1.printInfo();
mp1.printInfo();
}
}
When I compile the modified code it give me the error: cannot find symbol - variable p1. Why is that? What do I need to do in order to fix that?
What advantages second code has over first one?
It does not make sense MyTester to be abstract since it does not have any abstract method. The only reason might be to prevent the instantiation of MyTester class because it might not make sense for an instance to exist.
MyTester is declared abstract so you can't create any instances of it (there is no reason you would want to). See this link, it says:
An abstract class is a class that is declared abstract—it may or may
not include abstract methods. Abstract classes cannot be instantiated,
but they can be subclassed.
When I compile the modified code it give me the error: cannot find symbol - variable p1. Why is that? What do I need to do in order to fix that?
For future reference: You should create a new question and not edit your existing one. Also, if someone solved your first problem you should allways be so nice as to accept their answer. ;)
Anyway: You are getting that error because your object is only "known" as p1 in your main class.
In your "printInfo()" method you are trying to have the objects do calls on itself. So either just remove the "p1." part and just call the methods like "getFirstName()", or explicitly call "this.getFirstName()".
("this" is a java keyword refering to the current object instance.)
A tipp for you: Get a good JAVA IDE like Eclipse (https://eclipse.org/) and you will see simple errors like those even before compiling.
No. It makes no difference, as the class is never extended or used except as an entrypoint.
Here is my code in make sure to add student information with name ,age and their address. In order to make sure the student is unique. I use the hashCode() and equals() to make sure data integrity. The same name of student will be considered as override.
Problem is: The same information is never be cleaned out, Anybody know why? It seems the hashCode() and equals() never work.
class Student implements Comparable<Student>{
private String name;
private int age;
Student(String name, int age){
this.name = name;
this.age = age;
}
public int hashcode(){
return name.hashCode() + age *34;
}
//override equals method
public boolean equals(Object obj){
if(!(obj instanceof Student))
throw new ClassCastException("The data type is not match!");
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
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;
}
#Override
public int compareTo(Student s) {
int num = new Integer(this.age).compareTo(new Integer(s.age));
if (num == 0)
return this.name.compareTo(s.name);
return num;
}
}
public class HashMapDemo1 {
public static void main (String[] agrs){
HashMap<Student,String> hs = new HashMap<Student,String>();
hs.put(new Student("James",27),"Texas");
hs.put(new Student("James",27), "California");
hs.put(new Student("James",27), "New mexico");
hs.put(new Student("Jack",22),"New York");
hs.put(new Student("John",25),"Chicago");
hs.put(new Student("Francis",26),"Florida");
Set<Student> Keyset = hs.keySet();
Iterator<Student> it = Keyset.iterator();
while(it.hasNext()){
Student stu = it.next();
String addr = hs.get(stu);
System.out.print(stu.getName()+stu.getAge()+"..." +addr+"\n");
}
}
hashcode != hashCode
Be sure to use the #Override annotation whenever you think that you are overriding a super-class's method, as this will allow the compiler to notify you if/when you are wrong. As you're finding out, it's much easier to fix errors at the compilation stage rather than the run-time stage.
Myself, I'd not use the age field as part of equals or hashCode since age can change for a student with time. I'd use Date birthDate or some other invariant instead.
And also I agree with Radiodef: the equals(...) method should not throw an exception. If the parameter object is not Student type, simply return false.
The method you have implemented is public int hashcode().
It should be public int hashCode().
In my program I'm trying to compare names by last name, and if those are the same then compare by using the first name. However, I can't quite figure out how to compare the strings.
Can someone help me out with this?
public class Student implements IComparable
{
String firstName;
String lastName;
int score;
public Student()
{
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getFirstName()
{
return firstName;
}
public void getLastName(String lastName)
{
this.lastName = lastName;
}
public String getLastName()
{
return lastName;
}
public void getScore(int score)
{
this.score = score;
}
public int getScore()
{
return score;
}
#Override
public int compareTo(Object o)
{
//Compares Student objects by last name. If the last names are the same
//it compares by first name.
Student s = (Student) o;
if (this.getLastName().toUpperCase() < s.getLastName().toUpperCase())
return -1;
else if (this.getLastName().toUpperCase() > s.getLastName().toUpperCase())
return 1;
else
{
if(this.getFirstName().toUpperCase( < s.getFirstName().toUpperCase()
return -1;
else if (this.getFirstName().toUpperCase( > s.getFirstName().toUpperCase()
return 1;
else
return 0;
}
}
}
Don't make things more complicated:
String class already provides compareToIgnoreCase method
value returned by compare methods of String is already good to be directly returned
Basically the same functionality could be expressed with:
int compare = getLastName().compareToIgnoreCase(o.getLastName());
return compare == 0 ? getFirstName().compareToIgnoreCase(o.getFirstName()) : compare;
Mind that you need to check that o instanceof Student if you have an Object argument.
I don't get why you are using a custom IComparable interface, which sounds much like the one provided in C#, since Java provides Comparable<T> which is generic and doesn't require checking for the runtime type of the argument (since it's not Object anymore but T).