Class and array

I second JL235. You can also use more “specific” ArrayList with

List<Person> myArray = new ArrayList<Person>();

so everytime you need your Person class (by get(int) method), there is no need to cast it. ArrayList always returns Object type.

Actually, this just becomes slow casting under the hood. Templates in Java are kind of crap. If you’re worried about performance, better to make a subclass of ArrayList that accepts only a certain type of class. Then you can deal with the type casting yourself and make it maximally efficient.

Actually I doubt that his use case will need this kind of performance tuning. In fact I would advise not to worry about performance at all unless you have something working and you are experienced enough to fully understand the implications of certain changes (like synchronized vs unsynchronized collections)

Genrics, not templates, don’t always require casts (there are ways to avoid them). Casts are also far from slow. There is also no reason why they couldn’t be optimized out with runtime tracing (although that is purely speculation). However optimizing your algorithms in order to reduce their time complexity will have a far greater impact on performance.

Your sub-classing technique would make your code less maintainable whilst having a very minor impact on performance (if any).

Yes, I meant generics, not templates. Apologies.

Ask Kev his opinion of generics and you’ll get much more fire and brimstone than from me. Personally I’m going to stop arguing now, since it’s already been done many times before.

Have a look at this:
http://www.facsim.org/node/77

[quote]Before getting into the details, here’s the main problems with Java’s generics:

At run-time, all generic type information is lost. For example, a Stack cannot be distinguished (at run-time) from a Stack - they both become just a Stack.
At run-time, all type parameter instances are converted to/from Object references, meaning that there is a high upcast/downcast overhead (not to mention a high boxing-unboxing overhead, if using primitive types) when using generics.
All instances of generic classes have the exact same static members.
It is not possible to throw generic exceptions (generic classes derived from Throwable).
[/quote]

I just generified my entire game library :slight_smile: Bliss.

Cas :slight_smile:

Thanks for you suggestion. Did you mean create a class which extending ArrayList? can give an example? I’ve searched it but they don’t give code. (sorry for silly question) :wink:

Just dont bother! Stick to whats working for you and get something done before trying to optimize at this level. You wont get anywhere if you start this now. Trust me: “premature optimization is the root of all evil”

Okay, I will agree with this. Just stick with the Vector or whatever that you’ve got already.

But FYI, here is something like what I was referring to:


public class MonkeyArrayList extends ArrayList
{
    public Monkey get(int i)
    {
        return (Monkey) super.get(i);
    }

    public void add(Monkey m)
    {
        super.add(m);
    }

    //etc.
}

You honestly think this is faster?

I don’t get it. Generics does exactly the same, except that is doesn’t do the cast in the ArrayList, but at the callsite. What you do is moving the cast from the usual callsite into your own (newly created) callsite. For HotSpot it’s exactly the same code, while your subclass even adds another level of indirection. I’m stumped.

Well you’ll have half as many casts, because the setters don’t also need a cast. Or maybe I’m wrong and generics don’t do a cast at that point, but I thought they did.

But really in the end no I don’t think this is worth worrying about if your reason for doing it is speed. I would argue that in some situations it has more clarity, and you avoid some of the other issues mentioned in that article (like you can have MonkeyArrayList.staticVar separate from ApeArrayList.staticVar, for example).

Aye Eli is a little misled on the application of generics. Generics don’t make things faster or slower; but they do provide an extra level of compiler checkery which can make some code neater. Some code not so neat. Roll on project Coin which will sort it out.

Generics are like salt: use sparingly but effectively.

Also, casts in the JVM are much more cunning than you think.

Cas :slight_smile:

I’ve got to stop arguing points that I don’t even really follow myself. :stuck_out_tongue:

I used to do that :slight_smile: Now I just moan about Java being shit because I can’t use it on the BASTARD IPHONE. Grrr. etc.

Cas :slight_smile:

Moan on steve jobs instead for not supporting java lol.

Jobsy doesn’t actually mind Java at all. He’s pretty good pals with Larry too. The problem was the legacy dealings Apple had with Sun. I have a feeling things might look a little rosier in the not too distant future.

Cas :slight_smile:

Just to satisfy my own curiosity I just did a quick test (1M add, get, remove) for generic and non-generic Vectors and found no appreciable time difference. Phew! I was hoping there wouldn’t be!

I’m surprised others failed to pick up on this. ‘public void add(Object value)’ still exists, so your method fails to be a full replacement to Generics. Your method is only ever called if you know a Monkey is passed in at compile time as otherwise it’ll bypass it and call the old add. For example…


    MonkeyArrayList monkeys = new MonkeyArrayList();
    monkeys.add( "a string" );
    monkeys.add( 42 );
    monkeys.add( new Monkey() );

The above is perfectly valid and successfully executes.

To be fair you will get an exception when calling ‘get’ due to the cast. But consider this: if a non-Monkey is in the list then the error must have occurred at the point where the non-Monkey is added to the list (it shouldn’t have been added). Because the type error only occures when calling ‘get’ (on performing the cast) then you have moved the error away from where it has occured. The error is now more misleading as you’d expect everything inside of ‘monkeys’ to already be a Monkey.

Secondly you will also get an error when using an iterator or when using a foreach loop (I believe foreach loops are just iterators + syntax sugar). This is because the iterator calls ‘get’, but this is implementation specific! I could build a ‘SpecialList’ which returns an iterator which does not call ‘get’. If the ‘MonkeyArrayList’ extends my ‘SpecialList’ then there should not be a runtime error when using iterators or foreach loops.

Generics does not suffer from these issues. Finally yours offers no compile time validation. Generics does.

Very good point, I wrote this quickly without thinking. To take a real-world situation, have a look at BodyList from Phys2D. It isn’t an ArrayList, it has an ArrayList. I honestly momentarily debated that with myself before typing the example, obviously I made the wrong choice. You definitely wouldn’t want to subclass ArrayList, that would make no sense.


/*
 * Phys2D - a 2D physics engine based on the work of Erin Catto. The
 * original source remains:
 * 
 * Copyright (c) 2006 Erin Catto http://www.gphysics.com
 * 
 * This source is provided under the terms of the BSD License.
 * 
 * Copyright (c) 2006, Phys2D
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 *  * Redistributions of source code must retain the above 
 *    copyright notice, this list of conditions and the 
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above 
 *    copyright notice, this list of conditions and the following 
 *    disclaimer in the documentation and/or other materials provided 
 *    with the distribution.
 *  * Neither the name of the Phys2D/New Dawn Software nor the names of 
 *    its contributors may be used to endorse or promote products 
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 */
package net.phys2d.raw;

import java.util.ArrayList;

/**
 * A typed list of <code>Body</code>
 * 
 * @author Kevin Glass
 */
public class BodyList implements java.io.Serializable
{
	/** The elements in the list */
	private ArrayList elements = new ArrayList();
	
	/**
	 * Create an empty list
	 */
	public BodyList() {
		
	}
	
	/**
	 * Create a new list containing the elements specified
	 * 
	 * @param list The list of elements to add to the new list
	 */
	BodyList(BodyList list) {
		elements.addAll(list.elements);
	}
	
	/**
	 * Add a body to the list
	 * 
	 * @param body The body to add
	 */
	public void add(Body body) {
		elements.add(body);
	}
	
	/**
	 * Get the number of elements in the list
	 * 
	 * @return The number of the element in the list
	 */
	public int size() {
		return elements.size();
	}
	
	/**
	 * Remove a body from the list
	 * 
	 * @param body The body to remove from the list 
	 */
	public void remove(Body body) {
		elements.remove(body);
	}
	
	/**
	 * Get a body at a specific index
	 * 
	 * @param i The index of the body to retrieve
	 * @return The body retrieved
	 */
	public Body get(int i) {
		return (Body) elements.get(i);
	}
	
	/**
	 * Clear all the elements out of the list
	 */
	public void clear() {
		elements.clear();
	}
	
	/**
	 * Check if this list contains the specified body
	 * 
	 * @param body The body to look for
	 * @return True if this list contains the specified body
	 */
	public boolean contains(Body body) {
		return elements.contains(body);
	}
	
	/**
	 * Get a list of bodies containing all of the bodies in this
	 * list except those specified
	 * 
	 * @param others The bodies that should be removed from the contents
	 * @return The list of bodies excluding those specified
	 */
	public BodyList getContentsExcluding(BodyList others) {
		BodyList list = new BodyList(this);
		list.elements.removeAll(others.elements);
		
		return list;
	}
	
	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		String str = "[BodyList ";
		for (int i=0;i<elements.size();i++) {
			str += get(i)+",";
		}
		str += "]";
		
		return str;
	}
}


Thanks for the advice. Honestly I didn’t bother this. My current small project is using ArrayList (Ball is my own defined class) and it works well. I call get() every update() time so every Ball can draw themself and no lag.

I just want to know and take a glance about optimization for future need :slight_smile: