Java: Checking if a String is equal to a String - java

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.

Related

LinkedList can not be converted to boolean, what am i doing wronge?

I am currently learning Java. Today I am making a little program where I input numbers and the program shall write if they are sorted or not.
I think I got the logic right, but I got a little error that I can't handle.
package inlamningsuppgift_arSorterad;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class ifSorted {
public static void main(String[] arg) {
LinkedList a = new LinkedList();
Scanner sc = new Scanner(System.in);
System.out.println("Input your numbers, end with the letter \\n");
while (sc.hasNextDouble())
a.add(sc.nextDouble());
if (ifSorted(a))
System.out.println("List is sorted");
else
System.out.println("List is not sorted");
}
private static boolean ifSorted(LinkedList a) {
Collections.sort(a);
return a;
}
}
make this substitution! it work with Java8:
1- a.stream().sorted().collect(Collectors.toList() create a new sorted list
2- .equal(a) the new list comes compares the current
private static boolean ifSorted(LinkedList a) {
return a.stream().sorted().collect(Collectors.toList()).equals(a);
}
Lets take a look at your aerSorterat method.
private static boolean aerSorterat(LinkedList a) {
Collections.sort(a);
return a;
}
private static boolean means that your method will return a boolean which is either true or false .You inserted list [a] then returned [a] .No boolean .With your code You don't need that method.However you must cut the if else statement out of the loop so that after the user inserts a String for ex: out. It checks your list out side the loop.You can use the method if you want by inserting your if else statement in it and returning true or false then calling that method in the main method using ifsorted.aerSorterat(a);
You are actually trying to sort your list there with Collections.sort(a), but if you want to see if your values are sorted, you can do it e.g. with a loop like this:
private static boolean isSorted(List<Double> list) {
return ascending(list) || descending(list);
}
If you have to check both ways, you easy do that with both methods connecting with an ||, which is an logical or.
The single methods simply check if all values in a list are greater (ascending) oder lesser (descending) then their predecessors.
private static boolean ascending(List<Double> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i - 1) > list.get(i))
return false;
return true;
}
private static boolean descending(List<Double> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i - 1) < list.get(i))
return false;
return true;
}
If one of the values doesn't fit the premise, it simply returns false. If the loop is completed and left normally, that means that all values are sorted.
But to do that, you have to give the generic parameter <Double> as a parameter to your method, otherwise you cannot compare the values with < and >. Also I use List instead of LinkedList because with that given, you can use any kind of List you want.
If you want to use other objects than numbers, you need to change it a little.
First possability is, the objects you want to use have to implement the Comparable Interface, which provides the compareTo(...) method. Which that given, you can is it e.g. like the following:
public boolean ascending(List<YourObject> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i-1).compareTo(list.get(i)) > 0)
return false;
return true;
}
Simply swap the operator for descending. This e.g. can be used with a list of Strings.

Implementing an equals() method to compare contents of two 'bag' objects

I am working on a school assignment. The objective is to practice GUI's, clone() methods, and using/ modifying existing code. I am trying to write an equals method in the way the instructor desires-- by using a clone of the object, removing items from the bag (returns boolean based on success or failure to remove).
The bag is represented in an array, and should return true in cases such as {1,2,3} and {3,2,1}, ie order does not matter, only the number of each number present in the arrays.
Here is the issue
It works in most cases, however there is a bug in cases where the bags contain numbers as such: {1,1,2} and {1,2,2} and other similar iterations. It is returning true instead of false.
I believe it has something to do with the remove() method we are supposed to use. If i understand it correctly, it is supposed to put the value at the 'end' of the array and decrease the manyItems counter (this is a variable for number of items in the array, because array.length is by default in the constructor 10.)
The code is largely written by another person. We had to import the existing files and write new methods to complete the task we were given. I have all the GUI part done so i will not include that class, only the used methods in the IntArrayBag class.
A second pair of eyes would be helpful. Thanks.
public class IntArrayBag implements Cloneable
{
// Invariant of the IntArrayBag class:
// 1. The number of elements in the bag is in the instance variable
// manyItems, which is no more than data.length.
// 2. For an empty bag, we do not care what is stored in any of data;
// for a non-empty bag, the elements in the bag are stored in data[0]
// through data[manyItems-1], and we don�t care what�s in the
// rest of data.
private int[ ] data;
private int manyItems;
public IntArrayBag( )
{
final int INITIAL_CAPACITY = 10;
manyItems = 0;
data = new int[INITIAL_CAPACITY];
}
public IntArrayBag clone( )
{ // Clone an IntArrayBag object.
IntArrayBag answer;
try
{
answer = (IntArrayBag) super.clone( );
}
catch (CloneNotSupportedException e)
{ // This exception should not occur. But if it does, it would probably
// indicate a programming error that made super.clone unavailable.
// The most common error would be forgetting the "Implements Cloneable"
// clause at the start of this class.
throw new RuntimeException
("This class does not implement Cloneable");
}
answer.data = data.clone( );
return answer;
}
public int size( )
{
return manyItems;
}
public boolean remove(int target)
{
int index; // The location of target in the data array.
// First, set index to the location of target in the data array,
// which could be as small as 0 or as large as manyItems-1; If target
// is not in the array, then index will be set equal to manyItems;
for (index = 0; (index < manyItems) && (target != data[index]); index++)
// No work is needed in the body of this for-loop.
;
if (index == manyItems)
// The target was not found, so nothing is removed.
return false;
else
{ // The target was found at data[index].
// So reduce manyItems by 1 and copy the last element onto data[index].
manyItems--;
data[index] = data[manyItems];
return true;
}
}
//I added extra variables that are not needed to try to increase readability,
//as well as when i was trying to debug the code originally
public boolean equals(Object obj){
if (obj instanceof IntArrayBag){
IntArrayBag canidate = (IntArrayBag) obj; // i know this can be changed, this was required
IntArrayBag canidateTest = (IntArrayBag) canidate.clone(); //this was created
//as a clone because it was otherwise referring to the same memory address
//this caused items to be removed from bags when testing for equality
IntArrayBag test = (IntArrayBag) this.clone();
//fast check to see if the two objects have the same number of items,
//if they dont will return false and skip the item by item checking
if (test.size() != canidateTest.size())
return false;
//the loop will go through every element in the test bag it will
//then remove the value that is present at the first index of the test bag
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
int check = test.data[i];
//remove() returns a boolean so if the value is not present in each bag
//then the conditional will be met and the method will return false
boolean test1 = test.remove(check);
boolean test2 = canidateTest.remove(check);
if (test1 != test2)
return false;
}//end for loop
// if the loop goes through every element
//and finds every value was true it will return true
return true;
}//end if
else
return false;
}//end equals
}
I cannot see the big picture, as I havent coded GUIs in Java before, however, as far as comparing 2 int[] arrays, I would sort the arrays before the comparison. This will allow you to eliminate problem cases like the one you stated ( if sorting is possible), then apply something like:
while(array_1[index]==array_2[index] && index<array_1.length)
{index++;}
and find where did the loop break by checking the final value of index
Is it explicitly stated to use clone? You can achieve it easily by overriding the hashCode() for this Object.
You can override the hashCode() for this object as follows:
#Override
public int hashCode() {
final int prime = 5;
int result = 1;
/* Sort Array */
Arrays.sort(this.data);
/* Calculate Hash */
for(int d : this.data) {
result = prime * result + d;
}
/* Return Result */
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || this.getClass() != obj.getClass()){
return false;
}
return false;
}
If you want to continue using your implementation for equals to compare test and CandidateTest then also you can compute unique hashes and make decision based on the results.
Here is the code snippet:
/* Assuming that you have put size comparison logic on top
and the two objects are of same size */
final int prime = 31;
int testResult = 1;
int candidateTestResult = 1;
for(int i = 0; i < test.size(); i++) {
testResult = prime * testResult + test.data[i];
candidateTestResult = prime * candidateTestResult + candidateTest.data[i];
}
/* Return Result */
return testResult == candidateTestResult;
I believe the problem is in this line:
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
The problem here is that test and canidateTest are the clones that you made, and you are removing elements from those bags. And any time you remove an element from the bag, the size will decrease (because you decrease manyItems, and size() returns manyItems). This means you're only going to go through half the array. Suppose the original size is 4. Then, the first time through the loop, i==0 and test.size()==4; the second time, i==0 and test.size()==3; the third time, i==2 and test.size()==2, and you exit the loop. So you don't look at all 4 elements--you only look at 2.
You'll need to decide: do you want to go through the elements of the original array, or the elements of the clone? If you go through the elements of the clone, you actually never need to increment i. You can always look at test.data[0], since once you look at it, you remove it, so you know test.data[0] will be replaced with something else. In fact, you don't need i at all. Just loop until the bag size is 0, or until you determine that the bags aren't equal. On the other hand, if you go through the elements of this.data (i.e. look at this.data[i] or just data[i]), then make sure i goes all the way up to this.size().
(One more small point: the correct spelling is "candidate".)
Maybe you should try SET interface
view this in detail :http://www.tutorialspoint.com/java/java_set_interface.htm
A set object cannot contains duplicate elements, so it's suitable for your assignment than build your own class.
For example:[1,1,2] and [1,2,2]
you can use this to test whether they are equal
arr1 = {1,1,2}
arr2 = {1,2,2}
Set<Integer> set = new HashSet<Integer>();
for(int i : arr1){//build set of arr1
if(set.contains(i)==false){
set.add(i)
}
}
for(int i:arr2){
if(set.contains(i)==false){
System.out.println('not equal');
break;
}
}
Hope this is helpful.

