A summary of a pragmatic Java base collection

Source: Internet
Author: User
Tags bitset int size gopher

Java provides a variety of ways to hold objects (or handles to objects). The built-in types are arrays, and in addition, Java's tool library provides some
"Collection Class", using these collection classes, we can accommodate and manipulate our own objects.
statement: This blog content reference from "Java programming thought", the code comes from the book, most of the content is intercepted from the book Array and the first class of objects

The array identifier is actually a handle to a real object, regardless of the type of array used. Those objects themselves are in memory
Created in the heap. Heap objects can be "implicitly" created (that is, by default) or "explicitly" created (that is, explicitly specified, with a new
expression). Part of the heap object (actually the only field or method we can access) is a read-only length (length) member that tells
The maximum number of elements we can hold in that array object. For array objects, the [] syntax is the only alternative access method we can use.

The object array and the base data type array are almost identical in the way they are used. The only difference is that the object array holds the handle, and the base data type array holds the specific values

public class ArraySize {public static void main (string[] args) {//Arrays of objects:weeble[] A;//Null handle weeble[ ] B = new Weeble[5];
Null handles weeble[] c = new Weeble[4];
for (int i = 0; i < c.length i++) c[i] = new weeble ();
Weeble[] D = {new Weeble (), New Weeble (), New Weeble ()}; Compile error:variable a not initialized://!
System.out.println ("a.length=" + a.length);
System.out.println ("b.length =" + b.length); The handles inside the array are//automatically initialized to null:for (int i = 0; i < b.length; i++) System.out.
println ("b[" + i + "]=" + b[i]);
System.out.println ("c.length =" + c.length);
System.out.println ("d.length =" + d.length);
A = D;
System.out.println ("a.length =" + a.length);
Java 1.1 Initialization syntax:a = new weeble[] {new weeble (), New Weeble ()};
System.out.println ("a.length =" + a.length); Arrays of primitives:int[] e;
Null handle int[] f = new int[5];
Int[] g = new int[4]; for (int i = 0; i < g.length; i++) G[i] = I*i;
Int[] H = {11, 47, 93}; Compile error:variable e not initialized://!
System.out.println ("e.length=" + e.length);
System.out.println ("f.length =" + f.length); The primitives inside the array are//automatically initialized to zero:for (int i = 0; i < f.length; i++) SYSTEM.O
Ut.println ("f[" + i + "]=" + f[i]);
System.out.println ("g.length =" + g.length);
System.out.println ("h.length =" + h.length);
e = h;
System.out.println ("e.length =" + e.length);
Java 1.1 Initialization syntax:e = new int[] {1, 2};  System.out.println ("e.length =" + E.length);}
The output is as follows:
b.length = 5
b[0]=null
b[1]=null
b[2]=null b[3]=null b[4]=null c.length
= 4
D.length = 3
a.length = 3
a.length = 2
f.length = 5
f[0]=0
f[1]=0 f[2]=0 f[3]=0 f[4]=0
g.length = 4
h.length = 3
e.length = 3
e.length = 2

Where array A is initialized to a null handle. At this point, the compiler will prevent us from doing anything practical with this handle unless we are
correctly initialized it. Array B is initialized to point to an array of weeble handles, but that array does not actually place any
Weeble object. However, we can still query the size of that array because B points to a legitimate object.

In other words, we know only the size or capacity of an array object, and we don't know how many elements it actually holds.

However, because an array object is automatically initialized to null at the be made early of creation, you can check whether it is null and determine whether a particular array "empty" holds an object. Similarly, an array of base data types is automatically initialized to 0 (for numeric types), null (character type), or False (Boolean type)

The array C shows that we first create an array object, and then assign the Weeble object to all the "vacancies" in that array. The array d reveals
Collection initialization syntax, creating an array object (explicitly with the new command, similar to array c), and then using the Weeble object
Initialized, all work is done in a single statement.
Here's an expression:

A = D;

Showed us how to get a handle to the same array object and assign it to another array object, showing us how to get a handle to the same array object and assigning it to another array object base data type collection
Collection classes can only hold object handles. But for an array, it can hold the basic type of data directly, and can also hold the sentence pointing to the object.
Handle. You can place the value of the base data type into a collection using the wrapper class like Integer or Double.

Whether you place a base type of data into an array or encapsulate it into a class that is in a collection, it involves the problem of execution efficiency. Explicitly
However, if you can create and access an array of basic data types, the efficiency of the former is much higher than that of accessing a collection of encapsulated data.

The return of the array
Let's say we want to write a method now, and we don't want it to just return something, but to return a series of things. At this point, languages like C and C + + complicate the problem because we cannot return an array, only to return a pointer to an array. This is very troublesome, because it is difficult to control the "time" of the array, it is easy to cause memory "vulnerabilities" appear.

Java uses a similar approach, but we can "return an array". Of course, the actual return at this point is still the pointer to the array. But in Java, we never have to worry about the availability of that array-it will automatically exist as long as it is needed. And the garbage collector will automatically clear it when we're done.

public class Icecream {static string[] Flav = {"Chocolate", "Strawberry," "Vanilla Fudge Swirl"
, "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie"};
Static string[] Flavorset (int n) {//Force it to be positive & within bounds:n = Math.Abs (n)% (flav.length + 1);
String[] results = new String[n];
Int[] Picks = new Int[n];
for (int i = 0; i < picks.length i++) Picks[i] =-1;  for (int i = 0; i < picks.length i++) {Retry:while (true) {int t = (int) (Math.random () * flav.length), for (int j = 0; J < I;
J + +) 213 if (picks[j] = = t) continue retry;
Picks[i] = t;
Results[i] = flav[t];
Break
} return results; The public static void main (string[] args) {for (int i = 0; i < i++) {System.out.println ("flavorset (" + i + ") =")
;
string[] fl = Flavorset (flav.length);
for (int j = 0; J < Fl.length; J + +) System.out.println ("T" + fl[j]); }
}
} 

The Flavorset () method creates a String array named results. The size of the array is n--the exact numeric value depends on the arguments we pass to the method. It then randomly picks some "spices" (flavor) from the array Flav and put them into results and eventually returns to results. Returning an array is no different from returning any other object--the final return is a handle.

On the other hand, note that when Flavorset () randomly picks spices, it needs to make sure that a random selection that has previously occurred does not reappear. In order to achieve this goal, it uses an infinite while loop, constantly making random selections until it finds an element that is not in the picks array (and, of course, it can be compared to check if the random selection has occurred in the results array, but the string comparison is less efficient). If successful, add the element, interrupt the loop (break), and then find the next one (I will increment the value). But if T is an array that has already appeared in the picks, use the tabbed continue to jump back two levels, forcing a new T to be selected. This process can be clearly seen with a debugger.

Collection
to accommodate a group of objects, the most appropriate choice should be an array. And if you hold a series of basic data types, you must use arrays.

disadvantage: Unknown type

The disadvantage of using the Java collection is the loss of type information when an object is placed in a collection. This happens because the programmer at the time of the collection did not know exactly what type the user wanted to put into the collection. Indicating that a collection allows only a specific type prevents it from becoming a "general-purpose" tool that can cause trouble to users. To solve this problem, the collection actually holds the handle of some objects of type object.

Of course, also note that the collection does not include basic data types because they are not inherited from "anything."
Java does not allow people to misuse an object that is placed in a collection. If you throw a dog into a cat's collection, you still treat everything in the collection as a cat, so you get an "illegal" error when using that dog. In the same sense, if you try to "sculpt" a dog's handle to a cat, you will still get an "illegal" error during the run.

Class Cat {
private int catnumber;
Cat (int i) {
catnumber = i;
}
void print () {
System.out.println ("Cat #" + catnumber);
}
Class Dog {
private int dognumber;
Dog (int i) {
dognumber = i;
}
void print () {
System.out.println ("Dog #" + dognumber);
}
public class Catsanddogs {public
static void Main (string[] args) {
vector cats = new vector ();
for (int i = 0; i < 7; i++)
cats.addelement (new Cat (i));
Not a problem to add a dog to cats:
cats.addelement (New Dog (7));
for (int i = 0; i < cats.size (); i++)
((Cat) Cats.elementat (i)). Print ();
Dog is detected only at Run-time
}
}
Mistakes sometimes don't show up.
In some cases, the program seems to work correctly, not styling back to our original type. The first case is quite special: the String class gets extra help from the compiler to work properly. As long as the compiler expects a string object, but it does not get one, it automatically invokes the ToString () method defined in Object and capable of being overwritten by any Java class. This method generates a string object that satisfies the requirement and is then used when we need it. Therefore, the whole thing to do in order for the objects of your class to be displayed is to overwrite the ToString () method.
Class Mouse {
private int mousenumber;
Mouse (int i) {
mousenumber = i;
}
Magic method: Public
String toString () {return ' This is
Mouse # ' + mousenumber;
}
void print (String msg) {
if (msg!= null) System.out.println (msg);
System.out.println (
"Mouse number" + Mousenumber);
}
Class Mousetrap {
static void Caughtya (Object m) {
Mouse Mouse = (Mouse) m;//Cast from Object
mouse.print ( "Caught one!");
}
public class Worksanyway {public
static void Main (string[] args) {
vector mice = new vector ();
for (int i = 0; i < 3; i++)
mice.addelement (new Mouse (i)), 216 for
(int i = 0; i < mice.size (); i++) {
/ /No cast necessary, automatic call
//To Object.ToString ():
System.out.println (
"free Mouse:" + Mice.ele Mentat (i));
Mousetrap.caughtya (Mice.elementat (i));
}

You can see the redefinition code for toString () in Mouse. In the second for Loop of main (), you can find the following statement:

System.out.println ("Free Mouse:" +
Mice.elementat (i));

after "+", the compiler expects to see a String object. ElementAt () generates an Object, so the compiler calls toString () by default for the desired string. Unfortunately, it is only for strings that you can get results like this, and no other type of conversion will do that.

The second method of hidden styling has been applied in Mousetrap. The Caughtya () method receives not a Mouse, but an object. It is then styled as a Mouse. Of course, this is a very bold thing to do, because by receiving an Object, anything can be passed to the method. However, if the styling is not correct-if we pass the wrong type-a violation error will be obtained during the run. This, of course, is not checked at compile time, but can still prevent the problem from happening. Note that you do not need to sculpt when using this method:
Mousetrap.caughtya (Mice.elementat (i)); Generating vectors that can automatically discriminate types
A more "robust" scenario is to create a new class with Vector that receives only the
Type, and only the type we want to produce.

class Gopher {private int gophernumber;
Gopher (int i) {gophernumber = i} void print (String msg) {if (msg!= null) System.out.println (msg);
System.out.println ("Gopher number" + Gophernumber);} Class Gophertrap {static void Caughtya (Gopher g) {G.print ("caught one!");} class Gophervector {private Vector v = n
EW Vector (); public void AddElement (Gopher m) {v.addelement (M), public Gopher elementat (int index) {return (Gopher) V.elementat (Inde
x); public int size () {return v.size (),} public static void Main (string[] args) {Gophervector gophers = new Gophervector (
);
for (int i = 0; i < 3; i++) gophers.addelement (new Gopher (i));
for (int i = 0; i < gophers.size (); i++) Gophertrap.caughtya (Gophers.elementat (i)); }
} 

The new Gophervector class has a private member of type vector (there is some trouble with vector inheritance, a reason to know later), and the method is similar to vector. However, it does not receive and generate normal object, only for Gopher objects
Interested.
Since Gophervector only receives one Gopher (gopher), so if we use:
Gophers.addelement (New Pigeon ());
An error message is obtained during compilation. In this way, although it is more depressing from a coding standpoint, you can immediately determine whether the correct type is being used. Note that you do not need to sculpt when using ElementAt ()-It must be a Gopher enumerator

Accommodating a wide variety of objects is the primary task of the collection. In vectors, addelement () is the method we insert into the object, and ElementAt () is
The only way to extract objects. Vector is very flexible, we can choose anything at any time, and can use different indexes to select multiple elements.

If you look at the problem from a higher point of view, you will find a flaw in it: you need to know the exact type of the collection beforehand, otherwise it cannot be used. At first glance, this doesn't seem to matter. But what to do if you decide to use vector at the very beginning, and then decide in your program (to consider the reason for execution efficiency) to change into a List (part of the Java1.2 Collection Library).

We usually think of a repetition device as a "lightweight" object; that is, it takes a very small price to create it. But it is for this reason that we often find that there are some seemingly strange limitations to the repetitive device. For example, some iterations can only move in one direction.
The Java enumeration (enumeration, annotation ②) is an example of a repeating device with these limitations. You can no longer use it except for the following
Do any other thing:

(1) A method called elements () requires a collection to provide us with a enumeration. The first time we call it nextelement ()
, this enumeration returns the first element in the sequence.
(2) Obtain the next object with Nextelement ().
(3) Check if there are more objects in the sequence with hasmoreelements ()

Class Hamster {
private int hamsternumber;
Hamster (int i) {
hamsternumber = i;
}
Public String toString () {return ' This is
hamster # ' + hamsternumber;
}
}
Class Printer {
static void Printall (enumeration e) {while
(e.hasmoreelements ())
System.out.println (
e.nextelement (). toString ());
}
public class Hamstermaze {public
static void Main (string[] args) {
vector v = new vector ();
for (int i = 0; i < 3; i++)
v.addelement (New Hamster (i));
Printer.printall (V.elements ());
}

Study the printing method carefully:

static void Printall (enumeration e) {while
(e.hasmoreelements ())
System.out.println (
e.nextelement ( ). ToString ());

Note that there is no information associated with the sequence type. Everything we have is enumeration. To understand the sequence, a enumeration is sufficient: The next object can be obtained, and it is also known whether the end is reached. Get a series of objects and then traverse them to perform a specific action--a valuable type of programming concept set

V e c t o r
Crash Java
The Java standard collection contains the ToString () method, so they can generate their own String representations, including the objects they hold.
For example, in a vector, ToString () steps and iterates through the various elements of the vector and calls ToString () for each element. Suppose we want to print out the address of our class now. It seems as if a simple reference to this can be (especially the C + + Programmer's inclination to do so):

public class Crashjava {public
String toString () {return
' Crashjava address: ' + this + ' \ n ';
}
public static void Main (string[] args) {
vector v = new Vector ();
for (int i = 0; i < i++)
v.addelement (New Crashjava ());
System.out.println (v);
}

At this point, the automatic type conversion of the string is occurring. When we use the following statement:
"Crashjava Address:" + this
The compiler finds a "+" and something else that is not a string after a string, so it tries to convert this to a string. The conversion is called toString (), which produces a recursive call. If this happens within a Vector, it looks like the stack will overflow, and the control mechanism has no chance to respond at all.
If you do want to print out an object's address in this case, the solution is to invoke the ToString method of object. You do not need to join this at this time, just use super.tostring (). Of course, there is a prerequisite for this: we must inherit directly from Object, or no parent class overrides the ToString method.

B i t S e t
Bitset is actually a Vector composed of "bits". If you want to efficiently save a large number of "open-close" information, you should use Bitset. It only makes sense in terms of size; If you want efficient access, it's slower than using some of the intrinsic types of arrays.

The minimum length of a bitset is the length of a long Integer (long): 64 bits. This means that if we are prepared to save smaller data, such as 8-bit data, then Bitset is wasted. So it's best to create your own class and use it to hold your own logo bits.

S t a C K
A Stack can sometimes also be called a "back in First Out" (LIFO) collection. In other words, the last thing we "press in" on the stack will be the first
A "pop-up". Like all other Java collections, we push and eject the "object", so we have to pop something
To "Sculpt".

Here is a simple stack example that reads each row of an array and presses it into the stack as a string.

public class Stacks {
static string[] months = {"
January", "February", "March", "April",
"may", "June", "July "," August "," September ",
" October "," November "," December "};
public static void Main (string[] args {
stack stk = new stack ();
for (int i = 0; i < months.length i++)
Stk.push (Months[i] + "");
System.out.println ("STK =" + Stk);
Treating a stack as a Vector:
stk.addelement ("The Last Line");
System.out.println (
"element 5 =" + Stk.elementat (5));
SYSTEM.OUT.PRINTLN ("Popping elements:");
while (!stk.empty ())
System.out.println (Stk.pop ());
}
}

Each row of the months array is inherited into the stack by push (), which is later removed with pop () from the top of the stack. The point to be stated is that the Vector operation can also be performed on a Stack object. This may be determined by the nature of the inheritance of the--stack "belonging" to a Vector. Therefore, the operation of vectors can also be done against the Stack, such as the ElementAt () method

h A s h t a b l e
Vector allows us to choose from a range of objects with a number, so it actually associates numbers with objects.
But if we want to choose a series of objects based on other criteria. The stack is an example of this: its selection criterion is "The last thing to push onto the stack."
This "Select from a series of objects" concept can also be called a "map", "dictionary" or "associative array." Conceptually, it looks like a Vector, but instead of finding objects by numbers, it uses another object to find them. This is usually part of an important process in a program.

In Java, this concept is specifically reflected in the abstract class Dictionary. The interface of this class is very intuitive size () tells us how many elements it contains, IsEmpty () to determine whether the element is included (true), and put (object key, Object value) to add a value (what we want), and associates it with the same key (what you want to search for it), the Get (object key) Gets the value that corresponds to a key, and the Remove (object key) is used to remove the key-value pair from the list. You can also use enumeration techniques: the keys () produce an enumeration of keys (enumeration), and elements () produces an enumeration of all values. This is the whole of a Dict ionary (dictionary).

public class Assocarray extends Dictionary {private vector keys = new vector (); private vector values = new vector (); pub LIC int size () {return keys.size ():} public Boolean IsEmpty () {return keys.isempty ();} The public object is put (object key, O Bject value) {keys.addelement (key); values.addelement (value); return key;} public object get (object key) {int index = k
Eys.indexof (key);
IndexOf () Returns-1 if key not found:if (index = = 1) return null;
Return Values.elementat (index); The public object remove (Object key) {int index = Keys.indexof (key), if (index = = 1) return null; Keys.removeelementat (Inde
x);
Object returnval = values.elementat (index);
Values.removeelementat (index);
return returnval; Public enumeration keys () {return keys.elements ():} Public enumeration elements () {return values.elements ();}//Tes T it:public static void Main (string[] args) {assocarray AA = new Assocarray (); for (char C = ' a '; c <= ' z '; c + +) Aa.pu T (string.valueof (c), string.valueof (c). TouppercasE ());
Char[] ca = {' A ', ' e ', ' I ', ' o ', ' u '}; for (int i = 0; i < ca.length i++) System.out.println ("Uppercase:" + aa.get (string.valueof (ca[i)))

The first problem we notice in the definition of Assocarray is that it "expands" the dictionary. This means that Assocarray belongs to a type of Dictionary, so it can make the same request as Dictionary. If you want to build your own Dictionary and do it here, all you have to do is populate all the methods that are in Dictionary (and you must overwrite all methods because
They--except the builder--are abstract.

The standard Java library contains only one variant of Dictionary, named Hashtable (hash table, comment ③). The Java hash table has the same interface as Assocarray (since both are inherited from Dictionary). But one aspect reflects the difference: efficiency of implementation. If you think about what you have to do for a get (), you'll find that the search key is much slower in a Vector. But using a hash table at this point can speed up a lot. Instead of using lengthy linear search techniques to find a key, you use a special value called hash code. The hash code gets the information in the object and converts it to the "relatively unique" integer (int) of that object. All objects have a hash code, and Hashcode () is a method of the root class object. Hashtable gets the hashcode () of the object, and then uses it to quickly find the key.

Class Counter {
int i = 1;
Public String toString () {return
integer.tostring (i);
}
}
Class Statistics {public
static void Main (string[] args) {
Hashtable ht = new Hashtable ();
for (int i = 0; I < 10000 i++) {
//produce a number between 0 and:
integer r =
new Integer (int) (Math . random ());
if (Ht.containskey (R))
((Counter) Ht.get (R)). i++;
else
Ht.put (R, New Counter ());
SYSTEM.OUT.PRINTLN (HT);
}

1. Create a "critical" class
But when using a hash table, once we create our own class as a key to make the
, you will encounter a very common problem. For example, suppose a set of weather forecasting systems matches the groundhog (Soil-rat) object into a prediction (forecast). This looks very intuitive: we create two classes, then use Groundhog as a key and use prediction as a value. As shown below:

Class Groundhog {
int ghnumber;
Groundhog (int n) {ghnumber = n;}
}
Class Prediction {
Boolean shadow = Math.random () > 0.5;
Public String toString () {
if (shadow) return
"Six more weeks of winter!";
else return
"Early spring!";
}
public class Springdetector {public
static void Main (string[] args) {
Hashtable ht = new Hashtable ();
for (int i = 0; i < i++)
Ht.put (new Groundhog (i), new Prediction ());
SYSTEM.OUT.PRINTLN ("HT =" + HT + "\ n");
System.out.println (
"Looking up prediction for Groundhog #3:");
Groundhog GH = new Groundhog (3);
if (Ht.containskey (GH))
System.out.println ((prediction) Ht.get (GH));

The problem is that groundhog is inherited from the generic Object root class (if not
To set the underlying class, all classes are ultimately inherited from Object. In fact, the hash code of each object is generated using the Hashcode () method of object, and by default only its object's address is used. Therefore, the first instance of Groundhog (3) does not produce a hash code equal to the second instance of Groundhog (3), and we retrieve it with a second instance

Perhaps the whole thing to do at this point is to properly overwrite hashcode (). But doing this is still not possible unless you do another thing: the Equals () that covers the part of Object. This method is used when the hash table attempts to determine whether our key is equal to a key in the list. Similarly, the default object.equals () simply compares the object address, so a groundhog (3) does not equal
Another groundhog (3).
Therefore, in order to use your class as a key in a hash table, you must overwrite both hashcode () and Equals () as shown below:

Class Groundhog {
int ghnumber;
Groundhog (int n) {ghnumber = n;}
}
Class Prediction {
Boolean shadow = Math.random () > 0.5;
Public String toString () {
if (shadow) return
"Six more weeks of winter!";
else return
"Early spring!";
}
public class Springdetector {public
static void Main (string[] args) {
Hashtable ht = new Hashtable ();
for (int i = 0; i < i++)
Ht.put (

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.