Java: if conditions setting - java

I am trying to run a getBook() method in a Bookstore program which can allow me to find a book stored in the AL books not only if title and author are correct but also if one of them is null.
So, I wrote this code:
public Book getBook(String author, String title){
boolean condOk = false;
Book book = null;
if(books!=null){
for(int i=0; i<books.size(); i++){
if((author==null && title.equals(books.get(i).getTitle())) ||
(author.equals(books.get(i).getAuthor()) && title==null)){
condOk = true;
book = books.get(i);
break;
} else if(title.equals(books.get(i).getTitle()) &&
author.equals(books.get(i).getAuthor())){
condOk = true;
book = books.get(i);
break;
}
}
}
if(condOk==false) return null;
else return book;
}
The J-Unit test (not created by me) of this part, puts in books 4 objects (with constructor: String title, String author, ...) and then it tests the method getBook() three times: with author and title, with title expressed and author null, and a last time with the opposite situation.
I have already tried something and I noticed that if I substitute all the equals() calls with the logical op == everything works fine.
In the Book class everything is correct, all the getters and setters are in the right place.
So, why do I get such a behavior, when several times I read that comparing Strings with equals() is better than doing it with ==?

You run into a NullPointerException, for example if title is null and author is not equal to a book in the list. The condition of the first if is false, so you enter the else part and the condition of the second if cannot be evaluated because in title.equals(books.get(i).getTitle()) the title is null.
This does not happen if you use ==, it is allowed to compare null values with ==.

Related

Having trouble with for each loop

So I am trying to make this swing GUI that searches a list of books and then displays the book in a JTextArea. Here is my actionPerformed Method
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Search Books")){
String bookName = JOptionPane.showInputDialog(this, "Enter books to search"); // prompts user to enter book title
if (bookName == null){
sArea.append("Enter a Book");
}else{
for (Book b: ban.getListOfBooks()){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){ // appends string if it is equal to one of the book names
sArea.append(bookName);
}else{
sArea.append("Book not found");
}
}
}
}else{
...
So my problem is for the for each loop. Naturally it will print "Book not found" for every element in the list that is not equal. So if i have ten books, and i enter the name of the first one, it will print that and then "Book not found" nine times. How could i reformat this to only print out one thing?
You can use a boolean found flag and then check if the book was found at the end of the loop
}else{
boolean found = false;
for (Book b: ban.getListOfBooks()){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){ // appends string if it is equal to one of the book names
sArea.append(bookName);
found = true;
}else{
}
}
if (!found) sArea.append("Book not found");
}
If you want to still continue using foreach loop you can extract that part to a function, return the book name when it matches but if any book does not matche return "Not found" instead of appending every iterarion
Like this:
public String searchBook(List<Book> books, bookName ){
for (Book b: books)){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){
return b.getTitle();
}
}
return "Book not found"; }
So you just calling this function instead of your foreach loop like this:
sArea.append(this.searchBook(ban.getListOfBooks() , bookName))
It´s cleaner.
Finally I'm not sure if is correct to use append method If you just want to put the result everytime the user search.
Also if you have a List you can use indexOf or contains methods to know if a element exists in the list, it´s cleaner.
This can help you more : https://www.baeldung.com/find-list-element-java

Java - Issue with Collections.sort()