Boolean variable Explanation

I have a question about this block of Java code. (Yes, I am a beginner). The code works, I am just a little confused. This code checks the people and cars arrays to find if it has empty seats, which is what the tryToAdd method does. It will then add the person to that car. My question is about the boolean values. It looks to me that added is set to false. Then in the for loop it says: as long as added is true..do the loop. So, it seems that the loop should never run.
public void loadPassengers() {
for (Person p : people) {
boolean added = false;
for (int i = 0; !added && i < cars.size(); i++) {
added = cars.get(i).tryToAdd(p);
}
}
}
Then in the for loop it says: as long as added is true
Actually, it says the opposite of that. Look again:
for (int i = 0; !added && i < cars.size(); i++)
! is the 'logical inverse' (or not) operator. So this statement is actually saying 'stay in the for loop so long as we haven't added and i is less than the size of cars'.
Presumably, at some point cars.get(i).tryToAdd(p) will return true, and the for loop will terminate. Or you run out of cars. Either way the loop runs for at least one iteration (so long as you have at least one car).
You confused it. Actually,
if(!added)
{
//code
}
This condition is equal to:
if(added == false)
{
//code
}
So your logic says, as long as *added* is false, keep iterating, and try to perform' added = cars.get(i).tryToAdd(p); ,setting value of added to 'true'`
! is inverse of boolean.
You are executing a loop to say that unless a person is added (tryToAdd(p) which returns true) execute the loop. And also i < cars.size() says cars should have seat to add person.
Added explanation in your code.
public void loadPassengers() {
boolean added; //Declaring added variable outside for loop for memory management
for (Person p : people) { //Execute loop for each person
added = false; //setting added value to false for each person
// unless person is added execute the loop and also check for the car size.
for (int i = 0; (added == false && i < cars.size()); i++) { // added == false or !added is same
added = cars.get(i).tryToAdd(p); // tryToAdd(p) return true to confirm that a person is added
}
}
}

Checking an array list against another array list

This is a method in a spell checker. As the header explains, it should return true if and only if all the words added to the arraylist are found in the parent array, words. Otherwise it should return a false value. I've been fighting with this for a few hours and this is my current situation...
/**
* This method returns true if (and only if) all words in the
* given wordList are found in the dictionary.
*/
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(int index = 0; index < wordList.size(); index++)
{
if(words.contains(!wordList.contains(index)))
{
result = false;
}
result = true;
}
return result;
}
All I really need is a way to turn out a yes or no, but I'm lost.
Please try and work with the code given as this is an exercise to teach that code.
Thanks!
Your problem is here:
if(words.contains(!wordList.contains(index)))
!wordList.contains(index) is a boolean expression, so it always evaluates to either true or false. So you're actually checking if the words list contains true or false, not the word like you want. Replace it with if(!words.contains(wordList.get(index)) to check if the current word is found in the dictionary.
I would suggest a following solution: iterate wordList word by word, and for each word check if it's found in the dictionary. If not so, return false immediately. If you reach the end of the loop, return true.
Here could be another solution:
public static boolean allKnown(List<String> parent, List<String> child) {
List<String> temp = new ArrayList<String>(child);
temp.removeAll(parent);
return temp.isEmpty();
}
For example:
List<String> parent = Arrays.asList("w1", "w2", "w3", "w4");
List<String> childOk = Arrays.asList("w1", "w4");
List<String> childKo = Arrays.asList("w1", "xx");
System.out.println(allKnown(parent, childOk));
System.out.println(allKnown(parent, childKo));
Prints:
true
false
Take out result = true; - you don't want to reset the value to true at every step in the loop.
Also change wordList.contains to wordList.get (because you want to get the word at a specific index, not check if it's contained in wordList) and move the ! out (because you can't 'not' a string).
And you can also optimize by checking result's value in the for-loop condition (or simply returning directly in the if-statement).
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(int index = 0; index < wordList.size() && result; index++)
{
if(!words.contains(wordList.get(index)))
{
result = false;
}
}
return result;
}
If words really is an array and not an ArrayList, it doesn't have a contains method, you'll have to either have a double for-loop, or convert it to a list:
List<String> parentWords = Arrays.asList(words);
...
if (parentWords.contains(...))
Don't reset result to true after your if. Because like this the whole function will always return true.
A few tips:
Don't use ArrayList as a method parameter, always use the more abstract List (none of your code depends on ArrayList, so you can change the implementation later, if you like).
Iterate over List objects using the simplified syntax shown below.
You only need one word to be not in the words list to return false, so do exactly that (as shown below).
public boolean allKnown(List<String> wordList) {
for (String word : wordList) {
if (!words.contains(word)) {
return false;
}
}
return true;
}
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(String word : wordList)
{
if(!words.contains(word))
{
result = false;
}
}
return result;
}
Here is a simpler version :
public boolean allKnown(List<String> wordList) {
List<String> wordListCopy = new ArrayList<String>(wordList);
return !wordListCopy.retainAll(words);
}
PS : retainAll() removes from you wordList all of its elements that are not contained in you dictionnary. This method return true if your wordList changed as a result of the call (after removing the non existing element), in other word, this method return false when all your wordList elements exists in you dictionnary.

Use method to compare lists

I'm trying to use a method to compare t2o different lists. Basically I want to pass two different lists to a method which will return true or false if the elements of one array list are contained in the other using .contains. Right now it only returns true - and I'm not sure why. I'd like it to return false. If someone could help me figure this out, that would be great.
public class ArrayListTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
list1.add("cat");
list1.add("dog");
list1.add("zebra");
list1.add("lion");
list1.add("mouse");
//Test Values
//list2.add("cat");
list2.add("lizard");
boolean doesitcontain = contains(list1, list2);
System.out.println(doesitcontain);
}
public static boolean contains (List<String>list1, List<String>list2){
boolean yesitcontains;
for(int i = 0; i < list1.size(); i++){
if(list2.contains(list1.get(i))){
System.out.println("Duplicate: "+list1.get(i));
yesitcontains = true;
System.out.println(yesitcontains);
}else{
yesitcontains = false;
System.out.println(yesitcontains);
}
}
if (yesitcontains = true){
return true;
}else
return false;
}
}
You have inadvertently used the assignment operator where you intended the equality operator. In your specific case you should rewrite all this:
if (yesitcontains = true){
return true;
}else
return false;
}
to just
return yesitcontains;
and avoid any chance of confusion.
Furthermore, your algorithm will not work because you should return true immediately when you see a duplicate. Instead you go on with the loop and "forget" your finding. You can expect this to always return false except if the very last elements coincide.
In a wider context, I should also give you the following general advice:
Avoid indexed iteration over lists. Not all lists are ArrayLists and may show O(n) complexity for get(i). Instead use the enhanced for loop, which is safer, more concise, and more obvious;
Know the library: if you're just after confirming there are no duplicates, just Collections.disjoint(list1, list2) would give you what you need;
Be aware of algorithmic complexity: checking for duplicates in two lists is O(n2), but if you turn one of them into a HashSet, you'll get O(n).
Taking everything said above into account, the following would be an appropriate implementation:
static boolean disjoint(Collection<?> c1, Collection<?> c2) {
for(Object o : c1)
if (c2.contains(o))
return true;
return false;
}
If you look at Collections.disjoint, you'll find this exact same loop, preceded by a piece of code which optimizes the usage of sets for reasons described above.
Seems to me your method should be rewritten to:
public static boolean contains(List<String>list1, List<String>list2) {
return list2.containsAll(list1);
}
The code you currently have actually only checks if the last element of list1 is also in list2.
If you're actually looking for a contains any, this simple solution will do:
public static boolean contains(List<String>list1, List<String>list2) {
for (String str : list1) {
if (list2.contains(str)) {
return true;
}
}
return false;
}
if (yesitcontains = true){
should be
if (yesitcontains == true){
== is for comparison and = is for assignment.
if (yesitcontains = true){
will always evaluate to if(true) which causing return true;
EDIT:
(OR)
simply return yesitcontains; as commented.
if (yesitcontains == true) { } // use `==` here
or just
if (yesitcontains) { }
The below code assigns true to yesitcontains , and the expression will always be true.
if (yesitcontains = true) { }
There is no point of if() in your code , you can simple return yesitcontains;

Categories