📄 tij0090.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0089.html">Prev</a> | <a href="tij0091.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Types
of collections
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
standard Java 1.0<A NAME="Index776"></A>
and 1.1 library comes with a bare minimum set of collection classes, but
they’re probably enough to get by with for many of your programming
projects. (As you’ll see at the end of this chapter, Java 1.2<A NAME="Index777"></A>
provides a radically redesigned and filled-out library of collections.)
</FONT><a name="_Ref348399519"></a><a name="_Toc375545354"></a><a name="_Toc408018570"></a><P></DIV>
<A NAME="Heading252"></A><H3 ALIGN=LEFT>
Vector<P><A NAME="Index778"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is quite simple to use, as you’ve seen so far. Although most of the time
you’ll just use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addElement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to insert objects,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elementAt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to get them out one at a time, and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elements( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to get an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Enumeration</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to the sequence, there’s also a set of other methods that can be useful.
As usual with the Java libraries, we won’t use or talk about them all
here, but be sure to look them up in the electronic documentation to get a feel
for what they can do.
</FONT><P></DIV>
<A NAME="Heading253"></A><H4 ALIGN=LEFT>
Crashing
Java
<P><A NAME="Index779"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
Java standard collections contain a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method so they can produce a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
representation of themselves, including the objects they hold. Inside of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
for example, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
steps through the elements of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and calls
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for each one. Suppose you’d like to print out the address of your class.
It seems to make sense to simply refer to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(in
particular, C++ programmers are prone to this approach):
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: CrashJava.java</font>
<font color="#009900">// One way to crash Java</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> CrashJava {
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> "CrashJava address: " + <font color="#0000ff">this</font> + "\n";
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Vector v = <font color="#0000ff">new</font> Vector();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 10; i++)
v.addElement(<font color="#0000ff">new</font> CrashJava());
System.out.println(v);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It
turns out that if you simply create a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CrashJava</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and print it out, you’ll get an endless sequence of exceptions.
However, if you place the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CrashJava</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects in a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and print out that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as shown here, it can’t handle it and you don’t even get an
exception; Java just crashes. (But at least it didn’t bring down my
operating system.) This was tested with Java 1.1<A NAME="Index780"></A>.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What’s
happening is automatic type conversion for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s.
When you say:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">"CrashJava
address: " + this
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
compiler sees a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
followed by a ‘
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">something
that’s not a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so it tries to convert
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
It does this conversion by calling
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which produces a <A NAME="Index781"></A><A NAME="Index782"></A>recursive
call. When this occurs inside a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it appears that the <A NAME="Index783"></A><A NAME="Index784"></A>stack
overflows without the exception-handling mechanism getting a chance to respond.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you really do want to print the address of the object in this case, the
solution is to call the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method, which does just that. So instead of saying
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you’d say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
(This only works if you're directly inheriting from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or if none of your parent classes have overridden the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method).
</FONT><a name="_Toc375545355"></a><a name="_Toc408018571"></a><P></DIV>
<A NAME="Heading254"></A><H3 ALIGN=LEFT>
BitSet</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
<A NAME="Index785"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is really a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of bits, and it is used if you want to efficiently store a lot of on-off
information. It’s efficient only from the standpoint of size; if
you’re looking for efficient access, it is slightly slower than using an
array of some native type.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
addition, the minimum size of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is that of a long: 64 bits. This implies that if you’re storing anything
smaller, like 8 bits, a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will be wasteful, so you’re better off creating your own class to hold
your flags.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
a normal
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the collection will expand as you add more elements. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
does this as well – sort of. That is, sometimes it works and sometimes it
doesn’t, which makes it appear that the Java version 1.0 implementation of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is just badly done. (It is fixed in Java 1.1.<A NAME="Index786"></A>)
The following example shows how the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BitSet
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">works
and demonstrates the version 1.0 bug:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Bits.java</font>
<font color="#009900">// Demonstration of BitSet</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Bits {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Random rand = <font color="#0000ff">new</font> Random();
<font color="#009900">// Take the LSB of nextInt():</font>
<font color="#0000ff">byte</font> bt = (<font color="#0000ff">byte</font>)rand.nextInt();
BitSet bb = <font color="#0000ff">new</font> BitSet();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 7; i >=0; i--)
<font color="#0000ff">if</font>(((1 << i) & bt) != 0)
bb.set(i);
<font color="#0000ff">else</font>
bb.clear(i);
System.out.println("<font color="#0000ff">byte</font> value: " + bt);
printBitSet(bb);
<font color="#0000ff">short</font> st = (<font color="#0000ff">short</font>)rand.nextInt();
BitSet bs = <font color="#0000ff">new</font> BitSet();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 15; i >=0; i--)
<font color="#0000ff">if</font>(((1 << i) & st) != 0)
bs.set(i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -