• Post Reply Bookmark Topic Watch Topic
  • New Topic

Rationale for Set not containing a get(Object 0) method?  RSS feed

 
Mike Curwen
Ranch Hand
Posts: 3695
IntelliJ IDE Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Anyone?

I can't believe it wouldn't be useful. As TreeSet (or HashSet) currently stands, the only way to retrieve a single item from the Set is to iterate over all of them, using equals() to see if you have the 'right one'.

Maybe I'm using the wrong Collection object.

* I want a 'bag' of items.
* When I iterate over them, I want to iterate in the order they were inserted.
* Each object the 'bag' contains has it's own identifying 'number', so the containing bag's idea of what index its stored under does not matter.
* i should be able to remove() an item, based on its identifying 'number'.
* size() should return the number of items in the bag, and not the number of spaces (empty or not) in the bag


At first I figured ArrayList. But ArrayList.size() would report the number of null spaces as well, so the last * condition above is not satisified.

perhaps I should use ArrayList anyways, and just provide an over-ridden (or alternate) method to size() that only counts non-null entries ?

Grr. and I went an implemented Comparable!
 
Jason Menard
Sheriff
Posts: 6450
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can't believe it wouldn't be useful.
If you already had a reference to Object o, why would you need to get it from the Set?
* When I iterate over them, I want to iterate in the order they were inserted.
The new LinkedHashSet class from j2se 1.4 provides an ordered set, although no indices.
At first I figured ArrayList. But ArrayList.size() would report the number of null spaces as well, so the last * condition above is not satisified.
How about a LinkedList? The remove() method shifts indices when an item is removed.
[ July 11, 2003: Message edited by: Jason Menard ]
 
Frank Carver
Sheriff
Posts: 6920
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It appears your object "number" is acting as a key to the collection, so this sounds more like a Map, than a set.
I would suggest extending something like java.util.LinkedHashMap, and adding a method like
public void add(MyType thing)
{
put (thing.getNumber(), thing);
}
can you think of a reason why that won't work?
 
Jamie Robertson
Ranch Hand
Posts: 1879
MySQL Database Suse
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The ArrayList size() method does "Returns the number of elements in this collection" which is what I think you were asking for( wanted to make sure you didn't think it was the allocated size of the underlying Object array).
If not, the only way it would count null/empty values is if you added them to the list. So you could go with extending the ArrayList's add method to not add null objects or If you need to add empty/null values to the list, but not count them in the size, then I think you could extend the ArrayList class to accomplish the last piece of functionality by tracking incoming and outgoing nulls:
keeps track of nulls coming in and out:

Jamie
[ July 11, 2003: Message edited by: Jamie Robertson ]
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Curwen:
Anyone?

I can't believe it wouldn't be useful. As TreeSet (or HashSet) currently stands, the only way to retrieve a single item from the Set is to iterate over all of them, using equals() to see if you have the 'right one'.

Why can't you use the contains() method instead. This returns true if the Object is in the set.


Maybe I'm using the wrong Collection object.

Any Collection object that inherits from AbstractCollection has the aforementioned contains() method.

* I want a 'bag' of items.
* When I iterate over them, I want to iterate in the order they were inserted.
* Each object the 'bag' contains has it's own identifying 'number', so the containing bag's idea of what index its stored under does not matter.
* i should be able to remove() an item, based on its identifying 'number'.
* size() should return the number of items in the bag, and not the number of spaces (empty or not) in the bag

I think someone already mentioned that the size() function doesn't count the whole amount of memory that the Container has allocated for it. It only counts the number of spaces that are used. This may include null elements, if the object supports them, but the only reason, that I can think of, for a container to have null elements is if you knowingly added them yourself.
Of course, you may call an add() method with a null reference. The easiest way to avoid this is to use a Container that throws a NullPointerException when this occurs.
If you are worrying about removing objects, you don't need to. As far as I know, none of the Collections count an object after you remove() it and then calls size().
[ July 11, 2003: Message edited by: Layne Lund ]
 
Mike Curwen
Ranch Hand
Posts: 3695
IntelliJ IDE Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yah, I was having a bad day when I posted. Maybe I'm still having one.

Part of this is me not being a very good architect.

I want to code the simplest possible Cart. Cart contains LineItem. LineItems contains a Product. And I'm hoping to use Collection classes as much as possible.

Product has all the usual things like name, price, size, colour, etc. It also contains variable (custom) data for each Product. So it's not a typical product in a normal Amazon sense. When you order one of our Products, you get a form to fill out. This data should be retained in the cart so that it can be edited.

LineItem basically contains a Product a quantity and a line discount.

Cart contains LineItems, plus methods to calculate the cart total.

So far alright, because that's all just talk. Implementation has always been my problem.

Unlike a real-life Safeway shopping cart, my cart has at very least the implied order of insertion. But simple indexing will not work, because if I check off the first three cart items, and click 'delete' (on a cart summary jsp page, for example), I can't just say:
cart.remove(0);
cart.remove(1);
cart.remove(2);
This would remove the 1st, 3rd and 5th items.

So the "line number" can't change with addition and deletion of items. So ArrayList (whose index changes) is out, right? (OR else I can only delete one thing at a time).

I'm not sure why, but TreeSet appealed to me, because it had order and didn't have that index trouble. I could implement Comparable (my 'number' would do the ordering). And then I could use the object remove() method, by creating a blank LineItem object (with no Product) like:
cart.remove(new LineItem(0));
etc, etc...
Which is why (Jason) this wouldn't be the case:
"If you already had a reference to Object o, why would you need to get it from the Set?"

I didn't "really" have the object, but I had stupidly overriden LineItem's equals() method to only compare the 'number'. It was kinda cool, but I think in the end, stupid.
I think Frank has the right idea, but for right now I'm stuck with 1.3.1, which doesn't have the LinkedHashMap.

For now, i'm using ArrayList and just don't have anything that deletes more than one object at at a time.

Background: "We need this web site change done in two days.. there are no specs.. GO!" . That was Thursday around 11am. Both myself and the senior developer wanted to start moving towards a 'better' version of our site, rather than constantly 'patching' the old one, and we had already done preliminary head-space stuff about Products, Carts, etc, etc. So it was super-crunch time, and of course, nothing concrete had been thought about. The idea of the Cart was cool (currently we use a String[] for the cart, no objects at all), but we hadn't thought about it too deeply.
 
Mike Curwen
Ranch Hand
Posts: 3695
IntelliJ IDE Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For Layne:
>Why can't you use the contains() method instead.
>This returns true if the Object is in the set.
Because that only indicates the object is there, it doesn't give me the object... yah, I know.. if I have the object to send to contains(), don't I already have it? Right.. see discussion above.

>If you are worrying about removing objects, you
>don't need to. As far as I know, none of the
>Collections count an object after you remove()
>it and then calls size().
That was exactly what I was doing. DOH! Will the list of things I don't know/don't understand EVER END??
 
Joel McNary
Bartender
Posts: 1840
Eclipse IDE Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My solution to the problem was to use dynamic attribute-tagging in the JSP. Instead of Check-boxes, I had a Quantity field that you could use to update the quantities directly on the Summary page. The user then clicks a button and the cart re-calcualtes everything, deleting items if the quantity was set to zero.
From JSP:

Yes, I know now that I could use Beans instead of scriptlets, but I didn't know that then, and that's beside the point.
In the processing servlet, I had:

From this, I had both the id of the object and the requested quantity. Since the cart was a List, I just iterated over the list looking for that ID and then updating the quantity. If the Quantity was 0, I just removed the item. No worry about the index in the list, since I was basing my search on the id of the object.
I could had built a hash and keyed the objects on their ids, but the lists involved are small enough that the back-end work was not worth the gained benefit.
While this is not an exact parallel (I'm not using check-boxes), I'm sure that you could implement something similar to achieve your desired effect.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Simply want to agree with the prior suggestions to try out the LinkedHashMap...
 
Mike Curwen
Ranch Hand
Posts: 3695
IntelliJ IDE Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yah, I think in my confusion, I was trying to force a List to act like a Map (and at times, vica-versa).

So maybe I should refactor my LineItem back into having it's own 'number', meaning the LineItem will internally contain a unique id (or 'line number'), and not depend on the containing ArrayList's index (which is after all, changeable). That way I can either chose a very quick 'List' implementation of a Cart, as Joel did, or do a Map like Frank suggested (and I think I prefer).

If I use a plain Map (because I'm stuck with 1.3.1) I'll have an un-ordered cart, but perhaps I can supply a getOrderedListing() method that will return the LineItems in order.
 
Mike Curwen
Ranch Hand
Posts: 3695
IntelliJ IDE Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey I just realized something...

Our production server bit it about 2 hours ago, and everyone else is running around trying to fix it. They've decided it's not worth their time to try and revive a box whose boot sector appears corrupted, so they're going to make the move to our "new" production box. This was scheduled for a few weeks from now.

And the JDK on the new box?? 1.4.1

Yay LinkedHashMap !
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well LinkedHashMap would've been my main answer initially, but since Frank already posted it, I had nothing else to say. However now that you've posted more details I'm not sure you really need a Map at all. If you want to remove 0, 1, 2 in one step (or close to it), the simplest way is:

Another option is something like

Depending on what sorts of other processing you need to do, you may or may not be able to rearrange things along one of these patterns. retaining some sort of "absolute" index whose values are constant after other elements are deleted may still be useful. If so, I think a TreeMap whose keys are Integers is also a possiblity. Good luck...
 
Ken Blair
Ranch Hand
Posts: 1078
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mr. Yingst breaks out the wickedly obvious logic that most people never even think about. Seem to have more than a few solutions, seems to me its more or less a problem with bad design.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!