
 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
August 9, 1999. This issue covers:

         * Using Coordinate Transformations With the Java2D(tm) API
         * Using List Collections Efficiently


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
USING COORDINATE TRANSFORMATIONS WITH THE JAVA2D(TM) API

In the Java(tm) language, you can use the Graphics class in the AWT 
(Abstract Window Toolkit) to draw graphical entities such as lines, 
text, and images. The Java 2 Platform introduced a new class for 
graphics rendering, Graphics2D. This new class is a subclass of 
Graphics. It extends the capabilities of the Graphics class in 
areas such as geometry, color management, text layout, and 
coordinate transformations. These enhanced graphics features are 
part of the Java2D(tm) API.

Let's look at an example of using coordinate transformations:

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import javax.swing.*;
    
    class myComponent extends JComponent {
        private static final int N = 300;
    
        public Dimension getPreferredSize() {
            return new Dimension(N, N);
        }
    
        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D)g;
    
            AffineTransform aft = AffineTransform.
                getRotateInstance(Math.PI, N / 2, N / 2);
            g2d.setTransform(aft);
    
            Font f = new Font("monospaced", Font.BOLD, 24);
            g2d.setFont(f);
            String s = "testing";
            g2d.drawString(s, 100, 100);
            FontMetrics fm = getFontMetrics(f);
            int h = fm.getHeight();
            int w = fm.stringWidth(s);
            g2d.drawLine(100, 100 + h, 100 + w, 100 + h);
        }
    }
    
    public class graph2d {
        public static void main(String args[]) {
            JFrame f = new JFrame("testing");
            f.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
    
            JPanel p = new JPanel();
            p.add(new myComponent());
            f.getContentPane().add(p);
    
            f.pack();
            f.setVisible(true);
        }
    }

The example draws some text in a window. The text's font style is 
bold and its font size is 24-point. The example also draws a line 
under the text. The actual drawing is done relative to an instance
of the Graphics2D class, an abstract class that extends Graphics.
Because Graphics2D is abstract, you can't create an instance of it
directly, but you must subclass it in some way. This example uses 
an internal class, "sun.awt.image.BufferedImageGraphics2D",
for this purpose. You can see this if you add a line:

    System.out.println(g);

just inside the paint method. The paint method uses a parameter of 
type Graphics rather than Graphics2D, so casting to the
subclass is necessary.

Notice the coordinate transformation in the example. There's a
300 x 300 window, and a rotation transform centered around (150,150)
is specified. The rotation is for PI radians. If you remember your
trigonometry, a circle is divided into 2*PI (about 6.28) radians,
and so a rotation of PI radians is one-half of this, or 180 degrees 
out of a total of 360 degrees.

The net effect of this rotation is to draw the text upside down,
with the underline above the text. In other words, the text and line
are transformed before they are drawn.

Other kinds of transformations that are available in the Graphics2D
context include translation and scaling.

USING LIST COLLECTIONS EFFICIENTLY

Collection classes such as ArrayList are relatively new Java
features. These classes implement a collection interface,
that is, an abstract data type that represents a collection.
Two implementations of the list interface are ArrayList
and LinkedList.

The various list class implementations have performance tradeoffs. 
To see what some of these tradeoffs are, let's look at three short 
examples. Each example creates and uses an ArrayList or a LinkedList,
depending on which statement in the example is used to create the 
object. Try running each example as is, that is, using an ArrayList. 
Then run the LinkedList version by commenting out the statement that 
creates an ArrayList and uncommenting the statement that creates a 
LinkList.

The first example simply adds elements to the list structure:

    import java.util.*;
    
    public class list1 {
        public static void main(String args[]) {
            List lst = new ArrayList();
            //List lst = new LinkedList();
            final int N = 25000;
            for (int i = 0; i < N; i++)
                lst.add(new Integer(i));
        }
    }

The second example adds elements and then looks them up via "get":

    import java.util.*;
    
    public class list2 {
        public static void main(String args[]) {
            List lst = new ArrayList();
            //List lst = new LinkedList();
            final int N = 25000;
            for (int i = 0; i < N; i++)
                lst.add(new Integer(i));
            for (int i = 0; i < N; i++)
                lst.get(i);
        }
    }
    
The third example adds elements and then deletes the first element 
in the list until all are gone:

    import java.util.*;
    
    public class list3 {
        public static void main(String args[]) {
            List lst = new ArrayList();
            //List lst = new LinkedList();
            final int N = 25000;
            for (int i = 0; i < N; i++)
                lst.add(new Integer(i));
            for (int i = 0; i < N; i++)
                lst.remove(0);
        }
    }

The running times of these programs are:

                   ArrayList   LinkedList

    list1 (add)       0.4          0.4

    list2 (get)       0.4         21.3

    list3 (remove)    6.9          0.4
    

So adding new elements is pretty fast for either type of list. For
the ArrayList, doing random lookup using "get" is fast, but for
LinkedList, it's slow. It's slow because there's no efficient way 
to index into the middle of a linked list. When removing elements,
using ArrayList is slow. This is because all remaining elements in 
the underlying array of Object instances must be shifted down for
each remove operation. But here LinkedList is fast, because deletion 
can be done simply by changing a couple of links. So an ArrayList 
works best for cases where you're doing random access on the list, 
and a LinkedList works better if you're doing a lot of editing in 
the middle of the list.

An ArrayList uses space more effectively than a LinkedList. That's
because a LinkedList uses an auxiliary data structure to store 
each list element. These data structures are instances of an 
internal class of the form:

    class Entry {
        Object element;
        Entry next;
        Entry previous;
    }


The point of this exercise is not to convince you to use either 
ArrayList or LinkedList. Instead it's to make the point that there 
are substantial differences in how the different list 
representations perform. The same is true in other areas of the 
collection classes. For example, HashSet and TreeSet are two ways 
of representing sets. The first uses a hash table, the second a 
tree structure. There are tradeoffs between the two representations.

One basic programming tip with collection classes is to program in
terms of interfaces rather than specific classes. For example, you
might say:

    List lst = new ArrayList();

and then use "List" everywhere in your application, such as when
declaring method parameter types. If you do this, you can readily
change ArrayList to LinkedList (or even to your own list
implementation) at some later point.

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only.  To remove your name from the list,
see Subscribe/Unsubscribe below.


- FEEDBACK
Comments?  Send your feedback on the JDC Tech Tips to:

jdc-webmaster


- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member.  To unsubscribe from JDC Email,
go to the following address and enter the email address you wish to
remove from the mailing list:

http://developer.java.sun.com/unsubscribe.html


To become a JDC member and subscribe to this newsletter go to:

http://java.sun.com/jdc/


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://developer.java.sun.com/developer/TechTips/index.html


- COPYRIGHT
Copyright 1999 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright.  For more information, see:

http://developer.java.sun.com/developer/copyright.html


The JDC Tech Tips are written by Glen McCluskey.

JDC Tech Tips 
August 9, 1999










