Solved

List removeAll(Collection c) doesn't work

Posted on 2003-12-10
60
793 Views
Last Modified: 2007-12-19
try
    {
      boolean success = false;
      List listComment = new ArrayList();
      List list2 = new ArrayList();
     
      CodeTableSessionLocal ctl = getCodeTableSessionLocalHome().create();
      UnitSessionLocal usl = null;
     
      //get the list of unit comment
      if(typeOfKey.toUpperCase().equals("UNIT"))
      {
        usl = getUnitSessionLocalHome().create();
        list2 = usl.returnAllUnitComments(key);                        //Gives a size 1
      }
   
      //get the list of comment by department key
      listComment = ctl.returnAllComments(deptKey);      //Gives a size of 2
     
     // Remove all the elements in listComment from list2(listComment -= list2)
     // listComment becomes the asymmetric difference of listComment and list2

     success = listComment.removeAll(list2);    //return false

    return listComment;  //size of 2   but it should be size 1.
}

Does it matter if I have built my list with and object?

So List Comment is built like this


    try
    {
      List list = new ArrayList();
      Collection col = getCd_commentLocalHome().findAllByDept(deptKey);
      Iterator iterate = col.iterator();
      Cd_commentLocal commentLocal;
      while(iterate.hasNext())
       {  
          commentLocal = (Cd_commentLocal)iterate.next();
          Comment comment = new Comment();
          comment.setCommentKey(commentLocal.getComment_key());
          comment.setCommentTitle(commentLocal.getComment_title());
          list.add(comment);    
       }
      return list;
    }
    catch(NamingException ne)
    {
     System.out.println(ne.toString());
     throw new javax.ejb.EJBException(ne);
    }
    catch(FinderException fe)
    {
      System.out.println(fe.toString());
      throw new javax.ejb.EJBException(fe);
    }

The list 2 is created like this:

     try
     {
       Crse_unitLocal unitLocal = getCrse_unitLocalHome().findByPrimaryKey(unitKey);
       //getting comments for the unit (one or many)
       Collection col = unitLocal.getCrse_unit_comment_reln_fk_unit_key();
       Iterator it = col.iterator();
       Crse_unit_comment_relnLocal unitCommentLocal;
       List list = new ArrayList();
       while(it.hasNext()){
          unitCommentLocal = (Crse_unit_comment_relnLocal)it.next();
          Comment comment = new Comment();
          comment.setCommentKey(unitCommentLocal.getUnit_comment_reln_key());
          comment.setCommentTitle(unitCommentLocal.getCd_comment_fk_comment_key().getComment_title());
          list.add(comment);
        }
       return list;
     }
    catch(NamingException ne)
    {
     System.out.println(ne.toString());
     throw new javax.ejb.EJBException(ne);
    }
    catch(FinderException fe)
    {
      System.out.println(fe.toString());
      throw new javax.ejb.EJBException(fe);
    }

The Comment object is like this:

public class Comment
{
  private Long commentKey;
  private String commentTitle;
  private String commentDesc;
  private String note;
  private String modifiedBy;
  private String createdBy;
 
  public Long getCommentKey()
  {
    return commentKey;
  }

  public void setCommentKey(Long newCommentKey) {
    this.commentKey = newCommentKey;
  }

  public String getCommentDesc() {
   
    return commentDesc;
  }

  public void setCommentDesc(String newCommentDesc) {
    this.commentDesc = newCommentDesc;
  }

  public String getCommentTitle() {
    return commentTitle;
  }
 
  public void setCommentTitle(String newCommentTitle ) {
    this.commentTitle = newCommentTitle;
  }

  public String getNote() {
    return note;
  }
 
  public void setNote(String newNote ) {
    this.note = newNote;
  }

  public String getModifiedBy() {
    return modifiedBy;
  }
 
  public void setModifiedBy(String newModifiedBy ) {
    this.modifiedBy = newModifiedBy;
  }

  public String getCreatedBy() {
    return createdBy;
  }
 
  public void setCreatedBy(String newCreatedBy ) {
    this.createdBy = newCreatedBy;
  }
}
 
  Any help would be appreciated

