Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

How do I remove duplicates from an arraylist of objects from another class ? -EDITED  RSS feed

 
monica praslisa
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have a class called Switch which has as a constructor parameter an integer.
In another class called Network, in a method I create 2 instances of Switch, a and b. I am adding the 2 objects to an arraylist of type Switch called switchList. How can I compare the integer values of the objects so I can find duplicates and remove the objects that contain the duplicates. I tried something like this..but I get the wrong result bec the size of the arraylist keeps changing....


thank youuu
 
Paul Sturrock
Bartender
Posts: 10336
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you don;t want duplicates you could use a Set instead.
 
monica praslisa
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried with Set and using equals. It compared the objects, not the integers. I tried with contains also, same issue.. Ideas?
 
Campbell Ritchie
Marshal
Posts: 55672
161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you override your equals() method correctly?

And please beware of saying things like bec and youu whihc can be difficult for some people to understand.
 
monica praslisa
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I dont now how to overwrite the equals method. Can you give me an example that might work in my case ?
I would prefer to use Set and then it wont be this messy.

Thank you!
 
Embla Tingeling
Ranch Hand
Posts: 237
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
m fur wrote:I dont now how to overwrite the equals method. Can you give me an example that might work in my case ?
I would prefer to use Set and then it wont be this messy.


You must override both equals and hashCode, and you need to use a HashSet.

In its simplest form it looks like this,

 
Campbell Ritchie
Marshal
Posts: 55672
161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know you said "simplest form" but that equals method will be very unreliable. It will throw Exceptions if a null reference is passed or anything which isn't a Switch. I don't usually like "instanceof" in equals() methods, but this will be more reliable, provided you never extend the Switch class.The bit about instanceof will go "false" if a null or something which isn't a Switch is passed. Then the && will stop the right-hand half of the expression even being tried because the JVM already "knows" the whole expression will be false.

By the way, m fur, it's not "overwrite" but "override". Two apparently similar words but they mean something different.
 
monica praslisa
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you all ! I managed to solve the problem in a different way. But I will remember the equal tips . Thank you !
 
Campbell Ritchie
Marshal
Posts: 55672
161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well done
 
Embla Tingeling
Ranch Hand
Posts: 237
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:I know you said "simplest form" but that equals method will be very unreliable. It will throw Exceptions if a null reference is passed or anything which isn't a Switch.


I don't agree.

In my view, an equals method which is called with null or the wrong type should throw an exception! This is because this usually indicates a severe error condition that should be brought to the programmer's immediate attention. An equals method which silently returns false is far more unreliable. The bug that slipped through equals is then likely to show up somewhere else down the line where it may be far harder to catch.

I know the general contract for equals requires it to silently return false when called with null or the wrong type. But that's the general contract and I reserve the right to impose a stricter contract in my code. But in order to avoid heated debates with other developers I usually first implement a traditional equals according to the general contract and then put in these two assertions,



This usually satisfies everybody.
 
Campbell Ritchie
Marshal
Posts: 55672
161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Disagree.

An overridden method is a refinement of its superclass method. That means that feasibility of the superclass method always implies feasibility of the subclass method. A method which throws an exception is claiming to be infeasible.

