ArrayList vs LinkedList

Best Username Ever,

Wouldn’t that not work if the OP needed to add two Interactables of the same kind into his set?

Colton

I don’t think so. By “kind” do you mean class? Sets can’t store duplicates. Bags and Lists can, but storing multiple references to the same instance sounds like a source of bugs.

Car c1 = new Car(), c2 = new Car();
Building b = new Building();
collection.add(c1);
collection.add(c2); // Fine so far
collection.add(b);
collection.add(c1); // Does this get stored once or twice? Is it updated once or twice per update to c2?

Ah, I did a test, and you’re right! Very interesting, because my understanding of Sets was that they stored unique entries, and I guess individually allocated Objects of any kind are considered unique to the HashSet. Maybe this is common knowledge, but I just took a data structures course, and since that’s what I was taught, I figured it would hold true for this scenario. :stuck_out_tongue: Cool! :smiley:


package test;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetTest 
{   
    public static void main(String args[])
    {
        Set<Clown> clowns = new HashSet<Clown>();
        
        clowns.add(new Clown());
        clowns.add(new Clown());
        clowns.add(new Clown("Jack"));
        clowns.add(new Clown("Jill"));
        clowns.add(new Clown("Jill"));
        
        Iterator i = clowns.iterator();
        
        while (i.hasNext())
        {
            Clown c = (Clown)i.next();
            System.out.println(c.getName());
        }
    }
}

class Clown
{
    private String name;
    
    public Clown(String name)
    {
        this.name = name;
    }
    
    public Clown()
    {
        name = "John";
    }
    
    public String getName()
    {
        return name;
    }
}


run:
Jill
John
John
Jill
Jack
BUILD SUCCESSFUL (total time: 0 seconds)

Best regards,
Colton

It get stored twice, notice that what you store are references to objects, not the actual objects. :slight_smile:

About updating, collection won’t update anything, since all it holds is a memory adress, if what’s in that adress changes, it doesn’t need to be updated anywhere else.

:slight_smile:

Oh yes, that makes perfect sense now. Forgive me; I’m still learning! :] This is highly educational for me though, far beyond what school has ever taught me.

On a side note, Best Username, I’ve decided I may wish to start using Bags in my own games! ;] I know credit goes to kappa for it, but thank you for introducing me! I’m looking forward to doing some test cases to see how much faster it works in comparison to ArrayLists.

Best regards,
Colton


class Clown
{
    private String name;
    
    public Clown(String name)
    {
        this.name = name;
    }
    
    public Clown()
    {
        name = "John";
    }
    
    public String getName()
    {
        return name;
    }

+    public boolean equals(Object obj) {
+        if(obj instanceof Clown) {
+            Clown that = (Clown)obj;
+            return this.name.equals(that.name);
+        }
+        return false;
+    }

+    public int hashCode() {
+         return this.name.hashCode();
+    }
}


run:
Jill
John
- John
- Jill
Jack
BUILD SUCCESSFUL (total time: 0 seconds)

Riven,

Thanks! I guess I should jot down that one in my programming notebook for future purposes… my game engine could probably use a bit of that, now that I think about it :o

EDIT: Wait, so I was technically right about this? :o

Well, actually, I suppose without implementing equals() the hash set would work just fine for the OP’s purposes, but it just depends on whether or not that kind of functionality is added into the class. If it were me and I wanted to get the supposed performance benefits, then I guess I wouldn’t add it into classes I know would be added into the set, but now that Riven basically just ripped my code a new one and taught me a lesson I think I’d much rather implement things that way!

Colton

I don’t quite get how performance has anything to do with it. Implementing .equals(…) and .hashCode( ) is critical for HashMap/HashSet to work.

Sorry Riven! I meant the performance of the HashSet, not the classes to be placed within the HashSet! :stuck_out_tongue:

It’s just that he was saying he could get certain performance benefits with using the HashSet for these purposes, but it seems to me that if the objects passed into the set are equal, then this wouldn’t be useful in a situation like the OP described, where he has essentially a stage of Interactables; my point was, what if there are two Interactables with the same attributes? They wouldn’t be preserved in the set if this were the case, making the data structure worthless. Thus, in order to get the performance benefits he was talking about, he would have to omit those two methods you wrote in my code, which circumvented the set recognizing two objects with identical attributes. Otherwise, it would retain what makes it a set, and without the equals() and hashCode() methods, it seems to do little more than act as a list for those half-complete objects.