Thank you in advance.
0
Comment
Question by:Caro0101
  • 23
  • 16
  • 14
  • +3
60 Comments
 
LVL 15

Expert Comment

by:jimmack
ID: 9913259
Are you getting an exception?  If so what is the exception and where is it occurring (please could you identify the line from your code).
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9913281
Also, you've asked this question in two places (this - the Java Programming TA is the right one).  If you're quick ;-) you should be able to delete the question from the Programming Languages area.  The link to delete the question is just above the comment box.
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9913325
Sorry.  Ignore my first comment about exceptions, I didn't read your code properly and missed the comments you'd added regarding the size of the lists.
0
 

Author Comment

by:Caro0101
ID: 9913341
I did delete the one in the Programmin Languages area ..I'll go check again.

I don't get an exception it just returns false instead of true.

Could it be that is is I am building a list of comment objects do I need to cast it when I am comparing it or should I have the Comment object Extend Comparable and have a CompareTo in the Class?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9913347
You must override equals in the Comment class for object comparisons to work. You'd porbably be better to override hashCode too.
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9913378
Good grief!  A man can't even take a comfort break without CEHJ nipping in with the solution ;-)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9913405
Better take your wireless-upped laptop with you next time ;-)
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9913455
ROFL :-D
0
 

Author Comment

by:Caro0101
ID: 9913482
You must override equals in the Comment class for object comparisons to work. You'd porbably be better to override hashCode too

Not sure I understand what the override equals in the Comment class for the comparison to work means

Do I need to add implements Comparator {  to my Comment object and have


    public int compare(Object list1, Object list2) {
        Object element1 = (Comparable)((List)list1).get(m_sortColumn);
        Object element2 = (Comparable)((List)list2).get(m_sortColumn);
          if (m_sortDirection == SearchResults.ASCENDING) {
            if (element1.getClass().getName().equals("java.lang.String")) {
                return ((String)element1).compareToIgnoreCase((String)element2);
            }
                return ((Comparable)element1).compareTo((Comparable)element2);
          }
        if (element1.getClass().getName().equals("java.lang.String")) {
            return ((String)element2).compareToIgnoreCase((String)element1);
        }
            return ((Comparable)element2).compareTo((Comparable)element1);
    }
   
    public boolean equals(Object obj1, Object obj2) {
          return (obj1).equals(obj2);
    }

Need an example please .. Thank you.. I will add another 50 points
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9913545
You need to tell the collection classes precisely how one class instance is evaluated as being the same as another instance, otherwise they have no way of knowing if one Comment is the same as another.

The way you implement it depends on your application logic.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9913576
0
 
LVL 37

Expert Comment

by:zzynx
ID: 9913797
One possibility *could* be:

public class Comment {
...
    public boolean equals(Object o) {
        if (o == null) {
            return false; // comparison with a null object
        }
        try {
            Comment other = (Comment) o;
            return
               commentKey == other.getCommentKey() &&
               commentTitle == other.getCommentTitle() &&
               ///and so on... (your logic!)
               ;
        } catch (ClassCastException ex) {
            return false; // the given object is not of type Comment
        }
    }
   
    public int hashCode() {
        return commentKey;
        // try to return a hashkey as unique as possible
        // (e.g. "OR"-ing some of the properties is a good practice)
    }

}
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9913828
I'm not really sure if guessing helps. Only you can tell, Caro0101, how you want your application to determine if one Comment is the same as another.
0
 

Author Comment

by:Caro0101
ID: 9914291
Maybe I am complicating things by putting it into an Object.. would it work if I just did

       List list = new ArrayList();
       while(it.hasNext()){
          unitCommentLocal = (Crse_unit_comment_relnLocal)it.next();
          list.add(unitCommentLocal.getUnit_comment_reln_key());
          list.add(unitCommentLocal.getCd_comment_fk_comment_key().getComment_title());      
       return list;


instead of putting it into an object called Comment?

Thanks
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9914343
No you're not. It should be encapsulated into one class. How do you want this evaluated?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9914499
If you want them equal if their commentTitle and commentKey are equal, you could do:


 public boolean equals(Object other) {
         if (this == other)
               return true;
        if (other == null)
                  return false;
        try {
            Comment otherComment = (Comment) other;
            return commentKey.equals(otherComment.getCommentKey()) && commentTitle.equals(otherComment.getCommentTitle());
             
        } catch (ClassCastException e) {
            return false;
        }
 }
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9914523
hashCode could be something like

public int hashCode() {
      return commentKey.hashCode() * commentTitle.hashCode();
}
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9914557
You should also test for null key and title, or initalize them to an empty String in the no-arg constructor of Comment
0
 
LVL 92

Expert Comment

by:objects
ID: 9915255
> I'm not really sure if guessing helps.

Hmmm, so why do appear to guess what the user wants on a regular basis ;)
0
 

Author Comment

by:Caro0101
ID: 9915316
I tried the examples but I still get the same result.. Am I wrong to understand that list1.removeAll(list2) means I would get list1 to have all the elements which are not in list2?
0
 
LVL 92

Expert Comment

by:objects
ID: 9915328
> If you want them equal if their commentTitle and commentKey are equal

And then you have guess :-D
0
 
LVL 92

Expert Comment

by:objects
ID: 9915339
> Am I wrong to understand that list1.removeAll(list2) means I would
> get list1 to have all the elements which are not in list2?

No but the default match test is whether two objects are the same instance, so it will only remove any instances that are the exact same object.
0
 
LVL 92

Expert Comment

by:objects
ID: 9915351
So you need to define a method to determine under what conditions two Comment objects are equal.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9915362
>>I tried the examples but I still get the same result.

Can you post the code you're now using?
0
 
LVL 92

Assisted Solution

by:objects
objects earned 150 total points
ID: 9915404
I better have a guess too :)
Assuming your commentKey is a unique key, try the following:


public class Comment {
...
    public boolean equals(Object o) {
        boolean result = false;
        if (o instanceof Comment)
        {
            Comment other = (Comment) o;
            result = commentKey.equals(other.commentKey);
        }
        return result;
    }
   
    public int hashCode() {
        return commentKey.intValue();
    }
}
0
 

Author Comment

by:Caro0101
ID: 9915420
Am I building my Comment list of Object incorrectly. Or could it be that in the object I have more variables than I set and therefore they aren't equal?

I do want it to test that a Comment is equal by the CommentKey & Title but if for some reason I would need to add more data like the note or the description than this equal would no longer work or would it still work and just test for those two field?

Increased another 25 points..
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9915435
>>would it still work and just test for those two field?

Yes, if you've asked it to.

It's difficult to help if don't post the code you're actually using.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9915445
>>Am I building my Comment list of Object incorrectly.

Looks OK
0
 
LVL 92

Expert Comment

by:objects
ID: 9915565
> would it still work and just test for those two field?


If commentKey is a unique key, then two objects should be equal if just this field is equal. How exactly is this key used?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9915591
And if it's unique it can also be used for the hashcode
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 92

Expert Comment

by:objects
ID: 9915636
> And if it's unique it can also be used for the hashcode

already posted that above :)
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 300 total points
ID: 9915761
If you want to test on the fields you mentioned, this is how it works with removeAll. You save this to one file as CommentTest.java:


import java.util.*;

public class CommentTest {

  public static void main(String[] args) {
    Comment comment1 = new Comment();
    Comment comment2 = new Comment();
    Comment comment3 = new Comment();

    comment1.setCommentKey(new Long(1));
    comment1.setCommentTitle("ck1Title");

    comment2.setCommentKey(new Long(2));
    comment2.setCommentTitle("ck2Title");

    comment3.setCommentKey(new Long(3));
    comment3.setCommentTitle("ck3Title");

    ArrayList list1 = new ArrayList();
    list1.add(comment1);
   
    // Just 1 now in first list
   
    ArrayList list2 = new ArrayList();
    list2.add(comment1);
    list2.add(comment2);
    list2.add(comment3);
   
    // now all 3 in second list

    // remove all from second that are in the first
    list2.removeAll(list1);
   
    // print result

    System.out.println(list2);
  }

}


class Comment {


  private Long commentKey;
  private String commentTitle;
  private String commentDesc;
  private String note;
  private String modifiedBy;
  private String createdBy;

  public void setCommentKey(Long newCommentKey) {
    this.commentKey = newCommentKey;
  }


  public void setCommentDesc(String newCommentDesc) {
    this.commentDesc = newCommentDesc;
  }


  public void setCommentTitle(String newCommentTitle) {
    this.commentTitle = newCommentTitle;
  }


  public void setNote(String newNote) {
    this.note = newNote;
  }

  public void setModifiedBy(String newModifiedBy) {
    this.modifiedBy = newModifiedBy;
  }


  public void setCreatedBy(String newCreatedBy) {
    this.createdBy = newCreatedBy;
  }

  public Long getCommentKey() {
    return commentKey;
  }

  public String getCommentDesc() {

    return commentDesc;
  }

  public String getCommentTitle() {
    return commentTitle;
  }

  public String getNote() {
    return note;
  }

  public String getModifiedBy() {
    return modifiedBy;
  }

  public String getCreatedBy() {
    return createdBy;
  }

  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (other == null) {
      return false;
    }
    try {
      Comment otherComment = (Comment) other;
      return commentKey.equals(otherComment.getCommentKey()) && commentTitle.equals(otherComment.getCommentTitle());
    } catch (ClassCastException e) {
      return false;
    }
  }


  public int hashCode() {
    return commentKey.hashCode() * commentTitle.hashCode();
  }
 
  public String toString() {
    return getCommentKey() + "," + getCommentTitle();
  }
}
0
 
LVL 92

Expert Comment

by:objects
ID: 9915854
I don't think testing on Title is necessary. Just testing key equality should be sufficient.
See the code I posted earlier.

0
 
LVL 92

Expert Comment

by:objects
ID: 9915885
If you saved two comments to the db, with the same key but different titles would it add two different records to db, or would one overwrite the other?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9915910
>>I don't think testing on Title is necessary

Caro0101 said he/she wants to test on it though
0
 

Author Comment

by:Caro0101
ID: 9916077
This is the code I am running

public class Comment
{
  private Long commentKey;
  private String commentTitle;
  private String commentDesc;
  private String note;
  private String modifiedBy;
  private String createdBy;

  public Long getCommentKey()
  {
    return commentKey;
  }

  public void setCommentKey(Long newCommentKey) {
    this.commentKey = newCommentKey;
  }

  public String getCommentDesc() {
   
    return commentDesc;
  }

  public void setCommentDesc(String newCommentDesc) {
    this.commentDesc = newCommentDesc;
  }

  public String getCommentTitle() {
    return commentTitle;
  }
 
  public void setCommentTitle(String newCommentTitle ) {
    this.commentTitle = newCommentTitle;
  }

  public String getNote() {
    return note;
  }
 
  public void setNote(String newNote ) {
    this.note = newNote;
  }

  public String getModifiedBy() {
    return modifiedBy;
  }
 
  public void setModifiedBy(String newModifiedBy ) {
    this.modifiedBy = newModifiedBy;
  }

  public String getCreatedBy() {
    return createdBy;
  }
 
  public void setCreatedBy(String newCreatedBy ) {
    this.createdBy = newCreatedBy;
  }

  public boolean equals(Object other) {
     
      if (this == other)
          return true;
      if (other == null)
          return false;
      try {
          boolean results = false;
          Comment otherComment = (Comment) other;
          results = commentKey.equals(otherComment.getCommentKey());

          return results;

         
      } catch (ClassCastException e) {
          return false;
      }

  }
   
    public int hashCode() {
        return commentKey.intValue();
    }
}

results is false both times.. It should really be true the first time. So I don't think my object are being built right.. cause in the list2 I have (1) are the keys & in listComment I have (1,3)

So my final listComment should be only (3)

But it's not ..;-(
0
 
LVL 92

Expert Comment

by:objects
ID: 9916105
that code can be simplified a little as I posted earlier:

    public boolean equals(Object o) {
        boolean result = false;
        if (o instanceof Comment)
        {
            Comment other = (Comment) o;
            result = commentKey.equals(other.commentKey);
        }
        return result;
    }
0
 

Author Comment