That means:
  • The Object#equals method does not throw an Exception
  • An overridden equals() method should not throw an Exception
  • A supposedly overridden equals() method which might throw an Exception breaches the contract of feasibility and is not a refinement
  • An equals() method which might throw an Exception does not really override the Obejct#equals() method at all
  •  
    Campbell Ritchie
    Marshal
    Posts: 55672
    161
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Embla Tingeling wrote:

    This usually satisfies everybody.
    No, that always makes it worse.
     
    Mike Simmons
    Ranch Hand
    Posts: 3090
    14
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I would have to disagree with Campbell based on the "always". It's true that Embla's code violates the Object.equals() API, strictly speaking. But that's not the end of the world, and there can be other benefits that outweigh this. You do realize that Sun's own classes sometimes violate inherited APIs, right? Sometimes they even do it intentionally, and with good reason. It's a matter of tradeoffs.

    For those of us who favor rejecting null values at earliest opportunity, an equals() method that accepts nulls is just hiding errors. Embla's code makes some assumptions about the conditions it's to be run under, and those assumptions are quite clear on reading the code, and generate informative error messages if those assumptions are violated. (Well, unless assertions aren't run. See below.)

    Personally, my main objection to Embla's code was that the separate null check is unnecessary. It's already covered by the instanceof check. It does result in a more informative error message, which is probably what Embla was going for. There's a tradeoff here of being informative vs. being unnecessarily verbose. If you do want to be more informative, you might as well just put that info in a message that's printed to the user (see below).

    Two related additional objections are: Java language asserts aren't run by default, and Java language asserts are not very familiar to many programmers, having largely been supplanted by the rise of JUnit asserts (as well as those from other frameworks). Both of these are addressed if you're working for a company (or other entity) with a culture that does favor Java language asserts, and where you make sure that such asserts are automatically run as part of the build and/or continuous integration. It's not difficult to add a -ea flag to any invocation of the "java" executable - but it is something that's easy to forget.

    Personally I'd be happy to violate the equals() API to ensure prompt error reporting. But I'd probably do it with a custom library to guarantee both execution, and informative error messages. For example:

     
    Embla Tingeling
    Ranch Hand
    Posts: 237
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mike Simmons wrote:Personally, my main objection to Embla's code was that the separate null check is unnecessary. It's already covered by the instanceof check. It does result in a more informative error message, which is probably what Embla was going for. There's a tradeoff here of being informative vs. being unnecessarily verbose. If you do want to be more informative, you might as well just put that info in a message that's printed to the user (see below).


    The reason I use both is for convenience. Then it's possible to immediately know which of the checks was violated. And assertions are only active during development. In production code they're removed (by Java) so there's no performance impact at all.
     
    Campbell Ritchie
    Marshal
    Posts: 55672
    161
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I still disagree. The general contract for equals() says "some other object", not object of the same type, and also says specifically that it accepts null values as arguments. It cannot (obviously) be called on a null object.

    Agree there are mistakes in the standard Java API, though. And if you had told me the general contract for the equals() method was mistaken, I would consider that.
     
    Embla Tingeling
    Ranch Hand
    Posts: 237
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Disagree.

    An overridden method is a refinement of its superclass method. That means that feasibility of the superclass method always implies feasibility of the subclass method. A method which throws an exception is claiming to be infeasible.

    That means:
  • The Object#equals method does not throw an Exception
  • An overridden equals() method should not throw an Exception
  • A supposedly overridden equals() method which might throw an Exception breaches the contract of feasibility and is not a refinement
  • An equals() method which might throw an Exception does not really override the Obejct#equals() method at all


  • Where did you get this idea from? Subtypes can both be extensions and constraints of the supertype, even at the same time. Whether it's okay is a question of what the supertype contract looks like.

    Sun has defined a general contract for equals but nothing prevents you from adding an amendment if it's in the best interest of your program. In this case the amendment states that a subtype overriding equals is allowed to assert that the passed parameter points to an object and that the object is of the expected type. A very reasonable proposition indeed. Nothing forces you to let your own classes accept bad input silently.

    Take another example, hashCode. Say you override equals and equality is based on mutable state. The general contract now dictates that you must supply a matching hashCode override. But if you do you're inviting disaster. You can enter objects into any hash based collection and it will work fine. It will work fine up to the point when an object's state changes. Then the integrity of the whole collection will be compromised and it will show all sorts of strange behavior.

    The above can easily by fixed by adding an amendent to Sun's general contract. You allow the hashCode method to assert that it's never called. This means the assertion will throw whenever an object is inserted into a hash based collection and this is exactly what you want because this object isn't fit to be in such a collection.

     
    Embla Tingeling
    Ranch Hand
    Posts: 237
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:And if you had told me the general contract for the equals() method was mistaken, I would consider that.


    The general contract isn't mistaken but it requires classes to silently accept being violated. If you're not prepared to have that in your program you add an amendment to the general contract giving you the right to suckerpunch any perpetrator.

    Sun doesn't design your programs, you do.
     
    Campbell Ritchie
    Marshal
    Posts: 55672
    161
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sun do design the general contract for their classes; you are using that part which comes from the Object class. It might be mistaken, but was obviously designed so you can have nulls and reference types of "other types" and still compare them for equality. Particularly required in the Collections framework.
     
    Embla Tingeling
    Ranch Hand
    Posts: 237
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Sun do design the general contract for their classes; you are using that part which comes from the Object class. It might be mistaken, but was obviously designed so you can have nulls and reference types of "other types" and still compare them for equality. Particularly required in the Collections framework.


    Sun has designed the standard library and introduced the general contract, I don't dispute that. But nothing prevents you from imposing a stricter contract on your own program.

    The stricter contract is in effect during development only. In production code the restriction is lifted and the general contract is in effect. And if your program works with the stricter contract, it works with the general contract too, so no harm has been done. The difference is that it's now a better program. The stricter contract has very likely helped you catch bugs that otherwise still would be lurking somewhere.
     
    Campbell Ritchie
    Marshal
    Posts: 55672
    161
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If you revert to the general contract when you let the code loose, I am happy with that.

    What you describe is a laxer contract, however. By excluding nulls from your argument types, you make it easier to write the method.

    Contract between me and my builder: Yes, Campbell, I will repair your wall, if you pay me £300.

    Excluding nulls is a bit like the builder saying, yes, Campbell, I will repair your wall for £300 as long as it is made of ordinary bricks. Under certain circumstances he can decline to do the work, for example if he finds the walls made of specially hard bricks (many houses round here are built with very hard bricks). This is not a stricter contract because he can throw a HardBrickException to me . . .



    . . . and I can't throw a hard brick back at him


    A stricter contract would mean I can tell him to repair the wall even if it is made of concrete blocks.
     
    Embla Tingeling
    Ranch Hand
    Posts: 237
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:If you revert to the general contract when you let the code loose, I am happy with that.


    Why does that make you happy? You've established during development that your program works fine with the stricter regime. This means it will work fine in production too regardless of whether the restrictions are lifted or not. The reason for lifting the restrictions is performance. It costs you some to enforce the restrictions so when you've made sure they're abided by you can as well remove them.


    What you describe is a laxer contract, however.


    Whatever. I call it stricter because it bounces some custumers who were let in before.

    And how you characterize the amendment to the general contract doesn't really change anything.
     
    Campbell Ritchie
    Marshal
    Posts: 55672
    161
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It's laxer because you can get rid of your awkward customers and only deal with the easy ones . . .
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!