That’s just my reasoning, anyway; I could be very wrong. :-X

Colton

You could argue that java.lang.Object was poorly designed, as tieing the root class of a type hierarchy to some collection based on hashes, seems rather awkward. I mean, you don’t see Object defining compareTo(…) or compare(…, …) to directly tie in with TreeMap or PriorityQueue…

Anyway, enough off-topic-ness. Your ‘Clown’ class threw me off, it’s commonly accepted that two clowns with the same name are indistinguishable, hence the implementation of .equals(…) .

See Riven, now you’re just losing me; I’m still a fledgling! XD

I understand why you wrote the equals method now, and it’s clear that things go on under the hood that derive from Object that I wasn’t previously aware of (though I have seen equals() and hashCode() before in other programs). Was my reasoning regarding the HashSet reasonable though, or is there something else that I’m missing? It seems impractical–if not impossible–to me given that whatever objects are passed into it are implemented with equals and hashCode. By the way, thanks for taking the time to teach me a few things! :smiley:

Colton

The first part was serious (and it indeed adds a burden to developers… adding those methods to every class that will ever have instances of it in a HashSet / HashMap :-X)

The second part was a bad joke, sorry.

Oh, now what you’re saying makes sense. Whoops! Yeah, that’s a rather seeming design flaw. Luckily, I don’t work with them very often, and when I do, I find I’m using it in an application where I don’t have to worry about things like that (a recent example is a map of tiles to characters for my level save system, which maps tile types to Unicode characters that get outputted into a file).

I also get your joke now… very funny :wink: It’s times like these when you wish you could hear someone’s vocal intonation! :smiley:

Best regards,
Colton

Those clowns are attracting the zombies!

More seriously:

No-one uses HashSet for this operation because the only properties of HashSet which we want - the enforced uniqueness and fast lookup time - come at a rather large cost compared to simply using ArrayList in a particular way, and that particular way just happens to be exactly how you’d use it to write a game. If we’re looking at pure performance from memory and typical usage, ArrayList totally wins, every time. Besides, again in typical usage in a game, you almost always want the order of the elements added into the collection to remain fixed, for various reasons that will become apparent to you eventually, and therefore you’d want to use a LinkedHashSet if you were dead set on using a Set implementation.

Cas :slight_smile:

Note that Big O notation doesn’t take alot of real-world stuff into account.

princec,

I disagree. There are many ways in which collections can be used in a game. To imply that ArrayList is the best and only way is just way wrong.

Are you going to tell me that if I have a bunch of objects reporting that they can be removed and then removing them from a collection is better implemented with an ArrayList (with its O(n) search) is better than HashMap/Set (with its O(1)) search?

There are drawbacks to ArrayList, like removing and searching and adding to a full list. The big benefit ArrayList is its fast indexing. I am actually a big fan of LinkedHashSet and LinkedHashMap, as they act like Hash’s but keep their objects ordered.

*Thanks to the person who corrected me when I wrote O(logn) search time for Hash in previous post
thanks
jose

Surely it does, however, people easily mistake Big O notation for something that gives an indication of performance. It’s about performance degradation for a growing data set.

O(n2) could easily outperform O(1) for a data set smaller than 1 billion, in which case the algorithm featuring O(1) is barely usable for any real world problem.

Yes. Big O notation tells you nothing about absolute performance.

Ok so lets write up some code and test this out then. Instead of all of us arguing lets all of us work together here and figure this stuff out. That way we all leave smarter, happier, and agreeing on the test results. :slight_smile:

I will take a crack at writing up a test or two… not to prove anyone’s point but to get to bottom of which collection is good for what circumstances.

thanks
jose

There is no way to benchmark this. You can write two different benchmarks and have two different winners.

The point I was making is that you shouldn’t look at the Big O notation the way you did. You should pick the algorithm that bests suits your needs (performance wise or maintainability wise). Don’t let the ‘performance degradation under growth’ determine what you’re going to use, unless you experience performance issues for bigger data sets.

The reverse is also true, don’t always pick the fastest algorithm, because it’s probably not your bottleneck in the first place.

The problem is that in this case we are talking about Collections, which have the same/similar interface. That means the maintaiability it damn near the same. If you do not go by big-o then please elaborate?

thanks
jose