by:Caro0101
ID: 9916106
You are right I thought I needed to test on the title too but it is a unique key from the database so I can test on just the commentKey.

Thank you for taking your time on this question..

Added another 25 points..
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916121
I posted my code based on what you asked for Caro0101 ...
0
 
LVL 92

Expert Comment

by:objects
ID: 9916127
Add the following method to your Comment class:

public String toString()
{
   return commentKey.toString();
}

And then print out the list values before removeAll();

System.out.println("listComment="+listComment);
System.out.println("list2="+list2);
success = listComment.removeAll(list2);    //return false

0
 

Author Comment

by:Caro0101
ID: 9916131
What I don't understand is that when I walk thorugh the code it gives me the First key to be 1 and then the second to be 3.. So it is only comparing the listComment.. I don't see where I am passing the other Comment object holding the key I want to remove..

Thanks
0
 
LVL 92

Expert Comment

by:objects
ID: 9916151
oh, and also print the results after removeAll():

System.out.println("listComment="+listComment);
System.out.println("list2="+list2);
success = listComment.removeAll(list2);    //return false
System.out.println("result="+listComment);
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916172
Ive given you a working example Caro0101. If you now wnat to change to compare only on key, just change

return commentKey.equals(otherComment.getCommentKey()) && commentTitle.equals(otherComment.getCommentTitle());

to

return commentKey.equals(otherComment.getCommentKey());
0
 

Author Comment

by:Caro0101
ID: 9916196
Yes I know CEJH very sorry about that. I do appreciate your answers they are very helpful.
0
 

Author Comment

by:Caro0101
ID: 9916364
I must apologies by doing the System.out.println I notice that my code has been changed. We use version control with multiple locks and it looks like someone has ignored my changes..

Please advise me as to how you want these point shared cause you have all given me the write information and again I do apologize tremendously I should have made sure that the code I expected was actually there. You have to hate the multiple locks in version control..

My code actually worked yesterday without the overriding of the equal I thought I was going nuts when it wasn't working today but I didn't think to look to see if the version had been changed and my changes had been lost. Learning the hard way.

For your inconvenience I will add another 100 points
0
 

Author Comment

by:Caro0101
ID: 9916409
Increase points...by 100
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916418
That's OK. It's up to you how your distribute the points
0
 

Author Comment

by:Caro0101
ID: 9916420
Is 450 the max points for a question??
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916440
No - but that's quite enough - don't worry
0
 
LVL 92

Expert Comment

by:objects
ID: 9916444
> I must apologies by doing the System.out.println I notice that my code has been changed.

A little debugging to whats actually occuring so often helps us locate the problem :-)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916452
Incidentally, there are case where it *will* work without overriding equals, but only if you can be certain that the object references are equal where commentKey is equal
0
 

Author Comment

by:Caro0101
ID: 9916936
Yes I will keep the code in.

I agree a little debugging helps and I was at the point where the problem I thought was.. I guess I will have to always check to make sure other programmers are ignoring my changes when they merge there file. Lesson learn..

I tried to split the points but I can only split on an answer. Is there a way to split on a comment?

Do I need to accept the comments as answers and then split the points? Any help would be appreciated.

I am thinking 300 for CEHJ & 150 for Objects any objections? My reasoning is that CEHJ gave me a link to get a better understanding of why I needed to override the equal & the hashCode

Thanks
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9916970
>>Do I need to accept the comments as answers and then split the points?

That's it
0
 
LVL 92

Expert Comment

by:objects
ID: 9916999
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9917043
What happened!?
0
 

Author Comment

by:Caro0101
ID: 9917067
I screwed up.. I have put a question in the Community support to fix it.. Is that the right thing to do or am I too late?

I f I am too late I will open another question and answer it and I will give you 500 points.. for my mistake..
0
 
LVL 92

Expert Comment

by:objects
ID: 9917076
:-D
I can post you some points if you need them to do your Xmas shopping ;)
0
 

Expert Comment

by:YensidMod
ID: 9917259
I unaccepted the answer per Caro0101 request. Now she/he will re-split the points.

Yensidmod
EE Moderator
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9917398
8-)
0
 
LVL 92

Expert Comment

by:objects
ID: 9917498
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now