views:

412

answers:

2

Hey, everyone. I'm new to Java and I have 2D LinkedList like this:

LinkedList<LinkedList<String>> albums = new LinkedList<LinkedList<String>>();

Which is filled with data like so:

if (!artist.isEmpty() && !name.isEmpty()) {
    albums.add(new LinkedList<String>());
    albums.getLast().add(artist.toString());
    albums.getLast().add(name.toString());
}

But I want to make sure my list has no duplicate albums. How to check whenever my albums list already contains same pair of artist and name?

+2  A: 

Yes, commenter is right. Create a class Album with artist and name fields and implement equals() (and hashCode()) on them. And then you can use contains() to find the duplicate. Or even consider using a Set (but only if hash code is really defined on your class, since a set is backed by a hash).

Adrian
Is hash() necessary to use the contains() method?
Corey Sunwold
Not on a linked list (but if you ever gonna use a map or set, you Must have one. Just XOR the hash of the artist and name string).
Adrian
The name of method is `hashCode`. It's a defacto standard to implement `hashCode` when you implement `equals`. Strictly speaking `hashCode` is not necessary for `contains` to work.
Alexander Pogrebnyak
"Strictly speaking hashCode is not necessary for contains to work." Agreed. But anyone who fails to keep `hashcode` and `equals` consistent deserves to be hung, drawn and quartered. :-)
Stephen C
+2  A: 

My suggestion would be to create a new class, called Album that looks something like this:

public class Album
{
    private String name;
    private String artist;

    public Album(String name, String artist)
    {
        this.name = name;
        this.artist = artist;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getArtist()
    {
        return artist;
    }

    public void setArtist(String artist)
    {
        this.artist = artist;
    }

    public boolean equals(Object o)
    {
        if (o instanceof Album)
        {
            Album that = (Album)o;
            return album.equals(that.album) && artist.equals(that.artist);
        }
        else
        {
            return false;
        }
    }

    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((album == null) ? 0 : album.hashCode());
        result = prime * result + ((artist == null) ? 0 : artist.hashCode());
        return result;
    }
}

Then you should be able to use contains() to check whether or not the album already exists in the linked list.

Corey Sunwold
Equals **must** take an Object!!! and you should implement hash code.
Adrian
@Adrian: Thanks, I don't program in Java often.
Corey Sunwold
if you add @Override to the method, the compiler will warn you about such errors.
Adrian
thanks everyone, writing a class for this totally makes sense. I don't quite understand how the hashCode() works tho :)
rukoche
Just an observation--with this type of class, don't make them mutable by default; by that I mean if you don't HAVE to, don't define any setters and make your variables final. It's just a good habit to pick up--not a law or anything.
Bill K
@rukoche - the `hashcode()` method override is simply combining the hashcode values for the two fields into a single value. It is required because the class is also overriding `Object.equals(Object)`, and `hashcode` and `equals` must be consistent.
Stephen C
Further to what Bill K says, you should always assume all your variables are "final" unless you have a reason for them not to be. So you should change it to "private final String name;" and "private String artist;". It is highly unlikely that you would ever want to change the name.artist of an album. The benefit of doing this is you do not have to make copies of Albums when you call methods because you can be certain that the they are not modified by the method you called.
TofuBeer