This issue presents tips, techniques, and sample code for the following topics:
Using Coordinate Transformations With the Java2DTM API
In the JavaTM 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 Java2DTM 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.
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":
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.
The Java Developer ConnectionSM Tech
Tips are written by Glen McCluskey.
|