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 / GUI / January 2004

Tip: Looking for answers? Try searching our database.

ActionEvent Performance Issue

Thread view: 
Jim Cobban - 11 Dec 2003 18:46 GMT
I am trying to handle ActionEvents spawned by various components in a dialog
panel in an efficient way.  Perhaps I am missing something but I cannot find
an example of how to do this.

The examples I have found use setActionCommand on JButtons or JTextFields to
assign an action command String to the component.  This String is then
passed in the ActionEvent to actionPerformed method of the supplied
ActionListener.  This method looks something like:

   public void actionPerformed(ActionEvent ev)
   {
String actionCommand = ev.getActionCommand();
if (actionCommand == SAVE)
{  // apply updates to the Register element
    performSaveAction();
}  // apply updates to the Register element
else
if (actionCommand == SAVE_AS)
{  // apply updates to the Register element
    performSaveAsAction();
}  // apply updates to the Register element
else
if (actionCommand == CANCEL)
{  // finished with dialog
    frame.doDefaultCloseAction();// close the dialog without updating
}  // finished with dialog
else
if (actionCommand == EDIT_FIELD)
{  // pop up dialog to edit attributes of Field
    performEditFieldAction();
...
What bugs me about this implementation is that I cannot replace the series
of if-then-else statements with a switch statement to branch directly to the
function to be performed.  That is because the interface for
setActionCommand specifies that its parameter must be a String, rather than
an Object.  If it were an Object then I could pass in an Integer containing
the desired case statement value.

The only alternative that I can see is to associate a separate Action with
each JButton or JTextField, which I feel is excessive overhead.  Using
setActionCommand, I need merely implement the ActionListener interface
within the class creating the dialog, as opposed to creating a separate
class implementing Action corresponding to each component in the panel.

Signature

Jim Cobban   jcobban@magma.ca
34 Palomino Dr.
Kanata, ON, CANADA
K2M 1M1
+1-613-592-9438

Steve W. Jackson - 11 Dec 2003 19:39 GMT
>:I am trying to handle ActionEvents spawned by various components in a dialog
>:panel in an efficient way.  Perhaps I am missing something but I cannot find
[quoted text clipped - 39 lines]
>:within the class creating the dialog, as opposed to creating a separate
>:class implementing Action corresponding to each component in the panel.

There are pros and cons to the public nature of the actionPerformed
method that's shared by a variety of items, as well as for separate ones
for each.  So I'll skip that area for this reply.

As to your wish to use a switch, this is the same complaint I've long
had with C, which is the basic syntax foundation for Java.  But it's
probably simple to work around it for your particular use.  Simply set
the action command string to a number.  If you want a 1, use "1".  Then,
in your actionPerformed code, you can extract it via something like:

int value = Integer.parseInt(ev.getActionCommand());

You'll have to work out the NumberFormatException details to cover a
non-numeric value, of course, or other details.  But this would allow
you to use a switch if you preferred.  Of course, judicious arrangement
of your else-if alternatives can give you about the same performance in
most cases -- YMMV.

= Steve =
Signature

Steve W. Jackson
Montgomery, Alabama

Skippy - 12 Dec 2003 10:55 GMT
> >:What bugs me about this implementation is that I cannot replace the series
> >:of if-then-else statements with a switch statement to branch directly to the
> >:function to be performed.  That is because the interface for
> >:setActionCommand specifies that its parameter must be a String, rather than
> >:an Object.  If it were an Object then I could pass in an Integer containing
> >:the desired case statement value.

switch(actionCommand.hashcode())
{
      case SAVE_AS.hashcode(): [...];
}

just a brainwave
Antti S. Brax - 12 Dec 2003 11:11 GMT
a@b.invalid wrote in comp.lang.java.gui:
> switch(actionCommand.hashcode())
> {
>        case SAVE_AS.hashcode(): [...];
> }
>
> just a brainwave

    SAVE_AS.hashcode() is not a constant and therefore can not be
    used as a value in a case statement.

Signature

Antti S. Brax - asb(at)iki.fi   Rullalautailu pitää lapset poissa ladulta
  http://www.iki.fi/asb/          http://www.cs.helsinki.fi/u/abrax/hlb/

Jim Cobban - 12 Dec 2003 22:36 GMT
> a@b.invalid wrote in comp.lang.java.gui:
> > switch(actionCommand.hashcode())
[quoted text clipped - 6 lines]
> SAVE_AS.hashcode() is not a constant and therefore can not be
> used as a value in a case statement.

Furthermore hashcode does not map to a small range of integers, and
therefore could not be efficiently implemented by javac.  If your case
values are not fairly contiguous the compiler has to either emit
if-then-else code or else construct a hash table.
Alan Moore - 13 Dec 2003 04:50 GMT
>I am trying to handle ActionEvents spawned by various components in a dialog
>panel in an efficient way.  Perhaps I am missing something but I cannot find
[quoted text clipped - 39 lines]
>within the class creating the dialog, as opposed to creating a separate
>class implementing Action corresponding to each component in the panel.

You're talking about something that happens when a user clicks on a
button; performance is not an issue.
Jim Cobban - 15 Dec 2003 19:15 GMT
> You're talking about something that happens when a user clicks on a
> button; performance is not an issue.

That is a reasonable point.  I do not like being forced to write code in an
obviously inefficient way even if it is not on a performance critical path.
More significantly, perhaps, I find a switch statement to be more
self-documenting of the intention of the code.  Since the intention is to
select one of several more or less equal pieces of code to execute based
upon a value, if-then-else is simply not the most desirable construct to
employ.  For that matter although I personally use a formatting style in
which all of the ifs in an if-then-else string are at the same indentation
level, that is not the standard convention.  If I apply a pretty-formatter
to my code or allow my editor to apply standard formatting, the later cases
will soon scroll off the screen to the right.  Using if-then-else logic
forces me to declare that some of the buttons on my panel are more
"important" than others.

Perhaps if there was some obvious reason why the argument of
setActionCommand is better as a String rather than on Object this wouldn't
bug me.  But since the actual String value is never used, at least in
Localized code, I honestly don't see the point.  The only thing that is ever
done with the argument is to compare its reference to a reference to one of
the defining Strings.  That would work regardless of what type of Object it
was.
Alan Moore - 15 Dec 2003 20:58 GMT
>Perhaps if there was some obvious reason why the argument of
>setActionCommand is better as a String rather than on Object this wouldn't
[quoted text clipped - 3 lines]
>the defining Strings.  That would work regardless of what type of Object it
>was.

Oddly enough, I ran into this issue myself the other day, when I
wanted to use a Typesafe Enum as the action command.  I suspect it was
lack of imagination that drove that choice more than anything else.
Jon A. Cruz - 16 Jan 2004 17:56 GMT
> For that matter although I personally use a formatting style in
> which all of the ifs in an if-then-else string are at the same indentation
[quoted text clipped - 3 lines]
> forces me to declare that some of the buttons on my panel are more
> "important" than others.

There's a simple fix for that.

In general, just put the 'else' and 'if' on the same line. All the
formatters I use then in the context of 'else if' along with the
original 'if' will have everything at the same level.

> Perhaps if there was some obvious reason why the argument of
> setActionCommand is better as a String rather than on Object this wouldn't
> bug me.  But since the actual String value is never used, at least in
> Localized code, I honestly don't see the point.

The point is that with String.equals() you don't have to have identical
objects. You can derive them at runtime, pull them from a file and
substring, read them from network IO and substring, etc.

Even if they chose objects instead of Strings, you'd still have the same
issue with '==' versus '.equals', where the definition of equivalence
comes into play.
Gregory A. Swarthout - 16 Dec 2003 00:31 GMT
> I am trying to handle ActionEvents spawned by various components in a dialog
> panel in an efficient way.  Perhaps I am missing something but I cannot find
[quoted text clipped - 13 lines]
>  }  // apply updates to the Register element
>  else ...

Very nasty to use == to compare strings.

Greg
Thomas A. Russ - 16 Dec 2003 23:21 GMT
> Very nasty to use == to compare strings.
>
> Greg

Not necessarily.  If the strings have been "intern"ed using the
String.intern() method, then you can safely use == to compare them.  As
it happens, all literal strings have this property.

Signature

Thomas A. Russ,  USC/Information Sciences Institute

Gregory A. Swarthout - 17 Dec 2003 18:38 GMT
> > Very nasty to use == to compare strings.
> >
> > Greg
>
> Not necessarily.  If the strings have been "intern"ed using the
> String.intern() method, then you can safely use == to compare them.

Not necessarily.  Check out
http://www.javaworld.com/javaworld/javaqa/2003-12/01-qa-1212-intern.html
for the
explanation on why this can't always be counted on.

Greg
Thomas A. Russ - 17 Dec 2003 19:58 GMT
> > > Very nasty to use == to compare strings.
> > >
[quoted text clipped - 7 lines]
> for the
> explanation on why this can't always be counted on.

I guess I missed some subtle point there, but it seems to me the article
referenced above just discusses whether interned strings with no
references to them can be garbage collected.

It never indicated that the use of == on interned strings was rendered
unsafe.  In fact, I think the opposite point can be inferred -- namely
that as long as you maintain a reference to the string, then the == test
will succeed.  If that were not true, then the entire motivation for
having the intern method in the first place would disappear.

Following some of the promising links in the article just served to
confirm the information about object identity for constant strings.  My
conclusion based on that is that it is, in fact, safe to use == on
interned strings.  For example, the conclusion to the reference to
section 3.10.5 of the Java Language Specification notes:

* Literal strings within the same class (?8) in the same package (?7)
   represent references to the same String object (?4.3.1).
* Literal strings within different classes in the same package represent
   references to the same String object.
*  Literal strings within different classes in different packages
   likewise represent references to the same String object.
*  Strings computed by constant expressions (?15.28) are computed at
   compile time and then treated as if they were literals.
*  Strings  computed at run time are newly created and therefore
   distinct.
*  The result of explicitly interning a computed string is the same
   string as any pre-existing literal string with the same contents.

That seems to cover all of the cases that are of interest.  The only way
that garbage collection enters into this is if there are no references
to the string, which would also seem to mean that it does not appear
anywhere in the system as a constant.  In fact, the example program used
in the link took care to create the string from a character so as to
avoid having the string constant present to inhibit GC.

Signature

Thomas A. Russ,  USC/Information Sciences Institute

Filip Larsen - 17 Dec 2003 23:20 GMT
> > If the strings have been "intern"ed using the
> > String.intern() method, then you can safely use == to compare them.
>
> Not necessarily.  Check out

http://www.javaworld.com/javaworld/javaqa/2003-12/01-qa-1212-intern.html
> for the explanation on why this can't always be counted on.

Would you please explain where in the article it is claimed that
intern'ed strings not always can be compared with the == operator?

Regards,
Signature

Filip Larsen

Roedy Green - 18 Dec 2003 00:02 GMT
>Would you please explain where in the article it is claimed that
>intern'ed strings not always can be compared with the == operator?

Think he is referring to the limits on the total number of interned
strings in various JVMS. It might be as low as 64K.  That is still big
enough for a many applications such as the Replicator which makes use
of interned Strings to conserve space and speed up compares.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Gregory A. Swarthout - 18 Dec 2003 18:00 GMT
> > > If the strings have been "intern"ed using the
> > > String.intern() method, then you can safely use == to compare them.
[quoted text clipped - 6 lines]
> Would you please explain where in the article it is claimed that
> intern'ed strings not always can be compared with the == operator?

"As you can see, s1 is interned and later garbage collected. s2
represents the same string value but is re-interned as a new object.
In other words, Java does not prevent the "same" interned String from
being different objects at different times."

Since == compares object references, not the contents of the string,
it can return false under specific, deterministic situations.  Why
compare Strings by a method that *almost* always returns the same
value as .equals() when .equals() itself returns the results you need
100% of the time?

Greg
Filip Larsen - 19 Dec 2003 18:18 GMT
http://www.javaworld.com/javaworld/javaqa/2003-12/01-qa-1212-intern.html

> > Would you please explain where in the article it is claimed that
> > intern'ed strings not always can be compared with the == operator?
[quoted text clipped - 6 lines]
> Since == compares object references, not the contents of the string,
> it can return false under specific, deterministic situations.

No, the == operator cannot return false and the article does not claim
this.

The article claims (as you quote) that the underlying object id may be
different for two otherwise equal and intern'ed strings if those two
strings exists on "opposite sides" of a period with no reference to the
string in between. From this behaviour, however, it is not possible to
end up with a scenario where the == operator will "fail" due to this (if
you indeed can construct such code please post it here). Only code that
assumes or depends on the value of System.identityHashCode() for
intern'ed string to remaining fixed over time will be affected by this
behaviour.

> Why compare Strings by a method that *almost* always returns the same
> value as .equals() when .equals() itself returns the results you need
> 100% of the time?

I agree that equals in general should be preferred over the ==
operation. This is not because the == operator doesn't work, but because
canonicalization (sp?) of an object should be a class implementation
detail hidden as much as possible.

Regards,
Signature

Filip Larsen

Jon A. Cruz - 16 Jan 2004 17:43 GMT
>  else
>  if (actionCommand == CANCEL)
[quoted text clipped - 12 lines]
> an Object.  If it were an Object then I could pass in an Integer containing
> the desired case statement value.

      "We should forget about small efficiencies, say about 97% of the
time: premature optimization is the root of all evil." - Donald Knuth

First question I have is how much more efficient is a switch statement
in this specific case than a if-else structure? What's the actual
performance difference you see in different runtime environments?

Second question would be how much performance is enough performance? In
response to a user action, you usually don't care about things down into
single-digit milliseconds or microseconds. Remember, you don't want to
be optimizing the sytem idle loop.

Then there's the minor point of how you should maybe restructure your
checks.

try changing to

else if ( CANCEL.equals(actionCommand) )
{
...
}
else if ( EDIT_FIELD.equals(actionCommand) )
...

Remember, string literals are objects too.

Also, one of the first things VM's usually do for String.equals() is
check the hashcode (which is a static int) for mismatches. So in the
case of a string mismatch, all that is needed is a simple int compare.
Combine this with some hotspot style VM and you might be suprised at the
performance you actually get.


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



©2009 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.