Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2008

Tip: Looking for answers? Try searching our database.

Generics

Thread view: 
Todd - 06 Mar 2008 14:47 GMT
Hello,

I have been reading about generics to determine if there is a way to
accomplish what I _assumed_ could be done.  From what I can tell, what
I would like to do is not possible, but, honestly, generics are
confusing to me.

What I would like to do is have one method, say getValue(), that
returns each member of a mixed collection in its correct type.  I have
determined the the object type when storing it into the map, so it is
available to me for use in the getValue() method.  I thought that
something along the lines of

public <T> T getValue()
{
   return ObjectType.cast( value );
}

would work.  However, I am having no luck coming up with anything that
compiles, let alone runs, to return typed objects at runtime using a
single method.

I have searched through the group, but have not found anything that
clarifies for me whether this concept can be implemented.

Is there a way to return typed objects from a mixed collection at
runtime using a single method?  If so, could you provide me some tips
as to how to create the method or class with method to do so?

Thanks in advance,
Todd
Daniel Pitts - 06 Mar 2008 15:27 GMT
> Hello,
>
[quoted text clipped - 27 lines]
> Thanks in advance,
> Todd
Generics are determined either by the caller, or by the instantiater,
not by the returner.
Now, if did this:

public <T> T getValueAs(Class<T> type) {
    return type.cast(value);
}

you might have better luck.

Or, better off:

class MyRef<T> {
   T value;
   public MyClass() {
   }

   public void setValue(T value) {
      this.value = value;
   }

   public T getValue() {
      return value;
   }
}

MyRef<String> string = new MyRef<String>();
string.setValue("Hello!");

assert string.getValue().equals("Hello!");

What is it exactly that you are trying to do?  I mean, what feature are
you adding that needs this?

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Todd - 06 Mar 2008 15:41 GMT
On Mar 6, 8:27 am, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.net> wrote:
> > Hello,
>
[quoted text clipped - 66 lines]
> --
> Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

I am reading a data file that contains a mix of doubles, double
arrays, integers, integer arrays, booleans and strings.  Each entry
has a name (its key) and value associated with it.  I know that when I
request "NumEntries" that the return will be an integer, so I thought
I would code something like

Integer numEntries = getValue( "NumEntries" );

and have an integer return.  Further example, knowing "Description"
contains a string I would code something like

String description = getValue( "Description" );
Christian - 06 Mar 2008 16:30 GMT
Todd schrieb:
> On Mar 6, 8:27 am, Daniel Pitts
> <newsgroup.spamfil...@virtualinfinity.net> wrote:
[quoted text clipped - 17 lines]
>
> String description = getValue( "Description" );

Sometimes you are better off without using generics.
it might be better to use something like:

String getValue(String key) {}
int getIntValue(String key) {}

and not use generics for this.

Christian
Todd - 06 Mar 2008 19:34 GMT
I figured out how to do it!!

Thanks for the ideas,
Todd
Lew - 07 Mar 2008 01:15 GMT
> I figured out how to do it!!

Exactly how?

Signature

Lew

Todd - 10 Mar 2008 17:15 GMT
> > I figured out how to do it!!
>
> Exactly how?
>
> --
> Lew

All,

Here is the source that I came up with to do this.  Please critique
it.  I would like to have concrete comments as to how it could be
improved   For example, I read a TechTip that said it would be better
to use a scanner or at least String.split() in lieu of the
StringTokenizer.

Todd

//=========================================

import java.util.StringTokenizer;
import java.util.Vector;

/**
*
* @author heidenthal
*/
public class DataRecord
{
   public DataRecord( String value, String description )
   {
       // Fill the data record with the passed information
       this.value = new String( value );
       this.description = new String( description );

       // The record value needs to have its data type defined
       // for the typed return of the value
       dataType = determineType( value );
   }

   public String getDescription()
   {
       return description;
   }

   public <T> T getValue()
   {
       @SuppressWarnings( "unchecked" )  // TODO check cast and don't
suppress
       Class <T> type = dataType.getClassType();

       return type.cast( dataType.castValue( value ) );
   }

   public Class getClassType()
   {
       return dataType.getClassType();
   }

   private DataType determineType( String value )
   {
       dataType = DataType.STRING;

       // boolean type
       if( isBoolean( value ) )
       {
           dataType = DataType.BOOLEAN;
       }
       else if( isInteger( value ) )         // int type
       {
           dataType = DataType.INTEGER;
       }
       else if( isDouble( value ) )          // double type
       {
           dataType = DataType.DOUBLE;
       }
       else if( isDoubleArray( value ) )     // double[] type
       {
           dataType = DataType.DOUBLE_ARRAY;
       }

       return dataType;
   }

   private boolean isBoolean( String value )
   {
       if( value.equalsIgnoreCase( "true" ) ||
           value.equalsIgnoreCase( "false" ) )
       {
           return true;
       }

       return false;
   }

   private boolean isInteger( String value )
   {
       try
       {
           Integer.parseInt( value );
           return true;
       }
       catch( Exception exception )
       {
           return false;
       }
   }

   private boolean isDouble( String value )
   {
       try
       {
           Double.parseDouble( value );
           return true;
       }
       catch( Exception exception )
       {
           return false;
       }
   }

   private boolean isDoubleArray( String value )
   {
       if( value.contains( "{" ) && value.contains( "}" ) )
       {
           return true;
       }

       return false;
   }

   private String value;
   private String description;
   private DataType dataType;

   @SuppressWarnings( "unchecked" )  // TODO check cast and don't
suppress
   private enum DataType
   {
       STRING( String.class )
       {
           String castValue( String value )
           {
               return value;
           }
       },

       BOOLEAN( Boolean.class )
       {
           Boolean castValue( String value )
           {
               return Boolean.parseBoolean( value );
           }
       },

       INTEGER( Integer.class )
       {
           Integer castValue( String value )
           {
               return Integer.parseInt( value );
           }
       },

       DOUBLE( Double.class )
       {
           Double castValue( String value )
           {
               return Double.parseDouble( value );
           }
       },

       DOUBLE_ARRAY( Double[].class )
       {
           Double[] castValue( String value )
           {
               Vector<Double> values = new Vector<Double>();

               StringTokenizer tokenizer =
                       new StringTokenizer( value.substring( 1 ),
" }" );
               while( tokenizer.hasMoreTokens() )
               {

values.add( Double.parseDouble( tokenizer.nextToken() ) );
               }

               Double[] valuesArray = new Double[values.size()];
               valuesArray = values.toArray( valuesArray );

               return valuesArray;
           }
       };

       DataType( Class clazz )
       {
           this.clazz = clazz;
       }

       abstract <T> T castValue( String value );

       Class getClassType()
       {
           return clazz;
       }

       private Class clazz;
   }
}

//========================================

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Locale;
import java.util.StringTokenizer;

/**
*
* @author heidenthal
*/
public class DataCollection extends HashMap<String, DataRecord>
{
   public DataCollection( String filename )
   {
       buildDefaultMap( filename );
   }

   public void buildDefaultMap( String filename )
   {
       String line = null;
       InputStream reader =
Class.class.getResourceAsStream( filename );
       try
       {
           BufferedReader bufferedReader =
                   new BufferedReader( new
InputStreamReader( reader ) );
           while( (line = bufferedReader.readLine()) != null )
           {
               // Break the line into the key and data record
               StringTokenizer str = new StringTokenizer( line,"=" );

               // Get the key for the data
               String key =
str.nextToken().trim().toUpperCase(Locale.ENGLISH);

               // Get the record value
               String value = str.nextToken( "=," ).trim();

               // Get the description (if it exists)
               String description = str.nextToken( "\n" ).trim();

               // Create a new data record and add it to the
collection
               DataRecord dataRecord = new DataRecord( value,
description );

               this.put( key, dataRecord );
           }
       }
       catch( IOException ioException )
       {
           System.err.println( "Unable to open " + filename );
           System.err.println( ioException );
       }
   }

   public <T> T get( String key ) throws NullPointerException
   {
       DataRecord dataRecord =
               super.get( key.trim().toUpperCase(Locale.ENGLISH) );

       @SuppressWarnings( "unchecked" )  // TODO check cast and don't
suppress
       Class<T> type = dataRecord.getClassType();

       return type.cast( dataRecord.getValue() );
   }
}
Lew - 11 Mar 2008 01:13 GMT
> import java.util.StringTokenizer;
> import java.util.Vector;

Don't use java.util.Vector.  Use one of the List implementations that replaced
it in 1998, such as ArrayList.

>     public <T> T getValue()
>     {
>         @SuppressWarnings( "unchecked" )  // TODO check cast and don't
> suppress
>         Class <T> type = dataType.getClassType();

The need for an "unchecked" suppression is an indicator that you don't have
the generics quite right.  Don't feel bad; with type erasure it isn't easy to
get generics exactly right, warning-free.

Signature

Lew

Todd - 11 Mar 2008 13:59 GMT
> > import java.util.StringTokenizer;
> > import java.util.Vector;
[quoted text clipped - 14 lines]
> --
> Lew

Lew,

Question about ArrayList vs. Vector.  I remember reading that one
should only use Vector since it is the only collection _guaranteed_ to
be thread-safe.  Is this no longer considered true?

Todd
Owen Jacobson - 11 Mar 2008 14:31 GMT
> > > import java.util.StringTokenizer;
> > > import java.util.Vector;
[quoted text clipped - 14 lines]
> > --
> > Lew

Please don't quote signatures.

> Lew,
>
> Question about ArrayList vs. Vector.  I remember reading that one
> should only use Vector since it is the only collection _guaranteed_ to
> be thread-safe.  Is this no longer considered true?

It depends on what you mean by "thread-safe".  All of Vector's methods
are declared synchronized, which means that only one method may be in
progress on a single Vector at a time.  However, this provides no
guarantees about coherency across multiple method calls, nor
particularly across iteration.

If you need the same promise from a List, you can use
Collections.synchronizedList (backingList) to construct a wrapper
around a List that performs the same synchronization that Vector
does.  However, I've rarely found synchronizing on individual lists to
be all that useful, for the reasons I outlined above.

-o
Mark Space - 11 Mar 2008 21:04 GMT
> Question about ArrayList vs. Vector.  I remember reading that one
> should only use Vector since it is the only collection _guaranteed_ to
> be thread-safe.  Is this no longer considered true?

As Owen said, this is totally untrue.  Vectors are required to be thread
safe, thus requiring synchronization overhead whether you need it or
not.  All other (new) collections have a separate thread-safe version
that you can instantiate optionally if you want thread safety.

Where the heck did you read this drivel?  Seriously, I'm interested in
knowing who is promulgating nonsense about Java.

Thanks in advance.
Andreas Leitgeb - 12 Mar 2008 09:16 GMT
>> Question about ArrayList vs. Vector.  I remember reading that one
>> should only use Vector since it is the only collection _guaranteed_ to
[quoted text clipped - 4 lines]
> not.  All other (new) collections have a separate thread-safe version
> that you can instantiate optionally if you want thread safety.

It was partially untrue, in that Vector is not the only one. But anyway it
is the only one where you have thread-safety concisely, without the extra
boilerplate of Collections.synchronizedWhatever(...).

PS1: If Thread-safety is not an requirement, then Vector is of course
 unnecessarily slower than other Collections.

PS2: If I need to deal with the capacity of a synchronized array-like
 Collection, how would I do this with ArrayList and
 Collections.synchronized*What* ?
RedGrittyBrick - 12 Mar 2008 10:39 GMT
> PS1: If Thread-safety is not an requirement, then Vector is of ...
> PS2: If I need to deal with the capacity of a synchronized ...

PS1: Sony PlayStation.
PS2: Sony PlayStation 2.

For postscripts I prefer the traditional abbreviations:

PS
PPS

and so on.
Mark Space - 14 Mar 2008 20:31 GMT
> PS
> PPS

P. S. = post scriptum, after the writing.

P. P. S. = post post scriptum, after the after writing.

P. P. P. S = post post post scriptum, after the after-after writing.

etc.
Lew - 13 Mar 2008 00:58 GMT
> PS2: If I need to deal with the capacity of a synchronized array-like
>   Collection, how would I do this with ArrayList and
>   Collections.synchronized*What* ?

What do you mean, "to deal with the capacity of a ... Collection"?

For operations on a synchronized List, you use the returned List from the
Collections.synchronizedList() call.

  List <T> synched = Collections.synchronizedList( unsynched );
  ...
  synchronized( synched )
  {
    if ( synched.size() == 0 )
    {
      synched.add( foo );
    }
  }
etc.

Signature

Lew

Andreas Leitgeb - 13 Mar 2008 08:54 GMT
>> PS2: If I need to deal with the capacity of a synchronized array-like
>>   Collection, how would I do this with ArrayList and
>>   Collections.synchronized*What* ?
> What do you mean, "to deal with the capacity of a ... Collection"?

I meant, I had a look at the Javadoc for ArrayList and skimmed over
those of its methods that aren't specified by interfaces.  Only
those that deal with capacity (querying and setting) are specific
to ArrayList. Plus there is also removeRange(), which it inherits
from AbstractList, and thus also isn't available through List-API.
Vector also offers these features.

While I'm not judging the practical value of these, it seems like
Vector was the only threadsafe collection that had removeRange
and a means to get/set the capacity in case a known large number
of items needs to be added, to avoid multiple incremental
re-allocations.
Lew - 13 Mar 2008 14:27 GMT
>>> PS2: If I need to deal with the capacity of a synchronized array-like
>>>   Collection, how would I do this with ArrayList and
[quoted text clipped - 4 lines]
> those of its methods that aren't specified by interfaces.  Only
> those that deal with capacity (querying and setting) are specific

Well, setting, anyway.

> to ArrayList. Plus there is also removeRange(), which it inherits
> from AbstractList, and thus also isn't available through List-API.
[quoted text clipped - 5 lines]
> of items needs to be added, to avoid multiple incremental
> re-allocations.

Why do people insist on calling Vector "thread safe"?  Having synchronized
methods doesn't make it thread safe.

If you set the capacity then add items, you need to explicitly synchronize on
the Vector anyway.  Individual methods' synchronization doesn't extend through
multiple method calls.  There's no advantage to Vector here.

It also happens that removeRange() is a protected method, so relying on it
forces you to extend AbstractList or a subclass.  This is extra work that,
from what you've indicated, doesn't solve your synchronization problem.  Plus
now you have to maintain an extra class instead of simply relying on the Java
API.  Work you'd avoid by using ArrayList and synchronizing explicitly, since
you have to anyway.

I'd just use an ArrayList variable (for the extra methods List doesn't
support), and explicitly synchronize.

Signature

Lew

Lew - 13 Mar 2008 14:32 GMT
Andreas Leitgeb wrote:
>> it seems like
>> Vector was the only threadsafe collection that had removeRange and a
>> means to get/set the capacity in case a known large number
>> of items needs to be added, to avoid multiple incremental
>> re-allocations.

What's wrong with multiple re-allocations?  AIUI, ArrayList grows its capacity
by doubling the array size, so there's not going to be a whole lot of
re-allocation overhead - possibly even less than by manually calling
ensureCapacity(), if you're not at least doubling the internal capacity with
each call.

Signature

Lew

Andreas Leitgeb - 13 Mar 2008 18:18 GMT
> What's wrong with multiple re-allocations?  AIUI, ArrayList grows its capacity
> by doubling the array size,

I didn't intend to cause so much fuss with those few methods that Vector
and ArrayList have, but plain List hasn't.  I dislike fuss, which is
the reason, that when I need something synchronized then I'd rather
use a Vector than any of those Collections that I need to cast spells
on to make synchronized, and then even lose some of the functionality.
If my needs were more complicated, and I'd need extra sync-fuss even
above what the Vector offers, then I can just as well use any other
Collection and do all the sync myself.
Andreas Leitgeb - 13 Mar 2008 17:58 GMT
> Why do people insist on calling Vector "thread safe"?  Having synchronized
> methods doesn't make it thread safe.

I fail to see in which way a Vector was any *less* "thread safe" than
a  Collections.synchronizedList(new ArrayList(...)).

Docu for synchronizedList says:
" Returns a synchronized (thread-safe) ..."
Note, it doesn't say "synchronized and also thread-safe",
but rather seems to consider those two to be like synonyms.

Docu for Vector only says:
" Vector is synchronized.

What operations can I do on a synchronizedList without extra
synchronization-block, that I cannot do on a Vector likewise
and with same level of real thread-safety?
Lew - 14 Mar 2008 01:36 GMT
>> Why do people insist on calling Vector "thread safe"?  Having synchronized
>> methods doesn't make it thread safe.
>
> I fail to see in which way a Vector was any *less* "thread safe" than
> a  Collections.synchronizedList(new ArrayList(...)).

It isn't.

> Docu for synchronizedList says:
> " Returns a synchronized (thread-safe) ..."
> Note, it doesn't say "synchronized and also thread-safe",
> but rather seems to consider those two to be like synonyms.

Yes, and that is one instance of Sun's documentation leading people astray.

Individual methods are synchronized; using two synchronized methods separately
is not inherently thread-safe; consider check-and-set operations.

The OP's problem seemed to call for a check-and-set (check capacity, and
increase if needed, then add()).  Even with Vector or synchronizedList(), this
opens the barn door for a race condition without explicit synchronization.  As
I said, in this case I wouldn't use Vector or synchronizedList(); I'd declare
the variable a plain ArrayList for the extra methods the OP wanted (or just
List, since I think they're not really needed), and dispense with implicit
synchronization altogether.

> Docu for Vector only says:
> " Vector is synchronized.
>
> What operations can I do on a synchronizedList without extra
> synchronization-block, that I cannot do on a Vector likewise
> and with same level of real thread-safety?

None.

ArrayList and synchronizedList() give you Lists without the non-collections
methods of Vector and without Enumeration.  I like synchronizedList() better
than Vector because it lacks unneeded machinery; it Occam's Razors itself into
my heart.

It's not what List has that Vector doesn't; it's what Vector has that List
doesn't that makes me excoriate Vector.

Signature

Lew

Andreas Leitgeb - 14 Mar 2008 11:14 GMT
>> I fail to see in which way a Vector was any *less* "thread safe" than
>> a  Collections.synchronizedList(new ArrayList(...)).
> It isn't.
Ok, so at least I didn't miss anything on factual side :-)

> Individual methods are synchronized; using two synchronized methods separately
> is not inherently thread-safe; consider check-and-set operations.

Now I'm a bit surprised about your definition of "thread-safety",
because in a thread not very long ago, you insisted on static
methods being principially thread-safe, without consideration
of context...

PS: Occam's Razor says "don't buy more than you need" with a
 rather philosophical meaning of buying :-).  Anyway, I don't
 need to buy Vector's extra features. I get them for free.
 Even quite the opposite: synchronizedList costs me more
 characters to type.
Lew - 14 Mar 2008 13:50 GMT
> PS: Occam's Razor says "don't buy more than you need" with a
>   rather philosophical meaning of buying :-).  Anyway, I don't
>   need to buy Vector's extra features. I get them for free.
>   Even quite the opposite: synchronizedList costs me more
>   characters to type.

Typing effort is not part of my metric.  The presence of unneeded machinery is
the consideration.  It isn't ever needed, so why include it when ArrayList is
out there with exactly what's needed?

> Now I'm a bit surprised about your definition of "thread-safety",
> because in a thread not very long ago, you insisted on static
> methods being principially thread-safe, without consideration
> of context...

I insisted that they /could/ be thread-safe, not without consideration of
context.  Don't misrepresent my points.

Signature

Lew

Patricia Shanahan - 13 Mar 2008 15:53 GMT
>>> PS2: If I need to deal with the capacity of a synchronized array-like
>>>   Collection, how would I do this with ArrayList and
[quoted text clipped - 13 lines]
> of items needs to be added, to avoid multiple incremental
> re-allocations.

removeRange is not really needed, because the same job can be done using
only the List interface: myList.subList(from, to).clear();

This sort of operation requires explicit synchronization to prevent any
changes in the list between calculation of the index values and the
clear call.

Patricia
Lew - 12 Mar 2008 03:21 GMT
> Question about ArrayList vs. Vector.  I remember reading that one
> should only use Vector since it is the only collection _guaranteed_ to
> be thread-safe.  Is this no longer considered true?

It was never true, whether some considered it so or not.  The rule prior to
1998 was only to use Vector because it was the only choice.  After that, it
was to use ArrayList unless you needed or wanted the collection to be
inherently synchronized.  Most of the time you don't need thread safety
because the context is not multi-threaded.  So most of the time, the built-in
overhead of Vector's synchronization (much less in modern JVMs) was wasted
overhead.

It remains true since 1998 that if you do want or need to use synchronization
on your List, then Vector is the wrong choice.  The right choice is at least
Collections.synchronizedList( someList ).
<http://java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedLis
t(java.util.List
)>

More sophisticated concurrent algorithms can use the java.util.concurrent
package and its kin.
<http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html>

Signature

Lew



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.