I am currently writing a program that prints an ArrayList of books. Each ArrayList of books elements consist of a string (the title of a book) and an ArrayList (the authors of that book). I need to sort my ArrayList of books so that they appear in alphabetical order (sorted by titles). My issue is that when I print the new ArrayList (the list that I call Collections.sort() on) I get the same output as the first time I printed the non-sorted version.
I am calling myLib.sort(); from my driver program which goes to this method in my Library class:
public void sort()
{
Collections.sort(myBooks);
}
myBooks is the ArrayList of books I mentioned earlier. From what I've read, Collections.sort("ArrayList name") should sort my list alphabetically. If that is incorrect and I need to use compareTo() and equals() methods, then here are those methods as they appear in the class Book that I use to construct the books that go into my class Library:
public int compareTo(final Book theOther)
{
int result = 0;
if (myTitle.equals(theOther.myTitle))
{
if (myAuthors.get(0) != theOther.myAuthors.get(0))
{
result = 1;
}
}
else
{
result = 0;
}
return result;
}
public boolean equals(final Object theOther)
{
if (theOther instanceof String)
{
String other = (String) theOther;
return myTitle == other;
}
else
{
return false;
}
}
The only remaining possible issue that I can think of is with my printing method. My driver program prints myLib which is a Library. My Library class has the following toString() method:
public String toString()
{
String result = "";
for (int i = 0; i < myBooks.size(); i++)
{
String tempTitle = myBooks.get(i).getTitle();
ArrayList<String> tempAuthors = myBooks.get(i).getAuthors();
Book tempBook = new Book(tempTitle, tempAuthors);
result += (tempBook + "\n");
}
return result;
}
This gets each book and that book's string from my Book class toString() method which is the following:
public String toString()
{
return "\"" + myTitle + ",\" by " + myAuthors;
}
If this was too little, too much, too confusing, not clear enough, etc... Please let me know in a comment and I will edit the post ASAP. I can also post the entirety of my three classes if need be. I am new to Java and fairly new at posting so I'm still getting used to how things are done in both cases so I'd appreciate it if you'd go easy on me. Thank you!
Your compareTo() method seems to be wrong, note that Collections.sort() uses that method to compare the objects in your list.
You only check if the titles are equals, if they are then you compare the first authors and if they are equal you return 1, else you return 0;
compareTo() is used for check if this object is less, equals or greater than the one you are comparing with(returning 0 is for equals, a negative number for less and positive for greater, you return either a positive number either 0). I recommend you to read the javadoc for compareTo() method.
As an example here is an implementation of Book class where I only compare according to title (I omitted the comparison for the author list).
public class Book implements Comparable<Book> {
private String title;
private List<String> authors;
public Book(String title) {
this.title = title;
}
public int compareTo(Book o) {
return this.title.compareTo(o.title);
}
#Override
public boolean equals(Object b){
if(!(b instanceof Book)){
return false;
}
//authors comparison omitted
return this.title.equals(((Book) b).title);
}
#Override
public String toString(){
return "Title: "+ title; //todo: add authors also if need
}
}
As you see in Book.compareTo() method I rely on the String.compareTo().
it will return -1, 0 or 1; if you need to compare according to author list also you have to thing how will be the logic of the method and think of some issues:
if is enough to rely only on the first authors on the list
if you need to make sure that list of authors is sorted
what happens if the author list is empty
Also NOTE: compareTo should be consistent with equals which means if compareTo returns 0 then equals should return true and vice versa.
According to the documentation, you should also return negative value:
Returns a negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
public int compareTo(final Book theOther) {
int result = myTitle.compareTo(theOther.myTitle);
if (result == 0) {
result = myAuthors.get(0).compareTo(theOther.myAuthors.get(0));
}
return result;
}
check #flowryn for better answer, as he also mention about equals() according to the documentation:
It is strongly recommended, but not strictly required that
(x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class
that implements the Comparable interface and violates this condition
should clearly indicate this fact. The recommended language is "Note:
this class has a natural ordering that is inconsistent with equals."

Java: Checking if a String is equal to a String

I have an issue where I am trying to compare an object's name (String) to another String, and I've tried using .equals() as well as == but neither seem to work in my case.
The code I have right now is:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
else
{
return false;
}
}
}
The program always returns false, even if the name that has been set to product[i] is the same as the parameter given. I've tried looking at other questions relating to .equals() and == and other String references but I have not had any luck in finding something that relates to my problem.
I have seen people use compareTo(), but I'm not sure if that is necessary in my code, and I'm not completely sure on how to use it.
EDIT: As said by Houssni in the comments, I have just realised that the return statement ends the loop and method. Is it possible to check each product's name without having the method terminated after the first check, and have it return a boolean value?
EDIT 2: I have modified the code to how the answers that have been provided say, which is:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
}
return false;
}
I still get the same issue with the product[i].getName() not being equal to checkName and the method returning false, even though they should equal. Any possibilities on why this is happening, because I've looked through my code and I'm not sure.
Edit 3: The only other code that relates to the block of code above is the input of the parameter from another class, which is:
String checkName = JOptionPane.showInputDialog("Enter the name: ");
while (storingProducts.checkingObjectName(checkName) == false) //assume for storingProducts
{
JOptionPane.showMessageDialog(null, "No products were found. Please re-input name.");
checkName = JOptionPane.showInputDialog("Enter the name: ");
storingProducts.checkingObjectName(checkName);
}
if (storingProducts.checkingObjectName(checkName) == true)
//extra code
So, that's all the code relating to my issue. I'm still not sure why the method returns false, though both values are receiving the same String value.
Edit 4: The product and count are coming from the class with the checkingObjectName method:
public class Store
{
private Product[] product; //Product is another class that just sets and gets
private int count=3;
public Store()
{
product = new Product[count];
for (int i=0; i<count; i++)
{
product[i] = new Product();
}
//extra code
SOLUTION
I fixed the issue: instead of using .equals(), I tried using .equalsIgnoreCase() and it worked.
The method is returning as soon as it hits count 0 and it doesn't find a match. If you want to loop through your array until you find a matching name, your code should look like this:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
}
return false;
}
There are two ways to compare strings:
The first is to compare via addresses of the string. Such as: string blue = string red.
The second way to compare strings is through values. This can be done by using the string.equals("StringValue").
Since you have a return statement that will be reached on every posible situation (if condition is true or false), the method will always exit on the first iteration.
What can you do? If you want to return true if the name exists in the array and false otherwise, you can do:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName))
return true;
}
return false; // if after all elements has been checked
// and none was equal to 'checkName', return 'false'
}
How about collecting the names into a List (or Set) and check if checkName matches?
public boolean checkObjectName(final String checkName) {
List<String> productNames = new ArrayList<String>();
for (Product prod : product) {
productNames.add(prod.getName());
}
return productNames.contains(checkName);
}
Note that this will only work if you're comparing case-sensitive strings. Alternatively,
public boolean checkObjectName(final String checkName) {
List<String> productNames = new ArrayList<String>();
for (Product prod : product) {
productNames.add(prod.getName().toLowerCase());
}
return productNames.contains(checkName.toLowerCase());
}
If you do not like this approach, you can use the ones given already, and replace equals with equalsIgnoreCase.

If else statements inside jsp

I have a following problem - if else statements do not work in JSP, and to be honest I have no idea why. Basically I try to change the placeName depending on what number is stored in a string called place. After printing the values in the browser I can see the value is not changed. I am sure it is something simple but... Maybe some one had similar problem before?
<%
//requests the strings sent by previous page
String year = request.getParameter("year");
String place = request.getParameter("place");
out.print(year);
out.print(place);
String year2 = request.getParameter("year2");
String place2 = request.getParameter("place2");
//out.print(year2);
//out.print(place2);
if (place == "1")
{
placeName = "Belmullet";
}
else if (place == "2")
{
placeName = "Birr";
}
...more statements here...
else if (place == "15")
{
placeName = "Shannon airport";
};
%>
change the if condition:
if (place == "1") {
}
by
if ("1".equals(place)) {
}
and the same way for the other if conditions.
This SO question may helps you to learn the difference between == and equals().
It's because you're comparing Strings using ==. Instead, use the .equals() method.
The == operator tests to see if two object references refer to the exact same instance of an object.
The .equals() tests to see if the two objects being compared to each other are equivalent.

if statement comparing strings in java android [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java String.equals versus ==
I'm trying to write a method in az DBOpenHelper extends SQLOpenHelper class.
It supposed to evaluate if there's an entry in the DB with the same name.
public boolean existsContact(Contact contact) {
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_CONTACTS;
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(1);
String cname = contact.getName();
if (name == cname) {
cursor.close();
db.close();
return true;
}
} while (cursor.moveToNext());
}
db.close();
return false;
}
Here's the relevant part of Contact class:
public class Contact {
String _name;
public String getName(){
return this._name;
}
}
Now here's the strange thing:
Scenario A : if (name == cname) where name = "foo" and cname = "foo" equals false.
Eclipse debugger show name's foo and cname's foo have different id's.
both variables filled as seen before in code.
Scenario B: if(name == cname) where variabales are loaded like this:
String name = "foo";
String cname = "foo";
statement equals true as it's supposed to.
Scenario C: if("foo" == "foo") equals true...BUT...debugger goes out the window. LogCat show debugger connected, but there's no activity in eclipse's Debug perspective. Breakpoints have no effect. No Threads shown.
In java, when using == on two objects, you're not actually comparing the strings themselves. You'll need to use .equals(String).
== actually compares the two object's references, not their values.
string1.equals(String target) compares the two strings based off of the actual characters in the strings.
See: http://www.leepoint.net/notes-java/data/expressions/22compareobjects.html
== operator check object reference are equal or not but equals() method check values are same or not
if (name == cname)
{
cursor.close();
db.close();
return true;
}
change with it
if (name.equals(cname)){
cursor.close();
db.close();
return true;
}
When comparing objects in java that are not primitive data types (int, char, boolean, etc...), you have to use the method Object#equals(Object), which returns a boolean.
So, when you are comparing two Strings, you are actually checking if the two Objects are the same instance, instead of the actual value.
All you have to do is just change name == cname to name.equals(cname).

Categories