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).
Related
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.
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'm new to Java and i've been bashing my head over the wall to solve this problem. Anyway below is a class that creates a Person and below that, is a class that creates a Phonebook using an ArrayList of type Person. I want to write the remove function (in order to remove a Person from the list) but my problem is that since i only get the name of the person i can't use the Indexof function (cause it requires object) to get at what position lies the name.
This is my first time using an ArrayList to store an Object so i'm not even sure
how my results would appear. I'm guessing that if the position of the name (in my list) is 10 then 11 would be the phone and 12 would be the address. Am i correct?
public class Person
{
private String name;
private String phone;
private String address;
public Person (String n, String p, String a)
{
this.name = n;
this.phone = p;
this.address = a;
}
public void setPhone(String newPhone)
{
this.phone = newPhone;
}
public String getName()
{
return this.name;
}
public String getPhone()
{
return this.phone;
}
public String getAddress()
{
return this.address;
}
public String print()
{
return "Name is : " + this.name + "\nPhone is : " + this.phone + "\nAddress is : " + this.address;
}
}
import java.util.*;
public class phoneBook
{
Scanner in = new Scanner ( System.in );
private ArrayList <Person> persons = new ArrayList <Person>();
private int i;
private boolean flag;
public void addPerson(Person p)
{
persons.add(p);
}
public void listPersons ()
{
System.out.println(persons);
}
public void lookUp (String theName)
{
flag = persons.contains(theName);
if ( flag == true )
{
System.out.println("That name exists!");
}
else
{
System.out.println("That name does not exist!");
}
}
public void remove (String theName)
{
}
Edit: I'm planning to use the Scanner in another function. Don't worry about it.
I'm not sure of if do you want to get the object of that array, but each object is indexed to that array (with full attributes), now you can remove it by using the following code,
public String removePerson(ArrayList<Person> arrayList,String name)
{
for(Person currentPerson:arrayList)
{
if(currentPerson.getName().equals(name))
{
arrayList.remove(currentPerson);
return "Removed successfully"
}
}
return "No record found for that person";
}
just pass the arrayList and the name of that person to this method
You should override the equals() and hashCode() methods in the Person class. This way you will define when two objects of this type will be considered equal. Then you can use list.contains(yourObject) to determine if that object is equal to any object in your list, this based on your equals() implementation.
Does this help you?
public void remove (String theName,ArrayList<Person> persons) {
for (int i = 0; i < persons.size();++i) {
if(persons[i].getName().equals(theName)) {
persons.remove(i);
}
}
}
Best regards, Nazar
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().
I do have a User class which implements Comparable. After I add list of users into PriorityQueue<User> they should be prioritized by scores, but for some reason they don't. Could you please help me to figure out why users are not sorted in my Queue?
Update:
I am accessing queue by polling elements. prioritisedUsers.poll() it always comes with random scores with order respect.
PriorityQueue<User> prioritisedUsers = userPriorityStrategy.computeUserPriority(users);
while(!prioritisedUsers.isEmpty()){
System.out.println(prioritisedUsers.poll().getPriorityScore());
}
OUTPUT:
0.35036433736768735
0.6619121139678329
0.09520067929838127
0.4013591573863
0.6704568389588227
0.5989900926939181
0.7320779721160738
Thanks for any help!
public class User implements Comparable<User>{
private long id;
private String fistName;
private String lastName;
private double priorityScore;
public User (long id, String firstName, String lastName){
this.id = id;
this.fistName = firstName;
this.lastName = lastName;
}
public double getPriorityScore(){
return this.priorityScore;
}
public void setPriorityScore(double priorityScore){
this.priorityScore = priorityScore;
}
public long getId(){
return this.id;
}
public String getFistName(){
return this.fistName;
}
public String getLastName(){
return this.lastName;
}
public int compareTo(User o) {
return (int) (this.getPriorityScore() - o.getPriorityScore());
}
}
public PriorityQueue<User> computeUserPriority(List<User> users) {
PriorityQueue<User> prioritisedUsers = new PriorityQueue<User>(users.size());
for (User user : users) {
user.setPriorityScore(rand.nextDouble());
prioritisedUsers.add(user);
}
return prioritisedUsers;
}
I'm not so sure that your cast to (int) works well... because casting to an int implicitly drops any decimal.
If I'm not in wrong, try something like
public int compareTo(User object) {
if (this.getPriorityScore() < object.getPriorityScore())
return -1;
if (this.getPriorityScore() == object.getPriorityScore())
return 0;
return 1;
}
or alternatively and more simply:
public int compareTo(User o) {
return Double.compare(this.getPriorityScore(), o.getPriorityScore());
}