-2

I'm working on an app in android studio. The part of the app I'm having issues with is where the user can favourite and remove their favourite item. I do this by adding and removing the item from a list.

The thing is the add functionality works which is:

   public void addFavorite(Context context, NewSubject subject) {

        List<NewSubject> favorites = getFavorites(context);
        if (favorites == null)
            favorites = new ArrayList<NewSubject>();

        favorites.add(subject);
        saveFavorites(context, favorites);
    }

I am passing in an object of type "NewSubject" which is just a class of getters and setters for name and id.

The problem arises when I try to remove an item from this list. Code below:

public void removeFavorite(Context context, NewSubject subject) {

    ArrayList<NewSubject> favorites = getFavorites(context);
    if (favorites != null) {
        favorites.remove(subject);
        saveFavorites(context, favorites);
    }
}

I've even tried something like:

  for(int i = 0; i < favorites.size(); i++){
                if(favorites.get(i).getSubject_name() == subject.getSubject_name())
                    favorites.remove(i);
            }

Even though both subject names match, the if statement never triggers as true. By changing it to ID it does remove the item but I was wondering why it doesn't work the other way. MeetTitan suggested to use "equals" operator to compare Strings and this has fixed that issue. But I'm still wondering as to why removing the item by "subject" without the FOR loop and IF statement doesn't work.

I have cleared the app's data multiple times whilst trying to debug the source of the problem.

Thank you for your time and help, it is much appreciated.

Gary
  • 15
  • 3
  • You are trying to compare String objects with ==. You can't do that in Java. You have to do `str1.equals(str2);`, or else it will check if the object references are the same (which they probably won't be), instead of the content. Check out http://stackoverflow.com/questions/767372/java-string-equals-versus – MeetTitan Dec 20 '15 at 05:23
  • Thank you, that fixes the String problem but what about without the for loop and IF statement and just trying to remove the item by the object? – Gary Dec 20 '15 at 05:25
  • @Gary override equals and hashcode method for the class NewSubject – gvmani Dec 20 '15 at 06:06

3 Answers3

1

This applies if you are re-creating NewSubject twice... If you are trying to remove the exact same instance of NewSubject that you got from the collection, then I guessed wrong and this isn't the answer you are looking for.

Is it possible you haven't defined equals and hashCode in your Favorites object? Without those remove will only work with the EXACT same object instance in the collection. If you haven't, try defining them and see if remove() works the way you expect.

Without those methods defined, collections will respond this way:

Obj x=new Obj("data")
Obj y=new Obj("data")

collection.put(x)
collection.remove(y)

assert( collection.size() == 1) // was not removed because .equals didn't exist--remove reverted to == instead which failed, x != y

collection.remove(x)

assert( collection.size() == 0) // NOW it worked because you used the same instance.

if you define .equals and hashCode to compare the strings inside obj, then this will work:

collection.put(x)
collection.remove(y)

assert( collection.size() == 0) // worked because x.equals(y)!
Bill K
  • 62,186
  • 18
  • 105
  • 157
0

Try

String.equalsIgnoreCase(value1,value2) 

This might do your work.

Ghasem
  • 14,455
  • 21
  • 138
  • 171
Akash Amin
  • 2,741
  • 19
  • 38
0

From your example, it's evident that name is a String object. In java, you have to use ".equals()" or comparing two strings. You can do this:

    if(favorites.get(i).getSubject_name().equals(subject.getSubject_name())){
    ...
}

Or, you can override the equals() method in your NewSubject class to make this work:

favorites.remove(subject);

You can use something like this as your equals() method in the NewSubject class (considering you are only matching two NewSubject objects based on their names):

@Override
public boolean equals(Object other){
    if (other == null) return false;
    if (other == this) return true;
    NewSubject otherSubject = (NewSubject) other;
    if(this.getSubject_name().equals(otherSubject.getSubject_name())) 
      return true;
    else
      return false;
}

Update:

You may want to override hashcode() as well. If your NewSubject class ever gets used in a hash-based collection such as HashMap, overriding only equals() method will not be sufficient. For reference, this is from Effective Java by Joshua Bloch:

You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object.hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.

Hungry Coder
  • 1,800
  • 17
  • 22
  • You should override `hashCode()` if you override `equals()`. – MeetTitan Dec 20 '15 at 05:37
  • ArrayList is not a hash-based collection and it's *remove(object)* method doesn't depend on the hashcode. Ref: [link](https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove(java.lang.Object)). So, it will work fine for this case (tested). But, you are correct. Overriding *equals()* without overriding *hashcode()* may be dangerous in case the object is used in any hash-based collection like HashMap, HashTable, etc. My answer is updated. – Hungry Coder Dec 20 '15 at 17:04
  • Just because it *compiles*, doesn't mean it can't be *wrong*. In any event, you've updated you answer, enjoy a +1. – MeetTitan Dec 20 '15 at 20:52
  • It doesn't only compile, it will work perfectly fine with ArrayList and won't have any issues as long as you use it in a non-hash based collection. Check the ArrayList#remove(object) documentation, it doesn't bother about the hashcode, it only uses the equals() method. But I think, I already agreed that equals() should always be overriden along with hashcode() – Hungry Coder Dec 20 '15 at 22:54